User Tools

Site Tools


components_js

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
components_js [2018/03/12 19:19]
be.ing [Setup]
components_js [2019/08/17 18:38] (current)
be.ing [HotcueButton]
Line 141: Line 141:
   * **input**: the [[MIDI scripting#​MIDI input handling functions|function that receives MIDI input]]   * **input**: the [[MIDI scripting#​MIDI input handling functions|function that receives MIDI input]]
   * **output**: the [[midi scripting#​Connect output callback functions|function that gets called when outKey changes value]]. Typically this sends MIDI output to the controller to change the state of an LED, but it can do anything.   * **output**: the [[midi scripting#​Connect output callback functions|function that gets called when outKey changes value]]. Typically this sends MIDI output to the controller to change the state of an LED, but it can do anything.
-  * **connect**:​ register ''​output''​ as the callback function that gets executed when the value of the [[mixxxcontrols|Mixxx ControlObject]] specified by ''​group'',​ ''​outKey''​ changes. Implement a custom function if you need to connect callbacks for multiple Mixxx ControlObjects in one Component. Refer to the source code of [[#​SamplerButton|SamplerButton.prototype.connect]] for an example.+  * **connect**:​ register ''​output''​ as the callback function that gets executed when the value of the [[mixxxcontrols|Mixxx ControlObject]] specified by ''​group'',​ ''​outKey''​ changes. This is called automatically by the Component constructor if ''​group''​ and ''​outKey''​ are defined (otherwise it needs to be called after construction). Implement a custom function if you need to connect callbacks for multiple Mixxx ControlObjects in one Component. Refer to the source code of [[#​SamplerButton|SamplerButton.prototype.connect]] for an example.
  
 The following methods are called by the default Component ''​input''​ and ''​output''​ methods, as well as the default ''​input''​ functions of [[#​Button]],​ [[#Pot]], and [[#​Encoder]]. If you do not need to implement complex custom behavior, you can overwrite these instead of the default ''​input''​ and ''​output''​ methods: The following methods are called by the default Component ''​input''​ and ''​output''​ methods, as well as the default ''​input''​ functions of [[#​Button]],​ [[#Pot]], and [[#​Encoder]]. If you do not need to implement complex custom behavior, you can overwrite these instead of the default ''​input''​ and ''​output''​ methods:
Line 170: Line 170:
   * **sendShifted** (boolean, default false): whether to send a second, shifted MIDI message for every call to ''​send''​   * **sendShifted** (boolean, default false): whether to send a second, shifted MIDI message for every call to ''​send''​
   * **shiftChannel** (boolean, default false): whether the shifted MIDI message changes the MIDI channel (second nybble of the first byte of the MIDI signal)   * **shiftChannel** (boolean, default false): whether the shifted MIDI message changes the MIDI channel (second nybble of the first byte of the MIDI signal)
-  * **shiftComponent** (boolean, default false): whether the shifted MIDI message changes the MIDI control number (second byte) of the MIDI signal+  * **shiftControl** (boolean, default false): whether the shifted MIDI message changes the MIDI control number (second byte) of the MIDI signal
   * **shiftOffset** (number, default 0): how much to shift the MIDI channel or control number by   * **shiftOffset** (number, default 0): how much to shift the MIDI channel or control number by
  
Line 271: Line 271:
 } }
 </​code>​ </​code>​
 +
 +===Hotcue colors===
 +HotcueButton can show hotcue colors on the controller. There are three ways of implementing this. Which one to choose depends on the controller.
 +  - Set color via single byte based on controller internal palette
 +  - Set color via SysEx based on custom palette.
 +  - Set color via SysEx based on predefined colors by Mixxx.
 +
 +Option 1 is the simplest and most common method for most controllers. You must figure out which MIDI values correspond to which colors and the correlate it with the [[hotcue_colors|predefined hotcue colors]] (the controller'​s manual from the manufacturer may document this). Creating such HotcueButton could look like this:
 +<​code=javascript>​
 +var hotcueButton = new components.HotcueButton({
 +    number: 1,
 +    group: '​[Channel1]',​
 +    midi: [0x91, 0x26],
 +    // key-value map to correlate the Mixxx ColorID
 +    // with the value the controller expects for 
 +    // specific colors. These values are passed to
 +    // the HotcueButton'​s send method.
 +    colors: {
 +        0: 0x10,
 +        1: 0x18,
 +        2: 0x20,
 +        ...
 +    },
 +    // value to turn off the buttons LED.
 +    off: 0x00,
 +});
 +</​code>​
 +
 +With the second option, you can send predefined colors from the palette to the controller but this time via SysEx. Since SysEx is very controller specific, it is mandatory to specify a custom ''​sendRGB''​ method which is responsible for taking a color description,​ extracting the relevant information,​ and sending the SysEx Message to the controller. In this case, the values of the attributes in the ''​colors''​ object are passed as the input to the ''​sendRGB''​ method.
 +<​code=javascript>​
 +var hotcueButton = new components.HotcueButton({
 +    number: 1,
 +    group: '​[Channel1]',​
 +    midi: [0x91, 0x26],
 +    // key-value map to correlate the Mixxx ColorID
 +    // with an array which contains (in this case)
 +    // the RGB components of a color. These values
 +    // are passed as input to the sendRGB method.
 +    colors: {
 +        0: [0x00,​0x00,​0x00],​ // black
 +        1: [0xFF,​0x00,​0x00],​ // pure red
 +        2: [0xFF,​0xFF,​0x00],​ // pure Yellow
 +        ...
 +    },
 +    sendRGB: function (color_obj) {
 +        // example Message (hardcoded bytes are controller specific).
 + // colors entries contain 8-bit values, but SysEx only supports 7-bit values
 + // so were bitshifting by 1 to reduce the resolution.
 +        var msg = [0xF0, 0x00, 0x01, color_obj[0]>>​1,​color_obj[1]>>​1,​color_obj[2]>>​1];​
 +        // send message
 + midi.sendSysexMsg(msg,​ msg.length);​
 +    }
 +});
 +</​code>​
 +
 +The third option is similar to the second one. You need to define a ''​sendRGB''​ method again, but in this Mixxx provides the color palette automatically and you do not provide a ''​colors''​ object for the HotcueButton. The ''​sendRGB(color)''​ method gets passed a color object (more on the color API [[midi_scripting#​color_api|here]]). Such a button could be defined like this:
 +<​code=javascript>​
 +var hotcueButton = new components.HotcueButton({
 +    number: 1,
 +    group: '​[Channel1]',​
 +    midi: [0x91, 0x26],
 +    // colors automatically assigned by Components.JS framework
 +    sendRGB: function (color_obj) {
 +        // example Message (hardcoded bytes are controller specific).
 + // colors entries contain 8-bit values, but SysEx only supports 7-bit values
 + // so were bitshifting by 1 to reduce the resolution.
 +        var msg = [0xF0, 0x00, 0x01, color_obj.red>>​1,​color_obj.green>>​1,​color_obj.blue>>​1];​
 +        // send message
 + midi.sendSysexMsg(msg,​ msg.length);​
 +    }
 +});
 +</​code>​
 +
  
 ==== SamplerButton ==== ==== SamplerButton ====
Line 284: Line 357:
         number: n,         number: n,
         midi: [0x91, 0x02],         midi: [0x91, 0x02],
 +    });
 +)};
 +</​code>​
 +
 +You can also make the SamplerButtons velocity sensitive by setting the ''​volumeByVelocity:​ true''​ property on the object that gets passed to the constructor. This will change the volume at which the sample is being played at depending on how hard you pressed the button. Obviously, it will only work if your hardware features velocity sensitive buttons.
 +
 +<​code=javascript>​
 +var samplerButtons = [];
 +for (var n = 1; n <= 8; n++) {
 +    samplerButtons[n] = new components.SamplerButton({
 +        number: n,
 +        midi: [0x91, 0x02],
 +        volumeByVelocity:​ true,
     });     });
 )}; )};
Line 309: Line 395:
 )}; )};
 </​code>​ </​code>​
