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)
340 , _unbuffered_bytes(0)
348 AlsaRawMidiIn::recv_event (pframes_t &time, uint8_t *data, size_t &size)
350 const uint32_t read_space = _rb->read_space();
351 struct MidiEventHeader h(0,0);
353 if (read_space <= sizeof(MidiEventHeader)) {
358 // check if event is in current cycle
359 RingBuffer<uint8_t>::rw_vector vector;
360 _rb->get_read_vector(&vector);
361 if (vector.len[0] >= sizeof(MidiEventHeader)) {
362 memcpy((uint8_t*)&h, vector.buf[0], sizeof(MidiEventHeader));
364 if (vector.len[0] > 0) {
365 memcpy ((uint8_t*)&h, vector.buf[0], vector.len[0]);
367 memcpy (((uint8_t*)&h) + vector.len[0], vector.buf[1], sizeof(MidiEventHeader) - vector.len[0]);
370 if (h.time >= _clock_monotonic + _period_length_us ) {
372 printf("AlsaRawMidiIn DEBUG: POSTPONE EVENT TO NEXT CYCLE: %.1f spl\n", ((h.time - _clock_monotonic) / _sample_length_us));
376 _rb->increment_read_idx (sizeof(MidiEventHeader));
378 if (_rb->read ((uint8_t*)&h, sizeof(MidiEventHeader)) != sizeof(MidiEventHeader)) {
379 _DEBUGPRINT("AlsaRawMidiIn::recv_event Garbled MIDI EVENT HEADER!!\n");
385 _DEBUGPRINT("AlsaRawMidiIn::recv_event MIDI event too large!\n");
386 _rb->increment_read_idx (h.size);
389 if (_rb->read (&data[0], h.size) != h.size) {
390 _DEBUGPRINT("AlsaRawMidiIn::recv_event Garbled MIDI EVENT DATA!!\n");
393 if (h.time < _clock_monotonic) {
395 printf("AlsaRawMidiIn DEBUG: MIDI TIME < 0 %.1f spl\n", ((_clock_monotonic - h.time) / -_sample_length_us));
398 } else if (h.time >= _clock_monotonic + _period_length_us ) {
400 printf("AlsaRawMidiIn DEBUG: MIDI TIME > PERIOD %.1f spl\n", ((h.time - _clock_monotonic) / _sample_length_us));
402 time = _samples_per_period - 1;
404 time = floor ((h.time - _clock_monotonic) / _sample_length_us);
406 assert(time < _samples_per_period);
412 AlsaRawMidiIn::main_process_thread ()
416 unsigned short revents = 0;
418 int perr = poll (_pfds, _npfds, 100 /* ms */);
420 PBD::error << _("AlsaRawMidiIn: Error polling device. Terminating Midi Thread.") << endmsg;
427 if (snd_rawmidi_poll_descriptors_revents (_device, _pfds, _npfds, &revents)) {
428 PBD::error << _("AlsaRawMidiIn: Failed to poll device. Terminating Midi Thread.") << endmsg;
432 if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
433 PBD::error << _("AlsaRawMidiIn: poll error. Terminating Midi Thread.") << endmsg;
437 if (!(revents & POLLIN)) {
438 _DEBUGPRINT("AlsaRawMidiOut: POLLIN not ready.\n");
443 uint8_t data[MaxAlsaRawEventSize];
444 uint64_t time = g_get_monotonic_time();
445 ssize_t err = snd_rawmidi_read (_device, data, sizeof(data));
447 if ((err == -EAGAIN) || (err == -EWOULDBLOCK)) {
451 PBD::error << _("AlsaRawMidiIn: read error. Terminating Midi") << endmsg;
455 _DEBUGPRINT("AlsaRawMidiIn: zero read\n");
460 queue_event (time, data, err);
462 parse_events (time, data, err);
466 _DEBUGPRINT("AlsaRawMidiIn: MIDI IN THREAD STOPPED\n");
471 AlsaRawMidiIn::queue_event (const uint64_t time, const uint8_t *data, const size_t size) {
472 const uint32_t buf_size = sizeof(MidiEventHeader) + size;
473 _event._pending = false;
474 if (_rb->write_space() < buf_size) {
475 _DEBUGPRINT("AlsaRawMidiIn: ring buffer overflow\n");
478 struct MidiEventHeader h (time, size);
479 _rb->write ((uint8_t*) &h, sizeof(MidiEventHeader));
480 _rb->write (data, size);
485 AlsaRawMidiIn::parse_events (const uint64_t time, const uint8_t *data, const size_t size) {
486 if (_event._pending) {
487 if (queue_event (_event._time, _parser_buffer, _event._size)) {
491 for (size_t i = 0; i < size; ++i) {
492 if (process_byte(time, data[i])) {
493 if (queue_event (_event._time, _parser_buffer, _event._size)) {
500 // based on JackMidiRawInputWriteQueue by Devin Anderson //
502 AlsaRawMidiIn::process_byte(const uint64_t time, const uint8_t byte)
509 _parser_buffer[0] = byte;
510 prepare_byte_event(time, byte);
515 if (_status_byte == 0xf0) {
517 return prepare_buffered_event(time);
520 _unbuffered_bytes = 0;
526 // Non-realtime status byte
529 _unbuffered_bytes = 0;
532 switch (byte & 0xf0) {
538 // Note On, Note Off, Aftertouch, Control Change, Pitch Wheel
543 // Program Change, Channel Pressure
554 // MTC Quarter Frame, Song Select
569 prepare_byte_event(time, byte);
579 if (! _status_byte) {
580 // Data bytes without a status will be discarded.
585 if (! _total_bytes) {
586 // Apply running status.
587 record_byte(_status_byte);
590 return (_total_bytes == _expected_bytes) ? prepare_buffered_event(time) : false;