Milestone 2 is complete. You can now send and receive MIDI events.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2874 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -4,8 +4,6 @@
|
|||||||
|
|
||||||
#include <MidiEndpoint.h>
|
#include <MidiEndpoint.h>
|
||||||
|
|
||||||
class BMidiDispatcher;
|
|
||||||
|
|
||||||
class BMidiConsumer : public BMidiEndpoint
|
class BMidiConsumer : public BMidiEndpoint
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -75,7 +73,7 @@ public:
|
|||||||
uchar channel, uchar lsb, uchar msb, bigtime_t time);
|
uchar channel, uchar lsb, uchar msb, bigtime_t time);
|
||||||
|
|
||||||
virtual void SystemExclusive(
|
virtual void SystemExclusive(
|
||||||
void* data, size_t dataLength, bigtime_t time);
|
void* data, size_t length, bigtime_t time);
|
||||||
|
|
||||||
virtual void SystemCommon(
|
virtual void SystemCommon(
|
||||||
uchar status, uchar data1, uchar data2, bigtime_t time);
|
uchar status, uchar data1, uchar data2, bigtime_t time);
|
||||||
@@ -92,8 +90,8 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class BMidiDispatcher;
|
|
||||||
friend class BMidiRoster;
|
friend class BMidiRoster;
|
||||||
|
friend int32 _midi_event_thread(void*);
|
||||||
|
|
||||||
virtual void _Reserved1();
|
virtual void _Reserved1();
|
||||||
virtual void _Reserved2();
|
virtual void _Reserved2();
|
||||||
@@ -103,12 +101,14 @@ private:
|
|||||||
virtual void _Reserved6();
|
virtual void _Reserved6();
|
||||||
virtual void _Reserved7();
|
virtual void _Reserved7();
|
||||||
virtual void _Reserved8();
|
virtual void _Reserved8();
|
||||||
|
|
||||||
BMidiDispatcher* fDispatcher;
|
int32 EventThread();
|
||||||
bigtime_t fTimeout;
|
|
||||||
void* fTimeoutData;
|
bigtime_t timeout;
|
||||||
|
void* timeoutData;
|
||||||
int32 fCurrentProducer;
|
int32 currentProducer;
|
||||||
|
thread_id thread;
|
||||||
|
|
||||||
uint32 _reserved[1];
|
uint32 _reserved[1];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public:
|
|||||||
uchar channel, uchar lsb, uchar msb, bigtime_t time = 0) const;
|
uchar channel, uchar lsb, uchar msb, bigtime_t time = 0) const;
|
||||||
|
|
||||||
void SpraySystemExclusive(
|
void SpraySystemExclusive(
|
||||||
void* data, size_t dataLength, bigtime_t time = 0) const;
|
void* data, size_t length, bigtime_t time = 0) const;
|
||||||
|
|
||||||
void SpraySystemCommon(
|
void SpraySystemCommon(
|
||||||
uchar status, uchar data1, uchar data2, bigtime_t time = 0) const;
|
uchar status, uchar data1, uchar data2, bigtime_t time = 0) const;
|
||||||
@@ -106,7 +106,9 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
//void SprayEvent(BMidiEvent* event, size_t length) const;
|
void SprayEvent(
|
||||||
|
const void* data, size_t length, bool atomic, bigtime_t time,
|
||||||
|
bool sysex = false) const;
|
||||||
|
|
||||||
virtual void _Reserved1();
|
virtual void _Reserved1();
|
||||||
virtual void _Reserved2();
|
virtual void _Reserved2();
|
||||||
|
|||||||
@@ -14,10 +14,9 @@ const char* BMidiEndpoint::Name() const
|
|||||||
{
|
{
|
||||||
const char* str = NULL;
|
const char* str = NULL;
|
||||||
|
|
||||||
// It seems reasonable to assume that the pointer
|
// It seems reasonable to assume that the pointer returned by
|
||||||
// returned by BString::String() can change when the
|
// BString::String() can change when the string is modified,
|
||||||
// string is modified, e.g. to allocate more space.
|
// e.g. to allocate more space. That's why we lock here too.
|
||||||
// That's why we need to lock here too.
|
|
||||||
|
|
||||||
if (LockLooper())
|
if (LockLooper())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
* Copyright (c) 2002-2003 Matthijs Hollemans
|
* Copyright (c) 2002-2003 Matthijs Hollemans
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "MidiConsumer.h"
|
#include "MidiConsumer.h"
|
||||||
#include "MidiRoster.h"
|
#include "MidiRoster.h"
|
||||||
@@ -9,6 +11,13 @@
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int32 _midi_event_thread(void* data)
|
||||||
|
{
|
||||||
|
return ((BMidiLocalConsumer*) data)->EventThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
BMidiLocalConsumer::BMidiLocalConsumer(const char* name)
|
BMidiLocalConsumer::BMidiLocalConsumer(const char* name)
|
||||||
: BMidiConsumer(name)
|
: BMidiConsumer(name)
|
||||||
{
|
{
|
||||||
@@ -16,6 +25,13 @@ BMidiLocalConsumer::BMidiLocalConsumer(const char* name)
|
|||||||
|
|
||||||
isLocal = true;
|
isLocal = true;
|
||||||
refCount = 1;
|
refCount = 1;
|
||||||
|
timeout = (bigtime_t) -1;
|
||||||
|
timeoutData = NULL;
|
||||||
|
|
||||||
|
port = create_port(1, "MidiEventPort");
|
||||||
|
thread = spawn_thread(
|
||||||
|
_midi_event_thread, "MidiEventThread", B_REAL_TIME_PRIORITY, this);
|
||||||
|
resume_thread(thread);
|
||||||
|
|
||||||
BMidiRoster::MidiRoster()->CreateLocal(this);
|
BMidiRoster::MidiRoster()->CreateLocal(this);
|
||||||
}
|
}
|
||||||
@@ -27,6 +43,11 @@ BMidiLocalConsumer::~BMidiLocalConsumer()
|
|||||||
TRACE(("BMidiLocalConsumer::~BMidiLocalConsumer"))
|
TRACE(("BMidiLocalConsumer::~BMidiLocalConsumer"))
|
||||||
|
|
||||||
BMidiRoster::MidiRoster()->DeleteLocal(this);
|
BMidiRoster::MidiRoster()->DeleteLocal(this);
|
||||||
|
|
||||||
|
delete_port(port);
|
||||||
|
|
||||||
|
status_t result;
|
||||||
|
wait_for_thread(thread, &result);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -62,22 +83,22 @@ void BMidiLocalConsumer::SetLatency(bigtime_t latency_)
|
|||||||
|
|
||||||
int32 BMidiLocalConsumer::GetProducerID(void)
|
int32 BMidiLocalConsumer::GetProducerID(void)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
return currentProducer;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalConsumer::SetTimeout(bigtime_t when, void* data)
|
void BMidiLocalConsumer::SetTimeout(bigtime_t when, void* data)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
timeout = when;
|
||||||
|
timeoutData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalConsumer::Timeout(void* data)
|
void BMidiLocalConsumer::Timeout(void* data)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -85,7 +106,134 @@ void BMidiLocalConsumer::Timeout(void* data)
|
|||||||
void BMidiLocalConsumer::Data(
|
void BMidiLocalConsumer::Data(
|
||||||
uchar* data, size_t length, bool atomic, bigtime_t time)
|
uchar* data, size_t length, bool atomic, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
if (atomic)
|
||||||
|
{
|
||||||
|
switch (data[0] & 0xF0)
|
||||||
|
{
|
||||||
|
case B_NOTE_OFF:
|
||||||
|
{
|
||||||
|
if (length == 3)
|
||||||
|
{
|
||||||
|
NoteOff(data[0] & 0x0F, data[1], data[2], time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_NOTE_ON:
|
||||||
|
{
|
||||||
|
if (length == 3)
|
||||||
|
{
|
||||||
|
NoteOn(data[0] & 0x0F, data[1], data[2], time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_KEY_PRESSURE:
|
||||||
|
{
|
||||||
|
if (length == 3)
|
||||||
|
{
|
||||||
|
KeyPressure(data[0] & 0x0F, data[1], data[2], time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_CONTROL_CHANGE:
|
||||||
|
{
|
||||||
|
if (length == 3)
|
||||||
|
{
|
||||||
|
ControlChange(data[0] & 0x0F, data[1], data[2], time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_PROGRAM_CHANGE:
|
||||||
|
{
|
||||||
|
if (length == 2)
|
||||||
|
{
|
||||||
|
ProgramChange(data[0] & 0x0F, data[1], time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_CHANNEL_PRESSURE:
|
||||||
|
{
|
||||||
|
if (length == 2)
|
||||||
|
{
|
||||||
|
ChannelPressure(data[0] & 0x0F, data[1], time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_PITCH_BEND:
|
||||||
|
{
|
||||||
|
if (length == 3)
|
||||||
|
{
|
||||||
|
PitchBend(data[0] & 0x0F, data[1], data[2], time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 0xF0:
|
||||||
|
{
|
||||||
|
switch (data[0])
|
||||||
|
{
|
||||||
|
case B_SYS_EX_START:
|
||||||
|
{
|
||||||
|
if (data[length - 1] == B_SYS_EX_END)
|
||||||
|
{
|
||||||
|
SystemExclusive(data + 1, length - 2, time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_TUNE_REQUEST:
|
||||||
|
case B_SYS_EX_END:
|
||||||
|
{
|
||||||
|
if (length == 1)
|
||||||
|
{
|
||||||
|
SystemCommon(data[0], 0, 0, time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_CABLE_MESSAGE:
|
||||||
|
case B_MIDI_TIME_CODE:
|
||||||
|
case B_SONG_SELECT:
|
||||||
|
{
|
||||||
|
if (length == 2)
|
||||||
|
{
|
||||||
|
SystemCommon(data[0], data[1], 0, time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_SONG_POSITION:
|
||||||
|
{
|
||||||
|
if (length == 3)
|
||||||
|
{
|
||||||
|
SystemCommon(data[0], data[1], data[2], time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case B_TIMING_CLOCK:
|
||||||
|
case B_START:
|
||||||
|
case B_CONTINUE:
|
||||||
|
case B_STOP:
|
||||||
|
case B_ACTIVE_SENSING:
|
||||||
|
case B_SYSTEM_RESET:
|
||||||
|
{
|
||||||
|
if (length == 1)
|
||||||
|
{
|
||||||
|
SystemRealTime(data[0], time);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -93,7 +241,7 @@ void BMidiLocalConsumer::Data(
|
|||||||
void BMidiLocalConsumer::NoteOff(
|
void BMidiLocalConsumer::NoteOff(
|
||||||
uchar channel, uchar note, uchar velocity, bigtime_t time)
|
uchar channel, uchar note, uchar velocity, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -101,7 +249,7 @@ void BMidiLocalConsumer::NoteOff(
|
|||||||
void BMidiLocalConsumer::NoteOn(
|
void BMidiLocalConsumer::NoteOn(
|
||||||
uchar channel, uchar note, uchar velocity, bigtime_t time)
|
uchar channel, uchar note, uchar velocity, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -109,7 +257,7 @@ void BMidiLocalConsumer::NoteOn(
|
|||||||
void BMidiLocalConsumer::KeyPressure(
|
void BMidiLocalConsumer::KeyPressure(
|
||||||
uchar channel, uchar note, uchar pressure, bigtime_t time)
|
uchar channel, uchar note, uchar pressure, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -117,7 +265,7 @@ void BMidiLocalConsumer::KeyPressure(
|
|||||||
void BMidiLocalConsumer::ControlChange(
|
void BMidiLocalConsumer::ControlChange(
|
||||||
uchar channel, uchar controlNumber, uchar controlValue, bigtime_t time)
|
uchar channel, uchar controlNumber, uchar controlValue, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -125,7 +273,7 @@ void BMidiLocalConsumer::ControlChange(
|
|||||||
void BMidiLocalConsumer::ProgramChange(
|
void BMidiLocalConsumer::ProgramChange(
|
||||||
uchar channel, uchar programNumber, bigtime_t time)
|
uchar channel, uchar programNumber, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -133,7 +281,7 @@ void BMidiLocalConsumer::ProgramChange(
|
|||||||
void BMidiLocalConsumer::ChannelPressure(
|
void BMidiLocalConsumer::ChannelPressure(
|
||||||
uchar channel, uchar pressure, bigtime_t time)
|
uchar channel, uchar pressure, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -141,15 +289,15 @@ void BMidiLocalConsumer::ChannelPressure(
|
|||||||
void BMidiLocalConsumer::PitchBend(
|
void BMidiLocalConsumer::PitchBend(
|
||||||
uchar channel, uchar lsb, uchar msb, bigtime_t time)
|
uchar channel, uchar lsb, uchar msb, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalConsumer::SystemExclusive(
|
void BMidiLocalConsumer::SystemExclusive(
|
||||||
void* data, size_t dataLength, bigtime_t time)
|
void* data, size_t length, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -157,28 +305,28 @@ void BMidiLocalConsumer::SystemExclusive(
|
|||||||
void BMidiLocalConsumer::SystemCommon(
|
void BMidiLocalConsumer::SystemCommon(
|
||||||
uchar statusByte, uchar data1, uchar data2, bigtime_t time)
|
uchar statusByte, uchar data1, uchar data2, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalConsumer::SystemRealTime(uchar statusByte, bigtime_t time)
|
void BMidiLocalConsumer::SystemRealTime(uchar statusByte, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalConsumer::TempoChange(int32 bpm, bigtime_t time)
|
void BMidiLocalConsumer::TempoChange(int32 beatsPerMinute, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalConsumer::AllNotesOff(bool justChannel, bigtime_t time)
|
void BMidiLocalConsumer::AllNotesOff(bool justChannel, bigtime_t time)
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -193,3 +341,67 @@ void BMidiLocalConsumer::_Reserved7() { }
|
|||||||
void BMidiLocalConsumer::_Reserved8() { }
|
void BMidiLocalConsumer::_Reserved8() { }
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
int32 BMidiLocalConsumer::EventThread()
|
||||||
|
{
|
||||||
|
int32 msg_code;
|
||||||
|
ssize_t msg_size;
|
||||||
|
ssize_t buf_size = 100;
|
||||||
|
uint8* buffer = (uint8*) malloc(buf_size);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (timeout == (bigtime_t) -1)
|
||||||
|
{
|
||||||
|
msg_size = port_buffer_size(port);
|
||||||
|
}
|
||||||
|
else // have timeout
|
||||||
|
{
|
||||||
|
msg_size = port_buffer_size_etc(port, B_ABSOLUTE_TIMEOUT, timeout);
|
||||||
|
if (msg_size == B_TIMED_OUT)
|
||||||
|
{
|
||||||
|
Timeout(timeoutData);
|
||||||
|
timeout = (bigtime_t) -1;
|
||||||
|
timeoutData = NULL;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg_size < 0) { break; } // error reading port
|
||||||
|
|
||||||
|
if (msg_size > buf_size)
|
||||||
|
{
|
||||||
|
buffer = (uint8*) realloc(buffer, msg_size);
|
||||||
|
buf_size = msg_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
read_port(port, &msg_code, buffer, msg_size);
|
||||||
|
|
||||||
|
if (msg_size > 20) // minimum valid size
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("*** received: ");
|
||||||
|
for (int32 t = 0; t < msg_size; ++t)
|
||||||
|
{
|
||||||
|
printf("%02X, ", ((uint8*) buffer)[t]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
currentProducer = *((uint32*) (buffer + 0));
|
||||||
|
int32 targetId = *((uint32*) (buffer + 4));
|
||||||
|
bigtime_t time = *((bigtime_t*) (buffer + 8));
|
||||||
|
bool atomic = *((bool*) (buffer + 16));
|
||||||
|
|
||||||
|
if (targetId == id) // only if we are the destination
|
||||||
|
{
|
||||||
|
Data((uchar*) (buffer + 20), msg_size - 20, atomic, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
* Copyright (c) 2002-2003 Matthijs Hollemans
|
* Copyright (c) 2002-2003 Matthijs Hollemans
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "MidiConsumer.h"
|
#include "MidiConsumer.h"
|
||||||
#include "MidiProducer.h"
|
#include "MidiProducer.h"
|
||||||
@@ -55,7 +57,7 @@ void BMidiLocalProducer::Disconnected(BMidiConsumer* cons)
|
|||||||
void BMidiLocalProducer::SprayData(
|
void BMidiLocalProducer::SprayData(
|
||||||
void* data, size_t length, bool atomic, bigtime_t time) const
|
void* data, size_t length, bool atomic, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
SprayEvent(data, length, atomic, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -63,7 +65,19 @@ void BMidiLocalProducer::SprayData(
|
|||||||
void BMidiLocalProducer::SprayNoteOff(
|
void BMidiLocalProducer::SprayNoteOff(
|
||||||
uchar channel, uchar note, uchar velocity, bigtime_t time) const
|
uchar channel, uchar note, uchar velocity, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
if (channel < 16)
|
||||||
|
{
|
||||||
|
uchar data[3];
|
||||||
|
data[0] = B_NOTE_OFF + channel;
|
||||||
|
data[1] = note;
|
||||||
|
data[2] = velocity;
|
||||||
|
|
||||||
|
SprayEvent(&data, 3, true, time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugger("invalid MIDI channel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -71,7 +85,19 @@ void BMidiLocalProducer::SprayNoteOff(
|
|||||||
void BMidiLocalProducer::SprayNoteOn(
|
void BMidiLocalProducer::SprayNoteOn(
|
||||||
uchar channel, uchar note, uchar velocity, bigtime_t time) const
|
uchar channel, uchar note, uchar velocity, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
if (channel < 16)
|
||||||
|
{
|
||||||
|
uchar data[3];
|
||||||
|
data[0] = B_NOTE_ON + channel;
|
||||||
|
data[1] = note;
|
||||||
|
data[2] = velocity;
|
||||||
|
|
||||||
|
SprayEvent(&data, 3, true, time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugger("invalid MIDI channel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -79,7 +105,19 @@ void BMidiLocalProducer::SprayNoteOn(
|
|||||||
void BMidiLocalProducer::SprayKeyPressure(
|
void BMidiLocalProducer::SprayKeyPressure(
|
||||||
uchar channel, uchar note, uchar pressure, bigtime_t time) const
|
uchar channel, uchar note, uchar pressure, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
if (channel < 16)
|
||||||
|
{
|
||||||
|
uchar data[3];
|
||||||
|
data[0] = B_KEY_PRESSURE + channel;
|
||||||
|
data[1] = note;
|
||||||
|
data[2] = pressure;
|
||||||
|
|
||||||
|
SprayEvent(&data, 3, true, time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugger("invalid MIDI channel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -88,7 +126,19 @@ void BMidiLocalProducer::SprayControlChange(
|
|||||||
uchar channel, uchar controlNumber, uchar controlValue,
|
uchar channel, uchar controlNumber, uchar controlValue,
|
||||||
bigtime_t time) const
|
bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
if (channel < 16)
|
||||||
|
{
|
||||||
|
uchar data[3];
|
||||||
|
data[0] = B_CONTROL_CHANGE + channel;
|
||||||
|
data[1] = controlNumber;
|
||||||
|
data[2] = controlValue;
|
||||||
|
|
||||||
|
SprayEvent(&data, 3, true, time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugger("invalid MIDI channel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -96,7 +146,18 @@ void BMidiLocalProducer::SprayControlChange(
|
|||||||
void BMidiLocalProducer::SprayProgramChange(
|
void BMidiLocalProducer::SprayProgramChange(
|
||||||
uchar channel, uchar programNumber, bigtime_t time) const
|
uchar channel, uchar programNumber, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
if (channel < 16)
|
||||||
|
{
|
||||||
|
uchar data[2];
|
||||||
|
data[0] = B_PROGRAM_CHANGE + channel;
|
||||||
|
data[1] = programNumber;
|
||||||
|
|
||||||
|
SprayEvent(&data, 2, true, time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugger("invalid MIDI channel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -104,7 +165,18 @@ void BMidiLocalProducer::SprayProgramChange(
|
|||||||
void BMidiLocalProducer::SprayChannelPressure(
|
void BMidiLocalProducer::SprayChannelPressure(
|
||||||
uchar channel, uchar pressure, bigtime_t time) const
|
uchar channel, uchar pressure, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
if (channel < 16)
|
||||||
|
{
|
||||||
|
uchar data[2];
|
||||||
|
data[0] = B_CHANNEL_PRESSURE + channel;
|
||||||
|
data[1] = pressure;
|
||||||
|
|
||||||
|
SprayEvent(&data, 2, true, time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugger("invalid MIDI channel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -112,39 +184,82 @@ void BMidiLocalProducer::SprayChannelPressure(
|
|||||||
void BMidiLocalProducer::SprayPitchBend(
|
void BMidiLocalProducer::SprayPitchBend(
|
||||||
uchar channel, uchar lsb, uchar msb, bigtime_t time) const
|
uchar channel, uchar lsb, uchar msb, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
if (channel < 16)
|
||||||
|
{
|
||||||
|
uchar data[3];
|
||||||
|
data[0] = B_PITCH_BEND + channel;
|
||||||
|
data[1] = lsb;
|
||||||
|
data[2] = msb;
|
||||||
|
|
||||||
|
SprayEvent(&data, 3, true, time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugger("invalid MIDI channel");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalProducer::SpraySystemExclusive(
|
void BMidiLocalProducer::SpraySystemExclusive(
|
||||||
void* data, size_t dataLength, bigtime_t time) const
|
void* data, size_t length, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
SprayEvent(data, length, true, time, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalProducer::SpraySystemCommon(
|
void BMidiLocalProducer::SpraySystemCommon(
|
||||||
uchar statusByte, uchar data1, uchar data2, bigtime_t time) const
|
uchar status, uchar data1, uchar data2, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
size_t len;
|
||||||
|
uchar data[3];
|
||||||
|
data[0] = status;
|
||||||
|
data[1] = data1;
|
||||||
|
data[2] = data2;
|
||||||
|
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case B_TUNE_REQUEST:
|
||||||
|
case B_SYS_EX_END:
|
||||||
|
len = 1; break;
|
||||||
|
|
||||||
|
case B_CABLE_MESSAGE:
|
||||||
|
case B_MIDI_TIME_CODE:
|
||||||
|
case B_SONG_SELECT:
|
||||||
|
len = 2; break;
|
||||||
|
|
||||||
|
case B_SONG_POSITION:
|
||||||
|
len = 3; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
debugger("invalid system common status");
|
||||||
|
}
|
||||||
|
|
||||||
|
SprayEvent(&data, len, true, time);
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalProducer::SpraySystemRealTime(
|
void BMidiLocalProducer::SpraySystemRealTime(
|
||||||
uchar statusByte, bigtime_t time) const
|
uchar status, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
if (status >= B_TIMING_CLOCK)
|
||||||
|
{
|
||||||
|
SprayEvent(&status, 1, true, time);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
debugger("invalid real time status");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void BMidiLocalProducer::SprayTempoChange(
|
void BMidiLocalProducer::SprayTempoChange(
|
||||||
int32 bpm, bigtime_t time) const
|
int32 beatsPerMinute, bigtime_t time) const
|
||||||
{
|
{
|
||||||
UNIMPLEMENTED
|
// This method does nothing, just like the BeOS R5 Midi Kit.
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
@@ -159,3 +274,69 @@ void BMidiLocalProducer::_Reserved7() { }
|
|||||||
void BMidiLocalProducer::_Reserved8() { }
|
void BMidiLocalProducer::_Reserved8() { }
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
void BMidiLocalProducer::SprayEvent(
|
||||||
|
const void* data, size_t length, bool atomic, bigtime_t time,
|
||||||
|
bool sysex) const
|
||||||
|
{
|
||||||
|
if (LockProducer())
|
||||||
|
{
|
||||||
|
if (CountConsumers() > 0)
|
||||||
|
{
|
||||||
|
// We don't just send the MIDI event data to all connected
|
||||||
|
// consumers, we also send a header. The header contains our
|
||||||
|
// ID (4 bytes), the consumer's ID (4 bytes), the performance
|
||||||
|
// time (8 bytes), whether the data is atomic (1 byte), and
|
||||||
|
// padding (3 bytes). The MIDI event data follows the header.
|
||||||
|
|
||||||
|
size_t buf_size = 20 + length;
|
||||||
|
if (sysex) { buf_size += 2; } // add 0xF0 and 0xF7 markers
|
||||||
|
|
||||||
|
uint8* buffer = (uint8*) malloc(buf_size);
|
||||||
|
if (buffer != NULL)
|
||||||
|
{
|
||||||
|
*((uint32*) (buffer + 0)) = id;
|
||||||
|
*((bigtime_t*) (buffer + 8)) = time;
|
||||||
|
*((uint32*) (buffer + 16)) = 0;
|
||||||
|
*((bool*) (buffer + 16)) = atomic;
|
||||||
|
|
||||||
|
if (sysex)
|
||||||
|
{
|
||||||
|
*((uint8*) (buffer + 20)) = B_SYS_EX_START;
|
||||||
|
if (data != NULL)
|
||||||
|
{
|
||||||
|
memcpy(buffer + 21, data, length);
|
||||||
|
}
|
||||||
|
*((uint8*) (buffer + buf_size - 1)) = B_SYS_EX_END;
|
||||||
|
}
|
||||||
|
else if (data != NULL)
|
||||||
|
{
|
||||||
|
memcpy(buffer + 20, data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32 t = 0; t < CountConsumers(); ++t)
|
||||||
|
{
|
||||||
|
BMidiConsumer* cons = ConsumerAt(t);
|
||||||
|
*((uint32*) (buffer + 4)) = cons->id;
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
printf("*** spraying: ");
|
||||||
|
for (int32 t = 0; t < buf_size; ++t)
|
||||||
|
{
|
||||||
|
printf("%02X, ", buffer[t]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
write_port(cons->port, 0, buffer, buf_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnlockProducer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user