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 Gtk::Alignment* misc_align = manage (new Alignment (0.0, 0.5));
180 misc_align->add (lm_output_channel_combo);
181 lm_table.attach (*misc_align, 1, 3, row, row+1, xopt, (AttachOptions) 0);
184 label = manage (new Label (_("Input channel")));
185 lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
187 misc_align = manage (new Alignment (0.0, 0.5));
188 misc_align->add (lm_input_channel_combo);
189 lm_table.attach (*misc_align, 1, 3, row, row+1, FILL, (AttachOptions) 0);
192 lm_measure_label.set_padding (10, 10);
193 lm_measure_button.add (lm_measure_label);
194 lm_measure_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::latency_button_clicked));
195 lm_use_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::use_latency_button_clicked));
196 lm_back_button_signal = lm_back_button.signal_clicked().connect(
197 sigc::mem_fun(*this, &EngineControl::latency_back_button_clicked));
199 lm_use_button.set_sensitive (false);
201 /* Increase the default spacing around the labels of these three
207 if ((l = dynamic_cast<Gtk::Misc*>(lm_use_button.get_child())) != 0) {
208 l->set_padding (10, 10);
211 if ((l = dynamic_cast<Gtk::Misc*>(lm_back_button.get_child())) != 0) {
212 l->set_padding (10, 10);
215 preamble = manage (new Label);
216 preamble->set_width_chars (60);
217 preamble->set_line_wrap (true);
218 preamble->set_markup (_("Once the channels are connected, click the \"Measure\" button."));
219 lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
222 preamble = manage (new Label);
223 preamble->set_width_chars (60);
224 preamble->set_line_wrap (true);
225 preamble->set_markup (_("When satisfied with the results, click the \"Use results\" button."));
226 lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
228 ++row; // skip a row in the table
229 ++row; // skip a row in the table
231 lm_table.attach (lm_results, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
233 ++row; // skip a row in the table
234 ++row; // skip a row in the table
236 lm_table.attach (lm_measure_button, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
237 lm_table.attach (lm_use_button, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
238 lm_table.attach (lm_back_button, 2, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
240 lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
242 lm_vbox.set_border_width (12);
243 lm_vbox.pack_start (lm_table, false, false);
245 midi_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
249 notebook.pages().push_back (TabElem (basic_vbox, _("Audio")));
250 notebook.pages().push_back (TabElem (lm_vbox, _("Latency")));
251 notebook.pages().push_back (TabElem (midi_vbox, _("MIDI")));
252 notebook.set_border_width (12);
254 notebook.set_show_tabs (false);
255 notebook.show_all ();
257 notebook.set_name ("SettingsNotebook");
259 /* packup the notebook */
261 get_vbox()->set_border_width (12);
262 get_vbox()->pack_start (notebook);
264 /* need a special function to print "all available channels" when the
265 * channel counts hit zero.
268 input_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &input_channels));
269 output_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &output_channels));
271 midi_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::configure_midi_devices));
272 midi_devices_button.set_name ("generic button");
273 midi_devices_button.set_can_focus(true);
275 control_app_button.signal_clicked.connect (mem_fun (*this, &EngineControl::control_app_button_clicked));
276 control_app_button.set_name ("generic button");
277 control_app_button.set_can_focus(true);
278 manage_control_app_sensitivity ();
280 start_stop_button.signal_clicked.connect (mem_fun (*this, &EngineControl::start_stop_button_clicked));
281 start_stop_button.set_sensitive (false);
282 start_stop_button.set_name ("generic button");
283 start_stop_button.set_can_focus(true);
284 start_stop_button.set_can_default(true);
285 start_stop_button.set_act_on_release (false);
287 update_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::update_devices_button_clicked));
288 update_devices_button.set_sensitive (false);
289 update_devices_button.set_name ("generic button");
290 update_devices_button.set_can_focus(true);
292 use_buffered_io_button.signal_clicked.connect (mem_fun (*this, &EngineControl::use_buffered_io_button_clicked));
293 use_buffered_io_button.set_sensitive (false);
294 use_buffered_io_button.set_name ("generic button");
295 use_buffered_io_button.set_can_focus(true);
297 /* Pick up any existing audio setup configuration, if appropriate */
299 XMLNode* audio_setup = ARDOUR::Config->extra_xml ("AudioMIDISetup");
301 ARDOUR::AudioEngine::instance()->Running.connect (running_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_running, this), gui_context());
302 ARDOUR::AudioEngine::instance()->Stopped.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
303 ARDOUR::AudioEngine::instance()->Halted.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
304 ARDOUR::AudioEngine::instance()->DeviceListChanged.connect (devicelist_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::device_list_changed, this), gui_context());
307 if (!set_state (*audio_setup)) {
308 set_default_state ();
311 set_default_state ();
314 update_sensitivity ();
315 connect_changed_signals ();
317 notebook.signal_switch_page().connect (sigc::mem_fun (*this, &EngineControl::on_switch_page));
319 connect_disconnect_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::connect_disconnect_click));
321 connect_disconnect_button.set_no_show_all();
322 use_buffered_io_button.set_no_show_all();
323 update_devices_button.set_no_show_all();
324 start_stop_button.set_no_show_all();
325 midi_devices_button.set_no_show_all();
329 EngineControl::connect_changed_signals ()
331 backend_combo_connection = backend_combo.signal_changed ().connect (
332 sigc::mem_fun (*this, &EngineControl::backend_changed));
333 driver_combo_connection = driver_combo.signal_changed ().connect (
334 sigc::mem_fun (*this, &EngineControl::driver_changed));
335 sample_rate_combo_connection = sample_rate_combo.signal_changed ().connect (
336 sigc::mem_fun (*this, &EngineControl::sample_rate_changed));
337 buffer_size_combo_connection = buffer_size_combo.signal_changed ().connect (
338 sigc::mem_fun (*this, &EngineControl::buffer_size_changed));
339 nperiods_combo_connection = nperiods_combo.signal_changed ().connect (
340 sigc::mem_fun (*this, &EngineControl::nperiods_changed));
341 device_combo_connection = device_combo.signal_changed ().connect (
342 sigc::mem_fun (*this, &EngineControl::device_changed));
343 midi_option_combo_connection = midi_option_combo.signal_changed ().connect (
344 sigc::mem_fun (*this, &EngineControl::midi_option_changed));
346 input_device_combo_connection = input_device_combo.signal_changed ().connect (
347 sigc::mem_fun (*this, &EngineControl::input_device_changed));
348 output_device_combo_connection = output_device_combo.signal_changed ().connect (
349 sigc::mem_fun (*this, &EngineControl::output_device_changed));
351 input_latency_connection = input_latency.signal_changed ().connect (
352 sigc::mem_fun (*this, &EngineControl::parameter_changed));
353 output_latency_connection = output_latency.signal_changed ().connect (
354 sigc::mem_fun (*this, &EngineControl::parameter_changed));
355 input_channels_connection = input_channels.signal_changed ().connect (
356 sigc::mem_fun (*this, &EngineControl::parameter_changed));
357 output_channels_connection = output_channels.signal_changed ().connect (
358 sigc::mem_fun (*this, &EngineControl::parameter_changed));
362 EngineControl::block_changed_signals ()
364 if (block_signals++ == 0) {
365 DEBUG_ECONTROL ("Blocking changed signals");
366 backend_combo_connection.block ();
367 driver_combo_connection.block ();
368 sample_rate_combo_connection.block ();
369 buffer_size_combo_connection.block ();
370 nperiods_combo_connection.block ();
371 device_combo_connection.block ();
372 input_device_combo_connection.block ();
373 output_device_combo_connection.block ();
374 midi_option_combo_connection.block ();
375 input_latency_connection.block ();
376 output_latency_connection.block ();
377 input_channels_connection.block ();
378 output_channels_connection.block ();
383 EngineControl::unblock_changed_signals ()
385 if (--block_signals == 0) {
386 DEBUG_ECONTROL ("Unblocking changed signals");
387 backend_combo_connection.unblock ();
388 driver_combo_connection.unblock ();
389 sample_rate_combo_connection.unblock ();
390 buffer_size_combo_connection.unblock ();
391 nperiods_combo_connection.unblock ();
392 device_combo_connection.unblock ();
393 input_device_combo_connection.unblock ();
394 output_device_combo_connection.unblock ();
395 midi_option_combo_connection.unblock ();
396 input_latency_connection.unblock ();
397 output_latency_connection.unblock ();
398 input_channels_connection.unblock ();
399 output_channels_connection.unblock ();
403 EngineControl::SignalBlocker::SignalBlocker (EngineControl& engine_control,
404 const std::string& reason)
405 : ec (engine_control)
408 DEBUG_ECONTROL (string_compose ("SignalBlocker: %1", m_reason));
409 ec.block_changed_signals ();
412 EngineControl::SignalBlocker::~SignalBlocker ()
414 DEBUG_ECONTROL (string_compose ("~SignalBlocker: %1", m_reason));
415 ec.unblock_changed_signals ();
419 EngineControl::on_show ()
421 ArdourDialog::on_show ();
422 if (!ARDOUR::AudioEngine::instance()->current_backend() || !ARDOUR::AudioEngine::instance()->running()) {
423 // re-check _have_control (jackd running) see #6041
427 start_stop_button.grab_focus();
431 EngineControl::on_map ()
433 if (!ARDOUR_UI::instance()->the_session () && !PublicEditor::_instance) {
434 set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
435 } else if (UIConfiguration::instance().get_all_floating_windows_are_dialogs()) {
436 set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
438 set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
440 ArdourDialog::on_map ();
444 EngineControl::try_autostart ()
446 if (!start_stop_button.get_sensitive()) {
449 if (ARDOUR::AudioEngine::instance()->running()) {
452 return start_engine ();
456 EngineControl::start_engine ()
458 if (push_state_to_backend(true) != 0) {
459 MessageDialog msg(*this,
460 ARDOUR::AudioEngine::instance()->get_last_backend_error());
468 EngineControl::stop_engine (bool for_latency)
470 if (ARDOUR::AudioEngine::instance()->stop(for_latency)) {
471 MessageDialog msg(*this,
472 ARDOUR::AudioEngine::instance()->get_last_backend_error());
480 EngineControl::build_notebook ()
483 AttachOptions xopt = AttachOptions (FILL|EXPAND);
485 /* clear the table */
487 Gtkmm2ext::container_clear (basic_vbox);
488 Gtkmm2ext::container_clear (basic_packer);
490 if (control_app_button.get_parent()) {
491 control_app_button.get_parent()->remove (control_app_button);
494 label = manage (left_aligned_label (_("Audio System:")));
495 basic_packer.attach (*label, 0, 1, 0, 1, xopt, (AttachOptions) 0);
496 basic_packer.attach (backend_combo, 1, 2, 0, 1, xopt, (AttachOptions) 0);
498 basic_packer.attach (engine_status, 2, 3, 0, 1, xopt, (AttachOptions) 0);
499 engine_status.show();
501 basic_packer.attach (start_stop_button, 3, 4, 0, 1, xopt, xopt);
502 basic_packer.attach (update_devices_button, 3, 4, 1, 2, xopt, xopt);
503 basic_packer.attach (use_buffered_io_button, 3, 4, 2, 3, xopt, xopt);
505 lm_button_audio.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_audio_latency));
506 lm_button_audio.set_name ("generic button");
507 lm_button_audio.set_can_focus(true);
510 build_full_control_notebook ();
512 build_no_control_notebook ();
515 basic_vbox.pack_start (basic_hbox, false, false);
518 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
519 basic_vbox.show_all ();
524 EngineControl::build_full_control_notebook ()
526 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
529 using namespace Notebook_Helpers;
531 vector<string> strings;
532 AttachOptions xopt = AttachOptions (FILL|EXPAND);
533 int row = 1; // row zero == backend combo
535 /* start packing it up */
537 if (backend->requires_driver_selection()) {
538 label = manage (left_aligned_label (_("Driver:")));
539 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
540 basic_packer.attach (driver_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
544 if (backend->use_separate_input_and_output_devices()) {
545 label = manage (left_aligned_label (_("Input Device:")));
546 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
547 basic_packer.attach (input_device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
549 label = manage (left_aligned_label (_("Output Device:")));
550 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
551 basic_packer.attach (output_device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
553 // reset so it isn't used in state comparisons
554 device_combo.set_active_text ("");
556 label = manage (left_aligned_label (_("Device:")));
557 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
558 basic_packer.attach (device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
560 // reset these so they don't get used in state comparisons
561 input_device_combo.set_active_text ("");
562 output_device_combo.set_active_text ("");
565 label = manage (left_aligned_label (_("Sample rate:")));
566 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
567 basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
571 label = manage (left_aligned_label (_("Buffer size:")));
572 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
573 basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
574 buffer_size_duration_label.set_alignment (0.0); /* left-align */
575 basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
577 int ctrl_btn_span = 1;
578 if (backend->can_set_period_size ()) {
580 label = manage (left_aligned_label (_("Periods:")));
581 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
582 basic_packer.attach (nperiods_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
586 /* button spans 2 or 3 rows */
588 basic_packer.attach (control_app_button, 3, 4, row - ctrl_btn_span, row + 1, xopt, xopt);
591 input_channels.set_name ("InputChannels");
592 input_channels.set_flags (Gtk::CAN_FOCUS);
593 input_channels.set_digits (0);
594 input_channels.set_wrap (false);
595 output_channels.set_editable (true);
597 if (!ARDOUR::Profile->get_mixbus()) {
598 label = manage (left_aligned_label (_("Input Channels:")));
599 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
600 basic_packer.attach (input_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
604 output_channels.set_name ("OutputChannels");
605 output_channels.set_flags (Gtk::CAN_FOCUS);
606 output_channels.set_digits (0);
607 output_channels.set_wrap (false);
608 output_channels.set_editable (true);
610 if (!ARDOUR::Profile->get_mixbus()) {
611 label = manage (left_aligned_label (_("Output Channels:")));
612 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
613 basic_packer.attach (output_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
617 input_latency.set_name ("InputLatency");
618 input_latency.set_flags (Gtk::CAN_FOCUS);
619 input_latency.set_digits (0);
620 input_latency.set_wrap (false);
621 input_latency.set_editable (true);
623 label = manage (left_aligned_label (_("Hardware input latency:")));
624 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
625 basic_packer.attach (input_latency, 1, 2, row, row+1, xopt, (AttachOptions) 0);
626 label = manage (left_aligned_label (_("samples")));
627 basic_packer.attach (*label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
630 output_latency.set_name ("OutputLatency");
631 output_latency.set_flags (Gtk::CAN_FOCUS);
632 output_latency.set_digits (0);
633 output_latency.set_wrap (false);
634 output_latency.set_editable (true);
636 label = manage (left_aligned_label (_("Hardware output latency:")));
637 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
638 basic_packer.attach (output_latency, 1, 2, row, row+1, xopt, (AttachOptions) 0);
639 label = manage (left_aligned_label (_("samples")));
640 basic_packer.attach (*label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
642 /* button spans 2 rows */
644 basic_packer.attach (lm_button_audio, 3, 4, row-1, row+1, xopt, xopt);
647 label = manage (left_aligned_label (_("MIDI System:")));
648 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
649 basic_packer.attach (midi_option_combo, 1, 2, row, row + 1, SHRINK, (AttachOptions) 0);
650 basic_packer.attach (midi_devices_button, 3, 4, row, row+1, xopt, xopt);
655 EngineControl::build_no_control_notebook ()
657 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
660 using namespace Notebook_Helpers;
662 vector<string> strings;
663 AttachOptions xopt = AttachOptions (FILL|EXPAND);
664 int row = 1; // row zero == backend combo
665 const string msg = string_compose (_("%1 is already running. %2 will connect to it and use the existing settings."), backend->name(), PROGRAM_NAME);
667 label = manage (new Label);
668 label->set_markup (string_compose ("<span weight=\"bold\" foreground=\"red\">%1</span>", msg));
669 basic_packer.attach (*label, 0, 2, row, row + 1, xopt, (AttachOptions) 0);
672 if (backend->can_change_sample_rate_when_running()) {
673 label = manage (left_aligned_label (_("Sample rate:")));
674 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
675 basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
679 if (backend->can_change_buffer_size_when_running()) {
680 label = manage (left_aligned_label (_("Buffer size:")));
681 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
682 basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
683 buffer_size_duration_label.set_alignment (0.0); /* left-align */
684 basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, xopt, (AttachOptions) 0);
688 basic_packer.attach (connect_disconnect_button, 0, 2, row, row+1, FILL, AttachOptions (0));
692 EngineControl::~EngineControl ()
694 ignore_changes = true;
698 EngineControl::disable_latency_tab ()
700 vector<string> empty;
701 set_popdown_strings (lm_output_channel_combo, empty);
702 set_popdown_strings (lm_input_channel_combo, empty);
703 lm_measure_button.set_sensitive (false);
704 lm_use_button.set_sensitive (false);
708 EngineControl::enable_latency_tab ()
710 vector<string> outputs;
711 vector<string> inputs;
713 ARDOUR::DataType const type = _measure_midi ? ARDOUR::DataType::MIDI : ARDOUR::DataType::AUDIO;
714 ARDOUR::AudioEngine::instance()->get_physical_outputs (type, outputs);
715 ARDOUR::AudioEngine::instance()->get_physical_inputs (type, inputs);
717 if (!ARDOUR::AudioEngine::instance()->running()) {
718 MessageDialog msg (_("Failed to start or connect to audio-engine.\n\nLatency calibration requires a working audio interface."));
719 notebook.set_current_page (0);
723 else if (inputs.empty() || outputs.empty()) {
724 MessageDialog msg (_("Your selected audio configuration is playback- or capture-only.\n\nLatency calibration requires playback and capture"));
725 notebook.set_current_page (0);
730 lm_back_button_signal.disconnect();
732 lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), midi_tab));
735 lm_back_button_signal = lm_back_button.signal_clicked().connect(
736 sigc::mem_fun(*this, &EngineControl::latency_back_button_clicked));
740 set_popdown_strings (lm_output_channel_combo, outputs);
741 lm_output_channel_combo.set_active_text (outputs.front());
742 lm_output_channel_combo.set_sensitive (true);
744 set_popdown_strings (lm_input_channel_combo, inputs);
745 lm_input_channel_combo.set_active_text (inputs.front());
746 lm_input_channel_combo.set_sensitive (true);
748 lm_measure_button.set_sensitive (true);
752 EngineControl::setup_midi_tab_for_backend ()
754 string backend = backend_combo.get_active_text ();
756 Gtkmm2ext::container_clear (midi_vbox);
758 midi_vbox.set_border_width (12);
759 midi_device_table.set_border_width (12);
761 if (backend == "JACK") {
762 setup_midi_tab_for_jack ();
765 midi_vbox.pack_start (midi_device_table, true, true);
766 midi_vbox.pack_start (midi_back_button, false, false);
767 midi_vbox.show_all ();
771 EngineControl::update_sensitivity ()
773 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
775 start_stop_button.set_sensitive (false);
780 size_t devices_available = 0;
781 bool engine_running = ARDOUR::AudioEngine::instance()->running();
783 if (backend->use_separate_input_and_output_devices ()) {
784 devices_available += get_popdown_string_count (input_device_combo);
785 devices_available += get_popdown_string_count (output_device_combo);
787 devices_available += get_popdown_string_count (device_combo);
790 if (devices_available == 0) {
792 input_latency.set_sensitive (false);
793 output_latency.set_sensitive (false);
794 input_channels.set_sensitive (false);
795 output_channels.set_sensitive (false);
797 input_latency.set_sensitive (true);
798 output_latency.set_sensitive (true);
799 input_channels.set_sensitive (!engine_running);
800 output_channels.set_sensitive (!engine_running);
803 if (get_popdown_string_count (buffer_size_combo) > 0) {
804 if (!engine_running) {
805 buffer_size_combo.set_sensitive (valid);
806 } else if (backend->can_change_buffer_size_when_running ()) {
807 buffer_size_combo.set_sensitive (valid || !_have_control);
809 buffer_size_combo.set_sensitive (false);
812 buffer_size_combo.set_sensitive (false);
816 if (get_popdown_string_count (sample_rate_combo) > 0) {
817 bool allow_to_set_rate = false;
818 if (!engine_running) {
819 if (!ARDOUR_UI::instance()->the_session ()) {
820 // engine is not running, no session loaded -> anything goes.
821 allow_to_set_rate = true;
822 } else if (_desired_sample_rate > 0 && get_rate () != _desired_sample_rate) {
823 // only allow to change if the current setting is not the native session rate.
824 allow_to_set_rate = true;
827 sample_rate_combo.set_sensitive (allow_to_set_rate);
829 sample_rate_combo.set_sensitive (false);
833 if (get_popdown_string_count (nperiods_combo) > 0) {
834 if (!engine_running) {
835 nperiods_combo.set_sensitive (true);
837 nperiods_combo.set_sensitive (false);
840 nperiods_combo.set_sensitive (false);
844 start_stop_button.set_sensitive(true);
845 start_stop_button.show();
846 if (engine_running) {
847 start_stop_button.set_text("Stop");
848 update_devices_button.set_sensitive(false);
849 use_buffered_io_button.set_sensitive(false);
851 if (backend->can_request_update_devices()) {
852 update_devices_button.show();
854 update_devices_button.hide();
856 if (backend->can_use_buffered_io()) {
857 use_buffered_io_button.show();
859 use_buffered_io_button.hide();
861 start_stop_button.set_text("Start");
862 update_devices_button.set_sensitive(true);
863 use_buffered_io_button.set_sensitive(true);
866 update_devices_button.set_sensitive(false);
867 update_devices_button.hide();
868 use_buffered_io_button.set_sensitive(false);
869 use_buffered_io_button.hide();
870 start_stop_button.set_sensitive(false);
871 start_stop_button.hide();
874 if (engine_running && _have_control) {
875 input_device_combo.set_sensitive (false);
876 output_device_combo.set_sensitive (false);
877 device_combo.set_sensitive (false);
878 driver_combo.set_sensitive (false);
880 input_device_combo.set_sensitive (true);
881 output_device_combo.set_sensitive (true);
882 device_combo.set_sensitive (true);
883 if (backend->requires_driver_selection() && get_popdown_string_count(driver_combo) > 0) {
884 driver_combo.set_sensitive (true);
886 driver_combo.set_sensitive (false);
890 midi_option_combo.set_sensitive (!engine_running);
894 EngineControl::setup_midi_tab_for_jack ()
899 EngineControl::midi_latency_adjustment_changed (Gtk::Adjustment *a, MidiDeviceSettings device, bool for_input) {
901 device->input_latency = a->get_value();
903 device->output_latency = a->get_value();
906 if (ARDOUR::AudioEngine::instance()->running() && !_measure_midi) {
907 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
909 if (backend->can_change_systemic_latency_when_running () && device->enabled) {
911 backend->set_systemic_midi_input_latency (device->name, device->input_latency);
913 backend->set_systemic_midi_output_latency (device->name, device->output_latency);
920 EngineControl::midi_device_enabled_toggled (ArdourButton *b, MidiDeviceSettings device) {
921 b->set_active (!b->get_active());
922 device->enabled = b->get_active();
923 refresh_midi_display(device->name);
925 if (ARDOUR::AudioEngine::instance()->running()) {
926 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
928 backend->set_midi_device_enabled (device->name, device->enabled);
929 if (backend->can_change_systemic_latency_when_running () && device->enabled) {
930 backend->set_systemic_midi_input_latency (device->name, device->input_latency);
931 backend->set_systemic_midi_output_latency (device->name, device->output_latency);
937 EngineControl::refresh_midi_display (std::string focus)
939 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
943 AttachOptions xopt = AttachOptions (FILL|EXPAND);
946 Gtkmm2ext::container_clear (midi_device_table);
948 midi_device_table.set_spacings (6);
950 l = manage (new Label);
951 l->set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Devices")));
952 midi_device_table.attach (*l, 0, 4, row, row + 1, xopt, AttachOptions (0));
953 l->set_alignment (0.5, 0.5);
957 l = manage (new Label (_("Device"))); l->show (); l->set_alignment (0.5, 0.5);
958 midi_device_table.attach (*l, 0, 1, row, row + 2, xopt, AttachOptions (0));
959 l = manage (new Label (_("Hardware Latencies"))); l->show (); l->set_alignment (0.5, 0.5);
960 midi_device_table.attach (*l, 1, 3, row, row + 1, xopt, AttachOptions (0));
962 l = manage (new Label (_("Input"))); l->show (); l->set_alignment (0.5, 0.5);
963 midi_device_table.attach (*l, 1, 2, row, row + 1, xopt, AttachOptions (0));
964 l = manage (new Label (_("Output"))); l->show (); l->set_alignment (0.5, 0.5);
965 midi_device_table.attach (*l, 2, 3, row, row + 1, xopt, AttachOptions (0));
968 for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
973 bool enabled = (*p)->enabled;
975 m = manage (new ArdourButton ((*p)->name, ArdourButton::led_default_elements));
976 m->set_name ("midi device");
977 m->set_can_focus (Gtk::CAN_FOCUS);
978 m->add_events (Gdk::BUTTON_RELEASE_MASK);
979 m->set_active (enabled);
980 m->signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_device_enabled_toggled), m, *p));
981 midi_device_table.attach (*m, 0, 1, row, row + 1, xopt, AttachOptions (0)); m->show ();
982 if ((*p)->name == focus) {
986 a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
987 s = manage (new Gtk::SpinButton (*a));
988 a->set_value ((*p)->input_latency);
989 s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, true));
990 s->set_sensitive (_can_set_midi_latencies && enabled);
991 midi_device_table.attach (*s, 1, 2, row, row + 1, xopt, AttachOptions (0)); s->show ();
993 a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
994 s = manage (new Gtk::SpinButton (*a));
995 a->set_value ((*p)->output_latency);
996 s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, false));
997 s->set_sensitive (_can_set_midi_latencies && enabled);
998 midi_device_table.attach (*s, 2, 3, row, row + 1, xopt, AttachOptions (0)); s->show ();
1000 b = manage (new Button (_("Calibrate")));
1001 b->signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::calibrate_midi_latency), *p));
1002 b->set_sensitive (_can_set_midi_latencies && enabled);
1003 midi_device_table.attach (*b, 3, 4, row, row + 1, xopt, AttachOptions (0)); b->show ();
1010 EngineControl::backend_changed ()
1012 SignalBlocker blocker (*this, "backend_changed");
1013 string backend_name = backend_combo.get_active_text();
1014 boost::shared_ptr<ARDOUR::AudioBackend> backend;
1016 if (!(backend = ARDOUR::AudioEngine::instance()->set_backend (backend_name, downcase (std::string(PROGRAM_NAME)), ""))) {
1017 /* eh? setting the backend failed... how ? */
1018 /* A: stale config contains a backend that does not exist in current build */
1022 DEBUG_ECONTROL (string_compose ("Backend name: %1", backend_name));
1024 _have_control = ARDOUR::AudioEngine::instance()->setup_required ();
1027 setup_midi_tab_for_backend ();
1028 _midi_devices.clear();
1030 if (backend->requires_driver_selection()) {
1031 if (set_driver_popdown_strings ()) {
1035 /* this will change the device text which will cause a call to
1036 * device changed which will set up parameters
1041 update_midi_options ();
1043 connect_disconnect_button.hide();
1045 midi_option_changed();
1047 started_at_least_once = false;
1049 /* changing the backend implies stopping the engine
1050 * ARDOUR::AudioEngine() may or may not emit this signal
1051 * depending on previous engine state
1053 engine_stopped (); // set "active/inactive"
1055 if (!_have_control) {
1056 // set settings from backend that we do have control over
1057 set_buffersize_popdown_strings ();
1058 set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
1061 if (_have_control && !ignore_changes) {
1062 // set driver & devices
1063 State state = get_matching_state (backend_combo.get_active_text());
1065 DEBUG_ECONTROL ("backend-changed(): found prior state for backend");
1066 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1067 set_current_state (state);
1069 DEBUG_ECONTROL ("backend-changed(): no prior state for backend");
1072 DEBUG_ECONTROL (string_compose ("backend-changed(): _have_control=%1 ignore_changes=%2", _have_control, ignore_changes));
1075 if (!ignore_changes) {
1076 maybe_display_saved_state ();
1081 EngineControl::update_midi_options ()
1083 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1084 vector<string> midi_options = backend->enumerate_midi_options();
1086 if (midi_options.size() == 1) {
1087 /* only contains the "none" option */
1088 midi_option_combo.set_sensitive (false);
1090 if (_have_control) {
1091 set_popdown_strings (midi_option_combo, midi_options);
1092 midi_option_combo.set_active_text (midi_options.front());
1093 midi_option_combo.set_sensitive (true);
1095 midi_option_combo.set_sensitive (false);
1101 EngineControl::print_channel_count (Gtk::SpinButton* sb)
1103 if (ARDOUR::Profile->get_mixbus()) {
1107 uint32_t cnt = (uint32_t) sb->get_value();
1109 sb->set_text (_("all available channels"));
1112 snprintf (buf, sizeof (buf), "%d", cnt);
1118 // @return true if there are drivers available
1120 EngineControl::set_driver_popdown_strings ()
1122 DEBUG_ECONTROL ("set_driver_popdown_strings");
1123 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1124 vector<string> drivers = backend->enumerate_drivers();
1126 if (drivers.empty ()) {
1127 // This is an error...?
1131 string current_driver = backend->driver_name ();
1133 DEBUG_ECONTROL (string_compose ("backend->driver_name: %1", current_driver));
1135 if (std::find (drivers.begin (), drivers.end (), current_driver) ==
1138 current_driver = drivers.front ();
1141 set_popdown_strings (driver_combo, drivers);
1143 string_compose ("driver_combo.set_active_text: %1", current_driver));
1144 driver_combo.set_active_text (current_driver);
1149 EngineControl::get_default_device(const string& current_device_name,
1150 const vector<string>& available_devices)
1152 // If the current device is available, use it as default
1153 if (std::find (available_devices.begin (),
1154 available_devices.end (),
1155 current_device_name) != available_devices.end ()) {
1157 return current_device_name;
1160 using namespace ARDOUR;
1162 string default_device_name =
1163 AudioBackend::get_standard_device_name(AudioBackend::DeviceDefault);
1165 vector<string>::const_iterator i;
1167 // If there is a "Default" device available, use it
1168 for (i = available_devices.begin(); i != available_devices.end(); ++i) {
1169 if (*i == default_device_name) {
1174 string none_device_name =
1175 AudioBackend::get_standard_device_name(AudioBackend::DeviceNone);
1177 // Use the first device that isn't "None"
1178 for (i = available_devices.begin(); i != available_devices.end(); ++i) {
1179 if (*i != none_device_name) {
1184 // Use "None" if there are no other available
1185 return available_devices.front();
1188 // @return true if there are devices available
1190 EngineControl::set_device_popdown_strings ()
1192 DEBUG_ECONTROL ("set_device_popdown_strings");
1193 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1194 vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_devices ();
1196 /* NOTE: Ardour currently does not display the "available" field of the
1199 * Doing so would require a different GUI widget than the combo
1200 * box/popdown that we currently use, since it has no way to list
1201 * items that are not selectable. Something more like a popup menu,
1202 * which could have unselectable items, would be appropriate.
1205 vector<string> available_devices;
1207 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1208 available_devices.push_back (i->name);
1211 if (available_devices.empty ()) {
1215 set_popdown_strings (device_combo, available_devices);
1217 std::string default_device =
1218 get_default_device(backend->device_name(), available_devices);
1221 string_compose ("set device_combo active text: %1", default_device));
1223 device_combo.set_active_text(default_device);
1227 // @return true if there are input devices available
1229 EngineControl::set_input_device_popdown_strings ()
1231 DEBUG_ECONTROL ("set_input_device_popdown_strings");
1232 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1233 vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_input_devices ();
1235 vector<string> available_devices;
1237 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1238 available_devices.push_back (i->name);
1241 if (available_devices.empty()) {
1245 set_popdown_strings (input_device_combo, available_devices);
1247 std::string default_device =
1248 get_default_device(backend->input_device_name(), available_devices);
1251 string_compose ("set input_device_combo active text: %1", default_device));
1252 input_device_combo.set_active_text(default_device);
1256 // @return true if there are output devices available
1258 EngineControl::set_output_device_popdown_strings ()
1260 DEBUG_ECONTROL ("set_output_device_popdown_strings");
1261 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1262 vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_output_devices ();
1264 vector<string> available_devices;
1266 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1267 available_devices.push_back (i->name);
1270 if (available_devices.empty()) {
1274 set_popdown_strings (output_device_combo, available_devices);
1276 std::string default_device =
1277 get_default_device(backend->output_device_name(), available_devices);
1280 string_compose ("set output_device_combo active text: %1", default_device));
1281 output_device_combo.set_active_text(default_device);
1286 EngineControl::list_devices ()
1288 DEBUG_ECONTROL ("list_devices");
1289 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1292 /* now fill out devices, mark sample rates, buffer sizes insensitive */
1294 bool devices_available = false;
1296 if (backend->use_separate_input_and_output_devices ()) {
1297 bool input_devices_available = set_input_device_popdown_strings ();
1298 bool output_devices_available = set_output_device_popdown_strings ();
1299 devices_available = input_devices_available || output_devices_available;
1301 devices_available = set_device_popdown_strings ();
1304 if (devices_available) {
1307 device_combo.clear();
1308 input_device_combo.clear();
1309 output_device_combo.clear();
1311 update_sensitivity ();
1315 EngineControl::driver_changed ()
1317 SignalBlocker blocker (*this, "driver_changed");
1318 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1321 backend->set_driver (driver_combo.get_active_text());
1324 // TODO load LRU device(s) for backend + driver combo
1326 if (!ignore_changes) {
1327 maybe_display_saved_state ();
1332 EngineControl::get_sample_rates_for_all_devices ()
1334 boost::shared_ptr<ARDOUR::AudioBackend> backend =
1335 ARDOUR::AudioEngine::instance ()->current_backend ();
1336 vector<float> all_rates;
1338 if (backend->use_separate_input_and_output_devices ()) {
1339 all_rates = backend->available_sample_rates2 (get_input_device_name (), get_output_device_name ());
1341 all_rates = backend->available_sample_rates (get_device_name ());
1347 EngineControl::get_default_sample_rates ()
1349 vector<float> rates;
1350 rates.push_back (8000.0f);
1351 rates.push_back (16000.0f);
1352 rates.push_back (32000.0f);
1353 rates.push_back (44100.0f);
1354 rates.push_back (48000.0f);
1355 rates.push_back (88200.0f);
1356 rates.push_back (96000.0f);
1357 rates.push_back (192000.0f);
1358 rates.push_back (384000.0f);
1363 EngineControl::set_samplerate_popdown_strings ()
1365 DEBUG_ECONTROL ("set_samplerate_popdown_strings");
1366 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1371 if (_have_control) {
1372 sr = get_sample_rates_for_all_devices ();
1374 sr = get_default_sample_rates ();
1377 for (vector<float>::const_iterator x = sr.begin(); x != sr.end(); ++x) {
1378 s.push_back (rate_as_string (*x));
1379 if (*x == _desired_sample_rate) {
1384 set_popdown_strings (sample_rate_combo, s);
1387 if (ARDOUR::AudioEngine::instance()->running()) {
1388 sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
1389 } else if (ARDOUR_UI::instance()->the_session ()) {
1390 float active_sr = ARDOUR_UI::instance()->the_session()->nominal_sample_rate ();
1392 if (std::find (sr.begin (), sr.end (), active_sr) == sr.end ()) {
1393 active_sr = sr.front ();
1396 sample_rate_combo.set_active_text (rate_as_string (active_sr));
1397 } else if (desired.empty ()) {
1398 float new_active_sr = backend->default_sample_rate ();
1400 if (std::find (sr.begin (), sr.end (), new_active_sr) == sr.end ()) {
1401 new_active_sr = sr.front ();
1404 sample_rate_combo.set_active_text (rate_as_string (new_active_sr));
1406 sample_rate_combo.set_active_text (desired);
1409 update_sensitivity ();
1413 EngineControl::get_buffer_sizes_for_all_devices ()
1415 boost::shared_ptr<ARDOUR::AudioBackend> backend =
1416 ARDOUR::AudioEngine::instance ()->current_backend ();
1417 vector<uint32_t> all_sizes;
1419 if (backend->use_separate_input_and_output_devices ()) {
1420 all_sizes = backend->available_buffer_sizes2 (get_input_device_name (), get_output_device_name ());
1422 all_sizes = backend->available_buffer_sizes (get_device_name ());
1428 EngineControl::get_default_buffer_sizes ()
1430 vector<uint32_t> sizes;
1431 sizes.push_back (8);
1432 sizes.push_back (16);
1433 sizes.push_back (32);
1434 sizes.push_back (64);
1435 sizes.push_back (128);
1436 sizes.push_back (256);
1437 sizes.push_back (512);
1438 sizes.push_back (1024);
1439 sizes.push_back (2048);
1440 sizes.push_back (4096);
1441 sizes.push_back (8192);
1446 EngineControl::set_buffersize_popdown_strings ()
1448 DEBUG_ECONTROL ("set_buffersize_popdown_strings");
1449 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1450 vector<uint32_t> bs;
1453 if (_have_control) {
1454 bs = get_buffer_sizes_for_all_devices ();
1455 } else if (backend->can_change_buffer_size_when_running()) {
1456 bs = get_default_buffer_sizes ();
1459 for (vector<uint32_t>::const_iterator x = bs.begin(); x != bs.end(); ++x) {
1460 s.push_back (bufsize_as_string (*x));
1463 uint32_t previous_size = backend->buffer_size ();
1464 if (!buffer_size_combo.get_active_text().empty()) {
1465 previous_size = get_buffer_size ();
1468 set_popdown_strings (buffer_size_combo, s);
1472 if (std::find(bs.begin(), bs.end(), previous_size) != bs.end()) {
1473 buffer_size_combo.set_active_text(bufsize_as_string(previous_size));
1476 buffer_size_combo.set_active_text(s.front());
1478 uint32_t period = backend->buffer_size();
1479 if (0 == period && backend->use_separate_input_and_output_devices()) {
1480 period = backend->default_buffer_size(get_input_device_name());
1482 if (0 == period && backend->use_separate_input_and_output_devices()) {
1483 period = backend->default_buffer_size(get_output_device_name());
1485 if (0 == period && !backend->use_separate_input_and_output_devices()) {
1486 period = backend->default_buffer_size(get_device_name());
1489 set_active_text_if_present(buffer_size_combo, bufsize_as_string(period));
1491 show_buffer_duration ();
1493 update_sensitivity ();
1497 EngineControl::set_nperiods_popdown_strings ()
1499 DEBUG_ECONTROL ("set_nperiods_popdown_strings");
1500 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1501 vector<uint32_t> np;
1504 if (backend->can_set_period_size()) {
1505 np = backend->available_period_sizes (get_driver());
1508 for (vector<uint32_t>::const_iterator x = np.begin(); x != np.end(); ++x) {
1509 s.push_back (to_string (*x));
1512 set_popdown_strings (nperiods_combo, s);
1515 set_active_text_if_present (nperiods_combo, to_string (backend->period_size())); // XXX
1518 update_sensitivity ();
1522 EngineControl::device_changed ()
1524 SignalBlocker blocker (*this, "device_changed");
1525 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1528 string device_name_in;
1529 string device_name_out; // only used if backend support separate I/O devices
1531 if (backend->use_separate_input_and_output_devices()) {
1532 device_name_in = get_input_device_name ();
1533 device_name_out = get_output_device_name ();
1535 device_name_in = get_device_name ();
1538 /* we set the backend-device to query various device related intormation.
1539 * This has the side effect that backend->device_name() will match
1540 * the device_name and 'change_device' will never be true.
1541 * so work around this by setting...
1543 if (backend->use_separate_input_and_output_devices()) {
1544 if (device_name_in != backend->input_device_name() || device_name_out != backend->output_device_name ()) {
1545 queue_device_changed = true;
1548 if (device_name_in != backend->device_name()) {
1549 queue_device_changed = true;
1553 //the device name must be set FIRST so ASIO can populate buffersizes and the control panel button
1554 if (backend->use_separate_input_and_output_devices()) {
1555 backend->set_input_device_name (device_name_in);
1556 backend->set_output_device_name (device_name_out);
1558 backend->set_device_name(device_name_in);
1562 /* don't allow programmatic change to combos to cause a
1563 recursive call to this method.
1565 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1567 set_samplerate_popdown_strings ();
1568 set_buffersize_popdown_strings ();
1569 set_nperiods_popdown_strings ();
1571 /* TODO set min + max channel counts here */
1573 manage_control_app_sensitivity ();
1576 /* pick up any saved state for this device */
1578 if (!ignore_changes) {
1579 maybe_display_saved_state ();
1584 EngineControl::input_device_changed ()
1586 DEBUG_ECONTROL ("input_device_changed");
1588 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1589 if (backend && backend->match_input_output_devices_or_none ()) {
1590 const std::string& dev_none = ARDOUR::AudioBackend::get_standard_device_name (ARDOUR::AudioBackend::DeviceNone);
1592 if (get_output_device_name () != dev_none
1593 && get_input_device_name () != dev_none
1594 && get_input_device_name () != get_output_device_name ()) {
1595 block_changed_signals ();
1596 if (contains_value (output_device_combo, get_input_device_name ())) {
1597 output_device_combo.set_active_text (get_input_device_name ());
1599 assert (contains_value (output_device_combo, dev_none));
1600 output_device_combo.set_active_text (dev_none);
1602 unblock_changed_signals ();
1609 EngineControl::output_device_changed ()
1611 DEBUG_ECONTROL ("output_device_changed");
1612 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1613 if (backend && backend->match_input_output_devices_or_none ()) {
1614 const std::string& dev_none = ARDOUR::AudioBackend::get_standard_device_name (ARDOUR::AudioBackend::DeviceNone);
1616 if (get_input_device_name () != dev_none
1617 && get_input_device_name () != dev_none
1618 && get_input_device_name () != get_output_device_name ()) {
1619 block_changed_signals ();
1620 if (contains_value (input_device_combo, get_output_device_name ())) {
1621 input_device_combo.set_active_text (get_output_device_name ());
1623 assert (contains_value (input_device_combo, dev_none));
1624 input_device_combo.set_active_text (dev_none);
1626 unblock_changed_signals ();
1633 EngineControl::bufsize_as_string (uint32_t sz)
1635 return string_compose (P_("%1 sample", "%1 samples", sz), to_string(sz));
1639 EngineControl::sample_rate_changed ()
1641 DEBUG_ECONTROL ("sample_rate_changed");
1642 /* reset the strings for buffer size to show the correct msec value
1643 (reflecting the new sample rate).
1646 show_buffer_duration ();
1651 EngineControl::buffer_size_changed ()
1653 DEBUG_ECONTROL ("buffer_size_changed");
1654 if (ARDOUR::AudioEngine::instance()->running()) {
1655 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1656 if (backend && backend->can_change_buffer_size_when_running ()) {
1657 backend->set_buffer_size (get_buffer_size());
1660 show_buffer_duration ();
1664 EngineControl::nperiods_changed ()
1666 DEBUG_ECONTROL ("nperiods_changed");
1667 show_buffer_duration ();
1671 EngineControl::show_buffer_duration ()
1673 DEBUG_ECONTROL ("show_buffer_duration");
1674 /* buffer sizes - convert from just samples to samples + msecs for
1675 * the displayed string
1678 string bs_text = buffer_size_combo.get_active_text ();
1679 uint32_t samples = atoi (bs_text); /* will ignore trailing text */
1680 uint32_t rate = get_rate();
1682 /* Except for ALSA and Dummy backends, we don't know the number of periods
1683 * per cycle and settings.
1685 * jack1 vs jack2 have different default latencies since jack2 start
1686 * in async-mode unless --sync is given which adds an extra cycle
1687 * of latency. The value is not known if jackd is started externally..
1689 * So just display the period size, that's also what
1690 * ARDOUR_UI::update_sample_rate() does for the status bar.
1691 * (the statusbar calls AudioEngine::instance()->usecs_per_cycle()
1692 * but still, that's the buffer period, not [round-trip] latency)
1695 snprintf (buf, sizeof (buf), _("(%.1f ms)"), (samples / (rate/1000.0f)));
1696 buffer_size_duration_label.set_text (buf);
1700 EngineControl::midi_option_changed ()
1702 DEBUG_ECONTROL ("midi_option_changed");
1703 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1706 backend->set_midi_option (get_midi_option());
1708 vector<ARDOUR::AudioBackend::DeviceStatus> midi_devices = backend->enumerate_midi_devices();
1710 //_midi_devices.clear(); // TODO merge with state-saved settings..
1711 _can_set_midi_latencies = backend->can_set_systemic_midi_latencies();
1712 std::vector<MidiDeviceSettings> new_devices;
1714 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = midi_devices.begin(); i != midi_devices.end(); ++i) {
1715 MidiDeviceSettings mds = find_midi_device (i->name);
1716 if (i->available && !mds) {
1717 uint32_t input_latency = 0;
1718 uint32_t output_latency = 0;
1719 if (_can_set_midi_latencies) {
1720 input_latency = backend->systemic_midi_input_latency (i->name);
1721 output_latency = backend->systemic_midi_output_latency (i->name);
1723 bool enabled = backend->midi_device_enabled (i->name);
1724 MidiDeviceSettings ptr (new MidiDeviceSetting (i->name, enabled, input_latency, output_latency));
1725 new_devices.push_back (ptr);
1726 } else if (i->available) {
1727 new_devices.push_back (mds);
1730 _midi_devices = new_devices;
1732 if (_midi_devices.empty()) {
1733 midi_devices_button.hide ();
1735 midi_devices_button.show ();
1740 EngineControl::parameter_changed ()
1744 EngineControl::State
1745 EngineControl::get_matching_state (const string& backend)
1747 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1748 if ((*i)->backend == backend) {
1755 EngineControl::State
1756 EngineControl::get_matching_state (
1757 const string& backend,
1758 const string& driver,
1759 const string& device)
1761 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1762 if ((*i)->backend == backend &&
1763 (!_have_control || ((*i)->driver == driver && (*i)->device == device)))
1771 EngineControl::State
1772 EngineControl::get_matching_state (
1773 const string& backend,
1774 const string& driver,
1775 const string& input_device,
1776 const string& output_device)
1778 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1779 if ((*i)->backend == backend &&
1780 (!_have_control || ((*i)->driver == driver && ((*i)->input_device == input_device) && (*i)->output_device == output_device)))
1788 EngineControl::State
1789 EngineControl::get_saved_state_for_currently_displayed_backend_and_device ()
1791 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1794 if (backend->use_separate_input_and_output_devices ()) {
1795 return get_matching_state (backend_combo.get_active_text(),
1796 (backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
1797 input_device_combo.get_active_text(),
1798 output_device_combo.get_active_text());
1800 return get_matching_state (backend_combo.get_active_text(),
1801 (backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
1802 device_combo.get_active_text());
1806 return get_matching_state (backend_combo.get_active_text(),
1808 device_combo.get_active_text());
1811 bool EngineControl::equivalent_states (const EngineControl::State& state1,
1812 const EngineControl::State& state2)
1814 if (state1->backend == state2->backend &&
1815 state1->driver == state2->driver &&
1816 state1->device == state2->device &&
1817 state1->input_device == state2->input_device &&
1818 state1->output_device == state2->output_device) {
1824 // sort active first, then most recently used to the beginning of the list
1826 EngineControl::state_sort_cmp (const State &a, const State &b) {
1830 else if (b->active) {
1834 return a->lru > b->lru;
1838 EngineControl::State
1839 EngineControl::save_state ()
1843 if (!_have_control) {
1844 state = get_matching_state (backend_combo.get_active_text(), string(), string());
1846 state->lru = time (NULL) ;
1849 state.reset(new StateStruct);
1850 state->backend = get_backend ();
1852 state.reset(new StateStruct);
1853 store_state (state);
1856 for (StateList::iterator i = states.begin(); i != states.end();) {
1857 if (equivalent_states (*i, state)) {
1858 i = states.erase(i);
1864 states.push_back (state);
1866 states.sort (state_sort_cmp);
1872 EngineControl::store_state (State state)
1874 state->backend = get_backend ();
1875 state->driver = get_driver ();
1876 state->device = get_device_name ();
1877 state->input_device = get_input_device_name ();
1878 state->output_device = get_output_device_name ();
1879 state->sample_rate = get_rate ();
1880 state->buffer_size = get_buffer_size ();
1881 state->n_periods = get_nperiods ();
1882 state->input_latency = get_input_latency ();
1883 state->output_latency = get_output_latency ();
1884 state->input_channels = get_input_channels ();
1885 state->output_channels = get_output_channels ();
1886 state->midi_option = get_midi_option ();
1887 state->midi_devices = _midi_devices;
1888 state->use_buffered_io = get_use_buffered_io ();
1889 state->lru = time (NULL) ;
1893 EngineControl::maybe_display_saved_state ()
1895 if (!_have_control || ARDOUR::AudioEngine::instance()->running ()) {
1899 State state = get_saved_state_for_currently_displayed_backend_and_device ();
1902 DEBUG_ECONTROL ("Restoring saved state");
1903 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1905 if (0 == _desired_sample_rate && sample_rate_combo.get_sensitive ()) {
1906 sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
1908 set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
1910 set_active_text_if_present (nperiods_combo, to_string(state->n_periods));
1911 /* call this explicitly because we're ignoring changes to
1912 the controls at this point.
1914 show_buffer_duration ();
1915 input_latency.set_value (state->input_latency);
1916 output_latency.set_value (state->output_latency);
1918 use_buffered_io_button.set_active (state->use_buffered_io);
1920 if (!state->midi_option.empty()) {
1921 midi_option_combo.set_active_text (state->midi_option);
1922 _midi_devices = state->midi_devices;
1925 DEBUG_ECONTROL ("Unable to find saved state for backend and devices");
1930 EngineControl::get_state ()
1934 XMLNode* root = new XMLNode ("AudioMIDISetup");
1937 if (!states.empty()) {
1938 XMLNode* state_nodes = new XMLNode ("EngineStates");
1940 for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
1942 XMLNode* node = new XMLNode ("State");
1944 node->set_property ("backend", (*i)->backend);
1945 node->set_property ("driver", (*i)->driver);
1946 node->set_property ("device", (*i)->device);
1947 node->set_property ("input-device", (*i)->input_device);
1948 node->set_property ("output-device", (*i)->output_device);
1949 node->set_property ("sample-rate", (*i)->sample_rate);
1950 node->set_property ("buffer-size", (*i)->buffer_size);
1951 node->set_property ("n-periods", (*i)->n_periods);
1952 node->set_property ("input-latency", (*i)->input_latency);
1953 node->set_property ("output-latency", (*i)->output_latency);
1954 node->set_property ("input-channels", (*i)->input_channels);
1955 node->set_property ("output-channels", (*i)->output_channels);
1956 node->set_property ("active", (*i)->active);
1957 node->set_property ("use-buffered-io", (*i)->use_buffered_io);
1958 node->set_property ("midi-option", (*i)->midi_option);
1959 int32_t lru_val = (*i)->active ? time (NULL) : (*i)->lru;
1960 node->set_property ("lru", lru_val );
1962 XMLNode* midi_devices = new XMLNode ("MIDIDevices");
1963 for (std::vector<MidiDeviceSettings>::const_iterator p = (*i)->midi_devices.begin(); p != (*i)->midi_devices.end(); ++p) {
1964 XMLNode* midi_device_stuff = new XMLNode ("MIDIDevice");
1965 midi_device_stuff->set_property (X_("name"), (*p)->name);
1966 midi_device_stuff->set_property (X_("enabled"), (*p)->enabled);
1967 midi_device_stuff->set_property (X_("input-latency"), (*p)->input_latency);
1968 midi_device_stuff->set_property (X_("output-latency"), (*p)->output_latency);
1969 midi_devices->add_child_nocopy (*midi_device_stuff);
1971 node->add_child_nocopy (*midi_devices);
1973 state_nodes->add_child_nocopy (*node);
1976 root->add_child_nocopy (*state_nodes);
1983 EngineControl::set_default_state ()
1985 vector<string> backend_names;
1986 vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
1988 for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
1989 backend_names.push_back ((*b)->name);
1991 backend_combo.set_active_text (backend_names.front());
1993 // We could set default backends per platform etc here
1999 EngineControl::set_state (const XMLNode& root)
2001 XMLNodeList clist, cclist;
2002 XMLNodeConstIterator citer, cciter;
2003 XMLNode const * child;
2004 XMLNode const * grandchild;
2006 if (root.name() != "AudioMIDISetup") {
2010 clist = root.children();
2014 for (citer = clist.begin(); citer != clist.end(); ++citer) {
2018 if (child->name() != "EngineStates") {
2022 cclist = child->children();
2024 for (cciter = cclist.begin(); cciter != cclist.end(); ++cciter) {
2025 State state (new StateStruct);
2027 grandchild = *cciter;
2029 if (grandchild->name() != "State") {
2033 if (!grandchild->get_property ("backend", state->backend)) {
2037 // If any of the required properties are not found in the state node
2038 // then continue/skip to the next engine state
2039 if (!grandchild->get_property ("driver", state->driver) ||
2040 !grandchild->get_property ("device", state->device) ||
2041 !grandchild->get_property ("input-device", state->input_device) ||
2042 !grandchild->get_property ("output-device", state->output_device) ||
2043 !grandchild->get_property ("sample-rate", state->sample_rate) ||
2044 !grandchild->get_property ("buffer-size", state->buffer_size) ||
2045 !grandchild->get_property ("input-latency", state->input_latency) ||
2046 !grandchild->get_property ("output-latency", state->output_latency) ||
2047 !grandchild->get_property ("input-channels", state->input_channels) ||
2048 !grandchild->get_property ("output-channels", state->output_channels) ||
2049 !grandchild->get_property ("active", state->active) ||
2050 !grandchild->get_property ("use-buffered-io", state->use_buffered_io) ||
2051 !grandchild->get_property ("midi-option", state->midi_option)) {
2055 if (!grandchild->get_property ("n-periods", state->n_periods)) {
2056 // optional (new value in 4.5)
2057 state->n_periods = 0;
2060 state->midi_devices.clear();
2062 if ((midinode = ARDOUR::find_named_node (*grandchild, "MIDIDevices")) != 0) {
2063 const XMLNodeList mnc = midinode->children();
2064 for (XMLNodeList::const_iterator n = mnc.begin(); n != mnc.end(); ++n) {
2067 uint32_t input_latency;
2068 uint32_t output_latency;
2070 if (!(*n)->get_property (X_("name"), name) ||
2071 !(*n)->get_property (X_("enabled"), enabled) ||
2072 !(*n)->get_property (X_("input-latency"), input_latency) ||
2073 !(*n)->get_property (X_("output-latency"), output_latency)) {
2077 MidiDeviceSettings ptr (
2078 new MidiDeviceSetting (name, enabled, input_latency, output_latency));
2079 state->midi_devices.push_back (ptr);
2084 if (grandchild->get_property ("lru", lru_val)) {
2085 state->lru = lru_val;
2088 states.push_back (state);
2092 /* now see if there was an active state and switch the setup to it */
2094 /* purge states of backend that are not available in this built */
2095 vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
2096 vector<std::string> backend_names;
2098 for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator i = backends.begin(); i != backends.end(); ++i) {
2099 backend_names.push_back((*i)->name);
2101 for (StateList::iterator i = states.begin(); i != states.end();) {
2102 if (std::find(backend_names.begin(), backend_names.end(), (*i)->backend) == backend_names.end()) {
2103 i = states.erase(i);
2109 states.sort (state_sort_cmp);
2111 /* purge old states referring to the same backend */
2112 const time_t now = time (NULL);
2113 for (vector<std::string>::const_iterator bi = backend_names.begin(); bi != backend_names.end(); ++bi) {
2115 for (StateList::iterator i = states.begin(); i != states.end();) {
2116 if ((*i)->backend != *bi) {
2119 // keep at latest one for every audio-system
2124 // also keep states used in the last 90 days.
2125 if ((now - (*i)->lru) < 86400 * 90) {
2128 assert (!(*i)->active);
2129 i = states.erase(i);
2133 for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
2136 return set_current_state (*i);
2143 EngineControl::set_current_state (const State& state)
2145 DEBUG_ECONTROL ("set_current_state");
2147 boost::shared_ptr<ARDOUR::AudioBackend> backend;
2149 if (!(backend = ARDOUR::AudioEngine::instance ()->set_backend (
2150 state->backend, downcase (std::string(PROGRAM_NAME)), ""))) {
2151 DEBUG_ECONTROL (string_compose ("Unable to set backend to %1", state->backend));
2152 // this shouldn't happen as the invalid backend names should have been
2153 // removed from the list of states.
2157 // now reflect the change in the backend in the GUI so backend_changed will
2158 // do the right thing
2159 backend_combo.set_active_text (state->backend);
2161 if (!ARDOUR::AudioEngine::instance()->setup_required ()) {
2163 // we don't have control don't restore state
2168 if (!state->driver.empty ()) {
2169 if (!backend->requires_driver_selection ()) {
2170 DEBUG_ECONTROL ("Backend should require driver selection");
2171 // A backend has changed from having driver selection to not having
2172 // it or someone has been manually editing a config file and messed
2177 if (backend->set_driver (state->driver) != 0) {
2178 DEBUG_ECONTROL (string_compose ("Unable to set driver %1", state->driver));
2179 // Driver names for a backend have changed and the name in the
2180 // config file is now invalid or support for driver is no longer
2181 // included in the backend
2184 // no need to set the driver_combo as backend_changed will use
2185 // backend->driver_name to set the active driver
2188 if (!state->device.empty ()) {
2189 if (backend->set_device_name (state->device) != 0) {
2191 string_compose ("Unable to set device name %1", state->device));
2192 // device is no longer available on the system
2195 // no need to set active device as it will be picked up in
2196 // via backend_changed ()/set_device_popdown_strings
2199 // backend supports separate input/output devices
2200 if (backend->set_input_device_name (state->input_device) != 0) {
2201 DEBUG_ECONTROL (string_compose ("Unable to set input device name %1",
2202 state->input_device));
2203 // input device is no longer available on the system
2207 if (backend->set_output_device_name (state->output_device) != 0) {
2208 DEBUG_ECONTROL (string_compose ("Unable to set output device name %1",
2209 state->input_device));
2210 // output device is no longer available on the system
2213 // no need to set active devices as it will be picked up in via
2214 // backend_changed ()/set_*_device_popdown_strings
2219 // Now restore the state of the rest of the controls
2221 // We don't use a SignalBlocker as set_current_state is currently only
2222 // called from set_state before any signals are connected. If at some point
2223 // a more general named state mechanism is implemented and
2224 // set_current_state is called while signals are connected then a
2225 // SignalBlocker will need to be instantiated before setting these.
2227 device_combo.set_active_text (state->device);
2228 input_device_combo.set_active_text (state->input_device);
2229 output_device_combo.set_active_text (state->output_device);
2230 if (0 == _desired_sample_rate && sample_rate_combo.get_sensitive ()) {
2231 sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
2233 set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
2234 set_active_text_if_present (nperiods_combo, to_string (state->n_periods));
2235 input_latency.set_value (state->input_latency);
2236 output_latency.set_value (state->output_latency);
2237 midi_option_combo.set_active_text (state->midi_option);
2238 use_buffered_io_button.set_active (state->use_buffered_io);
2243 EngineControl::push_state_to_backend (bool start)
2245 DEBUG_ECONTROL ("push_state_to_backend");
2246 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2247 PBD::Unwinder<uint32_t> protect_ignore_device_changes (ignore_device_changes, ignore_device_changes + 1);
2253 /* figure out what is going to change */
2255 bool restart_required = false;
2256 bool was_running = ARDOUR::AudioEngine::instance()->running();
2257 bool change_driver = false;
2258 bool change_device = false;
2259 bool change_rate = false;
2260 bool change_bufsize = false;
2261 bool change_nperiods = false;
2262 bool change_latency = false;
2263 bool change_channels = false;
2264 bool change_midi = false;
2265 bool change_buffered_io = false;
2267 uint32_t ochan = get_output_channels ();
2268 uint32_t ichan = get_input_channels ();
2270 if (_have_control) {
2272 if (started_at_least_once) {
2274 /* we can control the backend */
2276 if (backend->requires_driver_selection()) {
2277 if (get_driver() != backend->driver_name()) {
2278 change_driver = true;
2282 if (backend->use_separate_input_and_output_devices()) {
2283 if (get_input_device_name() != backend->input_device_name()) {
2284 change_device = true;
2286 if (get_output_device_name() != backend->output_device_name()) {
2287 change_device = true;
2290 if (get_device_name() != backend->device_name()) {
2291 change_device = true;
2295 if (queue_device_changed) {
2296 change_device = true;
2299 if (get_rate() != backend->sample_rate()) {
2303 if (get_buffer_size() != backend->buffer_size()) {
2304 change_bufsize = true;
2307 if (backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0
2308 && get_nperiods() != backend->period_size()) {
2309 change_nperiods = true;
2312 if (get_midi_option() != backend->midi_option()) {
2316 if (backend->can_use_buffered_io()) {
2317 if (get_use_buffered_io() != backend->get_use_buffered_io()) {
2318 change_buffered_io = true;
2322 /* zero-requested channels means "all available" */
2325 ichan = backend->input_channels();
2329 ochan = backend->output_channels();
2332 if (ichan != backend->input_channels()) {
2333 change_channels = true;
2336 if (ochan != backend->output_channels()) {
2337 change_channels = true;
2340 if (get_input_latency() != backend->systemic_input_latency() ||
2341 get_output_latency() != backend->systemic_output_latency()) {
2342 change_latency = true;
2345 /* backend never started, so we have to force a group
2348 change_device = true;
2349 if (backend->requires_driver_selection()) {
2350 change_driver = true;
2353 change_bufsize = true;
2354 change_channels = true;
2355 change_latency = true;
2357 change_buffered_io = backend->can_use_buffered_io();
2358 change_channels = true;
2359 change_nperiods = backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0;
2364 /* we have no control over the backend, meaning that we can
2365 * only possibly change sample rate and buffer size.
2369 if (get_rate() != backend->sample_rate()) {
2370 change_bufsize = true;
2373 if (get_buffer_size() != backend->buffer_size()) {
2374 change_bufsize = true;
2378 queue_device_changed = false;
2380 if (!_have_control) {
2382 /* We do not have control over the backend, so the best we can
2383 * do is try to change the sample rate and/or bufsize and get
2387 if (change_rate && !backend->can_change_sample_rate_when_running()) {
2391 if (change_bufsize && !backend->can_change_buffer_size_when_running()) {
2396 backend->set_sample_rate (get_rate());
2399 if (change_bufsize) {
2400 backend->set_buffer_size (get_buffer_size());
2404 if (ARDOUR::AudioEngine::instance()->start ()) {
2405 error << string_compose (_("Could not start backend engine %1"), backend->name()) << endmsg;
2415 /* determine if we need to stop the backend before changing parameters */
2417 if (change_driver || change_device || change_channels || change_nperiods ||
2418 (change_latency && !backend->can_change_systemic_latency_when_running ()) ||
2419 (change_rate && !backend->can_change_sample_rate_when_running()) ||
2420 change_midi || change_buffered_io ||
2421 (change_bufsize && !backend->can_change_buffer_size_when_running())) {
2422 restart_required = true;
2424 restart_required = false;
2429 if (restart_required) {
2430 if (ARDOUR::AudioEngine::instance()->stop()) {
2436 if (change_driver && backend->set_driver (get_driver())) {
2437 error << string_compose (_("Cannot set driver to %1"), get_driver()) << endmsg;
2440 if (backend->use_separate_input_and_output_devices()) {
2441 if (change_device && backend->set_input_device_name (get_input_device_name())) {
2442 error << string_compose (_("Cannot set input device name to %1"), get_input_device_name()) << endmsg;
2445 if (change_device && backend->set_output_device_name (get_output_device_name())) {
2446 error << string_compose (_("Cannot set output device name to %1"), get_output_device_name()) << endmsg;
2450 if (change_device && backend->set_device_name (get_device_name())) {
2451 error << string_compose (_("Cannot set device name to %1"), get_device_name()) << endmsg;
2455 if (change_rate && backend->set_sample_rate (get_rate())) {
2456 error << string_compose (_("Cannot set sample rate to %1"), get_rate()) << endmsg;
2459 if (change_bufsize && backend->set_buffer_size (get_buffer_size())) {
2460 error << string_compose (_("Cannot set buffer size to %1"), get_buffer_size()) << endmsg;
2463 if (change_nperiods && backend->set_peridod_size (get_nperiods())) {
2464 error << string_compose (_("Cannot set periods to %1"), get_nperiods()) << endmsg;
2468 if (change_channels || get_input_channels() == 0 || get_output_channels() == 0) {
2469 if (backend->set_input_channels (get_input_channels())) {
2470 error << string_compose (_("Cannot set input channels to %1"), get_input_channels()) << endmsg;
2473 if (backend->set_output_channels (get_output_channels())) {
2474 error << string_compose (_("Cannot set output channels to %1"), get_output_channels()) << endmsg;
2478 if (change_latency) {
2479 if (backend->set_systemic_input_latency (get_input_latency())) {
2480 error << string_compose (_("Cannot set input latency to %1"), get_input_latency()) << endmsg;
2483 if (backend->set_systemic_output_latency (get_output_latency())) {
2484 error << string_compose (_("Cannot set output latency to %1"), get_output_latency()) << endmsg;
2490 backend->set_midi_option (get_midi_option());
2493 if (change_buffered_io) {
2494 backend->set_use_buffered_io (use_buffered_io_button.get_active());
2498 for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
2499 if (_measure_midi) {
2500 if (*p == _measure_midi) {
2501 backend->set_midi_device_enabled ((*p)->name, true);
2503 backend->set_midi_device_enabled ((*p)->name, false);
2505 if (backend->can_change_systemic_latency_when_running ()) {
2506 backend->set_systemic_midi_input_latency ((*p)->name, 0);
2507 backend->set_systemic_midi_output_latency ((*p)->name, 0);
2511 backend->set_midi_device_enabled ((*p)->name, (*p)->enabled);
2512 if (backend->can_set_systemic_midi_latencies()) {
2513 backend->set_systemic_midi_input_latency ((*p)->name, (*p)->input_latency);
2514 backend->set_systemic_midi_output_latency ((*p)->name, (*p)->output_latency);
2519 if (start || (was_running && restart_required)) {
2520 if (ARDOUR::AudioEngine::instance()->start()) {
2531 EngineControl::post_push ()
2533 /* get a pointer to the current state object, creating one if
2537 State state = get_saved_state_for_currently_displayed_backend_and_device ();
2540 state = save_state ();
2546 states.sort (state_sort_cmp);
2550 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
2551 (*i)->active = false;
2554 /* mark this one active (to be used next time the dialog is
2558 state->active = true;
2560 if (_have_control) { // XXX
2561 manage_control_app_sensitivity ();
2564 /* schedule a redisplay of MIDI ports */
2565 //Glib::signal_timeout().connect (sigc::bind_return (sigc::mem_fun (*this, &EngineControl::refresh_midi_display), false), 1000);
2570 EngineControl::get_rate () const
2572 float r = atof (sample_rate_combo.get_active_text ());
2573 /* the string may have been translated with an abbreviation for
2574 * thousands, so use a crude heuristic to fix this.
2584 EngineControl::get_buffer_size () const
2586 string txt = buffer_size_combo.get_active_text ();
2589 if (sscanf (txt.c_str(), "%d", &samples) != 1) {
2590 fprintf(stderr, "Find a trout and repeatedly slap the nearest C++ who throws exceptions without catching them.\n");
2591 fprintf(stderr, "Ardour will likely crash now, giving you time to get the trout.\n");
2599 EngineControl::get_nperiods () const
2601 string txt = nperiods_combo.get_active_text ();
2602 return atoi (txt.c_str());
2606 EngineControl::get_midi_option () const
2608 return midi_option_combo.get_active_text();
2612 EngineControl::get_use_buffered_io () const
2614 return use_buffered_io_button.get_active();
2618 EngineControl::get_input_channels() const
2620 if (ARDOUR::Profile->get_mixbus()) {
2621 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2622 if (!backend) return 0;
2623 return backend->input_channels();
2625 return (uint32_t) input_channels_adjustment.get_value();
2629 EngineControl::get_output_channels() const
2631 if (ARDOUR::Profile->get_mixbus()) {
2632 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2633 if (!backend) return 0;
2634 return backend->input_channels();
2636 return (uint32_t) output_channels_adjustment.get_value();
2640 EngineControl::get_input_latency() const
2642 return (uint32_t) input_latency_adjustment.get_value();
2646 EngineControl::get_output_latency() const
2648 return (uint32_t) output_latency_adjustment.get_value();
2652 EngineControl::get_backend () const
2654 return backend_combo.get_active_text ();
2658 EngineControl::get_driver () const
2660 if (driver_combo.get_parent()) {
2661 return driver_combo.get_active_text ();
2668 EngineControl::get_device_name () const
2670 return device_combo.get_active_text ();
2674 EngineControl::get_input_device_name () const
2676 return input_device_combo.get_active_text ();
2680 EngineControl::get_output_device_name () const
2682 return output_device_combo.get_active_text ();
2686 EngineControl::control_app_button_clicked ()
2688 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2694 backend->launch_control_app ();
2698 EngineControl::start_stop_button_clicked ()
2700 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2706 if (ARDOUR::AudioEngine::instance()->running()) {
2707 ARDOUR::AudioEngine::instance()->stop ();
2709 if (!ARDOUR_UI::instance()->the_session ()) {
2715 if (!ARDOUR_UI::instance()->the_session ()) {
2716 ArdourDialog::on_response (RESPONSE_OK);
2722 EngineControl::update_devices_button_clicked ()
2724 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2730 if (backend->update_devices()) {
2731 device_list_changed ();
2736 EngineControl::use_buffered_io_button_clicked ()
2738 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2744 bool set_buffered_io = !use_buffered_io_button.get_active();
2745 use_buffered_io_button.set_active (set_buffered_io);
2746 backend->set_use_buffered_io (set_buffered_io);
2750 EngineControl::manage_control_app_sensitivity ()
2752 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2758 string appname = backend->control_app_name();
2760 if (appname.empty()) {
2761 control_app_button.set_sensitive (false);
2763 control_app_button.set_sensitive (true);
2768 EngineControl::set_desired_sample_rate (uint32_t sr)
2770 _desired_sample_rate = sr;
2771 if (ARDOUR::AudioEngine::instance ()->running ()
2772 && ARDOUR::AudioEngine::instance ()->sample_rate () != sr) {
2779 EngineControl::on_switch_page (GtkNotebookPage*, guint page_num)
2781 if (page_num == 0) {
2782 _measure_midi.reset();
2783 update_sensitivity ();
2786 if (page_num == midi_tab) {
2788 refresh_midi_display ();
2791 if (page_num == latency_tab) {
2794 if (ARDOUR::AudioEngine::instance()->running()) {
2799 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
2801 /* save any existing latency values */
2803 uint32_t il = (uint32_t) input_latency.get_value ();
2804 uint32_t ol = (uint32_t) input_latency.get_value ();
2806 /* reset to zero so that our new test instance
2807 will be clean of any existing latency measures.
2809 NB. this should really be done by the backend
2810 when stated for latency measurement.
2813 input_latency.set_value (0);
2814 output_latency.set_value (0);
2816 push_state_to_backend (false);
2820 input_latency.set_value (il);
2821 output_latency.set_value (ol);
2824 // This should be done in push_state_to_backend()
2825 if (ARDOUR::AudioEngine::instance()->prepare_for_latency_measurement()) {
2826 disable_latency_tab ();
2829 enable_latency_tab ();
2833 end_latency_detection ();
2834 ARDOUR::AudioEngine::instance()->stop_latency_detection();
2839 /* latency measurement */
2842 EngineControl::check_audio_latency_measurement ()
2844 MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
2846 if (mtdm->resolve () < 0) {
2847 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
2851 if (mtdm->get_peak () > 0.707f) {
2852 // get_peak() resets the peak-hold in the detector.
2853 // this GUI callback is at 10Hz and so will be fine (test-signal is at higher freq)
2854 lm_results.set_markup (string_compose (results_markup, _("Input signal is > -3dBFS. Lower the signal level (output gain, input gain) on the audio-interface.")));
2858 if (mtdm->err () > 0.3) {
2864 ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
2866 if (sample_rate == 0) {
2867 lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
2868 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
2872 int samples_total = mtdm->del();
2873 int extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
2875 snprintf (buf, sizeof (buf), "%s%d samples (%.3lf ms)\n%s%d samples (%.3lf ms)",
2876 _("Detected roundtrip latency: "),
2877 samples_total, samples_total * 1000.0f/sample_rate,
2878 _("Systemic latency: "),
2879 extra, extra * 1000.0f/sample_rate);
2883 if (mtdm->err () > 0.2) {
2885 strcat (buf, _("(signal detection error)"));
2891 strcat (buf, _("(inverted - bad wiring)"));
2895 lm_results.set_markup (string_compose (results_markup, buf));
2898 have_lm_results = true;
2899 end_latency_detection ();
2900 lm_use_button.set_sensitive (true);
2908 EngineControl::check_midi_latency_measurement ()
2910 ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
2912 if (!mididm->have_signal () || mididm->latency () == 0) {
2913 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
2918 ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
2920 if (sample_rate == 0) {
2921 lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
2922 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
2926 ARDOUR::samplecnt_t samples_total = mididm->latency();
2927 ARDOUR::samplecnt_t extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
2928 snprintf (buf, sizeof (buf), "%s%" PRId64" samples (%.1lf ms) dev: %.2f[spl]\n%s%" PRId64" samples (%.1lf ms)",
2929 _("Detected roundtrip latency: "),
2930 samples_total, samples_total * 1000.0f / sample_rate, mididm->deviation (),
2931 _("Systemic latency: "),
2932 extra, extra * 1000.0f / sample_rate);
2936 if (!mididm->ok ()) {
2938 strcat (buf, _("(averaging)"));
2942 if (mididm->deviation () > 50.0) {
2944 strcat (buf, _("(too large jitter)"));
2946 } else if (mididm->deviation () > 10.0) {
2948 strcat (buf, _("(large jitter)"));
2952 have_lm_results = true;
2953 end_latency_detection ();
2954 lm_use_button.set_sensitive (true);
2955 lm_results.set_markup (string_compose (results_markup, buf));
2957 } else if (mididm->processed () > 400) {
2958 have_lm_results = false;
2959 end_latency_detection ();
2960 lm_results.set_markup (string_compose (results_markup, _("Timeout - large MIDI jitter.")));
2964 lm_results.set_markup (string_compose (results_markup, buf));
2970 EngineControl::start_latency_detection ()
2972 ARDOUR::AudioEngine::instance()->set_latency_input_port (lm_input_channel_combo.get_active_text());
2973 ARDOUR::AudioEngine::instance()->set_latency_output_port (lm_output_channel_combo.get_active_text());
2975 if (ARDOUR::AudioEngine::instance()->start_latency_detection (_measure_midi ? true : false) == 0) {
2976 lm_results.set_markup (string_compose (results_markup, _("Detecting ...")));
2977 if (_measure_midi) {
2978 latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_midi_latency_measurement), 100);
2980 latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_audio_latency_measurement), 100);
2982 lm_measure_label.set_text (_("Cancel"));
2983 have_lm_results = false;
2984 lm_use_button.set_sensitive (false);
2985 lm_input_channel_combo.set_sensitive (false);
2986 lm_output_channel_combo.set_sensitive (false);
2992 EngineControl::end_latency_detection ()
2994 latency_timeout.disconnect ();
2995 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
2996 lm_measure_label.set_text (_("Measure"));
2997 if (!have_lm_results) {
2998 lm_use_button.set_sensitive (false);
3000 lm_input_channel_combo.set_sensitive (true);
3001 lm_output_channel_combo.set_sensitive (true);
3006 EngineControl::latency_button_clicked ()
3009 start_latency_detection ();
3011 end_latency_detection ();
3016 EngineControl::latency_back_button_clicked ()
3018 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
3019 notebook.set_current_page(0);
3023 EngineControl::use_latency_button_clicked ()
3025 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3026 if (_measure_midi) {
3027 ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
3031 ARDOUR::samplecnt_t samples_total = mididm->latency();
3032 ARDOUR::samplecnt_t extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
3033 uint32_t one_way = max ((ARDOUR::samplecnt_t) 0, extra / 2);
3034 _measure_midi->input_latency = one_way;
3035 _measure_midi->output_latency = one_way;
3036 if (backend->can_change_systemic_latency_when_running ()) {
3037 backend->set_systemic_midi_input_latency (_measure_midi->name, one_way);
3038 backend->set_systemic_midi_output_latency (_measure_midi->name, one_way);
3040 notebook.set_current_page (midi_tab);
3042 MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
3048 double one_way = rint ((mtdm->del() - ARDOUR::AudioEngine::instance()->latency_signal_delay()) / 2.0);
3049 one_way = std::max (0., one_way);
3051 input_latency_adjustment.set_value (one_way);
3052 output_latency_adjustment.set_value (one_way);
3053 if (backend->can_change_systemic_latency_when_running ()) {
3054 backend->set_systemic_input_latency (one_way);
3055 backend->set_systemic_output_latency (one_way);
3058 /* back to settings page */
3059 notebook.set_current_page (0);
3064 EngineControl::on_delete_event (GdkEventAny* ev)
3066 if (notebook.get_current_page() == 2) {
3067 /* currently on latency tab - be sure to clean up */
3068 end_latency_detection ();
3070 return ArdourDialog::on_delete_event (ev);
3074 EngineControl::engine_running ()
3076 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3079 set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
3080 sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
3082 if (backend->can_set_period_size ()) {
3083 set_active_text_if_present (nperiods_combo, to_string (backend->period_size()));
3086 connect_disconnect_button.set_label (string_compose (_("Disconnect from %1"), backend->name()));
3087 connect_disconnect_button.show();
3089 started_at_least_once = true;
3090 if (_have_control) {
3091 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Running")));
3093 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Connected")));
3095 update_sensitivity();
3099 EngineControl::engine_stopped ()
3101 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3104 connect_disconnect_button.set_label (string_compose (_("Connect to %1"), backend->name()));
3105 connect_disconnect_button.show();
3107 if (_have_control) {
3108 engine_status.set_markup(string_compose ("<span foreground=\"red\">%1</span>", _("Stopped")));
3110 engine_status.set_markup(X_(""));
3113 update_sensitivity();
3117 EngineControl::device_list_changed ()
3119 if (ignore_device_changes) {
3122 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1); // ??
3123 if (!ARDOUR::AudioEngine::instance()->running()) {
3127 midi_option_changed();
3129 if (notebook.get_current_page() == midi_tab) {
3130 if (_midi_devices.empty ()) {
3131 notebook.set_current_page (0);
3133 refresh_midi_display ();
3139 EngineControl::connect_disconnect_click()
3141 if (ARDOUR::AudioEngine::instance()->running()) {
3144 if (!ARDOUR_UI::instance()->the_session ()) {
3150 if (!ARDOUR_UI::instance()->the_session ()) {
3151 ArdourDialog::on_response (RESPONSE_OK);
3157 EngineControl::calibrate_audio_latency ()
3159 _measure_midi.reset ();
3160 have_lm_results = false;
3161 lm_use_button.set_sensitive (false);
3162 lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
3163 notebook.set_current_page (latency_tab);
3167 EngineControl::calibrate_midi_latency (MidiDeviceSettings s)
3170 have_lm_results = false;
3171 lm_use_button.set_sensitive (false);
3172 lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
3173 notebook.set_current_page (latency_tab);
3177 EngineControl::configure_midi_devices ()
3179 notebook.set_current_page (midi_tab);