Added Christian Packmann's code for parsing raw MIDI streams.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7578 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003 Matthijs Hollemans
|
* Copyright (c) 2003-2004 Matthijs Hollemans
|
||||||
|
* Copyright (c) 2004 Christian Packmann
|
||||||
* Copyright (c) 2003 Jerome Leveque
|
* Copyright (c) 2003 Jerome Leveque
|
||||||
*
|
*
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
@@ -57,7 +58,7 @@ MidiPortProducer::MidiPortProducer(int fd_, const char *name = NULL)
|
|||||||
keepRunning = true;
|
keepRunning = true;
|
||||||
|
|
||||||
thread_id thread = spawn_thread(
|
thread_id thread = spawn_thread(
|
||||||
SpawnThread, "MidiDriversProducer", B_URGENT_PRIORITY, this);
|
SpawnThread, "MidiPortProducer", B_URGENT_PRIORITY, this);
|
||||||
|
|
||||||
resume_thread(thread);
|
resume_thread(thread);
|
||||||
}
|
}
|
||||||
@@ -80,117 +81,169 @@ int32 MidiPortProducer::SpawnThread(void* data)
|
|||||||
|
|
||||||
int32 MidiPortProducer::GetData()
|
int32 MidiPortProducer::GetData()
|
||||||
{
|
{
|
||||||
uchar data[3];
|
uint8 msgBuf[3];
|
||||||
|
uint8* sysexBuf;
|
||||||
|
|
||||||
|
uint8* msgPtr;
|
||||||
|
size_t msgSize;
|
||||||
|
size_t needed = 0;
|
||||||
|
uint8 runningStatus = 0;
|
||||||
|
|
||||||
|
bool haveSysEx = false;
|
||||||
|
size_t sysexAlloc;
|
||||||
|
size_t sysexSize;
|
||||||
|
|
||||||
|
uint8 next;
|
||||||
|
|
||||||
while (keepRunning)
|
while (keepRunning)
|
||||||
{
|
{
|
||||||
if (read(fd, data, 1) != 1)
|
if (read(fd, &next, 1) != 1)
|
||||||
{
|
{
|
||||||
perror("Error reading data from driver");
|
perror("Error reading data from driver");
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (data[0] & 0xF0)
|
if (haveSysEx) // System Exclusive
|
||||||
{
|
{
|
||||||
case B_NOTE_OFF:
|
if (next < 0x80) // data byte
|
||||||
read(fd, data + 1, 2);
|
|
||||||
SprayNoteOff(data[0] & 0x0F, data[1], data[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_NOTE_ON:
|
|
||||||
read(fd, data + 1, 2);
|
|
||||||
SprayNoteOn(data[0] & 0x0F, data[1], data[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_KEY_PRESSURE:
|
|
||||||
read(fd, data + 1, 2);
|
|
||||||
SprayKeyPressure(data[0] & 0x0F, data[1], data[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_CONTROL_CHANGE:
|
|
||||||
read(fd, data + 1, 2);
|
|
||||||
SprayControlChange(data[0] & 0x0F, data[1], data[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_PROGRAM_CHANGE:
|
|
||||||
read(fd, data + 1, 1);
|
|
||||||
SprayProgramChange(data[0] & 0x0F, data[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_CHANNEL_PRESSURE:
|
|
||||||
read(fd, data + 1, 1);
|
|
||||||
SprayChannelPressure(data[0] & 0x0F, data[1]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_PITCH_BEND:
|
|
||||||
read(fd, data + 1, 2);
|
|
||||||
SprayPitchBend(data[0] & 0x0F, data[1], data[2]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (data[0])
|
|
||||||
{
|
|
||||||
case B_SYS_EX_START:
|
|
||||||
{
|
{
|
||||||
size_t msg_size = 4096;
|
sysexBuf[sysexSize++] = next;
|
||||||
uchar* msg = (uchar*) malloc(msg_size);
|
if (sysexSize == sysexAlloc)
|
||||||
size_t count = 0;
|
|
||||||
|
|
||||||
while (read(fd, msg + count, 1) == 1)
|
|
||||||
{
|
{
|
||||||
// Realtime events may interleave System Exclusives. Any
|
sysexAlloc *= 2;
|
||||||
// non-realtime status byte (not just 0xF7) ends a sysex.
|
sysexBuf = (uint8*) realloc(sysexBuf, sysexAlloc);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (next < 0xF8) // end of sysex
|
||||||
|
{
|
||||||
|
SpraySystemExclusive(sysexBuf, sysexSize);
|
||||||
|
haveSysEx = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((next & 0xF8) == 0xF8) // System Realtime
|
||||||
|
{
|
||||||
|
SpraySystemRealTime(next);
|
||||||
|
}
|
||||||
|
else if ((next & 0xF0) == 0xF0) // System Common
|
||||||
|
{
|
||||||
|
runningStatus = 0;
|
||||||
|
msgBuf[0] = next;
|
||||||
|
msgPtr = msgBuf + 1;
|
||||||
|
switch (next)
|
||||||
|
{
|
||||||
|
case B_SYS_EX_START:
|
||||||
|
sysexAlloc = 4096;
|
||||||
|
sysexBuf = (uint8*) malloc(sysexAlloc);
|
||||||
|
sysexBuf[0] = next;
|
||||||
|
sysexSize = 1;
|
||||||
|
haveSysEx = true;
|
||||||
|
break;
|
||||||
|
|
||||||
if (msg[count] >= 0xF8)
|
case B_SONG_POSITION:
|
||||||
{
|
needed = 2;
|
||||||
SpraySystemRealTime(msg[count]);
|
msgSize = 3;
|
||||||
}
|
break;
|
||||||
else if (msg[count] >= 0xF0)
|
|
||||||
{
|
case B_MIDI_TIME_CODE:
|
||||||
SpraySystemExclusive(msg, count - 1);
|
case B_SONG_SELECT:
|
||||||
|
case B_CABLE_MESSAGE:
|
||||||
|
needed = 1;
|
||||||
|
msgSize = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_TUNE_REQUEST:
|
||||||
|
case B_SYS_EX_END:
|
||||||
|
SpraySystemCommon(next, 0, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((next & 0x80) == 0x80) // Voice message
|
||||||
|
{
|
||||||
|
runningStatus = next;
|
||||||
|
msgBuf[0] = next;
|
||||||
|
msgPtr = msgBuf + 1;
|
||||||
|
switch (next & 0xF0)
|
||||||
|
{
|
||||||
|
case B_NOTE_OFF:
|
||||||
|
case B_NOTE_ON:
|
||||||
|
case B_KEY_PRESSURE:
|
||||||
|
case B_CONTROL_CHANGE:
|
||||||
|
case B_PITCH_BEND:
|
||||||
|
needed = 2;
|
||||||
|
msgSize = 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PROGRAM_CHANGE:
|
||||||
|
case B_CHANNEL_PRESSURE:
|
||||||
|
needed = 1;
|
||||||
|
msgSize = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (needed > 0) // Data bytes to complete message
|
||||||
|
{
|
||||||
|
*msgPtr++ = next;
|
||||||
|
if (--needed == 0)
|
||||||
|
{
|
||||||
|
switch (msgBuf[0] & 0xF0)
|
||||||
|
{
|
||||||
|
case B_NOTE_OFF:
|
||||||
|
SprayNoteOff(msgBuf[0] & 0x0F, msgBuf[1], msgBuf[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_NOTE_ON:
|
||||||
|
SprayNoteOn(msgBuf[0] & 0x0F, msgBuf[1], msgBuf[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_KEY_PRESSURE:
|
||||||
|
SprayKeyPressure(msgBuf[0] & 0x0F, msgBuf[1], msgBuf[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_CONTROL_CHANGE:
|
||||||
|
SprayControlChange(msgBuf[0] & 0x0F, msgBuf[1], msgBuf[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PROGRAM_CHANGE:
|
||||||
|
SprayProgramChange(msgBuf[0] & 0x0F, msgBuf[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_CHANNEL_PRESSURE:
|
||||||
|
SprayChannelPressure(msgBuf[0] & 0x0F, msgBuf[1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_PITCH_BEND:
|
||||||
|
SprayPitchBend(msgBuf[0] & 0x0F, msgBuf[1], msgBuf[2]);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
else // a normal data byte
|
|
||||||
{
|
|
||||||
++count;
|
|
||||||
if (count == msg_size)
|
|
||||||
{
|
|
||||||
msg_size *= 2;
|
|
||||||
msg = (uchar*) realloc(msg, msg_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
free(msg);
|
switch (msgBuf[0])
|
||||||
break;
|
{
|
||||||
|
case B_SONG_POSITION:
|
||||||
|
SpraySystemCommon(msgBuf[0], msgBuf[1], msgBuf[2]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case B_MIDI_TIME_CODE:
|
||||||
|
case B_SONG_SELECT:
|
||||||
|
case B_CABLE_MESSAGE:
|
||||||
|
SpraySystemCommon(msgBuf[0], msgBuf[1], 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_TUNE_REQUEST:
|
|
||||||
case B_SYS_EX_END:
|
|
||||||
SpraySystemCommon(data[0], 0, 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_MIDI_TIME_CODE:
|
|
||||||
case B_SONG_SELECT:
|
|
||||||
case B_CABLE_MESSAGE:
|
|
||||||
read(fd, data + 1, 1);
|
|
||||||
SpraySystemCommon(data[0], data[1], 0);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_SONG_POSITION:
|
|
||||||
read(fd, data + 1, 2);
|
|
||||||
SpraySystemCommon(data[0], data[1], data[2]);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case B_TIMING_CLOCK:
|
|
||||||
case B_START:
|
|
||||||
case B_CONTINUE:
|
|
||||||
case B_STOP:
|
|
||||||
case B_ACTIVE_SENSING:
|
|
||||||
case B_SYSTEM_RESET:
|
|
||||||
SpraySystemRealTime(data[0]);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
else if (runningStatus != 0) // Repeated voice command
|
||||||
|
{
|
||||||
|
msgBuf[0] = runningStatus;
|
||||||
|
msgBuf[1] = next;
|
||||||
|
msgPtr = msgBuf + 2;
|
||||||
|
needed = msgSize - 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (haveSysEx)
|
||||||
|
{
|
||||||
|
free(sysexBuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|||||||
Reference in New Issue
Block a user