2 * Copyright (C) 2007-2012 Carl Hetherington <carl@carlh.net>
3 * Copyright (C) 2007-2017 Paul Davis <paul@linuxaudiosystems.com>
4 * Copyright (C) 2008-2012 David Robillard <d@drobilla.net>
5 * Copyright (C) 2013-2014 Colin Fletcher <colin.m.fletcher@googlemail.com>
6 * Copyright (C) 2013-2019 Robin Gareus <robin@gareus.org>
7 * Copyright (C) 2015-2016 Tim Mayberry <mojofunk@gmail.com>
8 * Copyright (C) 2015 Ben Loftis <ben@harrisonconsoles.com>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include <boost/scoped_ptr.hpp>
32 #include <gtkmm/messagedialog.h>
34 #include "pbd/error.h"
35 #include "pbd/locale_guard.h"
36 #include "pbd/xml++.h"
37 #include "pbd/unwind.h"
38 #include "pbd/failed_constructor.h"
40 #include <gtkmm/alignment.h>
41 #include <gtkmm/stock.h>
42 #include <gtkmm/notebook.h>
43 #include <gtkmm2ext/utils.h>
45 #include "ardour/audio_backend.h"
46 #include "ardour/audioengine.h"
47 #include "ardour/mtdm.h"
48 #include "ardour/mididm.h"
49 #include "ardour/rc_configuration.h"
50 #include "ardour/types.h"
51 #include "ardour/profile.h"
53 #include "pbd/convert.h"
54 #include "pbd/error.h"
58 #include "ardour_ui.h"
59 #include "engine_dialog.h"
60 #include "gui_thread.h"
61 #include "ui_config.h"
62 #include "public_editor.h"
69 using namespace Gtkmm2ext;
72 using namespace ArdourWidgets;
73 using namespace ARDOUR_UI_UTILS;
75 #define DEBUG_ECONTROL(msg) DEBUG_TRACE (PBD::DEBUG::EngineControl, string_compose ("%1: %2\n", __LINE__, msg));
77 static const unsigned int midi_tab = 2;
78 static const unsigned int latency_tab = 1; /* zero-based, page zero is the main setup page */
80 static const char* results_markup = X_("<span weight=\"bold\" size=\"larger\">%1</span>");
82 EngineControl::EngineControl ()
83 : ArdourDialog (_("Audio/MIDI Setup"))
86 , input_latency_adjustment (0, 0, 99999, 1)
87 , input_latency (input_latency_adjustment)
88 , output_latency_adjustment (0, 0, 99999, 1)
89 , output_latency (output_latency_adjustment)
90 , input_channels_adjustment (0, 0, 256, 1)
91 , input_channels (input_channels_adjustment)
92 , output_channels_adjustment (0, 0, 256, 1)
93 , output_channels (output_channels_adjustment)
94 , ports_adjustment (128, 8, 1024, 1, 16)
95 , ports_spinner (ports_adjustment)
96 , control_app_button (_("Device Control Panel"))
97 , midi_devices_button (_("Midi Device Setup"))
98 , start_stop_button (_("Stop"))
99 , update_devices_button (_("Refresh Devices"))
100 , use_buffered_io_button (_("Use Buffered I/O"), ArdourButton::led_default_elements)
101 , lm_measure_label (_("Measure"))
102 , lm_use_button (_("Use results"))
103 , lm_back_button (_("Back to settings ... (ignore results)"))
104 , lm_button_audio (_("Calibrate Audio"))
106 , have_lm_results (false)
108 , midi_back_button (_("Back to settings"))
110 , ignore_device_changes (0)
111 , _desired_sample_rate (0)
112 , started_at_least_once (false)
113 , queue_device_changed (false)
114 , _have_control (true)
117 using namespace Notebook_Helpers;
118 vector<string> backend_names;
120 AttachOptions xopt = AttachOptions (FILL|EXPAND);
123 set_name (X_("AudioMIDISetup"));
125 /* the backend combo is the one thing that is ALWAYS visible */
127 vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
129 if (backends.empty()) {
130 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));
132 throw failed_constructor ();
135 for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
136 backend_names.push_back ((*b)->name);
139 set_popdown_strings (backend_combo, backend_names);
141 /* setup basic packing characteristics for the table used on the main
142 * tab of the notebook
145 basic_packer.set_spacings (6);
146 basic_packer.set_border_width (12);
147 basic_packer.set_homogeneous (false);
151 basic_hbox.pack_start (basic_packer, false, false);
153 /* latency measurement tab */
155 lm_title.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Latency Measurement Tool")));
158 lm_table.set_row_spacings (12);
159 lm_table.set_col_spacings (6);
160 lm_table.set_homogeneous (false);
162 lm_table.attach (lm_title, 0, 3, row, row+1, xopt, (AttachOptions) 0);
165 lm_preamble.set_width_chars (60);
166 lm_preamble.set_line_wrap (true);
167 lm_preamble.set_markup (_("<span weight=\"bold\">Turn down the volume on your audio equipment to a very low level.</span>"));
169 lm_table.attach (lm_preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
172 Gtk::Label* preamble;
173 preamble = manage (new Label);
174 preamble->set_width_chars (60);
175 preamble->set_line_wrap (true);
176 preamble->set_markup (_("Select two channels below and connect them using a cable."));
178 lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
181 label = manage (new Label (_("Output channel:")));
182 lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
184 lm_output_channel_list = Gtk::ListStore::create (lm_output_channel_cols);
185 lm_output_channel_combo.set_model (lm_output_channel_list);
186 lm_output_channel_combo.pack_start (lm_output_channel_cols.pretty_name);
188 Gtk::Alignment* misc_align = manage (new Alignment (0.0, 0.5));
189 misc_align->add (lm_output_channel_combo);
190 lm_table.attach (*misc_align, 1, 3, row, row+1, xopt, (AttachOptions) 0);
193 label = manage (new Label (_("Input channel:")));
194 lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
196 lm_input_channel_list = Gtk::ListStore::create (lm_input_channel_cols);
197 lm_input_channel_combo.set_model (lm_input_channel_list);
198 lm_input_channel_combo.pack_start (lm_input_channel_cols.pretty_name);
200 misc_align = manage (new Alignment (0.0, 0.5));
201 misc_align->add (lm_input_channel_combo);
202 lm_table.attach (*misc_align, 1, 3, row, row+1, FILL, (AttachOptions) 0);
205 lm_measure_label.set_padding (10, 10);
206 lm_measure_button.add (lm_measure_label);
207 lm_measure_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::latency_button_clicked));
208 lm_use_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::use_latency_button_clicked));
209 lm_back_button_signal = lm_back_button.signal_clicked().connect(
210 sigc::mem_fun(*this, &EngineControl::latency_back_button_clicked));
212 lm_use_button.set_sensitive (false);
214 /* Increase the default spacing around the labels of these three
220 if ((l = dynamic_cast<Gtk::Misc*>(lm_use_button.get_child())) != 0) {
221 l->set_padding (10, 10);
224 if ((l = dynamic_cast<Gtk::Misc*>(lm_back_button.get_child())) != 0) {
225 l->set_padding (10, 10);
228 preamble = manage (new Label);
229 preamble->set_width_chars (60);
230 preamble->set_line_wrap (true);
231 preamble->set_markup (_("Once the channels are connected, click the \"Measure\" button."));
232 lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
235 preamble = manage (new Label);
236 preamble->set_width_chars (60);
237 preamble->set_line_wrap (true);
238 preamble->set_markup (_("When satisfied with the results, click the \"Use results\" button."));
239 lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
241 ++row; // skip a row in the table
242 ++row; // skip a row in the table
244 lm_table.attach (lm_results, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
246 ++row; // skip a row in the table
247 ++row; // skip a row in the table
249 lm_table.attach (lm_measure_button, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
250 lm_table.attach (lm_use_button, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
251 lm_table.attach (lm_back_button, 2, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
253 lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
255 lm_vbox.set_border_width (12);
256 lm_vbox.pack_start (lm_table, false, false);
258 midi_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
262 notebook.pages().push_back (TabElem (basic_vbox, _("Audio")));
263 notebook.pages().push_back (TabElem (lm_vbox, _("Latency")));
264 notebook.pages().push_back (TabElem (midi_vbox, _("MIDI")));
265 notebook.set_border_width (12);
267 notebook.set_show_tabs (false);
268 notebook.show_all ();
270 notebook.set_name ("SettingsNotebook");
272 /* packup the notebook */
274 get_vbox()->set_border_width (12);
275 get_vbox()->pack_start (notebook);
277 /* need a special function to print "all available channels" when the
278 * channel counts hit zero.
281 input_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &input_channels));
282 output_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &output_channels));
284 midi_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::configure_midi_devices));
285 midi_devices_button.set_name ("generic button");
286 midi_devices_button.set_can_focus(true);
288 control_app_button.signal_clicked.connect (mem_fun (*this, &EngineControl::control_app_button_clicked));
289 control_app_button.set_name ("generic button");
290 control_app_button.set_can_focus(true);
291 manage_control_app_sensitivity ();
293 start_stop_button.signal_clicked.connect (mem_fun (*this, &EngineControl::start_stop_button_clicked));
294 start_stop_button.set_sensitive (false);
295 start_stop_button.set_name ("generic button");
296 start_stop_button.set_can_focus(true);
297 start_stop_button.set_can_default(true);
298 start_stop_button.set_act_on_release (false);
300 update_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::update_devices_button_clicked));
301 update_devices_button.set_sensitive (false);
302 update_devices_button.set_name ("generic button");
303 update_devices_button.set_can_focus(true);
305 use_buffered_io_button.signal_clicked.connect (mem_fun (*this, &EngineControl::use_buffered_io_button_clicked));
306 use_buffered_io_button.set_sensitive (false);
307 use_buffered_io_button.set_name ("generic button");
308 use_buffered_io_button.set_can_focus(true);
310 /* Pick up any existing audio setup configuration, if appropriate */
312 XMLNode* audio_setup = ARDOUR::Config->extra_xml ("AudioMIDISetup");
314 ARDOUR::AudioEngine::instance()->Running.connect (running_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_running, this), gui_context());
315 ARDOUR::AudioEngine::instance()->Stopped.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
316 ARDOUR::AudioEngine::instance()->Halted.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
317 ARDOUR::AudioEngine::instance()->DeviceListChanged.connect (devicelist_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::device_list_changed, this), gui_context());
320 if (!set_state (*audio_setup)) {
321 set_default_state ();
324 set_default_state ();
327 update_sensitivity ();
328 connect_changed_signals ();
330 notebook.signal_switch_page().connect (sigc::mem_fun (*this, &EngineControl::on_switch_page));
332 connect_disconnect_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::connect_disconnect_click));
334 connect_disconnect_button.set_no_show_all();
335 use_buffered_io_button.set_no_show_all();
336 update_devices_button.set_no_show_all();
337 start_stop_button.set_no_show_all();
338 midi_devices_button.set_no_show_all();
342 EngineControl::connect_changed_signals ()
344 backend_combo_connection = backend_combo.signal_changed ().connect (
345 sigc::mem_fun (*this, &EngineControl::backend_changed));
346 driver_combo_connection = driver_combo.signal_changed ().connect (
347 sigc::mem_fun (*this, &EngineControl::driver_changed));
348 sample_rate_combo_connection = sample_rate_combo.signal_changed ().connect (
349 sigc::mem_fun (*this, &EngineControl::sample_rate_changed));
350 buffer_size_combo_connection = buffer_size_combo.signal_changed ().connect (
351 sigc::mem_fun (*this, &EngineControl::buffer_size_changed));
352 nperiods_combo_connection = nperiods_combo.signal_changed ().connect (
353 sigc::mem_fun (*this, &EngineControl::nperiods_changed));
354 device_combo_connection = device_combo.signal_changed ().connect (
355 sigc::mem_fun (*this, &EngineControl::device_changed));
356 midi_option_combo_connection = midi_option_combo.signal_changed ().connect (
357 sigc::mem_fun (*this, &EngineControl::midi_option_changed));
359 input_device_combo_connection = input_device_combo.signal_changed ().connect (
360 sigc::mem_fun (*this, &EngineControl::input_device_changed));
361 output_device_combo_connection = output_device_combo.signal_changed ().connect (
362 sigc::mem_fun (*this, &EngineControl::output_device_changed));
364 input_latency_connection = input_latency.signal_changed ().connect (
365 sigc::mem_fun (*this, &EngineControl::parameter_changed));
366 output_latency_connection = output_latency.signal_changed ().connect (
367 sigc::mem_fun (*this, &EngineControl::parameter_changed));
368 input_channels_connection = input_channels.signal_changed ().connect (
369 sigc::mem_fun (*this, &EngineControl::parameter_changed));
370 output_channels_connection = output_channels.signal_changed ().connect (
371 sigc::mem_fun (*this, &EngineControl::parameter_changed));
375 EngineControl::block_changed_signals ()
377 if (block_signals++ == 0) {
378 DEBUG_ECONTROL ("Blocking changed signals");
379 backend_combo_connection.block ();
380 driver_combo_connection.block ();
381 sample_rate_combo_connection.block ();
382 buffer_size_combo_connection.block ();
383 nperiods_combo_connection.block ();
384 device_combo_connection.block ();
385 input_device_combo_connection.block ();
386 output_device_combo_connection.block ();
387 midi_option_combo_connection.block ();
388 input_latency_connection.block ();
389 output_latency_connection.block ();
390 input_channels_connection.block ();
391 output_channels_connection.block ();
396 EngineControl::unblock_changed_signals ()
398 if (--block_signals == 0) {
399 DEBUG_ECONTROL ("Unblocking changed signals");
400 backend_combo_connection.unblock ();
401 driver_combo_connection.unblock ();
402 sample_rate_combo_connection.unblock ();
403 buffer_size_combo_connection.unblock ();
404 nperiods_combo_connection.unblock ();
405 device_combo_connection.unblock ();
406 input_device_combo_connection.unblock ();
407 output_device_combo_connection.unblock ();
408 midi_option_combo_connection.unblock ();
409 input_latency_connection.unblock ();
410 output_latency_connection.unblock ();
411 input_channels_connection.unblock ();
412 output_channels_connection.unblock ();
416 EngineControl::SignalBlocker::SignalBlocker (EngineControl& engine_control,
417 const std::string& reason)
418 : ec (engine_control)
421 DEBUG_ECONTROL (string_compose ("SignalBlocker: %1", m_reason));
422 ec.block_changed_signals ();
425 EngineControl::SignalBlocker::~SignalBlocker ()
427 DEBUG_ECONTROL (string_compose ("~SignalBlocker: %1", m_reason));
428 ec.unblock_changed_signals ();
432 EngineControl::on_show ()
434 ArdourDialog::on_show ();
435 if (!ARDOUR::AudioEngine::instance()->current_backend() || !ARDOUR::AudioEngine::instance()->running()) {
436 // re-check _have_control (jackd running) see #6041
440 start_stop_button.grab_focus();
444 EngineControl::on_map ()
446 if (!ARDOUR_UI::instance()->the_session () && !PublicEditor::_instance) {
447 set_type_hint (Gdk::WINDOW_TYPE_HINT_NORMAL);
448 } else if (UIConfiguration::instance().get_all_floating_windows_are_dialogs()) {
449 set_type_hint (Gdk::WINDOW_TYPE_HINT_DIALOG);
451 set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
453 ArdourDialog::on_map ();
457 EngineControl::try_autostart ()
459 if (!start_stop_button.get_sensitive()) {
462 if (ARDOUR::AudioEngine::instance()->running()) {
465 return start_engine ();
469 EngineControl::start_engine ()
471 if (push_state_to_backend(true) != 0) {
472 MessageDialog msg(*this,
473 ARDOUR::AudioEngine::instance()->get_last_backend_error());
481 EngineControl::stop_engine (bool for_latency)
483 if (ARDOUR::AudioEngine::instance()->stop(for_latency)) {
484 MessageDialog msg(*this,
485 ARDOUR::AudioEngine::instance()->get_last_backend_error());
493 EngineControl::build_notebook ()
496 AttachOptions xopt = AttachOptions (FILL|EXPAND);
498 /* clear the table */
500 Gtkmm2ext::container_clear (basic_vbox);
501 Gtkmm2ext::container_clear (basic_packer);
503 if (control_app_button.get_parent()) {
504 control_app_button.get_parent()->remove (control_app_button);
507 label = manage (left_aligned_label (_("Audio System:")));
508 basic_packer.attach (*label, 0, 1, 0, 1, xopt, (AttachOptions) 0);
509 basic_packer.attach (backend_combo, 1, 2, 0, 1, xopt, (AttachOptions) 0);
511 basic_packer.attach (engine_status, 2, 3, 0, 1, xopt, (AttachOptions) 0);
512 engine_status.show();
514 basic_packer.attach (start_stop_button, 3, 4, 0, 1, xopt, xopt);
515 basic_packer.attach (update_devices_button, 3, 4, 1, 2, xopt, xopt);
516 basic_packer.attach (use_buffered_io_button, 3, 4, 2, 3, xopt, xopt);
518 lm_button_audio.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_audio_latency));
519 lm_button_audio.set_name ("generic button");
520 lm_button_audio.set_can_focus(true);
523 build_full_control_notebook ();
525 build_no_control_notebook ();
528 basic_vbox.pack_start (basic_hbox, false, false);
531 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
532 basic_vbox.show_all ();
537 EngineControl::build_full_control_notebook ()
539 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
542 using namespace Notebook_Helpers;
544 vector<string> strings;
545 AttachOptions xopt = AttachOptions (FILL|EXPAND);
546 int row = 1; // row zero == backend combo
548 /* start packing it up */
550 if (backend->requires_driver_selection()) {
551 label = manage (left_aligned_label (_("Driver:")));
552 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
553 basic_packer.attach (driver_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
557 if (backend->use_separate_input_and_output_devices()) {
558 label = manage (left_aligned_label (_("Input Device:")));
559 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
560 basic_packer.attach (input_device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
562 label = manage (left_aligned_label (_("Output Device:")));
563 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
564 basic_packer.attach (output_device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
566 // reset so it isn't used in state comparisons
567 device_combo.set_active_text ("");
569 label = manage (left_aligned_label (_("Device:")));
570 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
571 basic_packer.attach (device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
573 // reset these so they don't get used in state comparisons
574 input_device_combo.set_active_text ("");
575 output_device_combo.set_active_text ("");
578 label = manage (left_aligned_label (_("Sample rate:")));
579 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
580 basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
584 label = manage (left_aligned_label (_("Buffer size:")));
585 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
586 basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
587 buffer_size_duration_label.set_alignment (0.0); /* left-align */
588 basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
590 int ctrl_btn_span = 1;
591 if (backend->can_set_period_size ()) {
593 label = manage (left_aligned_label (_("Periods:")));
594 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
595 basic_packer.attach (nperiods_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
599 /* button spans 2 or 3 rows */
601 basic_packer.attach (control_app_button, 3, 4, row - ctrl_btn_span, row + 1, xopt, xopt);
604 input_channels.set_name ("InputChannels");
605 input_channels.set_flags (Gtk::CAN_FOCUS);
606 input_channels.set_digits (0);
607 input_channels.set_wrap (false);
608 output_channels.set_editable (true);
610 if (!ARDOUR::Profile->get_mixbus()) {
611 label = manage (left_aligned_label (_("Input channels:")));
612 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
613 basic_packer.attach (input_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
617 output_channels.set_name ("OutputChannels");
618 output_channels.set_flags (Gtk::CAN_FOCUS);
619 output_channels.set_digits (0);
620 output_channels.set_wrap (false);
621 output_channels.set_editable (true);
623 if (!ARDOUR::Profile->get_mixbus()) {
624 label = manage (left_aligned_label (_("Output channels:")));
625 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
626 basic_packer.attach (output_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
630 input_latency.set_name ("InputLatency");
631 input_latency.set_flags (Gtk::CAN_FOCUS);
632 input_latency.set_digits (0);
633 input_latency.set_wrap (false);
634 input_latency.set_editable (true);
636 label = manage (left_aligned_label (_("Hardware input latency:")));
637 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
638 basic_packer.attach (input_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);
643 output_latency.set_name ("OutputLatency");
644 output_latency.set_flags (Gtk::CAN_FOCUS);
645 output_latency.set_digits (0);
646 output_latency.set_wrap (false);
647 output_latency.set_editable (true);
649 label = manage (left_aligned_label (_("Hardware output latency:")));
650 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
651 basic_packer.attach (output_latency, 1, 2, row, row+1, xopt, (AttachOptions) 0);
652 label = manage (left_aligned_label (_("samples")));
653 basic_packer.attach (*label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
655 /* button spans 2 rows */
657 basic_packer.attach (lm_button_audio, 3, 4, row-1, row+1, xopt, xopt);
660 label = manage (left_aligned_label (_("MIDI System:")));
661 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
662 basic_packer.attach (midi_option_combo, 1, 2, row, row + 1, SHRINK, (AttachOptions) 0);
663 basic_packer.attach (midi_devices_button, 3, 4, row, row+1, xopt, xopt);
668 EngineControl::build_no_control_notebook ()
670 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
673 using namespace Notebook_Helpers;
675 vector<string> strings;
676 AttachOptions xopt = AttachOptions (FILL|EXPAND);
677 int row = 1; // row zero == backend combo
678 const string msg = string_compose (_("%1 is already running. %2 will connect to it and use the existing settings."), backend->name(), PROGRAM_NAME);
680 label = manage (new Label);
681 label->set_markup (string_compose ("<span weight=\"bold\" foreground=\"red\">%1</span>", msg));
682 basic_packer.attach (*label, 0, 2, row, row + 1, xopt, (AttachOptions) 0);
685 if (backend->can_change_sample_rate_when_running()) {
686 label = manage (left_aligned_label (_("Sample rate:")));
687 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
688 basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
692 if (backend->can_change_buffer_size_when_running()) {
693 label = manage (left_aligned_label (_("Buffer size:")));
694 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
695 basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
696 buffer_size_duration_label.set_alignment (0.0); /* left-align */
697 basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, xopt, (AttachOptions) 0);
701 basic_packer.attach (connect_disconnect_button, 0, 2, row, row+1, FILL, AttachOptions (0));
705 EngineControl::~EngineControl ()
707 ignore_changes = true;
711 EngineControl::disable_latency_tab ()
713 lm_input_channel_list->clear ();
714 lm_output_channel_list->clear ();
715 lm_measure_button.set_sensitive (false);
716 lm_use_button.set_sensitive (false);
720 EngineControl::enable_latency_tab ()
722 vector<string> outputs;
723 vector<string> inputs;
725 ARDOUR::DataType const type = _measure_midi ? ARDOUR::DataType::MIDI : ARDOUR::DataType::AUDIO;
726 ARDOUR::AudioEngine::instance()->get_physical_outputs (type, outputs);
727 ARDOUR::AudioEngine::instance()->get_physical_inputs (type, inputs);
729 if (!ARDOUR::AudioEngine::instance()->running()) {
730 MessageDialog msg (_("Failed to start or connect to audio-engine.\n\nLatency calibration requires a working audio interface."));
731 notebook.set_current_page (0);
735 else if (inputs.empty() || outputs.empty()) {
736 MessageDialog msg (_("Your selected audio configuration is playback- or capture-only.\n\nLatency calibration requires playback and capture"));
737 notebook.set_current_page (0);
742 lm_back_button_signal.disconnect();
744 lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), midi_tab));
747 lm_back_button_signal = lm_back_button.signal_clicked().connect(
748 sigc::mem_fun(*this, &EngineControl::latency_back_button_clicked));
752 lm_output_channel_list->clear ();
753 for (vector<string>::const_iterator i = outputs.begin(); i != outputs.end(); ++i) {
754 Gtk::TreeModel::iterator iter = lm_output_channel_list->append ();
755 Gtk::TreeModel::Row row = *iter;
756 row[lm_output_channel_cols.port_name] = *i;
757 row[lm_output_channel_cols.pretty_name] = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*i);
759 lm_output_channel_combo.set_active (0);
760 lm_output_channel_combo.set_sensitive (true);
762 lm_input_channel_list->clear ();
763 for (vector<string>::const_iterator i = inputs.begin(); i != inputs.end(); ++i) {
764 Gtk::TreeModel::iterator iter = lm_input_channel_list->append ();
765 Gtk::TreeModel::Row row = *iter;
766 row[lm_input_channel_cols.port_name] = *i;
767 row[lm_input_channel_cols.pretty_name] = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*i);
769 lm_input_channel_combo.set_active (0);
770 lm_input_channel_combo.set_sensitive (true);
772 lm_measure_button.set_sensitive (true);
776 EngineControl::setup_midi_tab_for_backend ()
778 string backend = backend_combo.get_active_text ();
780 Gtkmm2ext::container_clear (midi_vbox);
782 midi_vbox.set_border_width (12);
783 midi_device_table.set_border_width (12);
785 if (backend == "JACK") {
786 setup_midi_tab_for_jack ();
789 midi_vbox.pack_start (midi_device_table, true, true);
790 midi_vbox.pack_start (midi_back_button, false, false);
791 midi_vbox.show_all ();
795 EngineControl::update_sensitivity ()
797 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
799 start_stop_button.set_sensitive (false);
804 size_t devices_available = 0;
805 bool engine_running = ARDOUR::AudioEngine::instance()->running();
807 if (backend->use_separate_input_and_output_devices ()) {
808 devices_available += get_popdown_string_count (input_device_combo);
809 devices_available += get_popdown_string_count (output_device_combo);
811 devices_available += get_popdown_string_count (device_combo);
814 if (devices_available == 0) {
816 input_latency.set_sensitive (false);
817 output_latency.set_sensitive (false);
818 input_channels.set_sensitive (false);
819 output_channels.set_sensitive (false);
821 input_latency.set_sensitive (true);
822 output_latency.set_sensitive (true);
823 input_channels.set_sensitive (!engine_running);
824 output_channels.set_sensitive (!engine_running);
827 if (get_popdown_string_count (buffer_size_combo) > 0) {
828 if (!engine_running) {
829 buffer_size_combo.set_sensitive (valid);
830 } else if (backend->can_change_buffer_size_when_running ()) {
831 buffer_size_combo.set_sensitive (valid || !_have_control);
833 buffer_size_combo.set_sensitive (false);
836 buffer_size_combo.set_sensitive (false);
840 if (get_popdown_string_count (sample_rate_combo) > 0) {
841 bool allow_to_set_rate = false;
842 if (!engine_running) {
843 if (!ARDOUR_UI::instance()->the_session ()) {
844 // engine is not running, no session loaded -> anything goes.
845 allow_to_set_rate = true;
846 } else if (_desired_sample_rate > 0 && get_rate () != _desired_sample_rate) {
847 // only allow to change if the current setting is not the native session rate.
848 allow_to_set_rate = true;
851 sample_rate_combo.set_sensitive (allow_to_set_rate);
853 sample_rate_combo.set_sensitive (false);
857 if (get_popdown_string_count (nperiods_combo) > 0) {
858 if (!engine_running) {
859 nperiods_combo.set_sensitive (true);
861 nperiods_combo.set_sensitive (false);
864 nperiods_combo.set_sensitive (false);
868 start_stop_button.set_sensitive(true);
869 start_stop_button.show();
870 if (engine_running) {
871 start_stop_button.set_text("Stop");
872 update_devices_button.set_sensitive(false);
873 use_buffered_io_button.set_sensitive(false);
875 if (backend->can_request_update_devices()) {
876 update_devices_button.show();
878 update_devices_button.hide();
880 if (backend->can_use_buffered_io()) {
881 use_buffered_io_button.show();
883 use_buffered_io_button.hide();
885 start_stop_button.set_text("Start");
886 update_devices_button.set_sensitive(true);
887 use_buffered_io_button.set_sensitive(true);
890 update_devices_button.set_sensitive(false);
891 update_devices_button.hide();
892 use_buffered_io_button.set_sensitive(false);
893 use_buffered_io_button.hide();
894 start_stop_button.set_sensitive(false);
895 start_stop_button.hide();
898 if (engine_running && _have_control) {
899 input_device_combo.set_sensitive (false);
900 output_device_combo.set_sensitive (false);
901 device_combo.set_sensitive (false);
902 driver_combo.set_sensitive (false);
904 input_device_combo.set_sensitive (true);
905 output_device_combo.set_sensitive (true);
906 device_combo.set_sensitive (true);
907 if (backend->requires_driver_selection() && get_popdown_string_count(driver_combo) > 0) {
908 driver_combo.set_sensitive (true);
910 driver_combo.set_sensitive (false);
914 midi_option_combo.set_sensitive (!engine_running);
918 EngineControl::setup_midi_tab_for_jack ()
923 EngineControl::midi_latency_adjustment_changed (Gtk::Adjustment *a, MidiDeviceSettings device, bool for_input) {
925 device->input_latency = a->get_value();
927 device->output_latency = a->get_value();
930 if (ARDOUR::AudioEngine::instance()->running() && !_measure_midi) {
931 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
933 if (backend->can_change_systemic_latency_when_running () && device->enabled) {
935 backend->set_systemic_midi_input_latency (device->name, device->input_latency);
937 backend->set_systemic_midi_output_latency (device->name, device->output_latency);
944 EngineControl::midi_device_enabled_toggled (ArdourButton *b, MidiDeviceSettings device) {
945 b->set_active (!b->get_active());
946 device->enabled = b->get_active();
947 refresh_midi_display(device->name);
949 if (ARDOUR::AudioEngine::instance()->running()) {
950 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
952 backend->set_midi_device_enabled (device->name, device->enabled);
953 if (backend->can_change_systemic_latency_when_running () && device->enabled) {
954 backend->set_systemic_midi_input_latency (device->name, device->input_latency);
955 backend->set_systemic_midi_output_latency (device->name, device->output_latency);
961 EngineControl::refresh_midi_display (std::string focus)
963 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
967 AttachOptions xopt = AttachOptions (FILL|EXPAND);
970 Gtkmm2ext::container_clear (midi_device_table);
972 midi_device_table.set_spacings (6);
974 l = manage (new Label);
975 l->set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Devices")));
976 midi_device_table.attach (*l, 0, 4, row, row + 1, xopt, AttachOptions (0));
977 l->set_alignment (0.5, 0.5);
981 l = manage (new Label (_("Device"))); l->show (); l->set_alignment (0.5, 0.5);
982 midi_device_table.attach (*l, 0, 1, row, row + 2, xopt, AttachOptions (0));
983 l = manage (new Label (_("Systemic Latency [samples]"))); l->show (); l->set_alignment (0.5, 0.5);
984 midi_device_table.attach (*l, 1, 3, row, row + 1, xopt, AttachOptions (0));
986 l = manage (new Label (_("Input"))); l->show (); l->set_alignment (0.5, 0.5);
987 midi_device_table.attach (*l, 1, 2, row, row + 1, xopt, AttachOptions (0));
988 l = manage (new Label (_("Output"))); l->show (); l->set_alignment (0.5, 0.5);
989 midi_device_table.attach (*l, 2, 3, row, row + 1, xopt, AttachOptions (0));
992 for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
997 bool enabled = (*p)->enabled;
999 m = manage (new ArdourButton ((*p)->name, ArdourButton::led_default_elements));
1000 m->set_name ("midi device");
1001 m->set_can_focus (Gtk::CAN_FOCUS);
1002 m->add_events (Gdk::BUTTON_RELEASE_MASK);
1003 m->set_active (enabled);
1004 m->signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_device_enabled_toggled), m, *p));
1005 midi_device_table.attach (*m, 0, 1, row, row + 1, xopt, AttachOptions (0)); m->show ();
1006 if ((*p)->name == focus) {
1010 a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
1011 s = manage (new Gtk::SpinButton (*a));
1012 a->set_value ((*p)->input_latency);
1013 s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, true));
1014 s->set_sensitive (_can_set_midi_latencies && enabled);
1015 midi_device_table.attach (*s, 1, 2, row, row + 1, xopt, AttachOptions (0)); s->show ();
1017 a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
1018 s = manage (new Gtk::SpinButton (*a));
1019 a->set_value ((*p)->output_latency);
1020 s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, false));
1021 s->set_sensitive (_can_set_midi_latencies && enabled);
1022 midi_device_table.attach (*s, 2, 3, row, row + 1, xopt, AttachOptions (0)); s->show ();
1024 b = manage (new Button (_("Calibrate")));
1025 b->signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::calibrate_midi_latency), *p));
1026 b->set_sensitive (_can_set_midi_latencies && enabled);
1027 midi_device_table.attach (*b, 3, 4, row, row + 1, xopt, AttachOptions (0)); b->show ();
1034 EngineControl::backend_changed ()
1036 SignalBlocker blocker (*this, "backend_changed");
1037 string backend_name = backend_combo.get_active_text();
1038 boost::shared_ptr<ARDOUR::AudioBackend> backend;
1040 if (!(backend = ARDOUR::AudioEngine::instance()->set_backend (backend_name, downcase (std::string(PROGRAM_NAME)), ""))) {
1041 /* eh? setting the backend failed... how ? */
1042 /* A: stale config contains a backend that does not exist in current build */
1046 DEBUG_ECONTROL (string_compose ("Backend name: %1", backend_name));
1048 _have_control = ARDOUR::AudioEngine::instance()->setup_required ();
1051 setup_midi_tab_for_backend ();
1052 _midi_devices.clear();
1054 if (backend->requires_driver_selection()) {
1055 if (set_driver_popdown_strings ()) {
1059 /* this will change the device text which will cause a call to
1060 * device changed which will set up parameters
1065 update_midi_options ();
1067 connect_disconnect_button.hide();
1069 midi_option_changed();
1071 started_at_least_once = false;
1073 /* changing the backend implies stopping the engine
1074 * ARDOUR::AudioEngine() may or may not emit this signal
1075 * depending on previous engine state
1077 engine_stopped (); // set "active/inactive"
1079 if (!_have_control) {
1080 // set settings from backend that we do have control over
1081 set_buffersize_popdown_strings ();
1082 set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
1085 if (_have_control && !ignore_changes) {
1086 // set driver & devices
1087 State state = get_matching_state (backend_combo.get_active_text());
1089 DEBUG_ECONTROL ("backend-changed(): found prior state for backend");
1090 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1091 set_current_state (state);
1093 DEBUG_ECONTROL ("backend-changed(): no prior state for backend");
1096 DEBUG_ECONTROL (string_compose ("backend-changed(): _have_control=%1 ignore_changes=%2", _have_control, ignore_changes));
1099 if (!ignore_changes) {
1100 maybe_display_saved_state ();
1105 EngineControl::update_midi_options ()
1107 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1108 vector<string> midi_options = backend->enumerate_midi_options();
1110 if (midi_options.size() == 1) {
1111 /* only contains the "none" option */
1112 set_popdown_strings (midi_option_combo, midi_options);
1113 midi_option_combo.set_sensitive (false);
1115 if (_have_control) {
1116 set_popdown_strings (midi_option_combo, midi_options);
1117 midi_option_combo.set_active_text (midi_options.front());
1118 midi_option_combo.set_sensitive (true);
1120 midi_option_combo.set_sensitive (false);
1126 EngineControl::print_channel_count (Gtk::SpinButton* sb)
1128 if (ARDOUR::Profile->get_mixbus()) {
1132 uint32_t cnt = (uint32_t) sb->get_value();
1134 sb->set_text (_("all available channels"));
1137 snprintf (buf, sizeof (buf), "%d", cnt);
1143 // @return true if there are drivers available
1145 EngineControl::set_driver_popdown_strings ()
1147 DEBUG_ECONTROL ("set_driver_popdown_strings");
1148 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1149 vector<string> drivers = backend->enumerate_drivers();
1151 if (drivers.empty ()) {
1152 // This is an error...?
1156 string current_driver = backend->driver_name ();
1158 DEBUG_ECONTROL (string_compose ("backend->driver_name: %1", current_driver));
1160 if (std::find (drivers.begin (), drivers.end (), current_driver) ==
1163 current_driver = drivers.front ();
1166 set_popdown_strings (driver_combo, drivers);
1168 string_compose ("driver_combo.set_active_text: %1", current_driver));
1169 driver_combo.set_active_text (current_driver);
1174 EngineControl::get_default_device(const string& current_device_name,
1175 const vector<string>& available_devices)
1177 // If the current device is available, use it as default
1178 if (std::find (available_devices.begin (),
1179 available_devices.end (),
1180 current_device_name) != available_devices.end ()) {
1182 return current_device_name;
1185 using namespace ARDOUR;
1187 string default_device_name =
1188 AudioBackend::get_standard_device_name(AudioBackend::DeviceDefault);
1190 vector<string>::const_iterator i;
1192 // If there is a "Default" device available, use it
1193 for (i = available_devices.begin(); i != available_devices.end(); ++i) {
1194 if (*i == default_device_name) {
1199 string none_device_name =
1200 AudioBackend::get_standard_device_name(AudioBackend::DeviceNone);
1202 // Use the first device that isn't "None"
1203 for (i = available_devices.begin(); i != available_devices.end(); ++i) {
1204 if (*i != none_device_name) {
1209 // Use "None" if there are no other available
1210 return available_devices.front();
1213 // @return true if there are devices available
1215 EngineControl::set_device_popdown_strings ()
1217 DEBUG_ECONTROL ("set_device_popdown_strings");
1218 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1219 vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_devices ();
1221 /* NOTE: Ardour currently does not display the "available" field of the
1224 * Doing so would require a different GUI widget than the combo
1225 * box/popdown that we currently use, since it has no way to list
1226 * items that are not selectable. Something more like a popup menu,
1227 * which could have unselectable items, would be appropriate.
1230 vector<string> available_devices;
1232 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1233 available_devices.push_back (i->name);
1236 if (available_devices.empty ()) {
1240 set_popdown_strings (device_combo, available_devices);
1242 std::string default_device =
1243 get_default_device(backend->device_name(), available_devices);
1246 string_compose ("set device_combo active text: %1", default_device));
1248 device_combo.set_active_text(default_device);
1252 // @return true if there are input devices available
1254 EngineControl::set_input_device_popdown_strings ()
1256 DEBUG_ECONTROL ("set_input_device_popdown_strings");
1257 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1258 vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_input_devices ();
1260 vector<string> available_devices;
1262 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1263 available_devices.push_back (i->name);
1266 if (available_devices.empty()) {
1270 set_popdown_strings (input_device_combo, available_devices);
1272 std::string default_device =
1273 get_default_device(backend->input_device_name(), available_devices);
1276 string_compose ("set input_device_combo active text: %1", default_device));
1277 input_device_combo.set_active_text(default_device);
1281 // @return true if there are output devices available
1283 EngineControl::set_output_device_popdown_strings ()
1285 DEBUG_ECONTROL ("set_output_device_popdown_strings");
1286 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1287 vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_output_devices ();
1289 vector<string> available_devices;
1291 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1292 available_devices.push_back (i->name);
1295 if (available_devices.empty()) {
1299 set_popdown_strings (output_device_combo, available_devices);
1301 std::string default_device =
1302 get_default_device(backend->output_device_name(), available_devices);
1305 string_compose ("set output_device_combo active text: %1", default_device));
1306 output_device_combo.set_active_text(default_device);
1311 EngineControl::list_devices ()
1313 DEBUG_ECONTROL ("list_devices");
1314 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1317 /* now fill out devices, mark sample rates, buffer sizes insensitive */
1319 bool devices_available = false;
1321 if (backend->use_separate_input_and_output_devices ()) {
1322 bool input_devices_available = set_input_device_popdown_strings ();
1323 bool output_devices_available = set_output_device_popdown_strings ();
1324 devices_available = input_devices_available || output_devices_available;
1326 devices_available = set_device_popdown_strings ();
1329 if (devices_available) {
1332 device_combo.clear();
1333 input_device_combo.clear();
1334 output_device_combo.clear();
1336 update_sensitivity ();
1340 EngineControl::driver_changed ()
1342 SignalBlocker blocker (*this, "driver_changed");
1343 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1346 backend->set_driver (driver_combo.get_active_text());
1349 // TODO load LRU device(s) for backend + driver combo
1351 if (!ignore_changes) {
1352 maybe_display_saved_state ();
1357 EngineControl::get_sample_rates_for_all_devices ()
1359 boost::shared_ptr<ARDOUR::AudioBackend> backend =
1360 ARDOUR::AudioEngine::instance ()->current_backend ();
1361 vector<float> all_rates;
1363 if (backend->use_separate_input_and_output_devices ()) {
1364 all_rates = backend->available_sample_rates2 (get_input_device_name (), get_output_device_name ());
1366 all_rates = backend->available_sample_rates (get_device_name ());
1372 EngineControl::get_default_sample_rates ()
1374 vector<float> rates;
1375 rates.push_back (8000.0f);
1376 rates.push_back (16000.0f);
1377 rates.push_back (32000.0f);
1378 rates.push_back (44100.0f);
1379 rates.push_back (48000.0f);
1380 rates.push_back (88200.0f);
1381 rates.push_back (96000.0f);
1382 rates.push_back (192000.0f);
1383 rates.push_back (384000.0f);
1388 EngineControl::set_samplerate_popdown_strings ()
1390 DEBUG_ECONTROL ("set_samplerate_popdown_strings");
1391 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1396 if (_have_control) {
1397 sr = get_sample_rates_for_all_devices ();
1399 sr = get_default_sample_rates ();
1402 for (vector<float>::const_iterator x = sr.begin(); x != sr.end(); ++x) {
1403 s.push_back (rate_as_string (*x));
1404 if (*x == _desired_sample_rate) {
1409 set_popdown_strings (sample_rate_combo, s);
1412 if (ARDOUR::AudioEngine::instance()->running()) {
1413 sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
1414 } else if (ARDOUR_UI::instance()->the_session ()) {
1415 float active_sr = ARDOUR_UI::instance()->the_session()->nominal_sample_rate ();
1417 if (std::find (sr.begin (), sr.end (), active_sr) == sr.end ()) {
1418 active_sr = sr.front ();
1421 sample_rate_combo.set_active_text (rate_as_string (active_sr));
1422 } else if (desired.empty ()) {
1423 float new_active_sr = backend->default_sample_rate ();
1425 if (std::find (sr.begin (), sr.end (), new_active_sr) == sr.end ()) {
1426 new_active_sr = sr.front ();
1429 sample_rate_combo.set_active_text (rate_as_string (new_active_sr));
1431 sample_rate_combo.set_active_text (desired);
1434 update_sensitivity ();
1438 EngineControl::get_buffer_sizes_for_all_devices ()
1440 boost::shared_ptr<ARDOUR::AudioBackend> backend =
1441 ARDOUR::AudioEngine::instance ()->current_backend ();
1442 vector<uint32_t> all_sizes;
1444 if (backend->use_separate_input_and_output_devices ()) {
1445 all_sizes = backend->available_buffer_sizes2 (get_input_device_name (), get_output_device_name ());
1447 all_sizes = backend->available_buffer_sizes (get_device_name ());
1453 EngineControl::get_default_buffer_sizes ()
1455 vector<uint32_t> sizes;
1456 sizes.push_back (8);
1457 sizes.push_back (16);
1458 sizes.push_back (32);
1459 sizes.push_back (64);
1460 sizes.push_back (128);
1461 sizes.push_back (256);
1462 sizes.push_back (512);
1463 sizes.push_back (1024);
1464 sizes.push_back (2048);
1465 sizes.push_back (4096);
1466 sizes.push_back (8192);
1471 EngineControl::set_buffersize_popdown_strings ()
1473 DEBUG_ECONTROL ("set_buffersize_popdown_strings");
1474 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1475 vector<uint32_t> bs;
1478 if (_have_control) {
1479 bs = get_buffer_sizes_for_all_devices ();
1480 } else if (backend->can_change_buffer_size_when_running()) {
1481 bs = get_default_buffer_sizes ();
1484 for (vector<uint32_t>::const_iterator x = bs.begin(); x != bs.end(); ++x) {
1485 s.push_back (bufsize_as_string (*x));
1488 uint32_t previous_size = backend->buffer_size ();
1489 if (!buffer_size_combo.get_active_text().empty()) {
1490 previous_size = get_buffer_size ();
1493 set_popdown_strings (buffer_size_combo, s);
1497 if (std::find(bs.begin(), bs.end(), previous_size) != bs.end()) {
1498 buffer_size_combo.set_active_text(bufsize_as_string(previous_size));
1501 buffer_size_combo.set_active_text(s.front());
1503 uint32_t period = backend->buffer_size();
1504 if (0 == period && backend->use_separate_input_and_output_devices()) {
1505 period = backend->default_buffer_size(get_input_device_name());
1507 if (0 == period && backend->use_separate_input_and_output_devices()) {
1508 period = backend->default_buffer_size(get_output_device_name());
1510 if (0 == period && !backend->use_separate_input_and_output_devices()) {
1511 period = backend->default_buffer_size(get_device_name());
1514 set_active_text_if_present(buffer_size_combo, bufsize_as_string(period));
1516 show_buffer_duration ();
1518 update_sensitivity ();
1522 EngineControl::set_nperiods_popdown_strings ()
1524 DEBUG_ECONTROL ("set_nperiods_popdown_strings");
1525 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1526 vector<uint32_t> np;
1529 if (backend->can_set_period_size()) {
1530 np = backend->available_period_sizes (get_driver());
1533 for (vector<uint32_t>::const_iterator x = np.begin(); x != np.end(); ++x) {
1534 s.push_back (to_string (*x));
1537 set_popdown_strings (nperiods_combo, s);
1540 set_active_text_if_present (nperiods_combo, to_string (backend->period_size())); // XXX
1543 update_sensitivity ();
1547 EngineControl::device_changed ()
1549 SignalBlocker blocker (*this, "device_changed");
1550 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1553 string device_name_in;
1554 string device_name_out; // only used if backend support separate I/O devices
1556 if (backend->use_separate_input_and_output_devices()) {
1557 device_name_in = get_input_device_name ();
1558 device_name_out = get_output_device_name ();
1560 device_name_in = get_device_name ();
1563 /* we set the backend-device to query various device related intormation.
1564 * This has the side effect that backend->device_name() will match
1565 * the device_name and 'change_device' will never be true.
1566 * so work around this by setting...
1568 if (backend->use_separate_input_and_output_devices()) {
1569 if (device_name_in != backend->input_device_name() || device_name_out != backend->output_device_name ()) {
1570 queue_device_changed = true;
1573 if (device_name_in != backend->device_name()) {
1574 queue_device_changed = true;
1578 //the device name must be set FIRST so ASIO can populate buffersizes and the control panel button
1579 if (backend->use_separate_input_and_output_devices()) {
1580 backend->set_input_device_name (device_name_in);
1581 backend->set_output_device_name (device_name_out);
1583 backend->set_device_name(device_name_in);
1587 /* don't allow programmatic change to combos to cause a
1588 recursive call to this method.
1590 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1592 set_samplerate_popdown_strings ();
1593 set_buffersize_popdown_strings ();
1594 set_nperiods_popdown_strings ();
1596 /* TODO set min + max channel counts here */
1598 manage_control_app_sensitivity ();
1601 /* pick up any saved state for this device */
1603 if (!ignore_changes) {
1604 maybe_display_saved_state ();
1609 EngineControl::input_device_changed ()
1611 DEBUG_ECONTROL ("input_device_changed");
1613 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1614 if (backend && backend->match_input_output_devices_or_none ()) {
1615 const std::string& dev_none = ARDOUR::AudioBackend::get_standard_device_name (ARDOUR::AudioBackend::DeviceNone);
1617 if (get_output_device_name () != dev_none
1618 && get_input_device_name () != dev_none
1619 && get_input_device_name () != get_output_device_name ()) {
1620 block_changed_signals ();
1621 if (contains_value (output_device_combo, get_input_device_name ())) {
1622 output_device_combo.set_active_text (get_input_device_name ());
1624 assert (contains_value (output_device_combo, dev_none));
1625 output_device_combo.set_active_text (dev_none);
1627 unblock_changed_signals ();
1634 EngineControl::output_device_changed ()
1636 DEBUG_ECONTROL ("output_device_changed");
1637 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1638 if (backend && backend->match_input_output_devices_or_none ()) {
1639 const std::string& dev_none = ARDOUR::AudioBackend::get_standard_device_name (ARDOUR::AudioBackend::DeviceNone);
1641 if (get_input_device_name () != dev_none
1642 && get_input_device_name () != dev_none
1643 && get_input_device_name () != get_output_device_name ()) {
1644 block_changed_signals ();
1645 if (contains_value (input_device_combo, get_output_device_name ())) {
1646 input_device_combo.set_active_text (get_output_device_name ());
1648 assert (contains_value (input_device_combo, dev_none));
1649 input_device_combo.set_active_text (dev_none);
1651 unblock_changed_signals ();
1658 EngineControl::bufsize_as_string (uint32_t sz)
1660 return string_compose (P_("%1 sample", "%1 samples", sz), to_string(sz));
1664 EngineControl::sample_rate_changed ()
1666 DEBUG_ECONTROL ("sample_rate_changed");
1667 /* reset the strings for buffer size to show the correct msec value
1668 (reflecting the new sample rate).
1671 show_buffer_duration ();
1676 EngineControl::buffer_size_changed ()
1678 DEBUG_ECONTROL ("buffer_size_changed");
1679 if (ARDOUR::AudioEngine::instance()->running()) {
1680 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1681 if (backend && backend->can_change_buffer_size_when_running ()) {
1682 backend->set_buffer_size (get_buffer_size());
1685 show_buffer_duration ();
1689 EngineControl::nperiods_changed ()
1691 DEBUG_ECONTROL ("nperiods_changed");
1692 show_buffer_duration ();
1696 EngineControl::show_buffer_duration ()
1698 DEBUG_ECONTROL ("show_buffer_duration");
1699 /* buffer sizes - convert from just samples to samples + msecs for
1700 * the displayed string
1703 string bs_text = buffer_size_combo.get_active_text ();
1704 uint32_t samples = atoi (bs_text); /* will ignore trailing text */
1705 uint32_t rate = get_rate();
1707 /* Except for ALSA and Dummy backends, we don't know the number of periods
1708 * per cycle and settings.
1710 * jack1 vs jack2 have different default latencies since jack2 start
1711 * in async-mode unless --sync is given which adds an extra cycle
1712 * of latency. The value is not known if jackd is started externally..
1714 * So just display the period size, that's also what
1715 * ARDOUR_UI::update_sample_rate() does for the status bar.
1716 * (the statusbar calls AudioEngine::instance()->usecs_per_cycle()
1717 * but still, that's the buffer period, not [round-trip] latency)
1720 snprintf (buf, sizeof (buf), _("(%.1f ms)"), (samples / (rate/1000.0f)));
1721 buffer_size_duration_label.set_text (buf);
1725 EngineControl::midi_option_changed ()
1727 DEBUG_ECONTROL ("midi_option_changed");
1728 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1731 backend->set_midi_option (get_midi_option());
1733 vector<ARDOUR::AudioBackend::DeviceStatus> midi_devices = backend->enumerate_midi_devices();
1735 _can_set_midi_latencies = backend->can_set_systemic_midi_latencies();
1736 std::vector<MidiDeviceSettings> new_devices;
1738 for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = midi_devices.begin(); i != midi_devices.end(); ++i) {
1739 MidiDeviceSettings mds = find_midi_device (i->name);
1740 if (i->available && !mds) {
1741 uint32_t input_latency = 0;
1742 uint32_t output_latency = 0;
1743 if (_can_set_midi_latencies) {
1744 input_latency = backend->systemic_midi_input_latency (i->name);
1745 output_latency = backend->systemic_midi_output_latency (i->name);
1747 bool enabled = backend->midi_device_enabled (i->name);
1748 MidiDeviceSettings ptr (new MidiDeviceSetting (i->name, enabled, input_latency, output_latency));
1749 new_devices.push_back (ptr);
1750 } else if (i->available) {
1751 new_devices.push_back (mds);
1754 _midi_devices = new_devices;
1756 if (_midi_devices.empty()) {
1757 midi_devices_button.hide ();
1759 midi_devices_button.show ();
1764 EngineControl::parameter_changed ()
1768 EngineControl::State
1769 EngineControl::get_matching_state (const string& backend)
1771 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1772 if ((*i)->backend == backend) {
1779 EngineControl::State
1780 EngineControl::get_matching_state (
1781 const string& backend,
1782 const string& driver,
1783 const string& device)
1785 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1786 if ((*i)->backend == backend &&
1787 (!_have_control || ((*i)->driver == driver && (*i)->device == device)))
1795 EngineControl::State
1796 EngineControl::get_matching_state (
1797 const string& backend,
1798 const string& driver,
1799 const string& input_device,
1800 const string& output_device)
1802 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1803 if ((*i)->backend == backend &&
1804 (!_have_control || ((*i)->driver == driver && ((*i)->input_device == input_device) && (*i)->output_device == output_device)))
1812 EngineControl::State
1813 EngineControl::get_saved_state_for_currently_displayed_backend_and_device ()
1815 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1818 if (backend->use_separate_input_and_output_devices ()) {
1819 return get_matching_state (backend_combo.get_active_text(),
1820 (backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
1821 input_device_combo.get_active_text(),
1822 output_device_combo.get_active_text());
1824 return get_matching_state (backend_combo.get_active_text(),
1825 (backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
1826 device_combo.get_active_text());
1830 return get_matching_state (backend_combo.get_active_text(),
1832 device_combo.get_active_text());
1835 bool EngineControl::equivalent_states (const EngineControl::State& state1,
1836 const EngineControl::State& state2)
1838 if (state1->backend == state2->backend &&
1839 state1->driver == state2->driver &&
1840 state1->device == state2->device &&
1841 state1->input_device == state2->input_device &&
1842 state1->output_device == state2->output_device) {
1848 // sort active first, then most recently used to the beginning of the list
1850 EngineControl::state_sort_cmp (const State &a, const State &b) {
1854 else if (b->active) {
1858 return a->lru > b->lru;
1862 EngineControl::State
1863 EngineControl::save_state ()
1867 if (!_have_control) {
1868 state = get_matching_state (backend_combo.get_active_text(), string(), string());
1870 state->lru = time (NULL) ;
1873 state.reset(new StateStruct);
1874 state->backend = get_backend ();
1876 state.reset(new StateStruct);
1877 store_state (state);
1880 for (StateList::iterator i = states.begin(); i != states.end();) {
1881 if (equivalent_states (*i, state)) {
1882 i = states.erase(i);
1888 states.push_back (state);
1890 states.sort (state_sort_cmp);
1896 EngineControl::store_state (State state)
1898 state->backend = get_backend ();
1899 state->driver = get_driver ();
1900 state->device = get_device_name ();
1901 state->input_device = get_input_device_name ();
1902 state->output_device = get_output_device_name ();
1903 state->sample_rate = get_rate ();
1904 state->buffer_size = get_buffer_size ();
1905 state->n_periods = get_nperiods ();
1906 state->input_latency = get_input_latency ();
1907 state->output_latency = get_output_latency ();
1908 state->input_channels = get_input_channels ();
1909 state->output_channels = get_output_channels ();
1910 state->midi_option = get_midi_option ();
1911 state->midi_devices = _midi_devices;
1912 state->use_buffered_io = get_use_buffered_io ();
1913 state->lru = time (NULL) ;
1917 EngineControl::maybe_display_saved_state ()
1919 if (!_have_control || ARDOUR::AudioEngine::instance()->running ()) {
1923 State state = get_saved_state_for_currently_displayed_backend_and_device ();
1926 DEBUG_ECONTROL ("Restoring saved state");
1927 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1929 if (0 == _desired_sample_rate && sample_rate_combo.get_sensitive ()) {
1930 sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
1932 set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
1934 set_active_text_if_present (nperiods_combo, to_string(state->n_periods));
1935 /* call this explicitly because we're ignoring changes to
1936 the controls at this point.
1938 show_buffer_duration ();
1939 input_latency.set_value (state->input_latency);
1940 output_latency.set_value (state->output_latency);
1942 use_buffered_io_button.set_active (state->use_buffered_io);
1944 if (!state->midi_option.empty()) {
1945 midi_option_combo.set_active_text (state->midi_option);
1946 _midi_devices = state->midi_devices;
1947 midi_option_changed ();
1950 DEBUG_ECONTROL ("Unable to find saved state for backend and devices");
1955 EngineControl::get_state ()
1959 XMLNode* root = new XMLNode ("AudioMIDISetup");
1962 if (!states.empty()) {
1963 XMLNode* state_nodes = new XMLNode ("EngineStates");
1965 for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
1967 XMLNode* node = new XMLNode ("State");
1969 node->set_property ("backend", (*i)->backend);
1970 node->set_property ("driver", (*i)->driver);
1971 node->set_property ("device", (*i)->device);
1972 node->set_property ("input-device", (*i)->input_device);
1973 node->set_property ("output-device", (*i)->output_device);
1974 node->set_property ("sample-rate", (*i)->sample_rate);
1975 node->set_property ("buffer-size", (*i)->buffer_size);
1976 node->set_property ("n-periods", (*i)->n_periods);
1977 node->set_property ("input-latency", (*i)->input_latency);
1978 node->set_property ("output-latency", (*i)->output_latency);
1979 node->set_property ("input-channels", (*i)->input_channels);
1980 node->set_property ("output-channels", (*i)->output_channels);
1981 node->set_property ("active", (*i)->active);
1982 node->set_property ("use-buffered-io", (*i)->use_buffered_io);
1983 node->set_property ("midi-option", (*i)->midi_option);
1984 int32_t lru_val = (*i)->active ? time (NULL) : (*i)->lru;
1985 node->set_property ("lru", lru_val );
1987 XMLNode* midi_devices = new XMLNode ("MIDIDevices");
1988 for (std::vector<MidiDeviceSettings>::const_iterator p = (*i)->midi_devices.begin(); p != (*i)->midi_devices.end(); ++p) {
1989 XMLNode* midi_device_stuff = new XMLNode ("MIDIDevice");
1990 midi_device_stuff->set_property (X_("name"), (*p)->name);
1991 midi_device_stuff->set_property (X_("enabled"), (*p)->enabled);
1992 midi_device_stuff->set_property (X_("input-latency"), (*p)->input_latency);
1993 midi_device_stuff->set_property (X_("output-latency"), (*p)->output_latency);
1994 midi_devices->add_child_nocopy (*midi_device_stuff);
1996 node->add_child_nocopy (*midi_devices);
1998 state_nodes->add_child_nocopy (*node);
2001 root->add_child_nocopy (*state_nodes);
2008 EngineControl::set_default_state ()
2010 vector<string> backend_names;
2011 vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
2013 for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
2014 backend_names.push_back ((*b)->name);
2016 backend_combo.set_active_text (backend_names.front());
2018 // We could set default backends per platform etc here
2024 EngineControl::set_state (const XMLNode& root)
2026 XMLNodeList clist, cclist;
2027 XMLNodeConstIterator citer, cciter;
2028 XMLNode const * child;
2029 XMLNode const * grandchild;
2031 if (root.name() != "AudioMIDISetup") {
2035 clist = root.children();
2039 for (citer = clist.begin(); citer != clist.end(); ++citer) {
2043 if (child->name() != "EngineStates") {
2047 cclist = child->children();
2049 for (cciter = cclist.begin(); cciter != cclist.end(); ++cciter) {
2050 State state (new StateStruct);
2052 grandchild = *cciter;
2054 if (grandchild->name() != "State") {
2058 if (!grandchild->get_property ("backend", state->backend)) {
2062 // If any of the required properties are not found in the state node
2063 // then continue/skip to the next engine state
2064 if (!grandchild->get_property ("driver", state->driver) ||
2065 !grandchild->get_property ("device", state->device) ||
2066 !grandchild->get_property ("input-device", state->input_device) ||
2067 !grandchild->get_property ("output-device", state->output_device) ||
2068 !grandchild->get_property ("sample-rate", state->sample_rate) ||
2069 !grandchild->get_property ("buffer-size", state->buffer_size) ||
2070 !grandchild->get_property ("input-latency", state->input_latency) ||
2071 !grandchild->get_property ("output-latency", state->output_latency) ||
2072 !grandchild->get_property ("input-channels", state->input_channels) ||
2073 !grandchild->get_property ("output-channels", state->output_channels) ||
2074 !grandchild->get_property ("active", state->active) ||
2075 !grandchild->get_property ("use-buffered-io", state->use_buffered_io) ||
2076 !grandchild->get_property ("midi-option", state->midi_option)) {
2080 if (!grandchild->get_property ("n-periods", state->n_periods)) {
2081 // optional (new value in 4.5)
2082 state->n_periods = 0;
2085 state->midi_devices.clear();
2087 if ((midinode = ARDOUR::find_named_node (*grandchild, "MIDIDevices")) != 0) {
2088 const XMLNodeList mnc = midinode->children();
2089 for (XMLNodeList::const_iterator n = mnc.begin(); n != mnc.end(); ++n) {
2092 uint32_t input_latency;
2093 uint32_t output_latency;
2095 if (!(*n)->get_property (X_("name"), name) ||
2096 !(*n)->get_property (X_("enabled"), enabled) ||
2097 !(*n)->get_property (X_("input-latency"), input_latency) ||
2098 !(*n)->get_property (X_("output-latency"), output_latency)) {
2102 MidiDeviceSettings ptr (
2103 new MidiDeviceSetting (name, enabled, input_latency, output_latency));
2104 state->midi_devices.push_back (ptr);
2109 if (grandchild->get_property ("lru", lru_val)) {
2110 state->lru = lru_val;
2113 states.push_back (state);
2117 /* now see if there was an active state and switch the setup to it */
2119 /* purge states of backend that are not available in this built */
2120 vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
2121 vector<std::string> backend_names;
2123 for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator i = backends.begin(); i != backends.end(); ++i) {
2124 backend_names.push_back((*i)->name);
2126 for (StateList::iterator i = states.begin(); i != states.end();) {
2127 if (std::find(backend_names.begin(), backend_names.end(), (*i)->backend) == backend_names.end()) {
2128 i = states.erase(i);
2134 states.sort (state_sort_cmp);
2136 /* purge old states referring to the same backend */
2137 const time_t now = time (NULL);
2138 for (vector<std::string>::const_iterator bi = backend_names.begin(); bi != backend_names.end(); ++bi) {
2140 for (StateList::iterator i = states.begin(); i != states.end();) {
2141 if ((*i)->backend != *bi) {
2144 // keep at latest one for every audio-system
2149 // also keep states used in the last 90 days.
2150 if ((now - (*i)->lru) < 86400 * 90) {
2153 assert (!(*i)->active);
2154 i = states.erase(i);
2158 for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
2161 return set_current_state (*i);
2168 EngineControl::set_current_state (const State& state)
2170 DEBUG_ECONTROL ("set_current_state");
2172 boost::shared_ptr<ARDOUR::AudioBackend> backend;
2174 if (!(backend = ARDOUR::AudioEngine::instance ()->set_backend (
2175 state->backend, downcase (std::string(PROGRAM_NAME)), ""))) {
2176 DEBUG_ECONTROL (string_compose ("Unable to set backend to %1", state->backend));
2177 // this shouldn't happen as the invalid backend names should have been
2178 // removed from the list of states.
2182 // now reflect the change in the backend in the GUI so backend_changed will
2183 // do the right thing
2184 backend_combo.set_active_text (state->backend);
2186 if (!ARDOUR::AudioEngine::instance()->setup_required ()) {
2188 // we don't have control don't restore state
2193 if (!state->driver.empty ()) {
2194 if (!backend->requires_driver_selection ()) {
2195 DEBUG_ECONTROL ("Backend should require driver selection");
2196 // A backend has changed from having driver selection to not having
2197 // it or someone has been manually editing a config file and messed
2202 if (backend->set_driver (state->driver) != 0) {
2203 DEBUG_ECONTROL (string_compose ("Unable to set driver %1", state->driver));
2204 // Driver names for a backend have changed and the name in the
2205 // config file is now invalid or support for driver is no longer
2206 // included in the backend
2209 // no need to set the driver_combo as backend_changed will use
2210 // backend->driver_name to set the active driver
2213 if (!state->device.empty ()) {
2214 if (backend->set_device_name (state->device) != 0) {
2216 string_compose ("Unable to set device name %1", state->device));
2217 // device is no longer available on the system
2220 // no need to set active device as it will be picked up in
2221 // via backend_changed ()/set_device_popdown_strings
2224 // backend supports separate input/output devices
2225 if (backend->set_input_device_name (state->input_device) != 0) {
2226 DEBUG_ECONTROL (string_compose ("Unable to set input device name %1",
2227 state->input_device));
2228 // input device is no longer available on the system
2232 if (backend->set_output_device_name (state->output_device) != 0) {
2233 DEBUG_ECONTROL (string_compose ("Unable to set output device name %1",
2234 state->input_device));
2235 // output device is no longer available on the system
2238 // no need to set active devices as it will be picked up in via
2239 // backend_changed ()/set_*_device_popdown_strings
2244 // Now restore the state of the rest of the controls
2246 // We don't use a SignalBlocker as set_current_state is currently only
2247 // called from set_state before any signals are connected. If at some point
2248 // a more general named state mechanism is implemented and
2249 // set_current_state is called while signals are connected then a
2250 // SignalBlocker will need to be instantiated before setting these.
2252 device_combo.set_active_text (state->device);
2253 input_device_combo.set_active_text (state->input_device);
2254 output_device_combo.set_active_text (state->output_device);
2255 if (0 == _desired_sample_rate && sample_rate_combo.get_sensitive ()) {
2256 sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
2258 set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
2259 set_active_text_if_present (nperiods_combo, to_string (state->n_periods));
2260 input_latency.set_value (state->input_latency);
2261 output_latency.set_value (state->output_latency);
2262 midi_option_combo.set_active_text (state->midi_option);
2263 use_buffered_io_button.set_active (state->use_buffered_io);
2268 EngineControl::push_state_to_backend (bool start)
2270 DEBUG_ECONTROL ("push_state_to_backend");
2271 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2272 PBD::Unwinder<uint32_t> protect_ignore_device_changes (ignore_device_changes, ignore_device_changes + 1);
2278 /* figure out what is going to change */
2280 bool restart_required = false;
2281 bool was_running = ARDOUR::AudioEngine::instance()->running();
2282 bool change_driver = false;
2283 bool change_device = false;
2284 bool change_rate = false;
2285 bool change_bufsize = false;
2286 bool change_nperiods = false;
2287 bool change_latency = false;
2288 bool change_channels = false;
2289 bool change_midi = false;
2290 bool change_buffered_io = false;
2292 uint32_t ochan = get_output_channels ();
2293 uint32_t ichan = get_input_channels ();
2295 if (_have_control) {
2297 if (started_at_least_once) {
2299 /* we can control the backend */
2301 if (backend->requires_driver_selection()) {
2302 if (get_driver() != backend->driver_name()) {
2303 change_driver = true;
2307 if (backend->use_separate_input_and_output_devices()) {
2308 if (get_input_device_name() != backend->input_device_name()) {
2309 change_device = true;
2311 if (get_output_device_name() != backend->output_device_name()) {
2312 change_device = true;
2315 if (get_device_name() != backend->device_name()) {
2316 change_device = true;
2320 if (queue_device_changed) {
2321 change_device = true;
2324 if (get_rate() != backend->sample_rate()) {
2328 if (get_buffer_size() != backend->buffer_size()) {
2329 change_bufsize = true;
2332 if (backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0
2333 && get_nperiods() != backend->period_size()) {
2334 change_nperiods = true;
2337 if (get_midi_option() != backend->midi_option()) {
2341 if (backend->can_use_buffered_io()) {
2342 if (get_use_buffered_io() != backend->get_use_buffered_io()) {
2343 change_buffered_io = true;
2347 /* zero-requested channels means "all available" */
2350 ichan = backend->input_channels();
2354 ochan = backend->output_channels();
2357 if (ichan != backend->input_channels()) {
2358 change_channels = true;
2361 if (ochan != backend->output_channels()) {
2362 change_channels = true;
2365 if (get_input_latency() != backend->systemic_input_latency() ||
2366 get_output_latency() != backend->systemic_output_latency()) {
2367 change_latency = true;
2370 /* backend never started, so we have to force a group
2373 change_device = true;
2374 if (backend->requires_driver_selection()) {
2375 change_driver = true;
2378 change_bufsize = true;
2379 change_channels = true;
2380 change_latency = true;
2382 change_buffered_io = backend->can_use_buffered_io();
2383 change_channels = true;
2384 change_nperiods = backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0;
2389 /* we have no control over the backend, meaning that we can
2390 * only possibly change sample rate and buffer size.
2394 if (get_rate() != backend->sample_rate()) {
2395 change_bufsize = true;
2398 if (get_buffer_size() != backend->buffer_size()) {
2399 change_bufsize = true;
2403 queue_device_changed = false;
2405 if (!_have_control) {
2407 /* We do not have control over the backend, so the best we can
2408 * do is try to change the sample rate and/or bufsize and get
2412 if (change_rate && !backend->can_change_sample_rate_when_running()) {
2416 if (change_bufsize && !backend->can_change_buffer_size_when_running()) {
2421 backend->set_sample_rate (get_rate());
2424 if (change_bufsize) {
2425 backend->set_buffer_size (get_buffer_size());
2429 if (ARDOUR::AudioEngine::instance()->start ()) {
2430 error << string_compose (_("Could not start backend engine %1"), backend->name()) << endmsg;
2440 /* determine if we need to stop the backend before changing parameters */
2442 if (change_driver || change_device || change_channels || change_nperiods ||
2443 (change_latency && !backend->can_change_systemic_latency_when_running ()) ||
2444 (change_rate && !backend->can_change_sample_rate_when_running()) ||
2445 change_midi || change_buffered_io ||
2446 (change_bufsize && !backend->can_change_buffer_size_when_running())) {
2447 restart_required = true;
2449 restart_required = false;
2454 if (restart_required) {
2455 if (ARDOUR::AudioEngine::instance()->stop()) {
2461 if (change_driver && backend->set_driver (get_driver())) {
2462 error << string_compose (_("Cannot set driver to %1"), get_driver()) << endmsg;
2465 if (backend->use_separate_input_and_output_devices()) {
2466 if (change_device && backend->set_input_device_name (get_input_device_name())) {
2467 error << string_compose (_("Cannot set input device name to %1"), get_input_device_name()) << endmsg;
2470 if (change_device && backend->set_output_device_name (get_output_device_name())) {
2471 error << string_compose (_("Cannot set output device name to %1"), get_output_device_name()) << endmsg;
2475 if (change_device && backend->set_device_name (get_device_name())) {
2476 error << string_compose (_("Cannot set device name to %1"), get_device_name()) << endmsg;
2480 if (change_rate && backend->set_sample_rate (get_rate())) {
2481 error << string_compose (_("Cannot set sample rate to %1"), get_rate()) << endmsg;
2484 if (change_bufsize && backend->set_buffer_size (get_buffer_size())) {
2485 error << string_compose (_("Cannot set buffer size to %1"), get_buffer_size()) << endmsg;
2488 if (change_nperiods && backend->set_peridod_size (get_nperiods())) {
2489 error << string_compose (_("Cannot set periods to %1"), get_nperiods()) << endmsg;
2493 if (change_channels || get_input_channels() == 0 || get_output_channels() == 0) {
2494 if (backend->set_input_channels (get_input_channels())) {
2495 error << string_compose (_("Cannot set input channels to %1"), get_input_channels()) << endmsg;
2498 if (backend->set_output_channels (get_output_channels())) {
2499 error << string_compose (_("Cannot set output channels to %1"), get_output_channels()) << endmsg;
2503 if (change_latency) {
2504 if (backend->set_systemic_input_latency (get_input_latency())) {
2505 error << string_compose (_("Cannot set input latency to %1"), get_input_latency()) << endmsg;
2508 if (backend->set_systemic_output_latency (get_output_latency())) {
2509 error << string_compose (_("Cannot set output latency to %1"), get_output_latency()) << endmsg;
2515 backend->set_midi_option (get_midi_option());
2518 if (change_buffered_io) {
2519 backend->set_use_buffered_io (use_buffered_io_button.get_active());
2523 for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
2524 if (_measure_midi) {
2525 /* Disable other MIDI devices while measuring.
2526 * This is a hack to only show ports from the selected device */
2527 if (*p == _measure_midi) {
2528 backend->set_midi_device_enabled ((*p)->name, true);
2530 backend->set_midi_device_enabled ((*p)->name, false);
2534 backend->set_midi_device_enabled ((*p)->name, (*p)->enabled);
2535 if (backend->can_set_systemic_midi_latencies()) {
2536 backend->set_systemic_midi_input_latency ((*p)->name, (*p)->input_latency);
2537 backend->set_systemic_midi_output_latency ((*p)->name, (*p)->output_latency);
2542 if (start || (was_running && restart_required)) {
2543 if (ARDOUR::AudioEngine::instance()->start()) {
2554 EngineControl::post_push ()
2556 /* get a pointer to the current state object, creating one if
2560 State state = get_saved_state_for_currently_displayed_backend_and_device ();
2563 state = save_state ();
2569 states.sort (state_sort_cmp);
2573 for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
2574 (*i)->active = false;
2577 /* mark this one active (to be used next time the dialog is
2581 state->active = true;
2583 if (_have_control) { // XXX
2584 manage_control_app_sensitivity ();
2587 /* schedule a redisplay of MIDI ports */
2588 //Glib::signal_timeout().connect (sigc::bind_return (sigc::mem_fun (*this, &EngineControl::refresh_midi_display), false), 1000);
2593 EngineControl::get_rate () const
2595 float r = atof (sample_rate_combo.get_active_text ());
2596 /* the string may have been translated with an abbreviation for
2597 * thousands, so use a crude heuristic to fix this.
2607 EngineControl::get_buffer_size () const
2609 string txt = buffer_size_combo.get_active_text ();
2612 if (sscanf (txt.c_str(), "%d", &samples) != 1) {
2613 fprintf(stderr, "Find a trout and repeatedly slap the nearest C++ who throws exceptions without catching them.\n");
2614 fprintf(stderr, "Ardour will likely crash now, giving you time to get the trout.\n");
2622 EngineControl::get_nperiods () const
2624 string txt = nperiods_combo.get_active_text ();
2625 return atoi (txt.c_str());
2629 EngineControl::get_midi_option () const
2631 return midi_option_combo.get_active_text();
2635 EngineControl::get_use_buffered_io () const
2637 return use_buffered_io_button.get_active();
2641 EngineControl::get_input_channels() const
2643 if (ARDOUR::Profile->get_mixbus()) {
2644 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2645 if (!backend) return 0;
2646 return backend->input_channels();
2648 return (uint32_t) input_channels_adjustment.get_value();
2652 EngineControl::get_output_channels() const
2654 if (ARDOUR::Profile->get_mixbus()) {
2655 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2656 if (!backend) return 0;
2657 return backend->input_channels();
2659 return (uint32_t) output_channels_adjustment.get_value();
2663 EngineControl::get_input_latency() const
2665 return (uint32_t) input_latency_adjustment.get_value();
2669 EngineControl::get_output_latency() const
2671 return (uint32_t) output_latency_adjustment.get_value();
2675 EngineControl::get_backend () const
2677 return backend_combo.get_active_text ();
2681 EngineControl::get_driver () const
2683 if (driver_combo.get_parent()) {
2684 return driver_combo.get_active_text ();
2691 EngineControl::get_device_name () const
2693 return device_combo.get_active_text ();
2697 EngineControl::get_input_device_name () const
2699 return input_device_combo.get_active_text ();
2703 EngineControl::get_output_device_name () const
2705 return output_device_combo.get_active_text ();
2709 EngineControl::control_app_button_clicked ()
2711 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2717 backend->launch_control_app ();
2721 EngineControl::start_stop_button_clicked ()
2723 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2729 if (ARDOUR::AudioEngine::instance()->running()) {
2730 ARDOUR::AudioEngine::instance()->stop ();
2732 if (!ARDOUR_UI::instance()->the_session ()) {
2738 if (!ARDOUR_UI::instance()->the_session ()) {
2739 ArdourDialog::on_response (RESPONSE_OK);
2745 EngineControl::update_devices_button_clicked ()
2747 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2753 if (backend->update_devices()) {
2754 device_list_changed ();
2759 EngineControl::use_buffered_io_button_clicked ()
2761 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2767 bool set_buffered_io = !use_buffered_io_button.get_active();
2768 use_buffered_io_button.set_active (set_buffered_io);
2769 backend->set_use_buffered_io (set_buffered_io);
2773 EngineControl::manage_control_app_sensitivity ()
2775 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2781 string appname = backend->control_app_name();
2783 if (appname.empty()) {
2784 control_app_button.set_sensitive (false);
2786 control_app_button.set_sensitive (true);
2791 EngineControl::set_desired_sample_rate (uint32_t sr)
2793 _desired_sample_rate = sr;
2794 if (ARDOUR::AudioEngine::instance ()->running ()
2795 && ARDOUR::AudioEngine::instance ()->sample_rate () != sr) {
2802 EngineControl::on_switch_page (GtkNotebookPage*, guint page_num)
2804 if (page_num == 0) {
2805 _measure_midi.reset();
2806 update_sensitivity ();
2809 if (page_num == midi_tab) {
2811 refresh_midi_display ();
2813 /* undo special case from push_state_to_backend() when measuring midi latency */
2814 if (_measure_midi && ARDOUR::AudioEngine::instance()->running ()) {
2815 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2816 if (backend->can_change_systemic_latency_when_running ()) {
2817 for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
2818 backend->set_midi_device_enabled ((*p)->name, (*p)->enabled);
2822 _measure_midi.reset();
2825 if (page_num == latency_tab) {
2828 if (ARDOUR::AudioEngine::instance()->running()) {
2833 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
2835 /* save any existing latency values */
2837 uint32_t il = (uint32_t) input_latency.get_value ();
2838 uint32_t ol = (uint32_t) input_latency.get_value ();
2840 /* reset to zero so that our new test instance
2841 will be clean of any existing latency measures.
2843 NB. this should really be done by the backend
2844 when stated for latency measurement.
2847 input_latency.set_value (0);
2848 output_latency.set_value (0);
2850 push_state_to_backend (false);
2854 input_latency.set_value (il);
2855 output_latency.set_value (ol);
2858 // This should be done in push_state_to_backend()
2859 if (ARDOUR::AudioEngine::instance()->prepare_for_latency_measurement()) {
2860 disable_latency_tab ();
2863 enable_latency_tab ();
2867 end_latency_detection ();
2872 /* latency measurement */
2875 EngineControl::check_audio_latency_measurement ()
2877 MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
2879 if (mtdm->resolve () < 0) {
2880 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
2884 if (mtdm->get_peak () > 0.707f) {
2885 // get_peak() resets the peak-hold in the detector.
2886 // this GUI callback is at 10Hz and so will be fine (test-signal is at higher freq)
2887 lm_results.set_markup (string_compose (results_markup, _("Input signal is > -3dBFS. Lower the signal level (output gain, input gain) on the audio-interface.")));
2891 if (mtdm->err () > 0.3) {
2897 ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
2899 if (sample_rate == 0) {
2900 lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
2901 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
2905 int samples_total = mtdm->del();
2906 int extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
2908 snprintf (buf, sizeof (buf), "%s%d samples (%.3lf ms)\n%s%d samples (%.3lf ms)",
2909 _("Detected roundtrip latency: "),
2910 samples_total, samples_total * 1000.0f/sample_rate,
2911 _("Systemic latency: "),
2912 extra, extra * 1000.0f/sample_rate);
2916 if (mtdm->err () > 0.2) {
2918 strcat (buf, _("(signal detection error)"));
2924 strcat (buf, _("(inverted - bad wiring)"));
2928 lm_results.set_markup (string_compose (results_markup, buf));
2931 have_lm_results = true;
2932 end_latency_detection ();
2933 lm_use_button.set_sensitive (true);
2941 EngineControl::check_midi_latency_measurement ()
2943 ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
2945 if (!mididm->have_signal () || mididm->latency () == 0) {
2946 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
2951 ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
2953 if (sample_rate == 0) {
2954 lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
2955 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
2959 ARDOUR::samplecnt_t samples_total = mididm->latency();
2960 ARDOUR::samplecnt_t extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
2961 snprintf (buf, sizeof (buf), "%s%" PRId64" samples (%.1lf ms) dev: %.2f[spl]\n%s%" PRId64" samples (%.1lf ms)",
2962 _("Detected roundtrip latency: "),
2963 samples_total, samples_total * 1000.0f / sample_rate, mididm->deviation (),
2964 _("Systemic latency: "),
2965 extra, extra * 1000.0f / sample_rate);
2969 if (!mididm->ok ()) {
2971 strcat (buf, _("(averaging)"));
2975 if (mididm->deviation () > 50.0) {
2977 strcat (buf, _("(too large jitter)"));
2979 } else if (mididm->deviation () > 10.0) {
2981 strcat (buf, _("(large jitter)"));
2985 have_lm_results = true;
2986 end_latency_detection ();
2987 lm_use_button.set_sensitive (true);
2988 lm_results.set_markup (string_compose (results_markup, buf));
2990 } else if (mididm->processed () > 400) {
2991 have_lm_results = false;
2992 end_latency_detection ();
2993 lm_results.set_markup (string_compose (results_markup, _("Timeout - large MIDI jitter.")));
2997 lm_results.set_markup (string_compose (results_markup, buf));
3003 EngineControl::start_latency_detection ()
3005 ARDOUR::AudioEngine::instance()->set_latency_input_port (lm_input_channel_combo.get_active ()->get_value (lm_input_channel_cols.port_name));
3006 ARDOUR::AudioEngine::instance()->set_latency_output_port (lm_output_channel_combo.get_active ()->get_value (lm_output_channel_cols.port_name));
3008 if (ARDOUR::AudioEngine::instance()->start_latency_detection (_measure_midi ? true : false) == 0) {
3009 lm_results.set_markup (string_compose (results_markup, _("Detecting ...")));
3010 if (_measure_midi) {
3011 latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_midi_latency_measurement), 100);
3013 latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_audio_latency_measurement), 100);
3015 lm_measure_label.set_text (_("Cancel"));
3016 have_lm_results = false;
3017 lm_use_button.set_sensitive (false);
3018 lm_input_channel_combo.set_sensitive (false);
3019 lm_output_channel_combo.set_sensitive (false);
3025 EngineControl::end_latency_detection ()
3027 latency_timeout.disconnect ();
3028 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
3029 lm_measure_label.set_text (_("Measure"));
3030 if (!have_lm_results) {
3031 lm_use_button.set_sensitive (false);
3033 lm_input_channel_combo.set_sensitive (true);
3034 lm_output_channel_combo.set_sensitive (true);
3039 EngineControl::latency_button_clicked ()
3042 start_latency_detection ();
3044 end_latency_detection ();
3049 EngineControl::latency_back_button_clicked ()
3051 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
3052 notebook.set_current_page(0);
3056 EngineControl::use_latency_button_clicked ()
3058 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3059 if (_measure_midi) {
3060 ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
3064 ARDOUR::samplecnt_t samples_total = mididm->latency();
3065 ARDOUR::samplecnt_t extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
3066 uint32_t one_way = max ((ARDOUR::samplecnt_t) 0, extra / 2);
3067 _measure_midi->input_latency = one_way;
3068 _measure_midi->output_latency = one_way;
3069 if (backend->can_change_systemic_latency_when_running ()) {
3070 backend->set_systemic_midi_input_latency (_measure_midi->name, one_way);
3071 backend->set_systemic_midi_output_latency (_measure_midi->name, one_way);
3073 notebook.set_current_page (midi_tab);
3075 MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
3081 double one_way = rint ((mtdm->del() - ARDOUR::AudioEngine::instance()->latency_signal_delay()) / 2.0);
3082 one_way = std::max (0., one_way);
3084 input_latency_adjustment.set_value (one_way);
3085 output_latency_adjustment.set_value (one_way);
3086 if (backend->can_change_systemic_latency_when_running ()) {
3087 backend->set_systemic_input_latency (one_way);
3088 backend->set_systemic_output_latency (one_way);
3091 /* back to settings page */
3092 notebook.set_current_page (0);
3097 EngineControl::on_delete_event (GdkEventAny* ev)
3099 if (notebook.get_current_page() == 2) {
3100 /* currently on latency tab - be sure to clean up */
3101 end_latency_detection ();
3103 return ArdourDialog::on_delete_event (ev);
3107 EngineControl::engine_running ()
3109 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3112 set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
3113 sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
3115 if (backend->can_set_period_size ()) {
3116 set_active_text_if_present (nperiods_combo, to_string (backend->period_size()));
3119 connect_disconnect_button.set_label (string_compose (_("Disconnect from %1"), backend->name()));
3120 connect_disconnect_button.show();
3122 started_at_least_once = true;
3123 if (_have_control) {
3124 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Running")));
3126 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Connected")));
3128 update_sensitivity();
3132 EngineControl::engine_stopped ()
3134 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3137 connect_disconnect_button.set_label (string_compose (_("Connect to %1"), backend->name()));
3138 connect_disconnect_button.show();
3140 if (_have_control) {
3141 engine_status.set_markup(string_compose ("<span foreground=\"red\">%1</span>", _("Stopped")));
3143 engine_status.set_markup(X_(""));
3146 update_sensitivity();
3150 EngineControl::device_list_changed ()
3152 if (ignore_device_changes) {
3155 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1); // ??
3156 if (!ARDOUR::AudioEngine::instance()->running()) {
3160 midi_option_changed();
3162 if (notebook.get_current_page() == midi_tab) {
3163 if (_midi_devices.empty ()) {
3164 notebook.set_current_page (0);
3166 refresh_midi_display ();
3172 EngineControl::connect_disconnect_click()
3174 if (ARDOUR::AudioEngine::instance()->running()) {
3177 if (!ARDOUR_UI::instance()->the_session ()) {
3183 if (!ARDOUR_UI::instance()->the_session ()) {
3184 ArdourDialog::on_response (RESPONSE_OK);
3190 EngineControl::calibrate_audio_latency ()
3192 _measure_midi.reset ();
3193 have_lm_results = false;
3194 lm_use_button.set_sensitive (false);
3195 lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
3196 notebook.set_current_page (latency_tab);
3200 EngineControl::calibrate_midi_latency (MidiDeviceSettings s)
3203 have_lm_results = false;
3204 lm_use_button.set_sensitive (false);
3205 lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
3206 notebook.set_current_page (latency_tab);
3210 EngineControl::configure_midi_devices ()
3212 notebook.set_current_page (midi_tab);