2 Copyright (C) 2010 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <boost/scoped_ptr.hpp>
27 #include <gtkmm/messagedialog.h>
29 #include "pbd/error.h"
30 #include "pbd/locale_guard.h"
31 #include "pbd/xml++.h"
32 #include "pbd/unwind.h"
33 #include "pbd/failed_constructor.h"
35 #include <gtkmm/alignment.h>
36 #include <gtkmm/stock.h>
37 #include <gtkmm/notebook.h>
38 #include <gtkmm2ext/utils.h>
40 #include "ardour/audio_backend.h"
41 #include "ardour/audioengine.h"
42 #include "ardour/mtdm.h"
43 #include "ardour/mididm.h"
44 #include "ardour/rc_configuration.h"
45 #include "ardour/types.h"
46 #include "ardour/profile.h"
48 #include "pbd/convert.h"
49 #include "pbd/error.h"
53 #include "ardour_ui.h"
54 #include "engine_dialog.h"
55 #include "gui_thread.h"
56 #include "ui_config.h"
57 #include "public_editor.h"
64 using namespace Gtkmm2ext;
67 using namespace ArdourWidgets;
68 using namespace ARDOUR_UI_UTILS;
70 #define DEBUG_ECONTROL(msg) DEBUG_TRACE (PBD::DEBUG::EngineControl, string_compose ("%1: %2\n", __LINE__, msg));
72 static const unsigned int midi_tab = 2;
73 static const unsigned int latency_tab = 1; /* zero-based, page zero is the main setup page */
75 static const char* results_markup = X_("<span weight=\"bold\" size=\"larger\">%1</span>");
77 EngineControl::EngineControl ()
78 : ArdourDialog (_("Audio/MIDI Setup"))
81 , input_latency_adjustment (0, 0, 99999, 1)
82 , input_latency (input_latency_adjustment)
83 , output_latency_adjustment (0, 0, 99999, 1)
84 , output_latency (output_latency_adjustment)
85 , input_channels_adjustment (0, 0, 256, 1)
86 , input_channels (input_channels_adjustment)
87 , output_channels_adjustment (0, 0, 256, 1)
88 , output_channels (output_channels_adjustment)
89 , ports_adjustment (128, 8, 1024, 1, 16)
90 , ports_spinner (ports_adjustment)
91 , control_app_button (_("Device Control Panel"))
92 , midi_devices_button (_("Midi Device Setup"))
93 , start_stop_button (_("Stop"))
94 , update_devices_button (_("Refresh Devices"))
95 , use_buffered_io_button (_("Use Buffered I/O"), ArdourButton::led_default_elements)
96 , lm_measure_label (_("Measure"))
97 , lm_use_button (_("Use results"))
98 , lm_back_button (_("Back to settings ... (ignore results)"))
99 , lm_button_audio (_("Calibrate Audio"))
101 , have_lm_results (false)
103 , midi_back_button (_("Back to settings"))
105 , ignore_device_changes (0)
106 , _desired_sample_rate (0)
107 , started_at_least_once (false)
108 , queue_device_changed (false)
109 , _have_control (true)
112 using namespace Notebook_Helpers;
113 vector<string> backend_names;
115 AttachOptions xopt = AttachOptions (FILL|EXPAND);
118 set_name (X_("AudioMIDISetup"));
120 /* the backend combo is the one thing that is ALWAYS visible */
122 vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
124 if (backends.empty()) {
125 MessageDialog msg (string_compose (_("No audio/MIDI backends detected. %1 cannot run\n\n(This is a build/packaging/system error. It should never happen.)"), PROGRAM_NAME));
127 throw failed_constructor ();
130 for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
131 backend_names.push_back ((*b)->name);
134 set_popdown_strings (backend_combo, backend_names);
136 /* setup basic packing characteristics for the table used on the main
137 * tab of the notebook
140 basic_packer.set_spacings (6);
141 basic_packer.set_border_width (12);
142 basic_packer.set_homogeneous (false);
146 basic_hbox.pack_start (basic_packer, false, false);
148 /* latency measurement tab */
150 lm_title.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Latency Measurement Tool")));
153 lm_table.set_row_spacings (12);
154 lm_table.set_col_spacings (6);
155 lm_table.set_homogeneous (false);
157 lm_table.attach (lm_title, 0, 3, row, row+1, xopt, (AttachOptions) 0);
160 lm_preamble.set_width_chars (60);
161 lm_preamble.set_line_wrap (true);
162 lm_preamble.set_markup (_("<span weight=\"bold\">Turn down the volume on your audio equipment to a very low level.</span>"));
164 lm_table.attach (lm_preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
167 Gtk::Label* preamble;
168 preamble = manage (new Label);
169 preamble->set_width_chars (60);
170 preamble->set_line_wrap (true);
171 preamble->set_markup (_("Select two channels below and connect them using a cable."));
173 lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
176 label = manage (new Label (_("Output channel:")));
177 lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
179 lm_output_channel_list = Gtk::ListStore::create (lm_output_channel_cols);
180 lm_output_channel_combo.set_model (lm_output_channel_list);
181 lm_output_channel_combo.pack_start (lm_output_channel_cols.pretty_name);
183 Gtk::Alignment* misc_align = manage (new Alignment (0.0, 0.5));
184 misc_align->add (lm_output_channel_combo);
185 lm_table.attach (*misc_align, 1, 3, row, row+1, xopt, (AttachOptions) 0);
188 label = manage (new Label (_("Input channel:")));
189 lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
191 lm_input_channel_list = Gtk::ListStore::create (lm_input_channel_cols);
192 lm_input_channel_combo.set_model (lm_input_channel_list);
193 lm_input_channel_combo.pack_start (lm_input_channel_cols.pretty_name);
195 misc_align = manage (new Alignment (0.0, 0.5));
196 misc_align->add (lm_input_channel_combo);
197 lm_table.attach (*misc_align, 1, 3, row, row+1, FILL, (AttachOptions) 0);
200 lm_measure_label.set_padding (10, 10);
201 lm_measure_button.add (lm_measure_label);
202 lm_measure_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::latency_button_clicked));
203 lm_use_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::use_latency_button_clicked));
204 lm_back_button_signal = lm_back_button.signal_clicked().connect(
205 sigc::mem_fun(*this, &EngineControl::latency_back_button_clicked));
207 lm_use_button.set_sensitive (false);
209 /* Increase the default spacing around the labels of these three
215 if ((l = dynamic_cast<Gtk::Misc*>(lm_use_button.get_child())) != 0) {
216 l->set_padding (10, 10);
219 if ((l = dynamic_cast<Gtk::Misc*>(lm_back_button.get_child())) != 0) {
220 l->set_padding (10, 10);
223 preamble = manage (new Label);
224 preamble->set_width_chars (60);
225 preamble->set_line_wrap (true);
226 preamble->set_markup (_("Once the channels are connected, click the \"Measure\" button."));
227 lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
230 preamble = manage (new Label);
231 preamble->set_width_chars (60);
232 preamble->set_line_wrap (true);
233 preamble->set_markup (_("When satisfied with the results, click the \"Use results\" button."));
234 lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
236 ++row; // skip a row in the table
237 ++row; // skip a row in the table
239 lm_table.attach (lm_results, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
241 ++row; // skip a row in the table
242 ++row; // skip a row in the table
244 lm_table.attach (lm_measure_button, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
245 lm_table.attach (lm_use_button, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
246 lm_table.attach (lm_back_button, 2, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
248 lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
250 lm_vbox.set_border_width (12);
251 lm_vbox.pack_start (lm_table, false, false);
253 midi_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
257 notebook.pages().push_back (TabElem (basic_vbox, _("Audio")));
258 notebook.pages().push_back (TabElem (lm_vbox, _("Latency")));
259 notebook.pages().push_back (TabElem (midi_vbox, _("MIDI")));
260 notebook.set_border_width (12);
262 notebook.set_show_tabs (false);
263 notebook.show_all ();
265 notebook.set_name ("SettingsNotebook");
267 /* packup the notebook */
269 get_vbox()->set_border_width (12);
270 get_vbox()->pack_start (notebook);
272 /* need a special function to print "all available channels" when the
273 * channel counts hit zero.
276 input_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &input_channels));
277 output_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &output_channels));
279 midi_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::configure_midi_devices));
280 midi_devices_button.set_name ("generic button");
281 midi_devices_button.set_can_focus(true);
283 control_app_button.signal_clicked.connect (mem_fun (*this, &EngineControl::control_app_button_clicked));
284 control_app_button.set_name ("generic button");
285 control_app_button.set_can_focus(true);
286 manage_control_app_sensitivity ();
288 start_stop_button.signal_clicked.connect (mem_fun (*this, &EngineControl::start_stop_button_clicked));
289 start_stop_button.set_sensitive (false);
290 start_stop_button.set_name ("generic button");
291 start_stop_button.set_can_focus(true);
292 start_stop_button.set_can_default(true);
293 start_stop_button.set_act_on_release (false);
295 update_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::update_devices_button_clicked));
296 update_devices_button.set_sensitive (false);
297 update_devices_button.set_name ("generic button");
298 update_devices_button.set_can_focus(true);
300 use_buffered_io_button.signal_clicked.connect (mem_fun (*this, &EngineControl::use_buffered_io_button_clicked));
301 use_buffered_io_button.set_sensitive (false);
302 use_buffered_io_button.set_name ("generic button");
303 use_buffered_io_button.set_can_focus(true);
305 /* Pick up any existing audio setup configuration, if appropriate */
307 XMLNode* audio_setup = ARDOUR::Config->extra_xml ("AudioMIDISetup");
309 ARDOUR::AudioEngine::instance()->Running.connect (running_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_running, this), gui_context());
310 ARDOUR::AudioEngine::instance()->Stopped.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
311 ARDOUR::AudioEngine::instance()->Halted.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
312 ARDOUR::AudioEngine::instance()->DeviceListChanged.connect (devicelist_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::device_list_changed, this), gui_context());
315 if (!set_state (*audio_setup)) {
316 set_default_state ();
319 set_default_state ();
322 update_sensitivity ();
323 connect_changed_signals ();
325 notebook.signal_switch_page().connect (sigc::mem_fun (*this, &EngineControl::on_switch_page));
327 connect_disconnect_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::connect_disconnect_click));
329 connect_disconnect_button.set_no_show_all();
330 use_buffered_io_button.set_no_show_all();
331 update_devices_button.set_no_show_all();
332 start_stop_button.set_no_show_all();
333 midi_devices_button.set_no_show_all();
337 EngineControl::connect_changed_signals ()
339 backend_combo_connection = backend_combo.signal_changed ().connect (
340 sigc::mem_fun (*this, &EngineControl::backend_changed));
341 driver_combo_connection = driver_combo.signal_changed ().connect (
342 sigc::mem_fun (*this, &EngineControl::driver_changed));
343 sample_rate_combo_connection = sample_rate_combo.signal_changed ().connect (
344 sigc::mem_fun (*this, &EngineControl::sample_rate_changed));
345 buffer_size_combo_connection = buffer_size_combo.signal_changed ().connect (
346 sigc::mem_fun (*this, &EngineControl::buffer_size_changed));
347 nperiods_combo_connection = nperiods_combo.signal_changed ().connect (
348 sigc::mem_fun (*this, &EngineControl::nperiods_changed));
349 device_combo_connection = device_combo.signal_changed ().connect (
350 sigc::mem_fun (*this, &EngineControl::device_changed));
351 midi_option_combo_connection = midi_option_combo.signal_changed ().connect (
352 sigc::mem_fun (*this, &EngineControl::midi_option_changed));
354 input_device_combo_connection = input_device_combo.signal_changed ().connect (
355 sigc::mem_fun (*this, &EngineControl::input_device_changed));
356 output_device_combo_connection = output_device_combo.signal_changed ().connect (
357 sigc::mem_fun (*this, &EngineControl::output_device_changed));
359 input_latency_connection = input_latency.signal_changed ().connect (
360 sigc::mem_fun (*this, &EngineControl::parameter_changed));
361 output_latency_connection = output_latency.signal_changed ().connect (
362 sigc::mem_fun (*this, &EngineControl::parameter_changed));
363 input_channels_connection = input_channels.signal_changed ().connect (
364 sigc::mem_fun (*this, &EngineControl::parameter_changed));
365 output_channels_connection = output_channels.signal_changed ().connect (
366 sigc::mem_fun (*this, &EngineControl::parameter_changed));
370 EngineControl::block_changed_signals ()
372 if (block_signals++ == 0) {
373 DEBUG_ECONTROL ("Blocking changed signals");
374 backend_combo_connection.block ();
375 driver_combo_connection.block ();
376 sample_rate_combo_connection.block ();
377 buffer_size_combo_connection.block ();
378 nperiods_combo_connection.block ();
379 device_combo_connection.block ();
380 input_device_combo_connection.block ();
381 output_device_combo_connection.block ();
382 midi_option_combo_connection.block ();
383 input_latency_connection.block ();
384 output_latency_connection.block ();
385 input_channels_connection.block ();
386 output_channels_connection.block ();
391 EngineControl::unblock_changed_signals ()
393 if (--block_signals == 0) {
394 DEBUG_ECONTROL ("Unblocking changed signals");
395 backend_combo_connection.unblock ();
396 driver_combo_connection.unblock ();
397 sample_rate_combo_connection.unblock ();
398 buffer_size_combo_connection.unblock ();
399 nperiods_combo_connection.unblock ();
400 device_combo_connection.unblock ();
401 input_device_combo_connection.unblock ();
402 output_device_combo_connection.unblock ();
403 midi_option_combo_connection.unblock ();
404 input_latency_connection.unblock ();
405 output_latency_connection.unblock ();
406 input_channels_connection.unblock ();
407 output_channels_connection.unblock ();
411 EngineControl::SignalBlocker::SignalBlocker (EngineControl& engine_control,
412 const std::string& reason)
413 : ec (engine_control)
416 DEBUG_ECONTROL (string_compose ("SignalBlocker: %1", m_reason));
417 ec.block_changed_signals ();
420 EngineControl::SignalBlocker::~SignalBlocker ()
422 DEBUG_ECONTROL (string_compose ("~SignalBlocker: %1", m_reason));
423 ec.unblock_changed_signals ();
427 EngineControl::on_show ()
429 ArdourDialog::on_show ();
430 if (!ARDOUR::AudioEngine::instance()->current_backend() || !ARDOUR::AudioEngine::instance()->running()) {
431 // re-check _have_control (jackd running) see #6041
435 start_stop_button.grab_focus();
439 EngineControl::on_map ()
441 if (!ARDOUR_UI::instance()->the_session () && !PublicEditor::_instance) {
442 set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
443 } else if (UIConfiguration::instance().get_all_floating_windows_are_dialogs()) {
444 set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
446 set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
448 ArdourDialog::on_map ();
452 EngineControl::try_autostart ()
454 if (!start_stop_button.get_sensitive()) {
457 if (ARDOUR::AudioEngine::instance()->running()) {
460 return start_engine ();
464 EngineControl::start_engine ()
466 if (push_state_to_backend(true) != 0) {
467 MessageDialog msg(*this,
468 ARDOUR::AudioEngine::instance()->get_last_backend_error());
476 EngineControl::stop_engine (bool for_latency)
478 if (ARDOUR::AudioEngine::instance()->stop(for_latency)) {
479 MessageDialog msg(*this,
480 ARDOUR::AudioEngine::instance()->get_last_backend_error());
488 EngineControl::build_notebook ()
491 AttachOptions xopt = AttachOptions (FILL|EXPAND);
493 /* clear the table */
495 Gtkmm2ext::container_clear (basic_vbox);
496 Gtkmm2ext::container_clear (basic_packer);
498 if (control_app_button.get_parent()) {
499 control_app_button.get_parent()->remove (control_app_button);
502 label = manage (left_aligned_label (_("Audio System:")));
503 basic_packer.attach (*label, 0, 1, 0, 1, xopt, (AttachOptions) 0);
504 basic_packer.attach (backend_combo, 1, 2, 0, 1, xopt, (AttachOptions) 0);
506 basic_packer.attach (engine_status, 2, 3, 0, 1, xopt, (AttachOptions) 0);
507 engine_status.show();
509 basic_packer.attach (start_stop_button, 3, 4, 0, 1, xopt, xopt);
510 basic_packer.attach (update_devices_button, 3, 4, 1, 2, xopt, xopt);
511 basic_packer.attach (use_buffered_io_button, 3, 4, 2, 3, xopt, xopt);
513 lm_button_audio.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_audio_latency));
514 lm_button_audio.set_name ("generic button");
515 lm_button_audio.set_can_focus(true);
518 build_full_control_notebook ();
520 build_no_control_notebook ();
523 basic_vbox.pack_start (basic_hbox, false, false);
526 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
527 basic_vbox.show_all ();
532 EngineControl::build_full_control_notebook ()
534 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
537 using namespace Notebook_Helpers;
539 vector<string> strings;
540 AttachOptions xopt = AttachOptions (FILL|EXPAND);
541 int row = 1; // row zero == backend combo
543 /* start packing it up */
545 if (backend->requires_driver_selection()) {
546 label = manage (left_aligned_label (_("Driver:")));
547 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
548 basic_packer.attach (driver_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
552 if (backend->use_separate_input_and_output_devices()) {
553 label = manage (left_aligned_label (_("Input Device:")));
554 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
555 basic_packer.attach (input_device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
557 label = manage (left_aligned_label (_("Output Device:")));
558 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
559 basic_packer.attach (output_device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
561 // reset so it isn't used in state comparisons
562 device_combo.set_active_text ("");
564 label = manage (left_aligned_label (_("Device:")));
565 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
566 basic_packer.attach (device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
568 // reset these so they don't get used in state comparisons
569 input_device_combo.set_active_text ("");
570 output_device_combo.set_active_text ("");
573 label = manage (left_aligned_label (_("Sample rate:")));
574 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
575 basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
579 label = manage (left_aligned_label (_("Buffer size:")));
580 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
581 basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
582 buffer_size_duration_label.set_alignment (0.0); /* left-align */
583 basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
585 int ctrl_btn_span = 1;
586 if (backend->can_set_period_size ()) {
588 label = manage (left_aligned_label (_("Periods:")));
589 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
590 basic_packer.attach (nperiods_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
594 /* button spans 2 or 3 rows */
596 basic_packer.attach (control_app_button, 3, 4, row - ctrl_btn_span, row + 1, xopt, xopt);
599 input_channels.set_name ("InputChannels");
600 input_channels.set_flags (Gtk::CAN_FOCUS);
601 input_channels.set_digits (0);
602 input_channels.set_wrap (false);
603 output_channels.set_editable (true);
605 if (!ARDOUR::Profile->get_mixbus()) {
606 label = manage (left_aligned_label (_("Input channels:")));
607 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
608 basic_packer.attach (input_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
612 output_channels.set_name ("OutputChannels");
613 output_channels.set_flags (Gtk::CAN_FOCUS);
614 output_channels.set_digits (0);
615 output_channels.set_wrap (false);
616 output_channels.set_editable (true);
618 if (!ARDOUR::Profile->get_mixbus()) {
619 label = manage (left_aligned_label (_("Output channels:")));
620 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
621 basic_packer.attach (output_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
625 input_latency.set_name ("InputLatency");
626 input_latency.set_flags (Gtk::CAN_FOCUS);
627 input_latency.set_digits (0);
628 input_latency.set_wrap (false);
629 input_latency.set_editable (true);
631 label = manage (left_aligned_label (_("Hardware input latency:")));
632 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
633 basic_packer.attach (input_latency, 1, 2, row, row+1, xopt, (AttachOptions) 0);
634 label = manage (left_aligned_label (_("samples")));
635 basic_packer.attach (*label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
638 output_latency.set_name ("OutputLatency");
639 output_latency.set_flags (Gtk::CAN_FOCUS);
640 output_latency.set_digits (0);
641 output_latency.set_wrap (false);
642 output_latency.set_editable (true);
644 label = manage (left_aligned_label (_("Hardware output latency:")));
645 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
646 basic_packer.attach (output_latency, 1, 2, row, row+1, xopt, (AttachOptions) 0);
647 label = manage (left_aligned_label (_("samples")));
648 basic_packer.attach (*label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
650 /* button spans 2 rows */
652 basic_packer.attach (lm_button_audio, 3, 4, row-1, row+1, xopt, xopt);
655 label = manage (left_aligned_label (_("MIDI System:")));
656 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
657 basic_packer.attach (midi_option_combo, 1, 2, row, row + 1, SHRINK, (AttachOptions) 0);
658 basic_packer.attach (midi_devices_button, 3, 4, row, row+1, xopt, xopt);
663 EngineControl::build_no_control_notebook ()
665 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
668 using namespace Notebook_Helpers;
670 vector<string> strings;
671 AttachOptions xopt = AttachOptions (FILL|EXPAND);
672 int row = 1; // row zero == backend combo
673 const string msg = string_compose (_("%1 is already running. %2 will connect to it and use the existing settings."), backend->name(), PROGRAM_NAME);
675 label = manage (new Label);
676 label->set_markup (string_compose ("<span weight=\"bold\" foreground=\"red\">%1</span>", msg));
677 basic_packer.attach (*label, 0, 2, row, row + 1, xopt, (AttachOptions) 0);
680 if (backend->can_change_sample_rate_when_running()) {
681 label = manage (left_aligned_label (_("Sample rate:")));
682 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
683 basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
687 if (backend->can_change_buffer_size_when_running()) {
688 label = manage (left_aligned_label (_("Buffer size:")));
689 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
690 basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
691 buffer_size_duration_label.set_alignment (0.0); /* left-align */
692 basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, xopt, (AttachOptions) 0);
696 basic_packer.attach (connect_disconnect_button, 0, 2, row, row+1, FILL, AttachOptions (0));
700 EngineControl::~EngineControl ()
702 ignore_changes = true;
706 EngineControl::disable_latency_tab ()
708 lm_input_channel_list->clear ();
709 lm_output_channel_list->clear ();
710 lm_measure_button.set_sensitive (false);
711 lm_use_button.set_sensitive (false);
715 EngineControl::enable_latency_tab ()
717 vector<string> outputs;
718 vector<string> inputs;
720 ARDOUR::DataType const type = _measure_midi ? ARDOUR::DataType::MIDI : ARDOUR::DataType::AUDIO;
721 ARDOUR::AudioEngine::instance()->get_physical_outputs (type, outputs);
722 ARDOUR::AudioEngine::instance()->get_physical_inputs (type, inputs);
724 if (!ARDOUR::AudioEngine::instance()->running()) {
725 MessageDialog msg (_("Failed to start or connect to audio-engine.\n\nLatency calibration requires a working audio interface."));
726 notebook.set_current_page (0);
730 else if (inputs.empty() || outputs.empty()) {
731 MessageDialog msg (_("Your selected audio configuration is playback- or capture-only.\n\nLatency calibration requires playback and capture"));
732 notebook.set_current_page (0);
737 lm_back_button_signal.disconnect();
739 lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), midi_tab));
742 lm_back_button_signal = lm_back_button.signal_clicked().connect(
743 sigc::mem_fun(*this, &EngineControl::latency_back_button_clicked));
747 lm_output_channel_list->clear ();
748 for (vector<string>::const_iterator i = outputs.begin(); i != outputs.end(); ++i) {
749 Gtk::TreeModel::iterator iter = lm_output_channel_list->append ();
750 Gtk::TreeModel::Row row = *iter;
751 row[lm_output_channel_cols.port_name] = *i;
752 row[lm_output_channel_cols.pretty_name] = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*i);
754 lm_output_channel_combo.set_active (0);
755 lm_output_channel_combo.set_sensitive (true);
757 lm_input_channel_list->clear ();
758 for (vector<string>::const_iterator i = inputs.begin(); i != inputs.end(); ++i) {
759 Gtk::TreeModel::iterator iter = lm_input_channel_list->append ();
760 Gtk::TreeModel::Row row = *iter;
761 row[lm_input_channel_cols.port_name] = *i;
762 row[lm_input_channel_cols.pretty_name] = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*i);
764 lm_input_channel_combo.set_active (0);
765 lm_input_channel_combo.set_sensitive (true);
767 lm_measure_button.set_sensitive (true);
771 EngineControl::setup_midi_tab_for_backend ()
773 string backend = backend_combo.get_active_text ();
775 Gtkmm2ext::container_clear (midi_vbox);
777 midi_vbox.set_border_width (12);
778 midi_device_table.set_border_width (12);
780 if (backend == "JACK") {
781 setup_midi_tab_for_jack ();
784 midi_vbox.pack_start (midi_device_table, true, true);
785 midi_vbox.pack_start (midi_back_button, false, false);
786 midi_vbox.show_all ();
790 EngineControl::update_sensitivity ()
792 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
794 start_stop_button.set_sensitive (false);
799 size_t devices_available = 0;
800 bool engine_running = ARDOUR::AudioEngine::instance()->running();
802 if (backend->use_separate_input_and_output_devices ()) {
803 devices_available += get_popdown_string_count (input_device_combo);
804 devices_available += get_popdown_string_count (output_device_combo);
806 devices_available += get_popdown_string_count (device_combo);
809 if (devices_available == 0) {
811 input_latency.set_sensitive (false);
812 output_latency.set_sensitive (false);
813 input_channels.set_sensitive (false);
814 output_channels.set_sensitive (false);
816 input_latency.set_sensitive (true);
817 output_latency.set_sensitive (true);
818 input_channels.set_sensitive (!engine_running);
819 output_channels.set_sensitive (!engine_running);
822 if (get_popdown_string_count (buffer_size_combo) > 0) {
823 if (!engine_running) {
824 buffer_size_combo.set_sensitive (valid);
825 } else if (backend->can_change_buffer_size_when_running ()) {
826 buffer_size_combo.set_sensitive (valid || !_have_control);
828 buffer_size_combo.set_sensitive (false);
831 buffer_size_combo.set_sensitive (false);
835 if (get_popdown_string_count (sample_rate_combo) > 0) {
836 bool allow_to_set_rate = false;
837 if (!engine_running) {
838 if (!ARDOUR_UI::instance()->the_session ()) {
839 // engine is not running, no session loaded -> anything goes.
840 allow_to_set_rate = true;
841 } else if (_desired_sample_rate > 0 && get_rate () != _desired_sample_rate) {
842 // only allow to change if the current setting is not the native session rate.
843 allow_to_set_rate = true;
846 sample_rate_combo.set_sensitive (allow_to_set_rate);
848 sample_rate_combo.set_sensitive (false);
852 if (get_popdown_string_count (nperiods_combo) > 0) {
853 if (!engine_running) {
854 nperiods_combo.set_sensitive (true);
856 nperiods_combo.set_sensitive (false);
859 nperiods_combo.set_sensitive (false);
863 start_stop_button.set_sensitive(true);
864 start_stop_button.show();
865 if (engine_running) {
866 start_stop_button.set_text("Stop");
867 update_devices_button.set_sensitive(false);
868 use_buffered_io_button.set_sensitive(false);
870 if (backend->can_request_update_devices()) {
871 update_devices_button.show();
873 update_devices_button.hide();
875 if (backend->can_use_buffered_io()) {
876 use_buffered_io_button.show();
878 use_buffered_io_button.hide();
880 start_stop_button.set_text("Start");
881 update_devices_button.set_sensitive(true);
882 use_buffered_io_button.set_sensitive(true);
885 update_devices_button.set_sensitive(false);
886 update_devices_button.hide();
887 use_buffered_io_button.set_sensitive(false);
888 use_buffered_io_button.hide();
889 start_stop_button.set_sensitive(false);
890 start_stop_button.hide();
893 if (engine_running && _have_control) {
894 input_device_combo.set_sensitive (false);
895 output_device_combo.set_sensitive (false);
896 device_combo.set_sensitive (false);
897 driver_combo.set_sensitive (false);
899 input_device_combo.set_sensitive (true);
900 output_device_combo.set_sensitive (true);
901 device_combo.set_sensitive (true);
902 if (backend->requires_driver_selection() && get_popdown_string_count(driver_combo) > 0) {
903 driver_combo.set_sensitive (true);
905 driver_combo.set_sensitive (false);
909 midi_option_combo.set_sensitive (!engine_running);
913 EngineControl::setup_midi_tab_for_jack ()
918 EngineControl::midi_latency_adjustment_changed (Gtk::Adjustment *a, MidiDeviceSettings device, bool for_input) {
920 device->input_latency = a->get_value();
922 device->output_latency = a->get_value();
925 if (ARDOUR::AudioEngine::instance()->running() && !_measure_midi) {
926 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
928 if (backend->can_change_systemic_latency_when_running () && device->enabled) {
930 backend->set_systemic_midi_input_latency (device->name, device->input_latency);
932 backend->set_systemic_midi_output_latency (device->name, device->output_latency);
939 EngineControl::midi_device_enabled_toggled (ArdourButton *b, MidiDeviceSettings device) {
940 b->set_active (!b->get_active());
941 device->enabled = b->get_active();
942 refresh_midi_display(device->name);
944 if (ARDOUR::AudioEngine::instance()->running()) {
945 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
947 backend->set_midi_device_enabled (device->name, device->enabled);
948 if (backend->can_change_systemic_latency_when_running () && device->enabled) {
949 backend->set_systemic_midi_input_latency (device->name, device->input_latency);
950 backend->set_systemic_midi_output_latency (device->name, device->output_latency);
956 EngineControl::refresh_midi_display (std::string focus)
958 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
962 AttachOptions xopt = AttachOptions (FILL|EXPAND);
965 Gtkmm2ext::container_clear (midi_device_table);
967 midi_device_table.set_spacings (6);
969 l = manage (new Label);
970 l->set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Devices")));
971 midi_device_table.attach (*l, 0, 4, row, row + 1, xopt, AttachOptions (0));
972 l->set_alignment (0.5, 0.5);
976 l = manage (new Label (_("Device"))); l->show (); l->set_alignment (0.5, 0.5);
977 midi_device_table.attach (*l, 0, 1, row, row + 2, xopt, AttachOptions (0));
978 l = manage (new Label (_("Systemic Latency [samples]"))); l->show (); l->set_alignment (0.5, 0.5);
979 midi_device_table.attach (*l, 1, 3, row, row + 1, xopt, AttachOptions (0));
981 l = manage (new Label (_("Input"))); l->show (); l->set_alignment (0.5, 0.5);
982 midi_device_table.attach (*l, 1, 2, row, row + 1, xopt, AttachOptions (0));
983 l = manage (new Label (_("Output"))); l->show (); l->set_alignment (0.5, 0.5);
984 midi_device_table.attach (*l, 2, 3, row, row + 1, xopt, AttachOptions (0));
987 for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
992 bool enabled = (*p)->enabled;
994 m = manage (new ArdourButton ((*p)->name, ArdourButton::led_default_elements));
995 m->set_name ("midi device");
996 m->set_can_focus (Gtk::CAN_FOCUS);
997 m->add_events (Gdk::BUTTON_RELEASE_MASK);
998 m->set_active (enabled);
999 m->signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_device_enabled_toggled), m, *p));
1000 midi_device_table.attach (*m, 0, 1, row, row + 1, xopt, AttachOptions (0)); m->show ();
1001 if ((*p)->name == focus) {
1005 a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
1006 s = manage (new Gtk::SpinButton (*a));
1007 a->set_value ((*p)->input_latency);
1008 s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, true));
1009 s->set_sensitive (_can_set_midi_latencies && enabled);
1010 midi_device_table.attach (*s, 1, 2, row, row + 1, xopt, AttachOptions (0)); s->show ();
1012 a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
1013 s = manage (new Gtk::SpinButton (*a));
1014 a->set_value ((*p)->output_latency);
1015 s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, false));
1016 s->set_sensitive (_can_set_midi_latencies && enabled);
1017 midi_device_table.attach (*s, 2, 3, row, row + 1, xopt, AttachOptions (0)); s->show ();
1019 b = manage (new Button (_("Calibrate")));
1020 b->signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::calibrate_midi_latency), *p));
1021 b->set_sensitive (_can_set_midi_latencies && enabled);
1022 midi_device_table.attach (*b, 3, 4, row, row + 1, xopt, AttachOptions (0)); b->show ();
1029 EngineControl::backend_changed ()
1031 SignalBlocker blocker (*this, "backend_changed");
1032 string backend_name = backend_combo.get_active_text();
1033 boost::shared_ptr<ARDOUR::AudioBackend> backend;
1035 if (!(backend = ARDOUR::AudioEngine::instance()->set_backend (backend_name, downcase (std::string(PROGRAM_NAME)), ""))) {
1036 /* eh? setting the backend failed... how ? */
1037 /* A: stale config contains a backend that does not exist in current build */
1041 DEBUG_ECONTROL (string_compose ("Backend name: %1", backend_name));
1043 _have_control = ARDOUR::AudioEngine::instance()->setup_required ();
1046 setup_midi_tab_for_backend ();
1047 _midi_devices.clear();
1049 if (backend->requires_driver_selection()) {
1050 if (set_driver_popdown_strings ()) {
1054 /* this will change the device text which will cause a call to
1055 * device changed which will set up parameters
1060 update_midi_options ();
1062 connect_disconnect_button.hide();
1064 midi_option_changed();
1066 started_at_least_once = false;
1068 /* changing the backend implies stopping the engine
1069 * ARDOUR::AudioEngine() may or may not emit this signal
1070 * depending on previous engine state
1072 engine_stopped (); // set "active/inactive"
1074 if (!_have_control) {
1075 // set settings from backend that we do have control over
1076 set_buffersize_popdown_strings ();
1077 set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
1080 if (_have_control && !ignore_changes) {
1081 // set driver & devices
1082 State state = get_matching_state (backend_combo.get_active_text());
1084 DEBUG_ECONTROL ("backend-changed(): found prior state for backend");
1085 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1086 set_current_state (state);
1088 DEBUG_ECONTROL ("backend-changed(): no prior state for backend");
1091 DEBUG_ECONTROL (string_compose ("backend-changed(): _have_control=%1 ignore_changes=%2", _have_control, ignore_changes));
1094 if (!ignore_changes) {
1095 maybe_display_saved_state ();
1100 EngineControl::update_midi_options ()
1102 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1103 vector<string> midi_options = backend->enumerate_midi_options();
1105 if (midi_options.size() == 1) {
1106 /* only contains the "none" option */
1107 midi_option_combo.set_sensitive (false);
1109 if (_have_control) {
1110 set_popdown_strings (midi_option_combo, midi_options);
1111 midi_option_combo.set_active_text (midi_options.front());
1112 midi_option_combo.set_sensitive (true);
1114 midi_option_combo.set_sensitive (false);
1120 EngineControl::print_channel_count (Gtk::SpinButton* sb)
1122 if (ARDOUR::Profile->get_mixbus()) {
1126 uint32_t cnt = (uint32_t) sb->get_value();
1128 sb->set_text (_("all available channels"));
1131 snprintf (buf, sizeof (buf), "%d", cnt);
1137 // @return true if there are drivers available
1139 EngineControl::set_driver_popdown_strings ()
1141 DEBUG_ECONTROL ("set_driver_popdown_strings");
1142 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1143 vector<string> drivers = backend->enumerate_drivers();
1145 if (drivers.empty ()) {
1146 // This is an error...?
1150 string current_driver = backend->driver_name ();
1152 DEBUG_ECONTROL (string_compose ("backend->driver_name: %1", current_driver));
1154 if (std::find (drivers.begin (), drivers.end (), current_driver) ==
1157 current_driver = drivers.front ();
1160 set_popdown_strings (driver_combo, drivers);
1162 string_compose ("driver_combo.set_active_text: %1", current_driver));
1163 driver_combo.set_active_text (current_driver);
1168 EngineControl::get_default_device(const string& current_device_name,
1169 const vector<string>& available_devices)
1171 // If the current device is available, use it as default
1172 if (std::find (available_devices.begin (),
1173 available_devices.end (),
1174 current_device_name) != available_devices.end ()) {
1176 return current_device_name;
1179 using namespace ARDOUR;
1181 string default_device_name =
1182 AudioBackend::get_standard_device_name(AudioBackend::DeviceDefault);
1184 vector<string>::const_iterator i;
1186 // If there is a "Default" device available, use it
1187 for (i = available_devices.begin(); i != available_devices.end(); ++i) {
1188 if (*i == default_device_name) {
1193 string none_device_name =
1194 AudioBackend::get_standard_device_name(AudioBackend::DeviceNone);
1196 // Use the first device that isn't "None"
1197 for (i = available_devices.begin(); i != available_devices.end(); ++i) {
1198 if (*i != none_device_name) {
1203 // Use "None" if there are no other available
1204 return available_devices.front();
1207 // @return true if there are devices available
1209 EngineControl::set_device_popdown_strings ()
1211 DEBUG_ECONTROL ("set_device_popdown_strings");
1212 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1213 vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_devices ();
1215 /* NOTE: Ardour currently does not display the "available" field of the
1218 * Doing so would require a different GUI widget than the combo
1219 * box/popdown that we currently use, since it has no way to list
1220 * items that are not selectable. Something more like a popup menu,
1221 * which could have unselectable items, would be appropriate.
1224 vector<string> available_devices;
1226 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1227 available_devices.push_back (i->name);
1230 if (available_devices.empty ()) {
1234 set_popdown_strings (device_combo, available_devices);
1236 std::string default_device =
1237 get_default_device(backend->device_name(), available_devices);
1240 string_compose ("set device_combo active text: %1", default_device));
1242 device_combo.set_active_text(default_device);
1246 // @return true if there are input devices available
1248 EngineControl::set_input_device_popdown_strings ()
1250 DEBUG_ECONTROL ("set_input_device_popdown_strings");
1251 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1252 vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_input_devices ();
1254 vector<string> available_devices;
1256 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1257 available_devices.push_back (i->name);
1260 if (available_devices.empty()) {
1264 set_popdown_strings (input_device_combo, available_devices);
1266 std::string default_device =
1267 get_default_device(backend->input_device_name(), available_devices);
1270 string_compose ("set input_device_combo active text: %1", default_device));
1271 input_device_combo.set_active_text(default_device);
1275 // @return true if there are output devices available
1277 EngineControl::set_output_device_popdown_strings ()
1279 DEBUG_ECONTROL ("set_output_device_popdown_strings");
1280 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1281 vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_output_devices ();
1283 vector<string> available_devices;
1285 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1286 available_devices.push_back (i->name);
1289 if (available_devices.empty()) {
1293 set_popdown_strings (output_device_combo, available_devices);
1295 std::string default_device =
1296 get_default_device(backend->output_device_name(), available_devices);
1299 string_compose ("set output_device_combo active text: %1", default_device));
1300 output_device_combo.set_active_text(default_device);
1305 EngineControl::list_devices ()
1307 DEBUG_ECONTROL ("list_devices");
1308 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1311 /* now fill out devices, mark sample rates, buffer sizes insensitive */
1313 bool devices_available = false;
1315 if (backend->use_separate_input_and_output_devices ()) {
1316 bool input_devices_available = set_input_device_popdown_strings ();
1317 bool output_devices_available = set_output_device_popdown_strings ();
1318 devices_available = input_devices_available || output_devices_available;
1320 devices_available = set_device_popdown_strings ();
1323 if (devices_available) {
1326 device_combo.clear();
1327 input_device_combo.clear();
1328 output_device_combo.clear();
1330 update_sensitivity ();
1334 EngineControl::driver_changed ()
1336 SignalBlocker blocker (*this, "driver_changed");
1337 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1340 backend->set_driver (driver_combo.get_active_text());
1343 // TODO load LRU device(s) for backend + driver combo
1345 if (!ignore_changes) {
1346 maybe_display_saved_state ();
1351 EngineControl::get_sample_rates_for_all_devices ()
1353 boost::shared_ptr<ARDOUR::AudioBackend> backend =
1354 ARDOUR::AudioEngine::instance ()->current_backend ();
1355 vector<float> all_rates;
1357 if (backend->use_separate_input_and_output_devices ()) {
1358 all_rates = backend->available_sample_rates2 (get_input_device_name (), get_output_device_name ());
1360 all_rates = backend->available_sample_rates (get_device_name ());
1366 EngineControl::get_default_sample_rates ()
1368 vector<float> rates;
1369 rates.push_back (8000.0f);
1370 rates.push_back (16000.0f);
1371 rates.push_back (32000.0f);
1372 rates.push_back (44100.0f);
1373 rates.push_back (48000.0f);
1374 rates.push_back (88200.0f);
1375 rates.push_back (96000.0f);
1376 rates.push_back (192000.0f);
1377 rates.push_back (384000.0f);
1382 EngineControl::set_samplerate_popdown_strings ()
1384 DEBUG_ECONTROL ("set_samplerate_popdown_strings");
1385 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1390 if (_have_control) {
1391 sr = get_sample_rates_for_all_devices ();
1393 sr = get_default_sample_rates ();
1396 for (vector<float>::const_iterator x = sr.begin(); x != sr.end(); ++x) {
1397 s.push_back (rate_as_string (*x));
1398 if (*x == _desired_sample_rate) {
1403 set_popdown_strings (sample_rate_combo, s);
1406 if (ARDOUR::AudioEngine::instance()->running()) {
1407 sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
1408 } else if (ARDOUR_UI::instance()->the_session ()) {
1409 float active_sr = ARDOUR_UI::instance()->the_session()->nominal_sample_rate ();
1411 if (std::find (sr.begin (), sr.end (), active_sr) == sr.end ()) {
1412 active_sr = sr.front ();
1415 sample_rate_combo.set_active_text (rate_as_string (active_sr));
1416 } else if (desired.empty ()) {
1417 float new_active_sr = backend->default_sample_rate ();
1419 if (std::find (sr.begin (), sr.end (), new_active_sr) == sr.end ()) {
1420 new_active_sr = sr.front ();
1423 sample_rate_combo.set_active_text (rate_as_string (new_active_sr));
1425 sample_rate_combo.set_active_text (desired);
1428 update_sensitivity ();
1432 EngineControl::get_buffer_sizes_for_all_devices ()
1434 boost::shared_ptr<ARDOUR::AudioBackend> backend =
1435 ARDOUR::AudioEngine::instance ()->current_backend ();
1436 vector<uint32_t> all_sizes;
1438 if (backend->use_separate_input_and_output_devices ()) {
1439 all_sizes = backend->available_buffer_sizes2 (get_input_device_name (), get_output_device_name ());
1441 all_sizes = backend->available_buffer_sizes (get_device_name ());
1447 EngineControl::get_default_buffer_sizes ()
1449 vector<uint32_t> sizes;
1450 sizes.push_back (8);
1451 sizes.push_back (16);
1452 sizes.push_back (32);
1453 sizes.push_back (64);
1454 sizes.push_back (128);
1455 sizes.push_back (256);
1456 sizes.push_back (512);
1457 sizes.push_back (1024);
1458 sizes.push_back (2048);
1459 sizes.push_back (4096);
1460 sizes.push_back (8192);
1465 EngineControl::set_buffersize_popdown_strings ()
1467 DEBUG_ECONTROL ("set_buffersize_popdown_strings");
1468 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1469 vector<uint32_t> bs;
1472 if (_have_control) {
1473 bs = get_buffer_sizes_for_all_devices ();
1474 } else if (backend->can_change_buffer_size_when_running()) {
1475 bs = get_default_buffer_sizes ();
1478 for (vector<uint32_t>::const_iterator x = bs.begin(); x != bs.end(); ++x) {
1479 s.push_back (bufsize_as_string (*x));
1482 uint32_t previous_size = backend->buffer_size ();
1483 if (!buffer_size_combo.get_active_text().empty()) {
1484 previous_size = get_buffer_size ();
1487 set_popdown_strings (buffer_size_combo, s);
1491 if (std::find(bs.begin(), bs.end(), previous_size) != bs.end()) {
1492 buffer_size_combo.set_active_text(bufsize_as_string(previous_size));
1495 buffer_size_combo.set_active_text(s.front());
1497 uint32_t period = backend->buffer_size();
1498 if (0 == period && backend->use_separate_input_and_output_devices()) {
1499 period = backend->default_buffer_size(get_input_device_name());
1501 if (0 == period && backend->use_separate_input_and_output_devices()) {
1502 period = backend->default_buffer_size(get_output_device_name());
1504 if (0 == period && !backend->use_separate_input_and_output_devices()) {
1505 period = backend->default_buffer_size(get_device_name());
1508 set_active_text_if_present(buffer_size_combo, bufsize_as_string(period));
1510 show_buffer_duration ();
1512 update_sensitivity ();
1516 EngineControl::set_nperiods_popdown_strings ()
1518 DEBUG_ECONTROL ("set_nperiods_popdown_strings");
1519 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1520 vector<uint32_t> np;
1523 if (backend->can_set_period_size()) {
1524 np = backend->available_period_sizes (get_driver());
1527 for (vector<uint32_t>::const_iterator x = np.begin(); x != np.end(); ++x) {
1528 s.push_back (to_string (*x));
1531 set_popdown_strings (nperiods_combo, s);
1534 set_active_text_if_present (nperiods_combo, to_string (backend->period_size())); // XXX
1537 update_sensitivity ();
1541 EngineControl::device_changed ()
1543 SignalBlocker blocker (*this, "device_changed");
1544 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1547 string device_name_in;
1548 string device_name_out; // only used if backend support separate I/O devices
1550 if (backend->use_separate_input_and_output_devices()) {
1551 device_name_in = get_input_device_name ();
1552 device_name_out = get_output_device_name ();
1554 device_name_in = get_device_name ();
1557 /* we set the backend-device to query various device related intormation.
1558 * This has the side effect that backend->device_name() will match
1559 * the device_name and 'change_device' will never be true.
1560 * so work around this by setting...
1562 if (backend->use_separate_input_and_output_devices()) {
1563 if (device_name_in != backend->input_device_name() || device_name_out != backend->output_device_name ()) {
1564 queue_device_changed = true;
1567 if (device_name_in != backend->device_name()) {
1568 queue_device_changed = true;
1572 //the device name must be set FIRST so ASIO can populate buffersizes and the control panel button
1573 if (backend->use_separate_input_and_output_devices()) {
1574 backend->set_input_device_name (device_name_in);
1575 backend->set_output_device_name (device_name_out);
1577 backend->set_device_name(device_name_in);
1581 /* don't allow programmatic change to combos to cause a
1582 recursive call to this method.
1584 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1586 set_samplerate_popdown_strings ();
1587 set_buffersize_popdown_strings ();
1588 set_nperiods_popdown_strings ();
1590 /* TODO set min + max channel counts here */
1592 manage_control_app_sensitivity ();
1595 /* pick up any saved state for this device */
1597 if (!ignore_changes) {
1598 maybe_display_saved_state ();
1603 EngineControl::input_device_changed ()
1605 DEBUG_ECONTROL ("input_device_changed");
1607 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1608 if (backend && backend->match_input_output_devices_or_none ()) {
1609 const std::string& dev_none = ARDOUR::AudioBackend::get_standard_device_name (ARDOUR::AudioBackend::DeviceNone);
1611 if (get_output_device_name () != dev_none
1612 && get_input_device_name () != dev_none
1613 && get_input_device_name () != get_output_device_name ()) {
1614 block_changed_signals ();
1615 if (contains_value (output_device_combo, get_input_device_name ())) {
1616 output_device_combo.set_active_text (get_input_device_name ());
1618 assert (contains_value (output_device_combo, dev_none));
1619 output_device_combo.set_active_text (dev_none);
1621 unblock_changed_signals ();
1628 EngineControl::output_device_changed ()
1630 DEBUG_ECONTROL ("output_device_changed");
1631 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1632 if (backend && backend->match_input_output_devices_or_none ()) {
1633 const std::string& dev_none = ARDOUR::AudioBackend::get_standard_device_name (ARDOUR::AudioBackend::DeviceNone);
1635 if (get_input_device_name () != dev_none
1636 && get_input_device_name () != dev_none
1637 && get_input_device_name () != get_output_device_name ()) {
1638 block_changed_signals ();
1639 if (contains_value (input_device_combo, get_output_device_name ())) {
1640 input_device_combo.set_active_text (get_output_device_name ());
1642 assert (contains_value (input_device_combo, dev_none));
1643 input_device_combo.set_active_text (dev_none);
1645 unblock_changed_signals ();
1652 EngineControl::bufsize_as_string (uint32_t sz)
1654 return string_compose (P_("%1 sample", "%1 samples", sz), to_string(sz));
1658 EngineControl::sample_rate_changed ()
1660 DEBUG_ECONTROL ("sample_rate_changed");
1661 /* reset the strings for buffer size to show the correct msec value
1662 (reflecting the new sample rate).
1665 show_buffer_duration ();
1670 EngineControl::buffer_size_changed ()
1672 DEBUG_ECONTROL ("buffer_size_changed");
1673 if (ARDOUR::AudioEngine::instance()->running()) {
1674 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1675 if (backend && backend->can_change_buffer_size_when_running ()) {
1676 backend->set_buffer_size (get_buffer_size());
1679 show_buffer_duration ();
1683 EngineControl::nperiods_changed ()
1685 DEBUG_ECONTROL ("nperiods_changed");
1686 show_buffer_duration ();
1690 EngineControl::show_buffer_duration ()
1692 DEBUG_ECONTROL ("show_buffer_duration");
1693 /* buffer sizes - convert from just samples to samples + msecs for
1694 * the displayed string
1697 string bs_text = buffer_size_combo.get_active_text ();
1698 uint32_t samples = atoi (bs_text); /* will ignore trailing text */
1699 uint32_t rate = get_rate();
1701 /* Except for ALSA and Dummy backends, we don't know the number of periods
1702 * per cycle and settings.
1704 * jack1 vs jack2 have different default latencies since jack2 start
1705 * in async-mode unless --sync is given which adds an extra cycle
1706 * of latency. The value is not known if jackd is started externally..
1708 * So just display the period size, that's also what
1709 * ARDOUR_UI::update_sample_rate() does for the status bar.
1710 * (the statusbar calls AudioEngine::instance()->usecs_per_cycle()
1711 * but still, that's the buffer period, not [round-trip] latency)
1714 snprintf (buf, sizeof (buf), _("(%.1f ms)"), (samples / (rate/1000.0f)));
1715 buffer_size_duration_label.set_text (buf);
1719 EngineControl::midi_option_changed ()
1721 DEBUG_ECONTROL ("midi_option_changed");
1722 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1725 backend->set_midi_option (get_midi_option());
1727 vector<ARDOUR::AudioBackend::DeviceStatus> midi_devices = backend->enumerate_midi_devices();
1729 //_midi_devices.clear(); // TODO merge with state-saved settings..
1730 _can_set_midi_latencies = backend->can_set_systemic_midi_latencies();
1731 std::vector<MidiDeviceSettings> new_devices;
1733 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = midi_devices.begin(); i != midi_devices.end(); ++i) {
1734 MidiDeviceSettings mds = find_midi_device (i->name);
1735 if (i->available && !mds) {
1736 uint32_t input_latency = 0;
1737 uint32_t output_latency = 0;
1738 if (_can_set_midi_latencies) {
1739 input_latency = backend->systemic_midi_input_latency (i->name);
1740 output_latency = backend->systemic_midi_output_latency (i->name);
1742 bool enabled = backend->midi_device_enabled (i->name);
1743 MidiDeviceSettings ptr (new MidiDeviceSetting (i->name, enabled, input_latency, output_latency));
1744 new_devices.push_back (ptr);
1745 } else if (i->available) {
1746 new_devices.push_back (mds);
1749 _midi_devices = new_devices;
1751 if (_midi_devices.empty()) {
1752 midi_devices_button.hide ();
1754 midi_devices_button.show ();
1759 EngineControl::parameter_changed ()
1763 EngineControl::State
1764 EngineControl::get_matching_state (const string& backend)
1766 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1767 if ((*i)->backend == backend) {
1774 EngineControl::State
1775 EngineControl::get_matching_state (
1776 const string& backend,
1777 const string& driver,
1778 const string& device)
1780 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1781 if ((*i)->backend == backend &&
1782 (!_have_control || ((*i)->driver == driver && (*i)->device == device)))
1790 EngineControl::State
1791 EngineControl::get_matching_state (
1792 const string& backend,
1793 const string& driver,
1794 const string& input_device,
1795 const string& output_device)
1797 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1798 if ((*i)->backend == backend &&
1799 (!_have_control || ((*i)->driver == driver && ((*i)->input_device == input_device) && (*i)->output_device == output_device)))
1807 EngineControl::State
1808 EngineControl::get_saved_state_for_currently_displayed_backend_and_device ()
1810 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1813 if (backend->use_separate_input_and_output_devices ()) {
1814 return get_matching_state (backend_combo.get_active_text(),
1815 (backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
1816 input_device_combo.get_active_text(),
1817 output_device_combo.get_active_text());
1819 return get_matching_state (backend_combo.get_active_text(),
1820 (backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
1821 device_combo.get_active_text());
1825 return get_matching_state (backend_combo.get_active_text(),
1827 device_combo.get_active_text());
1830 bool EngineControl::equivalent_states (const EngineControl::State& state1,
1831 const EngineControl::State& state2)
1833 if (state1->backend == state2->backend &&
1834 state1->driver == state2->driver &&
1835 state1->device == state2->device &&
1836 state1->input_device == state2->input_device &&
1837 state1->output_device == state2->output_device) {
1843 // sort active first, then most recently used to the beginning of the list
1845 EngineControl::state_sort_cmp (const State &a, const State &b) {
1849 else if (b->active) {
1853 return a->lru > b->lru;
1857 EngineControl::State
1858 EngineControl::save_state ()
1862 if (!_have_control) {
1863 state = get_matching_state (backend_combo.get_active_text(), string(), string());
1865 state->lru = time (NULL) ;
1868 state.reset(new StateStruct);
1869 state->backend = get_backend ();
1871 state.reset(new StateStruct);
1872 store_state (state);
1875 for (StateList::iterator i = states.begin(); i != states.end();) {
1876 if (equivalent_states (*i, state)) {
1877 i = states.erase(i);
1883 states.push_back (state);
1885 states.sort (state_sort_cmp);
1891 EngineControl::store_state (State state)
1893 state->backend = get_backend ();
1894 state->driver = get_driver ();
1895 state->device = get_device_name ();
1896 state->input_device = get_input_device_name ();
1897 state->output_device = get_output_device_name ();
1898 state->sample_rate = get_rate ();
1899 state->buffer_size = get_buffer_size ();
1900 state->n_periods = get_nperiods ();
1901 state->input_latency = get_input_latency ();
1902 state->output_latency = get_output_latency ();
1903 state->input_channels = get_input_channels ();
1904 state->output_channels = get_output_channels ();
1905 state->midi_option = get_midi_option ();
1906 state->midi_devices = _midi_devices;
1907 state->use_buffered_io = get_use_buffered_io ();
1908 state->lru = time (NULL) ;
1912 EngineControl::maybe_display_saved_state ()
1914 if (!_have_control || ARDOUR::AudioEngine::instance()->running ()) {
1918 State state = get_saved_state_for_currently_displayed_backend_and_device ();
1921 DEBUG_ECONTROL ("Restoring saved state");
1922 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1924 if (0 == _desired_sample_rate && sample_rate_combo.get_sensitive ()) {
1925 sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
1927 set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
1929 set_active_text_if_present (nperiods_combo, to_string(state->n_periods));
1930 /* call this explicitly because we're ignoring changes to
1931 the controls at this point.
1933 show_buffer_duration ();
1934 input_latency.set_value (state->input_latency);
1935 output_latency.set_value (state->output_latency);
1937 use_buffered_io_button.set_active (state->use_buffered_io);
1939 if (!state->midi_option.empty()) {
1940 midi_option_combo.set_active_text (state->midi_option);
1941 _midi_devices = state->midi_devices;
1944 DEBUG_ECONTROL ("Unable to find saved state for backend and devices");
1949 EngineControl::get_state ()
1953 XMLNode* root = new XMLNode ("AudioMIDISetup");
1956 if (!states.empty()) {
1957 XMLNode* state_nodes = new XMLNode ("EngineStates");
1959 for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
1961 XMLNode* node = new XMLNode ("State");
1963 node->set_property ("backend", (*i)->backend);
1964 node->set_property ("driver", (*i)->driver);
1965 node->set_property ("device", (*i)->device);
1966 node->set_property ("input-device", (*i)->input_device);
1967 node->set_property ("output-device", (*i)->output_device);
1968 node->set_property ("sample-rate", (*i)->sample_rate);
1969 node->set_property ("buffer-size", (*i)->buffer_size);
1970 node->set_property ("n-periods", (*i)->n_periods);
1971 node->set_property ("input-latency", (*i)->input_latency);
1972 node->set_property ("output-latency", (*i)->output_latency);
1973 node->set_property ("input-channels", (*i)->input_channels);
1974 node->set_property ("output-channels", (*i)->output_channels);
1975 node->set_property ("active", (*i)->active);
1976 node->set_property ("use-buffered-io", (*i)->use_buffered_io);
1977 node->set_property ("midi-option", (*i)->midi_option);
1978 int32_t lru_val = (*i)->active ? time (NULL) : (*i)->lru;
1979 node->set_property ("lru", lru_val );
1981 XMLNode* midi_devices = new XMLNode ("MIDIDevices");
1982 for (std::vector<MidiDeviceSettings>::const_iterator p = (*i)->midi_devices.begin(); p != (*i)->midi_devices.end(); ++p) {
1983 XMLNode* midi_device_stuff = new XMLNode ("MIDIDevice");
1984 midi_device_stuff->set_property (X_("name"), (*p)->name);
1985 midi_device_stuff->set_property (X_("enabled"), (*p)->enabled);
1986 midi_device_stuff->set_property (X_("input-latency"), (*p)->input_latency);
1987 midi_device_stuff->set_property (X_("output-latency"), (*p)->output_latency);
1988 midi_devices->add_child_nocopy (*midi_device_stuff);
1990 node->add_child_nocopy (*midi_devices);
1992 state_nodes->add_child_nocopy (*node);
1995 root->add_child_nocopy (*state_nodes);
2002 EngineControl::set_default_state ()
2004 vector<string> backend_names;
2005 vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
2007 for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
2008 backend_names.push_back ((*b)->name);
2010 backend_combo.set_active_text (backend_names.front());
2012 // We could set default backends per platform etc here
2018 EngineControl::set_state (const XMLNode& root)
2020 XMLNodeList clist, cclist;
2021 XMLNodeConstIterator citer, cciter;
2022 XMLNode const * child;
2023 XMLNode const * grandchild;
2025 if (root.name() != "AudioMIDISetup") {
2029 clist = root.children();
2033 for (citer = clist.begin(); citer != clist.end(); ++citer) {
2037 if (child->name() != "EngineStates") {
2041 cclist = child->children();
2043 for (cciter = cclist.begin(); cciter != cclist.end(); ++cciter) {
2044 State state (new StateStruct);
2046 grandchild = *cciter;
2048 if (grandchild->name() != "State") {
2052 if (!grandchild->get_property ("backend", state->backend)) {
2056 // If any of the required properties are not found in the state node
2057 // then continue/skip to the next engine state
2058 if (!grandchild->get_property ("driver", state->driver) ||
2059 !grandchild->get_property ("device", state->device) ||
2060 !grandchild->get_property ("input-device", state->input_device) ||
2061 !grandchild->get_property ("output-device", state->output_device) ||
2062 !grandchild->get_property ("sample-rate", state->sample_rate) ||
2063 !grandchild->get_property ("buffer-size", state->buffer_size) ||
2064 !grandchild->get_property ("input-latency", state->input_latency) ||
2065 !grandchild->get_property ("output-latency", state->output_latency) ||
2066 !grandchild->get_property ("input-channels", state->input_channels) ||
2067 !grandchild->get_property ("output-channels", state->output_channels) ||
2068 !grandchild->get_property ("active", state->active) ||
2069 !grandchild->get_property ("use-buffered-io", state->use_buffered_io) ||
2070 !grandchild->get_property ("midi-option", state->midi_option)) {
2074 if (!grandchild->get_property ("n-periods", state->n_periods)) {
2075 // optional (new value in 4.5)
2076 state->n_periods = 0;
2079 state->midi_devices.clear();
2081 if ((midinode = ARDOUR::find_named_node (*grandchild, "MIDIDevices")) != 0) {
2082 const XMLNodeList mnc = midinode->children();
2083 for (XMLNodeList::const_iterator n = mnc.begin(); n != mnc.end(); ++n) {
2086 uint32_t input_latency;
2087 uint32_t output_latency;
2089 if (!(*n)->get_property (X_("name"), name) ||
2090 !(*n)->get_property (X_("enabled"), enabled) ||
2091 !(*n)->get_property (X_("input-latency"), input_latency) ||
2092 !(*n)->get_property (X_("output-latency"), output_latency)) {
2096 MidiDeviceSettings ptr (
2097 new MidiDeviceSetting (name, enabled, input_latency, output_latency));
2098 state->midi_devices.push_back (ptr);
2103 if (grandchild->get_property ("lru", lru_val)) {
2104 state->lru = lru_val;
2107 states.push_back (state);
2111 /* now see if there was an active state and switch the setup to it */
2113 /* purge states of backend that are not available in this built */
2114 vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
2115 vector<std::string> backend_names;
2117 for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator i = backends.begin(); i != backends.end(); ++i) {
2118 backend_names.push_back((*i)->name);
2120 for (StateList::iterator i = states.begin(); i != states.end();) {
2121 if (std::find(backend_names.begin(), backend_names.end(), (*i)->backend) == backend_names.end()) {
2122 i = states.erase(i);
2128 states.sort (state_sort_cmp);
2130 /* purge old states referring to the same backend */
2131 const time_t now = time (NULL);
2132 for (vector<std::string>::const_iterator bi = backend_names.begin(); bi != backend_names.end(); ++bi) {
2134 for (StateList::iterator i = states.begin(); i != states.end();) {
2135 if ((*i)->backend != *bi) {
2138 // keep at latest one for every audio-system
2143 // also keep states used in the last 90 days.
2144 if ((now - (*i)->lru) < 86400 * 90) {
2147 assert (!(*i)->active);
2148 i = states.erase(i);
2152 for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
2155 return set_current_state (*i);
2162 EngineControl::set_current_state (const State& state)
2164 DEBUG_ECONTROL ("set_current_state");
2166 boost::shared_ptr<ARDOUR::AudioBackend> backend;
2168 if (!(backend = ARDOUR::AudioEngine::instance ()->set_backend (
2169 state->backend, downcase (std::string(PROGRAM_NAME)), ""))) {
2170 DEBUG_ECONTROL (string_compose ("Unable to set backend to %1", state->backend));
2171 // this shouldn't happen as the invalid backend names should have been
2172 // removed from the list of states.
2176 // now reflect the change in the backend in the GUI so backend_changed will
2177 // do the right thing
2178 backend_combo.set_active_text (state->backend);
2180 if (!ARDOUR::AudioEngine::instance()->setup_required ()) {
2182 // we don't have control don't restore state
2187 if (!state->driver.empty ()) {
2188 if (!backend->requires_driver_selection ()) {
2189 DEBUG_ECONTROL ("Backend should require driver selection");
2190 // A backend has changed from having driver selection to not having
2191 // it or someone has been manually editing a config file and messed
2196 if (backend->set_driver (state->driver) != 0) {
2197 DEBUG_ECONTROL (string_compose ("Unable to set driver %1", state->driver));
2198 // Driver names for a backend have changed and the name in the
2199 // config file is now invalid or support for driver is no longer
2200 // included in the backend
2203 // no need to set the driver_combo as backend_changed will use
2204 // backend->driver_name to set the active driver
2207 if (!state->device.empty ()) {
2208 if (backend->set_device_name (state->device) != 0) {
2210 string_compose ("Unable to set device name %1", state->device));
2211 // device is no longer available on the system
2214 // no need to set active device as it will be picked up in
2215 // via backend_changed ()/set_device_popdown_strings
2218 // backend supports separate input/output devices
2219 if (backend->set_input_device_name (state->input_device) != 0) {
2220 DEBUG_ECONTROL (string_compose ("Unable to set input device name %1",
2221 state->input_device));
2222 // input device is no longer available on the system
2226 if (backend->set_output_device_name (state->output_device) != 0) {
2227 DEBUG_ECONTROL (string_compose ("Unable to set output device name %1",
2228 state->input_device));
2229 // output device is no longer available on the system
2232 // no need to set active devices as it will be picked up in via
2233 // backend_changed ()/set_*_device_popdown_strings
2238 // Now restore the state of the rest of the controls
2240 // We don't use a SignalBlocker as set_current_state is currently only
2241 // called from set_state before any signals are connected. If at some point
2242 // a more general named state mechanism is implemented and
2243 // set_current_state is called while signals are connected then a
2244 // SignalBlocker will need to be instantiated before setting these.
2246 device_combo.set_active_text (state->device);
2247 input_device_combo.set_active_text (state->input_device);
2248 output_device_combo.set_active_text (state->output_device);
2249 if (0 == _desired_sample_rate && sample_rate_combo.get_sensitive ()) {
2250 sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
2252 set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
2253 set_active_text_if_present (nperiods_combo, to_string (state->n_periods));
2254 input_latency.set_value (state->input_latency);
2255 output_latency.set_value (state->output_latency);
2256 midi_option_combo.set_active_text (state->midi_option);
2257 use_buffered_io_button.set_active (state->use_buffered_io);
2262 EngineControl::push_state_to_backend (bool start)
2264 DEBUG_ECONTROL ("push_state_to_backend");
2265 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2266 PBD::Unwinder<uint32_t> protect_ignore_device_changes (ignore_device_changes, ignore_device_changes + 1);
2272 /* figure out what is going to change */
2274 bool restart_required = false;
2275 bool was_running = ARDOUR::AudioEngine::instance()->running();
2276 bool change_driver = false;
2277 bool change_device = false;
2278 bool change_rate = false;
2279 bool change_bufsize = false;
2280 bool change_nperiods = false;
2281 bool change_latency = false;
2282 bool change_channels = false;
2283 bool change_midi = false;
2284 bool change_buffered_io = false;
2286 uint32_t ochan = get_output_channels ();
2287 uint32_t ichan = get_input_channels ();
2289 if (_have_control) {
2291 if (started_at_least_once) {
2293 /* we can control the backend */
2295 if (backend->requires_driver_selection()) {
2296 if (get_driver() != backend->driver_name()) {
2297 change_driver = true;
2301 if (backend->use_separate_input_and_output_devices()) {
2302 if (get_input_device_name() != backend->input_device_name()) {
2303 change_device = true;
2305 if (get_output_device_name() != backend->output_device_name()) {
2306 change_device = true;
2309 if (get_device_name() != backend->device_name()) {
2310 change_device = true;
2314 if (queue_device_changed) {
2315 change_device = true;
2318 if (get_rate() != backend->sample_rate()) {
2322 if (get_buffer_size() != backend->buffer_size()) {
2323 change_bufsize = true;
2326 if (backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0
2327 && get_nperiods() != backend->period_size()) {
2328 change_nperiods = true;
2331 if (get_midi_option() != backend->midi_option()) {
2335 if (backend->can_use_buffered_io()) {
2336 if (get_use_buffered_io() != backend->get_use_buffered_io()) {
2337 change_buffered_io = true;
2341 /* zero-requested channels means "all available" */
2344 ichan = backend->input_channels();
2348 ochan = backend->output_channels();
2351 if (ichan != backend->input_channels()) {
2352 change_channels = true;
2355 if (ochan != backend->output_channels()) {
2356 change_channels = true;
2359 if (get_input_latency() != backend->systemic_input_latency() ||
2360 get_output_latency() != backend->systemic_output_latency()) {
2361 change_latency = true;
2364 /* backend never started, so we have to force a group
2367 change_device = true;
2368 if (backend->requires_driver_selection()) {
2369 change_driver = true;
2372 change_bufsize = true;
2373 change_channels = true;
2374 change_latency = true;
2376 change_buffered_io = backend->can_use_buffered_io();
2377 change_channels = true;
2378 change_nperiods = backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0;
2383 /* we have no control over the backend, meaning that we can
2384 * only possibly change sample rate and buffer size.
2388 if (get_rate() != backend->sample_rate()) {
2389 change_bufsize = true;
2392 if (get_buffer_size() != backend->buffer_size()) {
2393 change_bufsize = true;
2397 queue_device_changed = false;
2399 if (!_have_control) {
2401 /* We do not have control over the backend, so the best we can
2402 * do is try to change the sample rate and/or bufsize and get
2406 if (change_rate && !backend->can_change_sample_rate_when_running()) {
2410 if (change_bufsize && !backend->can_change_buffer_size_when_running()) {
2415 backend->set_sample_rate (get_rate());
2418 if (change_bufsize) {
2419 backend->set_buffer_size (get_buffer_size());
2423 if (ARDOUR::AudioEngine::instance()->start ()) {
2424 error << string_compose (_("Could not start backend engine %1"), backend->name()) << endmsg;
2434 /* determine if we need to stop the backend before changing parameters */
2436 if (change_driver || change_device || change_channels || change_nperiods ||
2437 (change_latency && !backend->can_change_systemic_latency_when_running ()) ||
2438 (change_rate && !backend->can_change_sample_rate_when_running()) ||
2439 change_midi || change_buffered_io ||
2440 (change_bufsize && !backend->can_change_buffer_size_when_running())) {
2441 restart_required = true;
2443 restart_required = false;
2448 if (restart_required) {
2449 if (ARDOUR::AudioEngine::instance()->stop()) {
2455 if (change_driver && backend->set_driver (get_driver())) {
2456 error << string_compose (_("Cannot set driver to %1"), get_driver()) << endmsg;
2459 if (backend->use_separate_input_and_output_devices()) {
2460 if (change_device && backend->set_input_device_name (get_input_device_name())) {
2461 error << string_compose (_("Cannot set input device name to %1"), get_input_device_name()) << endmsg;
2464 if (change_device && backend->set_output_device_name (get_output_device_name())) {
2465 error << string_compose (_("Cannot set output device name to %1"), get_output_device_name()) << endmsg;
2469 if (change_device && backend->set_device_name (get_device_name())) {
2470 error << string_compose (_("Cannot set device name to %1"), get_device_name()) << endmsg;
2474 if (change_rate && backend->set_sample_rate (get_rate())) {
2475 error << string_compose (_("Cannot set sample rate to %1"), get_rate()) << endmsg;
2478 if (change_bufsize && backend->set_buffer_size (get_buffer_size())) {
2479 error << string_compose (_("Cannot set buffer size to %1"), get_buffer_size()) << endmsg;
2482 if (change_nperiods && backend->set_peridod_size (get_nperiods())) {
2483 error << string_compose (_("Cannot set periods to %1"), get_nperiods()) << endmsg;
2487 if (change_channels || get_input_channels() == 0 || get_output_channels() == 0) {
2488 if (backend->set_input_channels (get_input_channels())) {
2489 error << string_compose (_("Cannot set input channels to %1"), get_input_channels()) << endmsg;
2492 if (backend->set_output_channels (get_output_channels())) {
2493 error << string_compose (_("Cannot set output channels to %1"), get_output_channels()) << endmsg;
2497 if (change_latency) {
2498 if (backend->set_systemic_input_latency (get_input_latency())) {
2499 error << string_compose (_("Cannot set input latency to %1"), get_input_latency()) << endmsg;
2502 if (backend->set_systemic_output_latency (get_output_latency())) {
2503 error << string_compose (_("Cannot set output latency to %1"), get_output_latency()) << endmsg;
2509 backend->set_midi_option (get_midi_option());
2512 if (change_buffered_io) {
2513 backend->set_use_buffered_io (use_buffered_io_button.get_active());
2517 for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
2518 if (_measure_midi) {
2519 if (*p == _measure_midi) {
2520 backend->set_midi_device_enabled ((*p)->name, true);
2522 backend->set_midi_device_enabled ((*p)->name, false);
2524 if (backend->can_change_systemic_latency_when_running ()) {
2525 backend->set_systemic_midi_input_latency ((*p)->name, 0);
2526 backend->set_systemic_midi_output_latency ((*p)->name, 0);
2530 backend->set_midi_device_enabled ((*p)->name, (*p)->enabled);
2531 if (backend->can_set_systemic_midi_latencies()) {
2532 backend->set_systemic_midi_input_latency ((*p)->name, (*p)->input_latency);
2533 backend->set_systemic_midi_output_latency ((*p)->name, (*p)->output_latency);
2538 if (start || (was_running && restart_required)) {
2539 if (ARDOUR::AudioEngine::instance()->start()) {
2550 EngineControl::post_push ()
2552 /* get a pointer to the current state object, creating one if
2556 State state = get_saved_state_for_currently_displayed_backend_and_device ();
2559 state = save_state ();
2565 states.sort (state_sort_cmp);
2569 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
2570 (*i)->active = false;
2573 /* mark this one active (to be used next time the dialog is
2577 state->active = true;
2579 if (_have_control) { // XXX
2580 manage_control_app_sensitivity ();
2583 /* schedule a redisplay of MIDI ports */
2584 //Glib::signal_timeout().connect (sigc::bind_return (sigc::mem_fun (*this, &EngineControl::refresh_midi_display), false), 1000);
2589 EngineControl::get_rate () const
2591 float r = atof (sample_rate_combo.get_active_text ());
2592 /* the string may have been translated with an abbreviation for
2593 * thousands, so use a crude heuristic to fix this.
2603 EngineControl::get_buffer_size () const
2605 string txt = buffer_size_combo.get_active_text ();
2608 if (sscanf (txt.c_str(), "%d", &samples) != 1) {
2609 fprintf(stderr, "Find a trout and repeatedly slap the nearest C++ who throws exceptions without catching them.\n");
2610 fprintf(stderr, "Ardour will likely crash now, giving you time to get the trout.\n");
2618 EngineControl::get_nperiods () const
2620 string txt = nperiods_combo.get_active_text ();
2621 return atoi (txt.c_str());
2625 EngineControl::get_midi_option () const
2627 return midi_option_combo.get_active_text();
2631 EngineControl::get_use_buffered_io () const
2633 return use_buffered_io_button.get_active();
2637 EngineControl::get_input_channels() const
2639 if (ARDOUR::Profile->get_mixbus()) {
2640 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2641 if (!backend) return 0;
2642 return backend->input_channels();
2644 return (uint32_t) input_channels_adjustment.get_value();
2648 EngineControl::get_output_channels() const
2650 if (ARDOUR::Profile->get_mixbus()) {
2651 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2652 if (!backend) return 0;
2653 return backend->input_channels();
2655 return (uint32_t) output_channels_adjustment.get_value();
2659 EngineControl::get_input_latency() const
2661 return (uint32_t) input_latency_adjustment.get_value();
2665 EngineControl::get_output_latency() const
2667 return (uint32_t) output_latency_adjustment.get_value();
2671 EngineControl::get_backend () const
2673 return backend_combo.get_active_text ();
2677 EngineControl::get_driver () const
2679 if (driver_combo.get_parent()) {
2680 return driver_combo.get_active_text ();
2687 EngineControl::get_device_name () const
2689 return device_combo.get_active_text ();
2693 EngineControl::get_input_device_name () const
2695 return input_device_combo.get_active_text ();
2699 EngineControl::get_output_device_name () const
2701 return output_device_combo.get_active_text ();
2705 EngineControl::control_app_button_clicked ()
2707 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2713 backend->launch_control_app ();
2717 EngineControl::start_stop_button_clicked ()
2719 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2725 if (ARDOUR::AudioEngine::instance()->running()) {
2726 ARDOUR::AudioEngine::instance()->stop ();
2728 if (!ARDOUR_UI::instance()->the_session ()) {
2734 if (!ARDOUR_UI::instance()->the_session ()) {
2735 ArdourDialog::on_response (RESPONSE_OK);
2741 EngineControl::update_devices_button_clicked ()
2743 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2749 if (backend->update_devices()) {
2750 device_list_changed ();
2755 EngineControl::use_buffered_io_button_clicked ()
2757 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2763 bool set_buffered_io = !use_buffered_io_button.get_active();
2764 use_buffered_io_button.set_active (set_buffered_io);
2765 backend->set_use_buffered_io (set_buffered_io);
2769 EngineControl::manage_control_app_sensitivity ()
2771 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2777 string appname = backend->control_app_name();
2779 if (appname.empty()) {
2780 control_app_button.set_sensitive (false);
2782 control_app_button.set_sensitive (true);
2787 EngineControl::set_desired_sample_rate (uint32_t sr)
2789 _desired_sample_rate = sr;
2790 if (ARDOUR::AudioEngine::instance ()->running ()
2791 && ARDOUR::AudioEngine::instance ()->sample_rate () != sr) {
2798 EngineControl::on_switch_page (GtkNotebookPage*, guint page_num)
2800 if (page_num == 0) {
2801 _measure_midi.reset();
2802 update_sensitivity ();
2805 if (page_num == midi_tab) {
2807 refresh_midi_display ();
2810 if (page_num == latency_tab) {
2813 if (ARDOUR::AudioEngine::instance()->running()) {
2818 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
2820 /* save any existing latency values */
2822 uint32_t il = (uint32_t) input_latency.get_value ();
2823 uint32_t ol = (uint32_t) input_latency.get_value ();
2825 /* reset to zero so that our new test instance
2826 will be clean of any existing latency measures.
2828 NB. this should really be done by the backend
2829 when stated for latency measurement.
2832 input_latency.set_value (0);
2833 output_latency.set_value (0);
2835 push_state_to_backend (false);
2839 input_latency.set_value (il);
2840 output_latency.set_value (ol);
2843 // This should be done in push_state_to_backend()
2844 if (ARDOUR::AudioEngine::instance()->prepare_for_latency_measurement()) {
2845 disable_latency_tab ();
2848 enable_latency_tab ();
2852 end_latency_detection ();
2853 ARDOUR::AudioEngine::instance()->stop_latency_detection();
2858 /* latency measurement */
2861 EngineControl::check_audio_latency_measurement ()
2863 MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
2865 if (mtdm->resolve () < 0) {
2866 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
2870 if (mtdm->get_peak () > 0.707f) {
2871 // get_peak() resets the peak-hold in the detector.
2872 // this GUI callback is at 10Hz and so will be fine (test-signal is at higher freq)
2873 lm_results.set_markup (string_compose (results_markup, _("Input signal is > -3dBFS. Lower the signal level (output gain, input gain) on the audio-interface.")));
2877 if (mtdm->err () > 0.3) {
2883 ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
2885 if (sample_rate == 0) {
2886 lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
2887 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
2891 int samples_total = mtdm->del();
2892 int extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
2894 snprintf (buf, sizeof (buf), "%s%d samples (%.3lf ms)\n%s%d samples (%.3lf ms)",
2895 _("Detected roundtrip latency: "),
2896 samples_total, samples_total * 1000.0f/sample_rate,
2897 _("Systemic latency: "),
2898 extra, extra * 1000.0f/sample_rate);
2902 if (mtdm->err () > 0.2) {
2904 strcat (buf, _("(signal detection error)"));
2910 strcat (buf, _("(inverted - bad wiring)"));
2914 lm_results.set_markup (string_compose (results_markup, buf));
2917 have_lm_results = true;
2918 end_latency_detection ();
2919 lm_use_button.set_sensitive (true);
2927 EngineControl::check_midi_latency_measurement ()
2929 ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
2931 if (!mididm->have_signal () || mididm->latency () == 0) {
2932 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
2937 ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
2939 if (sample_rate == 0) {
2940 lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
2941 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
2945 ARDOUR::samplecnt_t samples_total = mididm->latency();
2946 ARDOUR::samplecnt_t extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
2947 snprintf (buf, sizeof (buf), "%s%" PRId64" samples (%.1lf ms) dev: %.2f[spl]\n%s%" PRId64" samples (%.1lf ms)",
2948 _("Detected roundtrip latency: "),
2949 samples_total, samples_total * 1000.0f / sample_rate, mididm->deviation (),
2950 _("Systemic latency: "),
2951 extra, extra * 1000.0f / sample_rate);
2955 if (!mididm->ok ()) {
2957 strcat (buf, _("(averaging)"));
2961 if (mididm->deviation () > 50.0) {
2963 strcat (buf, _("(too large jitter)"));
2965 } else if (mididm->deviation () > 10.0) {
2967 strcat (buf, _("(large jitter)"));
2971 have_lm_results = true;
2972 end_latency_detection ();
2973 lm_use_button.set_sensitive (true);
2974 lm_results.set_markup (string_compose (results_markup, buf));
2976 } else if (mididm->processed () > 400) {
2977 have_lm_results = false;
2978 end_latency_detection ();
2979 lm_results.set_markup (string_compose (results_markup, _("Timeout - large MIDI jitter.")));
2983 lm_results.set_markup (string_compose (results_markup, buf));
2989 EngineControl::start_latency_detection ()
2991 ARDOUR::AudioEngine::instance()->set_latency_input_port (lm_input_channel_combo.get_active ()->get_value (lm_input_channel_cols.port_name));
2992 ARDOUR::AudioEngine::instance()->set_latency_output_port (lm_output_channel_combo.get_active ()->get_value (lm_output_channel_cols.port_name));
2994 if (ARDOUR::AudioEngine::instance()->start_latency_detection (_measure_midi ? true : false) == 0) {
2995 lm_results.set_markup (string_compose (results_markup, _("Detecting ...")));
2996 if (_measure_midi) {
2997 latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_midi_latency_measurement), 100);
2999 latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_audio_latency_measurement), 100);
3001 lm_measure_label.set_text (_("Cancel"));
3002 have_lm_results = false;
3003 lm_use_button.set_sensitive (false);
3004 lm_input_channel_combo.set_sensitive (false);
3005 lm_output_channel_combo.set_sensitive (false);
3011 EngineControl::end_latency_detection ()
3013 latency_timeout.disconnect ();
3014 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
3015 lm_measure_label.set_text (_("Measure"));
3016 if (!have_lm_results) {
3017 lm_use_button.set_sensitive (false);
3019 lm_input_channel_combo.set_sensitive (true);
3020 lm_output_channel_combo.set_sensitive (true);
3025 EngineControl::latency_button_clicked ()
3028 start_latency_detection ();
3030 end_latency_detection ();
3035 EngineControl::latency_back_button_clicked ()
3037 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
3038 notebook.set_current_page(0);
3042 EngineControl::use_latency_button_clicked ()
3044 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3045 if (_measure_midi) {
3046 ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
3050 ARDOUR::samplecnt_t samples_total = mididm->latency();
3051 ARDOUR::samplecnt_t extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
3052 uint32_t one_way = max ((ARDOUR::samplecnt_t) 0, extra / 2);
3053 _measure_midi->input_latency = one_way;
3054 _measure_midi->output_latency = one_way;
3055 if (backend->can_change_systemic_latency_when_running ()) {
3056 backend->set_systemic_midi_input_latency (_measure_midi->name, one_way);
3057 backend->set_systemic_midi_output_latency (_measure_midi->name, one_way);
3059 notebook.set_current_page (midi_tab);
3061 MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
3067 double one_way = rint ((mtdm->del() - ARDOUR::AudioEngine::instance()->latency_signal_delay()) / 2.0);
3068 one_way = std::max (0., one_way);
3070 input_latency_adjustment.set_value (one_way);
3071 output_latency_adjustment.set_value (one_way);
3072 if (backend->can_change_systemic_latency_when_running ()) {
3073 backend->set_systemic_input_latency (one_way);
3074 backend->set_systemic_output_latency (one_way);
3077 /* back to settings page */
3078 notebook.set_current_page (0);
3083 EngineControl::on_delete_event (GdkEventAny* ev)
3085 if (notebook.get_current_page() == 2) {
3086 /* currently on latency tab - be sure to clean up */
3087 end_latency_detection ();
3089 return ArdourDialog::on_delete_event (ev);
3093 EngineControl::engine_running ()
3095 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3098 set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
3099 sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
3101 if (backend->can_set_period_size ()) {
3102 set_active_text_if_present (nperiods_combo, to_string (backend->period_size()));
3105 connect_disconnect_button.set_label (string_compose (_("Disconnect from %1"), backend->name()));
3106 connect_disconnect_button.show();
3108 started_at_least_once = true;
3109 if (_have_control) {
3110 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Running")));
3112 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Connected")));
3114 update_sensitivity();
3118 EngineControl::engine_stopped ()
3120 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3123 connect_disconnect_button.set_label (string_compose (_("Connect to %1"), backend->name()));
3124 connect_disconnect_button.show();
3126 if (_have_control) {
3127 engine_status.set_markup(string_compose ("<span foreground=\"red\">%1</span>", _("Stopped")));
3129 engine_status.set_markup(X_(""));
3132 update_sensitivity();
3136 EngineControl::device_list_changed ()
3138 if (ignore_device_changes) {
3141 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1); // ??
3142 if (!ARDOUR::AudioEngine::instance()->running()) {
3146 midi_option_changed();
3148 if (notebook.get_current_page() == midi_tab) {
3149 if (_midi_devices.empty ()) {
3150 notebook.set_current_page (0);
3152 refresh_midi_display ();
3158 EngineControl::connect_disconnect_click()
3160 if (ARDOUR::AudioEngine::instance()->running()) {
3163 if (!ARDOUR_UI::instance()->the_session ()) {
3169 if (!ARDOUR_UI::instance()->the_session ()) {
3170 ArdourDialog::on_response (RESPONSE_OK);
3176 EngineControl::calibrate_audio_latency ()
3178 _measure_midi.reset ();
3179 have_lm_results = false;
3180 lm_use_button.set_sensitive (false);
3181 lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
3182 notebook.set_current_page (latency_tab);
3186 EngineControl::calibrate_midi_latency (MidiDeviceSettings s)
3189 have_lm_results = false;
3190 lm_use_button.set_sensitive (false);
3191 lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
3192 notebook.set_current_page (latency_tab);
3196 EngineControl::configure_midi_devices ()
3198 notebook.set_current_page (midi_tab);