├── _docimg ├── scripting_console.png ├── open_script_console.png ├── vscode_autocompletion.png ├── project_window_with_overlays.png ├── vscode_open_scripts_folder.png ├── remote_window_real_world_device.png ├── overview_big.svg └── script_structure.svg ├── behringer └── bcr2000 │ ├── docs │ ├── BCR2000_label_v1.6.pdf │ ├── bcr2000_midiremote.pdf │ ├── BCR2000 midi remote.pdf │ └── Behringer_BCR2000.midiremote │ ├── README.md │ └── behringer_bcr2000.js ├── LICENSE ├── examplecompany └── putasmileonyoursurface │ └── examplecompany_putasmileonyoursurface.js ├── README.md ├── alesis └── vi49 │ └── alesis_vi49.js ├── presonus └── faderport8 │ └── presonus_faderport8.js └── Akai └── LPD8 └── Akai_LPD8.json /_docimg/scripting_console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/_docimg/scripting_console.png -------------------------------------------------------------------------------- /_docimg/open_script_console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/_docimg/open_script_console.png -------------------------------------------------------------------------------- /_docimg/vscode_autocompletion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/_docimg/vscode_autocompletion.png -------------------------------------------------------------------------------- /_docimg/project_window_with_overlays.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/_docimg/project_window_with_overlays.png -------------------------------------------------------------------------------- /_docimg/vscode_open_scripts_folder.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/_docimg/vscode_open_scripts_folder.png -------------------------------------------------------------------------------- /_docimg/remote_window_real_world_device.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/_docimg/remote_window_real_world_device.png -------------------------------------------------------------------------------- /behringer/bcr2000/docs/BCR2000_label_v1.6.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/behringer/bcr2000/docs/BCR2000_label_v1.6.pdf -------------------------------------------------------------------------------- /behringer/bcr2000/docs/bcr2000_midiremote.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/behringer/bcr2000/docs/bcr2000_midiremote.pdf -------------------------------------------------------------------------------- /behringer/bcr2000/docs/BCR2000 midi remote.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/behringer/bcr2000/docs/BCR2000 midi remote.pdf -------------------------------------------------------------------------------- /behringer/bcr2000/docs/Behringer_BCR2000.midiremote: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/steinbergmedia/midiremote-userscripts/HEAD/behringer/bcr2000/docs/Behringer_BCR2000.midiremote -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Steinberg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /behringer/bcr2000/README.md: -------------------------------------------------------------------------------- 1 |

MIDI REMOTE for BEHRINGER BCR2000

