Extract part of EngineControl::backend_changed into EngineControl::update_midi_options
[ardour.git] / gtk2_ardour / engine_dialog.cc
index 866f6e563f8dacd0283689e84c3250eb96075943..28e0adcdca97155c5bd2eca768a56c74d3d08842 100644 (file)
@@ -49,6 +49,7 @@
 #include "pbd/error.h"
 
 #include "opts.h"
+#include "debug.h"
 #include "ardour_ui.h"
 #include "engine_dialog.h"
 #include "gui_thread.h"
@@ -62,6 +63,8 @@ using namespace PBD;
 using namespace Glib;
 using namespace ARDOUR_UI_UTILS;
 
+#define DEBUG_ECONTROL(msg) DEBUG_TRACE (PBD::DEBUG::EngineControl, string_compose ("%1: %2\n", __LINE__, msg));
+
 static const unsigned int midi_tab = 2;
 static const unsigned int latency_tab = 1; /* zero-based, page zero is the main setup page */
 
@@ -95,6 +98,7 @@ EngineControl::EngineControl ()
        , _desired_sample_rate (0)
        , started_at_least_once (false)
        , queue_device_changed (false)
+       , block_signals(0)
 {
        using namespace Notebook_Helpers;
        vector<string> backend_names;
@@ -176,8 +180,6 @@ EngineControl::EngineControl ()
        lm_table.attach (*misc_align, 1, 3, row, row+1, FILL, (AttachOptions) 0);
        ++row;
 
-       xopt = AttachOptions(0);
-
        lm_measure_label.set_padding (10, 10);
        lm_measure_button.add (lm_measure_label);
        lm_measure_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::latency_button_clicked));
@@ -299,29 +301,99 @@ EngineControl::EngineControl ()
                backend_changed ();
        }
 
+       connect_changed_signals ();
 
-       /* Connect to signals */
+       notebook.signal_switch_page().connect (sigc::mem_fun (*this, &EngineControl::on_switch_page));
 
-       backend_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::backend_changed));
-       driver_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::driver_changed));
-       sample_rate_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::sample_rate_changed));
-       buffer_size_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::buffer_size_changed));
-       device_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::device_changed));
-       midi_option_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::midi_option_changed));
+       connect_disconnect_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::connect_disconnect_click));
+       connect_disconnect_button.set_no_show_all();
 
-       input_device_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::input_device_changed));
-       output_device_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::output_device_changed));
+}
 
-       input_latency.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::parameter_changed));
-       output_latency.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::parameter_changed));
-       input_channels.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::parameter_changed));
-       output_channels.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::parameter_changed));
+void
+EngineControl::connect_changed_signals ()
+{
+       backend_combo_connection = backend_combo.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::backend_changed));
+       driver_combo_connection = driver_combo.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::driver_changed));
+       sample_rate_combo_connection = sample_rate_combo.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::sample_rate_changed));
+       buffer_size_combo_connection = buffer_size_combo.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::buffer_size_changed));
+       device_combo_connection = device_combo.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::device_changed));
+       midi_option_combo_connection = midi_option_combo.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::midi_option_changed));
+
+       input_device_combo_connection = input_device_combo.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::input_device_changed));
+       output_device_combo_connection = output_device_combo.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::output_device_changed));
+
+       input_latency_connection = input_latency.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::parameter_changed));
+       output_latency_connection = output_latency.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::parameter_changed));
+       input_channels_connection = input_channels.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::parameter_changed));
+       output_channels_connection = output_channels.signal_changed ().connect (
+           sigc::mem_fun (*this, &EngineControl::parameter_changed));
+}
 
-       notebook.signal_switch_page().connect (sigc::mem_fun (*this, &EngineControl::on_switch_page));
+void
+EngineControl::block_changed_signals ()
+{
+       if (block_signals++ == 0) {
+               DEBUG_ECONTROL ("Blocking changed signals");
+               backend_combo_connection.block ();
+               driver_combo_connection.block ();
+               sample_rate_combo_connection.block ();
+               buffer_size_combo_connection.block ();
+               device_combo_connection.block ();
+               input_device_combo_connection.block ();
+               output_device_combo_connection.block ();
+               midi_option_combo_connection.block ();
+               input_latency_connection.block ();
+               output_latency_connection.block ();
+               input_channels_connection.block ();
+               output_channels_connection.block ();
+       }
+}
 
