00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
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
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
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
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
00157 expected_data_bytes = 2;
00158 break;
00159 case 0xc0:
00160 case 0xd0:
00161
00162 expected_data_bytes = 1;
00163 break;
00164 case 0xf0:
00165 switch (datum) {
00166 case 0xf0:
00167
00168 expected_data_bytes = 0;
00169 break;
00170 case 0xf1:
00171 case 0xf3:
00172
00173 expected_data_bytes = 1;
00174 break;
00175 case 0xf2:
00176
00177 expected_data_bytes = 2;
00178 break;
00179 case 0xf4:
00180 case 0xf5:
00181
00182 HandleInvalidStatusByte(datum);
00183 expected_data_bytes = 0;
00184 status_byte = 0;
00185 break;
00186 case 0xf6:
00187
00188 WriteByteEvent(current_frame, datum);
00189 expected_data_bytes = 0;
00190 status_byte = 0;
00191 }
00192 break;
00193 }
00194 continue;
00195 }
00196
00197
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 }