rework raw-midi drain strategy (workaround for sync devices)

This commit is contained in:
Robin Gareus 2014-06-19 19:42:19 +02:00
parent 157161e482
commit bc67e47048
3 changed files with 30 additions and 6 deletions

View file

@ -1429,7 +1429,7 @@ AlsaAudioBackend::main_process_thread ()
static_cast<AlsaMidiPort*>(*it)->next_period(); static_cast<AlsaMidiPort*>(*it)->next_period();
} }
/* queue midi*/ /* queue midi */
i = 0; i = 0;
for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) { for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) {
assert (_rmidi_out.size() > i); assert (_rmidi_out.size() > i);

View file

@ -57,6 +57,7 @@ AlsaRawMidiIO::AlsaRawMidiIO (const char *device, const bool input)
AlsaRawMidiIO::~AlsaRawMidiIO () AlsaRawMidiIO::~AlsaRawMidiIO ()
{ {
if (_device) { if (_device) {
snd_rawmidi_drain (_device);
snd_rawmidi_close (_device); snd_rawmidi_close (_device);
_device = 0; _device = 0;
} }
@ -243,6 +244,7 @@ AlsaRawMidiOut::main_process_thread ()
{ {
_running = true; _running = true;
pthread_mutex_lock (&_notify_mutex); pthread_mutex_lock (&_notify_mutex);
bool need_drain = false;
while (_running) { while (_running) {
bool have_data = false; bool have_data = false;
struct MidiEventHeader h(0,0); struct MidiEventHeader h(0,0);
@ -269,13 +271,22 @@ AlsaRawMidiOut::main_process_thread ()
} }
if (!have_data) { if (!have_data) {
if (need_drain) {
snd_rawmidi_drain (_device);
need_drain = false;
}
pthread_cond_wait (&_notify_ready, &_notify_mutex); pthread_cond_wait (&_notify_ready, &_notify_mutex);
continue; continue;
} }
uint64_t now = g_get_monotonic_time(); uint64_t now = g_get_monotonic_time();
while (h.time > now + 500) { while (h.time > now + 500) {
select_sleep(h.time - now); if (need_drain) {
snd_rawmidi_drain (_device);
need_drain = false;
} else {
select_sleep(h.time - now);
}
now = g_get_monotonic_time(); now = g_get_monotonic_time();
} }
@ -309,7 +320,11 @@ retry:
ssize_t err = snd_rawmidi_write (_device, data, h.size); ssize_t err = snd_rawmidi_write (_device, data, h.size);
if ((err == -EAGAIN) || (err == -EWOULDBLOCK)) { if ((err == -EAGAIN)) {
snd_rawmidi_drain (_device);
goto retry;
}
if (err == -EWOULDBLOCK) {
select_sleep (1000); select_sleep (1000);
goto retry; goto retry;
} }
@ -323,7 +338,7 @@ retry:
h.size -= err; h.size -= err;
goto retry; goto retry;
} }
snd_rawmidi_drain (_device); need_drain = true;
} }
pthread_mutex_unlock (&_notify_mutex); pthread_mutex_unlock (&_notify_mutex);
@ -472,6 +487,7 @@ int
AlsaRawMidiIn::queue_event (const uint64_t time, const uint8_t *data, const size_t size) { AlsaRawMidiIn::queue_event (const uint64_t time, const uint8_t *data, const size_t size) {
const uint32_t buf_size = sizeof(MidiEventHeader) + size; const uint32_t buf_size = sizeof(MidiEventHeader) + size;
_event._pending = false; _event._pending = false;
if (size == 0) { if (size == 0) {
return -1; return -1;
} }
@ -488,6 +504,7 @@ AlsaRawMidiIn::queue_event (const uint64_t time, const uint8_t *data, const size
void void
AlsaRawMidiIn::parse_events (const uint64_t time, const uint8_t *data, const size_t size) { AlsaRawMidiIn::parse_events (const uint64_t time, const uint8_t *data, const size_t size) {
if (_event._pending) { if (_event._pending) {
_DEBUGPRINT("AlsaRawMidiIn: queue pending event\n");
if (queue_event (_event._time, _parser_buffer, _event._size)) { if (queue_event (_event._time, _parser_buffer, _event._size)) {
return; return;
} }
@ -533,6 +550,13 @@ AlsaRawMidiIn::process_byte(const uint64_t time, const uint8_t byte)
if (byte >= 0x80) { if (byte >= 0x80) {
// Non-realtime status byte // Non-realtime status byte
if (_total_bytes) { if (_total_bytes) {
_DEBUGPRINT("AlsaRawMidiIn: discarded bogus midi message\n");
#if 0
for (size_t i=0; i < _total_bytes; ++i) {
printf("%02x ", _parser_buffer[i]);
}
printf("\n");
#endif
_total_bytes = 0; _total_bytes = 0;
_unbuffered_bytes = 0; _unbuffered_bytes = 0;
} }
@ -591,7 +615,7 @@ AlsaRawMidiIn::process_byte(const uint64_t time, const uint8_t byte)
return false; return false;
} }
if (! _total_bytes) { if (! _total_bytes) {
// Apply running status. _DEBUGPRINT("AlsaRawMidiIn: apply running status\n");
record_byte(_status_byte); record_byte(_status_byte);
} }
record_byte(byte); record_byte(byte);

View file

@ -114,7 +114,7 @@ private:
} }
bool prepare_buffered_event(const uint64_t time) { bool prepare_buffered_event(const uint64_t time) {
const bool result = !_unbuffered_bytes; const bool result = _unbuffered_bytes == 0;
if (result) { if (result) {
_event.prepare(time, _total_bytes); _event.prepare(time, _total_bytes);
} }