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