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
00026 using Jack::JackCoreMidiInputPort;
00027
00028 JackCoreMidiInputPort::JackCoreMidiInputPort(double time_ratio,
00029 size_t max_bytes,
00030 size_t max_messages):
00031 JackCoreMidiPort(time_ratio)
00032 {
00033 thread_queue = new JackMidiAsyncQueue(max_bytes, max_messages);
00034 std::auto_ptr<JackMidiAsyncQueue> thread_queue_ptr(thread_queue);
00035 write_queue = new JackMidiBufferWriteQueue();
00036 std::auto_ptr<JackMidiBufferWriteQueue> write_queue_ptr(write_queue);
00037 sysex_buffer = new jack_midi_data_t[max_bytes];
00038 write_queue_ptr.release();
00039 thread_queue_ptr.release();
00040 jack_event = 0;
00041 }
00042
00043 JackCoreMidiInputPort::~JackCoreMidiInputPort()
00044 {
00045 delete thread_queue;
00046 delete write_queue;
00047 delete[] sysex_buffer;
00048 }
00049
00050 jack_nframes_t
00051 JackCoreMidiInputPort::GetFramesFromTimeStamp(MIDITimeStamp timestamp)
00052 {
00053 return GetFramesFromTime((jack_time_t) (timestamp * time_ratio));
00054 }
00055
00056 void
00057 JackCoreMidiInputPort::Initialize(const char *alias_name,
00058 const char *client_name,
00059 const char *driver_name, int index,
00060 MIDIEndpointRef endpoint)
00061 {
00062 JackCoreMidiPort::Initialize(alias_name, client_name, driver_name, index, endpoint, false);
00063 }
00064
00065 void
00066 JackCoreMidiInputPort::ProcessCoreMidi(const MIDIPacketList *packet_list)
00067 {
00068 set_threaded_log_function();
00069
00070 unsigned int packet_count = packet_list->numPackets;
00071 assert(packet_count);
00072 MIDIPacket *packet = (MIDIPacket *) packet_list->packet;
00073 for (unsigned int i = 0; i < packet_count; i++) {
00074 jack_midi_data_t *data = packet->data;
00075 size_t size = packet->length;
00076 assert(size);
00077 jack_midi_event_t event;
00078
00079
00080
00081
00082 if (sysex_bytes_sent) {
00083 if (data[0] & 0x80) {
00084 jack_error("JackCoreMidiInputPort::ProcessCoreMidi - System "
00085 "exclusive message aborted.");
00086 sysex_bytes_sent = 0;
00087 goto parse_event;
00088 }
00089 buffer_sysex_bytes:
00090 if ((sysex_bytes_sent + size) <= sizeof(sysex_buffer)) {
00091 memcpy(sysex_buffer + sysex_bytes_sent, packet,
00092 size * sizeof(jack_midi_data_t));
00093 }
00094 sysex_bytes_sent += size;
00095 if (data[size - 1] == 0xf7) {
00096 if (sysex_bytes_sent > sizeof(sysex_buffer)) {
00097 jack_error("JackCoreMidiInputPort::ProcessCoreMidi - "
00098 "Could not buffer a %d-byte system exclusive "
00099 "message. Discarding message.",
00100 sysex_bytes_sent);
00101 sysex_bytes_sent = 0;
00102 goto get_next_packet;
00103 }
00104 event.buffer = sysex_buffer;
00105 event.size = sysex_bytes_sent;
00106 sysex_bytes_sent = 0;
00107 goto send_event;
00108 }
00109 goto get_next_packet;
00110 }
00111
00112 parse_event:
00113 if (data[0] == 0xf0) {
00114 if (data[size - 1] != 0xf7) {
00115 goto buffer_sysex_bytes;
00116 }
00117 }
00118 event.buffer = data;
00119 event.size = size;
00120
00121 send_event:
00122 event.time = GetFramesFromTimeStamp(packet->timeStamp);
00123 switch (thread_queue->EnqueueEvent(&event)) {
00124 case JackMidiWriteQueue::BUFFER_FULL:
00125 jack_error("JackCoreMidiInputPort::ProcessCoreMidi - The thread "
00126 "queue buffer is full. Dropping event.");
00127 break;
00128 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
00129 jack_error("JackCoreMidiInputPort::ProcessCoreMidi - The thread "
00130 "queue couldn't enqueue a %d-byte packet. Dropping "
00131 "event.", event.size);
00132 break;
00133 default:
00134 ;
00135 }
00136
00137 get_next_packet:
00138 packet = MIDIPacketNext(packet);
00139 assert(packet);
00140 }
00141 }
00142
00143 void
00144 JackCoreMidiInputPort::ProcessJack(JackMidiBuffer *port_buffer,
00145 jack_nframes_t frames)
00146 {
00147 write_queue->ResetMidiBuffer(port_buffer, frames);
00148 if (! jack_event) {
00149 jack_event = thread_queue->DequeueEvent();
00150 }
00151
00152 for (; jack_event; jack_event = thread_queue->DequeueEvent()) {
00153
00154 switch (write_queue->EnqueueEvent(jack_event, frames)) {
00155 case JackMidiWriteQueue::BUFFER_TOO_SMALL:
00156 jack_error("JackCoreMidiInputPort::ProcessJack - The write queue "
00157 "couldn't enqueue a %d-byte event. Dropping event.",
00158 jack_event->size);
00159
00160 case JackMidiWriteQueue::OK:
00161 continue;
00162 default:
00163 ;
00164 }
00165 break;
00166 }
00167 }
00168
00169 bool
00170 JackCoreMidiInputPort::Start()
00171 {
00172
00173
00174 while (thread_queue->DequeueEvent());
00175 sysex_bytes_sent = 0;
00176 return true;
00177 }
00178
00179 bool
00180 JackCoreMidiInputPort::Stop()
00181 {
00182 return true;
00183 }