-       connect_disconnect_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::connect_disconnect_click));
-       connect_disconnect_button.set_no_show_all();
+void
+EngineControl::unblock_changed_signals ()
+{
+       if (--block_signals == 0) {
+               DEBUG_ECONTROL ("Unblocking changed signals");
+               backend_combo_connection.unblock ();
+               driver_combo_connection.unblock ();
+               sample_rate_combo_connection.unblock ();
+               buffer_size_combo_connection.unblock ();
+               device_combo_connection.unblock ();
+               input_device_combo_connection.unblock ();
+               output_device_combo_connection.unblock ();
+               midi_option_combo_connection.unblock ();
+               input_latency_connection.unblock ();
+               output_latency_connection.unblock ();
+               input_channels_connection.unblock ();
+               output_channels_connection.unblock ();
+       }
+}
+
+EngineControl::SignalBlocker::SignalBlocker (EngineControl& engine_control,
+                                             const std::string& reason)
+    : ec (engine_control)
+    , m_reason (reason)
+{
+       DEBUG_ECONTROL (string_compose ("SignalBlocker: %1", m_reason));
+       ec.block_changed_signals ();
+}
 
+EngineControl::SignalBlocker::~SignalBlocker ()
+{
+       DEBUG_ECONTROL (string_compose ("~SignalBlocker: %1", m_reason));
+       ec.unblock_changed_signals ();
 }
 
 void
@@ -333,8 +405,6 @@ EngineControl::on_show ()
                backend_changed ();
        }
        device_changed ();
-       input_device_changed ();
-       output_device_changed ();
        ok_button->grab_focus();
 }
 
@@ -751,14 +821,11 @@ EngineControl::refresh_midi_display (std::string focus)
        }
 }
 
-void
-EngineControl::update_sensitivity ()
-{
-}
-
 void
 EngineControl::backend_changed ()
 {
+       DEBUG_ECONTROL ("backend_changed");
+
        string backend_name = backend_combo.get_active_text();
        boost::shared_ptr<ARDOUR::AudioBackend> backend;
 
@@ -768,6 +835,8 @@ EngineControl::backend_changed ()
                return;
        }
 
+       DEBUG_ECONTROL (string_compose ("Backend name: %1", backend_name));
+
        _have_control = ARDOUR::AudioEngine::instance()->setup_required ();
 
        build_notebook ();
@@ -783,6 +852,8 @@ EngineControl::backend_changed ()
                                string current_driver;
                                current_driver = backend->driver_name ();
 
+                               DEBUG_ECONTROL (string_compose ("backend->driver_name: %1", current_driver));
+
                                // driver might not have been set yet
                                if (current_driver == "") {
                                        current_driver = driver_combo.get_active_text ();
@@ -793,6 +864,8 @@ EngineControl::backend_changed ()
 
                                PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
                                set_popdown_strings (driver_combo, drivers);
+                               DEBUG_ECONTROL (
+                                   string_compose ("driver_combo.set_active_text: %1", current_driver));
                                driver_combo.set_active_text (current_driver);
                        }
 
@@ -807,6 +880,23 @@ EngineControl::backend_changed ()
                list_devices ();
        }
 
+       update_midi_options ();
+
+       connect_disconnect_button.hide();
+
+       midi_option_changed();
+
+       started_at_least_once = false;
+
+       if (!ignore_changes) {
+               maybe_display_saved_state ();
+       }
+}
+
+void
+EngineControl::update_midi_options ()
+{
+       boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        vector<string> midi_options = backend->enumerate_midi_options();
 
        if (midi_options.size() == 1) {
@@ -821,16 +911,6 @@ EngineControl::backend_changed ()
                        midi_option_combo.set_sensitive (false);
                }
        }
-
-       connect_disconnect_button.hide();
-
-       midi_option_changed();
-
-       started_at_least_once = false;
-
-       if (!ignore_changes) {
-               maybe_display_saved_state ();
-       }
 }
 
 bool
