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.
This commit is contained in:
parent
8f9e63575f
commit
8b71967be9
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user