2 * Copyright (C) 2014 Robin Gareus <robin@gareus.org>
3 * Copyright (C) 2010 Devin Anderson
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "alsa_rawmidi.h"
25 #include "rt_thread.h"
27 #include "pbd/error.h"
30 using namespace ARDOUR;
32 /* max bytes per individual midi-event
33 * events larger than this are ignored */
34 #define MaxAlsaRawEventSize (64)
37 #define _DEBUGPRINT(STR) fprintf(stderr, STR);
39 #define _DEBUGPRINT(STR) ;
42 AlsaRawMidiIO::AlsaRawMidiIO (const char *device, const bool input)
47 , _sample_length_us (1e6 / 48000.0)
48 , _period_length_us (1.024e6 / 48000.0)
49 , _samples_per_period (1024)
52 pthread_mutex_init (&_notify_mutex, 0);
53 pthread_cond_init (&_notify_ready, 0);
57 AlsaRawMidiIO::~AlsaRawMidiIO ()
60 snd_rawmidi_close (_device);
64 pthread_mutex_destroy (&_notify_mutex);
65 pthread_cond_destroy (&_notify_ready);
70 AlsaRawMidiIO::init (const char *device_name, const bool input)
72 if (snd_rawmidi_open (
73 input ? &_device : NULL,
74 input ? NULL : &_device,
75 device_name, SND_RAWMIDI_NONBLOCK) < 0) {
79 _npfds = snd_rawmidi_poll_descriptors_count (_device);
81 _DEBUGPRINT("AlsaRawMidiIO: no poll descriptor(s).\n");
82 snd_rawmidi_close (_device);
86 _pfds = (struct pollfd*) malloc (_npfds * sizeof(struct pollfd));
87 snd_rawmidi_poll_descriptors (_device, _pfds, _npfds);
89 // MIDI (hw port) 31.25 kbaud
90 // worst case here is 8192 SPP and 8KSPS for which we'd need
91 // 4000 bytes sans MidiEventHeader.
92 // since we're not always in sync, let's use 4096.
93 _rb = new RingBuffer<uint8_t>(4096 + 4096 * sizeof(MidiEventHeader));
98 snd_rawmidi_params_t *params;
99 if (snd_rawmidi_params_malloc (¶ms)) {
102 if (snd_rawmidi_params_current (_device, params)) {
105 if (snd_rawmidi_params_set_avail_min (_device, params, 1)) {
108 if ( snd_rawmidi_params_set_buffer_size (_device, params, 64)) {
111 if (snd_rawmidi_params_set_no_active_sensing (_device, params, 1)) {
119 _DEBUGPRINT("AlsaRawMidiIO: parameter setup error\n");
120 snd_rawmidi_close (_device);
126 static void * pthread_process (void *arg)
128 AlsaRawMidiIO *d = static_cast<AlsaRawMidiIO *>(arg);
129 d->main_process_thread ();
135 AlsaRawMidiIO::start ()
137 if (_realtime_pthread_create (SCHED_FIFO, -19,
138 &_main_thread, pthread_process, this))
140 if (pthread_create (&_main_thread, NULL, pthread_process, this)) {
141 PBD::error << _("AlsaRawMidiIO: Failed to create process thread.") << endmsg;
144 PBD::warning << _("AlsaRawMidiIO: Cannot acquire realtime permissions.") << endmsg;
148 while (!_running && --timeout > 0) { Glib::usleep (1000); }
149 if (timeout == 0 || !_running) {
156 AlsaRawMidiIO::stop ()
165 pthread_mutex_lock (&_notify_mutex);
166 pthread_cond_signal (&_notify_ready);
167 pthread_mutex_unlock (&_notify_mutex);
169 if (pthread_join (_main_thread, &status)) {
170 PBD::error << _("AlsaRawMidiIO: Failed to terminate.") << endmsg;
177 AlsaRawMidiIO::setup_timing (const size_t samples_per_period, const float samplerate)
179 _period_length_us = (double) samples_per_period * 1e6 / samplerate;
180 _sample_length_us = 1e6 / samplerate;
181 _samples_per_period = samples_per_period;
185 AlsaRawMidiIO::sync_time (const uint64_t tme)
187 // TODO consider a PLL, if this turns out to be the bottleneck for jitter
188 // also think about using
189 // snd_pcm_status_get_tstamp() and snd_rawmidi_status_get_tstamp()
190 // instead of monotonic clock.
192 double tdiff = (_clock_monotonic + _period_length_us - tme) / 1000.0;
193 if (abs(tdiff) >= .05) {
194 printf("AlsaRawMidiIO MJ: %.1f ms\n", tdiff);
197 _clock_monotonic = tme;
200 ///////////////////////////////////////////////////////////////////////////////
202 // select sleeps _at most_ (compared to usleep() which sleeps at least)
203 static void select_sleep (uint32_t usec) {
204 if (usec <= 10) return;
208 tv.tv_sec = usec / 1000000;
209 tv.tv_usec = usec % 1000000;
211 select (max_fd, &fd, NULL, NULL, &tv);
214 ///////////////////////////////////////////////////////////////////////////////
216 AlsaRawMidiOut::AlsaRawMidiOut (const char *device)
217 : AlsaRawMidiIO (device, false)
223 AlsaRawMidiOut::send_event (const pframes_t time, const uint8_t *data, const size_t size)
225 const uint32_t buf_size = sizeof (MidiEventHeader) + size;
226 if (_rb->write_space() < buf_size) {
227 _DEBUGPRINT("AlsaRawMidiOut: ring buffer overflow\n");
230 struct MidiEventHeader h (_clock_monotonic + time * _sample_length_us, size);
231 _rb->write ((uint8_t*) &h, sizeof(MidiEventHeader));
232 _rb->write (data, size);
234 if (pthread_mutex_trylock (&_notify_mutex) == 0) {
235 pthread_cond_signal (&_notify_ready);
236 pthread_mutex_unlock (&_notify_mutex);
242 AlsaRawMidiOut::main_process_thread ()
245 pthread_mutex_lock (&_notify_mutex);
247 bool have_data = false;
248 struct MidiEventHeader h(0,0);
249 uint8_t data[MaxAlsaRawEventSize];
251 const uint32_t read_space = _rb->read_space();
253 if (read_space > sizeof(MidiEventHeader)) {
254 if (_rb->read ((uint8_t*)&h, sizeof(MidiEventHeader)) != sizeof(MidiEventHeader)) {
255 _DEBUGPRINT("AlsaRawMidiOut: Garbled MIDI EVENT HEADER!!\n");
258 assert (read_space >= h.size);
259 if (h.size > MaxAlsaRawEventSize) {
260 _rb->increment_read_idx (h.size);
261 _DEBUGPRINT("AlsaRawMidiOut: MIDI event too large!\n");
264 if (_rb->read (&data[0], h.size) != h.size) {
265 _DEBUGPRINT("AlsaRawMidiOut: Garbled MIDI EVENT DATA!!\n");
272 pthread_cond_wait (&_notify_ready, &_notify_mutex);
276 uint64_t now = g_get_monotonic_time();
277 while (h.time > now + 500) {
278 select_sleep(h.time - now);
279 now = g_get_monotonic_time();
283 int perr = poll (_pfds, _npfds, 10 /* ms */);
285 PBD::error << _("AlsaRawMidiOut: Error polling device. Terminating Midi Thread.") << endmsg;
289 _DEBUGPRINT("AlsaRawMidiOut: poll() timed out.\n");
293 unsigned short revents = 0;
294 if (snd_rawmidi_poll_descriptors_revents (_device, _pfds, _npfds, &revents)) {
295 PBD::error << _("AlsaRawMidiOut: Failed to poll device. Terminating Midi Thread.") << endmsg;
299 if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
300 PBD::error << _("AlsaRawMidiOut: poll error. Terminating Midi Thread.") << endmsg;
304 if (!(revents & POLLOUT)) {
305 _DEBUGPRINT("AlsaRawMidiOut: POLLOUT not ready.\n");
310 ssize_t err = snd_rawmidi_write (_device, data, h.size);
312 if ((err == -EAGAIN) || (err == -EWOULDBLOCK)) {
317 PBD::error << _("AlsaRawMidiOut: write failed. Terminating Midi Thread.") << endmsg;
320 if ((size_t) err < h.size) {
321 _DEBUGPRINT("AlsaRawMidiOut: short write\n");
322 memmove(&data[0], &data[err], err);
326 snd_rawmidi_drain (_device);
329 pthread_mutex_unlock (&_notify_mutex);
330 _DEBUGPRINT("AlsaRawMidiOut: MIDI OUT THREAD STOPPED\n");
335 ///////////////////////////////////////////////////////////////////////////////
337 AlsaRawMidiIn::AlsaRawMidiIn (const char *device)
338 : AlsaRawMidiIO (device, true)
341 , _unbuffered_bytes(0)
349 AlsaRawMidiIn::recv_event (pframes_t &time, uint8_t *data, size_t &size)
351 const uint32_t read_space = _rb->read_space();
352 struct MidiEventHeader h(0,0);
354 if (read_space <= sizeof(MidiEventHeader)) {
359 // check if event is in current cycle
360 RingBuffer<uint8_t>::rw_vector vector;
361 _rb->get_read_vector(&vector);
362 if (vector.len[0] >= sizeof(MidiEventHeader)) {
363 memcpy((uint8_t*)&h, vector.buf[0], sizeof(MidiEventHeader));
365 if (vector.len[0] > 0) {
366 memcpy ((uint8_t*)&h, vector.buf[0], vector.len[0]);
368 memcpy (((uint8_t*)&h) + vector.len[0], vector.buf[1], sizeof(MidiEventHeader) - vector.len[0]);
371 if (h.time >= _clock_monotonic + _period_length_us ) {
373 printf("AlsaRawMidiIn DEBUG: POSTPONE EVENT TO NEXT CYCLE: %.1f spl\n", ((h.time - _clock_monotonic) / _sample_length_us));
377 _rb->increment_read_idx (sizeof(MidiEventHeader));
379 if (_rb->read ((uint8_t*)&h, sizeof(MidiEventHeader)) != sizeof(MidiEventHeader)) {
380 _DEBUGPRINT("AlsaRawMidiIn::recv_event Garbled MIDI EVENT HEADER!!\n");
386 _DEBUGPRINT("AlsaRawMidiIn::recv_event MIDI event too large!\n");
387 _rb->increment_read_idx (h.size);
390 if (_rb->read (&data[0], h.size) != h.size) {
391 _DEBUGPRINT("AlsaRawMidiIn::recv_event Garbled MIDI EVENT DATA!!\n");
394 if (h.time < _clock_monotonic) {
396 printf("AlsaRawMidiIn DEBUG: MIDI TIME < 0 %.1f spl\n", ((_clock_monotonic - h.time) / -_sample_length_us));
399 } else if (h.time >= _clock_monotonic + _period_length_us ) {
401 printf("AlsaRawMidiIn DEBUG: MIDI TIME > PERIOD %.1f spl\n", ((h.time - _clock_monotonic) / _sample_length_us));
403 time = _samples_per_period - 1;
405 time = floor ((h.time - _clock_monotonic) / _sample_length_us);
407 assert(time < _samples_per_period);
413 AlsaRawMidiIn::main_process_thread ()
417 unsigned short revents = 0;
419 int perr = poll (_pfds, _npfds, 100 /* ms */);
421 PBD::error << _("AlsaRawMidiIn: Error polling device. Terminating Midi Thread.") << endmsg;
428 if (snd_rawmidi_poll_descriptors_revents (_device, _pfds, _npfds, &revents)) {
429 PBD::error << _("AlsaRawMidiIn: Failed to poll device. Terminating Midi Thread.") << endmsg;
433 if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
434 PBD::error << _("AlsaRawMidiIn: poll error. Terminating Midi Thread.") << endmsg;
438 if (!(revents & POLLIN)) {
439 _DEBUGPRINT("AlsaRawMidiOut: POLLIN not ready.\n");
444 uint8_t data[MaxAlsaRawEventSize];
445 uint64_t time = g_get_monotonic_time();
446 ssize_t err = snd_rawmidi_read (_device, data, sizeof(data));
448 if ((err == -EAGAIN) || (err == -EWOULDBLOCK)) {
452 PBD::error << _("AlsaRawMidiIn: read error. Terminating Midi") << endmsg;
456 _DEBUGPRINT("AlsaRawMidiIn: zero read\n");
461 queue_event (time, data, err);
463 parse_events (time, data, err);
467 _DEBUGPRINT("AlsaRawMidiIn: MIDI IN THREAD STOPPED\n");
472 AlsaRawMidiIn::queue_event (const uint64_t time, const uint8_t *data, const size_t size) {
473 const uint32_t buf_size = sizeof(MidiEventHeader) + size;
474 _event._pending = false;
478 if (_rb->write_space() < buf_size) {
479 _DEBUGPRINT("AlsaRawMidiIn: ring buffer overflow\n");
482 struct MidiEventHeader h (time, size);
483 _rb->write ((uint8_t*) &h, sizeof(MidiEventHeader));
484 _rb->write (data, size);
489 AlsaRawMidiIn::parse_events (const uint64_t time, const uint8_t *data, const size_t size) {
490 if (_event._pending) {
491 if (queue_event (_event._time, _parser_buffer, _event._size)) {
495 for (size_t i = 0; i < size; ++i) {
496 if (_first_time && !(data[i] & 0x80)) {
499 _first_time = false; /// TODO optimize e.g. use fn pointer to different parse_events()
500 if (process_byte(time, data[i])) {
501 if (queue_event (_event._time, _parser_buffer, _event._size)) {
508 // based on JackMidiRawInputWriteQueue by Devin Anderson //
510 AlsaRawMidiIn::process_byte(const uint64_t time, const uint8_t byte)
517 _parser_buffer[0] = byte;
518 prepare_byte_event(time, byte);
523 if (_status_byte == 0xf0) {
525 return prepare_buffered_event(time);
528 _unbuffered_bytes = 0;
534 // Non-realtime status byte
537 _unbuffered_bytes = 0;
540 switch (byte & 0xf0) {
546 // Note On, Note Off, Aftertouch, Control Change, Pitch Wheel
551 // Program Change, Channel Pressure
562 // MTC Quarter Frame, Song Select
577 prepare_byte_event(time, byte);
587 if (! _status_byte) {
588 // Data bytes without a status will be discarded.
593 if (! _total_bytes) {
594 // Apply running status.
595 record_byte(_status_byte);
598 return (_total_bytes == _expected_bytes) ? prepare_buffered_event(time) : false;