Page 184 - Hacking Roomba
P. 184
Chapter 8 — Making Roomba Sing 165
The second parameter of destinationCreate() determines what object to notify when MIDI
data arrives for that MIDIClient, and it is set to the RoombaMidi object itself. This means that
RoombaMidi must implement MIDIReadProc, and it must have an appropriate execute()
method. Listing 8-6 also shows the very simple execute() method that goes through the
incoming MIDIPacketList and processes each MIDIPacket with processMIDIEvent().
The processMIDIEvent() method parses the incoming MIDI data, looking for a note-on
(0x90) or note-off (0x80) MIDI message. If it finds one of them, it extracts the entire message
from the MIDIData buffer and invokes doNote() with it. Finally, doNote() finds the corre-
sponding RoombaCommPanel based off of MIDI channel, and calls playMidiNote() to
cause Roomba to sing or dance.
Listing 8-6: RoombaMidi.java MIDI Handling Methods
public void setupMidi() {
try {
midiclient = new MIDIClient(new CAFString(“RoombaMidi”),
null);
midiclient.destinationCreate(new CAFString(“RoombaMidi
In”), this);
} catch(Exception e) {
e.printStackTrace();
}
}
public void execute(MIDIInputPort port, MIDIEndpoint
srcEndPoint,
MIDIPacketList list) {
for(int i = 0; i < list.numPackets(); i++) {
MIDIPacket packet = list.getPacket(i);
processMIDIEvent(port, srcEndPoint, packet.getData());
}
}
void processMIDIEvent(MIDIInputPort port, MIDIEndpoint
endpoint,
MIDIData data) {
try {
int startOffset = data.getMIDIDataOffset();
int numMIDIdata = startOffset + data.getMIDIDataLength();
int i = startOffset;
do {
if(i >= numMIDIdata)
break;
int commandByte = data.getUByteAt(i);
int command = commandByte & 0xf0;
int channel = commandByte & ~0xf0;
if(command == 0x90 || command == 0x80) { // NOTE_ON or
NOTE_OFF
doNote(command, channel, data.getByteAt(i+1),
data.getByteAt(i+2));
Continued