summaryrefslogtreecommitdiff
path: root/libs/backends/alsa/alsa_audiobackend.cc
diff options
context:
space:
mode:
authorRobin Gareus <robin@gareus.org>2019-01-14 22:07:51 +0100
committerRobin Gareus <robin@gareus.org>2019-01-14 22:33:31 +0100
commit8b71967be9c35213cb670d3057ffdd699fe23af3 (patch)
tree0537b648d8fc3bc9f1ef58c90e3ba5ad18b61f28 /libs/backends/alsa/alsa_audiobackend.cc
parent8f9e63575fe527eb1cbeceda7565da189e00948b (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.cc26
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;