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 #include <new>
00023
00024 #include "JackMidiRawInputWriteQueue.h"
00025
00026 using Jack::JackMidiRawInputWriteQueue;
00027
00028 JackMidiRawInputWriteQueue::
00029 JackMidiRawInputWriteQueue(JackMidiWriteQueue *write_queue,
00030 size_t max_packet_data, size_t max_packets)
00031 {
00032 packet_queue = new JackMidiAsyncQueue(max_packet_data, max_packets);
00033 std::auto_ptr<JackMidiAsyncQueue> packet_queue_ptr(packet_queue);
00034 input_buffer = new jack_midi_data_t[max_packet_data];
00035 Clear();
00036 expected_bytes = 0;
00037 event_pending = false;
00038 input_buffer_size = max_packet_data;
00039 packet = 0;
00040 status_byte = 0;
00041 this->write_queue = write_queue;
00042 packet_queue_ptr.release();
00043 }
00044
00045 JackMidiRawInputWriteQueue::~JackMidiRawInputWriteQueue()
00046 {
00047 delete[] input_buffer;
00048 delete packet_queue;
00049 }
00050
00051 void
00052 JackMidiRawInputWriteQueue::Clear()
00053 {
00054 total_bytes = 0;
00055 unbuffered_bytes = 0;
00056 }
00057
00058 Jack::JackMidiWriteQueue::EnqueueResult
00059 JackMidiRawInputWriteQueue::EnqueueEvent(jack_nframes_t time, size_t size,
00060 jack_midi_data_t *buffer)
00061 {
00062 return packet_queue->EnqueueEvent(time, size, buffer);
00063 }
00064
00065 size_t
00066 JackMidiRawInputWriteQueue::GetAvailableSpace()
00067 {
00068 return packet_queue->GetAvailableSpace();
00069 }
00070
00071 void
00072 JackMidiRawInputWriteQueue::HandleBufferFailure(size_t unbuffered_bytes,
00073 size_t total_bytes)
00074 {
00075 jack_error("JackMidiRawInputWriteQueue::HandleBufferFailure - %d MIDI "
00076 "byte(s) of a %d byte message could not be buffered. The "
00077 "message has been dropped.", unbuffered_bytes, total_bytes);
00078 }
00079
00080 void
00081 JackMidiRawInputWriteQueue::HandleEventLoss(jack_midi_event_t *event)
00082 {
00083 jack_error("JackMidiRawInputWriteQueue::HandleEventLoss - A %d byte MIDI "
00084 "event scheduled for frame '%d' could not be processed because "
00085 "the write queue cannot accomodate an event of that size. The "
00086 "event has been discarded.", event->size, event->time);
00087 }
00088
00089 void
00090 JackMidiRawInputWriteQueue::HandleIncompleteMessage(size_t total_bytes)
00091 {
00092 jack_error("JackMidiRawInputWriteQueue::HandleIncompleteMessage - "
00093 "Discarding %d MIDI byte(s) of an incomplete message. The "
00094 "MIDI cable may have been unplugged.", total_bytes);
00095 }
00096
00097 void
00098 JackMidiRawInputWriteQueue::HandleInvalidStatusByte(jack_midi_data_t byte)
00099 {
00100 jack_error("JackMidiRawInputWriteQueue::HandleInvalidStatusByte - "
00101 "Dropping invalid MIDI status byte '%x'.", (unsigned int) byte);
00102 }
00103
00104 void
00105 JackMidiRawInputWriteQueue::HandleUnexpectedSysexEnd(size_t total_bytes)
00106 {
00107 jack_error("JackMidiRawInputWriteQueue::HandleUnexpectedSysexEnd - "
00108 "Received a sysex end byte without first receiving a sysex "
00109 "start byte. Discarding %d MIDI byte(s). The cable may have "
00110 "been unplugged.", total_bytes);
00111 }
00112
00113 bool
00114 JackMidiRawInputWriteQueue::PrepareBufferedEvent(jack_nframes_t time)
00115 {
00116 bool result = ! unbuffered_bytes;
00117 if (! result) {
00118 HandleBufferFailure(unbuffered_bytes, total_bytes);
00119 } else {
00120 PrepareEvent(time, total_bytes, input_buffer);
00121 }
00122 Clear();
00123 if (status_byte >= 0xf0) {
00124 expected_bytes = 0;
00125 status_byte = 0;
00126 }
00127 return result;
00128 }
00129
00130 bool
00131 JackMidiRawInputWriteQueue::PrepareByteEvent(jack_nframes_t time,
00132 jack_midi_data_t byte)
00133 {
00134 event_byte = byte;
00135 PrepareEvent(time, 1, &event_byte);
00136 return true;
00137 }
00138
00139 void
00140 JackMidiRawInputWriteQueue::PrepareEvent(jack_nframes_t time, size_t size,
00141 jack_midi_data_t *buffer)
00142 {
00143 event.buffer = buffer;
00144 event.size = size;
00145 event.time = time;
00146 event_pending = true;
00147 }
00148
00149 jack_nframes_t
00150 JackMidiRawInputWriteQueue::Process(jack_nframes_t boundary_frame)
00151 {
00152 if (event_pending) {
00153 if (! WriteEvent(boundary_frame)) {
00154 return event.time;
00155 }
00156 }
00157 if (! packet) {
00158 packet = packet_queue->DequeueEvent();
00159 }
00160 for (; packet; packet = packet_queue->DequeueEvent()) {
00161 for (; packet->size; (packet->buffer)++, (packet->size)--) {
00162 if (ProcessByte(packet->time, *(packet->buffer))) {
00163 if (! WriteEvent(boundary_frame)) {
00164 (packet->buffer)++;
00165 (packet->size)--;
00166 return event.time;
00167 }
00168 }
00169 }
00170 }
00171 return 0;
00172 }
00173
00174 bool
00175 JackMidiRawInputWriteQueue::ProcessByte(jack_nframes_t time,
00176 jack_midi_data_t byte)
00177 {
00178 if (byte >= 0xf8) {
00179
00180 if (byte == 0xfd) {
00181 HandleInvalidStatusByte(byte);
00182 return false;
00183 }
00184 return PrepareByteEvent(time, byte);
00185 }
00186 if (byte == 0xf7) {
00187
00188 if (status_byte == 0xf0) {
00189 RecordByte(byte);
00190 return PrepareBufferedEvent(time);
00191 }
00192 HandleUnexpectedSysexEnd(total_bytes);
00193 Clear();
00194 expected_bytes = 0;
00195 status_byte = 0;
00196 return false;
00197 }
00198 if (byte >= 0x80) {
00199
00200 if (total_bytes) {
00201 HandleIncompleteMessage(total_bytes);
00202 Clear();
00203 }
00204 status_byte = byte;
00205 switch (byte & 0xf0) {
00206 case 0x80:
00207 case 0x90:
00208 case 0xa0:
00209 case 0xb0:
00210 case 0xe0:
00211
00212 expected_bytes = 3;
00213 break;
00214 case 0xc0:
00215 case 0xd0:
00216
00217 expected_bytes = 2;
00218 break;
00219 case 0xf0:
00220 switch (byte) {
00221 case 0xf0:
00222
00223 expected_bytes = 0;
00224 break;
00225 case 0xf1:
00226 case 0xf3:
00227
00228 expected_bytes = 2;
00229 break;
00230 case 0xf2:
00231
00232 expected_bytes = 3;
00233 break;
00234 case 0xf4:
00235 case 0xf5:
00236
00237 HandleInvalidStatusByte(byte);
00238 expected_bytes = 0;
00239 status_byte = 0;
00240 return false;
00241 case 0xf6:
00242
00243 bool result = PrepareByteEvent(time, byte);
00244 if (result) {
00245 expected_bytes = 0;
00246 status_byte = 0;
00247 }
00248 return result;
00249 }
00250 }
00251 RecordByte(byte);
00252 return false;
00253 }
00254
00255 if (! status_byte) {
00256
00257 total_bytes++;
00258 unbuffered_bytes++;
00259 return false;
00260 }
00261 if (! total_bytes) {
00262
00263 RecordByte(status_byte);
00264 }
00265 RecordByte(byte);
00266 return (total_bytes == expected_bytes) ? PrepareBufferedEvent(time) :
00267 false;
00268 }
00269
00270 void
00271 JackMidiRawInputWriteQueue::RecordByte(jack_midi_data_t byte)
00272 {
00273 if (total_bytes < input_buffer_size) {
00274 input_buffer[total_bytes] = byte;
00275 } else {
00276 unbuffered_bytes++;
00277 }
00278 total_bytes++;
00279 }
00280
00281 bool
00282 JackMidiRawInputWriteQueue::WriteEvent(jack_nframes_t boundary_frame)
00283 {
00284 if ((! boundary_frame) || (event.time < boundary_frame)) {
00285 switch (write_queue->EnqueueEvent(&event)) {
00286 case BUFFER_TOO_SMALL:
00287 HandleEventLoss(&event);
00288
00289 case OK:
00290 event_pending = false;
00291 return true;
00292 default:
00293
00294
00295 ;
00296 }
00297 }
00298 return false;
00299 }