Driver

This is an implementation of ISingleDriver and the base class for single drivers which use Patch .

Declaration:

for default set/getPatchName methods
for default calculateCheckSum(Patch) method
for default trimSysex method
for default supportsPatch method
for sendPatchWorker method

IDriver interface methods

IPatchDriver interface methods

MIDI in/out methods to encapsulate lower MIDI layer

Methods for Patch class

Methods for ISinglePatch

Driver class utility methods

For debugging

Compatibility notes

declaration:

abstract public class Driver implements IPatchDriver
private Device device
Which device does this driver go with?
private final String patchType
The patch type. eg. "Single", "Bank", "Drumkit", etc.
private final String authors
The names of the authors of this driver.
protected String[] patchNumbers
Array holding names/numbers for all patches. Used for comboBox selection.

The following fields are used by default methods defined in
this file. If your extending driver can use a default method
as is, set the corresponding fields. Otherwise override the method.


for default set/getPatchName methods
see #setPatchName and #getPatchName
protected int patchNameStart
The offset in the patch where the patchname starts. '0' if patch is not named -- remember all offsets are zero based.
protected int patchNameSize
Number of characters in the patch name. (0 if no name)

for default calculateCheckSum(Patch) method
see calculateChecksum(Patch)
protected int checksumOffset
Offset of checksum byte.
Need to be set if default calculateChecksum(Patch)
method is used.
protected int checksumStart
Start of range that Checksum covers.
Need to be set if default calculateChecksum(Patch) method is used.
protected int checksumEnd
End of range that Checksum covers.
Need to be set if default calculateChecksum(Patch) method is used.

for default trimSysex method
see #trimSysex
protected int trimSize = 0;
The size of the patch for trimming purposes.

for default supportsPatch method
protected int patchSize
The size of the patch this Driver supports (or 0 for variable).
see #supportsPatch
protected String sysexID;
The hex header that sysex files of the format this driver
supports will have. The program will attempt to match loaded sysex drivers with the sysexID of a loaded driver. It can be up to 16 bytes and have wildcards (<code>*</code>).
ex. "F041\*\*003F12" see #supportsPatch (remove the \ characters, they are here because wikispace interpretes a double asterix as a "bold" tag.)

