Jack2 1.9.6
|
00001 /* 00002 Copyright (C) 2009 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 <cstring> 00022 #include <new> 00023 00024 #include "JackError.h" 00025 #include "JackPhysicalMidiInput.h" 00026 00027 namespace Jack { 00028 00029 JackPhysicalMidiInput::JackPhysicalMidiInput(size_t buffer_size) 00030 { 00031 size_t datum_size = sizeof(jack_midi_data_t); 00032 assert(buffer_size > 0); 00033 input_ring = jack_ringbuffer_create((buffer_size + 1) * datum_size); 00034 if (! input_ring) { 00035 throw std::bad_alloc(); 00036 } 00037 jack_ringbuffer_mlock(input_ring); 00038 Clear(); 00039 expected_data_bytes = 0; 00040 status_byte = 0; 00041 } 00042 00043 JackPhysicalMidiInput::~JackPhysicalMidiInput() 00044 { 00045 jack_ringbuffer_free(input_ring); 00046 } 00047 00048 void 00049 JackPhysicalMidiInput::Clear() 00050 { 00051 jack_ringbuffer_reset(input_ring); 00052 buffered_bytes = 0; 00053 unbuffered_bytes = 0; 00054 } 00055 00056 void 00057 JackPhysicalMidiInput::HandleBufferFailure(size_t unbuffered_bytes, 00058 size_t total_bytes) 00059 { 00060 jack_error("%d MIDI byte(s) of a %d byte message could not be buffered - " 00061 "message dropped", unbuffered_bytes, total_bytes); 00062 } 00063 00064 void 00065 JackPhysicalMidiInput::HandleIncompleteMessage(size_t bytes) 00066 { 00067 jack_error("Discarding %d MIDI byte(s) - incomplete message (cable " 00068 "unplugged?)", bytes); 00069 } 00070 00071 void 00072 JackPhysicalMidiInput::HandleInvalidStatusByte(jack_midi_data_t status) 00073 { 00074 jack_error("Dropping invalid MIDI status byte '%x'", 00075 (unsigned int) status); 00076 } 00077 00078 void 00079 JackPhysicalMidiInput::HandleUnexpectedSysexEnd(size_t bytes) 00080 { 00081 jack_error("Discarding %d MIDI byte(s) - received sysex end without sysex " 00082 "start (cable unplugged?)", bytes); 00083 } 00084 00085 void 00086 JackPhysicalMidiInput::HandleWriteFailure(size_t bytes) 00087 { 00088 jack_error("Failed to write a %d byte MIDI message to the port buffer", 00089 bytes); 00090 } 00091 00092 void 00093 JackPhysicalMidiInput::Process(jack_nframes_t frames) 00094 { 00095 assert(port_buffer); 00096 port_buffer->Reset(frames); 00097 jack_nframes_t current_frame = 0; 00098 size_t datum_size = sizeof(jack_midi_data_t); 00099 for (;;) { 00100 jack_midi_data_t datum; 00101 current_frame = Receive(&datum, current_frame, frames); 00102 if (current_frame >= frames) { 00103 break; 00104 } 00105 00106 jack_log("JackPhysicalMidiInput::Process (%d) - Received '%x' byte", 00107 current_frame, (unsigned int) datum); 00108 00109 if (datum >= 0xf8) { 00110 // Realtime 00111 if (datum == 0xfd) { 00112 HandleInvalidStatusByte(datum); 00113 } else { 00114 00115 jack_log("JackPhysicalMidiInput::Process - Writing realtime " 00116 "event."); 00117 00118 WriteByteEvent(current_frame, datum); 00119 } 00120 continue; 00121 } 00122 if (datum == 0xf7) { 00123 // Sysex end 00124 if (status_byte != 0xf0) { 00125 HandleUnexpectedSysexEnd(buffered_bytes + unbuffered_bytes); 00126 Clear(); 00127 expected_data_bytes = 0; 00128 status_byte = 0; 00129 } else { 00130 00131 jack_log("JackPhysicalMidiInput::Process - Writing sysex " 00132 "event."); 00133 00134 WriteBufferedSysexEvent(current_frame); 00135 } 00136 continue; 00137 } 00138 if (datum >= 0x80) { 00139 00140 // We're handling a non-realtime status byte 00141 00142 jack_log("JackPhysicalMidiInput::Process - Handling non-realtime " 00143 "status byte."); 00144 00145 if (buffered_bytes || unbuffered_bytes) { 00146 HandleIncompleteMessage(buffered_bytes + unbuffered_bytes + 1); 00147 Clear(); 00148 } 00149 status_byte = datum; 00150 switch (datum & 0xf0) { 00151 case 0x80: 00152 case 0x90: 00153 case 0xa0: 00154 case 0xb0: 00155 case 0xe0: 00156 // Note On, Note Off, Aftertouch, Control Change, Pitch Wheel 00157 expected_data_bytes = 2; 00158 break; 00159 case 0xc0: 00160 case 0xd0: 00161 // Program Change, Channel Pressure 00162 expected_data_bytes = 1; 00163 break; 00164 case 0xf0: 00165 switch (datum) { 00166 case 0xf0: 00167 // Sysex message 00168 expected_data_bytes = 0; 00169 break; 00170 case 0xf1: 00171 case 0xf3: 00172 // MTC Quarter frame, Song Select 00173 expected_data_bytes = 1; 00174 break; 00175 case 0xf2: 00176 // Song Position 00177 expected_data_bytes = 2; 00178 break; 00179 case 0xf4: 00180 case 0xf5: 00181 // Undefined 00182 HandleInvalidStatusByte(datum); 00183 expected_data_bytes = 0; 00184 status_byte = 0; 00185 break; 00186 case 0xf6: 00187 // Tune Request 00188 WriteByteEvent(current_frame, datum); 00189 expected_data_bytes = 0; 00190 status_byte = 0; 00191 } 00192 break; 00193 } 00194 continue; 00195 } 00196 00197 // We're handling a data byte 00198 00199 jack_log("JackPhysicalMidiInput::Process - Buffering data byte."); 00200 00201 if (jack_ringbuffer_write(input_ring, (const char *) &datum, 00202 datum_size) == datum_size) { 00203 buffered_bytes++; 00204 } else { 00205 unbuffered_bytes++; 00206 } 00207 unsigned long total_bytes = buffered_bytes + unbuffered_bytes; 00208 assert((! expected_data_bytes) || 00209 (total_bytes <= expected_data_bytes)); 00210 if (total_bytes == expected_data_bytes) { 00211 if (! unbuffered_bytes) { 00212 00213 jack_log("JackPhysicalMidiInput::Process - Writing buffered " 00214 "event."); 00215 00216 WriteBufferedEvent(current_frame); 00217 } else { 00218 HandleBufferFailure(unbuffered_bytes, total_bytes); 00219 Clear(); 00220 } 00221 if (status_byte >= 0xf0) { 00222 expected_data_bytes = 0; 00223 status_byte = 0; 00224 } 00225 } 00226 } 00227 } 00228 00229 void 00230 JackPhysicalMidiInput::WriteBufferedEvent(jack_nframes_t frame) 00231 { 00232 assert(port_buffer && port_buffer->IsValid()); 00233 size_t space = jack_ringbuffer_read_space(input_ring); 00234 jack_midi_data_t *event = port_buffer->ReserveEvent(frame, space + 1); 00235 if (event) { 00236 jack_ringbuffer_data_t vector[2]; 00237 jack_ringbuffer_get_read_vector(input_ring, vector); 00238 event[0] = status_byte; 00239 size_t data_length_1 = vector[0].len; 00240 memcpy(event + 1, vector[0].buf, data_length_1); 00241 size_t data_length_2 = vector[1].len; 00242 if (data_length_2) { 00243 memcpy(event + data_length_1 + 1, vector[1].buf, data_length_2); 00244 } 00245 } else { 00246 HandleWriteFailure(space + 1); 00247 } 00248 Clear(); 00249 } 00250 00251 void 00252 JackPhysicalMidiInput::WriteBufferedSysexEvent(jack_nframes_t frame) 00253 { 00254 assert(port_buffer && port_buffer->IsValid()); 00255 size_t space = jack_ringbuffer_read_space(input_ring); 00256 jack_midi_data_t *event = port_buffer->ReserveEvent(frame, space + 2); 00257 if (event) { 00258 jack_ringbuffer_data_t vector[2]; 00259 jack_ringbuffer_get_read_vector(input_ring, vector); 00260 event[0] = status_byte; 00261 size_t data_length_1 = vector[0].len; 00262 memcpy(event + 1, vector[0].buf, data_length_1); 00263 size_t data_length_2 = vector[1].len; 00264 if (data_length_2) { 00265 memcpy(event + data_length_1 + 1, vector[1].buf, data_length_2); 00266 } 00267 event[data_length_1 + data_length_2 + 1] = 0xf7; 00268 } else { 00269 HandleWriteFailure(space + 2); 00270 } 00271 Clear(); 00272 } 00273 00274 void 00275 JackPhysicalMidiInput::WriteByteEvent(jack_nframes_t frame, 00276 jack_midi_data_t datum) 00277 { 00278 assert(port_buffer && port_buffer->IsValid()); 00279 jack_midi_data_t *event = port_buffer->ReserveEvent(frame, 1); 00280 if (event) { 00281 event[0] = datum; 00282 } else { 00283 HandleWriteFailure(1); 00284 } 00285 } 00286 00287 }