diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc index f858f56b17..b5a59af642 100644 --- a/gtk2_ardour/engine_dialog.cc +++ b/gtk2_ardour/engine_dialog.cc @@ -63,7 +63,7 @@ EngineControl::EngineControl () , output_channels (output_channels_adjustment) , ports_adjustment (128, 8, 1024, 1, 16) , ports_spinner (ports_adjustment) - , realtime_button (_("Realtime")) + , control_app_button (_("Launch Control App")) , basic_packer (9, 3) { build_notebook (); @@ -71,6 +71,15 @@ EngineControl::EngineControl () get_vbox()->set_border_width (12); get_vbox()->pack_start (notebook); + Gtk::HBox* hpacker = manage (new HBox); + hpacker->pack_start (control_app_button, false, false); + hpacker->show (); + control_app_button.show(); + get_vbox()->pack_start (*hpacker); + + control_app_button.signal_clicked().connect (mem_fun (*this, &EngineControl::control_app_button_clicked)); + manage_control_app_sensitivity (); + add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); add_button (Gtk::Stock::APPLY, Gtk::RESPONSE_APPLY); @@ -347,6 +356,8 @@ EngineControl::device_changed () buffer_size_combo.set_active_text (s.front()); show_buffer_duration (); + manage_control_app_sensitivity (); + maybe_set_state (); } @@ -700,9 +711,12 @@ EngineControl::setup_engine (bool start) state->active = true; if (start) { - return ARDOUR::AudioEngine::instance()->start(); + if (ARDOUR::AudioEngine::instance()->start()) { + return -1; + } } + manage_control_app_sensitivity (); return 0; } catch (...) { @@ -773,3 +787,25 @@ EngineControl::get_device_name () const return device_combo.get_active_text (); } +void +EngineControl::control_app_button_clicked () +{ + boost::shared_ptr backend = ARDOUR::AudioEngine::instance()->current_backend(); + + if (!backend) { + return; + } + + backend->launch_control_app(); +} + +void +EngineControl::manage_control_app_sensitivity () +{ + boost::shared_ptr backend = ARDOUR::AudioEngine::instance()->current_backend(); + if (backend && backend->have_control_app()) { + control_app_button.set_sensitive (true); + } else { + control_app_button.set_sensitive (false); + } +} diff --git a/gtk2_ardour/engine_dialog.h b/gtk2_ardour/engine_dialog.h index deaa0afa54..97d41995fa 100644 --- a/gtk2_ardour/engine_dialog.h +++ b/gtk2_ardour/engine_dialog.h @@ -68,6 +68,8 @@ class EngineControl : public ArdourDialog { Gtk::Adjustment ports_adjustment; Gtk::SpinButton ports_spinner; + Gtk::Button control_app_button; + /* JACK specific */ Gtk::CheckButton realtime_button; @@ -80,7 +82,6 @@ class EngineControl : public ArdourDialog { Gtk::CheckButton hw_meter_button; Gtk::CheckButton verbose_output_button; - Gtk::ComboBoxText preset_combo; Gtk::ComboBoxText serverpath_combo; Gtk::ComboBoxText driver_combo; @@ -150,6 +151,8 @@ class EngineControl : public ArdourDialog { void build_notebook (); void on_response (int); + void control_app_button_clicked (); + void manage_control_app_sensitivity (); }; #endif /* __gtk2_ardour_engine_dialog_h__ */ diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h index 4192f0ea8b..f598f1a93a 100644 --- a/libs/ardour/ardour/audio_backend.h +++ b/libs/ardour/ardour/audio_backend.h @@ -228,6 +228,21 @@ class AudioBackend { virtual uint32_t systemic_input_latency () const = 0; virtual uint32_t systemic_output_latency () const = 0; + /** Return true if it is possible to launch a control app + * at this time. Return false otherwise. + * + * The audio backend may not know the device for which the + * control app should be opened, or there may no such + * application. In such cases, this method should return false. + */ + virtual bool have_control_app() const = 0; + + /** If the device name has been set, launch an application (if any exist) + * to manage the hardware settings of that device. If no such application + * exists, do nothing. + */ + virtual void launch_control_app () = 0; + /* Basic state control */ /** Start using the device named in the most recent call diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc index f452a78d49..f21440e046 100644 --- a/libs/backends/jack/jack_audiobackend.cc +++ b/libs/backends/jack/jack_audiobackend.cc @@ -17,10 +17,13 @@ */ +#include +#include #include #include #include +#include #include "pbd/error.h" @@ -340,7 +343,11 @@ JACKAudioBackend::set_systemic_output_latency (uint32_t l) std::string JACKAudioBackend::device_name () const { - return string(); + if (connected()) { + return "???"; + } + + return _target_device; } float @@ -947,3 +954,53 @@ JACKAudioBackend::can_change_buffer_size_when_running () const { return true; } + +string +JACKAudioBackend::control_app_name () const +{ + string appname; + + if (_target_device.empty()) { + return appname; + } + +#if defined (__linux) + /* Linux potential control apps */ + + if (_target_device == "Hammerfall DSP") { + appname = "hdspconf"; + } +#else +#if defined (__APPLE__) + /* OS X potential control apps */ +#else + /* Windows potential control apps */ +#endif +#endif + + return appname; +} + +bool +JACKAudioBackend::have_control_app () const +{ + return !control_app_name().empty(); +} + +void +JACKAudioBackend::launch_control_app () +{ + /* launch control app, don't care if it succeeds */ + + string appname = control_app_name (); + + if (appname.empty()) { + return; + } + + std::list args; + args.push_back (appname); + Glib::spawn_async ("", args, Glib::SPAWN_SEARCH_PATH); +} + + diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h index f47b630f49..15246a0305 100644 --- a/libs/backends/jack/jack_audiobackend.h +++ b/libs/backends/jack/jack_audiobackend.h @@ -84,6 +84,9 @@ class JACKAudioBackend : public AudioBackend { uint32_t systemic_input_latency () const; uint32_t systemic_output_latency () const; + bool have_control_app() const; + void launch_control_app (); + int start (); int stop (); int pause (); @@ -179,6 +182,7 @@ class JACKAudioBackend : public AudioBackend { mutable DriverDeviceMap all_devices; PBD::ScopedConnection disconnect_connection; + std::string control_app_name () const; }; } // namespace