move control app launching back into audio backend to allow ASIO/CoreAudio model to work; push initial state of AMS dialog to backend
Issues remain with the basic model of the AMS dialog - when is newly chosen state pushed into the backend (which can then modify the control app button sensitivity. This is a special problem for this button because APIs like ASIO and CoreAudio probably don't allow us to launch a control app for an arbitrary device, but only one actually in use. In this sense it is different from properties like available buffer size etc, where we can typically query without actually using the device.
This commit is contained in:
parent
29c9d94dbe
commit
2a89234027
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
|
||||
#include <glibmm/spawn.h>
|
||||
#include <gtkmm/messagedialog.h>
|
||||
|
||||
#include "pbd/error.h"
|
||||
|
@ -65,6 +64,7 @@ EngineControl::EngineControl ()
|
|||
, ports_spinner (ports_adjustment)
|
||||
, control_app_button (_("Launch Control App"))
|
||||
, basic_packer (9, 3)
|
||||
, ignore_changes (0)
|
||||
{
|
||||
build_notebook ();
|
||||
|
||||
|
@ -82,9 +82,12 @@ EngineControl::EngineControl ()
|
|||
|
||||
XMLNode* audio_setup = ARDOUR::Config->extra_xml ("AudioMIDISetup");
|
||||
|
||||
/* push a change as if we altered the backend */
|
||||
backend_changed ();
|
||||
|
||||
if (audio_setup) {
|
||||
set_state (*audio_setup);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -94,10 +97,10 @@ EngineControl::on_response (int response_id)
|
|||
|
||||
switch (response_id) {
|
||||
case RESPONSE_APPLY:
|
||||
setup_engine (true);
|
||||
push_state_to_backend (true);
|
||||
break;
|
||||
case RESPONSE_OK:
|
||||
setup_engine (true);
|
||||
push_state_to_backend (true);
|
||||
hide ();
|
||||
break;
|
||||
default:
|
||||
|
@ -120,10 +123,6 @@ EngineControl::build_notebook ()
|
|||
|
||||
set_popdown_strings (backend_combo, strings);
|
||||
backend_combo.set_active_text (strings.front());
|
||||
backend_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::backend_changed));
|
||||
backend_changed ();
|
||||
|
||||
driver_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::driver_changed));
|
||||
|
||||
basic_packer.set_spacings (6);
|
||||
basic_packer.set_border_width (12);
|
||||
|
@ -153,7 +152,6 @@ EngineControl::build_notebook ()
|
|||
basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
|
||||
row++;
|
||||
|
||||
sr_connection = sample_rate_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::sample_rate_changed));
|
||||
|
||||
label = manage (left_aligned_label (_("Buffer size:")));
|
||||
basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
|
||||
|
@ -162,21 +160,18 @@ EngineControl::build_notebook ()
|
|||
basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, xopt, (AttachOptions) 0);
|
||||
row++;
|
||||
|
||||
bs_connection = buffer_size_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::buffer_size_changed));
|
||||
|
||||
label = manage (left_aligned_label (_("Input Channels:")));
|
||||
basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
|
||||
basic_packer.attach (input_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
|
||||
++row;
|
||||
|
||||
input_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &input_channels));
|
||||
|
||||
label = manage (left_aligned_label (_("Output Channels:")));
|
||||
basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
|
||||
basic_packer.attach (output_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
|
||||
++row;
|
||||
|
||||
output_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &output_channels));
|
||||
|
||||
label = manage (left_aligned_label (_("Hardware input latency:")));
|
||||
basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
|
||||
|
@ -192,8 +187,6 @@ EngineControl::build_notebook ()
|
|||
basic_packer.attach (*label, 2, 3, row, row+1, xopt, (AttachOptions) 0);
|
||||
++row;
|
||||
|
||||
device_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::device_changed));
|
||||
|
||||
basic_hbox.pack_start (basic_packer, false, false);
|
||||
basic_vbox.pack_start (basic_hbox, false, false);
|
||||
|
||||
|
@ -215,6 +208,15 @@ EngineControl::build_notebook ()
|
|||
|
||||
notebook.set_name ("SettingsNotebook");
|
||||
|
||||
/* Connect to signals */
|
||||
|
||||
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));
|
||||
input_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &input_channels));
|
||||
output_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &output_channels));
|
||||
device_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::device_changed));
|
||||
}
|
||||
|
||||
EngineControl::~EngineControl ()
|
||||
|
@ -225,11 +227,15 @@ EngineControl::~EngineControl ()
|
|||
void
|
||||
EngineControl::backend_changed ()
|
||||
{
|
||||
if (ignore_changes) {
|
||||
return;
|
||||
}
|
||||
|
||||
string backend_name = backend_combo.get_active_text();
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend;
|
||||
|
||||
if (!(backend = ARDOUR::AudioEngine::instance()->set_backend (backend_name, "ardour", ""))) {
|
||||
/* eh? */
|
||||
/* eh? setting the backend failed... how ? */
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -244,7 +250,7 @@ EngineControl::backend_changed ()
|
|||
list_devices ();
|
||||
}
|
||||
|
||||
maybe_set_state ();
|
||||
maybe_display_saved_state ();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -302,18 +308,26 @@ EngineControl::list_devices ()
|
|||
void
|
||||
EngineControl::driver_changed ()
|
||||
{
|
||||
if (ignore_changes) {
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
assert (backend);
|
||||
|
||||
backend->set_driver (driver_combo.get_active_text());
|
||||
list_devices ();
|
||||
|
||||
maybe_set_state ();
|
||||
maybe_display_saved_state ();
|
||||
}
|
||||
|
||||
void
|
||||
EngineControl::device_changed ()
|
||||
{
|
||||
if (ignore_changes) {
|
||||
return;
|
||||
}
|
||||
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
assert (backend);
|
||||
string device_name = device_combo.get_active_text ();
|
||||
|
@ -323,7 +337,7 @@ EngineControl::device_changed ()
|
|||
recursive call to this method.
|
||||
*/
|
||||
|
||||
sr_connection.block ();
|
||||
ignore_changes++;
|
||||
|
||||
/* sample rates */
|
||||
|
||||
|
@ -341,7 +355,6 @@ EngineControl::device_changed ()
|
|||
set_popdown_strings (sample_rate_combo, s);
|
||||
sample_rate_combo.set_active_text (s.front());
|
||||
|
||||
sr_connection.unblock ();
|
||||
|
||||
vector<uint32_t> bs = backend->available_buffer_sizes(device_name);
|
||||
s.clear ();
|
||||
|
@ -360,12 +373,18 @@ EngineControl::device_changed ()
|
|||
|
||||
manage_control_app_sensitivity ();
|
||||
|
||||
maybe_set_state ();
|
||||
ignore_changes--;
|
||||
|
||||
maybe_display_saved_state ();
|
||||
}
|
||||
|
||||
void
|
||||
EngineControl::sample_rate_changed ()
|
||||
{
|
||||
if (ignore_changes) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* reset the strings for buffer size to show the correct msec value
|
||||
(reflecting the new sample rate).
|
||||
*/
|
||||
|
@ -378,6 +397,10 @@ EngineControl::sample_rate_changed ()
|
|||
void
|
||||
EngineControl::buffer_size_changed ()
|
||||
{
|
||||
if (ignore_changes) {
|
||||
return;
|
||||
}
|
||||
|
||||
show_buffer_duration ();
|
||||
save_state ();
|
||||
}
|
||||
|
@ -448,8 +471,8 @@ EngineControl::get_current_state ()
|
|||
|
||||
if (backend) {
|
||||
return get_matching_state (backend_combo.get_active_text(),
|
||||
(backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
|
||||
device_combo.get_active_text());
|
||||
(backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
|
||||
device_combo.get_active_text());
|
||||
}
|
||||
|
||||
|
||||
|
@ -485,19 +508,17 @@ EngineControl::save_state ()
|
|||
}
|
||||
|
||||
void
|
||||
EngineControl::maybe_set_state ()
|
||||
EngineControl::maybe_display_saved_state ()
|
||||
{
|
||||
State* state = get_current_state ();
|
||||
|
||||
if (state) {
|
||||
sr_connection.block ();
|
||||
bs_connection.block ();
|
||||
ignore_changes++;
|
||||
sample_rate_combo.set_active_text (state->sample_rate);
|
||||
buffer_size_combo.set_active_text (state->buffer_size);
|
||||
input_latency.set_value (state->input_latency);
|
||||
output_latency.set_value (state->output_latency);
|
||||
bs_connection.unblock ();
|
||||
sr_connection.unblock ();
|
||||
ignore_changes--;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -628,8 +649,7 @@ EngineControl::set_state (const XMLNode& root)
|
|||
|
||||
for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
|
||||
if ((*i).active) {
|
||||
sr_connection.block ();
|
||||
bs_connection.block ();
|
||||
ignore_changes++;
|
||||
backend_combo.set_active_text ((*i).backend);
|
||||
driver_combo.set_active_text ((*i).driver);
|
||||
device_combo.set_active_text ((*i).device);
|
||||
|
@ -637,18 +657,23 @@ EngineControl::set_state (const XMLNode& root)
|
|||
buffer_size_combo.set_active_text ((*i).buffer_size);
|
||||
input_latency.set_value ((*i).input_latency);
|
||||
output_latency.set_value ((*i).output_latency);
|
||||
sr_connection.unblock ();
|
||||
bs_connection.unblock ();
|
||||
ignore_changes--;
|
||||
|
||||
push_state_to_backend (false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
EngineControl::setup_engine (bool start)
|
||||
EngineControl::push_state_to_backend (bool start)
|
||||
{
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
assert (backend);
|
||||
|
||||
if (!backend) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* grab the parameters from the GUI and apply them */
|
||||
|
||||
|
@ -792,51 +817,25 @@ EngineControl::get_device_name () const
|
|||
void
|
||||
EngineControl::control_app_button_clicked ()
|
||||
{
|
||||
const char* env_value = g_getenv ("ARDOUR_DEVICE_CONTROL_APP");
|
||||
string appname;
|
||||
|
||||
cerr << "Environment var for control app: " << (env_value ? env_value : "empty") << endl;
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
|
||||
if (!env_value) {
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
|
||||
if (!backend) {
|
||||
return;
|
||||
}
|
||||
|
||||
appname = backend->control_app_name();
|
||||
} else {
|
||||
appname = env_value;
|
||||
}
|
||||
|
||||
cerr << "appname for control app " << appname << endl;
|
||||
|
||||
if (appname.empty()) {
|
||||
if (!backend) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<string> args;
|
||||
args.push_back (appname);
|
||||
Glib::spawn_async ("", args, Glib::SPAWN_SEARCH_PATH);
|
||||
|
||||
backend->launch_control_app ();
|
||||
}
|
||||
|
||||
void
|
||||
EngineControl::manage_control_app_sensitivity ()
|
||||
{
|
||||
const char* env_value = g_getenv ("ARDOUR_DEVICE_CONTROL_APP");
|
||||
string appname;
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
|
||||
if (!env_value) {
|
||||
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
|
||||
|
||||
if (!backend) {
|
||||
return;
|
||||
}
|
||||
|
||||
appname = backend->control_app_name();
|
||||
} else {
|
||||
appname = env_value;
|
||||
if (!backend) {
|
||||
return;
|
||||
}
|
||||
|
||||
string appname = backend->control_app_name();
|
||||
|
||||
if (appname.empty()) {
|
||||
control_app_button.set_sensitive (false);
|
||||
|
|
|
@ -41,7 +41,6 @@ class EngineControl : public ArdourDialog {
|
|||
~EngineControl ();
|
||||
|
||||
static bool need_setup ();
|
||||
int setup_engine (bool start);
|
||||
|
||||
XMLNode& get_state ();
|
||||
void set_state (const XMLNode&);
|
||||
|
@ -97,8 +96,7 @@ class EngineControl : public ArdourDialog {
|
|||
Gtk::VBox basic_vbox;
|
||||
Gtk::HBox midi_hbox;
|
||||
|
||||
sigc::connection sr_connection;
|
||||
sigc::connection bs_connection;
|
||||
uint32_t ignore_changes;
|
||||
|
||||
static bool engine_running ();
|
||||
|
||||
|
@ -144,7 +142,7 @@ class EngineControl : public ArdourDialog {
|
|||
const std::string& driver,
|
||||
const std::string& device);
|
||||
State* get_current_state ();
|
||||
void maybe_set_state ();
|
||||
void maybe_display_saved_state ();
|
||||
void save_state ();
|
||||
|
||||
static bool print_channel_count (Gtk::SpinButton*);
|
||||
|
@ -154,6 +152,7 @@ class EngineControl : public ArdourDialog {
|
|||
void on_response (int);
|
||||
void control_app_button_clicked ();
|
||||
void manage_control_app_sensitivity ();
|
||||
int push_state_to_backend (bool start);
|
||||
};
|
||||
|
||||
#endif /* __gtk2_ardour_engine_dialog_h__ */
|
||||
|
|
|
@ -234,7 +234,11 @@ class AudioBackend {
|
|||
* return an empty string.
|
||||
*/
|
||||
virtual std::string control_app_name() const = 0;
|
||||
|
||||
/** Launch the control app for the currently in-use or
|
||||
* selected device. May do nothing if the control
|
||||
* app is undefined or cannot be launched.
|
||||
*/
|
||||
virtual void launch_control_app () = 0;
|
||||
/* Basic state control */
|
||||
|
||||
/** Start using the device named in the most recent call
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
#include <boost/scoped_ptr.hpp>
|
||||
#include <glibmm/timer.h>
|
||||
#include <glibmm/spawn.h>
|
||||
|
||||
#include "pbd/error.h"
|
||||
|
||||
|
@ -957,25 +958,45 @@ JACKAudioBackend::can_change_buffer_size_when_running () const
|
|||
string
|
||||
JACKAudioBackend::control_app_name () const
|
||||
{
|
||||
/* Since JACK/ALSA really don't provide particularly integrated support
|
||||
for the idea of a control app to be used to control a device,
|
||||
allow the user to take some control themselves if necessary.
|
||||
*/
|
||||
|
||||
const char* env_value = g_getenv ("ARDOUR_DEVICE_CONTROL_APP");
|
||||
string appname;
|
||||
|
||||
std::cerr << "td = " << _target_driver << " tdev = " << _target_device << std::endl;
|
||||
|
||||
if (_target_driver.empty() || _target_device.empty()) {
|
||||
return appname;
|
||||
}
|
||||
|
||||
if (_target_driver == "ALSA") {
|
||||
|
||||
if (_target_device == "Hammerfall DSP") {
|
||||
appname = "hdspconf";
|
||||
} else if (_target_device == "M Audio Delta 1010") {
|
||||
appname = "mudita";
|
||||
if (!env_value) {
|
||||
if (_target_driver.empty() || _target_device.empty()) {
|
||||
return appname;
|
||||
}
|
||||
|
||||
if (_target_driver == "ALSA") {
|
||||
|
||||
if (_target_device == "Hammerfall DSP") {
|
||||
appname = "hdspconf";
|
||||
} else if (_target_device == "M Audio Delta 1010") {
|
||||
appname = "mudita";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appname = env_value;
|
||||
}
|
||||
|
||||
std::cerr << "appname retrurned as " << appname << std::endl;
|
||||
|
||||
return appname;
|
||||
}
|
||||
|
||||
void
|
||||
JACKAudioBackend::launch_control_app ()
|
||||
{
|
||||
string appname = control_app_name();
|
||||
|
||||
if (appname.empty()) {
|
||||
error << string_compose (_("There is no control application for the device \"%1\""), _target_device) << endmsg;
|
||||
return;
|
||||
}
|
||||
|
||||
std::list<string> args;
|
||||
args.push_back (appname);
|
||||
Glib::spawn_async ("", args, Glib::SPAWN_SEARCH_PATH);
|
||||
}
|
||||
|
|
|
@ -85,6 +85,7 @@ class JACKAudioBackend : public AudioBackend {
|
|||
uint32_t systemic_output_latency () const;
|
||||
|
||||
std::string control_app_name () const;
|
||||
void launch_control_app ();
|
||||
|
||||
int start ();
|
||||
int stop ();
|
||||
|
|
Loading…
Reference in New Issue