- 
 ==== EffectAssignmentButton ==== ==== EffectAssignmentButton ====
 An EffectAssignmentButton routes a deck through an EffectUnit. It is separate from the [[#​EffectUnit]] ComponentContainer because it is meant to be a part of a [[#Deck]]. Using [[#​Deck|Deck.setCurrentDeck]] to switch decks will switch the deck an EffectAssignmentButton assigns an EffectUnit to. An EffectAssignmentButton routes a deck through an EffectUnit. It is separate from the [[#​EffectUnit]] ComponentContainer because it is meant to be a part of a [[#Deck]]. Using [[#​Deck|Deck.setCurrentDeck]] to switch decks will switch the deck an EffectAssignmentButton assigns an EffectUnit to.
Line 377: Line 462:
   * **forEachComponent**:​ Iterate over all Components in this ComponentContainer and perform an operation on them. The operation is a function provided as the first argument to ''​forEachComponent''​. The operation function takes each Component as its first argument. In the context of the operation function, ''​this''​ refers to the ComponentContainer. ''​forEachComponent''​ iterates recursively through the Components in any ComponentContainers and arrays that are properties of this ComponentContainer. If you do not want ''​forEachComponent''​ to operate recursively,​ pass ''​false''​ as the second argument to ''​forEachComponent''​.   * **forEachComponent**:​ Iterate over all Components in this ComponentContainer and perform an operation on them. The operation is a function provided as the first argument to ''​forEachComponent''​. The operation function takes each Component as its first argument. In the context of the operation function, ''​this''​ refers to the ComponentContainer. ''​forEachComponent''​ iterates recursively through the Components in any ComponentContainers and arrays that are properties of this ComponentContainer. If you do not want ''​forEachComponent''​ to operate recursively,​ pass ''​false''​ as the second argument to ''​forEachComponent''​.
   * **reconnectComponents**:​ Call each Component'​s ''​disconnect''​ method, optionally perform an operation on it, then call its ''​connect''​ and ''​trigger''​ methods to sync the state of the controller'​s LEDs. Arguments are the same as ''​forEachComponent''​.   * **reconnectComponents**:​ Call each Component'​s ''​disconnect''​ method, optionally perform an operation on it, then call its ''​connect''​ and ''​trigger''​ methods to sync the state of the controller'​s LEDs. Arguments are the same as ''​forEachComponent''​.
 +  * **shutdown**:​ Iterate over all Components and call their shutdown methods. The Button ​ is the only component with a predefined shutdown method. All other components have to be implemented manually.
  
 Typically, ''​reconnectComponents''​ is used to switch between layers. The callback passed to reconnectComponents can manipulate each Component'​s properties as appropriate for the new layer. Below is a basic example for switching between decks 1 and 3. This is a simple example that does not handle the complexities presented by EQs, QuickEffects,​ or EffectAssignmentButtons like [[#​Deck|Deck.setCurrentDeck]] does. Typically, ''​reconnectComponents''​ is used to switch between layers. The callback passed to reconnectComponents can manipulate each Component'​s properties as appropriate for the new layer. Below is a basic example for switching between decks 1 and 3. This is a simple example that does not handle the complexities presented by EQs, QuickEffects,​ or EffectAssignmentButtons like [[#​Deck|Deck.setCurrentDeck]] does.
Line 476: Line 562:
  
 For the shift functionality to work, the shift button of your controller must be mapped to a function that calls the ''​shift''/''​unshift''​ methods of the EffectUnit on button press/​release. Also, if your controller sends different MIDI signals when shift is pressed, map those as well as the unshifted signals to the ''​input''​ method of each Component in your XML file. If the EffectUnit is a property of another [[#​ComponentContainer]] (for example a [[#Deck]]), calling ''​shift''​ and ''​unshift''​ on the parent ComponentContainer will recursively call it on the EffectUnit too (just like it will for any other ComponentContainer). For the shift functionality to work, the shift button of your controller must be mapped to a function that calls the ''​shift''/''​unshift''​ methods of the EffectUnit on button press/​release. Also, if your controller sends different MIDI signals when shift is pressed, map those as well as the unshifted signals to the ''​input''​ method of each Component in your XML file. If the EffectUnit is a property of another [[#​ComponentContainer]] (for example a [[#Deck]]), calling ''​shift''​ and ''​unshift''​ on the parent ComponentContainer will recursively call it on the EffectUnit too (just like it will for any other ComponentContainer).
 +
 +By default an effect can only be focused when the respective GUI unit is expanded: when the focus button of a collapsed unit is pressed, the GUI counterpart is expanded. Accordingly,​ units release the effect focus and switch back to Meta knob mapping as soon as an unit is collapsed.\\
 +However, there are situations when the on-screen parameters of a focused effect can safely stay hidden while the controller is mapped to the parameter knobs. Collapsed units show a focus indicator then. To enable this mode instatiate effect units with '​true'​ added after the effect unit numbers array. For example:
 +<​code=javascript>​
 +MyController.effectUnit = new components.EffectUnit([1,​ 3],true);
 +...
 +</​code>​
 +
  
 ==== Assignment switches ==== ==== Assignment switches ====
 Generally, most controllers should use [[#​EffectAssignmentButton]]s in [[#Deck]]s to enable effect units on decks. If you have a dedicated effects controller that does not manipulate decks, the enableOnChannelButtons provided by EffectUnit would be more appropriate. You can easily create these by calling ''​enableOnChannelButtons.addButton('​CHANNEL_NAME'​)''​ (do not put brackets around the Generally, most controllers should use [[#​EffectAssignmentButton]]s in [[#Deck]]s to enable effect units on decks. If you have a dedicated effects controller that does not manipulate decks, the enableOnChannelButtons provided by EffectUnit would be more appropriate. You can easily create these by calling ''​enableOnChannelButtons.addButton('​CHANNEL_NAME'​)''​ (do not put brackets around the
 CHANNEL_NAME) on the EffectUnit object, then define their ''​midi''​ properties. CHANNEL_NAME) on the EffectUnit object, then define their ''​midi''​ properties.
components_js.1520896798.txt.gz ยท Last modified: 2018/03/12 19:19 by be.ing