00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <cassert>
00021 #include <memory>
00022
00023 #include "JackCoreMidiInputPort.h"
00024 #include "JackMidiUtil.h"
00025 #include "JackError.h"
00026
00027 using Jack::JackCoreMidiInputPort;
00028
00034 inline static int _expectedEventSize(const unsigned char& byte) {
00035 if (byte < 0x80) return -1;
00036 if (byte < 0xC0) return 3;
00037 if (byte < 0xE0) return 2;
00038 if (byte < 0xF0) return 3;
00039 if (byte == 0xF0) return -1;
00040 if (byte == 0xF1) return 2;
00041 if (byte == 0xF2) return 3;
00042 if (byte == 0xF3) return 2;
00043 if (byte == 0xF4) return -1;
00044 if (byte == 0xF5) return -1;
00045 return 1;
00046 }
00047
00048 JackCoreMidiInputPort::JackCoreMidiInputPort(double time_ratio,
00049 size_t max_bytes,
00050 size_t max_messages):
00051 JackCoreMidiPort(time_ratio)
00052 {
00053 thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
00054 std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
00055 write_queue = new JackMidiBufferWriteQueue();
00056 std::auto_ptr<JackMidiBufferWriteQueue> write_queue_ptr(write_queue);
00057 sysex_buffer = new jack_midi_data_t[max_bytes];
00058 write_queue_ptr.release();
00059 thread_queue_ptr.release();
00060 jack_event = 0;
00061 running_status_buf[0] = 0;
00062 }
00063
00064 JackCoreMidiInputPort::~JackCoreMidiInputPort()
00065 {
00066 delete thread_queue;
00067 delete write_queue;
00068 delete[] sysex_buffer;
00069 }
00070
00071 jack_nframes_t
00072 JackCoreMidiInputPort::GetFramesFromTimeStamp(MIDITimeStamp timestamp)
00073 {
00074 return GetFramesFromTime((jack_time_t) (timestamp * time_ratio));
00075 }
00076
00077 void
00078 JackCoreMidiInputPort::Initialize(const char *alias_name,
00079 const char *client_name,
00080 const char *driver_name, int index,
00081 MIDIEndpointRef endpoint)
00082 {
00083 JackCoreMidiPort::Initialize(alias_name, client_name, driver_name, index, endpoint, false);
00084 }
00085
00086 void
00087 JackCoreMidiInputPort::ProcessCoreMidi(const MIDIPacketList *packet_list)
00088 {
00089 set_threaded_log_function();
00090
00091
00092
00093 unsigned int packet_count = packet_list->numPackets;
00094 assert(packet_count);
00095 MIDIPacket *packet = (MIDIPacket *) packet_list->packet;
00096 for (unsigned int i = 0; i < packet_count; i++) {
00097 jack_midi_data_t *data = packet->data;
00098 size_t size = packet->length;
00099 assert(size);
00100 jack_midi_event_t event;
00101
00102
00103
00104 int k = 0;
00105 int eventSize = 0;
00106 int chunkSize = 0;
00107
00108
00109
00110
00111 if (sysex_bytes_sent) {
00112 if (data[0] & 0x80) {
00113 jack_error("JackCoreMidiInputPort::ProcessCoreMidi - System "
00114 "exclusive message aborted.");
00115 sysex_bytes_sent = 0;
00116 goto parse_event;
00117 }
00118 buffer_sysex_bytes:
00119 if ((sysex_bytes_sent + size) <= sizeof(sysex_buffer)) {
00120 memcpy(sysex_buffer + sysex_bytes_sent, packet,
00121 size * sizeof(jack_midi_data_t));
00122 }
00123 sysex_bytes_sent += size;
00124 if (data[size - 1] == 0xf7) {
00125 if (sysex_bytes_sent > sizeof(sysex_buffer)) {
00126 jack_error("JackCoreMidiInputPort::ProcessCoreMidi - "
00127 "Could not buffer a %d-byte system exclusive "
00128 "message. Discarding message.",
00129 sysex_bytes_sent);
00130 sysex_bytes_sent = 0;
00131 goto get_next_packet;
00132 }
00133 event.buffer = sysex_buffer;
00134 event.size = sysex_bytes_sent;
00135 sysex_bytes_sent = 0;
00136 k = size;
00137 goto send_event;
00138 }
00139 goto get_next_packet;
00140 }
00141
00142 parse_event:
00143 if (data[k+0] == 0xf0) {
00144
00145
00146
00147 if (k != 0) {
00148 jack_error("JackCoreMidiInputPort::ProcessCoreMidi - Non "
00149 "isolated SysEx message in one packet, discarding.");
00150 goto get_next_packet;
00151 }
00152
00153 if (data[size - 1] != 0xf7) {
00154 goto buffer_sysex_bytes;
00155 }
00156 }
00157
00158
00159 if (!(data[k+0] & 0x80) && running_status_buf[0]) {
00160 eventSize = _expectedEventSize(running_status_buf[0]);
00161 chunkSize = (eventSize < 0) ? size - k : eventSize - 1;
00162 if (chunkSize <= 0) goto get_next_packet;
00163 if (chunkSize + 1 <= sizeof(running_status_buf)) {
00164 memcpy(&running_status_buf[1], &data[k], chunkSize);
00165 event.buffer = running_status_buf;
00166 event.size = chunkSize + 1;
00167 k += chunkSize;
00168 goto send_event;
00169 }
00170 }
00171
00172
00173
00174 eventSize = _expectedEventSize(data[k+0]);
00175 if (eventSize < 0) eventSize = size - k;
00176 if (eventSize <= 0) goto get_next_packet;
00177 event.buffer = &data[k];
00178 event.size = eventSize;
00179
00180 if (data[k+0] & 0x80) {
00181 if (data[k+0] < 0xf0) {
00182
00183 running_status_buf[0] = data[k+0];
00184 } else if (data[k+0] < 0xf8) {
00185
00186
00187
00188 running_status_buf[0] = 0;
00189 }
00190 }
00191 k += eventSize;
00192
00193 send_event:
00194 event.time = GetFramesFromTimeStamp(packet->timeStamp);
00195 switch (thread_queue->EnqueueEvent(&event)) {
00196 case JackMidiWriteQueue::BUFFER_FULL:
00197 jack_error("JackCoreMidiInputPort::ProcessCoreMidi - The thread "
00198 "queue buffer is full. Dropping event.");
00199 break;
00200 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
00201 jack_error("JackCoreMidiInputPort::ProcessCoreMidi - The thread "
00202 "queue couldn't enqueue a %d-byte packet. Dropping "
00203 "event.", event.size);
00204 break;
00205 default:
00206 ;
00207 }
00208 if (k < size) goto parse_event;
00209
00210 get_next_packet:
00211 packet = MIDIPacketNext(packet);
00212 assert(packet);
00213 }
00214 }
00215
00216 void
00217 JackCoreMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
00218 jack_nframes_t frames)
00219 {
00220 write_queue->ResetMidiBuffer(port_buffer, frames);
00221 if (! jack_event) {
00222 jack_event = thread_queue->DequeueEvent();
00223 }
00224
00225 for (; jack_event; jack_event = thread_queue->DequeueEvent()) {
00226
00227 switch (write_queue->EnqueueEvent(jack_event, frames)) {
00228 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
00229 jack_error("JackCoreMidiInputPort::ProcessJack - The write queue "
00230 "couldn't enqueue a %d-byte event. Dropping event.",
00231 jack_event->size);
00232
00233 case JackMidiWriteQueue::OK:
00234 continue;
00235 default:
00236 ;
00237 }
00238 break;
00239 }
00240 }
00241
00242 bool
00243 JackCoreMidiInputPort::Start()
00244 {
00245
00246
00247 while (thread_queue->DequeueEvent());
00248 sysex_bytes_sent = 0;
00249 running_status_buf[0] = 0;
00250 return true;
00251 }
00252
00253 bool
00254 JackCoreMidiInputPort::Stop()
00255 {
00256 return true;
00257 }