using namespace Gtkmm2ext;
using namespace PBD;
using namespace Glib;
+using namespace ARDOUR_UI_UTILS;
static const unsigned int midi_tab = 2;
static const unsigned int latency_tab = 1; /* zero-based, page zero is the main setup page */
-static const char* results_markup = X_("<span foreground=\"red\" style=\"italic\" size=\"larger\">%1</span>");
+static const char* results_markup = X_("<span weight=\"bold\" size=\"larger\">%1</span>");
EngineControl::EngineControl ()
: ArdourDialog (_("Audio/MIDI Setup"))
lm_table.attach (lm_title, 0, 3, row, row+1, xopt, (AttachOptions) 0);
row++;
- Gtk::Label* preamble;
-
- preamble = manage (new Label);
- preamble->set_width_chars (60);
- preamble->set_line_wrap (true);
- preamble->set_markup (_("<span weight=\"bold\">Turn down the volume on your audio equipment to a very low level.</span>"));
+ lm_preamble.set_width_chars (60);
+ lm_preamble.set_line_wrap (true);
+ lm_preamble.set_markup (_("<span weight=\"bold\">Turn down the volume on your audio equipment to a very low level.</span>"));
- lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
+ lm_table.attach (lm_preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
row++;
+ Gtk::Label* preamble;
preamble = manage (new Label);
preamble->set_width_chars (60);
preamble->set_line_wrap (true);
ARDOUR::AudioEngine::instance()->Stopped.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
ARDOUR::AudioEngine::instance()->Halted.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
- backend_changed ();
+ if (audio_setup)
+ {
+ set_state (*audio_setup);
+ }
+ {
+ /* ignore: don't save state */
+ PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
+ backend_changed ();
+ }
/* Connect to signals */
input_channels.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::parameter_changed));
output_channels.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::parameter_changed));
- if (audio_setup) {
- set_state (*audio_setup);
- }
-
notebook.signal_switch_page().connect (sigc::mem_fun (*this, &EngineControl::on_switch_page));
}
+void
+EngineControl::on_show ()
+{
+ ArdourDialog::on_show ();
+ ok_button->grab_focus();
+}
+
void
EngineControl::on_response (int response_id)
{
basic_vbox.pack_start (*hpacker);
}
- basic_vbox.show_all ();
+ {
+ PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
+ basic_vbox.show_all ();
+ }
}
void
ARDOUR::AudioEngine::instance()->get_physical_outputs (type, outputs);
ARDOUR::AudioEngine::instance()->get_physical_inputs (type, inputs);
- if (inputs.empty() || outputs.empty()) {
+ if (!ARDOUR::AudioEngine::instance()->running()) {
+ MessageDialog msg (_("Failed to start or connect to audio-engine.\n\nLatency calibration requires a working audio interface."));
+ notebook.set_current_page (0);
+ msg.run ();
+ return;
+ }
+ else if (inputs.empty() || outputs.empty()) {
MessageDialog msg (_("Your selected audio configuration is playback- or capture-only.\n\nLatency calibration requires playback and capture"));
- lm_measure_button.set_sensitive (false);
notebook.set_current_page (0);
msg.run ();
return;
}
- if (!outputs.empty()) {
- set_popdown_strings (lm_output_channel_combo, outputs);
- lm_output_channel_combo.set_active_text (outputs.front());
- lm_output_channel_combo.set_sensitive (true);
+ lm_back_button_signal.disconnect();
+ if (_measure_midi) {
+ lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), midi_tab));
+ lm_preamble.hide ();
} else {
- lm_output_channel_combo.set_sensitive (false);
+ lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
+ lm_preamble.show ();
}
- if (!inputs.empty()) {
- set_popdown_strings (lm_input_channel_combo, inputs);
- lm_input_channel_combo.set_active_text (inputs.front());
- lm_input_channel_combo.set_sensitive (true);
- } else {
- lm_input_channel_combo.set_sensitive (false);
- }
+ set_popdown_strings (lm_output_channel_combo, outputs);
+ lm_output_channel_combo.set_active_text (outputs.front());
+ lm_output_channel_combo.set_sensitive (true);
+
+ set_popdown_strings (lm_input_channel_combo, inputs);
+ lm_input_channel_combo.set_active_text (inputs.front());
+ lm_input_channel_combo.set_sensitive (true);
lm_measure_button.set_sensitive (true);
}
if (!drivers.empty()) {
{
+ string current_driver;
+ current_driver = backend->driver_name ();
+
+ // driver might not have been set yet
+ if (current_driver == "") {
+ current_driver = driver_combo.get_active_text ();
+ if (current_driver == "")
+ // driver has never been set, make sure it's not blank
+ current_driver = drivers.front ();
+ }
+
PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
set_popdown_strings (driver_combo, drivers);
- driver_combo.set_active_text (drivers.front());
+ driver_combo.set_active_text (current_driver);
}
driver_changed ();
update_sensitivity ();
{
+ string current_device;
+ current_device = backend->device_name ();
+ if (current_device == "") {
+ // device might not have been set yet
+ current_device = device_combo.get_active_text ();
+ if (current_device == "")
+ // device has never been set, make sure it's not blank
+ current_device = available_devices.front ();
+ }
+
PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
set_popdown_strings (device_combo, available_devices);
- device_combo.set_active_text (available_devices.front());
+
+ device_combo.set_active_text (current_device);
}
device_changed ();
+ input_latency.set_sensitive (true);
+ output_latency.set_sensitive (true);
+ input_channels.set_sensitive (true);
+ output_channels.set_sensitive (true);
+
ok_button->set_sensitive (true);
apply_button->set_sensitive (true);
} else {
+ device_combo.clear();
sample_rate_combo.set_sensitive (false);
buffer_size_combo.set_sensitive (false);
input_latency.set_sensitive (false);
output_latency.set_sensitive (false);
input_channels.set_sensitive (false);
output_channels.set_sensitive (false);
- ok_button->set_sensitive (false);
- apply_button->set_sensitive (false);
+ if (_have_control) {
+ ok_button->set_sensitive (false);
+ apply_button->set_sensitive (false);
+ } else {
+ ok_button->set_sensitive (true);
+ apply_button->set_sensitive (true);
+ }
}
}
}
}
-EngineControl::State*
+EngineControl::State
EngineControl::get_matching_state (
const string& backend,
const string& driver,
const string& device)
{
for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
- if ((*i).backend == backend &&
- (*i).driver == driver &&
- (*i).device == device) {
- return &(*i);
+ if ((*i)->backend == backend &&
+ (!_have_control || ((*i)->driver == driver && (*i)->device == device)))
+ {
+ return (*i);
}
}
- return 0;
+ return State();
}
-EngineControl::State*
+EngineControl::State
EngineControl::get_saved_state_for_currently_displayed_backend_and_device ()
{
boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
device_combo.get_active_text());
}
-EngineControl::State*
+EngineControl::State
EngineControl::save_state ()
{
+ State state;
+
if (!_have_control) {
- return 0;
+ state = get_matching_state (backend_combo.get_active_text(), string(), string());
+ if (state) {
+ return state;
+ }
+ state.reset(new StateStruct);
+ state->backend = get_backend ();
+ } else {
+ state.reset(new StateStruct);
+ store_state (state);
}
- State* state = new State;
- store_state (*state);
for (StateList::iterator i = states.begin(); i != states.end();) {
- if ((*i).backend == state->backend &&
- (*i).driver == state->driver &&
- (*i).device == state->device) {
+ if ((*i)->backend == state->backend &&
+ (*i)->driver == state->driver &&
+ (*i)->device == state->device) {
i = states.erase(i);
} else {
++i;
}
}
- states.push_back (*state);
+ states.push_back (state);
return state;
}
void
-EngineControl::store_state (State& state)
+EngineControl::store_state (State state)
{
- state.backend = get_backend ();
- state.driver = get_driver ();
- state.device = get_device_name ();
- state.sample_rate = get_rate ();
- state.buffer_size = get_buffer_size ();
- state.input_latency = get_input_latency ();
- state.output_latency = get_output_latency ();
- state.input_channels = get_input_channels ();
- state.output_channels = get_output_channels ();
- state.midi_option = get_midi_option ();
- state.midi_devices = _midi_devices;
+ state->backend = get_backend ();
+ state->driver = get_driver ();
+ state->device = get_device_name ();
+ state->sample_rate = get_rate ();
+ state->buffer_size = get_buffer_size ();
+ state->input_latency = get_input_latency ();
+ state->output_latency = get_output_latency ();
+ state->input_channels = get_input_channels ();
+ state->output_channels = get_output_channels ();
+ state->midi_option = get_midi_option ();
+ state->midi_devices = _midi_devices;
}
void
return;
}
- State* state = get_saved_state_for_currently_displayed_backend_and_device ();
+ State state = get_saved_state_for_currently_displayed_backend_and_device ();
if (state) {
PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
XMLNode* node = new XMLNode ("State");
- node->add_property ("backend", (*i).backend);
- node->add_property ("driver", (*i).driver);
- node->add_property ("device", (*i).device);
- node->add_property ("sample-rate", (*i).sample_rate);
- node->add_property ("buffer-size", (*i).buffer_size);
- node->add_property ("input-latency", (*i).input_latency);
- node->add_property ("output-latency", (*i).output_latency);
- node->add_property ("input-channels", (*i).input_channels);
- node->add_property ("output-channels", (*i).output_channels);
- node->add_property ("active", (*i).active ? "yes" : "no");
- node->add_property ("midi-option", (*i).midi_option);
+ node->add_property ("backend", (*i)->backend);
+ node->add_property ("driver", (*i)->driver);
+ node->add_property ("device", (*i)->device);
+ node->add_property ("sample-rate", (*i)->sample_rate);
+ node->add_property ("buffer-size", (*i)->buffer_size);
+ node->add_property ("input-latency", (*i)->input_latency);
+ node->add_property ("output-latency", (*i)->output_latency);
+ node->add_property ("input-channels", (*i)->input_channels);
+ node->add_property ("output-channels", (*i)->output_channels);
+ node->add_property ("active", (*i)->active ? "yes" : "no");
+ node->add_property ("midi-option", (*i)->midi_option);
XMLNode* midi_devices = new XMLNode ("MIDIDevices");
- for (std::vector<MidiDeviceSettings>::const_iterator p = (*i).midi_devices.begin(); p != (*i).midi_devices.end(); ++p) {
+ for (std::vector<MidiDeviceSettings>::const_iterator p = (*i)->midi_devices.begin(); p != (*i)->midi_devices.end(); ++p) {
XMLNode* midi_device_stuff = new XMLNode ("MIDIDevice");
midi_device_stuff->add_property (X_("name"), (*p)->name);
midi_device_stuff->add_property (X_("enabled"), (*p)->enabled);
cclist = child->children();
for (cciter = cclist.begin(); cciter != cclist.end(); ++cciter) {
- State state;
+ State state (new StateStruct);
grandchild = *cciter;
if ((prop = grandchild->property ("backend")) == 0) {
continue;
}
- state.backend = prop->value ();
+ state->backend = prop->value ();
if ((prop = grandchild->property ("driver")) == 0) {
continue;
}
- state.driver = prop->value ();
+ state->driver = prop->value ();
if ((prop = grandchild->property ("device")) == 0) {
continue;
}
- state.device = prop->value ();
+ state->device = prop->value ();
if ((prop = grandchild->property ("sample-rate")) == 0) {
continue;
}
- state.sample_rate = atof (prop->value ());
+ state->sample_rate = atof (prop->value ());
if ((prop = grandchild->property ("buffer-size")) == 0) {
continue;
}
- state.buffer_size = atoi (prop->value ());
+ state->buffer_size = atoi (prop->value ());
if ((prop = grandchild->property ("input-latency")) == 0) {
continue;
}
- state.input_latency = atoi (prop->value ());
+ state->input_latency = atoi (prop->value ());
if ((prop = grandchild->property ("output-latency")) == 0) {
continue;
}
- state.output_latency = atoi (prop->value ());
+ state->output_latency = atoi (prop->value ());
if ((prop = grandchild->property ("input-channels")) == 0) {
continue;
}
- state.input_channels = atoi (prop->value ());
+ state->input_channels = atoi (prop->value ());
if ((prop = grandchild->property ("output-channels")) == 0) {
continue;
}
- state.output_channels = atoi (prop->value ());
+ state->output_channels = atoi (prop->value ());
if ((prop = grandchild->property ("active")) == 0) {
continue;
}
- state.active = string_is_affirmative (prop->value ());
+ state->active = string_is_affirmative (prop->value ());
if ((prop = grandchild->property ("midi-option")) == 0) {
continue;
}
- state.midi_option = prop->value ();
+ state->midi_option = prop->value ();
- state.midi_devices.clear();
+ state->midi_devices.clear();
XMLNode* midinode;
- if ((midinode = find_named_node (*grandchild, "MIDIDevices")) != 0) {
+ if ((midinode = ARDOUR::find_named_node (*grandchild, "MIDIDevices")) != 0) {
const XMLNodeList mnc = midinode->children();
for (XMLNodeList::const_iterator n = mnc.begin(); n != mnc.end(); ++n) {
if ((*n)->property (X_("name")) == 0
atoi ((*n)->property (X_("input-latency"))->value ()),
atoi ((*n)->property (X_("output-latency"))->value ())
));
- state.midi_devices.push_back (ptr);
+ state->midi_devices.push_back (ptr);
}
}
* this can be removed again before release
*/
for (StateList::iterator i = states.begin(); i != states.end();) {
- if ((*i).backend == state.backend &&
- (*i).driver == state.driver &&
- (*i).device == state.device) {
+ if ((*i)->backend == state->backend &&
+ (*i)->driver == state->driver &&
+ (*i)->device == state->device) {
i = states.erase(i);
} else {
++i;
/* now see if there was an active state and switch the setup to it */
+ // purge states of backend that are not available in this built
+ vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
+ vector<std::string> backend_names;
+
+ for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator i = backends.begin(); i != backends.end(); ++i) {
+ backend_names.push_back((*i)->name);
+ }
+ for (StateList::iterator i = states.begin(); i != states.end();) {
+ if (std::find(backend_names.begin(), backend_names.end(), (*i)->backend) == backend_names.end()) {
+ i = states.erase(i);
+ } else {
+ ++i;
+ }
+ }
+
for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
- if ((*i).active) {
+ if ((*i)->active) {
ignore_changes++;
- backend_combo.set_active_text ((*i).backend);
- driver_combo.set_active_text ((*i).driver);
- device_combo.set_active_text ((*i).device);
- sample_rate_combo.set_active_text (rate_as_string ((*i).sample_rate));
- buffer_size_combo.set_active_text (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);
+ backend_combo.set_active_text ((*i)->backend);
+ driver_combo.set_active_text ((*i)->driver);
+ device_combo.set_active_text ((*i)->device);
+ sample_rate_combo.set_active_text (rate_as_string ((*i)->sample_rate));
+ buffer_size_combo.set_active_text (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);
ignore_changes--;
break;
}
* necessary
*/
- if (_have_control) {
- State* state = get_saved_state_for_currently_displayed_backend_and_device ();
+ State state = get_saved_state_for_currently_displayed_backend_and_device ();
- if (!state) {
- state = save_state ();
- assert (state);
- }
+ if (!state) {
+ state = save_state ();
+ assert (state);
+ }
- /* all off */
+ /* all off */
- for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
- (*i).active = false;
- }
+ for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
+ (*i)->active = false;
+ }
- /* mark this one active (to be used next time the dialog is
- * shown)
- */
+ /* mark this one active (to be used next time the dialog is
+ * shown)
+ */
- state->active = true;
+ state->active = true;
+ if (_have_control) { // XXX
manage_control_app_sensitivity ();
}
} else {
if (lm_running) {
+ end_latency_detection ();
ARDOUR::AudioEngine::instance()->stop_latency_detection();
}
}
}
if (solid) {
+ have_lm_results = true;
end_latency_detection ();
lm_use_button.set_sensitive (true);
- have_lm_results = true;
+ return false;
}
lm_results.set_markup (string_compose (results_markup, buf));
}
if (solid) {
+ have_lm_results = true;
end_latency_detection ();
lm_use_button.set_sensitive (true);
- have_lm_results = true;
+ return false;
+ } else if (mididm->processed () > 400) {
+ have_lm_results = false;
+ end_latency_detection ();
+ lm_results.set_markup (string_compose (results_markup, _("Timeout - large MIDI jitter.")));
+ return false;
}
lm_results.set_markup (string_compose (results_markup, buf));
lm_output_channel_combo.set_sensitive (false);
lm_running = true;
}
-
- lm_back_button_signal.disconnect();
- if (_measure_midi) {
- lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), midi_tab));
- } else {
- lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
- }
}
void
ARDOUR::AudioEngine::instance()->stop_latency_detection ();
lm_measure_label.set_text (_("Measure"));
if (!have_lm_results) {
- lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
- } else {
lm_use_button.set_sensitive (false);
}
lm_input_channel_combo.set_sensitive (true);
void
EngineControl::calibrate_audio_latency ()
{
- _measure_midi.reset();
+ _measure_midi.reset ();
+ have_lm_results = false;
+ lm_use_button.set_sensitive (false);
+ lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
notebook.set_current_page (latency_tab);
}
EngineControl::calibrate_midi_latency (MidiDeviceSettings s)
{
_measure_midi = s;
+ have_lm_results = false;
+ lm_use_button.set_sensitive (false);
+ lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
notebook.set_current_page (latency_tab);
}