X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=gtk2_ardour%2Fengine_dialog.cc;h=a32ccf146e81a8486721af2e2ba9be1f14f879dd;hb=736038556fa41607d54a57fd3339d4fd1782bddf;hp=b2a60dca910b5dd12b7858e07c69a534ad7c7da8;hpb=f2404a522d3914948caa357da792d8f84cec8456;p=ardour.git diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc index b2a60dca91..a32ccf146e 100644 --- a/gtk2_ardour/engine_dialog.cc +++ b/gtk2_ardour/engine_dialog.cc @@ -43,6 +43,7 @@ #include "ardour/mididm.h" #include "ardour/rc_configuration.h" #include "ardour/types.h" +#include "ardour/profile.h" #include "pbd/convert.h" #include "pbd/error.h" @@ -58,14 +59,16 @@ using namespace Gtk; 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_("%1"); +static const char* results_markup = X_("%1"); EngineControl::EngineControl () : ArdourDialog (_("Audio/MIDI Setup")) + , engine_status ("") , basic_packer (9, 4) , input_latency_adjustment (0, 0, 99999, 1) , input_latency (input_latency_adjustment) @@ -141,16 +144,14 @@ EngineControl::EngineControl () 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 (_("Turn down the volume on your audio equipment to a very low level.")); + lm_preamble.set_width_chars (60); + lm_preamble.set_line_wrap (true); + lm_preamble.set_markup (_("Turn down the volume on your audio equipment to a very low level.")); - 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); @@ -248,6 +249,9 @@ EngineControl::EngineControl () get_vbox()->set_border_width (12); get_vbox()->pack_start (notebook); + get_action_area()->pack_start (engine_status); + engine_status.show(); + /* need a special function to print "all available channels" when the * channel counts hit zero. */ @@ -258,13 +262,14 @@ EngineControl::EngineControl () midi_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::configure_midi_devices)); midi_devices_button.set_sensitive (false); midi_devices_button.set_name ("generic button"); + midi_devices_button.set_can_focus(true); control_app_button.signal_clicked().connect (mem_fun (*this, &EngineControl::control_app_button_clicked)); manage_control_app_sensitivity (); - cancel_button = add_button (Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); - ok_button = add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); + cancel_button = add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_CANCEL); apply_button = add_button (Gtk::Stock::APPLY, Gtk::RESPONSE_APPLY); + ok_button = add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK); /* Pick up any existing audio setup configuration, if appropriate */ @@ -274,7 +279,15 @@ EngineControl::EngineControl () 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 protect_ignore_changes (ignore_changes, ignore_changes + 1); + backend_changed (); + } /* Connect to signals */ @@ -289,11 +302,19 @@ EngineControl::EngineControl () 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)); + + connect_disconnect_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::connect_disconnect_click)); + connect_disconnect_button.set_no_show_all(); + +} + +void +EngineControl::on_show () +{ + ArdourDialog::on_show (); + device_changed (); + ok_button->grab_focus(); } void @@ -343,6 +364,7 @@ EngineControl::build_notebook () lm_button_audio.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_audio_latency)); lm_button_audio.set_name ("generic button"); + lm_button_audio.set_can_focus(true); if (_have_control) { build_full_control_notebook (); @@ -352,16 +374,10 @@ EngineControl::build_notebook () basic_vbox.pack_start (basic_hbox, false, false); - if (_have_control) { - Gtk::HBox* hpacker = manage (new HBox); - hpacker->set_border_width (12); - hpacker->pack_start (control_app_button, false, false); - hpacker->show (); - control_app_button.show(); - basic_vbox.pack_start (*hpacker); + { + PBD::Unwinder protect_ignore_changes (ignore_changes, ignore_changes + 1); + basic_vbox.show_all (); } - - basic_vbox.show_all (); } void @@ -401,6 +417,10 @@ EngineControl::build_full_control_notebook () basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0); buffer_size_duration_label.set_alignment (0.0); /* left-align */ basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0); + + /* button spans 2 rows */ + + basic_packer.attach (control_app_button, 3, 4, row-1, row+1, xopt, xopt); row++; input_channels.set_name ("InputChannels"); @@ -409,22 +429,26 @@ EngineControl::build_full_control_notebook () input_channels.set_wrap (false); output_channels.set_editable (true); - 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; - + if (!ARDOUR::Profile->get_mixbus()) { + 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; + } + output_channels.set_name ("OutputChannels"); output_channels.set_flags (Gtk::CAN_FOCUS); output_channels.set_digits (0); output_channels.set_wrap (false); output_channels.set_editable (true); - 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; - + if (!ARDOUR::Profile->get_mixbus()) { + 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; + } + input_latency.set_name ("InputLatency"); input_latency.set_flags (Gtk::CAN_FOCUS); input_latency.set_digits (0); @@ -496,8 +520,6 @@ EngineControl::build_no_control_notebook () row++; } - connect_disconnect_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::connect_disconnect_click)); - basic_packer.attach (connect_disconnect_button, 0, 2, row, row+1, FILL, AttachOptions (0)); row++; } @@ -527,29 +549,35 @@ EngineControl::enable_latency_tab () 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); } @@ -587,19 +615,15 @@ EngineControl::midi_latency_adjustment_changed (Gtk::Adjustment *a, MidiDeviceSe } } -bool -EngineControl::midi_device_enabled_toggled (GdkEventButton* ev, ArdourButton *b, MidiDeviceSettings device) { - if (ev->type == GDK_2BUTTON_PRESS || ev->type == GDK_3BUTTON_PRESS) { - return true; - } +void +EngineControl::midi_device_enabled_toggled (ArdourButton *b, MidiDeviceSettings device) { b->set_active (!b->get_active()); device->enabled = b->get_active(); - refresh_midi_display(); - return true; + refresh_midi_display(device->name); } void -EngineControl::refresh_midi_display () +EngineControl::refresh_midi_display (std::string focus) { boost::shared_ptr backend = ARDOUR::AudioEngine::instance()->current_backend(); assert (backend); @@ -639,10 +663,14 @@ EngineControl::refresh_midi_display () m = manage (new ArdourButton ((*p)->name, ArdourButton::led_default_elements)); m->set_name ("midi device"); + m->set_can_focus (Gtk::CAN_FOCUS); m->add_events (Gdk::BUTTON_RELEASE_MASK); m->set_active (enabled); - m->signal_button_release_event().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_device_enabled_toggled), m, *p)); + m->signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_device_enabled_toggled), m, *p)); midi_device_table.attach (*m, 0, 1, row, row + 1, xopt, AttachOptions (0)); m->show (); + if ((*p)->name == focus) { + m->grab_focus(); + } a = manage (new Gtk::Adjustment (0, 0, 99999, 1)); s = manage (new Gtk::SpinButton (*a)); @@ -695,9 +723,20 @@ EngineControl::backend_changed () 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 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 (); @@ -726,6 +765,8 @@ EngineControl::backend_changed () } } + connect_disconnect_button.hide(); + midi_option_changed(); started_at_least_once = false; @@ -738,6 +779,11 @@ EngineControl::backend_changed () bool EngineControl::print_channel_count (Gtk::SpinButton* sb) { + if (ARDOUR::Profile->get_mixbus()) { + cout << "Mixbus crash trap. sb->get_value(): " << sb->get_value(); + return true; + } + uint32_t cnt = (uint32_t) sb->get_value(); if (cnt == 0) { sb->set_text (_("all available channels")); @@ -779,25 +825,54 @@ EngineControl::list_devices () 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 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); + if (backend->can_change_sample_rate_when_running() && sample_rate_combo.get_children().size() > 0) { + sample_rate_combo.set_sensitive (true); + } + if (backend->can_change_buffer_size_when_running() && buffer_size_combo.get_children().size() > 0) { + buffer_size_combo.set_sensitive (true); + } + + } } } @@ -823,6 +898,9 @@ EngineControl::device_changed () assert (backend); string device_name = device_combo.get_active_text (); vector s; + + //the device name must be set FIRST so ASIO can populate buffersizes and the control panel button + backend->set_device_name(device_name); { PBD::Unwinder protect_ignore_changes (ignore_changes, ignore_changes + 1); @@ -901,7 +979,11 @@ EngineControl::device_changed () buffer_size_combo.set_sensitive (true); set_popdown_strings (buffer_size_combo, s); - buffer_size_combo.set_active_text (bufsize_as_string (backend->default_buffer_size())); + uint32_t period = backend->buffer_size(); + if (0 == period) { + period = backend->default_buffer_size(device_name); + } + buffer_size_combo.set_active_text (bufsize_as_string (period)); show_buffer_duration (); } else { buffer_size_combo.set_sensitive (false); @@ -966,15 +1048,25 @@ EngineControl::show_buffer_duration () uint32_t samples = atoi (bs_text); /* will ignore trailing text */ uint32_t rate = get_rate(); - /* Translators: "msecs" is ALWAYS plural here, so we do not - need singular form as well. - */ /* Developers: note the hard-coding of a double buffered model in the (2 * samples) computation of latency. we always start the audiobackend in this configuration. */ + /* note to jack1 developers: ardour also always starts the engine + * in async mode (no jack2 --sync option) which adds an extra cycle + * of latency with jack2 (and *3 would be correct) + * The value can also be wrong if jackd is started externally.. + * + * At the time of writing the ALSA backend always uses double-buffering *2, + * The Dummy backend *1, and who knows what ASIO really does :) + * + * So just display the period size, that's also what + * ARDOUR_UI::update_sample_rate() does for the status bar. + * (the statusbar calls AudioEngine::instance()->usecs_per_cycle() + * but still, that's the buffer period, not [round-trip] latency) + */ char buf[32]; - snprintf (buf, sizeof (buf), _("(%.1f msecs)"), (2 * samples) / (rate/1000.0)); + snprintf (buf, sizeof (buf), _("(%.1f ms)"), (samples / (rate/1000.0f))); buffer_size_duration_label.set_text (buf); } @@ -1029,23 +1121,23 @@ EngineControl::parameter_changed () } } -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 backend = ARDOUR::AudioEngine::instance()->current_backend(); @@ -1062,44 +1154,52 @@ EngineControl::get_saved_state_for_currently_displayed_backend_and_device () 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 @@ -1109,7 +1209,7 @@ EngineControl::maybe_display_saved_state () 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 protect_ignore_changes (ignore_changes, ignore_changes + 1); @@ -1145,20 +1245,20 @@ EngineControl::get_state () 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::const_iterator p = (*i).midi_devices.begin(); p != (*i).midi_devices.end(); ++p) { + for (std::vector::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); @@ -1205,7 +1305,7 @@ EngineControl::set_state (const XMLNode& root) cclist = child->children(); for (cciter = cclist.begin(); cciter != cclist.end(); ++cciter) { - State state; + State state (new StateStruct); grandchild = *cciter; @@ -1216,61 +1316,61 @@ EngineControl::set_state (const XMLNode& root) 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 @@ -1287,7 +1387,7 @@ EngineControl::set_state (const XMLNode& root) 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); } } @@ -1296,9 +1396,9 @@ EngineControl::set_state (const XMLNode& root) * 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; @@ -1312,18 +1412,33 @@ EngineControl::set_state (const XMLNode& root) /* 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 backends = ARDOUR::AudioEngine::instance()->available_backends(); + vector backend_names; + + for (vector::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; } @@ -1588,26 +1703,26 @@ EngineControl::post_push () * 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 (); } @@ -1652,12 +1767,22 @@ EngineControl::get_midi_option () const uint32_t EngineControl::get_input_channels() const { + if (ARDOUR::Profile->get_mixbus()) { + boost::shared_ptr backend = ARDOUR::AudioEngine::instance()->current_backend(); + if (!backend) return 0; + return backend->input_channels(); + } return (uint32_t) input_channels_adjustment.get_value(); } uint32_t EngineControl::get_output_channels() const { + if (ARDOUR::Profile->get_mixbus()) { + boost::shared_ptr backend = ARDOUR::AudioEngine::instance()->current_backend(); + if (!backend) return 0; + return backend->input_channels(); + } return (uint32_t) output_channels_adjustment.get_value(); } @@ -1794,6 +1919,7 @@ EngineControl::on_switch_page (GtkNotebookPage*, guint page_num) } else { if (lm_running) { + end_latency_detection (); ARDOUR::AudioEngine::instance()->stop_latency_detection(); } } @@ -1848,14 +1974,15 @@ EngineControl::check_audio_latency_measurement () solid = 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; } - lm_results.set_markup (string_compose (results_markup, buf)); - return true; } @@ -1904,9 +2031,16 @@ EngineControl::check_midi_latency_measurement () } if (solid) { + have_lm_results = true; end_latency_detection (); lm_use_button.set_sensitive (true); - have_lm_results = true; + lm_results.set_markup (string_compose (results_markup, buf)); + 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)); @@ -1934,13 +2068,6 @@ EngineControl::start_latency_detection () 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 @@ -1950,8 +2077,6 @@ EngineControl::end_latency_detection () 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); @@ -2025,8 +2150,10 @@ EngineControl::engine_running () sample_rate_combo.set_sensitive (true); connect_disconnect_button.set_label (string_compose (_("Disconnect from %1"), backend->name())); + connect_disconnect_button.show(); started_at_least_once = true; + engine_status.set_markup(string_compose ("%1", _("Active"))); } void @@ -2037,9 +2164,11 @@ EngineControl::engine_stopped () buffer_size_combo.set_sensitive (false); connect_disconnect_button.set_label (string_compose (_("Connect to %1"), backend->name())); + connect_disconnect_button.show(); sample_rate_combo.set_sensitive (true); buffer_size_combo.set_sensitive (true); + engine_status.set_markup(string_compose ("%1", _("Inactive"))); } void @@ -2055,7 +2184,10 @@ EngineControl::connect_disconnect_click() 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); } @@ -2063,6 +2195,9 @@ void 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); }