heuristic to workaround over-eager translation of NN000Hz as NN kHz
[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 <vector>
21 #include <cmath>
22 #include <fstream>
23 #include <map>
24
25 #include <boost/scoped_ptr.hpp>
26
27 #include <glibmm.h>
28 #include <gtkmm/messagedialog.h>
29
30 #include "pbd/epa.h"
31 #include "pbd/xml++.h"
32
33 #ifdef __APPLE__
34 #include <CoreAudio/CoreAudio.h>
35 #include <CoreFoundation/CFString.h>
36 #include <sys/param.h>
37 #include <mach-o/dyld.h>
38 #else
39 #include <alsa/asoundlib.h>
40 #endif
41
42 #include "ardour/profile.h"
43 #include <jack/jack.h>
44
45 #include <gtkmm/stock.h>
46 #include <gtkmm2ext/utils.h>
47
48 #include "pbd/convert.h"
49 #include "pbd/error.h"
50 #include "pbd/pathscanner.h"
51
52 #ifdef __APPLE
53 #include <CFBundle.h>
54 #endif
55
56 #include "engine_dialog.h"
57 #include "i18n.h"
58
59 using namespace std;
60 using namespace Gtk;
61 using namespace Gtkmm2ext;
62 using namespace PBD;
63 using namespace Glib;
64
65 EngineControl::EngineControl ()
66         : periods_adjustment (2, 2, 16, 1, 2),
67           periods_spinner (periods_adjustment),
68           priority_adjustment (60, 10, 90, 1, 10),
69           priority_spinner (priority_adjustment),
70           ports_adjustment (128, 8, 1024, 1, 16),
71           ports_spinner (ports_adjustment),
72           input_latency_adjustment (0, 0, 99999, 1),
73           input_latency (input_latency_adjustment),
74           output_latency_adjustment (0, 0, 99999, 1),
75           output_latency (output_latency_adjustment),
76           realtime_button (_("Realtime")),
77           no_memory_lock_button (_("Do not lock memory")),
78           unlock_memory_button (_("Unlock memory")),
79           soft_mode_button (_("No zombies")),
80           monitor_button (_("Provide monitor ports")),
81           force16bit_button (_("Force 16 bit")),
82           hw_monitor_button (_("H/W monitoring")),
83           hw_meter_button (_("H/W metering")),
84           verbose_output_button (_("Verbose output")),
85           start_button (_("Start")),
86           stop_button (_("Stop")),
87 #ifdef __APPLE__
88           basic_packer (5, 2),
89           options_packer (4, 2),
90           device_packer (4, 2)
91 #else
92           basic_packer (8, 2),
93           options_packer (14, 2),
94           device_packer (6, 2)
95 #endif
96 {
97         using namespace Notebook_Helpers;
98         Label* label;
99         vector<string> strings;
100         int row = 0;
101
102         _used = false;
103
104         strings.push_back (_("8000Hz"));
105         strings.push_back (_("22050Hz"));
106         strings.push_back (_("44100Hz"));
107         strings.push_back (_("48000Hz"));
108         strings.push_back (_("88200Hz"));
109         strings.push_back (_("96000Hz"));
110         strings.push_back (_("192000Hz"));
111         set_popdown_strings (sample_rate_combo, strings);
112         sample_rate_combo.set_active_text ("48000Hz");
113
114         strings.clear ();
115         strings.push_back ("32");
116         strings.push_back ("64");
117         strings.push_back ("128");
118         strings.push_back ("256");
119         strings.push_back ("512");
120         strings.push_back ("1024");
121         strings.push_back ("2048");
122         strings.push_back ("4096");
123         strings.push_back ("8192");
124         set_popdown_strings (period_size_combo, strings);
125         period_size_combo.set_active_text ("1024");
126
127         strings.clear ();
128         strings.push_back (_("None"));
129         strings.push_back (_("Triangular"));
130         strings.push_back (_("Rectangular"));
131         strings.push_back (_("Shaped"));
132         set_popdown_strings (dither_mode_combo, strings);
133         dither_mode_combo.set_active_text (_("None"));
134
135         /* basic parameters */
136
137         basic_packer.set_spacings (6);
138
139         strings.clear ();
140 #ifdef __APPLE__
141         strings.push_back (X_("CoreAudio"));
142 #else
143         strings.push_back (X_("ALSA"));
144         strings.push_back (X_("OSS"));
145         strings.push_back (X_("FreeBoB"));
146         strings.push_back (X_("FFADO"));
147 #endif
148         strings.push_back (X_("NetJACK"));
149         strings.push_back (X_("Dummy"));
150         set_popdown_strings (driver_combo, strings);
151         driver_combo.set_active_text (strings.front());
152
153         driver_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::driver_changed));
154         driver_changed ();
155
156         strings.clear ();
157         strings.push_back (_("Playback/recording on 1 device"));
158         strings.push_back (_("Playback/recording on 2 devices"));
159         strings.push_back (_("Playback only"));
160         strings.push_back (_("Recording only"));
161         set_popdown_strings (audio_mode_combo, strings);
162         audio_mode_combo.set_active_text (strings.front());
163
164         audio_mode_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::audio_mode_changed));
165         audio_mode_changed ();
166
167         strings.clear ();
168         strings.push_back (_("None"));
169         strings.push_back (_("seq"));
170         strings.push_back (_("raw"));
171         set_popdown_strings (midi_driver_combo, strings);
172         midi_driver_combo.set_active_text (strings.front ());
173
174         row = 0;
175
176         label = manage (new Label (_("Driver:")));
177         label->set_alignment (0, 0.5);
178         basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
179         basic_packer.attach (driver_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
180         row++;
181
182         label = manage (new Label (_("Audio|Interface:")));
183         label->set_alignment (0, 0.5);
184         basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
185         basic_packer.attach (interface_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
186         row++;
187
188         label = manage (new Label (_("Sample rate:")));
189         label->set_alignment (0, 0.5);
190         basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
191         basic_packer.attach (sample_rate_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
192         row++;
193
194         label = manage (new Label (_("Buffer size:")));
195         label->set_alignment (0, 0.5);
196         basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
197         basic_packer.attach (period_size_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
198         row++;
199
200 #ifndef __APPLE__
201         label = manage (new Label (_("Number of buffers:")));
202         label->set_alignment (0, 0.5);
203         basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
204         basic_packer.attach (periods_spinner, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
205         periods_spinner.set_value (2);
206         row++;
207 #endif
208
209         label = manage (new Label (_("Approximate latency:")));
210         label->set_alignment (0, 0.5);
211         basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
212         basic_packer.attach (latency_label, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
213         row++;
214
215         sample_rate_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::redisplay_latency));
216         periods_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &EngineControl::redisplay_latency));
217         period_size_combo.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::redisplay_latency));
218         redisplay_latency();
219         row++;
220         /* no audio mode with CoreAudio, its duplex or nuthin' */
221
222 #ifndef __APPLE__
223         label = manage (new Label (_("Audio mode:")));
224         label->set_alignment (0, 0.5);
225         basic_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
226         basic_packer.attach (audio_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
227         row++;
228 #endif
229
230         interface_combo.set_size_request (250, -1);
231         input_device_combo.set_size_request (250, -1);
232         output_device_combo.set_size_request (250, -1);
233
234         /*
235
236         if (engine_running()) {
237                 start_button.set_sensitive (false);
238         } else {
239                 stop_button.set_sensitive (false);
240         }
241
242         start_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::start_engine));
243         stop_button.signal_clicked().connect (sigc::mem_fun (*this, &EngineControl::start_engine));
244         */
245
246         button_box.pack_start (start_button, false, false);
247         button_box.pack_start (stop_button, false, false);
248
249         // basic_packer.attach (button_box, 0, 2, 8, 9, FILL|EXPAND, (AttachOptions) 0);
250
251         /* options */
252
253         options_packer.set_spacings (6);
254         row = 0;
255
256         options_packer.attach (realtime_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
257         ++row;
258
259         realtime_button.set_active (true);
260         realtime_button.signal_toggled().connect (sigc::mem_fun (*this, &EngineControl::realtime_changed));
261         realtime_changed ();
262
263 #if PROVIDE_TOO_MANY_OPTIONS
264
265 #ifndef __APPLE__
266         label = manage (new Label (_("Realtime Priority")));
267         label->set_alignment (1.0, 0.5);
268         options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
269         options_packer.attach (priority_spinner, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
270         ++row;
271         priority_spinner.set_value (60);
272
273         options_packer.attach (no_memory_lock_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
274         ++row;
275         options_packer.attach (unlock_memory_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
276         ++row;
277         options_packer.attach (soft_mode_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
278         ++row;
279         options_packer.attach (monitor_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
280         ++row;
281         options_packer.attach (force16bit_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
282         ++row;
283         options_packer.attach (hw_monitor_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
284         ++row;
285         options_packer.attach (hw_meter_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
286         ++row;
287         options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
288         ++row;
289 #else
290         options_packer.attach (verbose_output_button, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
291         ++row;
292 #endif
293
294         strings.clear ();
295         strings.push_back (_("Ignore"));
296         strings.push_back ("500 msec");
297         strings.push_back ("1 sec");
298         strings.push_back ("2 sec");
299         strings.push_back ("10 sec");
300         set_popdown_strings (timeout_combo, strings);
301         timeout_combo.set_active_text (strings.front ());
302
303         label = manage (new Label (_("Client timeout")));
304         label->set_alignment (1.0, 0.5);
305         options_packer.attach (timeout_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
306         options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
307         ++row;
308
309 #endif /* PROVIDE_TOO_MANY_OPTIONS */
310         label = manage (new Label (_("Number of ports:")));
311         label->set_alignment (0, 0.5);
312         options_packer.attach (ports_spinner, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
313         options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
314         ++row;
315
316         label = manage (new Label (_("MIDI driver:")));
317         label->set_alignment (0, 0.5);
318         options_packer.attach (midi_driver_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
319         options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
320         ++row;
321
322 #ifndef __APPLE__
323         label = manage (new Label (_("Dither:")));
324         label->set_alignment (0, 0.5);
325         options_packer.attach (dither_mode_combo, 1, 2, row, row + 1, FILL|EXPAND, AttachOptions(0));
326         options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
327         ++row;
328 #endif
329
330         find_jack_servers (server_strings);
331
332         if (server_strings.empty()) {
333                 fatal << _("No JACK server found anywhere on this system. Please install JACK and restart") << endmsg;
334                 /*NOTREACHED*/
335         }
336
337         set_popdown_strings (serverpath_combo, server_strings);
338         serverpath_combo.set_active_text (server_strings.front());
339
340         if (server_strings.size() > 1) {
341                 label = manage (new Label (_("Server:")));
342                 options_packer.attach (*label, 0, 1, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
343                 label->set_alignment (0.0, 0.5);
344                 options_packer.attach (serverpath_combo, 1, 2, row, row + 1, FILL|EXPAND, (AttachOptions) 0);
345                 ++row;
346         }
347
348         /* device settings */
349
350         device_packer.set_spacings (6);
351         row = 0;
352
353 #ifndef __APPLE__
354         label = manage (new Label (_("Input device:")));
355         label->set_alignment (0, 0.5);
356         device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
357         device_packer.attach (input_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
358         ++row;
359         label = manage (new Label (_("Output device:")));
360         label->set_alignment (0, 0.5);
361         device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
362         device_packer.attach (output_device_combo, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
363         ++row;
364 #endif
365         label = manage (new Label (_("Input channels:")));
366         label->set_alignment (0, 0.5);
367         device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
368         device_packer.attach (input_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
369         ++row;
370         label = manage (new Label (_("Output channels:")));
371         label->set_alignment (0, 0.5);
372         device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
373         device_packer.attach (output_channels, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
374         ++row;
375         label = manage (new Label (_("Hardware input latency:")));
376         label->set_alignment (0, 0.5);
377         device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
378         device_packer.attach (input_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
379         label = manage (new Label (_("samples")));
380         label->set_alignment (0, 0.5);
381         device_packer.attach (*label, 2, 3, row, row+1, FILL|EXPAND, (AttachOptions) 0);
382         ++row;
383         label = manage (new Label (_("Hardware output latency:")));
384         label->set_alignment (0, 0.5);
385         device_packer.attach (*label, 0, 1, row, row+1, FILL|EXPAND, (AttachOptions) 0);
386         device_packer.attach (output_latency, 1, 2, row, row+1, FILL|EXPAND, (AttachOptions) 0);
387         label = manage (new Label (_("samples")));
388         label->set_alignment (0, 0.5);
389         device_packer.attach (*label, 2, 3, row, row+1, FILL|EXPAND, (AttachOptions) 0);
390         ++row;
391
392         basic_hbox.pack_start (basic_packer, false, false);
393         options_hbox.pack_start (options_packer, false, false);
394
395         device_packer.set_border_width (12);
396         options_packer.set_border_width (12);
397         basic_packer.set_border_width (12);
398
399         notebook.pages().push_back (TabElem (basic_hbox, _("Device")));
400         notebook.pages().push_back (TabElem (options_hbox, _("Options")));
401         notebook.pages().push_back (TabElem (device_packer, _("Advanced")));
402         notebook.set_border_width (12);
403
404         set_border_width (12);
405         pack_start (notebook);
406 }
407
408 EngineControl::~EngineControl ()
409 {
410
411 }
412
413 void
414 EngineControl::build_command_line (vector<string>& cmd)
415 {
416         string str;
417         string driver;
418         bool using_alsa = false;
419         bool using_coreaudio = false;
420         bool using_dummy = false;
421         bool using_ffado = false;
422
423         /* first, path to jackd */
424
425         cmd.push_back (serverpath_combo.get_active_text ());
426
427         /* now jackd arguments */
428
429         str = timeout_combo.get_active_text ();
430
431         if (str != _("Ignore")) {
432
433                 double secs = 0;
434                 uint32_t msecs;
435                 secs = atof (str);
436                 msecs = (uint32_t) floor (secs * 1000.0);
437
438                 if (msecs > 0) {
439                         cmd.push_back ("-t");
440                         cmd.push_back (to_string (msecs, std::dec));
441                 }
442         }
443
444         if (no_memory_lock_button.get_active()) {
445                 cmd.push_back ("-m"); /* no munlock */
446         }
447
448         cmd.push_back ("-p"); /* port max */
449         cmd.push_back (to_string ((uint32_t) floor (ports_spinner.get_value()), std::dec));
450
451         if (realtime_button.get_active()) {
452                 cmd.push_back ("-R");
453                 cmd.push_back ("-P");
454                 cmd.push_back (to_string ((uint32_t) floor (priority_spinner.get_value()), std::dec));
455         } else {
456                 cmd.push_back ("-r"); /* override jackd's default --realtime */
457         }
458
459         if (unlock_memory_button.get_active()) {
460                 cmd.push_back ("-u");
461         }
462
463         if (verbose_output_button.get_active()) {
464                 cmd.push_back ("-v");
465         }
466
467         /* now add fixed arguments (not user-selectable) */
468
469         cmd.push_back ("-T"); // temporary */
470
471         /* next the driver */
472
473         cmd.push_back ("-d");
474
475         driver = driver_combo.get_active_text ();
476
477         if (driver == X_("ALSA")) {
478                 using_alsa = true;
479                 cmd.push_back ("alsa");
480         } else if (driver == X_("OSS")) {
481                 cmd.push_back ("oss");
482         } else if (driver == X_("CoreAudio")) {
483                 using_coreaudio = true;
484                 cmd.push_back ("coreaudio");
485         } else if (driver == X_("NetJACK")) {
486                 cmd.push_back ("netjack");
487         } else if (driver == X_("FreeBoB")) {
488                 cmd.push_back ("freebob");
489         } else if (driver == X_("FFADO")) {
490                 using_ffado = true;
491                 cmd.push_back ("firewire");
492         } else if ( driver == X_("Dummy")) {
493                 using_dummy = true;
494                 cmd.push_back ("dummy");
495         }
496
497         /* driver arguments */
498
499         if (!using_coreaudio) {
500                 str = audio_mode_combo.get_active_text();
501
502                 if (str == _("Playback/Recording on 1 Device")) {
503
504                         /* relax */
505
506                 } else if (str == _("Playback/Recording on 2 Devices")) {
507
508                         string input_device = get_device_name (driver, input_device_combo.get_active_text());
509                         string output_device = get_device_name (driver, output_device_combo.get_active_text());
510
511                         if (input_device.empty() || output_device.empty()) {
512                                 cmd.clear ();
513                                 return;
514                         }
515
516                         cmd.push_back ("-C");
517                         cmd.push_back (input_device);
518
519                         cmd.push_back ("-P");
520                         cmd.push_back (output_device);
521
522                 } else if (str == _("Playback only")) {
523                         cmd.push_back ("-P");
524                 } else if (str == _("Recording only")) {
525                         cmd.push_back ("-C");
526                 }
527
528                 if (!using_dummy) {
529                         cmd.push_back ("-n");
530                         cmd.push_back (to_string ((uint32_t) floor (periods_spinner.get_value()), std::dec));
531                 }
532         }
533
534         cmd.push_back ("-r");
535         cmd.push_back (to_string (get_rate(), std::dec));
536
537         cmd.push_back ("-p");
538         cmd.push_back (period_size_combo.get_active_text());
539
540         if (using_alsa || using_ffado || using_coreaudio) {
541
542                 double val = input_latency_adjustment.get_value();
543
544                 if (val) {
545                         cmd.push_back ("-I");
546                         cmd.push_back (to_string ((uint32_t) val, std::dec));
547                 }
548
549                 val = output_latency_adjustment.get_value();
550
551                 if (val) {
552                         cmd.push_back ("-O");
553                         cmd.push_back (to_string ((uint32_t) val, std::dec));
554                 }
555         }
556
557         if (using_alsa) {
558
559                 if (audio_mode_combo.get_active_text() != _("Playback/Recording on 2 Devices")) {
560
561                         string device = get_device_name (driver, interface_combo.get_active_text());
562                         if (device.empty()) {
563                                 cmd.clear ();
564                                 return;
565                         }
566
567                         cmd.push_back ("-d");
568                         cmd.push_back (device);
569                 }
570
571                 if (hw_meter_button.get_active()) {
572                         cmd.push_back ("-M");
573                 }
574
575                 if (hw_monitor_button.get_active()) {
576                         cmd.push_back ("-H");
577                 }
578
579                 str = dither_mode_combo.get_active_text();
580
581                 if (str == _("None")) {
582                 } else if (str == _("Triangular")) {
583                         cmd.push_back ("-z triangular");
584                 } else if (str == _("Rectangular")) {
585                         cmd.push_back ("-z rectangular");
586                 } else if (str == _("Shaped")) {
587                         cmd.push_back ("-z shaped");
588                 }
589
590                 if (force16bit_button.get_active()) {
591                         cmd.push_back ("-S");
592                 }
593
594                 if (soft_mode_button.get_active()) {
595                         cmd.push_back ("-s");
596                 }
597
598                 str = midi_driver_combo.get_active_text ();
599
600                 if (str == _("seq")) {
601                         cmd.push_back ("-X seq");
602                 } else if (str == _("raw")) {
603                         cmd.push_back ("-X raw");
604                 }
605         } else if (using_coreaudio) {
606
607 #ifdef __APPLE__
608                 // note: older versions of the CoreAudio JACK backend use -n instead of -d here
609
610                 string device = get_device_name (driver, interface_combo.get_active_text());
611                 if (device.empty()) {
612                         cmd.clear ();
613                         return;
614                 }
615
616                 cmd.push_back ("-d");
617                 cmd.push_back (device);
618 #endif
619
620         }
621 }
622
623 bool
624 EngineControl::engine_running ()
625 {
626         EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
627         boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
628
629         /* revert all environment settings back to whatever they were when ardour started
630          */
631
632         if (global_epa) {
633                 current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
634                 global_epa->restore ();
635         }
636
637         jack_status_t status;
638         jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
639
640         if (status == 0) {
641                 jack_client_close (c);
642                 return true;
643         }
644         return false;
645 }
646
647 int
648 EngineControl::setup_engine ()
649 {
650         vector<string> args;
651         std::string cwd = "/tmp";
652
653         build_command_line (args);
654
655         if (args.empty()) {
656                 return 1; // try again
657         }
658
659         std::string jackdrc_path = Glib::get_home_dir();
660         jackdrc_path += "/.jackdrc";
661
662         ofstream jackdrc (jackdrc_path.c_str());
663         if (!jackdrc) {
664                 error << string_compose (_("cannot open JACK rc file %1 to store parameters"), jackdrc_path) << endmsg;
665                 return -1;
666         }
667         cerr << "JACK COMMAND: ";
668         for (vector<string>::iterator i = args.begin(); i != args.end(); ++i) {
669                 cerr << (*i) << ' ';
670                 jackdrc << (*i) << ' ';
671         }
672         cerr << endl;
673         jackdrc << endl;
674         jackdrc.close ();
675
676         _used = true;
677
678         return 0;
679 }
680
681 void
682 EngineControl::realtime_changed ()
683 {
684 #ifndef __APPLE__
685         priority_spinner.set_sensitive (realtime_button.get_active());
686 #endif
687 }
688
689 void
690 EngineControl::enumerate_devices (const string& driver)
691 {
692         /* note: case matters for the map keys */
693
694         if (driver == "CoreAudio") {
695 #ifdef __APPLE__
696                 devices[driver] = enumerate_coreaudio_devices ();
697 #endif
698
699 #ifndef __APPLE__
700         } else if (driver == "ALSA") {
701                 devices[driver] = enumerate_alsa_devices ();
702         } else if (driver == "FreeBOB") {
703                 devices[driver] = enumerate_freebob_devices ();
704         } else if (driver == "FFADO") {
705                 devices[driver] = enumerate_ffado_devices ();
706         } else if (driver == "OSS") {
707                 devices[driver] = enumerate_oss_devices ();
708         } else if (driver == "Dummy") {
709                 devices[driver] = enumerate_dummy_devices ();
710         } else if (driver == "NetJACK") {
711                 devices[driver] = enumerate_netjack_devices ();
712         }
713 #else
714         }
715 #endif
716 }
717
718 #ifdef __APPLE__
719 static OSStatus
720 getDeviceUIDFromID( AudioDeviceID id, char *name, size_t nsize)
721 {
722         UInt32 size = sizeof(CFStringRef);
723         CFStringRef UI;
724         OSStatus res = AudioDeviceGetProperty(id, 0, false,
725                 kAudioDevicePropertyDeviceUID, &size, &UI);
726         if (res == noErr)
727                 CFStringGetCString(UI,name,nsize,CFStringGetSystemEncoding());
728         CFRelease(UI);
729         return res;
730 }
731
732 vector<string>
733 EngineControl::enumerate_coreaudio_devices ()
734 {
735         vector<string> devs;
736
737         // Find out how many Core Audio devices are there, if any...
738         // (code snippet gently "borrowed" from St?hane Letz jackdmp;)
739         OSStatus err;
740         Boolean isWritable;
741         size_t outSize = sizeof(isWritable);
742
743         backend_devs.clear ();
744
745         err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices,
746                                            &outSize, &isWritable);
747         if (err == noErr) {
748                 // Calculate the number of device available...
749                 int numCoreDevices = outSize / sizeof(AudioDeviceID);
750                 // Make space for the devices we are about to get...
751                 AudioDeviceID *coreDeviceIDs = new AudioDeviceID [numCoreDevices];
752                 err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices,
753                                                &outSize, (void *) coreDeviceIDs);
754                 if (err == noErr) {
755                         // Look for the CoreAudio device name...
756                         char coreDeviceName[256];
757                         size_t nameSize;
758
759                         for (int i = 0; i < numCoreDevices; i++) {
760
761                                 nameSize = sizeof (coreDeviceName);
762
763                                 /* enforce duplex devices only */
764
765                                 err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
766                                                                  0, true, kAudioDevicePropertyStreams,
767                                                                  &outSize, &isWritable);
768
769                                 if (err != noErr || outSize == 0) {
770                                         continue;
771                                 }
772
773                                 err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
774                                                                  0, false, kAudioDevicePropertyStreams,
775                                                                  &outSize, &isWritable);
776
777                                 if (err != noErr || outSize == 0) {
778                                         continue;
779                                 }
780
781                                 err = AudioDeviceGetPropertyInfo(coreDeviceIDs[i],
782                                                                  0, true, kAudioDevicePropertyDeviceName,
783                                                                  &outSize, &isWritable);
784                                 if (err == noErr) {
785                                         err = AudioDeviceGetProperty(coreDeviceIDs[i],
786                                                                      0, true, kAudioDevicePropertyDeviceName,
787                                                                      &nameSize, (void *) coreDeviceName);
788                                         if (err == noErr) {
789                                                 char drivername[128];
790
791                                                 // this returns the unique id for the device
792                                                 // that must be used on the commandline for jack
793
794                                                 if (getDeviceUIDFromID(coreDeviceIDs[i], drivername, sizeof (drivername)) == noErr) {
795                                                         devs.push_back (coreDeviceName);
796                                                         backend_devs.push_back (drivername);
797                                                 }
798                                         }
799                                 }
800                         }
801                 }
802                 delete [] coreDeviceIDs;
803         }
804
805
806         if (devs.size() == 0) {
807                 MessageDialog msg (_("\
808 You do not have any audio devices capable of\n\
809 simultaneous playback and recording.\n\n\
810 Please use Applications -> Utilities -> Audio MIDI Setup\n\
811 to create an \"aggregrate\" device, or install a suitable\n\
812 audio interface.\n\n\
813 Please send email to Apple and ask them why new Macs\n\
814 have no duplex audio device.\n\n\
815 Alternatively, if you really want just playback\n\
816 or recording but not both, start JACK before running\n\
817 Ardour and choose the relevant device then."
818                                            ),
819                                    true, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK);
820                 msg.set_title (_("No suitable audio devices"));
821                 msg.set_position (Gtk::WIN_POS_MOUSE);
822                 msg.run ();
823                 exit (1);
824         }
825
826
827         return devs;
828 }
829 #else
830 vector<string>
831 EngineControl::enumerate_alsa_devices ()
832 {
833         vector<string> devs;
834
835         snd_ctl_t *handle;
836         snd_ctl_card_info_t *info;
837         snd_pcm_info_t *pcminfo;
838         snd_ctl_card_info_alloca(&info);
839         snd_pcm_info_alloca(&pcminfo);
840         string devname;
841         int cardnum = -1;
842         int device = -1;
843
844         backend_devs.clear ();
845
846         while (snd_card_next (&cardnum) >= 0 && cardnum >= 0) {
847
848                 devname = "hw:";
849                 devname += to_string (cardnum, std::dec);
850
851                 if (snd_ctl_open (&handle, devname.c_str(), 0) >= 0 && snd_ctl_card_info (handle, info) >= 0) {
852
853                         while (snd_ctl_pcm_next_device (handle, &device) >= 0 && device >= 0) {
854
855                                 snd_pcm_info_set_device (pcminfo, device);
856                                 snd_pcm_info_set_subdevice (pcminfo, 0);
857                                 snd_pcm_info_set_stream (pcminfo, SND_PCM_STREAM_PLAYBACK);
858
859                                 if (snd_ctl_pcm_info (handle, pcminfo) >= 0) {
860                                         devs.push_back (snd_pcm_info_get_name (pcminfo));
861                                         devname += ',';
862                                         devname += to_string (device, std::dec);
863                                         backend_devs.push_back (devname);
864                                 }
865                         }
866
867                         snd_ctl_close(handle);
868                 }
869         }
870
871         return devs;
872 }
873
874 vector<string>
875 EngineControl::enumerate_ffado_devices ()
876 {
877         vector<string> devs;
878         backend_devs.clear ();
879         return devs;
880 }
881
882 vector<string>
883 EngineControl::enumerate_freebob_devices ()
884 {
885         vector<string> devs;
886         return devs;
887 }
888
889 vector<string>
890 EngineControl::enumerate_oss_devices ()
891 {
892         vector<string> devs;
893         return devs;
894 }
895 vector<string>
896 EngineControl::enumerate_dummy_devices ()
897 {
898         vector<string> devs;
899         return devs;
900 }
901 vector<string>
902 EngineControl::enumerate_netjack_devices ()
903 {
904         vector<string> devs;
905         return devs;
906 }
907 #endif
908
909 void
910 EngineControl::driver_changed ()
911 {
912         string driver = driver_combo.get_active_text();
913         string::size_type maxlen = 0;
914         int n = 0;
915
916         enumerate_devices (driver);
917
918         vector<string>& strings = devices[driver];
919
920         if (strings.empty() && driver != "FreeBoB" && driver != "FFADO" && driver != "Dummy") {
921                 return;
922         }
923
924         for (vector<string>::iterator i = strings.begin(); i != strings.end(); ++i, ++n) {
925                 if ((*i).length() > maxlen) {
926                         maxlen = (*i).length();
927                 }
928         }
929
930         set_popdown_strings (interface_combo, strings);
931         set_popdown_strings (input_device_combo, strings);
932         set_popdown_strings (output_device_combo, strings);
933
934         if (!strings.empty()) {
935                 interface_combo.set_active_text (strings.front());
936                 input_device_combo.set_active_text (strings.front());
937                 output_device_combo.set_active_text (strings.front());
938         }
939
940         if (driver == "ALSA") {
941                 soft_mode_button.set_sensitive (true);
942                 force16bit_button.set_sensitive (true);
943                 hw_monitor_button.set_sensitive (true);
944                 hw_meter_button.set_sensitive (true);
945                 monitor_button.set_sensitive (true);
946         } else {
947                 soft_mode_button.set_sensitive (false);
948                 force16bit_button.set_sensitive (false);
949                 hw_monitor_button.set_sensitive (false);
950                 hw_meter_button.set_sensitive (false);
951                 monitor_button.set_sensitive (false);
952         }
953 }
954
955 uint32_t
956 EngineControl::get_rate ()
957 {
958         double r = atof (sample_rate_combo.get_active_text ());
959         /* the string may have been translated with an abbreviation for
960          * thousands, so use a crude heuristic to fix this.
961          */
962         if (r < 1000.0) {
963                 r *= 1000.0;
964         }
965         return lrint (r);
966 }
967
968 void
969 EngineControl::redisplay_latency ()
970 {
971         uint32_t rate = get_rate();
972 #ifdef __APPLE_
973         float periods = 2;
974 #else
975         float periods = periods_adjustment.get_value();
976 #endif
977         float period_size = atof (period_size_combo.get_active_text());
978
979         char buf[32];
980         snprintf (buf, sizeof(buf), "%.1fmsec", (periods * period_size) / (rate/1000.0));
981
982         latency_label.set_text (buf);
983         latency_label.set_alignment (0, 0.5);
984 }
985
986 void
987 EngineControl::audio_mode_changed ()
988 {
989         std::string str = audio_mode_combo.get_active_text();
990
991         if (str == _("Playback/Recording on 1 Device")) {
992                 input_device_combo.set_sensitive (false);
993                 output_device_combo.set_sensitive (false);
994         } else if (str == _("Playback/Recording on 2 Devices")) {
995                 input_device_combo.set_sensitive (true);
996                 output_device_combo.set_sensitive (true);
997         } else if (str == _("Playback only")) {
998                 output_device_combo.set_sensitive (true);
999         } else if (str == _("Recording only")) {
1000                 input_device_combo.set_sensitive (true);
1001         }
1002 }
1003
1004 static bool jack_server_filter(const string& str, void */*arg*/)
1005 {
1006    return str == "jackd" || str == "jackdmp";
1007 }
1008
1009 void
1010 EngineControl::find_jack_servers (vector<string>& strings)
1011 {
1012 #ifdef __APPLE__
1013         /* this magic lets us finds the path to the OSX bundle, and then
1014            we infer JACK's location from there
1015         */
1016
1017         char execpath[MAXPATHLEN+1];
1018         uint32_t pathsz = sizeof (execpath);
1019
1020         _NSGetExecutablePath (execpath, &pathsz);
1021
1022         string path (Glib::path_get_dirname (execpath));
1023         path += "/jackd";
1024
1025         if (Glib::file_test (path, FILE_TEST_EXISTS)) {
1026                 strings.push_back (path);
1027         }
1028
1029         if (getenv ("ARDOUR_WITH_JACK")) {
1030                 /* no other options - only use the JACK we supply */
1031                 if (strings.empty()) {
1032                         fatal << string_compose (_("JACK appears to be missing from the %1 bundle"), PROGRAM_NAME) << endmsg;
1033                         /*NOTREACHED*/
1034                 }
1035                 return;
1036         }
1037 #else
1038         string path;
1039 #endif
1040
1041         PathScanner scanner;
1042         vector<string *> *jack_servers;
1043         std::map<string,int> un;
1044         char *p;
1045         bool need_minimal_path = false;
1046
1047         p = getenv ("PATH");
1048
1049         if (p && *p) {
1050                 path = p;
1051         } else {
1052                 need_minimal_path = true;
1053         }
1054
1055 #ifdef __APPLE__
1056         // many mac users don't have PATH set up to include
1057         // likely installed locations of JACK
1058         need_minimal_path = true;
1059 #endif
1060
1061         if (need_minimal_path) {
1062                 if (path.empty()) {
1063                         path = "/usr/bin:/bin:/usr/local/bin:/opt/local/bin";
1064                 } else {
1065                         path += ":/usr/local/bin:/opt/local/bin";
1066                 }
1067         }
1068
1069 #ifdef __APPLE__
1070         // push it back into the environment so that auto-started JACK can find it.
1071         // XXX why can't we just expect OS X users to have PATH set correctly? we can't ...
1072         setenv ("PATH", path.c_str(), 1);
1073 #endif
1074
1075         jack_servers = scanner (path, jack_server_filter, 0, false, true);
1076
1077         vector<string *>::iterator iter;
1078
1079         for (iter = jack_servers->begin(); iter != jack_servers->end(); iter++) {
1080                 string p = **iter;
1081
1082                 if (un[p]++ == 0) {
1083                         strings.push_back(p);
1084                 }
1085         }
1086 }
1087
1088
1089 string
1090 EngineControl::get_device_name (const string& driver, const string& human_readable)
1091 {
1092         vector<string>::iterator n;
1093         vector<string>::iterator i;
1094
1095         if (human_readable.empty()) {
1096                 /* this can happen if the user's .ardourrc file has a device name from
1097                    another computer system in it
1098                 */
1099                 MessageDialog msg (_("You need to choose an audio device first."));
1100                 msg.run ();
1101                 return string();
1102         }
1103
1104         if (backend_devs.empty()) {
1105                 return human_readable;
1106         }
1107
1108         for (i = devices[driver].begin(), n = backend_devs.begin(); i != devices[driver].end(); ++i, ++n) {
1109                 if (human_readable == (*i)) {
1110                         return (*n);
1111                 }
1112         }
1113
1114         if (i == devices[driver].end()) {
1115                 warning << string_compose (_("Audio device \"%1\" not known on this computer."), human_readable) << endmsg;
1116         }
1117
1118         return string();
1119 }
1120
1121 XMLNode&
1122 EngineControl::get_state ()
1123 {
1124         XMLNode* root = new XMLNode ("AudioSetup");
1125         XMLNode* child;
1126         std::string path;
1127
1128         child = new XMLNode ("periods");
1129         child->add_property ("val", to_string (periods_adjustment.get_value(), std::dec));
1130         root->add_child_nocopy (*child);
1131
1132         child = new XMLNode ("priority");
1133         child->add_property ("val", to_string (priority_adjustment.get_value(), std::dec));
1134         root->add_child_nocopy (*child);
1135
1136         child = new XMLNode ("ports");
1137         child->add_property ("val", to_string (ports_adjustment.get_value(), std::dec));
1138         root->add_child_nocopy (*child);
1139
1140         child = new XMLNode ("inchannels");
1141         child->add_property ("val", to_string (input_channels.get_value(), std::dec));
1142         root->add_child_nocopy (*child);
1143
1144         child = new XMLNode ("outchannels");
1145         child->add_property ("val", to_string (output_channels.get_value(), std::dec));
1146         root->add_child_nocopy (*child);
1147
1148         child = new XMLNode ("inlatency");
1149         child->add_property ("val", to_string (input_latency.get_value(), std::dec));
1150         root->add_child_nocopy (*child);
1151
1152         child = new XMLNode ("outlatency");
1153         child->add_property ("val", to_string (output_latency.get_value(), std::dec));
1154         root->add_child_nocopy (*child);
1155
1156         child = new XMLNode ("realtime");
1157         child->add_property ("val", to_string (realtime_button.get_active(), std::dec));
1158         root->add_child_nocopy (*child);
1159
1160         child = new XMLNode ("nomemorylock");
1161         child->add_property ("val", to_string (no_memory_lock_button.get_active(), std::dec));
1162         root->add_child_nocopy (*child);
1163
1164         child = new XMLNode ("unlockmemory");
1165         child->add_property ("val", to_string (unlock_memory_button.get_active(), std::dec));
1166         root->add_child_nocopy (*child);
1167
1168         child = new XMLNode ("softmode");
1169         child->add_property ("val", to_string (soft_mode_button.get_active(), std::dec));
1170         root->add_child_nocopy (*child);
1171
1172         child = new XMLNode ("force16bit");
1173         child->add_property ("val", to_string (force16bit_button.get_active(), std::dec));
1174         root->add_child_nocopy (*child);
1175
1176         child = new XMLNode ("hwmonitor");
1177         child->add_property ("val", to_string (hw_monitor_button.get_active(), std::dec));
1178         root->add_child_nocopy (*child);
1179
1180         child = new XMLNode ("hwmeter");
1181         child->add_property ("val", to_string (hw_meter_button.get_active(), std::dec));
1182         root->add_child_nocopy (*child);
1183
1184         child = new XMLNode ("verbose");
1185         child->add_property ("val", to_string (verbose_output_button.get_active(), std::dec));
1186         root->add_child_nocopy (*child);
1187
1188         child = new XMLNode ("samplerate");
1189         child->add_property ("val", sample_rate_combo.get_active_text());
1190         root->add_child_nocopy (*child);
1191
1192         child = new XMLNode ("periodsize");
1193         child->add_property ("val", period_size_combo.get_active_text());
1194         root->add_child_nocopy (*child);
1195
1196         child = new XMLNode ("serverpath");
1197         child->add_property ("val", serverpath_combo.get_active_text());
1198         root->add_child_nocopy (*child);
1199
1200         child = new XMLNode ("driver");
1201         child->add_property ("val", driver_combo.get_active_text());
1202         root->add_child_nocopy (*child);
1203
1204         child = new XMLNode ("interface");
1205         child->add_property ("val", interface_combo.get_active_text());
1206         root->add_child_nocopy (*child);
1207
1208         child = new XMLNode ("timeout");
1209         child->add_property ("val", timeout_combo.get_active_text());
1210         root->add_child_nocopy (*child);
1211
1212         child = new XMLNode ("dither");
1213         child->add_property ("val", dither_mode_combo.get_active_text());
1214         root->add_child_nocopy (*child);
1215
1216         child = new XMLNode ("audiomode");
1217         child->add_property ("val", audio_mode_combo.get_active_text());
1218         root->add_child_nocopy (*child);
1219
1220         child = new XMLNode ("inputdevice");
1221         child->add_property ("val", input_device_combo.get_active_text());
1222         root->add_child_nocopy (*child);
1223
1224         child = new XMLNode ("outputdevice");
1225         child->add_property ("val", output_device_combo.get_active_text());
1226         root->add_child_nocopy (*child);
1227
1228         child = new XMLNode ("mididriver");
1229         child->add_property ("val", midi_driver_combo.get_active_text());
1230         root->add_child_nocopy (*child);
1231
1232         return *root;
1233 }
1234
1235 void
1236 EngineControl::set_state (const XMLNode& root)
1237 {
1238         XMLNodeList          clist;
1239         XMLNodeConstIterator citer;
1240         XMLNode* child;
1241         XMLProperty* prop = NULL;
1242         bool using_dummy = false;
1243         bool using_ffado = false;
1244
1245         int val;
1246         string strval;
1247
1248         if ( (child = root.child ("driver"))){
1249                 prop = child->property("val");
1250
1251                 if (prop && (prop->value() == "Dummy") ) {
1252                         using_dummy = true;
1253                 }
1254                 if (prop && (prop->value() == "FFADO") ) {
1255                         using_ffado = true;
1256                 }
1257
1258         }
1259
1260         clist = root.children();
1261
1262         for (citer = clist.begin(); citer != clist.end(); ++citer) {
1263
1264                 child = *citer;
1265
1266                 prop = child->property ("val");
1267
1268                 if (!prop || prop->value().empty()) {
1269
1270                         if (((using_dummy || using_ffado)
1271                                 && ( child->name() == "interface"
1272                                         || child->name() == "inputdevice"
1273                                         || child->name() == "outputdevice"))
1274                                 || child->name() == "timeout")
1275                         {
1276                                 continue;
1277                         }
1278
1279                         error << string_compose (_("AudioSetup value for %1 is missing data"), child->name()) << endmsg;
1280                         continue;
1281                 }
1282
1283                 strval = prop->value();
1284
1285                 /* adjustments/spinners */
1286
1287                 if (child->name() == "periods") {
1288                         val = atoi (strval);
1289                         periods_adjustment.set_value(val);
1290                 } else if (child->name() == "priority") {
1291                         val = atoi (strval);
1292                         priority_adjustment.set_value(val);
1293                 } else if (child->name() == "ports") {
1294                         val = atoi (strval);
1295                         ports_adjustment.set_value(val);
1296                 } else if (child->name() == "inchannels") {
1297                         val = atoi (strval);
1298                         input_channels.set_value(val);
1299                 } else if (child->name() == "outchannels") {
1300                         val = atoi (strval);
1301                         output_channels.set_value(val);
1302                 } else if (child->name() == "inlatency") {
1303                         val = atoi (strval);
1304                         input_latency.set_value(val);
1305                 } else if (child->name() == "outlatency") {
1306                         val = atoi (strval);
1307                         output_latency.set_value(val);
1308                 }
1309
1310                 /* buttons */
1311
1312                 else if (child->name() == "realtime") {
1313                         val = atoi (strval);
1314                         realtime_button.set_active(val);
1315                 } else if (child->name() == "nomemorylock") {
1316                         val = atoi (strval);
1317                         no_memory_lock_button.set_active(val);
1318                 } else if (child->name() == "unlockmemory") {
1319                         val = atoi (strval);
1320                         unlock_memory_button.set_active(val);
1321                 } else if (child->name() == "softmode") {
1322                         val = atoi (strval);
1323                         soft_mode_button.set_active(val);
1324                 } else if (child->name() == "force16bit") {
1325                         val = atoi (strval);
1326                         force16bit_button.set_active(val);
1327                 } else if (child->name() == "hwmonitor") {
1328                         val = atoi (strval);
1329                         hw_monitor_button.set_active(val);
1330                 } else if (child->name() == "hwmeter") {
1331                         val = atoi (strval);
1332                         hw_meter_button.set_active(val);
1333                 } else if (child->name() == "verbose") {
1334                         val = atoi (strval);
1335                         verbose_output_button.set_active(val);
1336                 }
1337
1338                 /* combos */
1339
1340                 else if (child->name() == "samplerate") {
1341                         sample_rate_combo.set_active_text(strval);
1342                 } else if (child->name() == "periodsize") {
1343                         period_size_combo.set_active_text(strval);
1344                 } else if (child->name() == "serverpath") {
1345
1346                         /* only attempt to set this if we have bothered to look
1347                            up server names already. otherwise this is all
1348                            redundant (actually, all of this dialog/widget
1349                            is redundant in that case ...)
1350                         */
1351
1352                         if (!server_strings.empty()) {
1353                                 /* do not allow us to use a server path that doesn't
1354                                    exist on this system. this handles cases where
1355                                    the user has an RC file listing a serverpath
1356                                    from some other machine.
1357                                 */
1358                                 vector<string>::iterator x;
1359                                 for (x = server_strings.begin(); x != server_strings.end(); ++x) {
1360                                         if (*x == strval) {
1361                                                 break;
1362                                         }
1363                                 }
1364                                 if (x != server_strings.end()) {
1365                                         serverpath_combo.set_active_text (strval);
1366                                 } else {
1367                                         warning << string_compose (_("configuration files contain a JACK server path that doesn't exist (%1)"),
1368                                                                    strval)
1369                                                 << endmsg;
1370                                 }
1371                         }
1372
1373                 } else if (child->name() == "driver") {
1374                         driver_combo.set_active_text(strval);
1375                 } else if (child->name() == "interface") {
1376                         interface_combo.set_active_text(strval);
1377                 } else if (child->name() == "timeout") {
1378                         timeout_combo.set_active_text(strval);
1379                 } else if (child->name() == "dither") {
1380                         dither_mode_combo.set_active_text(strval);
1381                 } else if (child->name() == "audiomode") {
1382                         audio_mode_combo.set_active_text(strval);
1383                 } else if (child->name() == "inputdevice") {
1384                         input_device_combo.set_active_text(strval);
1385                 } else if (child->name() == "outputdevice") {
1386                         output_device_combo.set_active_text(strval);
1387                 } else if (child->name() == "mididriver") {
1388                         midi_driver_combo.set_active_text(strval);
1389                 }
1390         }
1391 }