User Tools

Site Tools


midi_scripting

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
Last revision Both sides next revision
midi_scripting [2019/11/24 08:58]
kobx formatting, remplaced --midiDebug with --controllerDebug
midi_scripting [2019/11/24 12:10]
kobx Added references to script.deckFromGroup to scratch how to
Line 1: Line 1:
  ​====== Controller Scripting ======  ​====== Controller Scripting ======
  
-In order to support the features of many MIDI controllers,​ Mixxx offers what we call MIDI Scripting (introduced in Mixxx v1.7.0). It enables MIDI controls to be mapped to [[http://​doc.trolltech.com/​4.5/​qtscript.html|QtScript]] (also known as [[http://​en.wikipedia.org/​wiki/​JavaScript_syntax|Javascript]]/​[[http://​www.ecma-international.org/​publications/​standards/​Ecma-262.htm|EMCAScript]]) functions, allowing mappings to manage complex behaviors. These user-created functions can then do anything desired with the MIDI event info such as affect different controls depending on whether another button is pressed, adjust incoming control values to work better with Mixxx (i.e. for [[#​scratching]]),​ send messages to LED displays on the controller, or even [[#turning a 2 deck controller into a 4 deck controller|turn a 2 deck controller into a 4 deck controller]].+In order to support the features of many MIDI controllers,​ Mixxx offers what we call MIDI Scripting (introduced in Mixxx v1.7.0). It enables MIDI controls to be mapped to [[http://​doc.trolltech.com/​4.5/​qtscript.html|QtScript]] (also known as [[http://​en.wikipedia.org/​wiki/​JavaScript_syntax|Javascript]]/​[[http://​www.ecma-international.org/​publications/​standards/​Ecma-262.htm|EMCAScript]]) functions, allowing mappings to manage complex behaviors. These user-created functions can then do anything desired with the MIDI event info such as affect different controls depending on whether another button is pressed, adjust incoming control values to work better with Mixxx (i.e. for [[#Scratching and jog wheels|scratching]]),​ send messages to LED displays on the controller, or even [[#turning a 2 deck controller into a 4 deck controller|turn a 2 deck controller into a 4 deck controller]].
  
 If you would like your mapping included in Mixxx, please see the coding guidelines on the [[Contributing Mappings]] page. If you would like your mapping included in Mixxx, please see the coding guidelines on the [[Contributing Mappings]] page.
Line 43: Line 43:
 You can add as many <​file>​ tags as you like, but be sure to specify the appropriate functionprefix in every one. These will all be loaded when the controller is activated. You can add as many <​file>​ tags as you like, but be sure to specify the appropriate functionprefix in every one. These will all be loaded when the controller is activated.
  
-There is a default script function file called ''​common-controller-scripts.js''​ which contains functions common to all controllers and is always loaded. See [[#available common ​functions]] below for information on these functions.+There is a default script function file called ''​common-controller-scripts.js''​ which contains functions common to all controllers and is always loaded. See [[#Helper ​functions]] below for information on these functions.
  
 ==== Script file header ==== ==== Script file header ====
Line 76: Line 76:
 The ID parameter of the init function is the ''​controller id''​ attribute from the XML file. The ID parameter of the init function is the ''​controller id''​ attribute from the XML file.
 This can be used to identify the particular controller instance in print statements. This can be used to identify the particular controller instance in print statements.
-The ''​debugging''​ parameter is set to '​true'​ if the user specified the ''​%%--controllerDebug%%''​ parameter on the command line (''​%%--mididebug%%''​ until Mixxx 1.10).+The ''​debugging''​ parameter is set to '​true'​ if the user specified the ''​%%--controllerDebug%%''​ parameter on the command line (''​%%--midiDebug%%''​ until Mixxx 1.10).
  
 **Note**: Instead of using global variables, define properties of your controller object (''​MyController''​ in this example) to avoid name collisions with other scripts that may be loaded. **Note**: Instead of using global variables, define properties of your controller object (''​MyController''​ in this example) to avoid name collisions with other scripts that may be loaded.
Line 249: Line 249:
  
 Generally, you should not call ''​midi.sendShortMsg''​ or ''​midi.sendSysexMsg''​ directly from functions that handle MIDI input. Instead, the input function should change the state of a [[MixxxControls|Mixxx Control]] and you should call ''​midi.sendShortMsg''/''​midi.sendSysexMsg''​ in a callback function that reacts to changes in that Mixxx Control. Refer to the section above for details. This way, the state of the controller will always be in sync with what Mixxx is actually doing, even if the user manipulates Mixxx with the keyboard, mouse, or another controller. If the MIDI input handling function only changes the state of script variables but not Mixxx Controls, then it would be appropriate to call ''​midi.sendShortMsg''/''​midi.sendSysexMsg''​ from the input handling function. Generally, you should not call ''​midi.sendShortMsg''​ or ''​midi.sendSysexMsg''​ directly from functions that handle MIDI input. Instead, the input function should change the state of a [[MixxxControls|Mixxx Control]] and you should call ''​midi.sendShortMsg''/''​midi.sendSysexMsg''​ in a callback function that reacts to changes in that Mixxx Control. Refer to the section above for details. This way, the state of the controller will always be in sync with what Mixxx is actually doing, even if the user manipulates Mixxx with the keyboard, mouse, or another controller. If the MIDI input handling function only changes the state of script variables but not Mixxx Controls, then it would be appropriate to call ''​midi.sendShortMsg''/''​midi.sendSysexMsg''​ from the input handling function.
 +
 +===== Debugging your mappings =====
 +As mentioned above, you don't have to restart Mixxx, when you're testing your scripts.
 +Every time you save your file, Mixxx will reload it immediately.
 +Additionally if you specify ''​%%--controllerDebug%%''​ (or ''​%%--midiDebug%%''​ prior to verion 1.11),
 +Mixxx then logs all incoming and outgoing MIDI messages.
 +Also you can use ''​print()''​ in your script to output further messages.
 +The second parameter passed to your ''​init()''​ functions specifies if the controller debug mode is enabled.
  
 ===== Components library ===== ===== Components library =====
 Now that you understand the basics, it is suggested to use the [[Components JS]] library for new mappings. Now that you understand the basics, it is suggested to use the [[Components JS]] library for new mappings.
 +
 ===== Soft-takeover ===== ===== Soft-takeover =====
 To prevent sudden wide parameter changes when the on-screen control diverges from a hardware control, use soft-takeover. While it's active on a particular parameter, manipulating the control on the hardware will have no effect until the position of the hardware control is close to that of the software, at which point it will take over and operate as usual. You can enable and disable it at any point, and it operates on each MixxxControl independently. Typically, for each control that has physical limits (typically, knobs and sliders) on your controller, you would enable soft-takeover in the ''​init()''​ script function and just leave it enabled. To prevent sudden wide parameter changes when the on-screen control diverges from a hardware control, use soft-takeover. While it's active on a particular parameter, manipulating the control on the hardware will have no effect until the position of the hardware control is close to that of the software, at which point it will take over and operate as usual. You can enable and disable it at any point, and it operates on each MixxxControl independently. Typically, for each control that has physical limits (typically, knobs and sliders) on your controller, you would enable soft-takeover in the ''​init()''​ script function and just leave it enabled.
Line 279: Line 288:
 engine.scratchTick(int deck, int interval); engine.scratchTick(int deck, int interval);
 engine.scratchDisable(int deck, bool ramp); engine.scratchDisable(int deck, bool ramp);
-bool engine.isScratching(int deck);</​code>​+bool engine.isScratching(int deck); 
 +</​code>​
  
 Here is how to use them: Here is how to use them:
Line 295: Line 305:
     * the movement value (typically 1 for one "​tick"​ forwards, -1 for one "​tick"​ backwards)     * the movement value (typically 1 for one "​tick"​ forwards, -1 for one "​tick"​ backwards)
   - When you're done scratching (like when the wheel is released,) just call ''​engine.scratchDisable()''​ with the number of the virtual deck to stop scratching and whether you want Mixxx to ramp up to the play speed or jump to it instantly. (Default is to ramp which also allows spin-backs with wheels.)   - When you're done scratching (like when the wheel is released,) just call ''​engine.scratchDisable()''​ with the number of the virtual deck to stop scratching and whether you want Mixxx to ramp up to the play speed or jump to it instantly. (Default is to ramp which also allows spin-backs with wheels.)
 +
 +**Note:** You can use ''​script.deckFromGroup(group)''​ to get the virtual deck number from the group string.
 +See [[#Helper functions]] for more information.
  
 Here is an example for the two most common types of wheels. Click the tab labeled '​scratchingExample.js'​ below to open this example as a file in your text editor. Here is an example for the two most common types of wheels. Click the tab labeled '​scratchingExample.js'​ below to open this example as a file in your text editor.
Line 300: Line 313:
 // The button that enables/​disables scratching // The button that enables/​disables scratching
 MyController.wheelTouch = function (channel, control, value, status, group) { MyController.wheelTouch = function (channel, control, value, status, group) {
 +    var deckNumber = script.deckFromGroup(group);​
     if ((status & 0xF0) === 0x90) {    // If button down     if ((status & 0xF0) === 0x90) {    // If button down
   //if (value === 0x7F) {  // Some wheels send 0x90 on press and release, so you need to check the value   //if (value === 0x7F) {  // Some wheels send 0x90 on press and release, so you need to check the value
Line 328: Line 342:
     ​     ​
     // In either case, register the movement     // In either case, register the movement
 +    var deckNumber = script.deckFromGroup(group);​
     if (engine.isScratching(deckNumber)) {     if (engine.isScratching(deckNumber)) {
         engine.scratchTick(deckNumber,​ newValue); // Scratch!         engine.scratchTick(deckNumber,​ newValue); // Scratch!
     } else {     } else {
-        engine.setValue('​[Channel'​+deckNumber+'​]'​, '​jog',​ newValue); // Pitch bend+        engine.setValue(group, '​jog',​ newValue); // Pitch bend
     }     }
 } }
midi_scripting.txt · Last modified: 2020/02/04 22:49 by mevsme