diff options
author | Robin Gareus <robin@gareus.org> | 2019-01-14 22:07:51 +0100 |
---|---|---|
committer | Robin Gareus <robin@gareus.org> | 2019-01-14 22:33:31 +0100 |
commit | 8b71967be9c35213cb670d3057ffdd699fe23af3 (patch) | |
tree | 0537b648d8fc3bc9f1ef58c90e3ba5ad18b61f28 /libs/backends/alsa/alsa_audiobackend.cc | |
parent | 8f9e63575fe527eb1cbeceda7565da189e00948b (diff) |
ALSA: add locks to safely add/remove MIDI devices
Theoretically this could be lock-free by using a queue of device
ports to be added/remove in sync in the process-callback, but
realistically adding/removing devices doesn't have to be rt-safe.
Diffstat (limited to 'libs/backends/alsa/alsa_audiobackend.cc')
-rw-r--r-- | libs/backends/alsa/alsa_audiobackend.cc | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/libs/backends/alsa/alsa_audiobackend.cc b/libs/backends/alsa/alsa_audiobackend.cc index 3266853bca..1355197522 100644 --- a/libs/backends/alsa/alsa_audiobackend.cc +++ b/libs/backends/alsa/alsa_audiobackend.cc @@ -78,6 +78,7 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info) { _instance_name = s_instance_name; pthread_mutex_init (&_port_callback_mutex, 0); + pthread_mutex_init (&_device_port_mutex, 0); _input_audio_device_info.valid = false; _output_audio_device_info.valid = false; @@ -87,6 +88,7 @@ AlsaAudioBackend::AlsaAudioBackend (AudioEngine& e, AudioBackendInfo& info) AlsaAudioBackend::~AlsaAudioBackend () { pthread_mutex_destroy (&_port_callback_mutex); + pthread_mutex_destroy (&_device_port_mutex); } /* AUDIOBACKEND API */ @@ -474,6 +476,7 @@ AlsaAudioBackend::update_systemic_audio_latencies () void AlsaAudioBackend::update_systemic_midi_latencies () { + pthread_mutex_lock (&_device_port_mutex); uint32_t i = 0; for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it, ++i) { assert (_rmidi_out.size() > i); @@ -495,6 +498,7 @@ AlsaAudioBackend::update_systemic_midi_latencies () lr.min = lr.max = (_measure_latency ? 0 : nfo->systemic_input_latency); set_latency_range (*it, true, lr); } + pthread_mutex_unlock (&_device_port_mutex); update_latencies (); } @@ -682,6 +686,7 @@ AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable register_system_midi_ports(device); } else { // remove all ports provided by the given device + pthread_mutex_lock (&_device_port_mutex); uint32_t i = 0; for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end ();) { assert (_rmidi_out.size() > i); @@ -705,6 +710,7 @@ AlsaAudioBackend::set_midi_device_enabled (std::string const device, bool enable _rmidi_in.erase (_rmidi_in.begin() + i); delete rm; } + pthread_mutex_unlock (&_device_port_mutex); } update_systemic_midi_latencies (); } @@ -1540,12 +1546,14 @@ AlsaAudioBackend::update_system_port_latecies () (*it)->update_connected_latency (false); } + pthread_mutex_lock (&_device_port_mutex); for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) { (*it)->update_connected_latency (true); } for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) { (*it)->update_connected_latency (false); } + pthread_mutex_unlock (&_device_port_mutex); for (AudioSlaves::iterator s = _slaves.begin (); s != _slaves.end (); ++s) { if ((*s)->dead) { @@ -1648,7 +1656,9 @@ AlsaAudioBackend::register_system_midi_ports(const std::string device) static_cast<AlsaMidiPort*>(p)->set_n_periods(_periods_per_cycle); // TODO check MIDI alignment AlsaPort *ap = static_cast<AlsaPort*>(p); ap->set_pretty_name (replace_name_io (i->first, false)); + pthread_mutex_lock (&_device_port_mutex); _system_midi_out.push_back (ap); + pthread_mutex_unlock (&_device_port_mutex); _rmidi_out.push_back (mout); } } @@ -1687,7 +1697,9 @@ AlsaAudioBackend::register_system_midi_ports(const std::string device) set_latency_range (p, false, lr); AlsaPort *ap = static_cast<AlsaPort*>(p); ap->set_pretty_name (replace_name_io (i->first, true)); + pthread_mutex_lock (&_device_port_mutex); _system_midi_in.push_back (ap); + pthread_mutex_unlock (&_device_port_mutex); _rmidi_in.push_back (midin); } } @@ -2170,6 +2182,8 @@ AlsaAudioBackend::main_process_thread () } } + /* only used when adding/removing MIDI device/system ports */ + pthread_mutex_lock (&_device_port_mutex); /* de-queue incoming midi*/ i = 0; for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) { @@ -2186,6 +2200,7 @@ AlsaAudioBackend::main_process_thread () } rm->sync_time (clock1); } + pthread_mutex_unlock (&_device_port_mutex); for (std::vector<AlsaPort*>::const_iterator it = _system_outputs.begin (); it != _system_outputs.end (); ++it) { memset ((*it)->get_buffer (_samples_per_period), 0, _samples_per_period * sizeof (Sample)); @@ -2199,6 +2214,8 @@ AlsaAudioBackend::main_process_thread () return 0; } + /* only used when adding/removing MIDI device/system ports */ + pthread_mutex_lock (&_device_port_mutex); for (std::vector<AlsaPort*>::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) { static_cast<AlsaMidiPort*>(*it)->next_period(); } @@ -2214,6 +2231,7 @@ AlsaAudioBackend::main_process_thread () rm->send_event (mit->timestamp (), mit->data (), mit->size ()); } } + pthread_mutex_unlock (&_device_port_mutex); /* write back audio */ i = 0; @@ -2265,6 +2283,7 @@ AlsaAudioBackend::main_process_thread () clock1 = g_get_monotonic_time(); uint32_t i = 0; + pthread_mutex_lock (&_device_port_mutex); for (std::vector<AlsaPort*>::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) { static_cast<AlsaMidiBuffer*>((*it)->get_buffer(0))->clear (); AlsaMidiIn *rm = _rmidi_in.at(i); @@ -2280,6 +2299,7 @@ AlsaAudioBackend::main_process_thread () } rm->sync_time (clock1); } + pthread_mutex_unlock (&_device_port_mutex); _last_process_start = 0; if (engine.process_callback (_samples_per_period)) { @@ -2289,10 +2309,12 @@ AlsaAudioBackend::main_process_thread () } // drop all outgoing MIDI messages + pthread_mutex_lock (&_device_port_mutex); for (std::vector<AlsaPort*>::const_iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) { - void *bptr = (*it)->get_buffer(0); - midi_clear(bptr); + void *bptr = (*it)->get_buffer(0); + midi_clear(bptr); } + pthread_mutex_unlock (&_device_port_mutex); _dsp_load = 1.0; reset_dll = true; |