for sendPatchWorker method
protected int deviceIDoffset;
Offset of deviceID in sysex.
Used by sendPatchWorker method. (array index of device ID)
(see #sendPatchWorker)
protected SysexHandler sysexRequestDump = null;
SysexHandler object to request dump.
You don't have to use this field if you override requestPatchDump method.
see #requestPatchDump, SysexHandler
protected int numSysexMsgs
Number of sysex messages in patch dump.
Not used now.
public Driver(String patchType, String authors)
Creates a new Driver instance.
@param patchType The patch type. eg. "Single", "Bank","Drumkit", etc.
@param authors The names of the authors of this driver.

IDriver interface methods

public final String getPatchType() {
return patchType; }
public final String getAuthors() {
return authors; }
public final void setDevice(Device d) {
device = d; }
public final Device getDevice() {
return device; }
public boolean supportsPatch(String patchString, byte[] sysex)
Compares the header & size of a Patch to this driver to see if this driver is the correct one to support the patch.
@param patchString the result of p.getPatchHeader().
@param sysex a byte array of sysex message
@return true if this driver supports the Patch.
see #patchSize and #sysexID
public boolean isSingleDriver() {return true;}
public boolean isBankDriver() {return false;}
public boolean isConverter() {return false;}
These are not 'final' because BankDriver and Converter class override them.
Synth drivers should not override these.

IPatchDriver interface methods

public int getPatchSize() {
return patchSize; }
public String[] getPatchNumbers() {
return patchNumbers; }
public String[] getPatchNumbersForStore() {
All patches assumed to be writable by default
return patchNumbers; }

public String[] getBankNumbers() {
return bankNumbers; }
public boolean canCreatePatch()
Check if this driver supports creating a new patch. By default it uses reflection to test if the method createNewPatch() is overridden by the subclass of Driver.
public final IPatch createPatch() {
return createNewPatch(); }
protected Patch createNewPatch() {
overridden by subclass
return null; }
Create a new Patch. Don't override this unless your driver properly implement this method.
see IPatchDriver#createPatch() and #createPatch()
public IPatch createPatch(byte[] sysex) {
return new Patch(sysex, this); }
public IPatch[] createPatches(SysexMessage[] msgs) {
byte[] sysex = MidiUtil.sysexMessagesToByteArray(msgs);
IPatch[] patarray = DriverUtil.createPatches(sysex, getDevice());
Maybe you don't get the expected patch!
Check all devices/drivers again! Call fixpatch() if supportsPatch returns false.
(Why don't we simply cause error? Hiroo)

for (int k = 0; k < patarray.length; k++) {
IPatch pk = patarray[k];
String patchString = pk.getPatchHeader();
if (!(pk.getDriver().supportsPatch(patchString, pk.getByteArray()))) {
patarray[k] = fixPatch((Patch) pk, patchString);}}
return patarray;}
private IPatch fixPatch(Patch pk, String patchString) {
Look for a proper driver and trim the patch.
see #createPatches(SysexMessage[]) and IPatchDriver#createPatches(SysexMessage[])
protected int trimSysex(Patch patch)
This method trims a patch, containing more than one real patch to a correct size. Useful for files containg more than one bank for example. Some drivers are incompatible with this method so it reqires explicit activation with the trimSize variable.
@param patch the patch, which should be trimmed to the right size
@return the size of the (modified) patch
see #fixPatch(Patch, String)
see IPatchDriver#createPatches(SysexMessage[])
no driver overrides this now.
return patch.sysex.length; == trimSize
}
public void requestPatchDump(int bankNum, int patchNum)
Request the synth to send a patch dump. If sysexRequestDump is not null, a request dump message is sent. Otherwise a
dialog window will prompt users: "The " + toString()
+ " driver does not support patch getting.\n\n"
+ "Please start the patch dump manually..."
see IPatchDriver#requestPatchDump(int, int) and SysexHandler

MIDI in/out methods to encapsulate lower MIDI layer

public final void send(MidiMessage msg) {
device.send(msg);}
public String toString() {
return getManufacturerName() + " " + getModelName() + " " + getPatchType(); }

methods for Patch class

protected String getPatchName(Patch p)
Gets the name of the patch from the sysex. If the patch uses some weird format or encoding, this needs to be overidden in the particular driver.
see Patch#getName()
protected void setPatchName(Patch p, String name)
Set the name of the patch in the sysex. If the patch uses some weird format or encoding, this needs to be overidden in the particular driver.
if patchNameSize is 0, an error "The Driver for this patch does not support Patch Name Editing." is shown.
see Patch#setName(String)
protected void storePatch(Patch p, int bankNum, int patchNum) {
setBankNum(bankNum);
setPatchNum(patchNum);
sendPatch(p);
}
Sends a patch to a set location on a synth. Override this if required.
see Patch#send(int, int)
protected void setPatchNum(int patchNum)
Send Program Change MIDI message.
see #storePatch(Patch, int, int)
protected void setBankNum(int bankNum)
Send Control Change (Bank Select) MIDI message.
see #storePatch(Patch, int, int)
boolean hasEditor()
see Patch#hasEditor()
protected JSLFrame editPatch(Patch p)
Override this if your driver implement Patch Editor. Don't override this otherwise.
see Patch#edit()

methods for ISinglePatch

protected void sendPatch(Patch p) {
sendPatchWorker(p);
}
Sends a patch to the synth's edit buffer.
Override this in the subclass if parameters or warnings need to be sent to the user (aka if the particular synth does not have a edit buffer or it is not MIDI accessable).
see Patch#send()
see ISinglePatch#send()
protected final void sendPatchWorker(Patch p)
Set Device ID :
p.sysex[deviceIDoffset] = (byte) (getDeviceID() - 1);
and send the sysex data to MIDI output :
send(p.sysex);
see #sendPatch(Patch)
protected void playPatch(Patch p)
Play note.
plays a MIDI file or a single note depending which preference is set.
Currently the MIDI sequencer support (playSequence() ) isn't implemented!
see Patch#play() and ISinglePatch#play()
private void playNote() {
Sends the patch sendPatch(p), sleeps 100 msec, then plays the note send(msg), then sleeps again, as set in AppConfig.getDelay(), expecting running status, and sends the note on message again send(msg). (note: maybe I misunderstood this part of the code.)
private void playSequence() {
MidiUtil.startSequencer(getDevice().getPort());
}

Driver class utility methods


protected final String getManufacturerName()
Return the name of manufacturer of synth.
protected final String getModelName()
Return the name of model of synth.
{return device.getModelName();}
protected final String getSynthName()
Return the personal name of the synth.
{return device.getSynthName();}
public final int getDeviceID()
Return MIDI devide ID.
{return device.getDeviceID();}
public final int getChannel()
Return MIDI channel number.
{return device.getChannel();}
public int getPatchNameSize()
Getter of patchNameSize.
{return patchNameSize;}
protected void calculateChecksum(Patch p)
Calculate check sum of a Patch. Need to be overridden if a patch is consist from multiple SysEX messages.
@param p a Patch value
protected void calculateChecksum(Patch patch, int start, int end, int offset) {
DriverUtil.calculateChecksum(patch.sysex, start, end, offset);
}
Calculate check sum of a Patch.
This method is called by calculateChecksum(Patch). The checksum
calculation method of this method is used by Roland, YAMAHA, etc.
Override this for different checksum calculation method.
Compatibility Note: This method became 'static' method.
@param patch: a Patch value
@param start: start offset
@param end: end offset
@param offset: offset of the checksum data
see #calculateChecksum(Patch)
public final void send(byte[] sysex)
Send Sysex byte array data to MIDI outport.
@param sysex: a byte array of Sysex data. If it has checksum, the checksum
must be calculated before calling this method.
public final void send(int status, int d1, int d2)
Send ShortMessage to MIDI outport.
msg.setMessage(status, d1, d2);
send(msg);
public final void send(int status, int d1)
Send ShortMessage to MIDI outport.
send(status, d1, 0);

For debugging.

protected String getFullPatchName(Patch p)
Returns String .. full name for referring to this patch for debugging purposes: { return getManufacturerName() + " | " + getModelName() + " | "
+ p.getType() + " | " + getSynthName() + " | " + getPatchName(p); }

Compatibility Notes

Compatibility Note 1: The following fields are now private. Use setter/getter method to access them.
device, patchType, authors
Compatibility Note 2: The following fields are now obsoleted. Use a getter method to access them. The getter method queries parent Device object.
deviceNum, driverNum, channel, port, inPort, manufacturer, model, inquiryID, id

Compatibility Note 3:**
SysexHandler.send(getPort(), sysex);
or
PatchEdit.MidiOut.writeLongMessage(getPort(), sysex);
was replaced by
send(sysex);