@@ -854,6 +934,7 @@ EngineControl::print_channel_count (Gtk::SpinButton* sb)
 bool
 EngineControl::set_driver_popdown_strings ()
 {
+       DEBUG_ECONTROL ("set_driver_popdown_strings");
        string backend_name = backend_combo.get_active_text();
        boost::shared_ptr<ARDOUR::AudioBackend> backend;
 
@@ -872,6 +953,7 @@ EngineControl::set_driver_popdown_strings ()
 bool
 EngineControl::set_device_popdown_strings ()
 {
+       DEBUG_ECONTROL ("set_device_popdown_strings");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_devices ();
 
@@ -892,7 +974,6 @@ EngineControl::set_device_popdown_strings ()
 
 
        if (!available_devices.empty()) {
-               update_sensitivity ();
 
                {
                        string current_device, found_device;
@@ -914,11 +995,10 @@ EngineControl::set_device_popdown_strings ()
 
                        PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
                        set_popdown_strings (device_combo, available_devices);
+                       DEBUG_ECONTROL (string_compose ("set device_combo active text: %1", current_device));
 
                        device_combo.set_active_text (current_device);
                }
-
-               device_changed ();
                return true;
        }
        return false;
@@ -928,6 +1008,7 @@ EngineControl::set_device_popdown_strings ()
 bool
 EngineControl::set_input_device_popdown_strings ()
 {
+       DEBUG_ECONTROL ("set_input_device_popdown_strings");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_input_devices ();
 
@@ -938,7 +1019,6 @@ EngineControl::set_input_device_popdown_strings ()
        }
 
        if (!available_devices.empty()) {
-               update_sensitivity ();
 
                {
                        string current_device, found_device;
@@ -961,10 +1041,9 @@ EngineControl::set_input_device_popdown_strings ()
                        PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
                        set_popdown_strings (input_device_combo, available_devices);
 
+                       DEBUG_ECONTROL (string_compose ("set input_device_combo active text: %1", current_device));
                        input_device_combo.set_active_text (current_device);
                }
-
-               input_device_changed ();
                return true;
        }
 
@@ -975,6 +1054,7 @@ EngineControl::set_input_device_popdown_strings ()
 bool
 EngineControl::set_output_device_popdown_strings ()
 {
+       DEBUG_ECONTROL ("set_output_device_popdown_strings");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_output_devices ();
 
@@ -985,7 +1065,6 @@ EngineControl::set_output_device_popdown_strings ()
        }
 
        if (!available_devices.empty()) {
-               update_sensitivity ();
 
                {
                        string current_device, found_device;
@@ -1008,10 +1087,9 @@ EngineControl::set_output_device_popdown_strings ()
                        PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
                        set_popdown_strings (output_device_combo, available_devices);
 
+                       DEBUG_ECONTROL (string_compose ("set input_device_combo active text: %1", current_device));
                        output_device_combo.set_active_text (current_device);
                }
-
-               output_device_changed ();
                return true;
        }
 
@@ -1021,6 +1099,7 @@ EngineControl::set_output_device_popdown_strings ()
 void
 EngineControl::list_devices ()
 {
+       DEBUG_ECONTROL ("list_devices");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        assert (backend);
 
@@ -1037,6 +1116,8 @@ EngineControl::list_devices ()
        }
 
        if (devices_available) {
+               device_changed ();
+
                input_latency.set_sensitive (true);
                output_latency.set_sensitive (true);
                input_channels.set_sensitive (true);
@@ -1075,6 +1156,7 @@ EngineControl::list_devices ()
 void
 EngineControl::driver_changed ()
 {
+       DEBUG_ECONTROL ("driver_changed");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        assert (backend);
 
@@ -1089,6 +1171,7 @@ EngineControl::driver_changed ()
 void
 EngineControl::set_samplerate_popdown_strings (const std::string& device_name)
 {
+       DEBUG_ECONTROL ("set_samplerate_popdown_strings");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        string desired;
        vector<float> sr;
@@ -1134,6 +1217,7 @@ EngineControl::set_samplerate_popdown_strings (const std::string& device_name)
 void
 EngineControl::set_buffersize_popdown_strings (const std::string& device_name)
 {
+       DEBUG_ECONTROL ("set_buffersize_popdown_strings");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        vector<uint32_t> bs;
        vector<string> s;
@@ -1161,6 +1245,7 @@ EngineControl::set_buffersize_popdown_strings (const std::string& device_name)
        if (!s.empty()) {
                buffer_size_combo.set_sensitive (true);
                set_popdown_strings (buffer_size_combo, s);
+               buffer_size_combo.set_active_text (s.front());
 
                uint32_t period = backend->buffer_size();
                if (0 == period) {
@@ -1176,6 +1261,7 @@ EngineControl::set_buffersize_popdown_strings (const std::string& device_name)
 void
 EngineControl::device_changed ()
 {
+       DEBUG_ECONTROL ("device_changed");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        assert (backend);
 
@@ -1239,63 +1325,15 @@ EngineControl::device_changed ()
 void
 EngineControl::input_device_changed ()
 {
-       boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
-       assert (backend);
-       string input_device_name = input_device_combo.get_active_text ();
-
-       if (!ignore_changes && input_device_name != backend->input_device_name()) {
-               queue_device_changed = true;
-       }
-
-       backend->set_input_device_name(input_device_name);
-
-       {
-               PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
-
-               set_samplerate_popdown_strings (input_device_name);
-               set_buffersize_popdown_strings (input_device_name);
-               /* XXX theoretically need to set min + max channel counts here
-               */
-
-               manage_control_app_sensitivity ();
-       }
-
-       /* pick up any saved state for this device */
-
-       if (!ignore_changes) {
-               maybe_display_saved_state ();
-       }
+       DEBUG_ECONTROL ("input_device_changed");
+       device_changed ();
 }
 
 void
 EngineControl::output_device_changed ()
 {
-       boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
-       assert (backend);
-       string output_device_name = output_device_combo.get_active_text ();
-
-       if (!ignore_changes && output_device_name != backend->output_device_name()) {
-               queue_device_changed = true;
-       }
-
-       backend->set_output_device_name(output_device_name);
-
-       {
-               PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
-
-               set_samplerate_popdown_strings (output_device_name);
-               set_buffersize_popdown_strings (output_device_name);
-               /* XXX theoretically need to set min + max channel counts here
-               */
-
-               manage_control_app_sensitivity ();
-       }
-
-       /* pick up any saved state for this device */
-
-       if (!ignore_changes) {
-               maybe_display_saved_state ();
-       }
+       DEBUG_ECONTROL ("output_device_changed");
+       device_changed ();
 }
 
 string
@@ -1312,6 +1350,7 @@ EngineControl::bufsize_as_string (uint32_t sz)
 void
 EngineControl::sample_rate_changed ()
 {
+       DEBUG_ECONTROL ("sample_rate_changed");
        /* reset the strings for buffer size to show the correct msec value
           (reflecting the new sample rate).
         */
@@ -1323,13 +1362,14 @@ EngineControl::sample_rate_changed ()
 void
 EngineControl::buffer_size_changed ()
 {
+       DEBUG_ECONTROL ("buffer_size_changed");
        show_buffer_duration ();
 }
 
 void
 EngineControl::show_buffer_duration ()
 {
-
+       DEBUG_ECONTROL ("show_buffer_duration");
        /* buffer sizes  - convert from just samples to samples + msecs for
         * the displayed string
         */
@@ -1363,6 +1403,7 @@ EngineControl::show_buffer_duration ()
 void
 EngineControl::midi_option_changed ()
 {
+       DEBUG_ECONTROL ("midi_option_changed");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
        assert (backend);
 
@@ -1765,35 +1806,45 @@ EngineControl::set_state (const XMLNode& root)
        for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
 
                if ((*i)->active) {
-                       PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
-                       backend_combo.set_active_text ((*i)->backend);
-
-                       /* The driver popdown strings need to be populated now so that
-                        * set_active_text will actually set a valid entry. Then
-                        * backend_changed() will populate all the other combo's so they
-                        * can also be set to valid entries and the state will be restored
-                        * correctly.
-                        */
-                       set_driver_popdown_strings ();
-                       driver_combo.set_active_text ((*i)->driver);
-                       backend_changed ();
-
-                       device_combo.set_active_text ((*i)->device);
-                       input_device_combo.set_active_text ((*i)->input_device);
-                       output_device_combo.set_active_text ((*i)->output_device);
-                       sample_rate_combo.set_active_text (rate_as_string ((*i)->sample_rate));
-                       set_active_text_if_present (buffer_size_combo, bufsize_as_string ((*i)->buffer_size));
-                       input_latency.set_value ((*i)->input_latency);
-                       output_latency.set_value ((*i)->output_latency);
-                       midi_option_combo.set_active_text ((*i)->midi_option);
+                       set_current_state (*i);
                        break;
                }
        }
 }
 
+void
+EngineControl::set_current_state (const State& state)
+{
+       DEBUG_ECONTROL ("set_current_state");
+       PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
+       backend_combo.set_active_text (state->backend);
+
+       /* The driver popdown strings need to be populated now so that
+        * set_active_text will actually set a valid entry. Then
+        * backend_changed() will populate all the other combo's so they
+        * can also be set to valid entries and the state will be restored
+        * correctly.
+        */
+       if (!state->driver.empty()) {
+               set_driver_popdown_strings ();
+       }
+       driver_combo.set_active_text (state->driver);
+       backend_changed ();
+
+       device_combo.set_active_text (state->device);
+       input_device_combo.set_active_text (state->input_device);
+       output_device_combo.set_active_text (state->output_device);
+       sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
+       set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
+       input_latency.set_value (state->input_latency);
+       output_latency.set_value (state->output_latency);
+       midi_option_combo.set_active_text (state->midi_option);
+}
+
 int
 EngineControl::push_state_to_backend (bool start)
 {
+       DEBUG_ECONTROL ("push_state_to_backend");
        boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
 
        if (!backend) {
@@ -2243,8 +2294,6 @@ EngineControl::set_desired_sample_rate (uint32_t sr)
 {
        _desired_sample_rate = sr;
        device_changed ();
-       input_device_changed ();
-       output_device_changed ();
 }
 
 void