Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mapping for MIDI Controller Behringer BCR2000 #3342

Conversation

git-developer
Copy link
Contributor

Documentation PR: mixxxdj/manual#310

This PR contains more than an average mapping:

  • Additional Javascript components for controls (Buttons & Encoders)
  • A Layer Manager component that simplifies arranging controls on a Shift layer

We'll probably discuss a little bit about all this, which could be done in this PR or the forum thread.

@git-developer
Copy link
Contributor Author

I've come across a few Wiki articles that might be interesting for the mapping. I'd appreciate if someone could shortly comment on the progress on these topics:

  1. Registering Midi Input Handlers From Javascript
    The mapping between MIDI and Mixx controls is already done in Javascript, so I'd prefer to remove the XML file completely.
  2. Controller Script Modules
    Can / should the mapping be moved to a Script Module?
  3. New controller system
    Does the new controller system have effects on the format of the Javascript mapping?

@Be-ing
Copy link
Contributor

Be-ing commented Nov 19, 2020

Registering Midi Input Handlers From Javascript, Controller Script Modules

These are old proposals that will not be implemented. The "New controller system" page has a summary of current plans.

Does the new controller system have effects on the format of the Javascript mapping?

Yes, it will be an entirely different API.

@git-developer
Copy link
Contributor Author

git-developer commented Nov 21, 2020

This PR contains several independent building blocks that together form a mapping for the Behringer BCR2000 controller. I'd like to explain these building blocks a little bit so that the whole stuff is easier to understand. Maybe a part of this code can be re-used for other things, your thoughts and comments are welcome.

General stuff (independent of the controller)

File midi-components-extension.js

This file contains a set of additional components which are quite generic and could be re-used for other mappings.

Support objects (type object, currently private)
  • log: Allows to log to the console on different levels
  • ComponentRegistry: A registry that allows storing Components in named ComponentContainers. Within a container, components are identified by their MIDI address.
Public Components (type Component unless specified otherwise)
  • ShiftButton: Simple button that triggers shift() and unshift() on a target component.

  • Trigger: A component that is always triggered on every input, regardless of the value.
    Example use: Button to reset key (pitch_set_zero).

  • CustomButton: A button with configurable Mixxx control values for on and off.

  • Timer (no component): An object that simplifies using a timer safely.

  • LongPressButton: A button that supports different actions on short and long press.

  • DirectionEncoder: An encoder for directions.
    Example use: encoder to browse the library (MoveVertical)

  • RangeAwareEncoder: An encoder for a value range of [-bound..0..+bound].
    Example use: encoder to change key (pitch)

  • EnumToggleButton: A button to cycle through the values of an enumeration.
    Example use: Toggle vinyl_control_mode

  • EnumEncoder: An encoder for enumeration values.
    Example use: Base component for LoopEncoder

  • LoopEncoder: An enum encoder that knows beat sizes.
    Example use: Encoder for beatloop_size and beatjump_size

  • LoopMoveEncoder: An encoder that moves the current loop.

  • BackLoopButton: A button that toggles a beatloop ending at the current play position, so the beat jump
    occurs immediately on button press and not after the first loop.

  • Publisher: Kind of a "sidecar" for the effect unit pots.
    When I mapped my controller, I wondered why the effect unit knobs do not send their value to the controller. It seems that they're just no made to do so. My guess is that the effect unit implementation was done with physical pots in mind that offer no LEDs. Anyway, when I looked at the EffectUnitKnob implementation, I saw that the outKey is used to implement focus changes, and I didn't want to touch that. Thus, I decided to create this Publisher component. It uses the Mixxx control of a source component (an effect unit control) and defines an outKey only (no input handling).
    Unfortunately, these effect unit control are quite tricky and change their internal state on focus and shift changes. Thus I had to implement a bind() function that syncs the outKey. bind() is to be called on those state changes. The call is currently done when the effect unit is setup (in generic-midi-controller-scripts.js).

  • LayerManager: This component helps working with layered components.
    The wiki article MIDI Scripting describes two approaches to implement a shift layer: either working with a condition within a component or switching components in a container. The LayerManager is a generic component that implements the second approach. Internally, it uses a component registry for the two layers Default and Shift. It is itself a Component offering shift() and unshift() to toggle between the these layers. Additionally, it offers input(), a facade to be called from the XML file that delegates to the component on the currently active layer.

  • EqualizerUnit (type ComponentContainer): A component container for an equalizer unit with 3 knobs and kill switches, enable button and super knob. It is always part of a deck.

  • GenericMidiController (type ComponentContainer): A generic, configurable MIDI controller.
    It consists of custom Decks, EffectUnits and additional component containers, where custom means:

    • Decks may be composed of arbitrary components.
    • Effect units have support for sending output values for encoders.
    • All components are managed by a LayerManager and thus may be put on either the Default or the Shift layer by configuration.

    The mapping is configured by a configurationProvider() function that is given as constructor argument.
    The GenericMidiController has no dependencies on the BCR2000 controller so that it may be used for other general purpose controllers (e.g. AKAI APC, AKAI Fire, AKAI midimix, Behringer X-Touch, DJ Techtools Midi Fighter, Faderfox, Icon Platform M+, Korg nanoKONTROL, Midiplus SmartPAD, Nektar Aura, Novation Launchpad, Studiologic SL Mixface).

Controller-specific

File Behringer-BCR2000-preset-scripts.js