2 | 3 | INSTALL: 4 | - Create folder structure "Behringer/BCR2000" inside "../MIDI Remote/Driver Scripts/Local" folder. 5 | - Copy .js file inside BCR2000 folder. 6 | - Connect your device. 7 | - Start Cubase/Nuendo. 8 | 9 | IMPORTANT: 10 | factory preset for BCR2000 is absolute mode, and this cause stutter moving on knobs: I used relative mode. 11 | BCR2000 need to be configured manually prior to use this script: 12 | - all knobs need to be in “rel1” mode; 13 | - all buttons “toggle off” mode. 14 | 15 | Or you can load attached .bcr preset (easy done with BC MANAGER https://mountainutilities.eu/bcmanager). 16 | 17 | This is the default CC assignement to match midi remote script: 18 | ![Immagine1](https://user-images.githubusercontent.com/101831235/159006077-9ba786d6-dd70-4328-be39-a26210b7813b.png) 19 | 20 |

FOCUS PAGE

21 | 22 | ![Focus page](https://user-images.githubusercontent.com/101831235/159119444-0d218338-423c-4c4d-963d-b3a0183a04fc.png) 23 | 24 | Use Encoder Groups buttons on BCR2000 to switch between 25 | - Sends 26 | - Focused Quick Controls 27 | - Track Quick Controls 28 | - Cues 29 | 30 | EQ Q/TYPE button, switches between Q and filter type on lower knobs 31 | 32 | Side buttons: 33 | use arrows buttons to move between tracks 34 | use page button to switch page 35 | 36 |

MIXING PAGE

37 | 38 | ![02](https://user-images.githubusercontent.com/101831235/159119463-9793dedd-06c1-4c50-b40a-d82e10955b9d.png) 39 | 40 | Side buttons: 41 | use arrows to switch banks 42 | 43 |   44 |

Changelog:

45 | 46 | - v 1.0 07/03/2022 47 | first release. 48 | - v 1.1 08/03/2022 49 | navigate tracks via side button. 50 | - v 1.2 09/03/2022 51 | Focused Quick Control lock added. 52 | - v 1.3 10/03/2022 53 | Pre-filter eq controls added. 54 | Added push button for Focused Quick Control: if focused parameter is a button now you can push the encoder to switch. 55 | - v 1.4. 56 | Added Layers for encoders Group. 57 | - v 1.5 11/03/2022 58 | Cue level control added. 59 | Control Room Main channel level control added. 60 | Monitor enable control added. 61 | Read and write automation control added. 62 | Foot-switches added. 63 | - v 1.6 19/03/2022 64 | Added label for focused track and selected page. 65 | Focus Control page: Phase control added, EQ Q/TYPE button added to switch between Q and filter type on lower knobs. Mixing page added to control banks of 8 channels at once. Mixing page shows track names. 66 | 67 | 68 | 69 | Programmed by Giampaolo Gesuale 70 | contact: giampaologesuale@gmail.com 71 | -------------------------------------------------------------------------------- /examplecompany/putasmileonyoursurface/examplecompany_putasmileonyoursurface.js: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 1. DRIVER SETUP - create driver object, midi ports and detection information 3 | //----------------------------------------------------------------------------- 4 | 5 | // get the api's entry point 6 | var midiremote_api = require('midiremote_api_v1') 7 | 8 | // create the device driver main object 9 | var deviceDriver = midiremote_api.makeDeviceDriver('ExampleCompany', 'PutASmileOnYourSurface', 'Steinberg Media Technologies GmbH') 10 | 11 | // create objects representing the hardware's MIDI ports 12 | var midiInput = deviceDriver.mPorts.makeMidiInput() 13 | var midiOutput = deviceDriver.mPorts.makeMidiOutput() 14 | 15 | // define all possible namings the devices MIDI ports could have 16 | // NOTE: Windows and MacOS handle port naming differently 17 | deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput) 18 | .expectInputNameEquals('SmileDevice IN') 19 | .expectOutputNameEquals('SmileDevice OUT') 20 | 21 | deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput) 22 | .expectInputNameEquals('SmileDevice (MIDI IN)') 23 | .expectOutputNameEquals('SmileDevice (MIDI OUT)') 24 | 25 | 26 | //----------------------------------------------------------------------------- 27 | // 2. SURFACE LAYOUT - create control elements and midi bindings 28 | //----------------------------------------------------------------------------- 29 | 30 | // create control element representing your hardware's surface 31 | 32 | deviceDriver.mSurface.makeBlindPanel(0, 0, 6, 6).setShapeCircle() 33 | 34 | var knob1 = deviceDriver.mSurface.makeKnob(0.75, 3.25, 1, 1.5) 35 | var knob2 = deviceDriver.mSurface.makeKnob(1.50, 4.00, 1, 1.5) 36 | var knob3 = deviceDriver.mSurface.makeKnob(2.50, 4.25, 1, 1.5) 37 | var knob4 = deviceDriver.mSurface.makeKnob(3.50, 4.00, 1, 1.5) 38 | var knob5 = deviceDriver.mSurface.makeKnob(4.25, 3.25, 1, 1.5) 39 | var knob6 = deviceDriver.mSurface.makeKnob(1.00, 1.15, 2, 2) 40 | var knob7 = deviceDriver.mSurface.makeKnob(3.00, 1.15, 2, 2) 41 | 42 | // bind midi ports to surface elements 43 | knob1.mSurfaceValue.mMidiBinding 44 | .setInputPort(midiInput) 45 | .setOutputPort(midiOutput) 46 | .bindToControlChange (0, 21) // channel 0, cc 21 47 | 48 | knob2.mSurfaceValue.mMidiBinding 49 | .setInputPort(midiInput) 50 | .setOutputPort(midiOutput) 51 | .bindToControlChange (0, 22) // channel 0, cc 22 52 | 53 | knob3.mSurfaceValue.mMidiBinding 54 | .setInputPort(midiInput) 55 | .setOutputPort(midiOutput) 56 | .bindToControlChange (0, 23) // channel 0, cc 23 57 | 58 | knob4.mSurfaceValue.mMidiBinding 59 | .setInputPort(midiInput) 60 | .setOutputPort(midiOutput) 61 | .bindToControlChange (0, 24) // channel 0, cc 24 62 | 63 | //----------------------------------------------------------------------------- 64 | // 3. HOST MAPPING - create mapping pages and host bindings 65 | //----------------------------------------------------------------------------- 66 | 67 | // create at least one mapping page 68 | var page = deviceDriver.mMapping.makePage('Example Mixer Page') 69 | 70 | // create host accessing objects 71 | var hostSelectedTrackChannel = page.mHostAccess.mTrackSelection.mMixerChannel 72 | 73 | 74 | // bind surface elements to host accessing object values 75 | page.makeValueBinding(knob1.mSurfaceValue, hostSelectedTrackChannel.mValue.mVolume) 76 | page.makeValueBinding(knob2.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex(0).mLevel) 77 | page.makeValueBinding(knob3.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex(1).mLevel) 78 | page.makeValueBinding(knob4.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex(2).mLevel) 79 | page.makeValueBinding(knob5.mSurfaceValue, hostSelectedTrackChannel.mSends.getByIndex(3).mLevel) 80 | page.makeValueBinding(knob6.mSurfaceValue, hostSelectedTrackChannel.mValue.mVolume) 81 | page.makeValueBinding(knob7.mSurfaceValue, hostSelectedTrackChannel.mValue.mPan) 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MIDI Remote API - User Scripts 2 | 3 | # About 4 | 5 | Welcome to the Steinberg **MIDI Remote API**. 6 | 7 | This document will guide you through the steps of writing a **MIDI Remote API Script** for a specific MIDI Controller Hardware. 8 | 9 | > **NOTE**: Scripts are written in the **[ES5](https://www.w3schools.com/js/js_es5.asp)** version of **JavaScript** 10 | 11 | # How to work with this repository 12 | 13 | 1. Make a fork of steinbergmedia/midiremote-userscripts 14 | 15 | 2. Rename your existing …/Driver Scripts/Local folder to something else (like Local_backup) 16 | 17 | 3. Create a new empty folder Local to replace it 18 | 19 | 4. Clone your forked repository inside the newly created empty Local folder 20 | 21 | 5. Copy your existing scripts from within the Local_backup folder into the Local folder 22 | 23 | 6. Still use the parent folder of Local, the Drive Scripts folder, as the workspace folder in Visual Studio Code 24 | 25 | 7. Make commits/pushes to your forked repo 26 | 27 | 8. Make pull requests to the upstream repo (steinbergmedia/midiremote-userscripts) 28 | 29 | > And don't forget to regulary do “fetch and merge” from the upstream repo (steinbergmedia/midiremote-userscripts) to stay in sync. 30 | 31 | 32 | # Basic Concept 33 | 34 | > The **MIDI Remote API Script** acts as a mediator between a Hardware Controller and Cubase / Nuendo 35 | 36 | 37 | 38 | 39 | 40 | 43 | 44 | > The **MIDI Remote API Script** emulates the hardware surface. This improves usability and recognizability. 45 | 46 | 47 | 48 | # Script Structure 49 | 50 | ### The **MIDI Remote API Script** consists of three building blocks 51 | 1. Driver Setup 52 | - create driver object 53 | - define driver ports to be associated with existing hardware midi ports 54 | - specify all possible port namings for automatic device detection 55 | 56 | 2. Surface Layout 57 | - visualize the hardware's surface elements (e.g. knobs, faders, buttons) 58 | - bind surface elements to midi messages 59 | 60 | 3. Host Mapping 61 | - create mapping pages for each user workflow (e.g. mixing, playing instruments, track navigation) 62 | 63 |
 
64 | 65 | > The following image illustrates that: 66 | 67 |
 
68 | 69 | 70 | 71 | 72 | # Getting Started 73 | 74 | 75 | 76 | ### To get started please perform these steps: 77 | 78 | 1. Make sure you have [Visual Studio Code](https://code.visualstudio.com/) installed. 79 | 80 |
81 | We highly recommend using Visual Studio Code for writing MIDI Remote API Scripts. We provide a JSDoc based auto-completion setup. You will not have to look up types and methods in a separate documentation. Visual Studio Code will help you write scripts intuitively. 82 |
83 | 84 | 85 | 86 | 2. Make sure the folder of the [Visual Studio Code](https://code.visualstudio.com/) executable is added to the PATH environment variable. 87 | 88 | 3. Make sure you have the newest Cubase / Nuendo installed. 89 | 90 | 4. Start Cubase / Nuendo. 91 | 92 | 5. Create a project with audio and/or instrument tracks. 93 | 94 | 6. Open the Remote tab in the lower zone. 95 | 96 | 97 | 98 | 1. Open the **MIDI Remote Driver Scripts** folder. 99 | 100 | > Mac: /Users/<Username>/Documents/Steinberg/<Cubase or Nuendo>/MIDI Remote/Driver Scripts 101 | 102 | > Windows: C:\Users\\<Username>\Documents\Steinberg\<Cubase or Nuendo>\MIDI Remote\Driver Scripts 103 | 104 |
 
105 | 106 | 1. Open a console (win: cmd, mac: terminal) and go to the **MIDI Remote Driver Scripts** folder. 107 | 108 | 2. Open [Visual Studio Code](https://code.visualstudio.com/) from the command line like this: 109 | 110 | > code . 111 | 112 | 113 | 114 | 10. Create a script file. 115 | 116 | The **MIDI Remote API Script** file follows the structure: 117 | <Driver Scripts Folder>/<Local or Public>/<vendor>/<device>/<vendor>_<device>.js 118 | 119 |
120 | WARNING: Always use the folder Local for development, folder Public will be overwritten when starting Cubase / Nuendo. 121 |
122 | 123 | Example: 124 | <Driver Scripts Folder>/Local/Nektar/Impact_LX49Plus/Nektar_Impact_LX49Plus.js 125 | 126 | 1. Connect your MIDI hardware controller. 127 | 128 | 2. Open script console. 129 | 130 | 131 | 132 | > The **Script Console** appears like this: 133 | 134 | 135 | 136 | > After modifying the script file press the 'Reload Scripts' button. 137 | -------------------------------------------------------------------------------- /_docimg/overview_big.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 | 14 | Cubase / Nuendo 15 | 16 |
17 |
18 |
19 |
20 | 21 | Host 22 | 23 |
24 |
25 | 26 | 27 | 28 | 29 |
30 |
31 |
32 | 33 | 34 | Host MIDI I/O 35 | 36 | 37 |
38 |
39 |
40 |
41 | 42 | Host MIDI I/O 43 | 44 |
45 |
46 | 47 | 48 | 49 | 50 |
51 |
52 |
53 | 54 | 55 | 56 | MIDI Remote Script 57 | 58 |
59 | 60 | Written in Javascript (ES5) 61 | 62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 | 70 | MIDI Remote Script... 71 | 72 |
73 |
74 | 75 | 76 | 77 | 78 |
79 |
80 |
81 | 82 | 83 | 84 | 85 | 86 | Host Functions 87 | 88 |
89 |
90 | 91 | Quick Controls,
92 | Selected Track,
93 | MixConsole,
94 | Key Commands,
95 | ... 96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 | 106 | Host Functions... 107 | 108 |
109 |
110 | 111 | 112 | 113 | 114 | 115 | 116 |
117 | 118 | 119 | 120 | 121 | Viewer does not support full SVG 1.1 122 | 123 | 124 | 125 |
126 | -------------------------------------------------------------------------------- /alesis/vi49/alesis_vi49.js: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // 1. DRIVER SETUP - create driver object, midi ports and detection information 3 | //----------------------------------------------------------------------------- 4 | 5 | // get the api's entry point 6 | var midiremote_api = require('midiremote_api_v1') 7 | 8 | // create the device driver main object 9 | var deviceDriver = midiremote_api.makeDeviceDriver('Alesis', 'VI49', 'MH') 10 | 11 | // create objects representing the hardware's MIDI ports 12 | var midiInput = deviceDriver.mPorts.makeMidiInput() 13 | var midiOutput = deviceDriver.mPorts.makeMidiOutput() 14 | 15 | // define all possible namings the devices MIDI ports could have 16 | // NOTE: Windows and MacOS handle port naming differently 17 | deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput) 18 | .expectInputNameEquals('VI49') 19 | .expectOutputNameEquals('VI49') 20 | 21 | //----------------------------------------------------------------------------- 22 | // 2. SURFACE LAYOUT - create control elements and midi bindings 23 | //----------------------------------------------------------------------------- 24 | var surface = deviceDriver.mSurface 25 | 26 | var keyboard = {} 27 | keyboard.knobs = {} 28 | keyboard.knobs.num = 12 29 | keyboard.knobs.channel = 0 30 | keyboard.buttons = {} 31 | keyboard.buttons.rows = 3 32 | keyboard.buttons.channel = 1 33 | keyboard.buttons.cc = [ 34 | 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 35 | 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 36 | 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 37 | ] 38 | keyboard.pads = {} 39 | keyboard.pads.num = 16 40 | keyboard.pads.channel = 1 41 | keyboard.pads.note = [ 42 | 48, 49, 50, 51, 43 | 44, 45, 46, 47, 44 | 40, 41, 42, 43, 45 | 36, 37, 38, 39, 46 | ] 47 | 48 | 49 | 50 | function makeKnobs(x, y, w, h, num, channel) { 51 | var knobs = [] 52 | for (var i = 0; i < num; i++) { 53 | var knob = surface.makeKnob(i * w + x, y, w, h) 54 | knob.mSurfaceValue.mMidiBinding.setInputPort(midiInput).setOutputPort(midiOutput).bindToControlChange(channel, i + 20) 55 | knobs[i] = knob 56 | } 57 | return knobs 58 | } 59 | 60 | function makeButtons(x, y, w, h, channel) { 61 | var buttons = [] 62 | for (var row = 0; row < keyboard.buttons.rows; row++) { 63 | for (var i = 0; i < keyboard.knobs.num; i++) { 64 | var button = surface.makeButton(i * w + x, row * h + y, w, h) 65 | button.mSurfaceValue.mMidiBinding.setInputPort(midiInput).setOutputPort(midiOutput).bindToControlChange(channel, keyboard.buttons.cc[row * 12 + i]) 66 | buttons.push(button) 67 | } 68 | } 69 | return buttons 70 | } 71 | 72 | function makePads(x, y, w, h, channel) { 73 | var pads = [] 74 | for (var row = 0; row < 4; row++) { 75 | for (var i = 0; i < 4; i++) { 76 | var pad = surface.makeTriggerPad(i * w + x, row * h + y, w, h) 77 | pad.mSurfaceValue.mMidiBinding.setInputPort(midiInput).setOutputPort(midiOutput).bindToNote(channel, keyboard.pads.note[row * 4 + i]) 78 | pads.push(pad) 79 | } 80 | } 81 | return pads 82 | } 83 | 84 | function makeTransport(x, y) { 85 | var transport = {} 86 | function mkButton(x, y, w, h, cc) { 87 | var button = {} 88 | button = surface.makeButton(x, y, w, h) 89 | button.mSurfaceValue.mMidiBinding.setInputPort(midiInput).setOutputPort(midiOutput).bindToControlChange(0, cc) 90 | return button 91 | } 92 | transport.rewind = mkButton(x, y, 1, 0.7, 116) 93 | transport.forward = mkButton(x + 1, y, 1, 0.7, 117) 94 | transport.stop = mkButton(x + 2, y, 1, 0.7, 118) 95 | transport.play = mkButton(x + 3, y, 1, 0.7, 119) 96 | transport.cycle = mkButton(x + 4, y, 1, 0.7, 115) 97 | transport.record = mkButton(x + 5, y, 1, 0.7, 114) 98 | return transport 99 | } 100 | 101 | function makeSurfaceElements(){ 102 | var surfaceElements = {} 103 | surfaceElements.knobs = makeKnobs(11, 0, 1.2, 2, keyboard.knobs.num, keyboard.knobs.channel) 104 | surfaceElements.buttons = makeButtons(11, 1.5, 1.2, 0.7, keyboard.buttons.channel) 105 | surfaceElements.pads = makePads(0, 4, 1, 1, keyboard.pads.channel) 106 | surfaceElements.transport = makeTransport(4, 2.5) 107 | surfaceElements.pb = surface.makeBlindPanel(0, 0, 0.75, 2) 108 | surfaceElements.mw = surface.makeBlindPanel(1, 0, 0.75, 2) 109 | surfaceElements.piano = surface.makePianoKeys(4, 4, 24, 4, 0, 48) 110 | return surfaceElements 111 | } 112 | 113 | var surfaceElements = makeSurfaceElements() 114 | //----------------------------------------------------------------------------- 115 | // 3. HOST MAPPING - create mapping pages and host bindings 116 | //----------------------------------------------------------------------------- 117 | 118 | var page = deviceDriver.mMapping.makePage('Default') 119 | //Knobs 120 | var knobs = surfaceElements.knobs 121 | for (var i = 0; i < 8; i++) { 122 | var knobSurfaceValue = knobs[i].mSurfaceValue 123 | page.makeValueBinding(knobSurfaceValue, page.mHostAccess.mFocusedQuickControls.getByIndex(i)).setValueTakeOverModePickup() 124 | } 125 | page.makeValueBinding(knobs[8].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mVolume).setValueTakeOverModePickup() 126 | page.makeValueBinding(knobs[9].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mPan).setValueTakeOverModePickup() 127 | page.makeValueBinding(knobs[10].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mSends.getByIndex(0).mLevel).setValueTakeOverModePickup() 128 | page.makeValueBinding(knobs[11].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mSends.getByIndex(1).mLevel).setValueTakeOverModePickup() 129 | 130 | //Transport 131 | var transport = surfaceElements.transport 132 | page.makeValueBinding(transport.rewind.mSurfaceValue, page.mHostAccess.mTransport.mValue.mRewind) 133 | page.makeValueBinding(transport.forward.mSurfaceValue, page.mHostAccess.mTransport.mValue.mForward) 134 | page.makeValueBinding(transport.stop.mSurfaceValue, page.mHostAccess.mTransport.mValue.mStop).setTypeToggle() 135 | page.makeValueBinding(transport.play.mSurfaceValue, page.mHostAccess.mTransport.mValue.mStart).setTypeToggle() 136 | page.makeValueBinding(transport.cycle.mSurfaceValue, page.mHostAccess.mTransport.mValue.mCycleActive).setTypeToggle() 137 | page.makeValueBinding(transport.record.mSurfaceValue, page.mHostAccess.mTransport.mValue.mRecord).setTypeToggle() 138 | 139 | 140 | //Pads 141 | var pads = surfaceElements.pads 142 | page.makeCommandBinding(pads[0].mSurfaceValue, 'Mixer', 'Bypass: Inserts') 143 | page.makeCommandBinding(pads[1].mSurfaceValue, 'Mixer', 'Bypass: EQs') 144 | page.makeCommandBinding(pads[2].mSurfaceValue, 'Mixer', 'Bypass: Channel Strip') 145 | page.makeCommandBinding(pads[3].mSurfaceValue, 'Mixer', 'Bypass: Sends') 146 | 147 | page.makeCommandBinding(pads[4].mSurfaceValue, 'Devices', 'Mixer') 148 | page.makeCommandBinding(pads[5].mSurfaceValue, 'Editors', 'Open/Close Editor') 149 | page.makeActionBinding(pads[6].mSurfaceValue, page.mHostAccess.mTrackSelection.mAction.mPrevTrack) 150 | page.makeActionBinding(pads[7].mSurfaceValue, page.mHostAccess.mTrackSelection.mAction.mNextTrack) 151 | 152 | page.makeValueBinding(pads[8].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mMute).setTypeToggle() 153 | page.makeValueBinding(pads[9].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mSolo).setTypeToggle() 154 | page.makeValueBinding(pads[10].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mAutomationRead).setTypeToggle() 155 | page.makeValueBinding(pads[11].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mAutomationWrite).setTypeToggle() 156 | 157 | page.makeValueBinding(pads[12].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mRecordEnable).setTypeToggle() 158 | page.makeValueBinding(pads[13].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mMonitorEnable).setTypeToggle() 159 | page.makeValueBinding(pads[14].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mEditorOpen).setTypeToggle() 160 | page.makeValueBinding(pads[15].mSurfaceValue, page.mHostAccess.mTrackSelection.mMixerChannel.mValue.mInstrumentOpen).setTypeToggle() 161 | 162 | 163 | //Switches 164 | var buttons = surfaceElements.buttons 165 | page.makeCommandBinding(buttons[0].mSurfaceValue, 'Transport', 'To Marker 1') 166 | page.makeCommandBinding(buttons[1].mSurfaceValue, 'Transport', 'To Marker 2') 167 | page.makeCommandBinding(buttons[2].mSurfaceValue, 'Transport', 'To Marker 3') 168 | page.makeCommandBinding(buttons[3].mSurfaceValue, 'Transport', 'To Marker 4') 169 | page.makeCommandBinding(buttons[4].mSurfaceValue, 'Transport', 'To Marker 5') 170 | page.makeCommandBinding(buttons[5].mSurfaceValue, 'Transport', 'To Marker 6') 171 | page.makeCommandBinding(buttons[6].mSurfaceValue, 'Transport', 'To Marker 7') 172 | page.makeCommandBinding(buttons[7].mSurfaceValue, 'Transport', 'To Marker 8') 173 | page.makeCommandBinding(buttons[8].mSurfaceValue, 'Transport', 'To Marker 9') 174 | -------------------------------------------------------------------------------- /behringer/bcr2000/behringer_bcr2000.js: -------------------------------------------------------------------------------- 1 | // Behringer BCR2000 v 1.6 by Giampaolo Gesuale 2 | 3 | //----------------------------------------------------------------------------- 4 | // 1. DRIVER SETUP - create driver object, midi ports and detection information 5 | //----------------------------------------------------------------------------- 6 | 7 | var midiremote_api = require('midiremote_api_v1') 8 | var deviceDriver = midiremote_api.makeDeviceDriver('Behringer', 'BCR2000', 'Giampaolo Gesuale') 9 | 10 | var midiInput = deviceDriver.mPorts.makeMidiInput() 11 | var midiOutput = deviceDriver.mPorts.makeMidiOutput() 12 | 13 | deviceDriver.makeDetectionUnit().detectPortPair(midiInput, midiOutput) 14 | .expectInputNameEquals('BCR2000') 15 | .expectOutputNameEquals('BCR2000') 16 | 17 | //user guide 18 | //deviceDriver.setUserGuide ('BCR2000_midi_remote.pdf') 19 | 20 | //submit bcr preset: to be tested 21 | //midiOutput.sendSysexFile(activeDevice, 'preset.bcr', 5) 22 | 23 | //----------------------------------------------------------------------------- 24 | // 2. SURFACE LAYOUT - create control elements and midi bindings 25 | //----------------------------------------------------------------------------- 26 | 27 | var surface= deviceDriver.mSurface 28 | var selTrackName = surface.makeLabelField(18,2,4,1) 29 | var pagename = surface.makeLabelField(18,12,4,0.9) 30 | 31 | var trackNames = [] 32 | for (var i = 0; i < 8; ++i){ 33 | var trackName = surface.makeLabelField(i*2,15,2,0.6) 34 | trackNames.push(trackName) 35 | } 36 | 37 | 38 | //layer zone 39 | var encoderGroups = surface.makeControlLayerZone('Encoder Groups') 40 | var encoderGroup1 = encoderGroups.makeControlLayer('Group 1') 41 | var encoderGroup2 = encoderGroups.makeControlLayer('Group 2') 42 | var encoderGroup3 = encoderGroups.makeControlLayer('Group 3') 43 | var encoderGroup4 = encoderGroups.makeControlLayer('Group 4') 44 | 45 | var knobs =[] 46 | var buttons = [] 47 | 48 | var inarow = 8 49 | var nEncoders = 32 50 | var gruppo = encoderGroup1 51 | 52 | //encoders 53 | for(var r = 0; r < nEncoders/inarow; ++r) { 54 | switch (r){ 55 | case 0: gruppo = encoderGroup1 56 | break 57 | case 1: gruppo = encoderGroup2 58 | break 59 | case 2: gruppo = encoderGroup3 60 | break 61 | case 3: gruppo = encoderGroup4 62 | } 63 | for (var c=0; c lastNavKnobValue) { 261 | console.log("UP 2: " + newValue + ", scene: " + knobScene); 262 | navKnobButtons[knobScene][1].mSurfaceValue.setProcessValue(context, 127) 263 | } else { 264 | console.log("DOWN 3: " + newValue + ", scene: " + knobScene); 265 | navKnobButtons[knobScene][0].mSurfaceValue.setProcessValue(context, 127) 266 | } 267 | lastNavKnobValue = newValue; 268 | } 269 | 270 | knob.mSurfaceValue.mMidiBinding 271 | .setInputPort(midiInput) 272 | .setOutputPort(midiOutput) 273 | .bindToControlChange(0, 49); 274 | 275 | hostMapper.mapNavigationKnobButtons(navKnobButtons); 276 | } 277 | 278 | this.initFaders = function() { 279 | var selectButtonsMidi = [ 280 | {channel: 1, code: 64}, 281 | {channel: 1, code: 66}, 282 | {channel: 1, code: 67}, 283 | {channel: 1, code: 65}, 284 | {channel: 1, code: 68}, 285 | {channel: 1, code: 80}, 286 | {channel: 1, code: 81}, 287 | {channel: 1, code: 123}, 288 | 289 | ]; 290 | 291 | var fadersMidi = [1, 11, 7, 10, 5, 84, 2, 16]; 292 | var faders = []; 293 | 294 | for(var i = 0; i < numBankItems; i++) { 295 | 296 | var selectButton = deviceDriver.mSurface.makeButton(i * 2 + 2, 0, 2, 1) 297 | selectButton.mSurfaceValue.mMidiBinding 298 | .setInputPort(midiInput) 299 | .setOutputPort(midiOutput) 300 | .bindToControlChange (selectButtonsMidi[i].channel, selectButtonsMidi[i].code); 301 | hostMapper.mapSelectButton(selectButton, i); 302 | 303 | var muteButton = deviceDriver.mSurface.makeButton(i * 2 + 2, 1, 1, 1); 304 | muteButton.mSurfaceValue.mMidiBinding 305 | .setInputPort(midiInput) 306 | .setOutputPort(midiOutput) 307 | .bindToControlChange(2, 23 + i); 308 | hostMapper.mapMuteButton(muteButton, i); 309 | 310 | var soloButton = deviceDriver.mSurface.makeButton(i * 2 + 3, 1, 1, 1); 311 | soloButton.mSurfaceValue.mMidiBinding 312 | .setInputPort(midiInput) 313 | .setOutputPort(midiOutput) 314 | .bindToControlChange(3, 23 + i); 315 | hostMapper.mapSoloButton(soloButton, i); 316 | 317 | var fader = deviceDriver.mSurface.makeFader(i * 2 + 0.5 + 2, 2, 1, 6); 318 | 319 | fader.mSurfaceValue.mMidiBinding 320 | .setInputPort(midiInput) //received from device 321 | // causes fader 3 to overtake fader 1 322 | // .setOutputPort(midiOutput) //sent to device, 323 | .bindToControlChange(0, fadersMidi[i]); 324 | 325 | faders.push(fader); 326 | } 327 | hostMapper.mapFaders(faders); 328 | } 329 | return this; 330 | } 331 | 332 | // --- 333 | 334 | function HostMapper(device) { 335 | var pageDefault = device.driver.mMapping.makePage("Main Page"); 336 | var pageEq = device.driver.mMapping.makePage("Channel Page"); 337 | 338 | pageDefault.mOnActivate = function (context) { 339 | console.log('Default Page Activated'); 340 | } 341 | pageEq.mOnActivate = function (context) { 342 | console.log('Channel Page Activated'); 343 | } 344 | var mixerBankZone = pageDefault.mHostAccess.mMixConsole.makeMixerBankZone(); 345 | var selectedMixerChannel = pageEq.mHostAccess.mTrackSelection.mMixerChannel; 346 | 347 | var mainChannel = mixerBankZone.makeMixerBankChannel(); 348 | 349 | var channels = []; 350 | 351 | for (var i = 0 ; i < 8 ; i++) { 352 | channels.push(mixerBankZone.makeMixerBankChannel()); 353 | } 354 | this.pageDefault = pageDefault; 355 | this.pageEq = pageEq; 356 | 357 | this.mapPluginsButton = function(button) { 358 | pageDefault.makeActionBinding(button.mSurfaceValue, device.driver.mAction.mNextPage); 359 | pageEq.makeActionBinding(button.mSurfaceValue, device.driver.mAction.mPrevPage); 360 | } 361 | 362 | this.mapPanKnob = function(panKnob) { 363 | this.pageDefault.makeValueBinding (panKnob.mSurfaceValue, pageDefault.mHostAccess.mTrackSelection.mMixerChannel.mValue.mPan) ; 364 | } 365 | 366 | this.mapNavigationKnobButtons = function(navKnobButtons){ 367 | pageDefault.makeActionBinding(navKnobButtons[0][0].mSurfaceValue, pageDefault.mHostAccess.mTrackSelection.mAction.mPrevTrack); 368 | pageDefault.makeActionBinding(navKnobButtons[0][1].mSurfaceValue, pageDefault.mHostAccess.mTrackSelection.mAction.mNextTrack); 369 | 370 | pageDefault.makeCommandBinding(navKnobButtons[1][1].mSurfaceValue, 'Zoom', 'Zoom In'); 371 | pageDefault.makeCommandBinding(navKnobButtons[1][0].mSurfaceValue, 'Zoom', 'Zoom Out'); 372 | 373 | pageDefault.makeCommandBinding(navKnobButtons[2][1].mSurfaceValue, 'Transport', 'Nudge Cursor Right'); 374 | pageDefault.makeCommandBinding(navKnobButtons[2][0].mSurfaceValue, 'Transport', 'Nudge Cursor Left'); 375 | 376 | pageDefault.makeCommandBinding(navKnobButtons[3][1].mSurfaceValue, 'Navigate', 'Right'); 377 | pageDefault.makeCommandBinding(navKnobButtons[3][0].mSurfaceValue, 'Navigate', 'Left'); 378 | 379 | } 380 | 381 | this.mapFaders = function(faders) { 382 | for (var i = 0 ; i < faders.length ; i++) { 383 | this.mapFader(faders[i], i); 384 | } 385 | }; 386 | 387 | this.mapFader = function(fader, channelIndex) { 388 | this.pageDefault.makeValueBinding (fader.mSurfaceValue, channels[channelIndex].mValue.mVolume) ; 389 | 390 | // from host to device 391 | (function (channelNumber) { 392 | channels[channelNumber].mValue.mVolume.mOnProcessValueChange = function (a, b, newValue) { 393 | device.midiOutput.sendMidi(a, [176 + channelNumber, 7, parseInt(newValue * 127)]); 394 | } 395 | })(channelIndex); 396 | 397 | 398 | 399 | switch (channelIndex) { 400 | case 0: 401 | this.pageEq.makeValueBinding (fader.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand1.mGain); 402 | 403 | selectedMixerChannel.mChannelEQ.mBand1.mGain.mOnProcessValueChange = function (a, b, newValue) { 404 | device.midiOutput.sendMidi(a, [176 + channelIndex, 7, parseInt(newValue * 127)]); 405 | } 406 | break; 407 | case 1: 408 | this.pageEq.makeValueBinding (fader.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand2.mGain); 409 | 410 | selectedMixerChannel.mChannelEQ.mBand2.mGain.mOnProcessValueChange = function (a, b, newValue) { 411 | device.midiOutput.sendMidi(a, [176 + channelIndex, 7, parseInt(newValue * 127)]); 412 | } 413 | break; 414 | case 2: 415 | this.pageEq.makeValueBinding (fader.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand3.mGain); 416 | 417 | selectedMixerChannel.mChannelEQ.mBand3.mGain.mOnProcessValueChange = function (a, b, newValue) { 418 | device.midiOutput.sendMidi(a, [176 + channelIndex, 7, parseInt(newValue * 127)]); 419 | } 420 | break; 421 | case 3: 422 | this.pageEq.makeValueBinding (fader.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand4.mGain); 423 | 424 | selectedMixerChannel.mChannelEQ.mBand4.mGain.mOnProcessValueChange = function (a, b, newValue) { 425 | device.midiOutput.sendMidi(a, [176 + channelIndex, 7, parseInt(newValue * 127)]); 426 | } 427 | break; 428 | case 4: 429 | this.pageEq.makeValueBinding (fader.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand1.mFreq); 430 | 431 | selectedMixerChannel.mChannelEQ.mBand1.mFreq.mOnProcessValueChange = function (a, b, newValue) { 432 | device.midiOutput.sendMidi(a, [176 + channelIndex, 7, parseInt(newValue * 127)]); 433 | } 434 | break; 435 | case 5: 436 | this.pageEq.makeValueBinding (fader.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand2.mFreq); 437 | 438 | selectedMixerChannel.mChannelEQ.mBand2.mFreq.mOnProcessValueChange = function (a, b, newValue) { 439 | device.midiOutput.sendMidi(a, [176 + channelIndex, 7, parseInt(newValue * 127)]); 440 | } 441 | break; 442 | case 6: 443 | this.pageEq.makeValueBinding (fader.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand3.mFreq); 444 | 445 | selectedMixerChannel.mChannelEQ.mBand3.mFreq.mOnProcessValueChange = function (a, b, newValue) { 446 | device.midiOutput.sendMidi(a, [176 + channelIndex, 7, parseInt(newValue * 127)]); 447 | } 448 | break; 449 | case 7: 450 | this.pageEq.makeValueBinding (fader.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand4.mFreq); 451 | 452 | selectedMixerChannel.mChannelEQ.mBand4.mFreq.mOnProcessValueChange = function (a, b, newValue) { 453 | device.midiOutput.sendMidi(a, [176 + channelIndex, 7, parseInt(newValue * 127)]); 454 | } 455 | break; 456 | } 457 | }; 458 | 459 | this.mapSelectButton = function(button, channelIndex) { 460 | switch (channelIndex) { 461 | case 0: 462 | this.pageEq.makeValueBinding (button.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand1.mOn); 463 | break; 464 | case 1: 465 | this.pageEq.makeValueBinding (button.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand2.mOn); 466 | break; 467 | case 2: 468 | this.pageEq.makeValueBinding (button.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand3.mOn); 469 | break; 470 | case 3: 471 | this.pageEq.makeValueBinding (button.mSurfaceValue, selectedMixerChannel.mChannelEQ.mBand4.mOn); 472 | break; 473 | } 474 | this.pageDefault.makeValueBinding (button.mSurfaceValue, channels[channelIndex].mValue.mSelected); 475 | }; 476 | 477 | this.mapMuteButtons = function(buttons) { 478 | for(var i = 0 ; i < buttons.length ; i++) { 479 | this.mapMuteButton (buttons[i], i); 480 | } 481 | }; 482 | 483 | this.mapMuteButton = function(button, channelIndex) { 484 | this.pageDefault.makeValueBinding(button.mSurfaceValue, channels[channelIndex].mValue.mMute); 485 | }; 486 | 487 | this.mapSoloButtons = function(buttons) { 488 | for(var i = 0 ; i < buttons.length ; i++) { 489 | this.mapSoloButton (buttons[i], i); 490 | } 491 | }; 492 | 493 | this.mapSoloButton = function(button, channelIndex) { 494 | this.pageDefault.makeValueBinding(button.mSurfaceValue, channels[channelIndex].mValue.mSolo); 495 | }; 496 | 497 | this.getMainChannel = function() { 498 | return mainChannel; 499 | } 500 | 501 | return this; 502 | } -------------------------------------------------------------------------------- /_docimg/script_structure.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 |
12 |
13 | 14 | 15 | 1. Driver Setup 16 | 17 | 18 |
19 |
20 |
21 |
22 | 23 | Driver Setup 24 | 25 |
26 |
27 | 28 | 29 | 30 | 31 |
32 |
33 |
34 | 35 | 36 | 2. Surface Layout 37 | 38 | 39 |
40 |
41 |
42 |
43 | 44 | Surface Layout 45 | 46 |
47 |
48 | 49 | 50 | 51 | 52 |
53 |
54 |
55 | 56 | 57 | 3. Host Mapping 58 | 59 | 60 |
61 |
62 |
63 |
64 | 65 | Host Mapping 66 | 67 |
68 |
69 | 70 | 71 | 72 | 73 |
74 |
75 |
76 | 77 | 78 | 79 | SurfaceElement 80 | 81 | 82 |
83 | 84 | Knob, Fader, Button, ... 85 | 86 |
87 |
88 |
89 |
90 |
91 | 92 | Element... 93 | 94 |
95 |
96 | 97 | 98 | 99 | 100 | 101 | 102 |
103 |
104 |
105 | 106 | 107 | Page 108 | 109 | 110 |
111 |
112 |
113 |
114 | 115 | Page 116 | 117 |
118 |
119 | 120 | 121 | 122 | 123 |
124 |
125 |
126 | 127 | 128 | ValueBinding 129 | 130 | 131 |
132 |
133 |
134 |
135 | 136 | ValueBinding 137 | 138 |
139 |
140 | 141 | 142 | 143 | 144 |
145 |
146 |
147 | 148 | 149 | 150 | HostObject 151 | 152 |
153 | Transport, MixConsole, ... 154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 | 162 | HostObject... 163 | 164 |
165 |
166 | 167 | 168 | 169 | 170 |
171 |
172 |
173 | 174 | SurfaceValue 175 | 176 |
177 |
178 |
179 |
180 | 181 | SurfaceValue 182 | 183 |
184 |
185 | 186 | 187 | 188 | 189 |
190 |
191 |
192 | 193 | HostValue 194 | 195 |
196 |
197 |
198 |
199 | 200 | HostValue 201 | 202 |
203 |
204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 |
219 |
220 |
221 | 222 | 223 | 224 | HostAccess 225 | 226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 | 234 | HostAccess 235 | 236 |
237 |
238 | 239 | 240 | 241 | 242 |
243 |
244 |
245 | 246 | 247 | MIDI Input 248 | 249 | 250 |
251 |
252 |
253 |
254 | 255 | MIDI Input 256 | 257 |
258 |
259 | 260 | 261 | 262 | 263 |
264 |
265 |
266 | 267 | 268 | MIDI Output 269 | 270 | 271 |
272 |
273 |
274 |
275 | 276 | MIDI Output 277 | 278 |
279 |
280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 |
297 |
298 |
299 | 300 | 301 | MIDI Binding 302 | 303 | 304 |
305 |
306 |
307 |
308 | 309 | MIDI Binding 310 | 311 |
312 |
313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 |
323 | 324 | 325 | 326 | 327 | Viewer does not support full SVG 1.1 328 | 329 | 330 | 331 |
332 | -------------------------------------------------------------------------------- /Akai/LPD8/Akai_LPD8.json: -------------------------------------------------------------------------------- 1 | { 2 | "api": "midiremote", 3 | "version": "1.0", 4 | "objects": { 5 | "root": 80, 6 | "internal": [ 7 | { 8 | "id": 1, 9 | "type": "DeviceDriver", 10 | "members": { 11 | "VendorName": "Akai", 12 | "DeviceName": "LPD8", 13 | "CreatedBy": "Alex Herington", 14 | "DetectionUnits": [ 15 | 9 16 | ], 17 | "Ports": 2, 18 | "Surface": 3, 19 | "Mapping": 4 20 | } 21 | }, 22 | { 23 | "id": 2, 24 | "type": "Ports", 25 | "members": { 26 | "MidiInputs": [ 27 | 5 28 | ], 29 | "MidiOutputs": [ 30 | 6 31 | ] 32 | } 33 | }, 34 | { 35 | "id": 3, 36 | "type": "Surface", 37 | "members": { 38 | "SurfaceElements": [ 39 | 10, 40 | 14, 41 | 18, 42 | 22, 43 | 26, 44 | 30, 45 | 34, 46 | 38, 47 | 42, 48 | 46, 49 | 50, 50 | 54, 51 | 58, 52 | 62, 53 | 66, 54 | 70 55 | ] 56 | } 57 | }, 58 | { 59 | "id": 4, 60 | "type": "FactoryMapping", 61 | "members": { 62 | "Pages": [ 63 | 7 64 | ] 65 | } 66 | }, 67 | { 68 | "id": 5, 69 | "type": "DeviceMidiInput", 70 | "members": { 71 | "Name": "" 72 | } 73 | }, 74 | { 75 | "id": 6, 76 | "type": "DeviceMidiOutput", 77 | "members": { 78 | "Name": "" 79 | } 80 | }, 81 | { 82 | "id": 7, 83 | "type": "FactoryMappingPage", 84 | "members": { 85 | "Name": "Default", 86 | "HostAccess": 8 87 | } 88 | }, 89 | { 90 | "id": 8, 91 | "type": "HostAccess" 92 | }, 93 | { 94 | "id": 9, 95 | "type": "DeviceDetectionUnit", 96 | "members": { 97 | "Entries": [ 98 | 77 99 | ] 100 | } 101 | }, 102 | { 103 | "id": 10, 104 | "type": "Knob", 105 | "members": { 106 | "Rect": { 107 | "X": 8.0, 108 | "Y": 0.0, 109 | "W": 2.0, 110 | "H": 2.0 111 | }, 112 | "SurfaceValue": 11 113 | } 114 | }, 115 | { 116 | "id": 11, 117 | "type": "SurfaceElementValue", 118 | "members": { 119 | "MidiBinding": 12 120 | } 121 | }, 122 | { 123 | "id": 12, 124 | "type": "SurfaceValueMidiBinding", 125 | "members": { 126 | "InputPort": 5, 127 | "OutputPort": 6, 128 | "IsConsuming": true, 129 | "MidiChannelBinding": 13 130 | } 131 | }, 132 | { 133 | "id": 13, 134 | "type": "MidiBindingToControlChange", 135 | "members": { 136 | "ChannelNumber": 0, 137 | "ControlChangeNumber": 1, 138 | "Type": "Absolute" 139 | } 140 | }, 141 | { 142 | "id": 14, 143 | "type": "Knob", 144 | "members": { 145 | "Rect": { 146 | "X": 10.0, 147 | "Y": 0.0, 148 | "W": 2.0, 149 | "H": 2.0 150 | }, 151 | "SurfaceValue": 15 152 | } 153 | }, 154 | { 155 | "id": 15, 156 | "type": "SurfaceElementValue", 157 | "members": { 158 | "MidiBinding": 16 159 | } 160 | }, 161 | { 162 | "id": 16, 163 | "type": "SurfaceValueMidiBinding", 164 | "members": { 165 | "InputPort": 5, 166 | "OutputPort": 6, 167 | "IsConsuming": true, 168 | "MidiChannelBinding": 17 169 | } 170 | }, 171 | { 172 | "id": 17, 173 | "type": "MidiBindingToControlChange", 174 | "members": { 175 | "ChannelNumber": 0, 176 | "ControlChangeNumber": 2, 177 | "Type": "Absolute" 178 | } 179 | }, 180 | { 181 | "id": 18, 182 | "type": "Knob", 183 | "members": { 184 | "Rect": { 185 | "X": 12.0, 186 | "Y": 0.0, 187 | "W": 2.0, 188 | "H": 2.0 189 | }, 190 | "SurfaceValue": 19 191 | } 192 | }, 193 | { 194 | "id": 19, 195 | "type": "SurfaceElementValue", 196 | "members": { 197 | "MidiBinding": 20 198 | } 199 | }, 200 | { 201 | "id": 20, 202 | "type": "SurfaceValueMidiBinding", 203 | "members": { 204 | "InputPort": 5, 205 | "OutputPort": 6, 206 | "IsConsuming": true, 207 | "MidiChannelBinding": 21 208 | } 209 | }, 210 | { 211 | "id": 21, 212 | "type": "MidiBindingToControlChange", 213 | "members": { 214 | "ChannelNumber": 0, 215 | "ControlChangeNumber": 3, 216 | "Type": "Absolute" 217 | } 218 | }, 219 | { 220 | "id": 22, 221 | "type": "Knob", 222 | "members": { 223 | "Rect": { 224 | "X": 14.0, 225 | "Y": 0.0, 226 | "W": 2.0, 227 | "H": 2.0 228 | }, 229 | "SurfaceValue": 23 230 | } 231 | }, 232 | { 233 | "id": 23, 234 | "type": "SurfaceElementValue", 235 | "members": { 236 | "MidiBinding": 24 237 | } 238 | }, 239 | { 240 | "id": 24, 241 | "type": "SurfaceValueMidiBinding", 242 | "members": { 243 | "InputPort": 5, 244 | "OutputPort": 6, 245 | "IsConsuming": true, 246 | "MidiChannelBinding": 25 247 | } 248 | }, 249 | { 250 | "id": 25, 251 | "type": "MidiBindingToControlChange", 252 | "members": { 253 | "ChannelNumber": 0, 254 | "ControlChangeNumber": 4, 255 | "Type": "Absolute" 256 | } 257 | }, 258 | { 259 | "id": 26, 260 | "type": "Knob", 261 | "members": { 262 | "Rect": { 263 | "X": 8.0, 264 | "Y": 2.0, 265 | "W": 2.0, 266 | "H": 2.0 267 | }, 268 | "SurfaceValue": 27 269 | } 270 | }, 271 | { 272 | "id": 27, 273 | "type": "SurfaceElementValue", 274 | "members": { 275 | "MidiBinding": 28 276 | } 277 | }, 278 | { 279 | "id": 28, 280 | "type": "SurfaceValueMidiBinding", 281 | "members": { 282 | "InputPort": 5, 283 | "OutputPort": 6, 284 | "IsConsuming": true, 285 | "MidiChannelBinding": 29 286 | } 287 | }, 288 | { 289 | "id": 29, 290 | "type": "MidiBindingToControlChange", 291 | "members": { 292 | "ChannelNumber": 0, 293 | "ControlChangeNumber": 5, 294 | "Type": "Absolute" 295 | } 296 | }, 297 | { 298 | "id": 30, 299 | "type": "Knob", 300 | "members": { 301 | "Rect": { 302 | "X": 10.0, 303 | "Y": 2.0, 304 | "W": 2.0, 305 | "H": 2.0 306 | }, 307 | "SurfaceValue": 31 308 | } 309 | }, 310 | { 311 | "id": 31, 312 | "type": "SurfaceElementValue", 313 | "members": { 314 | "MidiBinding": 32 315 | } 316 | }, 317 | { 318 | "id": 32, 319 | "type": "SurfaceValueMidiBinding", 320 | "members": { 321 | "InputPort": 5, 322 | "OutputPort": 6, 323 | "IsConsuming": true, 324 | "MidiChannelBinding": 33 325 | } 326 | }, 327 | { 328 | "id": 33, 329 | "type": "MidiBindingToControlChange", 330 | "members": { 331 | "ChannelNumber": 0, 332 | "ControlChangeNumber": 6, 333 | "Type": "Absolute" 334 | } 335 | }, 336 | { 337 | "id": 34, 338 | "type": "Knob", 339 | "members": { 340 | "Rect": { 341 | "X": 12.0, 342 | "Y": 2.0, 343 | "W": 2.0, 344 | "H": 2.0 345 | }, 346 | "SurfaceValue": 35 347 | } 348 | }, 349 | { 350 | "id": 35, 351 | "type": "SurfaceElementValue", 352 | "members": { 353 | "MidiBinding": 36 354 | } 355 | }, 356 | { 357 | "id": 36, 358 | "type": "SurfaceValueMidiBinding", 359 | "members": { 360 | "InputPort": 5, 361 | "OutputPort": 6, 362 | "IsConsuming": true, 363 | "MidiChannelBinding": 37 364 | } 365 | }, 366 | { 367 | "id": 37, 368 | "type": "MidiBindingToControlChange", 369 | "members": { 370 | "ChannelNumber": 0, 371 | "ControlChangeNumber": 7, 372 | "Type": "Absolute" 373 | } 374 | }, 375 | { 376 | "id": 38, 377 | "type": "Knob", 378 | "members": { 379 | "Rect": { 380 | "X": 14.0, 381 | "Y": 2.0, 382 | "W": 2.0, 383 | "H": 2.0 384 | }, 385 | "SurfaceValue": 39 386 | } 387 | }, 388 | { 389 | "id": 39, 390 | "type": "SurfaceElementValue", 391 | "members": { 392 | "MidiBinding": 40 393 | } 394 | }, 395 | { 396 | "id": 40, 397 | "type": "SurfaceValueMidiBinding", 398 | "members": { 399 | "InputPort": 5, 400 | "OutputPort": 6, 401 | "IsConsuming": true, 402 | "MidiChannelBinding": 41 403 | } 404 | }, 405 | { 406 | "id": 41, 407 | "type": "MidiBindingToControlChange", 408 | "members": { 409 | "ChannelNumber": 0, 410 | "ControlChangeNumber": 8, 411 | "Type": "Absolute" 412 | } 413 | }, 414 | { 415 | "id": 42, 416 | "type": "Button", 417 | "members": { 418 | "Rect": { 419 | "X": 0.0, 420 | "Y": 0.0, 421 | "W": 2.0, 422 | "H": 2.0 423 | }, 424 | "SurfaceValue": 43, 425 | "Type": "Push", 426 | "Shape": "Rectangle" 427 | } 428 | }, 429 | { 430 | "id": 43, 431 | "type": "SurfaceElementValue", 432 | "members": { 433 | "MidiBinding": 44 434 | } 435 | }, 436 | { 437 | "id": 44, 438 | "type": "SurfaceValueMidiBinding", 439 | "members": { 440 | "InputPort": 5, 441 | "OutputPort": 6, 442 | "IsConsuming": true, 443 | "MidiChannelBinding": 45 444 | } 445 | }, 446 | { 447 | "id": 45, 448 | "type": "MidiBindingToNote", 449 | "members": { 450 | "ChannelNumber": 0, 451 | "Pitch": 40 452 | } 453 | }, 454 | { 455 | "id": 46, 456 | "type": "Button", 457 | "members": { 458 | "Rect": { 459 | "X": 2.0, 460 | "Y": 0.0, 461 | "W": 2.0, 462 | "H": 2.0 463 | }, 464 | "SurfaceValue": 47, 465 | "Type": "Push", 466 | "Shape": "Rectangle" 467 | } 468 | }, 469 | { 470 | "id": 47, 471 | "type": "SurfaceElementValue", 472 | "members": { 473 | "MidiBinding": 48 474 | } 475 | }, 476 | { 477 | "id": 48, 478 | "type": "SurfaceValueMidiBinding", 479 | "members": { 480 | "InputPort": 5, 481 | "OutputPort": 6, 482 | "IsConsuming": true, 483 | "MidiChannelBinding": 49 484 | } 485 | }, 486 | { 487 | "id": 49, 488 | "type": "MidiBindingToNote", 489 | "members": { 490 | "ChannelNumber": 0, 491 | "Pitch": 41 492 | } 493 | }, 494 | { 495 | "id": 50, 496 | "type": "Button", 497 | "members": { 498 | "Rect": { 499 | "X": 4.0, 500 | "Y": 0.0, 501 | "W": 2.0, 502 | "H": 2.0 503 | }, 504 | "SurfaceValue": 51, 505 | "Type": "Push", 506 | "Shape": "Rectangle" 507 | } 508 | }, 509 | { 510 | "id": 51, 511 | "type": "SurfaceElementValue", 512 | "members": { 513 | "MidiBinding": 52 514 | } 515 | }, 516 | { 517 | "id": 52, 518 | "type": "SurfaceValueMidiBinding", 519 | "members": { 520 | "InputPort": 5, 521 | "OutputPort": 6, 522 | "IsConsuming": true, 523 | "MidiChannelBinding": 53 524 | } 525 | }, 526 | { 527 | "id": 53, 528 | "type": "MidiBindingToNote", 529 | "members": { 530 | "ChannelNumber": 0, 531 | "Pitch": 42 532 | } 533 | }, 534 | { 535 | "id": 54, 536 | "type": "Button", 537 | "members": { 538 | "Rect": { 539 | "X": 6.0, 540 | "Y": 0.0, 541 | "W": 2.0, 542 | "H": 2.0 543 | }, 544 | "SurfaceValue": 55, 545 | "Type": "Push", 546 | "Shape": "Rectangle" 547 | } 548 | }, 549 | { 550 | "id": 55, 551 | "type": "SurfaceElementValue", 552 | "members": { 553 | "MidiBinding": 56 554 | } 555 | }, 556 | { 557 | "id": 56, 558 | "type": "SurfaceValueMidiBinding", 559 | "members": { 560 | "InputPort": 5, 561 | "OutputPort": 6, 562 | "IsConsuming": true, 563 | "MidiChannelBinding": 57 564 | } 565 | }, 566 | { 567 | "id": 57, 568 | "type": "MidiBindingToNote", 569 | "members": { 570 | "ChannelNumber": 0, 571 | "Pitch": 43 572 | } 573 | }, 574 | { 575 | "id": 58, 576 | "type": "Button", 577 | "members": { 578 | "Rect": { 579 | "X": 0.0, 580 | "Y": 2.0, 581 | "W": 2.0, 582 | "H": 2.0 583 | }, 584 | "SurfaceValue": 59, 585 | "Type": "Push", 586 | "Shape": "Rectangle" 587 | } 588 | }, 589 | { 590 | "id": 59, 591 | "type": "SurfaceElementValue", 592 | "members": { 593 | "MidiBinding": 60 594 | } 595 | }, 596 | { 597 | "id": 60, 598 | "type": "SurfaceValueMidiBinding", 599 | "members": { 600 | "InputPort": 5, 601 | "OutputPort": 6, 602 | "IsConsuming": true, 603 | "MidiChannelBinding": 61 604 | } 605 | }, 606 | { 607 | "id": 61, 608 | "type": "MidiBindingToNote", 609 | "members": { 610 | "ChannelNumber": 0, 611 | "Pitch": 36 612 | } 613 | }, 614 | { 615 | "id": 62, 616 | "type": "Button", 617 | "members": { 618 | "Rect": { 619 | "X": 2.0, 620 | "Y": 2.0, 621 | "W": 2.0, 622 | "H": 2.0 623 | }, 624 | "SurfaceValue": 63, 625 | "Type": "Push", 626 | "Shape": "Rectangle" 627 | } 628 | }, 629 | { 630 | "id": 63, 631 | "type": "SurfaceElementValue", 632 | "members": { 633 | "MidiBinding": 64 634 | } 635 | }, 636 | { 637 | "id": 64, 638 | "type": "SurfaceValueMidiBinding", 639 | "members": { 640 | "InputPort": 5, 641 | "OutputPort": 6, 642 | "IsConsuming": true, 643 | "MidiChannelBinding": 65 644 | } 645 | }, 646 | { 647 | "id": 65, 648 | "type": "MidiBindingToNote", 649 | "members": { 650 | "ChannelNumber": 0, 651 | "Pitch": 37 652 | } 653 | }, 654 | { 655 | "id": 66, 656 | "type": "Button", 657 | "members": { 658 | "Rect": { 659 | "X": 4.0, 660 | "Y": 2.0, 661 | "W": 2.0, 662 | "H": 2.0 663 | }, 664 | "SurfaceValue": 67, 665 | "Type": "Push", 666 | "Shape": "Rectangle" 667 | } 668 | }, 669 | { 670 | "id": 67, 671 | "type": "SurfaceElementValue", 672 | "members": { 673 | "MidiBinding": 68 674 | } 675 | }, 676 | { 677 | "id": 68, 678 | "type": "SurfaceValueMidiBinding", 679 | "members": { 680 | "InputPort": 5, 681 | "OutputPort": 6, 682 | "IsConsuming": true, 683 | "MidiChannelBinding": 69 684 | } 685 | }, 686 | { 687 | "id": 69, 688 | "type": "MidiBindingToNote", 689 | "members": { 690 | "ChannelNumber": 0, 691 | "Pitch": 38 692 | } 693 | }, 694 | { 695 | "id": 70, 696 | "type": "Button", 697 | "members": { 698 | "Rect": { 699 | "X": 6.0, 700 | "Y": 2.0, 701 | "W": 2.0, 702 | "H": 2.0 703 | }, 704 | "SurfaceValue": 71, 705 | "Type": "Push", 706 | "Shape": "Rectangle" 707 | } 708 | }, 709 | { 710 | "id": 71, 711 | "type": "SurfaceElementValue", 712 | "members": { 713 | "MidiBinding": 72 714 | } 715 | }, 716 | { 717 | "id": 72, 718 | "type": "SurfaceValueMidiBinding", 719 | "members": { 720 | "InputPort": 5, 721 | "OutputPort": 6, 722 | "IsConsuming": true, 723 | "MidiChannelBinding": 73 724 | } 725 | }, 726 | { 727 | "id": 73, 728 | "type": "MidiBindingToNote", 729 | "members": { 730 | "ChannelNumber": 0, 731 | "Pitch": 39 732 | } 733 | }, 734 | { 735 | "id": 74, 736 | "type": "ExcludeInputChannelType" 737 | }, 738 | { 739 | "id": 75, 740 | "type": "ExcludeOutputChannelType" 741 | }, 742 | { 743 | "id": 76, 744 | "type": "IncludeOutputChannelType" 745 | }, 746 | { 747 | "id": 77, 748 | "type": "DetectionPortPair", 749 | "members": { 750 | "InputPort": 5, 751 | "OutputPort": 6, 752 | "InputNameFilters": [ 753 | 78 754 | ], 755 | "OutputNameFilters": [ 756 | 79 757 | ] 758 | } 759 | }, 760 | { 761 | "id": 78, 762 | "type": "DetectionInputNameFilterEquals", 763 | "members": { 764 | "FilterValue": "LPD8" 765 | } 766 | }, 767 | { 768 | "id": 79, 769 | "type": "DetectionOutputNameFilterEquals", 770 | "members": { 771 | "FilterValue": "LPD8" 772 | } 773 | } 774 | ], 775 | "external": [ 776 | { 777 | "id": 80, 778 | "type": "DomainModel", 779 | "members": { 780 | "DeviceDrivers": [ 781 | 1 782 | ] 783 | } 784 | } 785 | ] 786 | } 787 | } --------------------------------------------------------------------------------