fix device-list update concurrency issue.

It may happen that during push_state_to_backend() a device is
reconfigured in a way that triggers a "Device Changed" callback before
the engine is started. This callback can trigger a change to the
configuration that will be used when the engine is actually started.

This has been seen on OSX in conjunction with Aggregate Devices
(even if the aggregate is not used, but the device which is used
is also part of an aggregate) 

example: HW changed callback arrives, device-list is re-populated,
*A*irplay" is at the top of the list, Airplay supports only 44.1K,
Samplerate changes... later save also writes this new rate to the file.
This commit is contained in:
Robin Gareus 2016-01-29 01:12:32 +01:00
parent cf558ee18c
commit c0a843a905
2 changed files with 7 additions and 1 deletions

View File

@ -96,6 +96,7 @@ EngineControl::EngineControl ()
, lm_running (false)
, midi_back_button (_("Back to settings"))
, ignore_changes (0)
, ignore_device_changes (0)
, _desired_sample_rate (0)
, started_at_least_once (false)
, queue_device_changed (false)
@ -2220,6 +2221,7 @@ EngineControl::push_state_to_backend (bool start)
{
DEBUG_ECONTROL ("push_state_to_backend");
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
PBD::Unwinder<uint32_t> protect_ignore_device_changes (ignore_device_changes, ignore_device_changes + 1);
if (!backend) {
return 0;
@ -3041,6 +3043,9 @@ EngineControl::engine_stopped ()
void
EngineControl::device_list_changed ()
{
if (ignore_device_changes) {
return;
}
PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1); // ??
list_devices ();
midi_option_changed();

View File

@ -120,7 +120,8 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
Gtk::CheckButton aj_button;
uint32_t ignore_changes;
uint32_t ignore_changes; // state save/load
uint32_t ignore_device_changes; // AudioEngine::DeviceListChanged
uint32_t _desired_sample_rate;
bool started_at_least_once;
bool queue_device_changed;