This file maps the MIDI addresses of hardware controls to readable names like buttonRow2[3] or pushEncoderGroup2[5]. Since the BCR2000 has 32 user-programmable presets, the MIDI addresses are not fix. When a user prefers to use a customized preset over the factory settings, this file encapsulates the preset information, leaving the component mapping untouched.

Preset-specific

File BCR2000.midi.xml

I don't really want to maintain this file, but it seems to be necessary to delegate MIDI input to the Javascript world. So it simply contains a lot of input definitions that all delegate to the same input function of the controller mapping (delegating again to the LayerManager that knows the currently active component for a MIDI address).

File Behringer-BCR2000-scripts.js

Configuration for the actual controller mapping. This file contains all information about

  • used components (e.g. a button or an encoder)
  • layer for each component (Default or Shift)
  • MIDI address and
  • Mixxx control (e.g. vinylcontrol_mode or key)

This allows more than 1 GenericMidiContollers at a time.
This is not strictly necessary for shift handling but avoids binding to an undefined mixxx control.

This reverts commit 612e456.
@Holzhaus
Copy link
Member

Holzhaus commented Jan 5, 2021

@git-developer Sorry for this mess. Maybe you're interested in joining the Zulip discussion regarding the new API?

@git-developer
Copy link
Contributor Author

I understand your concerns.

It would be no problem for me to "hide" the code by moving it so that others don't use it unintentionally. Just one thing: some of those components are used in my mapping for the Behringer DDM4000 mixer. Thus, I'd like to use a common namespace for these components. What do you think of changing the namespace components.extension to components.experimental or behringer.experimental, and renaming the midi-components-extension.js to midi-components-experimental.js or Behringer-experimental-scripts.js or something? Or do you prefer copying the common code into both mapping files (shiver)?

I'm new to Zulip. Is there a topic in the controller stream for the discussion on the new mapping system?

@uklotzde
Copy link
Contributor

uklotzde commented Jan 6, 2021

Duplicating the code would be the worst decision. Using one of the behringer prefixes works for me and prevents general usage.

@git-developer
Copy link
Contributor Author

I replaced common by behringer.

Can I do something about the failing build? I'm not sure what's wrong, looks like a problem downloading a key finder library, unrelated to this PR.

@git-developer
Copy link
Contributor Author

Looks like the build is failing in my fork only.

@Holzhaus
Copy link
Member

Holzhaus commented Jan 7, 2021

Can I do something about the failing build? I'm not sure what's wrong, looks like a problem downloading a key finder library, unrelated to this PR.

git pull origin 2.3

Copy link
Contributor

@uklotzde uklotzde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After renaming the files I consider this ready to be merged. The corresponding manual PR is in place, though still failing to build.

Hopefully, there are still some owners of this/these devices who will appreciate the retrofitting efforts! :)

@uklotzde
Copy link
Contributor

@Be-ing @Holzhaus Ready to merge? This is a prerequisite for the DDM 4000 mapping in #3542

@Be-ing
Copy link
Contributor

Be-ing commented Jan 25, 2021

No, this hasn't even begun review.

@github-actions
Copy link

This PR is marked as stale because it has been open 90 days with no activity.

@github-actions github-actions bot added the stale Stale issues that haven't been updated for a long time. label Apr 26, 2021
@git-developer
Copy link
Contributor Author

This PR was marked as stale but is actually waiting for a review or merge.

@uklotzde uklotzde removed the stale Stale issues that haven't been updated for a long time. label Apr 27, 2021
@uklotzde
Copy link
Contributor

Yes, sorry for the bot marker. Reviewers are a scarce resource and Mixxx is understaffed.

Copy link
Member

@Swiftb0y Swiftb0y left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm sorry nobody was able to properly review your PR. I'm unable to review the mapping properly as well because of its enormous size. The code looks pretty solid at first glance and you seem to know your JS, so I trust you that this code is of decent quality.

does anyone object to merging this?

@uklotzde
Copy link
Contributor

I'm sorry nobody was able to properly review your PR. I'm unable to review the mapping properly as well because of its enormous size. The code looks pretty solid at first glance and you seem to know your JS, so I trust you that this code is of decent quality.

does anyone object to merging this?

This was also my impression when skimming over the code. Neither other mappings nor the core application would be affected if it doesn't work as expected.

I don't expect that we are able to find someone for testing who owns this legacy controller. After the mapping has been merged and becomes accessible for regular users we might get feedback.

@Holzhaus @daschuer Do you agree?

@Holzhaus
Copy link
Member

Ok for me. In general I don't want to maintain another abstraction library. It should be clear that other controller mappings shouldn't build upon that library. But I'm okay with merging it.

Documentation PR looks good, so I'm okay with merging this.

@Swiftb0y Swiftb0y merged commit 00b5b27 into mixxxdj:2.3 May 2, 2021
@git-developer
Copy link
Contributor Author

Thanks!

@Holzhaus
Copy link
Member

Holzhaus commented May 2, 2021

@Swiftb0y please always merge the corresponding manual changes, too.

@Swiftb0y
Copy link
Member

Swiftb0y commented May 2, 2021

Yes, I'm sorry I didn't have that on my radar.

@uklotzde
Copy link
Contributor

uklotzde commented May 2, 2021

@Swiftb0y Thanks 🎉

As a consequence #3542 will become ready which builds on the common code merged with this PR.

@uklotzde uklotzde added this to the 2.3.0 milestone May 7, 2021
@git-developer git-developer deleted the feature/controller-mapping-behringer-bcr2000 branch May 9, 2021 05:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants