Definition file for a HID Controller in Version 8
The Definition File for a HID controller is a XML file installed in Documents\VirtualDJ\Devices\ folder and has the following form.
<device ...><audio ... /><page>definition of HID elements</page></device>
<?xml version="1.0" encoding="UTF-8"?>
<device name="XDJAERO" author="Atomix Productions" version="800" description="Pioneer XDJ-AERO" type="HID" vid="0x08E4" pid="0x0172" reportsize="16" outreportsize="32" decks="4">
<audio description="PIONEER XDJ-AERO" vid="0x08E4" pid="0x0172" asio="PIONEER XDJ-AERO ASIO" input="0" output="2" mic="no" Mixer ="yes" />
<constant byte="0" value="0x01" />
<constant byte="2" value="0x80" />
<!-- Buttons -->
<button name="PLAY_PAUSE" bit="0x20" deck="1" />
<!-- Encoders -->
<encoder name="BROWSE" word="4" endian="little" min="0" max="65536" />
<!-- Sliders -->
<slider name="PITCH" word="5" endian="little" signed="true" min="-1000" max="+1000" deck="1" />
<constant byte="0" value="0x01" />
<led name="LED_PLAY" bit="0x20" deck="1" />
<bar name="VU_METER" byte="5" enablebit="0x28" max="256" deck="1" />
<digit word="6" name="DIGIT_BPM" endian="little" dotbit="0x3B" deck="1" />
* The <!-- --> are optional comments, not executable.
The <device> line holds all the identifiers that will secure the unique and proper detection of a controller, and has the following parameters.
- name - Provide a unique short name for the device, which will be used in the mapping file as well. The name will not be visible anywhere else. (E.g. name="XDJAERO")
- type - must be "HID"
- description - Provide a description. This will be visible in the Controllers tab of Config. (E.g. description="Pioneer XDJ-AERO"). In v8 it is preferred to give this name in the definition instead of the mapping file because a single device can have multiple mappers.
- version - VDJ version this definition was created for. E.g. version="800"
- decks - Number of decks that can be controlled with this controller. E.g. decks="2" for a 2-sides controller, or decks="1" for a single-deck controller, or decks="4" for a 2-sides controller which offers additional layers for each deck per side.
- singledeck - Set to "yes" if it is a single-deck controller (decks="1") with a switch button to toggle to a second deck. When 1 controller is connected it will switch between 1 and 2, but when 2 controllers are connected, they will switch between 1 and 3, and 2 and 4. Can be used for 2-deck controller that can control 4 decks as well.
- padColumns padRows padSides - (Optional) Define the matrix that the controller provides to control the Sampler. If the controller has sampler pads, provide the number of horizontal pads in one sampler area, the number of vertical pads in one sampler area and the number of the sides. If the controller has a sampler area on each side, the padSides should be 2, if there is only one sampler area on the controller it should be 1.
- platform="pc|mac" (Optional). Most of the time this shouldn't be needed, but if a controller has a different driver or firmware for mac or pc, use this to have the definition loaded only on the specified platform. In this case, use 2 definition files for the device, one with platform pc and one with platform mac.
VirtualDJ 8 provides an implemented tool to get all the information that your Audio, MIDI and HID devices offer. Open VirtualDJ 8, goto the Options tab of the Config and set the setting CreateMidiLog to Yes from the Advanced Options. Close VirtualDJ 8 and make sure your device is properly connected and its drivers are installed. Launch VirtualDJ 8 and then close right after. Open the generated Log Report.txt file you will find in /Documents/VirtualDJ folder to get all the reported data.
Download Hidtrace tool from here. In this tool, select your device from the drop down menu on the left, and click any button on your controller. you should be able to see the device properites on the right side of the window now, among with a matrix of the reported values of the current page.
The <audio> line is optional. If the controller has a built-in sound card, then define its properties using this line, in order a special button in the Audio tab of Config to be offered with a pre-defined audio configuration.
Alternatively, the image can be base64 encoded and embedded in the xml by using image="embedded://base64encodedstring"
vid/pid are required for any sound config
optionally, some devices may also require mid (usually not)
The <audio> definition can be used as a stand-alone definition file to offer a pre-defined audio configuration when the defined sound card is connected. The audio definition follows the above structure, with the difference that a name="" needs to be provided.
<audio name="TRAKTORAUDIO2" description="Traktor Audio 2" vid="0x17cc" pid="0x041d" identifier="#nita2_avs#" asio="Traktor Audio 2" Mixer ="no" output="2" >[/list][/list]
The <device> element has child elements <page>, with these properties:
- type can be "in", "out", "packets", "init", "wait" or "exit"
- pagesize (optional) if different, report page size in bytes
Pages "IN" are HID report pages sent by the device on the HID port.
If your device sends more than one report page, you must differentiate the pages using a <constant> element.
When VirtualDJ receives the HID report, it will use the first <page> element where all <constant> elements match the content of the report.
Pages "OUT" are HID report pages that the application can send to the device on the HID port.
If the report page needs to have some specific headers to identify the page, you can use <constant> elements, as described in the Pages IN section.
(for Hercules DJConsole RMX, Hercules DJControl MP3 where ReportID equals 1, please use <constant byte="-1" value="0x01"/>)
Pages defined with the type "init" will be sent to the HID port when the device is initialized.
The pages will be sent in the order they appear in the XML.
You can use <constant> elements to fill the page, as defined in Pages IN.
If a page has the type "wait", the device will not start until this page has been received, after all the "init" pages have been sent.
Pages defined with the type "exit" will be sent when the device is exited.
The <constant> element can have one of these properties:
Each button, slider, knob, LED, LCD, etc, will be defined by a child item of a <page> element.
- All elements (except <constant>) can implement these properties:
All elements also have properties that defines their position and length inside the page report.
The position can be defined by one of these properties:
- bit: gives the position in number of bits since the beginning of the page (1 bit = 0 or 1)
- byte: gives the position in number of bytes since the beginning of the page (1 byte = 8 bits)
- word: gives the position in number of words since the beginning of the page (1 word = 2 bytes = 16 bits)
- dword: gives the position in number of dwords since the beginning of the page (1 dword = 2 words = 4 bytes = 32 bits)
If the number of bits taken by the element in the report is different than the size implied by the method used to give the position, you can specify the size by one of these properties:
- nbbits: (optional) specifically gives the number of bits
- size: (optional) can be "bit", "byte", "word", "dword"
If the size is greater or equal to "word", you can specify this property:
- endian: (optional) can be "little" or "big" (default is "big")
A button is defined by a <button> element, with the following properties:
<button bit="42" name="PLAY" />
If the button does not change the report value on pushed/released, but on on/off, you can use a <toggle> element with the following properties:
- value: (optional) specify the value the element should match
- inverted: (optional) set to "true" if the bit is 0 when activated and "value" when deactivated
A slider is defined by a <slider> element, with the following properties:
<slider word="2" endian="little" max="1000" name="VOLUME" />
A jog wheel is defined by a <jog> element, with the following properties:
<jog byte="19" size="word" full="300" name="JOGWHEEL" deck="1" />
If the jogwheel is motorized, you will need to add motor="true" to <device ... motor="true" />
For the mapping, you could use motorwheel3 posdelta and motorwheel3 timedelta 1000
To get the data to these 2 from hid, you could use <jog> , one for the position and one for the time.
The controller should offer in the HID reports a number counting up when moving forward and counting down when moving backward, wrapping around at the boundaries defined in the <jog /> definition
The definition defines full= as one rotation.
The controller should also have a counter that counts based on time, always counting up at a fixed speed regardless of what the jog is doing. For most microcontrollers there will probably be such a timer based on the clock speed that could be used and scaled.
The '1000' in the mapping is the number of counts per millisecond for the time counter. (currently it assume full=16384 so you may need to use a different value depending on your counter.
An encoder is defined by a <encoder> element, with the following properties:
<encoder word="4" endian="little" min="0" max="65536" name="BROWSE" />
You can put <action> elements with the usual position, size and name properties.
The VDJ Script action for this name will be called every time the report page containing this <action> is received.
a LED is defined by a <led> element, with the following properties:
<led bit="0x42" name="LED_PLAY" default="PLAY" deck="1" />
a LED that offers different colors is defined by a <color> element, with the following properties
<color byte="0x00" nbbits="24" bitspercolor="7" name="LED_PAD1" default="PAD1" deck="1" />
<color byte="0x03" values="0x01=red,0x02=#112233" name="LED_MODE" default="MODE" deck="1" />
Digits on a LCD are defined by a <digit> element, with the following properties:
Text displays are defined by a <text> element, with the following properties:
Progress bars are defined by a <bar> element, with the following properties:
Alternatively, progress bars can be defined as a buffer of binary bits.
For this, use a <bar> element with the following properties:
- type: if set to "bitfill" the buffer will progressively fill with 1s. If set to "bitmove", the buffer will have only one 1 moving through the buffer.
- inverted: (optional) invert the direction of the buffer.