Update GPL boilerplate and (C)
[ardour.git] / gtk2_ardour / engine_dialog.cc
1 /*
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>
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #include <exception>
26 #include <vector>
27 #include <cmath>
28 #include <map>
29
30 #include <boost/scoped_ptr.hpp>
31
32 #include <gtkmm/messagedialog.h>
33
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"
39
40 #include <gtkmm/alignment.h>
41 #include <gtkmm/stock.h>
42 #include <gtkmm/notebook.h>
43 #include <gtkmm2ext/utils.h>
44
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"
52
53 #include "pbd/convert.h"
54 #include "pbd/error.h"
55
56 #include "opts.h"
57 #include "debug.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"
63 #include "utils.h"
64 #include "pbd/i18n.h"
65 #include "splash.h"
66
67 using namespace std;
68 using namespace Gtk;
69 using namespace Gtkmm2ext;
70 using namespace PBD;
71 using namespace Glib;
72 using namespace ArdourWidgets;
73 using namespace ARDOUR_UI_UTILS;
74
75 #define DEBUG_ECONTROL(msg) DEBUG_TRACE (PBD::DEBUG::EngineControl, string_compose ("%1: %2\n", __LINE__, msg));
76
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 */
79
80 static const char* results_markup = X_("<span weight=\"bold\" size=\"larger\">%1</span>");
81
82 EngineControl::EngineControl ()
83         : ArdourDialog (_("Audio/MIDI Setup"))
84         , engine_status ("")
85         , basic_packer (9, 4)
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"))
105         , lm_table (12, 3)
106         , have_lm_results (false)
107         , lm_running (false)
108         , midi_back_button (_("Back to settings"))
109         , ignore_changes (0)
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)
115         , block_signals(0)
116 {
117         using namespace Notebook_Helpers;
118         vector<string> backend_names;
119         Label* label;
120         AttachOptions xopt = AttachOptions (FILL|EXPAND);
121         int row;
122
123         set_name (X_("AudioMIDISetup"));
124
125         /* the backend combo is the one thing that is ALWAYS visible */
126
127         vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
128
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));
131                 msg.run ();
132                 throw failed_constructor ();
133         }
134
135         for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
136                 backend_names.push_back ((*b)->name);
137         }
138
139         set_popdown_strings (backend_combo, backend_names);
140
141         /* setup basic packing characteristics for the table used on the main
142          * tab of the notebook
143          */
144
145         basic_packer.set_spacings (6);
146         basic_packer.set_border_width (12);
147         basic_packer.set_homogeneous (false);
148
149         /* pack it in */
150
151         basic_hbox.pack_start (basic_packer, false, false);
152
153         /* latency measurement tab */
154
155         lm_title.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Latency Measurement Tool")));
156
157         row = 0;
158         lm_table.set_row_spacings (12);
159         lm_table.set_col_spacings (6);
160         lm_table.set_homogeneous (false);
161
162         lm_table.attach (lm_title, 0, 3, row, row+1, xopt, (AttachOptions) 0);
163         row++;
164
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>"));
168
169         lm_table.attach (lm_preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
170         row++;
171
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."));
177
178         lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
179         row++;
180
181         label = manage (new Label (_("Output channel:")));
182         lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
183
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);
187
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);
191         ++row;
192
193         label = manage (new Label (_("Input channel:")));
194         lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
195
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);
199
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);
203         ++row;
204
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));
211
212         lm_use_button.set_sensitive (false);
213
214         /* Increase the default spacing around the labels of these three
215          * buttons
216          */
217
218         Gtk::Misc* l;
219
220         if ((l = dynamic_cast<Gtk::Misc*>(lm_use_button.get_child())) != 0) {
221                 l->set_padding (10, 10);
222         }
223
224         if ((l = dynamic_cast<Gtk::Misc*>(lm_back_button.get_child())) != 0) {
225                 l->set_padding (10, 10);
226         }
227
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);
233         row++;
234
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);
240
241         ++row; // skip a row in the table
242         ++row; // skip a row in the table
243
244         lm_table.attach (lm_results, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
245
246         ++row; // skip a row in the table
247         ++row; // skip a row in the table
248
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);
252
253         lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
254
255         lm_vbox.set_border_width (12);
256         lm_vbox.pack_start (lm_table, false, false);
257
258         midi_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
259
260         /* pack it all up */
261
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);
266
267         notebook.set_show_tabs (false);
268         notebook.show_all ();
269
270         notebook.set_name ("SettingsNotebook");
271
272         /* packup the notebook */
273
274         get_vbox()->set_border_width (12);
275         get_vbox()->pack_start (notebook);
276
277         /* need a special function to print "all available channels" when the
278          * channel counts hit zero.
279          */
280
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));
283
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);
287
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 ();
292
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);
299
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);
304
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);
309
310         /* Pick up any existing audio setup configuration, if appropriate */
311
312         XMLNode* audio_setup = ARDOUR::Config->extra_xml ("AudioMIDISetup");
313
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());
318
319         if (audio_setup) {
320                 if (!set_state (*audio_setup)) {
321                         set_default_state ();
322                 }
323         } else {
324                 set_default_state ();
325         }
326
327         update_sensitivity ();
328         connect_changed_signals ();
329
330         notebook.signal_switch_page().connect (sigc::mem_fun (*this, &EngineControl::on_switch_page));
331
332         connect_disconnect_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::connect_disconnect_click));
333
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();
339 }
340
341 void
342 EngineControl::connect_changed_signals ()
343 {
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));
358
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));
363
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));
372 }
373
374 void
375 EngineControl::block_changed_signals ()
376 {
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 ();
392         }
393 }
394
395 void
396 EngineControl::unblock_changed_signals ()
397 {
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 ();
413         }
414 }
415
416 EngineControl::SignalBlocker::SignalBlocker (EngineControl& engine_control,
417                                              const std::string& reason)
418         : ec (engine_control)
419         , m_reason (reason)
420 {
421         DEBUG_ECONTROL (string_compose ("SignalBlocker: %1", m_reason));
422         ec.block_changed_signals ();
423 }
424
425 EngineControl::SignalBlocker::~SignalBlocker ()
426 {
427         DEBUG_ECONTROL (string_compose ("~SignalBlocker: %1", m_reason));
428         ec.unblock_changed_signals ();
429 }
430
431 void
432 EngineControl::on_show ()
433 {
434         ArdourDialog::on_show ();
435         if (!ARDOUR::AudioEngine::instance()->current_backend() || !ARDOUR::AudioEngine::instance()->running()) {
436                 // re-check _have_control (jackd running) see #6041
437                 backend_changed ();
438         }
439         device_changed ();
440         start_stop_button.grab_focus();
441 }
442
443 void
444 EngineControl::on_map ()
445 {
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);
450         } else {
451                 set_type_hint (Gdk::WINDOW_TYPE_HINT_UTILITY);
452         }
453         ArdourDialog::on_map ();
454 }
455
456 bool
457 EngineControl::try_autostart ()
458 {
459         if (!start_stop_button.get_sensitive()) {
460                 return false;
461         }
462         if (ARDOUR::AudioEngine::instance()->running()) {
463                 return true;
464         }
465         return start_engine ();
466 }
467
468 bool
469 EngineControl::start_engine ()
470 {
471         if (push_state_to_backend(true) != 0) {
472                 MessageDialog msg(*this,
473                                   ARDOUR::AudioEngine::instance()->get_last_backend_error());
474                 msg.run();
475                 return false;
476         }
477         return true;
478 }
479
480 bool
481 EngineControl::stop_engine (bool for_latency)
482 {
483         if (ARDOUR::AudioEngine::instance()->stop(for_latency)) {
484                 MessageDialog msg(*this,
485                                   ARDOUR::AudioEngine::instance()->get_last_backend_error());
486                 msg.run();
487                 return false;
488         }
489         return true;
490 }
491
492 void
493 EngineControl::build_notebook ()
494 {
495         Label* label;
496         AttachOptions xopt = AttachOptions (FILL|EXPAND);
497
498         /* clear the table */
499
500         Gtkmm2ext::container_clear (basic_vbox);
501         Gtkmm2ext::container_clear (basic_packer);
502
503         if (control_app_button.get_parent()) {
504                 control_app_button.get_parent()->remove (control_app_button);
505         }
506
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);
510
511         basic_packer.attach (engine_status, 2, 3, 0, 1, xopt, (AttachOptions) 0);
512         engine_status.show();
513
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);
517
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);
521
522         if (_have_control) {
523                 build_full_control_notebook ();
524         } else {
525                 build_no_control_notebook ();
526         }
527
528         basic_vbox.pack_start (basic_hbox, false, false);
529
530         {
531                 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
532                 basic_vbox.show_all ();
533         }
534 }
535
536 void
537 EngineControl::build_full_control_notebook ()
538 {
539         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
540         assert (backend);
541
542         using namespace Notebook_Helpers;
543         Label* label;
544         vector<string> strings;
545         AttachOptions xopt = AttachOptions (FILL|EXPAND);
546         int row = 1; // row zero == backend combo
547
548         /* start packing it up */
549
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);
554                 row++;
555         }
556
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);
561                 row++;
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);
565                 row++;
566                 // reset so it isn't used in state comparisons
567                 device_combo.set_active_text ("");
568         } else {
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);
572                 row++;
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 ("");
576         }
577
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);
581         row++;
582
583
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);
589
590         int ctrl_btn_span = 1;
591         if (backend->can_set_period_size ()) {
592                 row++;
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);
596                 ++ctrl_btn_span;
597         }
598
599         /* button spans 2 or 3 rows */
600
601         basic_packer.attach (control_app_button, 3, 4, row - ctrl_btn_span, row + 1, xopt, xopt);
602         row++;
603
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);
609
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);
614                 ++row;
615         }
616
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);
622
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);
627                 ++row;
628         }
629
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);
635
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);
641         ++row;
642
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);
648
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);
654
655         /* button spans 2 rows */
656
657         basic_packer.attach (lm_button_audio, 3, 4, row-1, row+1, xopt, xopt);
658         ++row;
659
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);
664         row++;
665 }
666
667 void
668 EngineControl::build_no_control_notebook ()
669 {
670         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
671         assert (backend);
672
673         using namespace Notebook_Helpers;
674         Label* label;
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);
679
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);
683         row++;
684
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);
689                 row++;
690         }
691
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);
698                 row++;
699         }
700
701         basic_packer.attach (connect_disconnect_button, 0, 2, row, row+1, FILL, AttachOptions (0));
702         row++;
703 }
704
705 EngineControl::~EngineControl ()
706 {
707         ignore_changes = true;
708 }
709
710 void
711 EngineControl::disable_latency_tab ()
712 {
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);
717 }
718
719 void
720 EngineControl::enable_latency_tab ()
721 {
722         vector<string> outputs;
723         vector<string> inputs;
724
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);
728
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);
732                 msg.run ();
733                 return;
734         }
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);
738                 msg.run ();
739                 return;
740         }
741
742         lm_back_button_signal.disconnect();
743         if (_measure_midi) {
744                 lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), midi_tab));
745                 lm_preamble.hide ();
746         } else {
747                 lm_back_button_signal = lm_back_button.signal_clicked().connect(
748                     sigc::mem_fun(*this, &EngineControl::latency_back_button_clicked));
749                 lm_preamble.show ();
750         }
751
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);
758         }
759         lm_output_channel_combo.set_active (0);
760         lm_output_channel_combo.set_sensitive (true);
761
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);
768         }
769         lm_input_channel_combo.set_active (0);
770         lm_input_channel_combo.set_sensitive (true);
771
772         lm_measure_button.set_sensitive (true);
773 }
774
775 void
776 EngineControl::setup_midi_tab_for_backend ()
777 {
778         string backend = backend_combo.get_active_text ();
779
780         Gtkmm2ext::container_clear (midi_vbox);
781
782         midi_vbox.set_border_width (12);
783         midi_device_table.set_border_width (12);
784
785         if (backend == "JACK") {
786                 setup_midi_tab_for_jack ();
787         }
788
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 ();
792 }
793
794 void
795 EngineControl::update_sensitivity ()
796 {
797         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
798         if (!backend) {
799                 start_stop_button.set_sensitive (false);
800                 return;
801         }
802
803         bool valid = true;
804         size_t devices_available = 0;
805         bool engine_running = ARDOUR::AudioEngine::instance()->running();
806
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);
810         } else {
811                 devices_available += get_popdown_string_count (device_combo);
812         }
813
814         if (devices_available == 0) {
815                 valid = false;
816                 input_latency.set_sensitive (false);
817                 output_latency.set_sensitive (false);
818                 input_channels.set_sensitive (false);
819                 output_channels.set_sensitive (false);
820         } else {
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);
825         }
826
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);
832                 } else {
833                         buffer_size_combo.set_sensitive (false);
834                 }
835         } else {
836                 buffer_size_combo.set_sensitive (false);
837                 valid = false;
838         }
839
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;
849                         }
850                 }
851                 sample_rate_combo.set_sensitive (allow_to_set_rate);
852         } else {
853                 sample_rate_combo.set_sensitive (false);
854                 valid = false;
855         }
856
857         if (get_popdown_string_count (nperiods_combo) > 0) {
858                 if (!engine_running) {
859                         nperiods_combo.set_sensitive (true);
860                 } else {
861                         nperiods_combo.set_sensitive (false);
862                 }
863         } else {
864                 nperiods_combo.set_sensitive (false);
865         }
866
867         if (_have_control) {
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);
874                 } else {
875                         if (backend->can_request_update_devices()) {
876                                 update_devices_button.show();
877                         } else {
878                                 update_devices_button.hide();
879                         }
880                         if (backend->can_use_buffered_io()) {
881                                 use_buffered_io_button.show();
882                         } else {
883                                 use_buffered_io_button.hide();
884                         }
885                         start_stop_button.set_text("Start");
886                         update_devices_button.set_sensitive(true);
887                         use_buffered_io_button.set_sensitive(true);
888                 }
889         } else {
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();
896         }
897
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);
903         } else {
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);
909                 } else {
910                         driver_combo.set_sensitive (false);
911                 }
912         }
913
914         midi_option_combo.set_sensitive (!engine_running);
915 }
916
917 void
918 EngineControl::setup_midi_tab_for_jack ()
919 {
920 }
921
922 void
923 EngineControl::midi_latency_adjustment_changed (Gtk::Adjustment *a, MidiDeviceSettings device, bool for_input) {
924         if (for_input) {
925                 device->input_latency = a->get_value();
926         } else {
927                 device->output_latency = a->get_value();
928         }
929
930         if (ARDOUR::AudioEngine::instance()->running() && !_measure_midi) {
931                 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
932                 assert (backend);
933                 if (backend->can_change_systemic_latency_when_running () && device->enabled) {
934                         if (for_input) {
935                                 backend->set_systemic_midi_input_latency (device->name, device->input_latency);
936                         } else {
937                                 backend->set_systemic_midi_output_latency (device->name, device->output_latency);
938                         }
939                 }
940         }
941 }
942
943 void
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);
948
949         if (ARDOUR::AudioEngine::instance()->running()) {
950                 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
951                 assert (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);
956                 }
957         }
958 }
959
960 void
961 EngineControl::refresh_midi_display (std::string focus)
962 {
963         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
964         assert (backend);
965
966         int row  = 0;
967         AttachOptions xopt = AttachOptions (FILL|EXPAND);
968         Gtk::Label* l;
969
970         Gtkmm2ext::container_clear (midi_device_table);
971
972         midi_device_table.set_spacings (6);
973
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);
978         row++;
979         l->show ();
980
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));
985         row++;
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));
990         row++;
991
992         for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
993                 ArdourButton *m;
994                 Gtk::Button* b;
995                 Gtk::Adjustment *a;
996                 Gtk::SpinButton *s;
997                 bool enabled = (*p)->enabled;
998
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) {
1007                         m->grab_focus();
1008                 }
1009
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 ();
1016
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 ();
1023
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 ();
1028
1029                 row++;
1030         }
1031 }
1032
1033 void
1034 EngineControl::backend_changed ()
1035 {
1036         SignalBlocker blocker (*this, "backend_changed");
1037         string backend_name = backend_combo.get_active_text();
1038         boost::shared_ptr<ARDOUR::AudioBackend> backend;
1039
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 */
1043                 return;
1044         }
1045
1046         DEBUG_ECONTROL (string_compose ("Backend name: %1", backend_name));
1047
1048         _have_control = ARDOUR::AudioEngine::instance()->setup_required ();
1049
1050         build_notebook ();
1051         setup_midi_tab_for_backend ();
1052         _midi_devices.clear();
1053
1054         if (backend->requires_driver_selection()) {
1055                 if (set_driver_popdown_strings ()) {
1056                         driver_changed ();
1057                 }
1058         } else {
1059                 /* this will change the device text which will cause a call to
1060                  * device changed which will set up parameters
1061                  */
1062                 list_devices ();
1063         }
1064
1065         update_midi_options ();
1066
1067         connect_disconnect_button.hide();
1068
1069         midi_option_changed();
1070
1071         started_at_least_once = false;
1072
1073         /* changing the backend implies stopping the engine
1074          * ARDOUR::AudioEngine() may or may not emit this signal
1075          * depending on previous engine state
1076          */
1077         engine_stopped (); // set "active/inactive"
1078
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()));
1083         }
1084
1085         if (_have_control && !ignore_changes) {
1086                 // set driver & devices
1087                 State state = get_matching_state (backend_combo.get_active_text());
1088                 if (state) {
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);
1092                 } else {
1093                         DEBUG_ECONTROL ("backend-changed(): no prior state for backend");
1094                 }
1095         } else {
1096                 DEBUG_ECONTROL (string_compose ("backend-changed(): _have_control=%1 ignore_changes=%2", _have_control, ignore_changes));
1097         }
1098
1099         if (!ignore_changes) {
1100                 maybe_display_saved_state ();
1101         }
1102 }
1103
1104 void
1105 EngineControl::update_midi_options ()
1106 {
1107         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1108         vector<string> midi_options = backend->enumerate_midi_options();
1109
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);
1114         } else {
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);
1119                 } else {
1120                         midi_option_combo.set_sensitive (false);
1121                 }
1122         }
1123 }
1124
1125 bool
1126 EngineControl::print_channel_count (Gtk::SpinButton* sb)
1127 {
1128         if (ARDOUR::Profile->get_mixbus()) {
1129                 return true;
1130         }
1131
1132         uint32_t cnt = (uint32_t) sb->get_value();
1133         if (cnt == 0) {
1134                 sb->set_text (_("all available channels"));
1135         } else {
1136                 char buf[32];
1137                 snprintf (buf, sizeof (buf), "%d", cnt);
1138                 sb->set_text (buf);
1139         }
1140         return true;
1141 }
1142
1143 // @return true if there are drivers available
1144 bool
1145 EngineControl::set_driver_popdown_strings ()
1146 {
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();
1150
1151         if (drivers.empty ()) {
1152                 // This is an error...?
1153                 return false;
1154         }
1155
1156         string current_driver = backend->driver_name ();
1157
1158         DEBUG_ECONTROL (string_compose ("backend->driver_name: %1", current_driver));
1159
1160         if (std::find (drivers.begin (), drivers.end (), current_driver) ==
1161             drivers.end ()) {
1162
1163                 current_driver = drivers.front ();
1164         }
1165
1166         set_popdown_strings (driver_combo, drivers);
1167         DEBUG_ECONTROL (
1168             string_compose ("driver_combo.set_active_text: %1", current_driver));
1169         driver_combo.set_active_text (current_driver);
1170         return true;
1171 }
1172
1173 std::string
1174 EngineControl::get_default_device(const string& current_device_name,
1175                                   const vector<string>& available_devices)
1176 {
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 ()) {
1181
1182                 return current_device_name;
1183         }
1184
1185         using namespace ARDOUR;
1186
1187         string default_device_name =
1188             AudioBackend::get_standard_device_name(AudioBackend::DeviceDefault);
1189
1190         vector<string>::const_iterator i;
1191
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) {
1195                         return *i;
1196                 }
1197         }
1198
1199         string none_device_name =
1200             AudioBackend::get_standard_device_name(AudioBackend::DeviceNone);
1201
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) {
1205                         return *i;
1206                 }
1207         }
1208
1209         // Use "None" if there are no other available
1210         return available_devices.front();
1211 }
1212
1213 // @return true if there are devices available
1214 bool
1215 EngineControl::set_device_popdown_strings ()
1216 {
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 ();
1220
1221         /* NOTE: Ardour currently does not display the "available" field of the
1222          * returned devices.
1223          *
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.
1228          */
1229
1230         vector<string> available_devices;
1231
1232         for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1233                 available_devices.push_back (i->name);
1234         }
1235
1236         if (available_devices.empty ()) {
1237                 return false;
1238         }
1239
1240         set_popdown_strings (device_combo, available_devices);
1241
1242         std::string default_device =
1243             get_default_device(backend->device_name(), available_devices);
1244
1245         DEBUG_ECONTROL (
1246             string_compose ("set device_combo active text: %1", default_device));
1247
1248         device_combo.set_active_text(default_device);
1249         return true;
1250 }
1251
1252 // @return true if there are input devices available
1253 bool
1254 EngineControl::set_input_device_popdown_strings ()
1255 {
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 ();
1259
1260         vector<string> available_devices;
1261
1262         for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1263                 available_devices.push_back (i->name);
1264         }
1265
1266         if (available_devices.empty()) {
1267                 return false;
1268         }
1269
1270         set_popdown_strings (input_device_combo, available_devices);
1271
1272         std::string default_device =
1273             get_default_device(backend->input_device_name(), available_devices);
1274
1275         DEBUG_ECONTROL (
1276             string_compose ("set input_device_combo active text: %1", default_device));
1277         input_device_combo.set_active_text(default_device);
1278         return true;
1279 }
1280
1281 // @return true if there are output devices available
1282 bool
1283 EngineControl::set_output_device_popdown_strings ()
1284 {
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 ();
1288
1289         vector<string> available_devices;
1290
1291         for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1292                 available_devices.push_back (i->name);
1293         }
1294
1295         if (available_devices.empty()) {
1296                 return false;
1297         }
1298
1299         set_popdown_strings (output_device_combo, available_devices);
1300
1301         std::string default_device =
1302             get_default_device(backend->output_device_name(), available_devices);
1303
1304         DEBUG_ECONTROL (
1305             string_compose ("set output_device_combo active text: %1", default_device));
1306         output_device_combo.set_active_text(default_device);
1307         return true;
1308 }
1309
1310 void
1311 EngineControl::list_devices ()
1312 {
1313         DEBUG_ECONTROL ("list_devices");
1314         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1315         assert (backend);
1316
1317         /* now fill out devices, mark sample rates, buffer sizes insensitive */
1318
1319         bool devices_available = false;
1320
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;
1325         } else {
1326                 devices_available = set_device_popdown_strings ();
1327         }
1328
1329         if (devices_available) {
1330                 device_changed ();
1331         } else {
1332                 device_combo.clear();
1333                 input_device_combo.clear();
1334                 output_device_combo.clear();
1335         }
1336         update_sensitivity ();
1337 }
1338
1339 void
1340 EngineControl::driver_changed ()
1341 {
1342         SignalBlocker blocker (*this, "driver_changed");
1343         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1344         assert (backend);
1345
1346         backend->set_driver (driver_combo.get_active_text());
1347         list_devices ();
1348
1349         // TODO load LRU device(s) for backend + driver combo
1350
1351         if (!ignore_changes) {
1352                 maybe_display_saved_state ();
1353         }
1354 }
1355
1356 vector<float>
1357 EngineControl::get_sample_rates_for_all_devices ()
1358 {
1359         boost::shared_ptr<ARDOUR::AudioBackend> backend =
1360             ARDOUR::AudioEngine::instance ()->current_backend ();
1361         vector<float> all_rates;
1362
1363         if (backend->use_separate_input_and_output_devices ()) {
1364                 all_rates = backend->available_sample_rates2 (get_input_device_name (), get_output_device_name ());
1365         } else {
1366                 all_rates = backend->available_sample_rates (get_device_name ());
1367         }
1368         return all_rates;
1369 }
1370
1371 vector<float>
1372 EngineControl::get_default_sample_rates ()
1373 {
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);
1384         return rates;
1385 }
1386
1387 void
1388 EngineControl::set_samplerate_popdown_strings ()
1389 {
1390         DEBUG_ECONTROL ("set_samplerate_popdown_strings");
1391         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1392         string desired;
1393         vector<float> sr;
1394         vector<string> s;
1395
1396         if (_have_control) {
1397                 sr = get_sample_rates_for_all_devices ();
1398         } else {
1399                 sr = get_default_sample_rates ();
1400         }
1401
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) {
1405                         desired = s.back();
1406                 }
1407         }
1408
1409         set_popdown_strings (sample_rate_combo, s);
1410
1411         if (!s.empty()) {
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 ();
1416
1417                         if (std::find (sr.begin (), sr.end (), active_sr) == sr.end ()) {
1418                                 active_sr = sr.front ();
1419                         }
1420
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 ();
1424
1425                         if (std::find (sr.begin (), sr.end (), new_active_sr) == sr.end ()) {
1426                                 new_active_sr = sr.front ();
1427                         }
1428
1429                         sample_rate_combo.set_active_text (rate_as_string (new_active_sr));
1430                 } else {
1431                         sample_rate_combo.set_active_text (desired);
1432                 }
1433         }
1434         update_sensitivity ();
1435 }
1436
1437 vector<uint32_t>
1438 EngineControl::get_buffer_sizes_for_all_devices ()
1439 {
1440         boost::shared_ptr<ARDOUR::AudioBackend> backend =
1441             ARDOUR::AudioEngine::instance ()->current_backend ();
1442         vector<uint32_t> all_sizes;
1443
1444         if (backend->use_separate_input_and_output_devices ()) {
1445                 all_sizes = backend->available_buffer_sizes2 (get_input_device_name (), get_output_device_name ());
1446         } else {
1447                 all_sizes = backend->available_buffer_sizes (get_device_name ());
1448         }
1449         return all_sizes;
1450 }
1451
1452 vector<uint32_t>
1453 EngineControl::get_default_buffer_sizes ()
1454 {
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);
1467         return sizes;
1468 }
1469
1470 void
1471 EngineControl::set_buffersize_popdown_strings ()
1472 {
1473         DEBUG_ECONTROL ("set_buffersize_popdown_strings");
1474         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1475         vector<uint32_t> bs;
1476         vector<string> s;
1477
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 ();
1482         }
1483
1484         for (vector<uint32_t>::const_iterator x = bs.begin(); x != bs.end(); ++x) {
1485                 s.push_back (bufsize_as_string (*x));
1486         }
1487
1488         uint32_t previous_size = backend->buffer_size ();
1489         if (!buffer_size_combo.get_active_text().empty()) {
1490                 previous_size = get_buffer_size ();
1491         }
1492
1493         set_popdown_strings (buffer_size_combo, s);
1494
1495         if (!s.empty()) {
1496
1497                 if (std::find(bs.begin(), bs.end(), previous_size) != bs.end()) {
1498                         buffer_size_combo.set_active_text(bufsize_as_string(previous_size));
1499                 } else {
1500
1501                         buffer_size_combo.set_active_text(s.front());
1502
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());
1506                         }
1507                         if (0 == period && backend->use_separate_input_and_output_devices()) {
1508                                 period = backend->default_buffer_size(get_output_device_name());
1509                         }
1510                         if (0 == period && !backend->use_separate_input_and_output_devices()) {
1511                                 period = backend->default_buffer_size(get_device_name());
1512                         }
1513
1514                         set_active_text_if_present(buffer_size_combo, bufsize_as_string(period));
1515                 }
1516                 show_buffer_duration ();
1517         }
1518         update_sensitivity ();
1519 }
1520
1521 void
1522 EngineControl::set_nperiods_popdown_strings ()
1523 {
1524         DEBUG_ECONTROL ("set_nperiods_popdown_strings");
1525         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1526         vector<uint32_t> np;
1527         vector<string> s;
1528
1529         if (backend->can_set_period_size()) {
1530                 np = backend->available_period_sizes (get_driver());
1531         }
1532
1533         for (vector<uint32_t>::const_iterator x = np.begin(); x != np.end(); ++x) {
1534                 s.push_back (to_string (*x));
1535         }
1536
1537         set_popdown_strings (nperiods_combo, s);
1538
1539         if (!s.empty()) {
1540                 set_active_text_if_present (nperiods_combo, to_string (backend->period_size())); // XXX
1541         }
1542
1543         update_sensitivity ();
1544 }
1545
1546 void
1547 EngineControl::device_changed ()
1548 {
1549         SignalBlocker blocker (*this, "device_changed");
1550         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1551         assert (backend);
1552
1553         string device_name_in;
1554         string device_name_out; // only used if backend support separate I/O devices
1555
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 ();
1559         } else {
1560                 device_name_in = get_device_name ();
1561         }
1562
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...
1567          */
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;
1571                 }
1572         } else {
1573                 if (device_name_in != backend->device_name()) {
1574                         queue_device_changed = true;
1575                 }
1576         }
1577
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);
1582         } else {
1583                 backend->set_device_name(device_name_in);
1584         }
1585
1586         {
1587                 /* don't allow programmatic change to combos to cause a
1588                    recursive call to this method.
1589                  */
1590                 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1591
1592                 set_samplerate_popdown_strings ();
1593                 set_buffersize_popdown_strings ();
1594                 set_nperiods_popdown_strings ();
1595
1596                 /* TODO set min + max channel counts here */
1597
1598                 manage_control_app_sensitivity ();
1599         }
1600
1601         /* pick up any saved state for this device */
1602
1603         if (!ignore_changes) {
1604                 maybe_display_saved_state ();
1605         }
1606 }
1607
1608 void
1609 EngineControl::input_device_changed ()
1610 {
1611         DEBUG_ECONTROL ("input_device_changed");
1612
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);
1616
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 ());
1623                         } else {
1624                                 assert (contains_value (output_device_combo, dev_none));
1625                                 output_device_combo.set_active_text (dev_none);
1626                         }
1627                         unblock_changed_signals ();
1628                 }
1629         }
1630         device_changed ();
1631 }
1632
1633 void
1634 EngineControl::output_device_changed ()
1635 {
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);
1640
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 ());
1647                         } else {
1648                                 assert (contains_value (input_device_combo, dev_none));
1649                                 input_device_combo.set_active_text (dev_none);
1650                         }
1651                         unblock_changed_signals ();
1652                 }
1653         }
1654         device_changed ();
1655 }
1656
1657 string
1658 EngineControl::bufsize_as_string (uint32_t sz)
1659 {
1660         return string_compose (P_("%1 sample", "%1 samples", sz), to_string(sz));
1661 }
1662
1663 void
1664 EngineControl::sample_rate_changed ()
1665 {
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).
1669          */
1670
1671         show_buffer_duration ();
1672
1673 }
1674
1675 void
1676 EngineControl::buffer_size_changed ()
1677 {
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());
1683                 }
1684         }
1685         show_buffer_duration ();
1686 }
1687
1688 void
1689 EngineControl::nperiods_changed ()
1690 {
1691         DEBUG_ECONTROL ("nperiods_changed");
1692         show_buffer_duration ();
1693 }
1694
1695 void
1696 EngineControl::show_buffer_duration ()
1697 {
1698         DEBUG_ECONTROL ("show_buffer_duration");
1699         /* buffer sizes  - convert from just samples to samples + msecs for
1700          * the displayed string
1701          */
1702
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();
1706
1707         /* Except for ALSA and Dummy backends, we don't know the number of periods
1708          * per cycle and settings.
1709          *
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..
1713          *
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)
1718          */
1719         char buf[32];
1720         snprintf (buf, sizeof (buf), _("(%.1f ms)"), (samples / (rate/1000.0f)));
1721         buffer_size_duration_label.set_text (buf);
1722 }
1723
1724 void
1725 EngineControl::midi_option_changed ()
1726 {
1727         DEBUG_ECONTROL ("midi_option_changed");
1728         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1729         assert (backend);
1730
1731         backend->set_midi_option (get_midi_option());
1732
1733         vector<ARDOUR::AudioBackend::DeviceStatus> midi_devices = backend->enumerate_midi_devices();
1734
1735         _can_set_midi_latencies = backend->can_set_systemic_midi_latencies();
1736         std::vector<MidiDeviceSettings> new_devices;
1737
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);
1746                         }
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);
1752                 }
1753         }
1754         _midi_devices = new_devices;
1755
1756         if (_midi_devices.empty()) {
1757                 midi_devices_button.hide ();
1758         } else {
1759                 midi_devices_button.show ();
1760         }
1761 }
1762
1763 void
1764 EngineControl::parameter_changed ()
1765 {
1766 }
1767
1768 EngineControl::State
1769 EngineControl::get_matching_state (const string& backend)
1770 {
1771         for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1772                 if ((*i)->backend == backend) {
1773                         return (*i);
1774                 }
1775         }
1776         return State();
1777 }
1778
1779 EngineControl::State
1780 EngineControl::get_matching_state (
1781                 const string& backend,
1782                 const string& driver,
1783                 const string& device)
1784 {
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)))
1788                 {
1789                         return (*i);
1790                 }
1791         }
1792         return State();
1793 }
1794
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)
1801 {
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)))
1805                 {
1806                         return (*i);
1807                 }
1808         }
1809         return State();
1810 }
1811
1812 EngineControl::State
1813 EngineControl::get_saved_state_for_currently_displayed_backend_and_device ()
1814 {
1815         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1816
1817         if (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());
1823                 } else {
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());
1827                 }
1828         }
1829
1830         return get_matching_state (backend_combo.get_active_text(),
1831                         string(),
1832                         device_combo.get_active_text());
1833 }
1834
1835 bool EngineControl::equivalent_states (const EngineControl::State& state1,
1836                                        const EngineControl::State& state2)
1837 {
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) {
1843                 return true;
1844         }
1845         return false;
1846 }
1847
1848 // sort active first, then most recently used to the beginning of the list
1849 bool
1850 EngineControl::state_sort_cmp (const State &a, const State &b) {
1851         if (a->active) {
1852                 return true;
1853         }
1854         else if (b->active) {
1855                 return false;
1856         }
1857         else {
1858                 return a->lru > b->lru;
1859         }
1860 }
1861
1862 EngineControl::State
1863 EngineControl::save_state ()
1864 {
1865         State state;
1866
1867         if (!_have_control) {
1868                 state = get_matching_state (backend_combo.get_active_text(), string(), string());
1869                 if (state) {
1870                         state->lru = time (NULL) ;
1871                         return state;
1872                 }
1873                 state.reset(new StateStruct);
1874                 state->backend = get_backend ();
1875         } else {
1876                 state.reset(new StateStruct);
1877                 store_state (state);
1878         }
1879
1880         for (StateList::iterator i = states.begin(); i != states.end();) {
1881                 if (equivalent_states (*i, state)) {
1882                         i =  states.erase(i);
1883                 } else {
1884                         ++i;
1885                 }
1886         }
1887
1888         states.push_back (state);
1889
1890         states.sort (state_sort_cmp);
1891
1892         return state;
1893 }
1894
1895 void
1896 EngineControl::store_state (State state)
1897 {
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) ;
1914 }
1915
1916 void
1917 EngineControl::maybe_display_saved_state ()
1918 {
1919         if (!_have_control || ARDOUR::AudioEngine::instance()->running ()) {
1920                 return;
1921         }
1922
1923         State state = get_saved_state_for_currently_displayed_backend_and_device ();
1924
1925         if (state) {
1926                 DEBUG_ECONTROL ("Restoring saved state");
1927                 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1928
1929                 if (0 == _desired_sample_rate && sample_rate_combo.get_sensitive ()) {
1930                         sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
1931                 }
1932                 set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
1933
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.
1937                  */
1938                 show_buffer_duration ();
1939                 input_latency.set_value (state->input_latency);
1940                 output_latency.set_value (state->output_latency);
1941
1942                 use_buffered_io_button.set_active (state->use_buffered_io);
1943
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 ();
1948                 }
1949         } else {
1950                 DEBUG_ECONTROL ("Unable to find saved state for backend and devices");
1951         }
1952 }
1953
1954 XMLNode&
1955 EngineControl::get_state ()
1956 {
1957         LocaleGuard lg;
1958
1959         XMLNode* root = new XMLNode ("AudioMIDISetup");
1960         std::string path;
1961
1962         if (!states.empty()) {
1963                 XMLNode* state_nodes = new XMLNode ("EngineStates");
1964
1965                 for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
1966
1967                         XMLNode* node = new XMLNode ("State");
1968
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 );
1986
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);
1995                         }
1996                         node->add_child_nocopy (*midi_devices);
1997
1998                         state_nodes->add_child_nocopy (*node);
1999                 }
2000
2001                 root->add_child_nocopy (*state_nodes);
2002         }
2003
2004         return *root;
2005 }
2006
2007 void
2008 EngineControl::set_default_state ()
2009 {
2010         vector<string> backend_names;
2011         vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
2012
2013         for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
2014                 backend_names.push_back ((*b)->name);
2015         }
2016         backend_combo.set_active_text (backend_names.front());
2017
2018         // We could set default backends per platform etc here
2019
2020         backend_changed ();
2021 }
2022
2023 bool
2024 EngineControl::set_state (const XMLNode& root)
2025 {
2026         XMLNodeList          clist, cclist;
2027         XMLNodeConstIterator citer, cciter;
2028         XMLNode const * child;
2029         XMLNode const * grandchild;
2030
2031         if (root.name() != "AudioMIDISetup") {
2032                 return false;
2033         }
2034
2035         clist = root.children();
2036
2037         states.clear ();
2038
2039         for (citer = clist.begin(); citer != clist.end(); ++citer) {
2040
2041                 child = *citer;
2042
2043                 if (child->name() != "EngineStates") {
2044                         continue;
2045                 }
2046
2047                 cclist = child->children();
2048
2049                 for (cciter = cclist.begin(); cciter != cclist.end(); ++cciter) {
2050                         State state (new StateStruct);
2051
2052                         grandchild = *cciter;
2053
2054                         if (grandchild->name() != "State") {
2055                                 continue;
2056                         }
2057
2058                         if (!grandchild->get_property ("backend", state->backend)) {
2059                                 continue;
2060                         }
2061
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)) {
2077                                 continue;
2078                         }
2079
2080                         if (!grandchild->get_property ("n-periods", state->n_periods)) {
2081                                 // optional (new value in 4.5)
2082                                 state->n_periods = 0;
2083                         }
2084
2085                         state->midi_devices.clear();
2086                         XMLNode* midinode;
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) {
2090                                         std::string name;
2091                                         bool enabled;
2092                                         uint32_t input_latency;
2093                                         uint32_t output_latency;
2094
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)) {
2099                                                 continue;
2100                                         }
2101
2102                                         MidiDeviceSettings ptr (
2103                                             new MidiDeviceSetting (name, enabled, input_latency, output_latency));
2104                                         state->midi_devices.push_back (ptr);
2105                                 }
2106                         }
2107
2108                         int32_t lru_val;
2109                         if (grandchild->get_property ("lru", lru_val)) {
2110                                 state->lru = lru_val;
2111                         }
2112
2113                         states.push_back (state);
2114                 }
2115         }
2116
2117         /* now see if there was an active state and switch the setup to it */
2118
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;
2122
2123         for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator i = backends.begin(); i != backends.end(); ++i) {
2124                 backend_names.push_back((*i)->name);
2125         }
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);
2129                 } else {
2130                         ++i;
2131                 }
2132         }
2133
2134         states.sort (state_sort_cmp);
2135
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) {
2139                 bool first = true;
2140                 for (StateList::iterator i = states.begin(); i != states.end();) {
2141                         if ((*i)->backend != *bi) {
2142                                 ++i; continue;
2143                         }
2144                         // keep at latest one for every audio-system
2145                         if (first) {
2146                                 first = false;
2147                                 ++i; continue;
2148                         }
2149                         // also keep states used in the last 90 days.
2150                         if ((now - (*i)->lru) < 86400 * 90) {
2151                                 ++i; continue;
2152                         }
2153                         assert (!(*i)->active);
2154                         i = states.erase(i);
2155                 }
2156         }
2157
2158         for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
2159
2160                 if ((*i)->active) {
2161                         return set_current_state (*i);
2162                 }
2163         }
2164         return false;
2165 }
2166
2167 bool
2168 EngineControl::set_current_state (const State& state)
2169 {
2170         DEBUG_ECONTROL ("set_current_state");
2171
2172         boost::shared_ptr<ARDOUR::AudioBackend> backend;
2173
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.
2179                 return false;
2180         }
2181
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);
2185
2186         if (!ARDOUR::AudioEngine::instance()->setup_required ()) {
2187                 backend_changed ();
2188                 // we don't have control don't restore state
2189                 return true;
2190         }
2191
2192
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
2198                         // it up
2199                         return false;
2200                 }
2201
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
2207                         return false;
2208                 }
2209                 // no need to set the driver_combo as backend_changed will use
2210                 // backend->driver_name to set the active driver
2211         }
2212
2213         if (!state->device.empty ()) {
2214                 if (backend->set_device_name (state->device) != 0) {
2215                         DEBUG_ECONTROL (
2216                             string_compose ("Unable to set device name %1", state->device));
2217                         // device is no longer available on the system
2218                         return false;
2219                 }
2220                 // no need to set active device as it will be picked up in
2221                 // via backend_changed ()/set_device_popdown_strings
2222
2223         } else {
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
2229                         return false;
2230                 }
2231
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
2236                         return false;
2237                 }
2238                 // no need to set active devices as it will be picked up in via
2239                 // backend_changed ()/set_*_device_popdown_strings
2240         }
2241
2242         backend_changed ();
2243
2244         // Now restore the state of the rest of the controls
2245
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.
2251
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));
2257         }
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);
2264         return true;
2265 }
2266
2267 int
2268 EngineControl::push_state_to_backend (bool start)
2269 {
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);
2273
2274         if (!backend) {
2275                 return 0;
2276         }
2277
2278         /* figure out what is going to change */
2279
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;
2291
2292         uint32_t ochan = get_output_channels ();
2293         uint32_t ichan = get_input_channels ();
2294
2295         if (_have_control) {
2296
2297                 if (started_at_least_once) {
2298
2299                         /* we can control the backend */
2300
2301                         if (backend->requires_driver_selection()) {
2302                                 if (get_driver() != backend->driver_name()) {
2303                                         change_driver = true;
2304                                 }
2305                         }
2306
2307                         if (backend->use_separate_input_and_output_devices()) {
2308                                 if (get_input_device_name() != backend->input_device_name()) {
2309                                         change_device = true;
2310                                 }
2311                                 if (get_output_device_name() != backend->output_device_name()) {
2312                                         change_device = true;
2313                                 }
2314                         } else {
2315                                 if (get_device_name() != backend->device_name()) {
2316                                         change_device = true;
2317                                 }
2318                         }
2319
2320                         if (queue_device_changed) {
2321                                 change_device = true;
2322                         }
2323
2324                         if (get_rate() != backend->sample_rate()) {
2325                                 change_rate = true;
2326                         }
2327
2328                         if (get_buffer_size() != backend->buffer_size()) {
2329                                 change_bufsize = true;
2330                         }
2331
2332                         if (backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0
2333                                         && get_nperiods() != backend->period_size()) {
2334                                 change_nperiods = true;
2335                         }
2336
2337                         if (get_midi_option() != backend->midi_option()) {
2338                                 change_midi = true;
2339                         }
2340
2341                         if (backend->can_use_buffered_io()) {
2342                                 if (get_use_buffered_io() != backend->get_use_buffered_io()) {
2343                                         change_buffered_io = true;
2344                                 }
2345                         }
2346
2347                         /* zero-requested channels means "all available" */
2348
2349                         if (ichan == 0) {
2350                                 ichan = backend->input_channels();
2351                         }
2352
2353                         if (ochan == 0) {
2354                                 ochan = backend->output_channels();
2355                         }
2356
2357                         if (ichan != backend->input_channels()) {
2358                                 change_channels = true;
2359                         }
2360
2361                         if (ochan != backend->output_channels()) {
2362                                 change_channels = true;
2363                         }
2364
2365                         if (get_input_latency() != backend->systemic_input_latency() ||
2366                                         get_output_latency() != backend->systemic_output_latency()) {
2367                                 change_latency = true;
2368                         }
2369                 } else {
2370                         /* backend never started, so we have to force a group
2371                            of settings.
2372                          */
2373                         change_device = true;
2374                         if (backend->requires_driver_selection()) {
2375                                 change_driver = true;
2376                         }
2377                         change_rate = true;
2378                         change_bufsize = true;
2379                         change_channels = true;
2380                         change_latency = true;
2381                         change_midi = 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;
2385                 }
2386
2387         } else {
2388
2389                 /* we have no control over the backend, meaning that we can
2390                  * only possibly change sample rate and buffer size.
2391                  */
2392
2393
2394                 if (get_rate() != backend->sample_rate()) {
2395                         change_bufsize = true;
2396                 }
2397
2398                 if (get_buffer_size() != backend->buffer_size()) {
2399                         change_bufsize = true;
2400                 }
2401         }
2402
2403         queue_device_changed = false;
2404
2405         if (!_have_control) {
2406
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
2409                  * out of here.
2410                  */
2411
2412                 if (change_rate && !backend->can_change_sample_rate_when_running()) {
2413                         return 1;
2414                 }
2415
2416                 if (change_bufsize && !backend->can_change_buffer_size_when_running()) {
2417                         return 1;
2418                 }
2419
2420                 if (change_rate) {
2421                         backend->set_sample_rate (get_rate());
2422                 }
2423
2424                 if (change_bufsize) {
2425                         backend->set_buffer_size (get_buffer_size());
2426                 }
2427
2428                 if (start) {
2429                         if (ARDOUR::AudioEngine::instance()->start ()) {
2430                                 error << string_compose (_("Could not start backend engine %1"), backend->name()) << endmsg;
2431                                 return -1;
2432                         }
2433                 }
2434
2435                 post_push ();
2436
2437                 return 0;
2438         }
2439
2440         /* determine if we need to stop the backend before changing parameters */
2441
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;
2448         } else {
2449                 restart_required = false;
2450         }
2451
2452
2453         if (was_running) {
2454                 if (restart_required) {
2455                         if (ARDOUR::AudioEngine::instance()->stop()) {
2456                                 return -1;
2457                         }
2458                 }
2459         }
2460
2461         if (change_driver && backend->set_driver (get_driver())) {
2462                 error << string_compose (_("Cannot set driver to %1"), get_driver()) << endmsg;
2463                 return -1;
2464         }
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;
2468                         return -1;
2469                 }
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;
2472                         return -1;
2473                 }
2474         } else {
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;
2477                         return -1;
2478                 }
2479         }
2480         if (change_rate && backend->set_sample_rate (get_rate())) {
2481                 error << string_compose (_("Cannot set sample rate to %1"), get_rate()) << endmsg;
2482                 return -1;
2483         }
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;
2486                 return -1;
2487         }
2488         if (change_nperiods && backend->set_peridod_size (get_nperiods())) {
2489                 error << string_compose (_("Cannot set periods to %1"), get_nperiods()) << endmsg;
2490                 return -1;
2491         }
2492
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;
2496                         return -1;
2497                 }
2498                 if (backend->set_output_channels (get_output_channels())) {
2499                         error << string_compose (_("Cannot set output channels to %1"), get_output_channels()) << endmsg;
2500                         return -1;
2501                 }
2502         }
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;
2506                         return -1;
2507                 }
2508                 if (backend->set_systemic_output_latency (get_output_latency())) {
2509                         error << string_compose (_("Cannot set output latency to %1"), get_output_latency()) << endmsg;
2510                         return -1;
2511                 }
2512         }
2513
2514         if (change_midi) {
2515                 backend->set_midi_option (get_midi_option());
2516         }
2517
2518         if (change_buffered_io) {
2519                 backend->set_use_buffered_io (use_buffered_io_button.get_active());
2520         }
2521
2522         if (1 /* TODO */) {
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);
2529                                 } else {
2530                                         backend->set_midi_device_enabled ((*p)->name, false);
2531                                 }
2532                                 continue;
2533                         }
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);
2538                         }
2539                 }
2540         }
2541
2542         if (start || (was_running && restart_required)) {
2543                 if (ARDOUR::AudioEngine::instance()->start()) {
2544                         return -1;
2545                 }
2546         }
2547
2548         post_push ();
2549
2550         return 0;
2551 }
2552
2553 void
2554 EngineControl::post_push ()
2555 {
2556         /* get a pointer to the current state object, creating one if
2557          * necessary
2558          */
2559
2560         State state = get_saved_state_for_currently_displayed_backend_and_device ();
2561
2562         if (!state) {
2563                 state = save_state ();
2564                 assert (state);
2565         } else {
2566                 store_state(state);
2567         }
2568
2569         states.sort (state_sort_cmp);
2570
2571         /* all off */
2572
2573         for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
2574                 (*i)->active = false;
2575         }
2576
2577         /* mark this one active (to be used next time the dialog is
2578          * shown)
2579          */
2580
2581         state->active = true;
2582
2583         if (_have_control) { // XXX
2584                 manage_control_app_sensitivity ();
2585         }
2586
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);
2589 }
2590
2591
2592 float
2593 EngineControl::get_rate () const
2594 {
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.
2598          */
2599         if (r < 1000.0) {
2600                 r *= 1000.0;
2601         }
2602         return r;
2603 }
2604
2605
2606 uint32_t
2607 EngineControl::get_buffer_size () const
2608 {
2609         string txt = buffer_size_combo.get_active_text ();
2610         uint32_t samples;
2611
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");
2615                 throw exception ();
2616         }
2617
2618         return samples;
2619 }
2620
2621 uint32_t
2622 EngineControl::get_nperiods () const
2623 {
2624         string txt = nperiods_combo.get_active_text ();
2625         return atoi (txt.c_str());
2626 }
2627
2628 string
2629 EngineControl::get_midi_option () const
2630 {
2631         return midi_option_combo.get_active_text();
2632 }
2633
2634 bool
2635 EngineControl::get_use_buffered_io () const
2636 {
2637         return use_buffered_io_button.get_active();
2638 }
2639
2640 uint32_t
2641 EngineControl::get_input_channels() const
2642 {
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();
2647         }
2648         return (uint32_t) input_channels_adjustment.get_value();
2649 }
2650
2651 uint32_t
2652 EngineControl::get_output_channels() const
2653 {
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();
2658         }
2659         return (uint32_t) output_channels_adjustment.get_value();
2660 }
2661
2662 uint32_t
2663 EngineControl::get_input_latency() const
2664 {
2665         return (uint32_t) input_latency_adjustment.get_value();
2666 }
2667
2668 uint32_t
2669 EngineControl::get_output_latency() const
2670 {
2671         return (uint32_t) output_latency_adjustment.get_value();
2672 }
2673
2674 string
2675 EngineControl::get_backend () const
2676 {
2677         return backend_combo.get_active_text ();
2678 }
2679
2680 string
2681 EngineControl::get_driver () const
2682 {
2683         if (driver_combo.get_parent()) {
2684                 return driver_combo.get_active_text ();
2685         } else {
2686                 return "";
2687         }
2688 }
2689
2690 string
2691 EngineControl::get_device_name () const
2692 {
2693         return device_combo.get_active_text ();
2694 }
2695
2696 string
2697 EngineControl::get_input_device_name () const
2698 {
2699         return input_device_combo.get_active_text ();
2700 }
2701
2702 string
2703 EngineControl::get_output_device_name () const
2704 {
2705         return output_device_combo.get_active_text ();
2706 }
2707
2708 void
2709 EngineControl::control_app_button_clicked ()
2710 {
2711         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2712
2713         if (!backend) {
2714                 return;
2715         }
2716
2717         backend->launch_control_app ();
2718 }
2719
2720 void
2721 EngineControl::start_stop_button_clicked ()
2722 {
2723         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2724
2725         if (!backend) {
2726                 return;
2727         }
2728
2729         if (ARDOUR::AudioEngine::instance()->running()) {
2730                 ARDOUR::AudioEngine::instance()->stop ();
2731         } else {
2732                 if (!ARDOUR_UI::instance()->the_session ()) {
2733                         pop_splash ();
2734                         hide ();
2735                         ARDOUR::GUIIdle ();
2736                 }
2737                 start_engine ();
2738                 if (!ARDOUR_UI::instance()->the_session ()) {
2739                         ArdourDialog::on_response (RESPONSE_OK);
2740                 }
2741         }
2742 }
2743
2744 void
2745 EngineControl::update_devices_button_clicked ()
2746 {
2747         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2748
2749         if (!backend) {
2750                 return;
2751         }
2752
2753         if (backend->update_devices()) {
2754                 device_list_changed ();
2755         }
2756 }
2757
2758 void
2759 EngineControl::use_buffered_io_button_clicked ()
2760 {
2761         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2762
2763         if (!backend) {
2764                 return;
2765         }
2766
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);
2770 }
2771
2772 void
2773 EngineControl::manage_control_app_sensitivity ()
2774 {
2775         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2776
2777         if (!backend) {
2778                 return;
2779         }
2780
2781         string appname = backend->control_app_name();
2782
2783         if (appname.empty()) {
2784                 control_app_button.set_sensitive (false);
2785         } else {
2786                 control_app_button.set_sensitive (true);
2787         }
2788 }
2789
2790 void
2791 EngineControl::set_desired_sample_rate (uint32_t sr)
2792 {
2793         _desired_sample_rate = sr;
2794         if (ARDOUR::AudioEngine::instance ()->running ()
2795                         && ARDOUR::AudioEngine::instance ()->sample_rate () != sr) {
2796                 stop_engine ();
2797         }
2798         device_changed ();
2799 }
2800
2801 void
2802 EngineControl::on_switch_page (GtkNotebookPage*, guint page_num)
2803 {
2804         if (page_num == 0) {
2805                 _measure_midi.reset();
2806                 update_sensitivity ();
2807         }
2808
2809         if (page_num == midi_tab) {
2810                 /* MIDI tab */
2811                 refresh_midi_display ();
2812
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);
2819                                 }
2820                         }
2821                 }
2822                 _measure_midi.reset();
2823         }
2824
2825         if (page_num == latency_tab) {
2826                 /* latency tab */
2827
2828                 if (ARDOUR::AudioEngine::instance()->running()) {
2829                         stop_engine (true);
2830                 }
2831
2832                 {
2833                         PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
2834
2835                         /* save any existing latency values */
2836
2837                         uint32_t il = (uint32_t) input_latency.get_value ();
2838                         uint32_t ol = (uint32_t) input_latency.get_value ();
2839
2840                         /* reset to zero so that our new test instance
2841                            will be clean of any existing latency measures.
2842
2843                            NB. this should really be done by the backend
2844                            when stated for latency measurement.
2845                         */
2846
2847                         input_latency.set_value (0);
2848                         output_latency.set_value (0);
2849
2850                         push_state_to_backend (false);
2851
2852                         /* reset control */
2853
2854                         input_latency.set_value (il);
2855                         output_latency.set_value (ol);
2856
2857                 }
2858                 // This should be done in push_state_to_backend()
2859                 if (ARDOUR::AudioEngine::instance()->prepare_for_latency_measurement()) {
2860                         disable_latency_tab ();
2861                 }
2862
2863                 enable_latency_tab ();
2864
2865         } else {
2866                 if (lm_running) {
2867                         end_latency_detection ();
2868                 }
2869         }
2870 }
2871
2872 /* latency measurement */
2873
2874 bool
2875 EngineControl::check_audio_latency_measurement ()
2876 {
2877         MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
2878
2879         if (mtdm->resolve () < 0) {
2880                 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
2881                 return true;
2882         }
2883
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.")));
2888                 return true;
2889         }
2890
2891         if (mtdm->err () > 0.3) {
2892                 mtdm->invert ();
2893                 mtdm->resolve ();
2894         }
2895
2896         char buf[256];
2897         ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
2898
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 ();
2902                 return false;
2903         }
2904
2905         int samples_total = mtdm->del();
2906         int extra = samples_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
2907
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);
2913
2914         bool solid = true;
2915
2916         if (mtdm->err () > 0.2) {
2917                 strcat (buf, " ");
2918                 strcat (buf, _("(signal detection error)"));
2919                 solid = false;
2920         }
2921
2922         if (mtdm->inv ()) {
2923                 strcat (buf, " ");
2924                 strcat (buf, _("(inverted - bad wiring)"));
2925                 solid = false;
2926         }
2927
2928         lm_results.set_markup (string_compose (results_markup, buf));
2929
2930         if (solid) {
2931                 have_lm_results = true;
2932                 end_latency_detection ();
2933                 lm_use_button.set_sensitive (true);
2934                 return false;
2935         }
2936
2937         return true;
2938 }
2939
2940 bool
2941 EngineControl::check_midi_latency_measurement ()
2942 {
2943         ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
2944
2945         if (!mididm->have_signal () || mididm->latency () == 0) {
2946                 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
2947                 return true;
2948         }
2949
2950         char buf[256];
2951         ARDOUR::samplecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
2952
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 ();
2956                 return false;
2957         }
2958
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);
2966
2967         bool solid = true;
2968
2969         if (!mididm->ok ()) {
2970                 strcat (buf, " ");
2971                 strcat (buf, _("(averaging)"));
2972                 solid = false;
2973         }
2974
2975         if (mididm->deviation () > 50.0) {
2976                 strcat (buf, " ");
2977                 strcat (buf, _("(too large jitter)"));
2978                 solid = false;
2979         } else if (mididm->deviation () > 10.0) {
2980                 strcat (buf, " ");
2981                 strcat (buf, _("(large jitter)"));
2982         }
2983
2984         if (solid) {
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));
2989                 return false;
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.")));
2994                 return false;
2995         }
2996
2997         lm_results.set_markup (string_compose (results_markup, buf));
2998
2999         return true;
3000 }
3001
3002 void
3003 EngineControl::start_latency_detection ()
3004 {
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));
3007
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);
3012                 } else {
3013                         latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_audio_latency_measurement), 100);
3014                 }
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);
3020                 lm_running = true;
3021         }
3022 }
3023
3024 void
3025 EngineControl::end_latency_detection ()
3026 {
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);
3032         }
3033         lm_input_channel_combo.set_sensitive (true);
3034         lm_output_channel_combo.set_sensitive (true);
3035         lm_running = false;
3036 }
3037
3038 void
3039 EngineControl::latency_button_clicked ()
3040 {
3041         if (!lm_running) {
3042                 start_latency_detection ();
3043         } else {
3044                 end_latency_detection ();
3045         }
3046 }
3047
3048 void
3049 EngineControl::latency_back_button_clicked ()
3050 {
3051         ARDOUR::AudioEngine::instance()->stop_latency_detection ();
3052         notebook.set_current_page(0);
3053 }
3054
3055 void
3056 EngineControl::use_latency_button_clicked ()
3057 {
3058         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3059         if (_measure_midi) {
3060                 ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
3061                 if (!mididm) {
3062                         return;
3063                 }
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);
3072                 }
3073                 notebook.set_current_page (midi_tab);
3074         } else {
3075                 MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
3076
3077                 if (!mtdm) {
3078                         return;
3079                 }
3080
3081                 double one_way = rint ((mtdm->del() - ARDOUR::AudioEngine::instance()->latency_signal_delay()) / 2.0);
3082                 one_way = std::max (0., one_way);
3083
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);
3089                 }
3090
3091                 /* back to settings page */
3092                 notebook.set_current_page (0);
3093         }
3094 }
3095
3096 bool
3097 EngineControl::on_delete_event (GdkEventAny* ev)
3098 {
3099         if (notebook.get_current_page() == 2) {
3100                 /* currently on latency tab - be sure to clean up */
3101                 end_latency_detection ();
3102         }
3103         return ArdourDialog::on_delete_event (ev);
3104 }
3105
3106 void
3107 EngineControl::engine_running ()
3108 {
3109         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3110         assert (backend);
3111
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()));
3114
3115         if (backend->can_set_period_size ()) {
3116                 set_active_text_if_present (nperiods_combo, to_string (backend->period_size()));
3117         }
3118
3119         connect_disconnect_button.set_label (string_compose (_("Disconnect from %1"), backend->name()));
3120         connect_disconnect_button.show();
3121
3122         started_at_least_once = true;
3123         if (_have_control) {
3124                 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Running")));
3125         } else {
3126                 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Connected")));
3127         }
3128         update_sensitivity();
3129 }
3130
3131 void
3132 EngineControl::engine_stopped ()
3133 {
3134         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3135         assert (backend);
3136
3137         connect_disconnect_button.set_label (string_compose (_("Connect to %1"), backend->name()));
3138         connect_disconnect_button.show();
3139
3140         if (_have_control) {
3141                 engine_status.set_markup(string_compose ("<span foreground=\"red\">%1</span>", _("Stopped")));
3142         } else {
3143                 engine_status.set_markup(X_(""));
3144         }
3145
3146         update_sensitivity();
3147 }
3148
3149 void
3150 EngineControl::device_list_changed ()
3151 {
3152         if (ignore_device_changes) {
3153                 return;
3154         }
3155         PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1); // ??
3156         if (!ARDOUR::AudioEngine::instance()->running()) {
3157                 list_devices ();
3158         }
3159
3160         midi_option_changed();
3161
3162         if (notebook.get_current_page() == midi_tab) {
3163                 if (_midi_devices.empty ()) {
3164                         notebook.set_current_page (0);
3165                 } else {
3166                         refresh_midi_display ();
3167                 }
3168         }
3169 }
3170
3171 void
3172 EngineControl::connect_disconnect_click()
3173 {
3174         if (ARDOUR::AudioEngine::instance()->running()) {
3175                 stop_engine ();
3176         } else {
3177                 if (!ARDOUR_UI::instance()->the_session ()) {
3178                         pop_splash ();
3179                         hide ();
3180                         ARDOUR::GUIIdle ();
3181                 }
3182                 start_engine ();
3183                 if (!ARDOUR_UI::instance()->the_session ()) {
3184                         ArdourDialog::on_response (RESPONSE_OK);
3185                 }
3186         }
3187 }
3188
3189 void
3190 EngineControl::calibrate_audio_latency ()
3191 {
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);
3197 }
3198
3199 void
3200 EngineControl::calibrate_midi_latency (MidiDeviceSettings s)
3201 {
3202         _measure_midi = 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);
3207 }
3208
3209 void
3210 EngineControl::configure_midi_devices ()
3211 {
3212         notebook.set_current_page (midi_tab);
3213 }