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::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::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::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it) { (*it)->update_connected_latency (true); } for (std::vector::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(p)->set_n_periods(_periods_per_cycle); // TODO check MIDI alignment AlsaPort *ap = static_cast(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(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::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::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::iterator it = _system_midi_out.begin (); it != _system_midi_out.end (); ++it) { static_cast(*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::const_iterator it = _system_midi_in.begin (); it != _system_midi_in.end (); ++it, ++i) { static_cast((*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::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; diff --git a/libs/backends/alsa/alsa_audiobackend.h b/libs/backends/alsa/alsa_audiobackend.h index ef218b49a1..e04c72e561 100644 --- a/libs/backends/alsa/alsa_audiobackend.h +++ b/libs/backends/alsa/alsa_audiobackend.h @@ -393,6 +393,8 @@ class AlsaAudioBackend : public AudioBackend { pthread_t _midi_device_thread_id; bool _midi_device_thread_active; + pthread_mutex_t _device_port_mutex; + /* processing */ float _dsp_load; ARDOUR::DSPLoadCalculator _dsp_load_calc;