Here's a first attempt at some documentation for the decoder plugins.
The sample code is in Groovy. Since this is a first draft I expect it
needs improvement. Please let me know if you have ANY questions or
comments.
------
INITIALIZATION
Decoders are used for reading (and writing) individual parameters from
a sysex message. There is a separate Decoder instance for each type of
sysex message. Before a decoder can be used, it needs to be
initialized by creating Parameter objects describing the sysex
message. Two methods are used for this: newParameter and
finishParameter. Parameters must be created in the order they occur
in the sysex message, and each parameter must be finished before
creating the next. The Parameter must store any information that the
decoder needs for de/en-coding. For compatibility with the XML driver,
all this information must be accessible via setters starting with
"set" or "add" and taking a String argument.
For example, this XML:
<range>
<name>Address Mid</name>
<min>0</min>
<max>0x7f</max>
<comment>Some info</comment>
</range>
Could result in these method calls:
param = decoder.newParameter("range")
param.setName("Address Mid")
param.setMin("0")
param.setMax("0x7f")
param.addComment("Some info")
When finishParameter is called, the Decoder is not responsible for
storing the parameter, but it needs to save any information necessary
for creating the next paramter. At a minimum it must keep track of the
total size (in bytes) of the sysex message, but it could also store
other state information that needs to be passed to the Parameter
constructor.
USING DECODERS
The methods decode and decodeString take a Parameter and a byte array
of sysex data (not including the beginning sysex byte) and return,
respectively, an int or a string. Conversely, encode and encodeString
store the specified value into a byte array of sysex data.
Also, there is method encode(int, XMLParameter) which returns a hex
string of the encoded value. This is mainly used for sending single
parameter changes to the synth, as in:
device.send(midiMessage(
"F0 ${paramChangeHeader()} ${decoder.encode(val, param)} F7"))
(Note: This is merely an example of how encode is used, not the exact
syntax used by an XML driver implementation)
IMPLEMENTATION
Currently plugins must be written in Groovy, although it would not be
difficult to add support for Java ones. The decoder must have a
default constructor and a non-static main method which registers the
plugin. For example:
// Simple decoder with a useful default constructor
PluginRegistry.registerDecoder("MyDecoder", getClass())
// Decoder which doesn't use default constructor
c = getClass().getConstructor(new Class[] { Integer.class } )
PluginRegistry.registerDecoder("MultiDec 1", c, new Object[] { 1 })
PluginRegistry.registerDecoder("MultiDec 2", c, new Object[] { 2 })
|