Generic MIDI devices
Deejaysystem can use any controller compatible with the MIDI standard. New devices can be supported by writing definition files in XML format.
MIDI controllers supported by Deejaysystem are defined each with a file named midi_<device name here>.xml in the Plugins folder. Default input mappings (controller inputs to Deejaysystem functions) are defined in the file Plugins\MidiDefaults.xml.
Contact us if you've written a XML file for your controller and want it to be included in the next release of Deejaysystem.
MIDI device definition file: midi_*.xml
The file must be a xml file with a name starting by midi_, so it matches the file pattern midi_*.xml. The file must be located in the Plugins folder.
Structure of a MIDI device definition file:
<MidiDevice> <Info>
...
</Info>
<Inputs>
<Input ... />
<Input ... />
...
</Inputs>
<Outputs>
<Output ... />
<Output ... />
...
</Outputs>
<OutputMaps>
<OutputMap ... />
<OutputMap ... />
...
</OutputMaps> </MidiDevice>
Outputs and OutputMaps are optional.
1. The Info section
Provides data to identify the device:
<MidiDevice>
<Info> <Name>Numark Omni Control</Name> <PrefixId>NMC</PrefixId> <MidiInName>Numark OMNI CONTROL MIDI</MidiInName> <MidiOutName>Numark OMNI CONTROL MIDI</MidiOutName> </Info>
A device may have several MIDI names:
<MidiDevice>
<Info> <Name>Hercules DJ Console Mk2 / DJ Control MP3</Name> <PrefixId>HDC</PrefixId> <MidiInNames> <MidiName>Hercules DJ Console Mk2 MIDI</MidiName> <MidiName>Hercules DJ Control MP3 MIDI</MidiName> </MidiInNames> <MidiOutName>Hercules DJ Console Mk2 MIDI</MidiOutName> </Info>
Identification of the device by vendor, product and device type. Also uses an external DLL module for translating some MIDI messages:
<MidiDevice>
<Info> <Name>Denon DN-HC4500</Name>
<PrefixId>DNHC</PrefixId> <MidiInVendor>0xFFFF</MidiInVendor> <MidiInProduct>0xFFFF</MidiInProduct> <MidiOutVendor>0xFFFF</MidiOutVendor> <MidiOutProduct>0xFFFF</MidiOutProduct> <MidiOutDeviceType>1</MidiOutDeviceType> <ExternalModule>MidiDevices.dll</ExternalModule> </Info>
Following values are admitted in the Info section:
Value |
Description |
NAME* |
Display name |
PREFIXID* |
UNIQUE prefix. This prefix + underscore (_) prefixes all the names of input, output and external function for this device. Only letters and numbers allowed. It must begin and end by a letter. |
DESCRIPTION |
Description, comments... |
SINGLEDECK |
0 or 1, default 0. Indicates whether the device sends information to the active deck only. |
EXTERNALMODULE |
Name (without path) of a DLL file with functions that are invoked to translate MIDI messages in TRANSLATED mode outputs. See the Outputs section for more info. |
|
MIDIINNAME |
Name to identify the device in the MIDI-IN device list |
MIDIINVENDOR
MIDIINPRODUCT |
Vendor and product codes for the MIDI-IN device. If no MIDIINNAME is specified or it doesn't match with any of the plugged devices, then a search by Vendor and Product is performed. |
|
MIDIOUTNAME |
Name to identify the device in the MIDI-OUT device list |
MIDIOUTVENDOR
MIDIOUTPRODUCT
MODOUTDEVICETYPE |
Vendor and product codes for the MIDI-OUT device. If no MIDIOUTNAME is specified or it doesn't match with any of the plugged devices, then a search by Vendor, Product and Type is performed. |
* Mandatory
2. The Inputs section
Enumerates the available input controls available in the device and the MIDI data to interpret them. Each control (INPUT) is defined in a subsection Input. Values depend on the type of control:
<Inputs>
<Input Name="A_MONITOR"
Type="BUTTON"
Command="0x0B"
Id="0x15"
Press="0x7F"
Release="0"
/> <Input Name="A_VOLUME"
Type="ANALOG"
Command="0x0B"
Id="0x32"
Min="0"
Max="127"
Default="127"
NoCenter="1"
/> <Input Name="A_JOG"
Type="ENCODER"
Command="0x0B"
Id="0x36"
Mode="1"
Left="127"
Right="1"
Pulses="45"
/>
<Input Name="A_PITCH"
Type="ANALOGHR"
Channel="0"
Command="0x0E"
Min="0"
Max="16383"
Center="8192"
Invert="1"
/>
...
Common values to all controls:
Value |
Description |
NAME* |
Identifier of the control. Must be unique among the controls of this device. |
TYPE* |
Control type: BUTTON, ANALOG, ANALOGHR or ENCODER |
CHANNEL |
MIDI channel. If not specified will use any channel. |
COMMAND* |
MIDI command triggered by this control. |
ID |
MIDI identifier for this control (Data1). Except ANALOGHR type controls. |
DEFAULT |
Default initial value of this control. Used when the logical value at its initial position is different from 0. |
* Mandatory
BUTTON type controls
Two-state controls (button, switch...). Generate logical values 0 (off) and 1 (on).
Value |
Description |
COMMANDRELEASE |
Optional, if different from COMMAND. |
PRESS |
MIDI value delivered when pressing or activating the control (Data2) |
RELEASE |
MIDI value delivered when releasing or deactivating the control (Data2) |
ANALOG y ANALOGHR type controls
They emit a limited range of values (wheel, slider, fader ...). Generate analog logical values from -1.0 (one end of the run), 0.0 (middle), and +1.0 (other end of the run). If NOCENTER is specified they generate values between 0.0 and 1.0.
Value |
Description |
MIN, MAX |
Minimum and maximum MIDI values issued by the control (Data2). |
CENTER |
MIDI value that represents the center of control. Optional, if not indicated is calculated as the integer part of (MAX-MIN) / 2. The control generates the logical value 0 in the center. |
NOCENTER |
Indicates that the control has no defined logic center. Only generates positive logical values. If included, it ignores CENTER. Example: volume sliders. |
INVERT |
Generate opposing values between the extremes of the run. |
ANALOGHR controls emit a 14-bit value by combining Data1 (7 bit lower) and Data2 (7 bit higher). Various ANALOGHR controls on the same device differ by the CHANNEL value instead of ID.
ENCODER type controls
Analog wheels that indicate motion in one direction or another (jog-wheel, shuttle-dial...). Generate logical values between -1.0 (left) and +1.0 (right) depending on the speed and direction of the motion. If not moving they generate 0.
Value |
Description |
MODE |
Operation mode: 0, 1, 2. Defines the form in which the controller sends the values of movement |
LEFT, RIGHT |
MIDI values that indicate one motion unit in each direction (Data2) |
PULSES |
Number of motion units that represent a complete control turn (360º) |
Operation modes (MODE):
- 0 - Single left-right values. Data2 contains only
LEFT or RIGHT.
- 1 - Base 0. Data2 is a 7 bits signed value indicating the units and the direction of motion. 0 means rest.
- 2 - Base 64. Data2 is a 7 bits unsigned value indicating the units and the direction of motion. 64 means rest.
3. The Outputs section
Enumerates the MIDI outputs offered by the device for display, lights, etc.. and the MIDI data to trigger them. Each output (OUTPUT) is defined with a subsection Output.
<Outputs>
<Output Name="A_CUE" Type="BOOL" Channel="0" Command="0x0B" Data1="0x4A" Data1Off="0x4B" Data2="0x26" /> <Output Name="A_TIME" Type="INT" Mode="TRANSLATED" ExternalId="0x01" /> <Output Name="A_DATAREQUEST" Type="CONTROL" Channel="0" Command="0x0B" Data1="0x4A" Data2="0x3C" />
Value |
Description |
NAME* |
Identifier of the output. Must be unique among the outputs of this device. |
TYPE* |
Data type that receives the output: BOOL, CONTROL, INT, TEXT |
MODE |
Operation mode: MIDI (default) or TRANSLATED. INT and TEXT only support TRANSLATED. |
* Mandatory
Output type (TYPE) |
Description |
Supported modes (MODE) |
BOOL |
Receives On and Off events. Example: lights. |
MIDI, TRANSLATED |
CONTROL |
Device commands. Example: DataRequest requests the current positions of the analog controls. |
MIDI, TRANSLATED |
INT |
Integer numeric value |
TRANSLATED |
TEXT |
Text line |
TRANSLATED |
MIDI operation mode
All the data needed to operate the MIDI output is specified:
<Outputs> <Output Name="A_CUE" Type="BOOL" Channel="0" Command="0x0B" Data1="0x4A" Data1Off="0x4B" Data2="0x26" /> <Output Name="A_PLAY" Type="BOOL" Channel="0" Command="0x0B" Data1="0x4A" Data1Off="0x4B" Data2="0x27" /> <Output Name="A_DATAREQUEST" Type="CONTROL" Channel="0" Command="0x0B" Data1="0x4A" Data2="0x3C" />
Output type (TYPE) |
Requested values |
BOOL |
CHANNEL, COMMAND, DATA1, DATA2: MIDI message that activates or enables the output. Mandatory.
COMMANDOFF, DATA1OFF, DATA2OFF: need at least one of these. They combine with the above to form the MIDI message that shuts off or disables the output. |
CONTROL |
CHANNEL, COMMAND, DATA1, DATA2: MIDI message that invokes the command in the device. Mandatory. |
TRANSLATED operation mode
Used when multiple MIDI messages or a SysEx (System Exclusive) message are required to set the value of one or several outputs in the device.
Requires a external DLL library specified at the Info section (<ExternalModule>) with an exported function <PREFIX>_MidiProc. PREFIX is also defined in the Info section (<PrefixId>). The DLL must be located in the Plugins folder.
The output is identified with an EXTERNALID value. On each action on this output the EXTERNALID value is fed to the function <PREFIX>_MidiProc in the external module, which then translates the action into a sequence of MIDI messages or into a SysEx message. This returning data is then sent to the device.
<Outputs>
<Output Name="A_TIMEMODE" Type="BOOL" Mode="TRANSLATED" ExternalId="0x00" />
<Output Name="A_TIME" Type="INT" Mode="TRANSLATED" ExternalId="0x01" />
<Output Name="A_PITCH" Type="INT" Mode="TRANSLATED" ExternalId="0x02" />
<Output Name="A_TEXT1" Type="TEXT" Mode="TRANSLATED" ExternalId="0x05" Lines="1" Length="12" />
Output type (TYPE) |
Requested values |
BOOL |
EXTERNALID |
CONTROL |
EXTERNALID |
INT |
EXTERNALID
MIN, MAX: opcional, range of values supported by the output. Informative, has no real effect. |
TEXT |
EXTERNALID
LENGTH: number of characters that the output can display in a line of text at once.
LINES: numbre of text lines, default 1. Not actually used. |
The DLL contains one or more exported functions as follows:
DWORD __stdcall
HDC_MidiProc(DWORD dwCommand, DWORD dwOutputId, LONG lValue, void* pData, DWORD dwDataSize);
DWORD __stdcall
DNHC_MidiProc(DWORD dwCommand, DWORD dwOutputId, LONG lValue, void* pData, DWORD dwDataSize);
dwCommand: Action to be executed on the output:
dwCommand |
Requested action |
0 (VALUE) |
Apply the lValue value to the output. In BOOL outputs 0 is FALSE and any other value is TRUE. |
1 (UNDEFINED) |
Show undefined value or no value. Example: show "---" in the track number when no track is loaded.
|
2 (ALLON) |
The output should turn on everything it has, all its lights, segments, etc.. It is used at the startup to ensure that all outputs are working properly. |
3 (ALLOFF) |
The output should be shut down completely. |
4 (TEXT) |
lValue is a pointer to a null-terminated single-byte Ansi string (LPCSTR). Only applicable to TEXT outputs. |
100 (INITIALIZE) |
Sent on startup, once to each exported function, before any other command. |
101 (RELEASE) |
Sent on release, once to each exported function. After this no more commands are sent. |
dwOutputId: Id of the output specified on EXTERNALID.
lValue: Value to be sent to the output in the action VALUE (dwCommand = 0), or pointer to string in action TEXT (dwCommand = 4).
pData: Pointer to a buffer of dwDataSize bytes. You should cast this pointer to SMidiMessage* if returning a sequence of MIDI messages, or to BYTE* if you are returning a SysEx (System Exclusive) message.
Return value: The number of MIDI messages that has been filled into the buffer, or the number of bytes of the SysEx message plus a MIDI_SYSEX flag:
Returning a sequence of MIDI messages
struct SMidiMessage
{
union {
// Mensaje en bruto
DWORD dwMessage;
// Mensaje por componentes
struct {
BYTE nChannel : 4; // Status byte
BYTE nCommand : 4;
BYTE nData1 : 7;
BYTE nSpacer1 : 1; // Always 0
BYTE nData2 : 7;
BYTE nSpacer2 : 1; // Always 0
BYTE nUnused : 8;
};
};
};
Cast pData to SMidiMessage*, then fill the MIDI messages and return the number messages in the sequence:
SMidiMessage* pMidiMessages = (SMidiMessage*)pData;
pData[0].nChannel = 1;
pData[0].nCommand = 7;
pData[0].nData1 = 0; pData[0].nData2 = 1;
pData[1].nChannel = 2;
pData[1].nCommand = 7;
pData[1].nData1 = 0; pData[1].nData2 = 2;
return 2; // Two MIDI messages in this sequence
Returning a MIDI SysEx message
Cast pData to BYTE*, then fill in the bytes for the SysEx message including header (F7) and terminator (F0). Return the number of bytes with the most significant bit of the DWORD set:
BYTE* pSysEx = (BYTE*)pData;
pSysEx[0] = 0xF0; pSysEx[1] = 0x7E; pSysEx[2] = 0x70; pSysEx[3] = 0x4A; pSysEx[4] = 0x39; pSysEx[5] = 0xF7;
return 6 | 0x80000000; // 6 bytes in this SysEx message
4. The OutputMaps section
Binds the data and values of Deejaysystem to the outputs available on the device (as defined in Outputs). Each bind or map is defined by a subsection OutputMap.
<OutputMaps>
<OutputMap Source="DjsA_PlayLed" Output="A_PLAY" />
<OutputMap Source="DjsA_CueLed" Output="A_CUE" />
<OutputMap Source="DjsA_TimeValue" Output="A_TIME"
Requires="DjsA_IsTrackOpen" Blink="DjsA_IsTimeBlink" />
<OutputMap Source="DjsA_TrackValue" Output="A_TRACK"
Requires="DjsA_TrackValue" />
Value |
Description |
SOURCE* |
Source data in Deejaysystem |
OUTPUT* |
Output receiving the SOURCE data value |
IGNORE
IGNORENEG |
Avoid any action on the output if the specified data source has nonzero value.
IGNORENEG avoids any action if the data has zero value. |
REQUIRES
REQUIRESNEG |
Switch off the output (ALLOFF) if the specified data source has nonzero value.
REQUIRESNEG switchs off the output if the data has zero value. |
UNDEFINED
UNDEFINEDNEG |
Set the undefined value at the output (UNDEFINED) if the specified data source has nonzero value.
UNDEFINEDNEG sets the undefined value if the data has zero value. |
BLINK |
Indicates a data source that makes the output blink (VALUE / ALLOFF) |
Available source data. Those that begin by DjsA_ are also available as DjsB_.
Data (SOURCE) |
Value type |
Notes |
Djs_NULL |
INT |
Always 0 |
Djs_Enabled |
BOOL |
Always TRUE |
Djs_Blink |
BOOL |
|
Djs_Blink2 |
BOOL |
|
|
DjsA_PitchValue |
INT |
10000 = pitch +10.000 |
DjsA_PitchBendValue |
INT |
-1000 = bend -1.000 |
DjsA_VolumeValue |
INT |
10000 = 100% |
DjsA_VideoOutLed |
BOOL |
|
DjsA_RemainTimeLed |
BOOL |
|
DjsA_TrueTimeLed |
BOOL |
|
DjsA_ShowBpmLed |
BOOL |
|
DjsA_MonitorLed |
BOOL |
|
DjsA_AutoGainLed |
BOOL |
|
DjsA_PitchLed |
BOOL |
|
DjsA_PitchBendPlusLed |
BOOL |
|
DjsA_PitchBendMinusLed |
BOOL |
|
DjsA_TitleText |
TEXT |
|
DjsA_Status1Text |
TEXT |
|
DjsA_Status2Text |
TEXT |
|
|
DjsA_IsTrackLoading |
BOOL |
|
DjsA_IsTrackOpen |
BOOL |
|
DjsA_PlayingState |
INT |
0 = paused/cued, 1 = playing, 2 = cueing (CUE button hold) |
DjsA_TrackValue |
INT |
|
DjsA_TrackPercentValue |
INT |
0..100 |
DjsA_TimeValue |
INT |
ms |
DjsA_BpmValue |
INT |
1600 = 160 BPMs |
DjsA_IsTimeBlink |
BOOL |
|
DjsA_PlayLed |
BOOL |
|
DjsA_CueLed |
BOOL |
|
|
Mixer_MonitorMixLed |
BOOL |
|
Playlist_Enabled |
BOOL |
|
Playlist_MixNowLed |
BOOL |
|
Playlist_AutoPlayLed |
BOOL |
|
Playlist_ShuffleLed |
BOOL |
|
Playlist_ListLoopLed |
BOOL |
|
Video_FullScreenEnabled |
BOOL |
|
Mods_ControlEnabled |
BOOL |
|
Mods_ShiftEnabled |
BOOL |
|
Mods_AltEnabled |
BOOL |
|
Mods_Extra1Enabled |
BOOL |
|
Mods_Extra2Enabled |
BOOL |
|
Default maps file: MidiDefaults.xml
The default settings (maps) for all input devices (MIDI and non-MIDI) are read from the file Plugins\MidiDefaults.xml. These settings are loaded on the first startup and when restoring defaults with Settings > Control > Defaults.
Note: Modifications to this file are lost when reinstalling the software or upgrading it to a newer version. Please contact us if you've written a XML file for your controller and you want your default maps to be included in the next release of Deejaysystem.
|