-
Notifications
You must be signed in to change notification settings - Fork 26
Expand file tree
/
Copy pathMKtl_description_files.schelp
More file actions
373 lines (304 loc) · 13.6 KB
/
MKtl_description_files.schelp
File metadata and controls
373 lines (304 loc) · 13.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
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
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
title:: MKtl description files
summary:: describes the format for MKtl desc files and the entries in them.
categories:: Libraries>Modality
related:: Overviews/Modality, Classes/MKtl, Classes/MKtlDesc, Tutorials/How_to_create_a_description_file, Reference/MKtl_description_files, Reference/Naming_conventions_in_element_descriptions
A description file contains detailed information about a controller.
Precise information about each of its interaction elements like sliders, knobs, or buttons help to create good performance setups very efficiently.
Evaluating the code in a desc file should return a link::Classes/Dictionary:: (or more conveniently, an link::Classes/Event::) of a well-defined structure. Description files are located here:
code::
MKtlDesc.openFolder;
::
NOTE::
Find a similar controller that is already supported and use it as a blueprint for your new description file.
::
This document gives an overview on
list::
##link::#Filename conventions::
##link::#Semantic information::
##link::#Identifier naming convention::
##link::#Syntax::
::
section:: Filename convention
The filename should be of the following format:
code::
<vendor>-<device_name>_<optional_setup_naming>.desc.scd
::
where
list::
## code::<vendor>:: is lower-case name of vendor with spaces replaced by code::'-'::.
## code::<device_name>:: is lower-case name of the device with spaces replaced by code::'-'::.
This is both unique enough to identify devices, and allows linking to the modality website entry on each device.
## code::<optional_setup_naming>:: can be used to create multiple desc files for the same device, e.g. to support multiple ports (as e.g. the QuNexus keyboard), for special presets, such as making separate desc files for switchable hardware pages, or for personalized versions of desc files.
::
section:: Semantic and technical information
NOTE::
A description file is bound to a single protocol - currently one of \midi, \hid, and \osc (or \virtual for sketches). If a device communicates on multiple protocols (e.g. the EMPHASIS::icon iCONTROLS::), or on multiple ports (the EMPHASIS::QuNexus::), its components can be built from separate desc files and optionally be merged with link::Classes/CompMKtl:: where that is desirable.
::
subsection:: Top level
DEFINITIONLIST::
## deviceName | osx | linux [required]
|| For MIDI and HID, this is the device name as reported by the hardware or OS drivers. (OSC devices are not registered by the OS, so the name is only for description here).
## protocol [required]
|| The protocol used by the device. one of
code:: [\hid, \midi, \osc, \virtual].::
## deviceType [optional, but highly recommended]
|| Semantic description of what kind of device it is. This will make it easier to find another device that might easily replace it. For examples, do:
code::
MKtlDevice.deviceTypes;
MKtlDesc.loadDescs; MKtlDesc.deviceTypesUsed;
-> [ controller, drum, drumpad, externalMidiPort, fader, faderbox, gamepad, joystick, keyboard, launchpad, manta, midiKeyboard, minibee, mixer, mouse, multiController, organelle, phoneApp, push, ribbon, surface ]
::
## elementTypes [optional, but highly recommended]
|| Description of what kind of elements the device has. For example: code:: \fader, \button, \knob, \encoder, \joyAxis ...::
code::
// See all currently used types
MKtlElement.types.cs;
-> [ 'accelAxis', 'bender', 'button', 'compass', 'cvIn', 'cvOut', 'encoder', 'fader', 'gyroAxis', 'hatSwitch', 'joyAxis', 'key', 'keyTouch', 'knob', 'led', 'lever', 'midiBut', 'mouseAxis', 'mouseWheel', 'multiPurpose', 'option', 'pad', 'padX', 'padY', 'pianoKey', 'ribbon', 'rumble', 'scroller', 'slider', 'springFader', 'switch', 'thumbAxis', 'touch', 'trigger', 'voltage', 'wheel', 'xfader' ]
::
## status [optional, but highly recommended]
|| A string describing the status of this description, i.e. how complete and how well tested it is, by platform, with a nametag and date. E.g. the akai lpd8 has:
code::
status: (
osx: "tested and working, 2016_03_15, adc",
linux: "tested and working 2016_03_20, nescivi",
win: "unknown"
)
::
status is unknown until somebody tests the device, and incompleteness can be noted, such as "elements incomplete (X missing)" etc.
## idInfo | osx | linux [required]
|| The info used to fully identify the device.
For HID devices, this is a String with <productname>_<vendorname>, e.g.:
code::
"Cyborg X_Saitek"
::
For MIDI devices with a single source and/or destination port, this is the same as the deviceName. For multi-port MIDI devices, this should be a dictionary with entries for
code::
(deviceName: <deviceName>, // as reported in
srcPortIndex: <index in list of this device's in ports>,
destPortIndex: <index in list of this device's out ports>);
// The KeithMcMillen QuNexus has 3 I/O ports, and the idInfo for port 0 is:
idInfo: (deviceName: "QuNexus", srcPortIndex: 0, destPortIndex: 0)
::
For OSC devices, this is a dictionary with information on the ipAdresses and ports used. (As NetAddresses may change, this often requires updating by hand. )
## elementsDesc [required]
|| A (usually hierarchical) dictionary describing the control elements of the device. These controls are called elements within the Modality toolkit.
## deviceInfo [optional]
|| A dictionary giving additional information on the device.
## collectives [optional]
|| Specific groups that are needed to send or receive data collectively from the device. These are commonly used in OSC devices.
## specs [optional]
|| A dictionary with specs in serialized notation, like code::(\key: [0, 144, \lin])::. These overwrite existing spec definitions locally for this description only: When an element has a symbol for a spec, this is looked up locally first, then in MKtl.globalSpecs, then in global Spec.specs.
::
subsection:: The description of a single element
A control element is a part of a controller (often for physical interaction, like a slider, knob, accelerometer etc. etc.) that does one or more of the following things:
list::
## creates and sends a one-dimensional stream of values when played,
## accepts a one-dimensional stream of values when sent from software.
::
For full details on single element description see also:
link::Reference/Naming_conventions_in_element_descriptions::
An element description is a dict (or event) containing these entries:
DEFINITIONLIST::
## midiMsgType
|| code::midiMsgType:: has to be present for elements belonging to a MIDI device.
## hidElementID | <hidUsage|hidUsagePage>
|| code::hidElementID:: or both code::hidUsage:: and code::hidUsagePage:: have to be present for elements belonging to an HID device.
## oscPath
|| code::oscPath:: has to be present for elements belonging to an OSC device, or it has to use code::ioType: \groupIn:: or code::ioType: \groupOut::
## spec
|| The element code::\spec:: has to be present and is a symbol that, if called code::.asSpec:: upon, returns the (global) code::ControlSpec:: suitable for this element.
## midiChan, midiNum
|| \midiChan is needed for all midi messages including code::\bend, \touch, \program::, \midiNum is needed only for code::\noteOn, \noteOff, \control and \polyTouch:: messages.
::
The 'elementsDesc' field is a dictionary that can contain other dictionaries or arrays, which will be used to build hierarchical groups of elements in the MKtl to be built from the description. At the leaves of this data structure must be a dictionary describing an element. Its most important keys are code:: \key, \shared, \elements::; \key defines a local lookup name for the element or group; \shared defines properties shared between elements in this group, and \elements is an array of elements which again contains dictionaries describing elements or groups.
A typical structure would be:
code::
(
// ...
elementsDesc: [ // the elementsDesc of the whole device
(
key: \top, // name of this group,
// all elements use cc and midichan 0
shared: (midiChan: 0, midiMsgType: \control),
// the elements descriptions:
elements: [
// a group of 2 sliders
(
key: \sl, // group name
// they share elementType and spec
shared: (elementType: \slider, spec: \midiCC ),
elements: [
( key: \1, midiNum: 21 ),
( key: \2, midiNum: 22 )
]
),
// a group of 2 buttons
(
key: \bt,
// they share elementType and spec
shared: (elementType: \button, spec: \midiBut),
elements: [
( key: \1, midiNum: 41 ),
( key: \2, midiNum: 42 )
]
)
]
)
]
)
::
The 'specs' field contains a dictionary of specifications of controller ranges which the MKtl will use. An example:
code::
(
\shaper: [0, 128, \lin],
\mover: [1, 4096, \exp]
)
::
subsection:: deviceInfo
The deviceInfo is typically of the following form. All entries are optional.
code::
(
...
deviceInfo: (
vendorURI: "http://vendor/product",
manualURI: "http://manual.pdf",
description: "Short sentence on what a great controller this is.",
features: [
"23 colorblinding pads",
"42 invisible sliders",
],
notes: "Make sure the device is in total-recall mode!",
type: [\pad, \slider],
// a scribble is a PDF for drawing a controller mapping on paper
// see e.g. ableton push for a device that has one
hasScribble: false
),
elementsDesc: (
...
)
)
::
section:: Identifier naming convention
Naming conventions for identifiers are:
list::
## code::kn:: for knobs,
## code::sl:: for sliders,
## code::bt:: for buttons,
## code::key:: for keys,
## code::pad:: for pads, etc. Elements with names or symbols on them should have that name, e.g. a play button should be called \play, a rewind button \rew, etc.
::
Naming conventions for type values are:
list::
## code::slider:: for sliders,
## code::knob:: for knobs,
## code::button:: for buttons,
## code::key:: for keys,
## code::pad:: for pads
## code::oscMessage:: for osc-messages (of collectives)
::
note::
The description file for the "Korg nanoKONTROL 2"
code::
korg-nanokontrol2.desc.scd
::
is a good example for element naming. All naming examples are taken from there.
::
Generally, element names should be as clear as possible, and reasonably short to allow for compact code (e.g. for live coding mappings of controllers). The main advantage of following the conventions is that similar elements across devices will have identical or at least similar names, and thus allow substituting one device for a similar one with minimal code changes.
Unnamed buttons should be called \bt, sliders \sl, knobs \kn, pads \pad, etc., and when they are physically in arrays, they should be given like this:
code::
(
key: \kn,
shared: (\midiMsgType: \cc, \type: \knob, \midiChan: 0, \spec: \midiCC),
elements: (16..23).collect { |i| (\midiNum: i) }
)
::
When elements in an array are not explicitly given name keys, they will get self-generated keys as follows:
code::
// index -> key
0 -> '1',
1 -> '2',
// etc
::
When in rows and columns, these can be nested:
code::
(
key: \bt,
shared: (\midiMsgType: \cc, \type: \button, \midiChan: 0, \spec: \midiCC),
elements: [(32..39),(48..55),(64..71)].collect { |xs|
(
elements: xs.collect { |i| (\midiNum: i) }
)
}
)
::
Elements with names or symbols on them should be given that name,
e.g. a button name "play" or with a > sign on it should be
called \play or \playBt. in the nanoKontrol 2 file, such button names include transport buttons \rew, \fwd, \stop, \play, \rec,
\cycle, track buttons \tleft, \tright, and marker buttons \mset, \mleft, \mright.
When in doubt, consult files of devices with similar elements, and follow the naming schemes there.
section:: Grouping conventions:
Multiple elements of the same type, such as a bank of sliders, should be put in a single group, which can also be nested, as shown above.
Groups of elements which belong to a single physical control element (or otherwise belong together semantically) should be put in a single group. E.g. a gamepad thumbstick typically has an x-axis, a y-axis, and sometimes a hat switch, which should be in one group:
code::
(key: \l, // the left joystick
elements: [
(key: \x, 'hidUsage': 48),
(key: \y, 'hidUsage': 49)
]
)
// A group of two thumbsticks would be:
(
key: \joy,
shared: ('hidUsagePage': 1, 'elementType': 'joyAxis', 'ioType': 'in',
spec: \cent1, mode: \center ),
elements: [
(key: \l,
elements: [
(key: \x, 'hidUsage': 48),
(key: \y, 'hidUsage': 49)
]
),
(key: \r,
elements: [
(key: \x, 'hidUsage': 50),
(key: \y, 'hidUsage': 53)
]
)
]
);
::
For MIDI noteOn and noteOff, one can create pairs with MKtlDesc.notePair,
which creates a dict with elements for \on and \off,
and proper shared info including some gui layout information.
code::
// the element description
~onoffgroup = MKtlDesc.notePair( \bt1, 12, (elementType: \button, spec: \midiBut));
// in a dict
~descdict = (idInfo: "test", \protocol: \midi, elementsDesc: ~onoffgroup);
// in an MKtl
MKtl(\x, ~descdict);
// creates two elements with separate actions:
MKtl(\x).gui;
MKtl(\x).elAt(\on).valueAction_(1);
MKtl(\x).elAt(\off).valueAction_(0);
// check at top layer whether \on or \off happened last:
MKtl(\x).elAt.isOn
::
When other elements should go into this group, one can also make them separately:
code::
// description of a pad with noteOn, noteOff and poly touch:
d = (
\pad1,
shared: (midiChan: 0, midiNum: 45),
elements: [
(key: \on, \midiMsgType: \noteOn, spec: \midiVel),
(key: \off, \midiMsgType: \noteOff, spec: \midiVel),
(key: \touch, \midiMsgType: \polyTouch, spec: \midiCC)
]
);
::
This creates a semantically clear group, and generates separate elements
with independent actions for each message type.
the noteOn action could be used to start a synth,
touch to update one of its parameters while alive,
and noteOff (using noteOff velocity) to end this synth.