Jack2
1.9.10
|
00001 /* 00002 Copyright (C) 2010 Devin Anderson 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 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 // Realtime 00181 if (byte == 0xfd) { 00182 HandleInvalidStatusByte(byte); 00183 return false; 00184 } 00185 return PrepareByteEvent(time, byte); 00186 } 00187 if (byte == 0xf7) { 00188 // Sysex end 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 // Non-realtime status byte 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 // Note On, Note Off, Aftertouch, Control Change, Pitch Wheel 00213 expected_bytes = 3; 00214 break; 00215 case 0xc0: 00216 case 0xd0: 00217 // Program Change, Channel Pressure 00218 expected_bytes = 2; 00219 break; 00220 case 0xf0: 00221 switch (byte) { 00222 case 0xf0: 00223 // Sysex 00224 expected_bytes = 0; 00225 break; 00226 case 0xf1: 00227 case 0xf3: 00228 // MTC Quarter Frame, Song Select 00229 expected_bytes = 2; 00230 break; 00231 case 0xf2: 00232 // Song Position 00233 expected_bytes = 3; 00234 break; 00235 case 0xf4: 00236 case 0xf5: 00237 // Undefined 00238 HandleInvalidStatusByte(byte); 00239 expected_bytes = 0; 00240 status_byte = 0; 00241 return false; 00242 case 0xf6: 00243 // Tune Request 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 // Data byte 00256 if (! status_byte) { 00257 // Data bytes without a status will be discarded. 00258 total_bytes++; 00259 unbuffered_bytes++; 00260 return false; 00261 } 00262 if (! total_bytes) { 00263 // Apply running status. 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 // Fallthrough on purpose 00290 case OK: 00291 event_pending = false; 00292 return true; 00293 default: 00294 // This is here to stop compilers from warning us about not 00295 // handling enumeration values. 00296 ; 00297 } 00298 } 00299 return false; 00300 }