23 #include "JackCoreMidiInputPort.h"
24 #include "JackMidiUtil.h"
25 #include "JackError.h"
34 inline static int _expectedEventSize(
const unsigned char& byte) {
35 if (byte < 0x80)
return -1;
36 if (byte < 0xC0)
return 3;
37 if (byte < 0xE0)
return 2;
38 if (byte < 0xF0)
return 3;
39 if (byte == 0xF0)
return -1;
40 if (byte == 0xF1)
return 2;
41 if (byte == 0xF2)
return 3;
42 if (byte == 0xF3)
return 2;
43 if (byte == 0xF4)
return -1;
44 if (byte == 0xF5)
return -1;
48 JackCoreMidiInputPort::JackCoreMidiInputPort(
double time_ratio,
51 JackCoreMidiPort(time_ratio)
53 thread_queue =
new JackMidiAsyncQueue(max_bytes, max_messages);
54 std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
55 write_queue =
new JackMidiBufferWriteQueue();
56 std::auto_ptr<JackMidiBufferWriteQueue> write_queue_ptr(write_queue);
57 sysex_buffer =
new jack_midi_data_t[max_bytes];
58 write_queue_ptr.release();
59 thread_queue_ptr.release();
61 running_status_buf[0] = 0;
64 JackCoreMidiInputPort::~JackCoreMidiInputPort()
68 delete[] sysex_buffer;
72 JackCoreMidiInputPort::GetFramesFromTimeStamp(MIDITimeStamp timestamp)
74 return GetFramesFromTime((jack_time_t) (timestamp * time_ratio));
78 JackCoreMidiInputPort::Initialize(
const char *alias_name,
79 const char *client_name,
80 const char *driver_name,
int index,
81 MIDIEndpointRef endpoint)
83 JackCoreMidiPort::Initialize(alias_name, client_name, driver_name, index, endpoint,
false);
87 JackCoreMidiInputPort::ProcessCoreMidi(
const MIDIPacketList *packet_list)
89 set_threaded_log_function();
93 unsigned int packet_count = packet_list->numPackets;
95 MIDIPacket *packet = (MIDIPacket *) packet_list->packet;
96 for (
unsigned int i = 0; i < packet_count; i++) {
97 jack_midi_data_t *data = packet->data;
98 size_t size = packet->length;
111 if (sysex_bytes_sent) {
112 if (data[0] & 0x80) {
113 jack_error(
"JackCoreMidiInputPort::ProcessCoreMidi - System "
114 "exclusive message aborted.");
115 sysex_bytes_sent = 0;
119 if ((sysex_bytes_sent + size) <=
sizeof(sysex_buffer)) {
120 memcpy(sysex_buffer + sysex_bytes_sent, packet,
121 size *
sizeof(jack_midi_data_t));
123 sysex_bytes_sent += size;
124 if (data[size - 1] == 0xf7) {
125 if (sysex_bytes_sent >
sizeof(sysex_buffer)) {
126 jack_error(
"JackCoreMidiInputPort::ProcessCoreMidi - "
127 "Could not buffer a %d-byte system exclusive "
128 "message. Discarding message.",
130 sysex_bytes_sent = 0;
131 goto get_next_packet;
133 event.buffer = sysex_buffer;
134 event.size = sysex_bytes_sent;
135 sysex_bytes_sent = 0;
139 goto get_next_packet;
143 if (data[k+0] == 0xf0) {
148 jack_error(
"JackCoreMidiInputPort::ProcessCoreMidi - Non "
149 "isolated SysEx message in one packet, discarding.");
150 goto get_next_packet;
153 if (data[size - 1] != 0xf7) {
154 goto buffer_sysex_bytes;
159 if (!(data[k+0] & 0x80) && running_status_buf[0]) {
160 eventSize = _expectedEventSize(running_status_buf[0]);
161 chunkSize = (eventSize < 0) ? size - k : eventSize - 1;
162 if (chunkSize <= 0)
goto get_next_packet;
163 if (chunkSize + 1 <=
sizeof(running_status_buf)) {
164 memcpy(&running_status_buf[1], &data[k], chunkSize);
165 event.buffer = running_status_buf;
166 event.size = chunkSize + 1;
174 eventSize = _expectedEventSize(data[k+0]);
175 if (eventSize < 0) eventSize = size - k;
176 if (eventSize <= 0)
goto get_next_packet;
177 event.buffer = &data[k];
178 event.size = eventSize;
180 if (data[k+0] & 0x80) {
181 if (data[k+0] < 0xf0) {
183 running_status_buf[0] = data[k+0];
184 }
else if (data[k+0] < 0xf8) {
188 running_status_buf[0] = 0;
194 event.time = GetFramesFromTimeStamp(packet->timeStamp);
196 case JackMidiWriteQueue::BUFFER_FULL:
197 jack_error(
"JackCoreMidiInputPort::ProcessCoreMidi - The thread "
198 "queue buffer is full. Dropping event.");
200 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
201 jack_error(
"JackCoreMidiInputPort::ProcessCoreMidi - The thread "
202 "queue couldn't enqueue a %d-byte packet. Dropping "
203 "event.", event.
size);
208 if (k < size)
goto parse_event;
211 packet = MIDIPacketNext(packet);
217 JackCoreMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
218 jack_nframes_t frames)
225 for (; jack_event; jack_event = thread_queue->
DequeueEvent()) {
227 switch (write_queue->
EnqueueEvent(jack_event, frames)) {
228 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
229 jack_error(
"JackCoreMidiInputPort::ProcessJack - The write queue "
230 "couldn't enqueue a %d-byte event. Dropping event.",
233 case JackMidiWriteQueue::OK:
243 JackCoreMidiInputPort::Start()
248 sysex_bytes_sent = 0;
249 running_status_buf[0] = 0;
254 JackCoreMidiInputPort::Stop()
EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer)
SERVER_EXPORT void jack_error(const char *fmt,...)
void ResetMidiBuffer(JackMidiBuffer *buffer, jack_nframes_t frames)
virtual jack_midi_event_t * DequeueEvent()
virtual EnqueueResult EnqueueEvent(jack_nframes_t time, size_t size, jack_midi_data_t *buffer)