correctly show both the old MIDI setup tab (device oriented) and the new one (port...
[ardour.git] / gtk2_ardour / engine_dialog.cc
1 /*
2     Copyright (C) 2010 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #include <exception>
21 #include <vector>
22 #include <cmath>
23 #include <map>
24
25 #include <boost/scoped_ptr.hpp>
26
27 #include <gtkmm/messagedialog.h>
28
29 #include "pbd/error.h"
30 #include "pbd/xml++.h"
31 #include "pbd/unwind.h"
32 #include "pbd/failed_constructor.h"
33
34 #include <gtkmm/alignment.h>
35 #include <gtkmm/stock.h>
36 #include <gtkmm/notebook.h>
37 #include <gtkmm2ext/utils.h>
38
39 #include "ardour/audio_backend.h"
40 #include "ardour/audioengine.h"
41 #include "ardour/mtdm.h"
42 #include "ardour/mididm.h"
43 #include "ardour/rc_configuration.h"
44 #include "ardour/types.h"
45 #include "ardour/profile.h"
46
47 #include "pbd/convert.h"
48 #include "pbd/error.h"
49
50 #include "opts.h"
51 #include "debug.h"
52 #include "ardour_ui.h"
53 #include "engine_dialog.h"
54 #include "gui_thread.h"
55 #include "utils.h"
56 #include "pbd/i18n.h"
57
58 using namespace std;
59 using namespace Gtk;
60 using namespace Gtkmm2ext;
61 using namespace PBD;
62 using namespace Glib;
63 using namespace ARDOUR_UI_UTILS;
64
65 #define DEBUG_ECONTROL(msg) DEBUG_TRACE (PBD::DEBUG::EngineControl, string_compose ("%1: %2\n", __LINE__, msg));
66
67 static const unsigned int midi_tab = 2;
68 static const unsigned int latency_tab = 1; /* zero-based, page zero is the main setup page */
69
70 static const char* results_markup = X_("<span weight=\"bold\" size=\"larger\">%1</span>");
71
72 EngineControl::EngineControl ()
73         : ArdourDialog (_("Audio/MIDI Setup"))
74         , engine_status ("")
75         , basic_packer (9, 4)
76         , input_latency_adjustment (0, 0, 99999, 1)
77         , input_latency (input_latency_adjustment)
78         , output_latency_adjustment (0, 0, 99999, 1)
79         , output_latency (output_latency_adjustment)
80         , input_channels_adjustment (0, 0, 256, 1)
81         , input_channels (input_channels_adjustment)
82         , output_channels_adjustment (0, 0, 256, 1)
83         , output_channels (output_channels_adjustment)
84         , ports_adjustment (128, 8, 1024, 1, 16)
85         , ports_spinner (ports_adjustment)
86         , control_app_button (_("Device Control Panel"))
87         , midi_devices_button (_("Midi Device Setup"))
88         , start_stop_button (_("Stop"))
89         , update_devices_button (_("Refresh Devices"))
90         , use_buffered_io_button (_("Use Buffered I/O"), ArdourButton::led_default_elements)
91         , lm_measure_label (_("Measure"))
92         , lm_use_button (_("Use results"))
93         , lm_back_button (_("Back to settings ... (ignore results)"))
94         , lm_button_audio (_("Calibrate Audio"))
95         , lm_table (12, 3)
96         , have_lm_results (false)
97         , lm_running (false)
98         , midi_back_button (_("Back to settings"))
99         , ignore_changes (0)
100         , ignore_device_changes (0)
101         , _desired_sample_rate (0)
102         , started_at_least_once (false)
103         , queue_device_changed (false)
104         , _have_control (true)
105         , block_signals(0)
106 {
107         using namespace Notebook_Helpers;
108         vector<string> backend_names;
109         Label* label;
110         AttachOptions xopt = AttachOptions (FILL|EXPAND);
111         int row;
112
113         set_name (X_("AudioMIDISetup"));
114
115         /* the backend combo is the one thing that is ALWAYS visible */
116
117         vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
118
119         if (backends.empty()) {
120                 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));
121                 msg.run ();
122                 throw failed_constructor ();
123         }
124
125         for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
126                 backend_names.push_back ((*b)->name);
127         }
128
129         set_popdown_strings (backend_combo, backend_names);
130
131         /* setup basic packing characteristics for the table used on the main
132          * tab of the notebook
133          */
134
135         basic_packer.set_spacings (6);
136         basic_packer.set_border_width (12);
137         basic_packer.set_homogeneous (false);
138
139         /* pack it in */
140
141         basic_hbox.pack_start (basic_packer, false, false);
142
143         /* latency measurement tab */
144
145         lm_title.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("Latency Measurement Tool")));
146
147         row = 0;
148         lm_table.set_row_spacings (12);
149         lm_table.set_col_spacings (6);
150         lm_table.set_homogeneous (false);
151
152         lm_table.attach (lm_title, 0, 3, row, row+1, xopt, (AttachOptions) 0);
153         row++;
154
155         lm_preamble.set_width_chars (60);
156         lm_preamble.set_line_wrap (true);
157         lm_preamble.set_markup (_("<span weight=\"bold\">Turn down the volume on your audio equipment to a very low level.</span>"));
158
159         lm_table.attach (lm_preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
160         row++;
161
162         Gtk::Label* preamble;
163         preamble = manage (new Label);
164         preamble->set_width_chars (60);
165         preamble->set_line_wrap (true);
166         preamble->set_markup (_("Select two channels below and connect them using a cable."));
167
168         lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
169         row++;
170
171         label = manage (new Label (_("Output channel")));
172         lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
173
174         Gtk::Alignment* misc_align = manage (new Alignment (0.0, 0.5));
175         misc_align->add (lm_output_channel_combo);
176         lm_table.attach (*misc_align, 1, 3, row, row+1, xopt, (AttachOptions) 0);
177         ++row;
178
179         label = manage (new Label (_("Input channel")));
180         lm_table.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
181
182         misc_align = manage (new Alignment (0.0, 0.5));
183         misc_align->add (lm_input_channel_combo);
184         lm_table.attach (*misc_align, 1, 3, row, row+1, FILL, (AttachOptions) 0);
185         ++row;
186
187         lm_measure_label.set_padding (10, 10);
188         lm_measure_button.add (lm_measure_label);
189         lm_measure_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::latency_button_clicked));
190         lm_use_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::use_latency_button_clicked));
191         lm_back_button_signal = lm_back_button.signal_clicked().connect(
192             sigc::mem_fun(*this, &EngineControl::latency_back_button_clicked));
193
194         lm_use_button.set_sensitive (false);
195
196         /* Increase the default spacing around the labels of these three
197          * buttons
198          */
199
200         Gtk::Misc* l;
201
202         if ((l = dynamic_cast<Gtk::Misc*>(lm_use_button.get_child())) != 0) {
203                 l->set_padding (10, 10);
204         }
205
206         if ((l = dynamic_cast<Gtk::Misc*>(lm_back_button.get_child())) != 0) {
207                 l->set_padding (10, 10);
208         }
209
210         preamble = manage (new Label);
211         preamble->set_width_chars (60);
212         preamble->set_line_wrap (true);
213         preamble->set_markup (_("Once the channels are connected, click the \"Measure\" button."));
214         lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
215         row++;
216
217         preamble = manage (new Label);
218         preamble->set_width_chars (60);
219         preamble->set_line_wrap (true);
220         preamble->set_markup (_("When satisfied with the results, click the \"Use results\" button."));
221         lm_table.attach (*preamble, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
222
223         ++row; // skip a row in the table
224         ++row; // skip a row in the table
225
226         lm_table.attach (lm_results, 0, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
227
228         ++row; // skip a row in the table
229         ++row; // skip a row in the table
230
231         lm_table.attach (lm_measure_button, 0, 1, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
232         lm_table.attach (lm_use_button, 1, 2, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
233         lm_table.attach (lm_back_button, 2, 3, row, row+1, AttachOptions(FILL|EXPAND), (AttachOptions) 0);
234
235         lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
236
237         lm_vbox.set_border_width (12);
238         lm_vbox.pack_start (lm_table, false, false);
239
240         midi_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), 0));
241
242         /* pack it all up */
243
244         notebook.pages().push_back (TabElem (basic_vbox, _("Audio")));
245         notebook.pages().push_back (TabElem (lm_vbox, _("Latency")));
246         notebook.pages().push_back (TabElem (midi_vbox, _("MIDI")));
247         notebook.set_border_width (12);
248
249         //notebook.set_show_tabs (false);
250         notebook.show_all ();
251
252         notebook.set_name ("SettingsNotebook");
253
254         /* packup the notebook */
255
256         get_vbox()->set_border_width (12);
257         get_vbox()->pack_start (notebook);
258
259         /* need a special function to print "all available channels" when the
260          * channel counts hit zero.
261          */
262
263         input_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &input_channels));
264         output_channels.signal_output().connect (sigc::bind (sigc::ptr_fun (&EngineControl::print_channel_count), &output_channels));
265
266         midi_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::configure_midi_devices));
267         midi_devices_button.set_name ("generic button");
268         midi_devices_button.set_can_focus(true);
269
270         control_app_button.signal_clicked.connect (mem_fun (*this, &EngineControl::control_app_button_clicked));
271         control_app_button.set_name ("generic button");
272         control_app_button.set_can_focus(true);
273         manage_control_app_sensitivity ();
274
275         start_stop_button.signal_clicked.connect (mem_fun (*this, &EngineControl::start_stop_button_clicked));
276         start_stop_button.set_sensitive (false);
277         start_stop_button.set_name ("generic button");
278         start_stop_button.set_can_focus(true);
279
280         update_devices_button.signal_clicked.connect (mem_fun (*this, &EngineControl::update_devices_button_clicked));
281         update_devices_button.set_sensitive (false);
282         update_devices_button.set_name ("generic button");
283         update_devices_button.set_can_focus(true);
284
285         use_buffered_io_button.signal_clicked.connect (mem_fun (*this, &EngineControl::use_buffered_io_button_clicked));
286         use_buffered_io_button.set_sensitive (false);
287         use_buffered_io_button.set_name ("generic button");
288         use_buffered_io_button.set_can_focus(true);
289
290         cancel_button = add_button (Gtk::Stock::CLOSE, Gtk::RESPONSE_CANCEL);
291         ok_button = add_button (Gtk::Stock::OK, Gtk::RESPONSE_OK);
292
293         /* Pick up any existing audio setup configuration, if appropriate */
294
295         XMLNode* audio_setup = ARDOUR::Config->extra_xml ("AudioMIDISetup");
296
297         ARDOUR::AudioEngine::instance()->Running.connect (running_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_running, this), gui_context());
298         ARDOUR::AudioEngine::instance()->Stopped.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
299         ARDOUR::AudioEngine::instance()->Halted.connect (stopped_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::engine_stopped, this), gui_context());
300         ARDOUR::AudioEngine::instance()->DeviceListChanged.connect (devicelist_connection, MISSING_INVALIDATOR, boost::bind (&EngineControl::device_list_changed, this), gui_context());
301
302         if (audio_setup) {
303                 if (!set_state (*audio_setup)) {
304                         set_default_state ();
305                 }
306         } else {
307                 set_default_state ();
308         }
309
310         update_sensitivity ();
311         connect_changed_signals ();
312
313         notebook.signal_switch_page().connect (sigc::mem_fun (*this, &EngineControl::on_switch_page));
314
315         connect_disconnect_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::connect_disconnect_click));
316
317         connect_disconnect_button.set_no_show_all();
318         use_buffered_io_button.set_no_show_all();
319         update_devices_button.set_no_show_all();
320         start_stop_button.set_no_show_all();
321         midi_devices_button.set_no_show_all();
322 }
323
324 void
325 EngineControl::connect_changed_signals ()
326 {
327         backend_combo_connection = backend_combo.signal_changed ().connect (
328             sigc::mem_fun (*this, &EngineControl::backend_changed));
329         driver_combo_connection = driver_combo.signal_changed ().connect (
330             sigc::mem_fun (*this, &EngineControl::driver_changed));
331         sample_rate_combo_connection = sample_rate_combo.signal_changed ().connect (
332             sigc::mem_fun (*this, &EngineControl::sample_rate_changed));
333         buffer_size_combo_connection = buffer_size_combo.signal_changed ().connect (
334             sigc::mem_fun (*this, &EngineControl::buffer_size_changed));
335         nperiods_combo_connection = nperiods_combo.signal_changed ().connect (
336             sigc::mem_fun (*this, &EngineControl::nperiods_changed));
337         device_combo_connection = device_combo.signal_changed ().connect (
338             sigc::mem_fun (*this, &EngineControl::device_changed));
339         midi_option_combo_connection = midi_option_combo.signal_changed ().connect (
340             sigc::mem_fun (*this, &EngineControl::midi_option_changed));
341
342         input_device_combo_connection = input_device_combo.signal_changed ().connect (
343             sigc::mem_fun (*this, &EngineControl::input_device_changed));
344         output_device_combo_connection = output_device_combo.signal_changed ().connect (
345             sigc::mem_fun (*this, &EngineControl::output_device_changed));
346
347         input_latency_connection = input_latency.signal_changed ().connect (
348             sigc::mem_fun (*this, &EngineControl::parameter_changed));
349         output_latency_connection = output_latency.signal_changed ().connect (
350             sigc::mem_fun (*this, &EngineControl::parameter_changed));
351         input_channels_connection = input_channels.signal_changed ().connect (
352             sigc::mem_fun (*this, &EngineControl::parameter_changed));
353         output_channels_connection = output_channels.signal_changed ().connect (
354             sigc::mem_fun (*this, &EngineControl::parameter_changed));
355 }
356
357 void
358 EngineControl::block_changed_signals ()
359 {
360         if (block_signals++ == 0) {
361                 DEBUG_ECONTROL ("Blocking changed signals");
362                 backend_combo_connection.block ();
363                 driver_combo_connection.block ();
364                 sample_rate_combo_connection.block ();
365                 buffer_size_combo_connection.block ();
366                 nperiods_combo_connection.block ();
367                 device_combo_connection.block ();
368                 input_device_combo_connection.block ();
369                 output_device_combo_connection.block ();
370                 midi_option_combo_connection.block ();
371                 input_latency_connection.block ();
372                 output_latency_connection.block ();
373                 input_channels_connection.block ();
374                 output_channels_connection.block ();
375         }
376 }
377
378 void
379 EngineControl::unblock_changed_signals ()
380 {
381         if (--block_signals == 0) {
382                 DEBUG_ECONTROL ("Unblocking changed signals");
383                 backend_combo_connection.unblock ();
384                 driver_combo_connection.unblock ();
385                 sample_rate_combo_connection.unblock ();
386                 buffer_size_combo_connection.unblock ();
387                 nperiods_combo_connection.unblock ();
388                 device_combo_connection.unblock ();
389                 input_device_combo_connection.unblock ();
390                 output_device_combo_connection.unblock ();
391                 midi_option_combo_connection.unblock ();
392                 input_latency_connection.unblock ();
393                 output_latency_connection.unblock ();
394                 input_channels_connection.unblock ();
395                 output_channels_connection.unblock ();
396         }
397 }
398
399 EngineControl::SignalBlocker::SignalBlocker (EngineControl& engine_control,
400                                              const std::string& reason)
401     : ec (engine_control)
402     , m_reason (reason)
403 {
404         DEBUG_ECONTROL (string_compose ("SignalBlocker: %1", m_reason));
405         ec.block_changed_signals ();
406 }
407
408 EngineControl::SignalBlocker::~SignalBlocker ()
409 {
410         DEBUG_ECONTROL (string_compose ("~SignalBlocker: %1", m_reason));
411         ec.unblock_changed_signals ();
412 }
413
414 void
415 EngineControl::on_show ()
416 {
417         ArdourDialog::on_show ();
418         if (!ARDOUR::AudioEngine::instance()->current_backend() || !ARDOUR::AudioEngine::instance()->running()) {
419                 // re-check _have_control (jackd running) see #6041
420                 backend_changed ();
421         }
422         device_changed ();
423         ok_button->grab_focus();
424 }
425
426 bool
427 EngineControl::try_autostart ()
428 {
429         if (!start_stop_button.get_sensitive()) {
430                 return false;
431         }
432         if (ARDOUR::AudioEngine::instance()->running()) {
433                 return true;
434         }
435         return start_engine ();
436 }
437
438 bool
439 EngineControl::start_engine ()
440 {
441         if (push_state_to_backend(true) != 0) {
442                 MessageDialog msg(*this,
443                                   ARDOUR::AudioEngine::instance()->get_last_backend_error());
444                 msg.run();
445                 return false;
446         }
447         return true;
448 }
449
450 bool
451 EngineControl::stop_engine (bool for_latency)
452 {
453         if (ARDOUR::AudioEngine::instance()->stop(for_latency)) {
454                 MessageDialog msg(*this,
455                                   ARDOUR::AudioEngine::instance()->get_last_backend_error());
456                 msg.run();
457                 return false;
458         }
459         return true;
460 }
461
462 void
463 EngineControl::on_response (int response_id)
464 {
465         ArdourDialog::on_response (response_id);
466
467         switch (response_id) {
468         case RESPONSE_OK:
469                 if (!start_engine()) {
470                         return;
471                 } else {
472                         hide();
473                 }
474 #ifdef PLATFORM_WINDOWS
475
476                 // But if there's no session open, this can produce
477                 // a long gap when nothing appears to be happening.
478                 // Let's show the splash image while we're waiting.
479                 if (!ARDOUR_COMMAND_LINE::no_splash) {
480                         if (ARDOUR_UI::instance()) {
481                                 if (!ARDOUR_UI::instance()->session_loaded) {
482                                         ARDOUR_UI::instance()->show_splash();
483                                 }
484                         }
485                 }
486 #endif
487                 break;
488         case RESPONSE_DELETE_EVENT: {
489                 GdkEventButton ev;
490                 ev.type = GDK_BUTTON_PRESS;
491                 ev.button = 1;
492                 on_delete_event((GdkEventAny*)&ev);
493                 break;
494         }
495         case RESPONSE_CANCEL:
496                 if (ARDOUR_UI::instance() && ARDOUR_UI::instance()->session_loaded) {
497                         ARDOUR_UI::instance()->check_audioengine(*this);
498                 }
499         // fall through
500         default:
501                 hide();
502         }
503 }
504
505 void
506 EngineControl::build_notebook ()
507 {
508         Label* label;
509         AttachOptions xopt = AttachOptions (FILL|EXPAND);
510
511         /* clear the table */
512
513         Gtkmm2ext::container_clear (basic_vbox);
514         Gtkmm2ext::container_clear (basic_packer);
515
516         if (control_app_button.get_parent()) {
517                 control_app_button.get_parent()->remove (control_app_button);
518         }
519
520         label = manage (left_aligned_label (_("Audio System:")));
521         basic_packer.attach (*label, 0, 1, 0, 1, xopt, (AttachOptions) 0);
522         basic_packer.attach (backend_combo, 1, 2, 0, 1, xopt, (AttachOptions) 0);
523
524         basic_packer.attach (engine_status, 2, 3, 0, 1, xopt, (AttachOptions) 0);
525         engine_status.show();
526
527         basic_packer.attach (start_stop_button, 3, 4, 0, 1, xopt, xopt);
528         basic_packer.attach (update_devices_button, 3, 4, 1, 2, xopt, xopt);
529         basic_packer.attach (use_buffered_io_button, 3, 4, 2, 3, xopt, xopt);
530
531         lm_button_audio.signal_clicked.connect (sigc::mem_fun (*this, &EngineControl::calibrate_audio_latency));
532         lm_button_audio.set_name ("generic button");
533         lm_button_audio.set_can_focus(true);
534
535         if (_have_control) {
536                 build_full_control_notebook ();
537         } else {
538                 build_no_control_notebook ();
539         }
540
541         basic_vbox.pack_start (basic_hbox, false, false);
542
543         {
544                 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
545                 basic_vbox.show_all ();
546         }
547 }
548
549 void
550 EngineControl::build_full_control_notebook ()
551 {
552         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
553         assert (backend);
554
555         using namespace Notebook_Helpers;
556         Label* label;
557         vector<string> strings;
558         AttachOptions xopt = AttachOptions (FILL|EXPAND);
559         int row = 1; // row zero == backend combo
560
561         /* start packing it up */
562
563         if (backend->requires_driver_selection()) {
564                 label = manage (left_aligned_label (_("Driver:")));
565                 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
566                 basic_packer.attach (driver_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
567                 row++;
568         }
569
570         if (backend->use_separate_input_and_output_devices()) {
571                 label = manage (left_aligned_label (_("Input Device:")));
572                 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
573                 basic_packer.attach (input_device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
574                 row++;
575                 label = manage (left_aligned_label (_("Output Device:")));
576                 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
577                 basic_packer.attach (output_device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
578                 row++;
579                 // reset so it isn't used in state comparisons
580                 device_combo.set_active_text ("");
581         } else {
582                 label = manage (left_aligned_label (_("Device:")));
583                 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
584                 basic_packer.attach (device_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
585                 row++;
586                 // reset these so they don't get used in state comparisons
587                 input_device_combo.set_active_text ("");
588                 output_device_combo.set_active_text ("");
589         }
590
591         label = manage (left_aligned_label (_("Sample rate:")));
592         basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
593         basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
594         row++;
595
596
597         label = manage (left_aligned_label (_("Buffer size:")));
598         basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
599         basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
600         buffer_size_duration_label.set_alignment (0.0); /* left-align */
601         basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
602
603         int ctrl_btn_span = 1;
604         if (backend->can_set_period_size ()) {
605                 row++;
606                 label = manage (left_aligned_label (_("Periods:")));
607                 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
608                 basic_packer.attach (nperiods_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
609                 ++ctrl_btn_span;
610         }
611
612         /* button spans 2 or 3 rows */
613
614         basic_packer.attach (control_app_button, 3, 4, row - ctrl_btn_span, row + 1, xopt, xopt);
615         row++;
616
617         input_channels.set_name ("InputChannels");
618         input_channels.set_flags (Gtk::CAN_FOCUS);
619         input_channels.set_digits (0);
620         input_channels.set_wrap (false);
621         output_channels.set_editable (true);
622
623         if (!ARDOUR::Profile->get_mixbus()) {
624                 label = manage (left_aligned_label (_("Input Channels:")));
625                 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
626                 basic_packer.attach (input_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
627                 ++row;
628         }
629
630         output_channels.set_name ("OutputChannels");
631         output_channels.set_flags (Gtk::CAN_FOCUS);
632         output_channels.set_digits (0);
633         output_channels.set_wrap (false);
634         output_channels.set_editable (true);
635
636         if (!ARDOUR::Profile->get_mixbus()) {
637                 label = manage (left_aligned_label (_("Output Channels:")));
638                 basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
639                 basic_packer.attach (output_channels, 1, 2, row, row+1, xopt, (AttachOptions) 0);
640                 ++row;
641         }
642
643         input_latency.set_name ("InputLatency");
644         input_latency.set_flags (Gtk::CAN_FOCUS);
645         input_latency.set_digits (0);
646         input_latency.set_wrap (false);
647         input_latency.set_editable (true);
648
649         label = manage (left_aligned_label (_("Hardware input latency:")));
650         basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
651         basic_packer.attach (input_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         ++row;
655
656         output_latency.set_name ("OutputLatency");
657         output_latency.set_flags (Gtk::CAN_FOCUS);
658         output_latency.set_digits (0);
659         output_latency.set_wrap (false);
660         output_latency.set_editable (true);
661
662         label = manage (left_aligned_label (_("Hardware output latency:")));
663         basic_packer.attach (*label, 0, 1, row, row+1, xopt, (AttachOptions) 0);
664         basic_packer.attach (output_latency, 1, 2, row, row+1, xopt, (AttachOptions) 0);
665         label = manage (left_aligned_label (_("samples")));
666         basic_packer.attach (*label, 2, 3, row, row+1, SHRINK, (AttachOptions) 0);
667
668         /* button spans 2 rows */
669
670         basic_packer.attach (lm_button_audio, 3, 4, row-1, row+1, xopt, xopt);
671         ++row;
672
673         label = manage (left_aligned_label (_("MIDI System:")));
674         basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
675         basic_packer.attach (midi_option_combo, 1, 2, row, row + 1, SHRINK, (AttachOptions) 0);
676         basic_packer.attach (midi_devices_button, 3, 4, row, row+1, xopt, xopt);
677         row++;
678 }
679
680 void
681 EngineControl::build_no_control_notebook ()
682 {
683         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
684         assert (backend);
685
686         using namespace Notebook_Helpers;
687         Label* label;
688         vector<string> strings;
689         AttachOptions xopt = AttachOptions (FILL|EXPAND);
690         int row = 1; // row zero == backend combo
691         const string msg = string_compose (_("%1 is already running. %2 will connect to it and use the existing settings."), backend->name(), PROGRAM_NAME);
692
693         label = manage (new Label);
694         label->set_markup (string_compose ("<span weight=\"bold\" foreground=\"red\">%1</span>", msg));
695         basic_packer.attach (*label, 0, 2, row, row + 1, xopt, (AttachOptions) 0);
696         row++;
697
698         if (backend->can_change_sample_rate_when_running()) {
699                 label = manage (left_aligned_label (_("Sample rate:")));
700                 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
701                 basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
702                 row++;
703         }
704
705         if (backend->can_change_buffer_size_when_running()) {
706                 label = manage (left_aligned_label (_("Buffer size:")));
707                 basic_packer.attach (*label, 0, 1, row, row + 1, xopt, (AttachOptions) 0);
708                 basic_packer.attach (buffer_size_combo, 1, 2, row, row + 1, xopt, (AttachOptions) 0);
709                 buffer_size_duration_label.set_alignment (0.0); /* left-align */
710                 basic_packer.attach (buffer_size_duration_label, 2, 3, row, row+1, xopt, (AttachOptions) 0);
711                 row++;
712         }
713
714         basic_packer.attach (connect_disconnect_button, 0, 2, row, row+1, FILL, AttachOptions (0));
715         row++;
716 }
717
718 EngineControl::~EngineControl ()
719 {
720         ignore_changes = true;
721 }
722
723 void
724 EngineControl::disable_latency_tab ()
725 {
726         vector<string> empty;
727         set_popdown_strings (lm_output_channel_combo, empty);
728         set_popdown_strings (lm_input_channel_combo, empty);
729         lm_measure_button.set_sensitive (false);
730         lm_use_button.set_sensitive (false);
731 }
732
733 void
734 EngineControl::enable_latency_tab ()
735 {
736         vector<string> outputs;
737         vector<string> inputs;
738
739         ARDOUR::DataType const type = _measure_midi ? ARDOUR::DataType::MIDI : ARDOUR::DataType::AUDIO;
740         ARDOUR::AudioEngine::instance()->get_physical_outputs (type, outputs);
741         ARDOUR::AudioEngine::instance()->get_physical_inputs (type, inputs);
742
743         if (!ARDOUR::AudioEngine::instance()->running()) {
744                 MessageDialog msg (_("Failed to start or connect to audio-engine.\n\nLatency calibration requires a working audio interface."));
745                 notebook.set_current_page (0);
746                 msg.run ();
747                 return;
748         }
749         else if (inputs.empty() || outputs.empty()) {
750                 MessageDialog msg (_("Your selected audio configuration is playback- or capture-only.\n\nLatency calibration requires playback and capture"));
751                 notebook.set_current_page (0);
752                 msg.run ();
753                 return;
754         }
755
756         lm_back_button_signal.disconnect();
757         if (_measure_midi) {
758                 lm_back_button_signal = lm_back_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (notebook, &Gtk::Notebook::set_current_page), midi_tab));
759                 lm_preamble.hide ();
760         } else {
761                 lm_back_button_signal = lm_back_button.signal_clicked().connect(
762                     sigc::mem_fun(*this, &EngineControl::latency_back_button_clicked));
763                 lm_preamble.show ();
764         }
765
766         set_popdown_strings (lm_output_channel_combo, outputs);
767         lm_output_channel_combo.set_active_text (outputs.front());
768         lm_output_channel_combo.set_sensitive (true);
769
770         set_popdown_strings (lm_input_channel_combo, inputs);
771         lm_input_channel_combo.set_active_text (inputs.front());
772         lm_input_channel_combo.set_sensitive (true);
773
774         lm_measure_button.set_sensitive (true);
775 }
776
777 void
778 EngineControl::setup_midi_tab_for_backend ()
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         midi_vbox.pack_start (midi_device_table, true, true);
786
787         pretty_name_column = midi_input_view.append_column (_("Pretty Name"), midi_port_columns.pretty_name) - 1;
788         use_column = midi_input_view.append_column (_("Use"), midi_port_columns.in_use) - 1;
789         music_column = midi_input_view.append_column (_("Use for Music"), midi_port_columns.music_data) - 1;
790         control_column = midi_input_view.append_column (_("Use for Control"), midi_port_columns.control_data) - 1;
791         selection_column = midi_input_view.append_column (_("Follow Selection"), midi_port_columns.control_data) - 1;
792
793         midi_output_view.append_column (_("Pretty Name"), midi_port_columns.pretty_name);
794         midi_output_view.append_column (_("Use"), midi_port_columns.in_use);
795         midi_output_view.append_column (_("Use for Music"), midi_port_columns.music_data);
796         midi_output_view.append_column (_("Use for Control"), midi_port_columns.control_data);
797         midi_output_view.append_column (_("Follow Selection"), midi_port_columns.control_data);
798
799         midi_input_view.get_selection()->set_mode (SELECTION_NONE);
800         midi_output_view.get_selection()->set_mode (SELECTION_NONE);
801
802         midi_vbox.pack_start (midi_input_view);
803         midi_vbox.pack_start (midi_output_view);
804
805         midi_vbox.pack_start (midi_back_button, false, false);
806         midi_vbox.show_all ();
807 }
808
809 void
810 EngineControl::refill_midi_ports (bool for_input)
811 {
812         using namespace ARDOUR;
813
814         std::vector<string> ports;
815
816         AudioEngine::instance()->get_ports (string(), DataType::MIDI, for_input ? IsInput : IsOutput, ports);
817
818         Glib::RefPtr<ListStore> model = Gtk::ListStore::create (midi_port_columns);
819
820         for (vector<string>::const_iterator s = ports.begin(); s != ports.end(); ++s) {
821
822                 if (AudioEngine::instance()->port_is_mine (*s)) {
823                         continue;
824                 }
825
826                 TreeModel::Row row = *(model->append());
827
828                 string pretty = AudioEngine::instance()->get_pretty_name_by_name (*s);
829                 row[midi_port_columns.name] = *s;
830                 row[midi_port_columns.pretty_name] = (pretty.empty() ? *s : pretty);
831                 row[midi_port_columns.in_use] = true;
832                 row[midi_port_columns.music_data] = true;
833                 row[midi_port_columns.control_data] = true;
834         }
835
836         Gtk::TreeView& view (for_input ? midi_input_view : midi_output_view);
837
838         view.set_model (model);
839
840         CellRendererText* pretty_name_cell = dynamic_cast<CellRendererText*> (view.get_column_cell_renderer (pretty_name_column));
841         pretty_name_cell->property_editable() = true;
842         pretty_name_cell->signal_edited().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::pretty_name_edit), &view));
843
844         CellRendererToggle* toggle_cell;
845
846         toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (use_column));
847         toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_use_column_toggled), &view));
848
849         toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (music_column));
850         toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_music_column_toggled), &view));
851
852         toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (control_column));
853         toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_control_column_toggled), &view));
854
855         toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (selection_column));
856         toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_selection_column_toggled), &view));
857 }
858
859 void
860 EngineControl::midi_use_column_toggled (string const & path, TreeView* view)
861 {
862         TreeIter iter = view->get_model()->get_iter (path);
863
864         if (!iter) {
865                 return;
866         }
867
868         bool value ((*iter)[midi_port_columns.in_use]);
869         (*iter)[midi_port_columns.in_use] = !value;
870
871 }
872
873 void
874 EngineControl::midi_music_column_toggled (string const & path, TreeView* view)
875 {
876         TreeIter iter = view->get_model()->get_iter (path);
877
878         if (!iter) {
879                 return;
880         }
881
882         bool value ((*iter)[midi_port_columns.music_data]);
883         (*iter)[midi_port_columns.music_data] = !value;
884 }
885
886 void
887 EngineControl::midi_control_column_toggled (string const & path, TreeView* view)
888 {
889         TreeIter iter = view->get_model()->get_iter (path);
890
891         if (!iter) {
892                 return;
893         }
894
895         bool value ((*iter)[midi_port_columns.control_data]);
896         (*iter)[midi_port_columns.control_data] = !value;
897
898         if (!value) {
899                 // ARDOUR::AudioEngine::instance()->remove_port_purpose (PortFlags (ControlData));
900         } else {
901                 // ARDOUR::AudioEngine::instance()->add_port_purpose (PortFlags (ControlData));
902         }
903 }
904
905 void
906 EngineControl::midi_selection_column_toggled (string const & path, TreeView* view)
907 {
908         TreeIter iter = view->get_model()->get_iter (path);
909
910         if (!iter) {
911                 return;
912         }
913         bool value ((*iter)[midi_port_columns.selection]);
914         (*iter)[midi_port_columns.selection] = !value;
915 }
916
917 void
918 EngineControl::pretty_name_edit (std::string const & path, string const & new_text, Gtk::TreeView* view)
919 {
920         TreeIter iter = view->get_model()->get_iter (path);
921
922         if (!iter) {
923                 return;
924         }
925
926         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
927         if (backend) {
928                 ARDOUR::PortEngine::PortHandle ph = backend->get_port_by_name ((*iter)[midi_port_columns.name]);
929                 if (ph) {
930                         backend->set_port_property (ph, "http://jackaudio.org/metadata/pretty-name", new_text, "");
931                         (*iter)[midi_port_columns.pretty_name] = new_text;
932                 }
933         }
934 }
935
936 void
937 EngineControl::update_sensitivity ()
938 {
939         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
940         if (!backend) {
941                 ok_button->set_sensitive (false);
942                 start_stop_button.set_sensitive (false);
943                 return;
944         }
945
946         bool valid = true;
947         size_t devices_available = 0;
948
949         if (backend->use_separate_input_and_output_devices ()) {
950                 devices_available += get_popdown_string_count (input_device_combo);
951                 devices_available += get_popdown_string_count (output_device_combo);
952         } else {
953                 devices_available += get_popdown_string_count (device_combo);
954         }
955
956         if (devices_available == 0) {
957                 valid = false;
958                 input_latency.set_sensitive (false);
959                 output_latency.set_sensitive (false);
960                 input_channels.set_sensitive (false);
961                 output_channels.set_sensitive (false);
962         } else {
963                 input_latency.set_sensitive (true);
964                 output_latency.set_sensitive (true);
965                 input_channels.set_sensitive (true);
966                 output_channels.set_sensitive (true);
967         }
968
969         if (get_popdown_string_count (buffer_size_combo) > 0) {
970                 if (!ARDOUR::AudioEngine::instance()->running()) {
971                         buffer_size_combo.set_sensitive (valid);
972                 } else if (backend->can_change_sample_rate_when_running()) {
973                         buffer_size_combo.set_sensitive (valid || !_have_control);
974                 } else {
975 #if 1
976                         /* TODO
977                          * Currently there is no way to manually stop the
978                          * engine in order to re-configure it.
979                          * This needs to remain sensitive for now.
980                          *
981                          * (it's also handy to implicily
982                          * re-start the engine)
983                          */
984                         buffer_size_combo.set_sensitive (true);
985 #else
986                         buffer_size_combo.set_sensitive (false);
987 #endif
988                 }
989         } else {
990                 buffer_size_combo.set_sensitive (false);
991                 valid = false;
992         }
993
994         if (get_popdown_string_count (sample_rate_combo) > 0) {
995                 bool allow_to_set_rate = false;
996                 if (!ARDOUR::AudioEngine::instance()->running()) {
997                         if (!ARDOUR_UI::instance()->session_loaded) {
998                                 // engine is not running, no session loaded -> anything goes.
999                                 allow_to_set_rate = true;
1000                         } else if (_desired_sample_rate > 0 && get_rate () != _desired_sample_rate) {
1001                                 // only allow to change if the current setting is not the native session rate.
1002                                 allow_to_set_rate = true;
1003                         }
1004                 }
1005                 sample_rate_combo.set_sensitive (allow_to_set_rate);
1006         } else {
1007                 sample_rate_combo.set_sensitive (false);
1008                 valid = false;
1009         }
1010
1011         if (get_popdown_string_count (nperiods_combo) > 0) {
1012                 if (!ARDOUR::AudioEngine::instance()->running()) {
1013                         nperiods_combo.set_sensitive (true);
1014                 } else {
1015                         nperiods_combo.set_sensitive (false);
1016                 }
1017         } else {
1018                 nperiods_combo.set_sensitive (false);
1019         }
1020
1021         if (_have_control) {
1022                 start_stop_button.set_sensitive(true);
1023                 start_stop_button.show();
1024                 if (ARDOUR::AudioEngine::instance()->running()) {
1025                         start_stop_button.set_text("Stop");
1026                         update_devices_button.set_sensitive(false);
1027                         use_buffered_io_button.set_sensitive(false);
1028                 } else {
1029                         if (backend->can_request_update_devices()) {
1030                                 update_devices_button.show();
1031                         } else {
1032                                 update_devices_button.hide();
1033                         }
1034                         if (backend->can_use_buffered_io()) {
1035                                 use_buffered_io_button.show();
1036                         } else {
1037                                 use_buffered_io_button.hide();
1038                         }
1039                         start_stop_button.set_text("Start");
1040                         update_devices_button.set_sensitive(true);
1041                         use_buffered_io_button.set_sensitive(true);
1042                 }
1043         } else {
1044                 update_devices_button.set_sensitive(false);
1045                 update_devices_button.hide();
1046                 use_buffered_io_button.set_sensitive(false);
1047                 use_buffered_io_button.hide();
1048                 start_stop_button.set_sensitive(false);
1049                 start_stop_button.hide();
1050         }
1051
1052         if (ARDOUR::AudioEngine::instance()->running() && _have_control) {
1053                 input_device_combo.set_sensitive (false);
1054                 output_device_combo.set_sensitive (false);
1055                 device_combo.set_sensitive (false);
1056                 driver_combo.set_sensitive (false);
1057         } else {
1058                 input_device_combo.set_sensitive (true);
1059                 output_device_combo.set_sensitive (true);
1060                 device_combo.set_sensitive (true);
1061                 if (backend->requires_driver_selection() && get_popdown_string_count(driver_combo) > 0) {
1062                         driver_combo.set_sensitive (true);
1063                 } else {
1064                         driver_combo.set_sensitive (false);
1065                 }
1066         }
1067
1068         if (valid || !_have_control) {
1069                 ok_button->set_sensitive (true);
1070         } else {
1071                 ok_button->set_sensitive (false);
1072         }
1073 }
1074
1075 void
1076 EngineControl::midi_latency_adjustment_changed (Gtk::Adjustment *a, MidiDeviceSettings device, bool for_input) {
1077         if (for_input) {
1078                 device->input_latency = a->get_value();
1079         } else {
1080                 device->output_latency = a->get_value();
1081         }
1082 }
1083
1084 void
1085 EngineControl::midi_device_enabled_toggled (ArdourButton *b, MidiDeviceSettings device) {
1086         b->set_active (!b->get_active());
1087         device->enabled = b->get_active();
1088         refresh_midi_display(device->name);
1089 }
1090
1091 void
1092 EngineControl::refresh_midi_display (std::string focus)
1093 {
1094         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1095         assert (backend);
1096
1097         int row  = 0;
1098         AttachOptions xopt = AttachOptions (FILL|EXPAND);
1099         Gtk::Label* l;
1100
1101         Gtkmm2ext::container_clear (midi_device_table);
1102
1103         midi_device_table.set_spacings (6);
1104
1105         l = manage (new Label);
1106         l->set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Devices")));
1107         midi_device_table.attach (*l, 0, 4, row, row + 1, xopt, AttachOptions (0));
1108         l->set_alignment (0.5, 0.5);
1109         row++;
1110         l->show ();
1111
1112         l = manage (new Label (_("Device"))); l->show (); l->set_alignment (0.5, 0.5);
1113         midi_device_table.attach (*l, 0, 1, row, row + 2, xopt, AttachOptions (0));
1114         l = manage (new Label (_("Hardware Latencies"))); l->show (); l->set_alignment (0.5, 0.5);
1115         midi_device_table.attach (*l, 1, 3, row, row + 1, xopt, AttachOptions (0));
1116         row++;
1117         l = manage (new Label (_("Input"))); l->show (); l->set_alignment (0.5, 0.5);
1118         midi_device_table.attach (*l, 1, 2, row, row + 1, xopt, AttachOptions (0));
1119         l = manage (new Label (_("Output"))); l->show (); l->set_alignment (0.5, 0.5);
1120         midi_device_table.attach (*l, 2, 3, row, row + 1, xopt, AttachOptions (0));
1121         row++;
1122
1123         for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
1124                 ArdourButton *m;
1125                 Gtk::Button* b;
1126                 Gtk::Adjustment *a;
1127                 Gtk::SpinButton *s;
1128                 bool enabled = (*p)->enabled;
1129
1130                 m = manage (new ArdourButton ((*p)->name, ArdourButton::led_default_elements));
1131                 m->set_name ("midi device");
1132                 m->set_can_focus (Gtk::CAN_FOCUS);
1133                 m->add_events (Gdk::BUTTON_RELEASE_MASK);
1134                 m->set_active (enabled);
1135                 m->signal_clicked.connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_device_enabled_toggled), m, *p));
1136                 midi_device_table.attach (*m, 0, 1, row, row + 1, xopt, AttachOptions (0)); m->show ();
1137                 if ((*p)->name == focus) {
1138                         m->grab_focus();
1139                 }
1140
1141                 a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
1142                 s = manage (new Gtk::SpinButton (*a));
1143                 a->set_value ((*p)->input_latency);
1144                 s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, true));
1145                 s->set_sensitive (_can_set_midi_latencies && enabled);
1146                 midi_device_table.attach (*s, 1, 2, row, row + 1, xopt, AttachOptions (0)); s->show ();
1147
1148                 a = manage (new Gtk::Adjustment (0, 0, 99999, 1));
1149                 s = manage (new Gtk::SpinButton (*a));
1150                 a->set_value ((*p)->output_latency);
1151                 s->signal_value_changed().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::midi_latency_adjustment_changed), a, *p, false));
1152                 s->set_sensitive (_can_set_midi_latencies && enabled);
1153                 midi_device_table.attach (*s, 2, 3, row, row + 1, xopt, AttachOptions (0)); s->show ();
1154
1155                 b = manage (new Button (_("Calibrate")));
1156                 b->signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &EngineControl::calibrate_midi_latency), *p));
1157                 b->set_sensitive (_can_set_midi_latencies && enabled);
1158                 midi_device_table.attach (*b, 3, 4, row, row + 1, xopt, AttachOptions (0)); b->show ();
1159
1160                 row++;
1161         }
1162 }
1163
1164 void
1165 EngineControl::backend_changed ()
1166 {
1167         SignalBlocker blocker (*this, "backend_changed");
1168         string backend_name = backend_combo.get_active_text();
1169         boost::shared_ptr<ARDOUR::AudioBackend> backend;
1170
1171         if (!(backend = ARDOUR::AudioEngine::instance()->set_backend (backend_name, downcase (std::string(PROGRAM_NAME)), ""))) {
1172                 /* eh? setting the backend failed... how ? */
1173                 /* A: stale config contains a backend that does not exist in current build */
1174                 return;
1175         }
1176
1177         DEBUG_ECONTROL (string_compose ("Backend name: %1", backend_name));
1178
1179         _have_control = ARDOUR::AudioEngine::instance()->setup_required ();
1180
1181         build_notebook ();
1182         setup_midi_tab_for_backend ();
1183         _midi_devices.clear();
1184
1185         if (backend->requires_driver_selection()) {
1186                 if (set_driver_popdown_strings ()) {
1187                         driver_changed ();
1188                 }
1189         } else {
1190                 /* this will change the device text which will cause a call to
1191                  * device changed which will set up parameters
1192                  */
1193                 list_devices ();
1194         }
1195
1196         update_midi_options ();
1197
1198         connect_disconnect_button.hide();
1199
1200         midi_option_changed();
1201
1202         started_at_least_once = false;
1203
1204         /* changing the backend implies stopping the engine
1205          * ARDOUR::AudioEngine() may or may not emit this signal
1206          * depending on previous engine state
1207          */
1208         engine_stopped (); // set "active/inactive"
1209
1210         if (!_have_control) {
1211                 // set settings from backend that we do have control over
1212                 set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
1213         }
1214
1215         if (_have_control && !ignore_changes) {
1216                 // set driver & devices
1217                 State state = get_matching_state (backend_combo.get_active_text());
1218                 if (state) {
1219                         PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1220                         set_current_state (state);
1221                 }
1222         }
1223
1224         if (!ignore_changes) {
1225                 maybe_display_saved_state ();
1226         }
1227 }
1228
1229 void
1230 EngineControl::update_midi_options ()
1231 {
1232         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1233         vector<string> midi_options = backend->enumerate_midi_options();
1234
1235         if (midi_options.size() == 1) {
1236                 /* only contains the "none" option */
1237                 midi_option_combo.set_sensitive (false);
1238         } else {
1239                 if (_have_control) {
1240                         set_popdown_strings (midi_option_combo, midi_options);
1241                         midi_option_combo.set_active_text (midi_options.front());
1242                         midi_option_combo.set_sensitive (true);
1243                 } else {
1244                         midi_option_combo.set_sensitive (false);
1245                 }
1246         }
1247 }
1248
1249 bool
1250 EngineControl::print_channel_count (Gtk::SpinButton* sb)
1251 {
1252         if (ARDOUR::Profile->get_mixbus()) {
1253                 return true;
1254         }
1255
1256         uint32_t cnt = (uint32_t) sb->get_value();
1257         if (cnt == 0) {
1258                 sb->set_text (_("all available channels"));
1259         } else {
1260                 char buf[32];
1261                 snprintf (buf, sizeof (buf), "%d", cnt);
1262                 sb->set_text (buf);
1263         }
1264         return true;
1265 }
1266
1267 // @return true if there are drivers available
1268 bool
1269 EngineControl::set_driver_popdown_strings ()
1270 {
1271         DEBUG_ECONTROL ("set_driver_popdown_strings");
1272         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1273         vector<string> drivers = backend->enumerate_drivers();
1274
1275         if (drivers.empty ()) {
1276                 // This is an error...?
1277                 return false;
1278         }
1279
1280         string current_driver = backend->driver_name ();
1281
1282         DEBUG_ECONTROL (string_compose ("backend->driver_name: %1", current_driver));
1283
1284         if (std::find (drivers.begin (), drivers.end (), current_driver) ==
1285             drivers.end ()) {
1286
1287                 current_driver = drivers.front ();
1288         }
1289
1290         set_popdown_strings (driver_combo, drivers);
1291         DEBUG_ECONTROL (
1292             string_compose ("driver_combo.set_active_text: %1", current_driver));
1293         driver_combo.set_active_text (current_driver);
1294         return true;
1295 }
1296
1297 std::string
1298 EngineControl::get_default_device(const string& current_device_name,
1299                                   const vector<string>& available_devices)
1300 {
1301         // If the current device is available, use it as default
1302         if (std::find (available_devices.begin (),
1303                        available_devices.end (),
1304                        current_device_name) != available_devices.end ()) {
1305
1306                 return current_device_name;
1307         }
1308
1309         using namespace ARDOUR;
1310
1311         string default_device_name =
1312             AudioBackend::get_standard_device_name(AudioBackend::DeviceDefault);
1313
1314         vector<string>::const_iterator i;
1315
1316         // If there is a "Default" device available, use it
1317         for (i = available_devices.begin(); i != available_devices.end(); ++i) {
1318                 if (*i == default_device_name) {
1319                         return *i;
1320                 }
1321         }
1322
1323         string none_device_name =
1324             AudioBackend::get_standard_device_name(AudioBackend::DeviceNone);
1325
1326         // Use the first device that isn't "None"
1327         for (i = available_devices.begin(); i != available_devices.end(); ++i) {
1328                 if (*i != none_device_name) {
1329                         return *i;
1330                 }
1331         }
1332
1333         // Use "None" if there are no other available
1334         return available_devices.front();
1335 }
1336
1337 // @return true if there are devices available
1338 bool
1339 EngineControl::set_device_popdown_strings ()
1340 {
1341         DEBUG_ECONTROL ("set_device_popdown_strings");
1342         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1343         vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_devices ();
1344
1345         /* NOTE: Ardour currently does not display the "available" field of the
1346          * returned devices.
1347          *
1348          * Doing so would require a different GUI widget than the combo
1349          * box/popdown that we currently use, since it has no way to list
1350          * items that are not selectable. Something more like a popup menu,
1351          * which could have unselectable items, would be appropriate.
1352          */
1353
1354         vector<string> available_devices;
1355
1356         for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1357                 available_devices.push_back (i->name);
1358         }
1359
1360         if (available_devices.empty ()) {
1361                 return false;
1362         }
1363
1364         set_popdown_strings (device_combo, available_devices);
1365
1366         std::string default_device =
1367             get_default_device(backend->device_name(), available_devices);
1368
1369         DEBUG_ECONTROL (
1370             string_compose ("set device_combo active text: %1", default_device));
1371
1372         device_combo.set_active_text(default_device);
1373         return true;
1374 }
1375
1376 // @return true if there are input devices available
1377 bool
1378 EngineControl::set_input_device_popdown_strings ()
1379 {
1380         DEBUG_ECONTROL ("set_input_device_popdown_strings");
1381         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1382         vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_input_devices ();
1383
1384         vector<string> available_devices;
1385
1386         for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1387                 available_devices.push_back (i->name);
1388         }
1389
1390         if (available_devices.empty()) {
1391                 return false;
1392         }
1393
1394         set_popdown_strings (input_device_combo, available_devices);
1395
1396         std::string default_device =
1397             get_default_device(backend->input_device_name(), available_devices);
1398
1399         DEBUG_ECONTROL (
1400             string_compose ("set input_device_combo active text: %1", default_device));
1401         input_device_combo.set_active_text(default_device);
1402         return true;
1403 }
1404
1405 // @return true if there are output devices available
1406 bool
1407 EngineControl::set_output_device_popdown_strings ()
1408 {
1409         DEBUG_ECONTROL ("set_output_device_popdown_strings");
1410         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1411         vector<ARDOUR::AudioBackend::DeviceStatus> all_devices = backend->enumerate_output_devices ();
1412
1413         vector<string> available_devices;
1414
1415         for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = all_devices.begin(); i != all_devices.end(); ++i) {
1416                 available_devices.push_back (i->name);
1417         }
1418
1419         if (available_devices.empty()) {
1420                 return false;
1421         }
1422
1423         set_popdown_strings (output_device_combo, available_devices);
1424
1425         std::string default_device =
1426             get_default_device(backend->output_device_name(), available_devices);
1427
1428         DEBUG_ECONTROL (
1429             string_compose ("set output_device_combo active text: %1", default_device));
1430         output_device_combo.set_active_text(default_device);
1431         return true;
1432 }
1433
1434 void
1435 EngineControl::list_devices ()
1436 {
1437         DEBUG_ECONTROL ("list_devices");
1438         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1439         assert (backend);
1440
1441         /* now fill out devices, mark sample rates, buffer sizes insensitive */
1442
1443         bool devices_available = false;
1444
1445         if (backend->use_separate_input_and_output_devices ()) {
1446                 bool input_devices_available = set_input_device_popdown_strings ();
1447                 bool output_devices_available = set_output_device_popdown_strings ();
1448                 devices_available = input_devices_available || output_devices_available;
1449         } else {
1450                 devices_available = set_device_popdown_strings ();
1451         }
1452
1453         if (devices_available) {
1454                 device_changed ();
1455         } else {
1456                 device_combo.clear();
1457                 input_device_combo.clear();
1458                 output_device_combo.clear();
1459         }
1460         update_sensitivity ();
1461 }
1462
1463 void
1464 EngineControl::driver_changed ()
1465 {
1466         SignalBlocker blocker (*this, "driver_changed");
1467         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1468         assert (backend);
1469
1470         backend->set_driver (driver_combo.get_active_text());
1471         list_devices ();
1472
1473         // TODO load LRU device(s) for backend + driver combo
1474
1475         if (!ignore_changes) {
1476                 maybe_display_saved_state ();
1477         }
1478 }
1479
1480 vector<float>
1481 EngineControl::get_sample_rates_for_all_devices ()
1482 {
1483         boost::shared_ptr<ARDOUR::AudioBackend> backend =
1484             ARDOUR::AudioEngine::instance ()->current_backend ();
1485         vector<float> all_rates;
1486
1487         if (backend->use_separate_input_and_output_devices ()) {
1488                 all_rates = backend->available_sample_rates2 (get_input_device_name (), get_output_device_name ());
1489         } else {
1490                 all_rates = backend->available_sample_rates (get_device_name ());
1491         }
1492         return all_rates;
1493 }
1494
1495 vector<float>
1496 EngineControl::get_default_sample_rates ()
1497 {
1498         vector<float> rates;
1499         rates.push_back (8000.0f);
1500         rates.push_back (16000.0f);
1501         rates.push_back (32000.0f);
1502         rates.push_back (44100.0f);
1503         rates.push_back (48000.0f);
1504         rates.push_back (88200.0f);
1505         rates.push_back (96000.0f);
1506         rates.push_back (192000.0f);
1507         rates.push_back (384000.0f);
1508         return rates;
1509 }
1510
1511 void
1512 EngineControl::set_samplerate_popdown_strings ()
1513 {
1514         DEBUG_ECONTROL ("set_samplerate_popdown_strings");
1515         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1516         string desired;
1517         vector<float> sr;
1518         vector<string> s;
1519
1520         if (_have_control) {
1521                 sr = get_sample_rates_for_all_devices ();
1522         } else {
1523                 sr = get_default_sample_rates ();
1524         }
1525
1526         for (vector<float>::const_iterator x = sr.begin(); x != sr.end(); ++x) {
1527                 s.push_back (rate_as_string (*x));
1528                 if (*x == _desired_sample_rate) {
1529                         desired = s.back();
1530                 }
1531         }
1532
1533         set_popdown_strings (sample_rate_combo, s);
1534
1535         if (!s.empty()) {
1536                 if (ARDOUR::AudioEngine::instance()->running()) {
1537                         sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
1538                 }
1539                 else if (desired.empty ()) {
1540                         float new_active_sr = backend->default_sample_rate ();
1541
1542                         if (std::find (sr.begin (), sr.end (), new_active_sr) == sr.end ()) {
1543                                 new_active_sr = sr.front ();
1544                         }
1545
1546                         sample_rate_combo.set_active_text (rate_as_string (new_active_sr));
1547                 } else {
1548                         sample_rate_combo.set_active_text (desired);
1549                 }
1550
1551         }
1552         update_sensitivity ();
1553 }
1554
1555 vector<uint32_t>
1556 EngineControl::get_buffer_sizes_for_all_devices ()
1557 {
1558         boost::shared_ptr<ARDOUR::AudioBackend> backend =
1559             ARDOUR::AudioEngine::instance ()->current_backend ();
1560         vector<uint32_t> all_sizes;
1561
1562         if (backend->use_separate_input_and_output_devices ()) {
1563                 all_sizes = backend->available_buffer_sizes2 (get_input_device_name (), get_output_device_name ());
1564         } else {
1565                 all_sizes = backend->available_buffer_sizes (get_device_name ());
1566         }
1567         return all_sizes;
1568 }
1569
1570 vector<uint32_t>
1571 EngineControl::get_default_buffer_sizes ()
1572 {
1573         vector<uint32_t> sizes;
1574         sizes.push_back (8);
1575         sizes.push_back (16);
1576         sizes.push_back (32);
1577         sizes.push_back (64);
1578         sizes.push_back (128);
1579         sizes.push_back (256);
1580         sizes.push_back (512);
1581         sizes.push_back (1024);
1582         sizes.push_back (2048);
1583         sizes.push_back (4096);
1584         sizes.push_back (8192);
1585         return sizes;
1586 }
1587
1588 void
1589 EngineControl::set_buffersize_popdown_strings ()
1590 {
1591         DEBUG_ECONTROL ("set_buffersize_popdown_strings");
1592         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1593         vector<uint32_t> bs;
1594         vector<string> s;
1595
1596         if (_have_control) {
1597                 bs = get_buffer_sizes_for_all_devices ();
1598         } else if (backend->can_change_buffer_size_when_running()) {
1599                 bs = get_default_buffer_sizes ();
1600         }
1601
1602         for (vector<uint32_t>::const_iterator x = bs.begin(); x != bs.end(); ++x) {
1603                 s.push_back (bufsize_as_string (*x));
1604         }
1605
1606         uint32_t previous_size = 0;
1607         if (!buffer_size_combo.get_active_text().empty()) {
1608                 previous_size = get_buffer_size ();
1609         }
1610
1611         set_popdown_strings (buffer_size_combo, s);
1612
1613         if (!s.empty()) {
1614
1615                 if (std::find(bs.begin(), bs.end(), previous_size) != bs.end()) {
1616                         buffer_size_combo.set_active_text(bufsize_as_string(previous_size));
1617                 } else {
1618
1619                         buffer_size_combo.set_active_text(s.front());
1620
1621                         uint32_t period = backend->buffer_size();
1622                         if (0 == period && backend->use_separate_input_and_output_devices()) {
1623                                 period = backend->default_buffer_size(get_input_device_name());
1624                         }
1625                         if (0 == period && backend->use_separate_input_and_output_devices()) {
1626                                 period = backend->default_buffer_size(get_output_device_name());
1627                         }
1628                         if (0 == period && !backend->use_separate_input_and_output_devices()) {
1629                                 period = backend->default_buffer_size(get_device_name());
1630                         }
1631
1632                         set_active_text_if_present(buffer_size_combo, bufsize_as_string(period));
1633                 }
1634                 show_buffer_duration ();
1635         }
1636         update_sensitivity ();
1637 }
1638
1639 void
1640 EngineControl::set_nperiods_popdown_strings ()
1641 {
1642         DEBUG_ECONTROL ("set_nperiods_popdown_strings");
1643         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1644         vector<uint32_t> np;
1645         vector<string> s;
1646
1647         if (backend->can_set_period_size()) {
1648                 np = backend->available_period_sizes (get_driver());
1649         }
1650
1651         for (vector<uint32_t>::const_iterator x = np.begin(); x != np.end(); ++x) {
1652                 s.push_back (nperiods_as_string (*x));
1653         }
1654
1655         set_popdown_strings (nperiods_combo, s);
1656
1657         if (!s.empty()) {
1658                 set_active_text_if_present (nperiods_combo, nperiods_as_string (backend->period_size())); // XXX
1659         }
1660
1661         update_sensitivity ();
1662 }
1663
1664 void
1665 EngineControl::device_changed ()
1666 {
1667         SignalBlocker blocker (*this, "device_changed");
1668         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1669         assert (backend);
1670
1671         string device_name_in;
1672         string device_name_out; // only used if backend support separate I/O devices
1673
1674         if (backend->use_separate_input_and_output_devices()) {
1675                 device_name_in  = get_input_device_name ();
1676                 device_name_out = get_output_device_name ();
1677         } else {
1678                 device_name_in = get_device_name ();
1679         }
1680
1681         /* we set the backend-device to query various device related intormation.
1682          * This has the side effect that backend->device_name() will match
1683          * the device_name and  'change_device' will never be true.
1684          * so work around this by setting...
1685          */
1686         if (backend->use_separate_input_and_output_devices()) {
1687                 if (device_name_in != backend->input_device_name() || device_name_out != backend->output_device_name ()) {
1688                         queue_device_changed = true;
1689                 }
1690         } else {
1691                 if (device_name_in != backend->device_name()) {
1692                         queue_device_changed = true;
1693                 }
1694         }
1695
1696         //the device name must be set FIRST so ASIO can populate buffersizes and the control panel button
1697         if (backend->use_separate_input_and_output_devices()) {
1698                 backend->set_input_device_name (device_name_in);
1699                 backend->set_output_device_name (device_name_out);
1700         } else {
1701                 backend->set_device_name(device_name_in);
1702         }
1703
1704         {
1705                 /* don't allow programmatic change to combos to cause a
1706                    recursive call to this method.
1707                  */
1708                 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
1709
1710                 set_samplerate_popdown_strings ();
1711                 set_buffersize_popdown_strings ();
1712                 set_nperiods_popdown_strings ();
1713
1714                 /* TODO set min + max channel counts here */
1715
1716                 manage_control_app_sensitivity ();
1717         }
1718
1719         /* pick up any saved state for this device */
1720
1721         if (!ignore_changes) {
1722                 maybe_display_saved_state ();
1723         }
1724 }
1725
1726 void
1727 EngineControl::input_device_changed ()
1728 {
1729         DEBUG_ECONTROL ("input_device_changed");
1730         device_changed ();
1731 }
1732
1733 void
1734 EngineControl::output_device_changed ()
1735 {
1736         DEBUG_ECONTROL ("output_device_changed");
1737         device_changed ();
1738 }
1739
1740 string
1741 EngineControl::bufsize_as_string (uint32_t sz)
1742 {
1743         return string_compose (P_("%1 sample", "%1 samples", sz), sz);
1744 }
1745
1746 string
1747 EngineControl::nperiods_as_string (uint32_t np)
1748 {
1749         char buf[8];
1750         snprintf (buf, sizeof (buf), "%u", np);
1751         return buf;
1752 }
1753
1754
1755 void
1756 EngineControl::sample_rate_changed ()
1757 {
1758         DEBUG_ECONTROL ("sample_rate_changed");
1759         /* reset the strings for buffer size to show the correct msec value
1760            (reflecting the new sample rate).
1761          */
1762
1763         show_buffer_duration ();
1764
1765 }
1766
1767 void
1768 EngineControl::buffer_size_changed ()
1769 {
1770         DEBUG_ECONTROL ("buffer_size_changed");
1771         show_buffer_duration ();
1772 }
1773
1774 void
1775 EngineControl::nperiods_changed ()
1776 {
1777         DEBUG_ECONTROL ("nperiods_changed");
1778         show_buffer_duration ();
1779 }
1780
1781 void
1782 EngineControl::show_buffer_duration ()
1783 {
1784         DEBUG_ECONTROL ("show_buffer_duration");
1785         /* buffer sizes  - convert from just samples to samples + msecs for
1786          * the displayed string
1787          */
1788
1789         string bs_text = buffer_size_combo.get_active_text ();
1790         uint32_t samples = atoi (bs_text); /* will ignore trailing text */
1791         uint32_t rate = get_rate();
1792
1793         /* Except for ALSA and Dummy backends, we don't know the number of periods
1794          * per cycle and settings.
1795          *
1796          * jack1 vs jack2 have different default latencies since jack2 start
1797          * in async-mode unless --sync is given which adds an extra cycle
1798          * of latency. The value is not known if jackd is started externally..
1799          *
1800          * So just display the period size, that's also what
1801          * ARDOUR_UI::update_sample_rate() does for the status bar.
1802          * (the statusbar calls AudioEngine::instance()->usecs_per_cycle()
1803          * but still, that's the buffer period, not [round-trip] latency)
1804          */
1805         char buf[32];
1806         snprintf (buf, sizeof (buf), _("(%.1f ms)"), (samples / (rate/1000.0f)));
1807         buffer_size_duration_label.set_text (buf);
1808 }
1809
1810 void
1811 EngineControl::midi_option_changed ()
1812 {
1813         DEBUG_ECONTROL ("midi_option_changed");
1814         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1815         assert (backend);
1816
1817         backend->set_midi_option (get_midi_option());
1818
1819         vector<ARDOUR::AudioBackend::DeviceStatus> midi_devices = backend->enumerate_midi_devices();
1820
1821         //_midi_devices.clear(); // TODO merge with state-saved settings..
1822         _can_set_midi_latencies = backend->can_set_systemic_midi_latencies();
1823         std::vector<MidiDeviceSettings> new_devices;
1824
1825         for (vector<ARDOUR::AudioBackend::DeviceStatus>::const_iterator i = midi_devices.begin(); i != midi_devices.end(); ++i) {
1826                 MidiDeviceSettings mds = find_midi_device (i->name);
1827                 if (i->available && !mds) {
1828                         uint32_t input_latency = 0;
1829                         uint32_t output_latency = 0;
1830                         if (_can_set_midi_latencies) {
1831                                 input_latency = backend->systemic_midi_input_latency (i->name);
1832                                 output_latency = backend->systemic_midi_output_latency (i->name);
1833                         }
1834                         bool enabled = backend->midi_device_enabled (i->name);
1835                         MidiDeviceSettings ptr (new MidiDeviceSetting (i->name, enabled, input_latency, output_latency));
1836                         new_devices.push_back (ptr);
1837                 } else if (i->available) {
1838                         new_devices.push_back (mds);
1839                 }
1840         }
1841         _midi_devices = new_devices;
1842
1843         if (_midi_devices.empty()) {
1844                 midi_devices_button.hide ();
1845         } else {
1846                 midi_devices_button.show ();
1847         }
1848 }
1849
1850 void
1851 EngineControl::parameter_changed ()
1852 {
1853 }
1854
1855 EngineControl::State
1856 EngineControl::get_matching_state (const string& backend)
1857 {
1858         for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1859                 if ((*i)->backend == backend) {
1860                         return (*i);
1861                 }
1862         }
1863         return State();
1864 }
1865
1866 EngineControl::State
1867 EngineControl::get_matching_state (
1868                 const string& backend,
1869                 const string& driver,
1870                 const string& device)
1871 {
1872         for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1873                 if ((*i)->backend == backend &&
1874                                 (!_have_control || ((*i)->driver == driver && (*i)->device == device)))
1875                 {
1876                         return (*i);
1877                 }
1878         }
1879         return State();
1880 }
1881
1882 EngineControl::State
1883 EngineControl::get_matching_state (
1884                 const string& backend,
1885                 const string& driver,
1886                 const string& input_device,
1887                 const string& output_device)
1888 {
1889         for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
1890                 if ((*i)->backend == backend &&
1891                                 (!_have_control || ((*i)->driver == driver && ((*i)->input_device == input_device) && (*i)->output_device == output_device)))
1892                 {
1893                         return (*i);
1894                 }
1895         }
1896         return State();
1897 }
1898
1899 EngineControl::State
1900 EngineControl::get_saved_state_for_currently_displayed_backend_and_device ()
1901 {
1902         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
1903
1904         if (backend) {
1905                 if (backend->use_separate_input_and_output_devices ()) {
1906                         return get_matching_state (backend_combo.get_active_text(),
1907                                         (backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
1908                                         input_device_combo.get_active_text(),
1909                                         output_device_combo.get_active_text());
1910                 } else {
1911                         return get_matching_state (backend_combo.get_active_text(),
1912                                         (backend->requires_driver_selection() ? (std::string) driver_combo.get_active_text() : string()),
1913                                         device_combo.get_active_text());
1914                 }
1915         }
1916
1917         return get_matching_state (backend_combo.get_active_text(),
1918                         string(),
1919                         device_combo.get_active_text());
1920 }
1921
1922 bool EngineControl::equivalent_states (const EngineControl::State& state1,
1923                                        const EngineControl::State& state2)
1924 {
1925         if (state1->backend == state2->backend &&
1926                         state1->driver == state2->driver &&
1927                         state1->device == state2->device &&
1928                         state1->input_device == state2->input_device &&
1929                         state1->output_device == state2->output_device) {
1930                 return true;
1931         }
1932         return false;
1933 }
1934
1935 bool
1936 EngineControl::state_sort_cmp (const State &a, const State &b) {
1937         if (a->active) {
1938                 return true;
1939         }
1940         else if (b->active) {
1941                 return false;
1942         }
1943         else {
1944                 return a->lru < b->lru;
1945         }
1946 }
1947
1948 EngineControl::State
1949 EngineControl::save_state ()
1950 {
1951         State state;
1952
1953         if (!_have_control) {
1954                 state = get_matching_state (backend_combo.get_active_text(), string(), string());
1955                 if (state) {
1956                         state->lru = time (NULL) ;
1957                         return state;
1958                 }
1959                 state.reset(new StateStruct);
1960                 state->backend = get_backend ();
1961         } else {
1962                 state.reset(new StateStruct);
1963                 store_state (state);
1964         }
1965
1966         for (StateList::iterator i = states.begin(); i != states.end();) {
1967                 if (equivalent_states (*i, state)) {
1968                         i =  states.erase(i);
1969                 } else {
1970                         ++i;
1971                 }
1972         }
1973
1974         states.push_back (state);
1975
1976         states.sort (state_sort_cmp);
1977
1978         return state;
1979 }
1980
1981 void
1982 EngineControl::store_state (State state)
1983 {
1984         state->backend = get_backend ();
1985         state->driver = get_driver ();
1986         state->device = get_device_name ();
1987         state->input_device = get_input_device_name ();
1988         state->output_device = get_output_device_name ();
1989         state->sample_rate = get_rate ();
1990         state->buffer_size = get_buffer_size ();
1991         state->n_periods = get_nperiods ();
1992         state->input_latency = get_input_latency ();
1993         state->output_latency = get_output_latency ();
1994         state->input_channels = get_input_channels ();
1995         state->output_channels = get_output_channels ();
1996         state->midi_option = get_midi_option ();
1997         state->midi_devices = _midi_devices;
1998         state->use_buffered_io = get_use_buffered_io ();
1999         state->lru = time (NULL) ;
2000 }
2001
2002 void
2003 EngineControl::maybe_display_saved_state ()
2004 {
2005         if (!_have_control) {
2006                 return;
2007         }
2008
2009         State state = get_saved_state_for_currently_displayed_backend_and_device ();
2010
2011         if (state) {
2012                 DEBUG_ECONTROL ("Restoring saved state");
2013                 PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
2014
2015                 if (!_desired_sample_rate) {
2016                         sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
2017                 }
2018                 set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
2019
2020                 set_active_text_if_present (nperiods_combo, nperiods_as_string (state->n_periods));
2021                 /* call this explicitly because we're ignoring changes to
2022                    the controls at this point.
2023                  */
2024                 show_buffer_duration ();
2025                 input_latency.set_value (state->input_latency);
2026                 output_latency.set_value (state->output_latency);
2027
2028                 use_buffered_io_button.set_active (state->use_buffered_io);
2029
2030                 if (!state->midi_option.empty()) {
2031                         midi_option_combo.set_active_text (state->midi_option);
2032                         _midi_devices = state->midi_devices;
2033                 }
2034         } else {
2035                 DEBUG_ECONTROL ("Unable to find saved state for backend and devices");
2036         }
2037 }
2038
2039 XMLNode&
2040 EngineControl::get_state ()
2041 {
2042         LocaleGuard lg;
2043
2044         XMLNode* root = new XMLNode ("AudioMIDISetup");
2045         std::string path;
2046
2047         if (!states.empty()) {
2048                 XMLNode* state_nodes = new XMLNode ("EngineStates");
2049
2050                 for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
2051
2052                         XMLNode* node = new XMLNode ("State");
2053
2054                         node->add_property ("backend", (*i)->backend);
2055                         node->add_property ("driver", (*i)->driver);
2056                         node->add_property ("device", (*i)->device);
2057                         node->add_property ("input-device", (*i)->input_device);
2058                         node->add_property ("output-device", (*i)->output_device);
2059                         node->add_property ("sample-rate", (*i)->sample_rate);
2060                         node->add_property ("buffer-size", (*i)->buffer_size);
2061                         node->add_property ("n-periods", (*i)->n_periods);
2062                         node->add_property ("input-latency", (*i)->input_latency);
2063                         node->add_property ("output-latency", (*i)->output_latency);
2064                         node->add_property ("input-channels", (*i)->input_channels);
2065                         node->add_property ("output-channels", (*i)->output_channels);
2066                         node->add_property ("active", (*i)->active ? "yes" : "no");
2067                         node->add_property ("use-buffered-io", (*i)->use_buffered_io ? "yes" : "no");
2068                         node->add_property ("midi-option", (*i)->midi_option);
2069                         node->add_property ("lru", (*i)->active ? time (NULL) : (*i)->lru);
2070
2071                         XMLNode* midi_devices = new XMLNode ("MIDIDevices");
2072                         for (std::vector<MidiDeviceSettings>::const_iterator p = (*i)->midi_devices.begin(); p != (*i)->midi_devices.end(); ++p) {
2073                                 XMLNode* midi_device_stuff = new XMLNode ("MIDIDevice");
2074                                 midi_device_stuff->add_property (X_("name"), (*p)->name);
2075                                 midi_device_stuff->add_property (X_("enabled"), (*p)->enabled);
2076                                 midi_device_stuff->add_property (X_("input-latency"), (*p)->input_latency);
2077                                 midi_device_stuff->add_property (X_("output-latency"), (*p)->output_latency);
2078                                 midi_devices->add_child_nocopy (*midi_device_stuff);
2079                         }
2080                         node->add_child_nocopy (*midi_devices);
2081
2082                         state_nodes->add_child_nocopy (*node);
2083                 }
2084
2085                 root->add_child_nocopy (*state_nodes);
2086         }
2087
2088         return *root;
2089 }
2090
2091 void
2092 EngineControl::set_default_state ()
2093 {
2094         vector<string> backend_names;
2095         vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
2096
2097         for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator b = backends.begin(); b != backends.end(); ++b) {
2098                 backend_names.push_back ((*b)->name);
2099         }
2100         backend_combo.set_active_text (backend_names.front());
2101
2102         // We could set default backends per platform etc here
2103
2104         backend_changed ();
2105 }
2106
2107 bool
2108 EngineControl::set_state (const XMLNode& root)
2109 {
2110         XMLNodeList          clist, cclist;
2111         XMLNodeConstIterator citer, cciter;
2112         XMLNode const * child;
2113         XMLNode const * grandchild;
2114         XMLProperty const * prop = NULL;
2115
2116         if (root.name() != "AudioMIDISetup") {
2117                 return false;
2118         }
2119
2120         clist = root.children();
2121
2122         states.clear ();
2123
2124         for (citer = clist.begin(); citer != clist.end(); ++citer) {
2125
2126                 child = *citer;
2127
2128                 if (child->name() != "EngineStates") {
2129                         continue;
2130                 }
2131
2132                 cclist = child->children();
2133
2134                 for (cciter = cclist.begin(); cciter != cclist.end(); ++cciter) {
2135                         State state (new StateStruct);
2136
2137                         grandchild = *cciter;
2138
2139                         if (grandchild->name() != "State") {
2140                                 continue;
2141                         }
2142
2143                         if ((prop = grandchild->property ("backend")) == 0) {
2144                                 continue;
2145                         }
2146                         state->backend = prop->value ();
2147
2148                         if ((prop = grandchild->property ("driver")) == 0) {
2149                                 continue;
2150                         }
2151                         state->driver = prop->value ();
2152
2153                         if ((prop = grandchild->property ("device")) == 0) {
2154                                 continue;
2155                         }
2156                         state->device = prop->value ();
2157
2158                         if ((prop = grandchild->property ("input-device")) == 0) {
2159                                 continue;
2160                         }
2161                         state->input_device = prop->value ();
2162
2163                         if ((prop = grandchild->property ("output-device")) == 0) {
2164                                 continue;
2165                         }
2166                         state->output_device = prop->value ();
2167
2168                         if ((prop = grandchild->property ("sample-rate")) == 0) {
2169                                 continue;
2170                         }
2171                         state->sample_rate = atof (prop->value ());
2172
2173                         if ((prop = grandchild->property ("buffer-size")) == 0) {
2174                                 continue;
2175                         }
2176                         state->buffer_size = atoi (prop->value ());
2177
2178                         if ((prop = grandchild->property ("n-periods")) == 0) {
2179                                 // optional (new value in 4.5)
2180                                 state->n_periods = 0;
2181                         } else {
2182                                 state->n_periods = atoi (prop->value ());
2183                         }
2184
2185                         if ((prop = grandchild->property ("input-latency")) == 0) {
2186                                 continue;
2187                         }
2188                         state->input_latency = atoi (prop->value ());
2189
2190                         if ((prop = grandchild->property ("output-latency")) == 0) {
2191                                 continue;
2192                         }
2193                         state->output_latency = atoi (prop->value ());
2194
2195                         if ((prop = grandchild->property ("input-channels")) == 0) {
2196                                 continue;
2197                         }
2198                         state->input_channels = atoi (prop->value ());
2199
2200                         if ((prop = grandchild->property ("output-channels")) == 0) {
2201                                 continue;
2202                         }
2203                         state->output_channels = atoi (prop->value ());
2204
2205                         if ((prop = grandchild->property ("active")) == 0) {
2206                                 continue;
2207                         }
2208                         state->active = string_is_affirmative (prop->value ());
2209
2210                         if ((prop = grandchild->property ("use-buffered-io")) == 0) {
2211                                 continue;
2212                         }
2213                         state->use_buffered_io = string_is_affirmative (prop->value ());
2214
2215                         if ((prop = grandchild->property ("midi-option")) == 0) {
2216                                 continue;
2217                         }
2218                         state->midi_option = prop->value ();
2219
2220                         state->midi_devices.clear();
2221                         XMLNode* midinode;
2222                         if ((midinode = ARDOUR::find_named_node (*grandchild, "MIDIDevices")) != 0) {
2223                                 const XMLNodeList mnc = midinode->children();
2224                                 for (XMLNodeList::const_iterator n = mnc.begin(); n != mnc.end(); ++n) {
2225                                         if ((*n)->property (X_("name")) == 0
2226                                                         || (*n)->property (X_("enabled")) == 0
2227                                                         || (*n)->property (X_("input-latency")) == 0
2228                                                         || (*n)->property (X_("output-latency")) == 0
2229                                                  ) {
2230                                                 continue;
2231                                         }
2232
2233                                         MidiDeviceSettings ptr (new MidiDeviceSetting(
2234                                                                 (*n)->property (X_("name"))->value (),
2235                                                                 string_is_affirmative ((*n)->property (X_("enabled"))->value ()),
2236                                                                 atoi ((*n)->property (X_("input-latency"))->value ()),
2237                                                                 atoi ((*n)->property (X_("output-latency"))->value ())
2238                                                                 ));
2239                                         state->midi_devices.push_back (ptr);
2240                                 }
2241                         }
2242
2243                         if ((prop = grandchild->property ("lru"))) {
2244                                 state->lru = atoi (prop->value ());
2245                         }
2246
2247 #if 1
2248                         /* remove accumulated duplicates (due to bug in ealier version)
2249                          * this can be removed again before release
2250                          */
2251                         for (StateList::iterator i = states.begin(); i != states.end();) {
2252                                 if ((*i)->backend == state->backend &&
2253                                                 (*i)->driver == state->driver &&
2254                                                 (*i)->device == state->device) {
2255                                         i =  states.erase(i);
2256                                 } else {
2257                                         ++i;
2258                                 }
2259                         }
2260 #endif
2261
2262                         states.push_back (state);
2263                 }
2264         }
2265
2266         /* now see if there was an active state and switch the setup to it */
2267
2268         // purge states of backend that are not available in this built
2269         vector<const ARDOUR::AudioBackendInfo*> backends = ARDOUR::AudioEngine::instance()->available_backends();
2270         vector<std::string> backend_names;
2271
2272         for (vector<const ARDOUR::AudioBackendInfo*>::const_iterator i = backends.begin(); i != backends.end(); ++i) {
2273                 backend_names.push_back((*i)->name);
2274         }
2275         for (StateList::iterator i = states.begin(); i != states.end();) {
2276                 if (std::find(backend_names.begin(), backend_names.end(), (*i)->backend) == backend_names.end()) {
2277                         i = states.erase(i);
2278                 } else {
2279                         ++i;
2280                 }
2281         }
2282
2283         states.sort (state_sort_cmp);
2284
2285         for (StateList::const_iterator i = states.begin(); i != states.end(); ++i) {
2286
2287                 if ((*i)->active) {
2288                         return set_current_state (*i);
2289                 }
2290         }
2291         return false;
2292 }
2293
2294 bool
2295 EngineControl::set_current_state (const State& state)
2296 {
2297         DEBUG_ECONTROL ("set_current_state");
2298
2299         boost::shared_ptr<ARDOUR::AudioBackend> backend;
2300
2301         if (!(backend = ARDOUR::AudioEngine::instance ()->set_backend (
2302                   state->backend, downcase (std::string(PROGRAM_NAME)), ""))) {
2303                 DEBUG_ECONTROL (string_compose ("Unable to set backend to %1", state->backend));
2304                 // this shouldn't happen as the invalid backend names should have been
2305                 // removed from the list of states.
2306                 return false;
2307         }
2308
2309         // now reflect the change in the backend in the GUI so backend_changed will
2310         // do the right thing
2311         backend_combo.set_active_text (state->backend);
2312
2313         if (!ARDOUR::AudioEngine::instance()->setup_required ()) {
2314                 backend_changed ();
2315                 // we don't have control don't restore state
2316                 return true;
2317         }
2318
2319
2320         if (!state->driver.empty ()) {
2321                 if (!backend->requires_driver_selection ()) {
2322                         DEBUG_ECONTROL ("Backend should require driver selection");
2323                         // A backend has changed from having driver selection to not having
2324                         // it or someone has been manually editing a config file and messed
2325                         // it up
2326                         return false;
2327                 }
2328
2329                 if (backend->set_driver (state->driver) != 0) {
2330                         DEBUG_ECONTROL (string_compose ("Unable to set driver %1", state->driver));
2331                         // Driver names for a backend have changed and the name in the
2332                         // config file is now invalid or support for driver is no longer
2333                         // included in the backend
2334                         return false;
2335                 }
2336                 // no need to set the driver_combo as backend_changed will use
2337                 // backend->driver_name to set the active driver
2338         }
2339
2340         if (!state->device.empty ()) {
2341                 if (backend->set_device_name (state->device) != 0) {
2342                         DEBUG_ECONTROL (
2343                             string_compose ("Unable to set device name %1", state->device));
2344                         // device is no longer available on the system
2345                         return false;
2346                 }
2347                 // no need to set active device as it will be picked up in
2348                 // via backend_changed ()/set_device_popdown_strings
2349
2350         } else {
2351                 // backend supports separate input/output devices
2352                 if (backend->set_input_device_name (state->input_device) != 0) {
2353                         DEBUG_ECONTROL (string_compose ("Unable to set input device name %1",
2354                                                         state->input_device));
2355                         // input device is no longer available on the system
2356                         return false;
2357                 }
2358
2359                 if (backend->set_output_device_name (state->output_device) != 0) {
2360                         DEBUG_ECONTROL (string_compose ("Unable to set output device name %1",
2361                                                         state->input_device));
2362                         // output device is no longer available on the system
2363                         return false;
2364                 }
2365                 // no need to set active devices as it will be picked up in via
2366                 // backend_changed ()/set_*_device_popdown_strings
2367         }
2368
2369         backend_changed ();
2370
2371         // Now restore the state of the rest of the controls
2372
2373         // We don't use a SignalBlocker as set_current_state is currently only
2374         // called from set_state before any signals are connected. If at some point
2375         // a more general named state mechanism is implemented and
2376         // set_current_state is called while signals are connected then a
2377         // SignalBlocker will need to be instantiated before setting these.
2378
2379         device_combo.set_active_text (state->device);
2380         input_device_combo.set_active_text (state->input_device);
2381         output_device_combo.set_active_text (state->output_device);
2382         if (!_desired_sample_rate) {
2383                 sample_rate_combo.set_active_text (rate_as_string (state->sample_rate));
2384         }
2385         set_active_text_if_present (buffer_size_combo, bufsize_as_string (state->buffer_size));
2386         set_active_text_if_present (nperiods_combo, nperiods_as_string (state->n_periods));
2387         input_latency.set_value (state->input_latency);
2388         output_latency.set_value (state->output_latency);
2389         midi_option_combo.set_active_text (state->midi_option);
2390         use_buffered_io_button.set_active (state->use_buffered_io);
2391         return true;
2392 }
2393
2394 int
2395 EngineControl::push_state_to_backend (bool start)
2396 {
2397         DEBUG_ECONTROL ("push_state_to_backend");
2398         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2399         PBD::Unwinder<uint32_t> protect_ignore_device_changes (ignore_device_changes, ignore_device_changes + 1);
2400
2401         if (!backend) {
2402                 return 0;
2403         }
2404
2405         /* figure out what is going to change */
2406
2407         bool restart_required = false;
2408         bool was_running = ARDOUR::AudioEngine::instance()->running();
2409         bool change_driver = false;
2410         bool change_device = false;
2411         bool change_rate = false;
2412         bool change_bufsize = false;
2413         bool change_nperiods = false;
2414         bool change_latency = false;
2415         bool change_channels = false;
2416         bool change_midi = false;
2417         bool change_buffered_io = false;
2418
2419         uint32_t ochan = get_output_channels ();
2420         uint32_t ichan = get_input_channels ();
2421
2422         if (_have_control) {
2423
2424                 if (started_at_least_once) {
2425
2426                         /* we can control the backend */
2427
2428                         if (backend->requires_driver_selection()) {
2429                                 if (get_driver() != backend->driver_name()) {
2430                                         change_driver = true;
2431                                 }
2432                         }
2433
2434                         if (backend->use_separate_input_and_output_devices()) {
2435                                 if (get_input_device_name() != backend->input_device_name()) {
2436                                         change_device = true;
2437                                 }
2438                                 if (get_output_device_name() != backend->output_device_name()) {
2439                                         change_device = true;
2440                                 }
2441                         } else {
2442                                 if (get_device_name() != backend->device_name()) {
2443                                         change_device = true;
2444                                 }
2445                         }
2446
2447                         if (queue_device_changed) {
2448                                 change_device = true;
2449                         }
2450
2451                         if (get_rate() != backend->sample_rate()) {
2452                                 change_rate = true;
2453                         }
2454
2455                         if (get_buffer_size() != backend->buffer_size()) {
2456                                 change_bufsize = true;
2457                         }
2458
2459                         if (backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0
2460                                         && get_nperiods() != backend->period_size()) {
2461                                 change_nperiods = true;
2462                         }
2463
2464                         if (get_midi_option() != backend->midi_option()) {
2465                                 change_midi = true;
2466                         }
2467
2468                         if (backend->can_use_buffered_io()) {
2469                                 if (get_use_buffered_io() != backend->get_use_buffered_io()) {
2470                                         change_buffered_io = true;
2471                                 }
2472                         }
2473
2474                         /* zero-requested channels means "all available" */
2475
2476                         if (ichan == 0) {
2477                                 ichan = backend->input_channels();
2478                         }
2479
2480                         if (ochan == 0) {
2481                                 ochan = backend->output_channels();
2482                         }
2483
2484                         if (ichan != backend->input_channels()) {
2485                                 change_channels = true;
2486                         }
2487
2488                         if (ochan != backend->output_channels()) {
2489                                 change_channels = true;
2490                         }
2491
2492                         if (get_input_latency() != backend->systemic_input_latency() ||
2493                                         get_output_latency() != backend->systemic_output_latency()) {
2494                                 change_latency = true;
2495                         }
2496                 } else {
2497                         /* backend never started, so we have to force a group
2498                            of settings.
2499                          */
2500                         change_device = true;
2501                         if (backend->requires_driver_selection()) {
2502                                 change_driver = true;
2503                         }
2504                         change_rate = true;
2505                         change_bufsize = true;
2506                         change_channels = true;
2507                         change_latency = true;
2508                         change_midi = true;
2509                         change_buffered_io = backend->can_use_buffered_io();
2510                         change_channels = true;
2511                         change_nperiods = backend->can_set_period_size() && get_popdown_string_count (nperiods_combo) > 0;
2512                 }
2513
2514         } else {
2515
2516                 /* we have no control over the backend, meaning that we can
2517                  * only possibly change sample rate and buffer size.
2518                  */
2519
2520
2521                 if (get_rate() != backend->sample_rate()) {
2522                         change_bufsize = true;
2523                 }
2524
2525                 if (get_buffer_size() != backend->buffer_size()) {
2526                         change_bufsize = true;
2527                 }
2528         }
2529
2530         queue_device_changed = false;
2531
2532         if (!_have_control) {
2533
2534                 /* We do not have control over the backend, so the best we can
2535                  * do is try to change the sample rate and/or bufsize and get
2536                  * out of here.
2537                  */
2538
2539                 if (change_rate && !backend->can_change_sample_rate_when_running()) {
2540                         return 1;
2541                 }
2542
2543                 if (change_bufsize && !backend->can_change_buffer_size_when_running()) {
2544                         return 1;
2545                 }
2546
2547                 if (change_rate) {
2548                         backend->set_sample_rate (get_rate());
2549                 }
2550
2551                 if (change_bufsize) {
2552                         backend->set_buffer_size (get_buffer_size());
2553                 }
2554
2555                 if (start) {
2556                         if (ARDOUR::AudioEngine::instance()->start ()) {
2557                                 error << string_compose (_("Could not start backend engine %1"), backend->name()) << endmsg;
2558                                 return -1;
2559                         }
2560                 }
2561
2562                 post_push ();
2563
2564                 return 0;
2565         }
2566
2567         /* determine if we need to stop the backend before changing parameters */
2568
2569         if (change_driver || change_device || change_channels || change_nperiods ||
2570                         (change_latency && !backend->can_change_systemic_latency_when_running ()) ||
2571                         (change_rate && !backend->can_change_sample_rate_when_running()) ||
2572                         change_midi || change_buffered_io ||
2573                         (change_bufsize && !backend->can_change_buffer_size_when_running())) {
2574                 restart_required = true;
2575         } else {
2576                 restart_required = false;
2577         }
2578
2579
2580         if (was_running) {
2581                 if (restart_required) {
2582                         if (ARDOUR::AudioEngine::instance()->stop()) {
2583                                 return -1;
2584                         }
2585                 }
2586         }
2587
2588         if (change_driver && backend->set_driver (get_driver())) {
2589                 error << string_compose (_("Cannot set driver to %1"), get_driver()) << endmsg;
2590                 return -1;
2591         }
2592         if (backend->use_separate_input_and_output_devices()) {
2593                 if (change_device && backend->set_input_device_name (get_input_device_name())) {
2594                         error << string_compose (_("Cannot set input device name to %1"), get_input_device_name()) << endmsg;
2595                         return -1;
2596                 }
2597                 if (change_device && backend->set_output_device_name (get_output_device_name())) {
2598                         error << string_compose (_("Cannot set output device name to %1"), get_output_device_name()) << endmsg;
2599                         return -1;
2600                 }
2601         } else {
2602                 if (change_device && backend->set_device_name (get_device_name())) {
2603                         error << string_compose (_("Cannot set device name to %1"), get_device_name()) << endmsg;
2604                         return -1;
2605                 }
2606         }
2607         if (change_rate && backend->set_sample_rate (get_rate())) {
2608                 error << string_compose (_("Cannot set sample rate to %1"), get_rate()) << endmsg;
2609                 return -1;
2610         }
2611         if (change_bufsize && backend->set_buffer_size (get_buffer_size())) {
2612                 error << string_compose (_("Cannot set buffer size to %1"), get_buffer_size()) << endmsg;
2613                 return -1;
2614         }
2615         if (change_nperiods && backend->set_peridod_size (get_nperiods())) {
2616                 error << string_compose (_("Cannot set periods to %1"), get_nperiods()) << endmsg;
2617                 return -1;
2618         }
2619
2620         if (change_channels || get_input_channels() == 0 || get_output_channels() == 0) {
2621                 if (backend->set_input_channels (get_input_channels())) {
2622                         error << string_compose (_("Cannot set input channels to %1"), get_input_channels()) << endmsg;
2623                         return -1;
2624                 }
2625                 if (backend->set_output_channels (get_output_channels())) {
2626                         error << string_compose (_("Cannot set output channels to %1"), get_output_channels()) << endmsg;
2627                         return -1;
2628                 }
2629         }
2630         if (change_latency) {
2631                 if (backend->set_systemic_input_latency (get_input_latency())) {
2632                         error << string_compose (_("Cannot set input latency to %1"), get_input_latency()) << endmsg;
2633                         return -1;
2634                 }
2635                 if (backend->set_systemic_output_latency (get_output_latency())) {
2636                         error << string_compose (_("Cannot set output latency to %1"), get_output_latency()) << endmsg;
2637                         return -1;
2638                 }
2639         }
2640
2641         if (change_midi) {
2642                 backend->set_midi_option (get_midi_option());
2643         }
2644
2645         if (change_buffered_io) {
2646                 backend->set_use_buffered_io (use_buffered_io_button.get_active());
2647         }
2648
2649         if (1 /* TODO */) {
2650                 for (vector<MidiDeviceSettings>::const_iterator p = _midi_devices.begin(); p != _midi_devices.end(); ++p) {
2651                         if (_measure_midi) {
2652                                 if (*p == _measure_midi) {
2653                                         backend->set_midi_device_enabled ((*p)->name, true);
2654                                 } else {
2655                                         backend->set_midi_device_enabled ((*p)->name, false);
2656                                 }
2657                                 if (backend->can_change_systemic_latency_when_running ()) {
2658                                         backend->set_systemic_midi_input_latency ((*p)->name, 0);
2659                                         backend->set_systemic_midi_output_latency ((*p)->name, 0);
2660                                 }
2661                                 continue;
2662                         }
2663                         backend->set_midi_device_enabled ((*p)->name, (*p)->enabled);
2664                         if (backend->can_set_systemic_midi_latencies()) {
2665                                 backend->set_systemic_midi_input_latency ((*p)->name, (*p)->input_latency);
2666                                 backend->set_systemic_midi_output_latency ((*p)->name, (*p)->output_latency);
2667                         }
2668                 }
2669         }
2670
2671         if (start || (was_running && restart_required)) {
2672                 if (ARDOUR::AudioEngine::instance()->start()) {
2673                         return -1;
2674                 }
2675         }
2676
2677         post_push ();
2678
2679         return 0;
2680 }
2681
2682 void
2683 EngineControl::post_push ()
2684 {
2685         /* get a pointer to the current state object, creating one if
2686          * necessary
2687          */
2688
2689         State state = get_saved_state_for_currently_displayed_backend_and_device ();
2690
2691         if (!state) {
2692                 state = save_state ();
2693                 assert (state);
2694         } else {
2695                 store_state(state);
2696         }
2697
2698         states.sort (state_sort_cmp);
2699
2700         /* all off */
2701
2702         for (StateList::iterator i = states.begin(); i != states.end(); ++i) {
2703                 (*i)->active = false;
2704         }
2705
2706         /* mark this one active (to be used next time the dialog is
2707          * shown)
2708          */
2709
2710         state->active = true;
2711
2712         if (_have_control) { // XXX
2713                 manage_control_app_sensitivity ();
2714         }
2715
2716         /* schedule a redisplay of MIDI ports */
2717         //Glib::signal_timeout().connect (sigc::bind_return (sigc::mem_fun (*this, &EngineControl::refresh_midi_display), false), 1000);
2718 }
2719
2720
2721 float
2722 EngineControl::get_rate () const
2723 {
2724         float r = atof (sample_rate_combo.get_active_text ());
2725         /* the string may have been translated with an abbreviation for
2726          * thousands, so use a crude heuristic to fix this.
2727          */
2728         if (r < 1000.0) {
2729                 r *= 1000.0;
2730         }
2731         return r;
2732 }
2733
2734
2735 uint32_t
2736 EngineControl::get_buffer_size () const
2737 {
2738         string txt = buffer_size_combo.get_active_text ();
2739         uint32_t samples;
2740
2741         if (sscanf (txt.c_str(), "%d", &samples) != 1) {
2742                 fprintf(stderr, "Find a trout and repeatedly slap the nearest C++ who throws exceptions without catching them.\n");
2743                 fprintf(stderr, "Ardour will likely crash now, giving you time to get the trout.\n");
2744                 throw exception ();
2745         }
2746
2747         return samples;
2748 }
2749
2750 uint32_t
2751 EngineControl::get_nperiods () const
2752 {
2753         string txt = nperiods_combo.get_active_text ();
2754         return atoi (txt.c_str());
2755 }
2756
2757 string
2758 EngineControl::get_midi_option () const
2759 {
2760         return midi_option_combo.get_active_text();
2761 }
2762
2763 bool
2764 EngineControl::get_use_buffered_io () const
2765 {
2766         return use_buffered_io_button.get_active();
2767 }
2768
2769 uint32_t
2770 EngineControl::get_input_channels() const
2771 {
2772         if (ARDOUR::Profile->get_mixbus()) {
2773                 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2774                 if (!backend) return 0;
2775                 return backend->input_channels();
2776         }
2777         return (uint32_t) input_channels_adjustment.get_value();
2778 }
2779
2780 uint32_t
2781 EngineControl::get_output_channels() const
2782 {
2783         if (ARDOUR::Profile->get_mixbus()) {
2784                 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2785                 if (!backend) return 0;
2786                 return backend->input_channels();
2787         }
2788         return (uint32_t) output_channels_adjustment.get_value();
2789 }
2790
2791 uint32_t
2792 EngineControl::get_input_latency() const
2793 {
2794         return (uint32_t) input_latency_adjustment.get_value();
2795 }
2796
2797 uint32_t
2798 EngineControl::get_output_latency() const
2799 {
2800         return (uint32_t) output_latency_adjustment.get_value();
2801 }
2802
2803 string
2804 EngineControl::get_backend () const
2805 {
2806         return backend_combo.get_active_text ();
2807 }
2808
2809 string
2810 EngineControl::get_driver () const
2811 {
2812         if (driver_combo.get_parent()) {
2813                 return driver_combo.get_active_text ();
2814         } else {
2815                 return "";
2816         }
2817 }
2818
2819 string
2820 EngineControl::get_device_name () const
2821 {
2822         return device_combo.get_active_text ();
2823 }
2824
2825 string
2826 EngineControl::get_input_device_name () const
2827 {
2828         return input_device_combo.get_active_text ();
2829 }
2830
2831 string
2832 EngineControl::get_output_device_name () const
2833 {
2834         return output_device_combo.get_active_text ();
2835 }
2836
2837 void
2838 EngineControl::control_app_button_clicked ()
2839 {
2840         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2841
2842         if (!backend) {
2843                 return;
2844         }
2845
2846         backend->launch_control_app ();
2847 }
2848
2849 void
2850 EngineControl::start_stop_button_clicked ()
2851 {
2852         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2853
2854         if (!backend) {
2855                 return;
2856         }
2857
2858         if (ARDOUR::AudioEngine::instance()->running()) {
2859                 ARDOUR::AudioEngine::instance()->stop ();
2860         } else {
2861                 start_engine ();
2862         }
2863 }
2864
2865 void
2866 EngineControl::update_devices_button_clicked ()
2867 {
2868         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2869
2870         if (!backend) {
2871                 return;
2872         }
2873
2874         if (backend->update_devices()) {
2875                 device_list_changed ();
2876         }
2877 }
2878
2879 void
2880 EngineControl::use_buffered_io_button_clicked ()
2881 {
2882         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2883
2884         if (!backend) {
2885                 return;
2886         }
2887
2888         bool set_buffered_io = !use_buffered_io_button.get_active();
2889         use_buffered_io_button.set_active (set_buffered_io);
2890         backend->set_use_buffered_io (set_buffered_io);
2891 }
2892
2893 void
2894 EngineControl::manage_control_app_sensitivity ()
2895 {
2896         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2897
2898         if (!backend) {
2899                 return;
2900         }
2901
2902         string appname = backend->control_app_name();
2903
2904         if (appname.empty()) {
2905                 control_app_button.set_sensitive (false);
2906         } else {
2907                 control_app_button.set_sensitive (true);
2908         }
2909 }
2910
2911 void
2912 EngineControl::set_desired_sample_rate (uint32_t sr)
2913 {
2914         _desired_sample_rate = sr;
2915         if (ARDOUR::AudioEngine::instance ()->running ()
2916                         && ARDOUR::AudioEngine::instance ()->sample_rate () != sr) {
2917                 stop_engine ();
2918         }
2919         device_changed ();
2920 }
2921
2922 void
2923 EngineControl::on_switch_page (GtkNotebookPage*, guint page_num)
2924 {
2925         if (page_num == 0) {
2926                 cancel_button->set_sensitive (true);
2927                 _measure_midi.reset();
2928                 update_sensitivity ();
2929         } else {
2930                 cancel_button->set_sensitive (false);
2931                 ok_button->set_sensitive (false);
2932         }
2933
2934         if (page_num == midi_tab) {
2935                 /* MIDI tab */
2936                 refresh_midi_display ();
2937         }
2938
2939         if (page_num == latency_tab) {
2940                 /* latency tab */
2941
2942                 if (ARDOUR::AudioEngine::instance()->running()) {
2943                         stop_engine (true);
2944                 }
2945
2946                 {
2947                         PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1);
2948
2949                         /* save any existing latency values */
2950
2951                         uint32_t il = (uint32_t) input_latency.get_value ();
2952                         uint32_t ol = (uint32_t) input_latency.get_value ();
2953
2954                         /* reset to zero so that our new test instance
2955                            will be clean of any existing latency measures.
2956
2957                            NB. this should really be done by the backend
2958                            when stated for latency measurement.
2959                         */
2960
2961                         input_latency.set_value (0);
2962                         output_latency.set_value (0);
2963
2964                         push_state_to_backend (false);
2965
2966                         /* reset control */
2967
2968                         input_latency.set_value (il);
2969                         output_latency.set_value (ol);
2970
2971                 }
2972                 // This should be done in push_state_to_backend()
2973                 if (ARDOUR::AudioEngine::instance()->prepare_for_latency_measurement()) {
2974                         disable_latency_tab ();
2975                 }
2976
2977                 enable_latency_tab ();
2978
2979         } else {
2980                 if (lm_running) {
2981                         end_latency_detection ();
2982                         ARDOUR::AudioEngine::instance()->stop_latency_detection();
2983                 }
2984         }
2985 }
2986
2987 /* latency measurement */
2988
2989 bool
2990 EngineControl::check_audio_latency_measurement ()
2991 {
2992         MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
2993
2994         if (mtdm->resolve () < 0) {
2995                 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
2996                 return true;
2997         }
2998
2999         if (mtdm->get_peak () > 0.707f) {
3000                 // get_peak() resets the peak-hold in the detector.
3001                 // this GUI callback is at 10Hz and so will be fine (test-signal is at higher freq)
3002                 lm_results.set_markup (string_compose (results_markup, _("Input signal is > -3dBFS. Lower the signal level (output gain, input gain) on the audio-interface.")));
3003                 return true;
3004         }
3005
3006         if (mtdm->err () > 0.3) {
3007                 mtdm->invert ();
3008                 mtdm->resolve ();
3009         }
3010
3011         char buf[256];
3012         ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3013
3014         if (sample_rate == 0) {
3015                 lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
3016                 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
3017                 return false;
3018         }
3019
3020         int frames_total = mtdm->del();
3021         int extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
3022
3023         snprintf (buf, sizeof (buf), "%s%d samples (%.3lf ms)\n%s%d samples (%.3lf ms)",
3024                         _("Detected roundtrip latency: "),
3025                         frames_total, frames_total * 1000.0f/sample_rate,
3026                         _("Systemic latency: "),
3027                         extra, extra * 1000.0f/sample_rate);
3028
3029         bool solid = true;
3030
3031         if (mtdm->err () > 0.2) {
3032                 strcat (buf, " ");
3033                 strcat (buf, _("(signal detection error)"));
3034                 solid = false;
3035         }
3036
3037         if (mtdm->inv ()) {
3038                 strcat (buf, " ");
3039                 strcat (buf, _("(inverted - bad wiring)"));
3040                 solid = false;
3041         }
3042
3043         lm_results.set_markup (string_compose (results_markup, buf));
3044
3045         if (solid) {
3046                 have_lm_results = true;
3047                 end_latency_detection ();
3048                 lm_use_button.set_sensitive (true);
3049                 return false;
3050         }
3051
3052         return true;
3053 }
3054
3055 bool
3056 EngineControl::check_midi_latency_measurement ()
3057 {
3058         ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
3059
3060         if (!mididm->have_signal () || mididm->latency () == 0) {
3061                 lm_results.set_markup (string_compose (results_markup, _("No signal detected ")));
3062                 return true;
3063         }
3064
3065         char buf[256];
3066         ARDOUR::framecnt_t const sample_rate = ARDOUR::AudioEngine::instance()->sample_rate();
3067
3068         if (sample_rate == 0) {
3069                 lm_results.set_markup (string_compose (results_markup, _("Disconnected from audio engine")));
3070                 ARDOUR::AudioEngine::instance()->stop_latency_detection ();
3071                 return false;
3072         }
3073
3074         ARDOUR::framecnt_t frames_total = mididm->latency();
3075         ARDOUR::framecnt_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
3076         snprintf (buf, sizeof (buf), "%s%" PRId64" samples (%.1lf ms) dev: %.2f[spl]\n%s%" PRId64" samples (%.1lf ms)",
3077                         _("Detected roundtrip latency: "),
3078                         frames_total, frames_total * 1000.0f / sample_rate, mididm->deviation (),
3079                         _("Systemic latency: "),
3080                         extra, extra * 1000.0f / sample_rate);
3081
3082         bool solid = true;
3083
3084         if (!mididm->ok ()) {
3085                 strcat (buf, " ");
3086                 strcat (buf, _("(averaging)"));
3087                 solid = false;
3088         }
3089
3090         if (mididm->deviation () > 50.0) {
3091                 strcat (buf, " ");
3092                 strcat (buf, _("(too large jitter)"));
3093                 solid = false;
3094         } else if (mididm->deviation () > 10.0) {
3095                 strcat (buf, " ");
3096                 strcat (buf, _("(large jitter)"));
3097         }
3098
3099         if (solid) {
3100                 have_lm_results = true;
3101                 end_latency_detection ();
3102                 lm_use_button.set_sensitive (true);
3103                 lm_results.set_markup (string_compose (results_markup, buf));
3104                 return false;
3105         } else if (mididm->processed () > 400) {
3106                 have_lm_results = false;
3107                 end_latency_detection ();
3108                 lm_results.set_markup (string_compose (results_markup, _("Timeout - large MIDI jitter.")));
3109                 return false;
3110         }
3111
3112         lm_results.set_markup (string_compose (results_markup, buf));
3113
3114         return true;
3115 }
3116
3117 void
3118 EngineControl::start_latency_detection ()
3119 {
3120         ARDOUR::AudioEngine::instance()->set_latency_input_port (lm_input_channel_combo.get_active_text());
3121         ARDOUR::AudioEngine::instance()->set_latency_output_port (lm_output_channel_combo.get_active_text());
3122
3123         if (ARDOUR::AudioEngine::instance()->start_latency_detection (_measure_midi ? true : false) == 0) {
3124                 lm_results.set_markup (string_compose (results_markup, _("Detecting ...")));
3125                 if (_measure_midi) {
3126                         latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_midi_latency_measurement), 100);
3127                 } else {
3128                         latency_timeout = Glib::signal_timeout().connect (mem_fun (*this, &EngineControl::check_audio_latency_measurement), 100);
3129                 }
3130                 lm_measure_label.set_text (_("Cancel"));
3131                 have_lm_results = false;
3132                 lm_use_button.set_sensitive (false);
3133                 lm_input_channel_combo.set_sensitive (false);
3134                 lm_output_channel_combo.set_sensitive (false);
3135                 lm_running = true;
3136         }
3137 }
3138
3139 void
3140 EngineControl::end_latency_detection ()
3141 {
3142         latency_timeout.disconnect ();
3143         ARDOUR::AudioEngine::instance()->stop_latency_detection ();
3144         lm_measure_label.set_text (_("Measure"));
3145         if (!have_lm_results) {
3146                 lm_use_button.set_sensitive (false);
3147         }
3148         lm_input_channel_combo.set_sensitive (true);
3149         lm_output_channel_combo.set_sensitive (true);
3150         lm_running = false;
3151 }
3152
3153 void
3154 EngineControl::latency_button_clicked ()
3155 {
3156         if (!lm_running) {
3157                 start_latency_detection ();
3158         } else {
3159                 end_latency_detection ();
3160         }
3161 }
3162
3163 void
3164 EngineControl::latency_back_button_clicked ()
3165 {
3166         ARDOUR::AudioEngine::instance()->stop(true);
3167         notebook.set_current_page(0);
3168 }
3169
3170 void
3171 EngineControl::use_latency_button_clicked ()
3172 {
3173         if (_measure_midi) {
3174                 ARDOUR::MIDIDM* mididm = ARDOUR::AudioEngine::instance()->mididm ();
3175                 if (!mididm) {
3176                         return;
3177                 }
3178                 ARDOUR::framecnt_t frames_total = mididm->latency();
3179                 ARDOUR::framecnt_t extra = frames_total - ARDOUR::AudioEngine::instance()->latency_signal_delay();
3180                 uint32_t one_way = max ((ARDOUR::framecnt_t) 0, extra / 2);
3181                 _measure_midi->input_latency = one_way;
3182                 _measure_midi->output_latency = one_way;
3183                 notebook.set_current_page (midi_tab);
3184         } else {
3185                 MTDM* mtdm = ARDOUR::AudioEngine::instance()->mtdm ();
3186
3187                 if (!mtdm) {
3188                         return;
3189                 }
3190
3191                 double one_way = rint ((mtdm->del() - ARDOUR::AudioEngine::instance()->latency_signal_delay()) / 2.0);
3192                 one_way = std::max (0., one_way);
3193
3194                 input_latency_adjustment.set_value (one_way);
3195                 output_latency_adjustment.set_value (one_way);
3196
3197                 /* back to settings page */
3198                 notebook.set_current_page (0);
3199         }
3200 }
3201
3202 bool
3203 EngineControl::on_delete_event (GdkEventAny* ev)
3204 {
3205         if (notebook.get_current_page() == 2) {
3206                 /* currently on latency tab - be sure to clean up */
3207                 end_latency_detection ();
3208         }
3209         return ArdourDialog::on_delete_event (ev);
3210 }
3211
3212 void
3213 EngineControl::engine_running ()
3214 {
3215         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3216         assert (backend);
3217
3218         set_active_text_if_present (buffer_size_combo, bufsize_as_string (backend->buffer_size()));
3219         sample_rate_combo.set_active_text (rate_as_string (backend->sample_rate()));
3220
3221         if (backend->can_set_period_size ()) {
3222                 set_active_text_if_present (nperiods_combo, nperiods_as_string (backend->period_size()));
3223         }
3224
3225         connect_disconnect_button.set_label (string_compose (_("Disconnect from %1"), backend->name()));
3226         connect_disconnect_button.show();
3227
3228         started_at_least_once = true;
3229         if (_have_control) {
3230                 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Running")));
3231         } else {
3232                 engine_status.set_markup(string_compose ("<span foreground=\"green\">%1</span>", _("Connected")));
3233         }
3234         update_sensitivity();
3235
3236         refill_midi_ports (true);
3237         refill_midi_ports (false);
3238 }
3239
3240 void
3241 EngineControl::engine_stopped ()
3242 {
3243         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
3244         assert (backend);
3245
3246         connect_disconnect_button.set_label (string_compose (_("Connect to %1"), backend->name()));
3247         connect_disconnect_button.show();
3248
3249         if (_have_control) {
3250                 engine_status.set_markup(string_compose ("<span foreground=\"red\">%1</span>", _("Stopped")));
3251         } else {
3252                 engine_status.set_markup(X_(""));
3253         }
3254
3255         update_sensitivity();
3256 }
3257
3258 void
3259 EngineControl::device_list_changed ()
3260 {
3261         if (ignore_device_changes) {
3262                 return;
3263         }
3264         PBD::Unwinder<uint32_t> protect_ignore_changes (ignore_changes, ignore_changes + 1); // ??
3265         list_devices ();
3266         midi_option_changed();
3267 }
3268
3269 void
3270 EngineControl::connect_disconnect_click()
3271 {
3272         if (ARDOUR::AudioEngine::instance()->running()) {
3273                 stop_engine ();
3274         } else {
3275                 start_engine ();
3276         }
3277 }
3278
3279 void
3280 EngineControl::calibrate_audio_latency ()
3281 {
3282         _measure_midi.reset ();
3283         have_lm_results = false;
3284         lm_use_button.set_sensitive (false);
3285         lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
3286         notebook.set_current_page (latency_tab);
3287 }
3288
3289 void
3290 EngineControl::calibrate_midi_latency (MidiDeviceSettings s)
3291 {
3292         _measure_midi = s;
3293         have_lm_results = false;
3294         lm_use_button.set_sensitive (false);
3295         lm_results.set_markup (string_compose (results_markup, _("No measurement results yet")));
3296         notebook.set_current_page (latency_tab);
3297 }
3298
3299 void
3300 EngineControl::configure_midi_devices ()
3301 {
3302         notebook.set_current_page (midi_tab);
3303 }