add LTC generator
[ardour.git] / gtk2_ardour / rc_option_editor.cc
1 /*
2     Copyright (C) 2001-2011 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 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 #include <gtkmm/liststore.h>
25 #include <gtkmm/stock.h>
26 #include <gtkmm/scale.h>
27 #include <gtkmm2ext/utils.h>
28 #include <gtkmm2ext/slider_controller.h>
29 #include <gtkmm2ext/gtk_ui.h>
30
31 #include "pbd/fpu.h"
32 #include "pbd/cpus.h"
33
34 #include "midi++/manager.h"
35
36 #include "ardour/audioengine.h"
37 #include "ardour/dB.h"
38 #include "ardour/rc_configuration.h"
39 #include "ardour/control_protocol_manager.h"
40 #include "control_protocol/control_protocol.h"
41
42 #include "ardour_window.h"
43 #include "ardour_dialog.h"
44 #include "gui_thread.h"
45 #include "midi_tracer.h"
46 #include "rc_option_editor.h"
47 #include "utils.h"
48 #include "midi_port_dialog.h"
49 #include "sfdb_ui.h"
50 #include "keyboard.h"
51 #include "i18n.h"
52
53 using namespace std;
54 using namespace Gtk;
55 using namespace Gtkmm2ext;
56 using namespace PBD;
57 using namespace ARDOUR;
58
59 class ClickOptions : public OptionEditorBox
60 {
61 public:
62         ClickOptions (RCConfiguration* c, Gtk::Window* p)
63                 : _rc_config (c),
64                   _parent (p)
65         {
66                 Table* t = manage (new Table (2, 3));
67                 t->set_spacings (4);
68
69                 Label* l = manage (left_aligned_label (_("Click audio file:")));
70                 t->attach (*l, 0, 1, 0, 1, FILL);
71                 t->attach (_click_path_entry, 1, 2, 0, 1, FILL);
72                 Button* b = manage (new Button (_("Browse...")));
73                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
74                 t->attach (*b, 2, 3, 0, 1, FILL);
75
76                 l = manage (left_aligned_label (_("Click emphasis audio file:")));
77                 t->attach (*l, 0, 1, 1, 2, FILL);
78                 t->attach (_click_emphasis_path_entry, 1, 2, 1, 2, FILL);
79                 b = manage (new Button (_("Browse...")));
80                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
81                 t->attach (*b, 2, 3, 1, 2, FILL);
82                 
83                 _box->pack_start (*t, false, false);
84
85                 _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));      
86                 _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
87         }
88
89         void parameter_changed (string const & p)
90         {
91                 if (p == "click-sound") {
92                         _click_path_entry.set_text (_rc_config->get_click_sound());
93                 } else if (p == "click-emphasis-sound") {
94                         _click_emphasis_path_entry.set_text (_rc_config->get_click_emphasis_sound());
95                 }
96         }
97
98         void set_state_from_config ()
99         {
100                 parameter_changed ("click-sound");
101                 parameter_changed ("click-emphasis-sound");
102         }
103
104 private:
105
106         void click_browse_clicked ()
107         {
108                 SoundFileChooser sfdb (*_parent, _("Choose Click"));
109
110                 sfdb.show_all ();
111                 sfdb.present ();
112
113                 if (sfdb.run () == RESPONSE_OK) {
114                         click_chosen (sfdb.get_filename());
115                 }
116         }
117
118         void click_chosen (string const & path)
119         {
120                 _click_path_entry.set_text (path);
121                 _rc_config->set_click_sound (path);
122         }
123
124         void click_changed ()
125         {
126                 click_chosen (_click_path_entry.get_text ());
127         }
128         
129         void click_emphasis_browse_clicked ()
130         {
131                 SoundFileChooser sfdb (*_parent, _("Choose Click Emphasis"));
132
133                 sfdb.show_all ();
134                 sfdb.present ();
135
136                 if (sfdb.run () == RESPONSE_OK) {
137                         click_emphasis_chosen (sfdb.get_filename());
138                 }
139         }
140
141         void click_emphasis_chosen (string const & path)
142         {
143                 _click_emphasis_path_entry.set_text (path);
144                 _rc_config->set_click_emphasis_sound (path);
145         }
146
147         void click_emphasis_changed ()
148         {
149                 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
150         }
151
152         RCConfiguration* _rc_config;
153         Gtk::Window* _parent;
154         Entry _click_path_entry;
155         Entry _click_emphasis_path_entry;
156 };
157
158 class UndoOptions : public OptionEditorBox
159 {
160 public:
161         UndoOptions (RCConfiguration* c) :
162                 _rc_config (c),
163                 _limit_undo_button (_("Limit undo history to")),
164                 _save_undo_button (_("Save undo history of"))
165         {
166                 Table* t = new Table (2, 3);
167                 t->set_spacings (4);
168
169                 t->attach (_limit_undo_button, 0, 1, 0, 1, FILL);
170                 _limit_undo_spin.set_range (0, 512);
171                 _limit_undo_spin.set_increments (1, 10);
172                 t->attach (_limit_undo_spin, 1, 2, 0, 1, FILL | EXPAND);
173                 Label* l = manage (left_aligned_label (_("commands")));
174                 t->attach (*l, 2, 3, 0, 1);
175
176                 t->attach (_save_undo_button, 0, 1, 1, 2, FILL);
177                 _save_undo_spin.set_range (0, 512);
178                 _save_undo_spin.set_increments (1, 10);
179                 t->attach (_save_undo_spin, 1, 2, 1, 2, FILL | EXPAND);
180                 l = manage (left_aligned_label (_("commands")));
181                 t->attach (*l, 2, 3, 1, 2);
182
183                 _box->pack_start (*t);
184
185                 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
186                 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
187                 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
188                 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
189         }
190
191         void parameter_changed (string const & p)
192         {
193                 if (p == "history-depth") {
194                         int32_t const d = _rc_config->get_history_depth();
195                         _limit_undo_button.set_active (d != 0);
196                         _limit_undo_spin.set_sensitive (d != 0);
197                         _limit_undo_spin.set_value (d);
198                 } else if (p == "save-history") {
199                         bool const x = _rc_config->get_save_history ();
200                         _save_undo_button.set_active (x);
201                         _save_undo_spin.set_sensitive (x);
202                 } else if (p == "save-history-depth") {
203                         _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
204                 }
205         }
206
207         void set_state_from_config ()
208         {
209                 parameter_changed ("save-history");
210                 parameter_changed ("history-depth");
211                 parameter_changed ("save-history-depth");
212         }
213
214         void limit_undo_toggled ()
215         {
216                 bool const x = _limit_undo_button.get_active ();
217                 _limit_undo_spin.set_sensitive (x);
218                 int32_t const n = x ? 16 : 0;
219                 _limit_undo_spin.set_value (n);
220                 _rc_config->set_history_depth (n);
221         }
222
223         void limit_undo_changed ()
224         {
225                 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
226         }
227
228         void save_undo_toggled ()
229         {
230                 bool const x = _save_undo_button.get_active ();
231                 _rc_config->set_save_history (x);
232         }
233
234         void save_undo_changed ()
235         {
236                 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
237         }
238
239 private:
240         RCConfiguration* _rc_config;
241         CheckButton _limit_undo_button;
242         SpinButton _limit_undo_spin;
243         CheckButton _save_undo_button;
244         SpinButton _save_undo_spin;
245 };
246
247
248
249 static const struct {
250     const char *name;
251     guint modifier;
252 } modifiers[] = {
253
254         { "Unmodified", 0 },
255
256 #ifdef GTKOSX
257
258         /* Command = Meta
259            Option/Alt = Mod1
260         */
261         { "Key|Shift", GDK_SHIFT_MASK },
262         { "Command", GDK_META_MASK },
263         { "Control", GDK_CONTROL_MASK },
264         { "Option", GDK_MOD1_MASK },
265         { "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
266         { "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
267         { "Shift-Option", GDK_SHIFT_MASK|GDK_MOD1_MASK },
268         { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
269
270 #else
271         { "Key|Shift", GDK_SHIFT_MASK },
272         { "Control", GDK_CONTROL_MASK },
273         { "Alt (Mod1)", GDK_MOD1_MASK },
274         { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
275         { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
276         { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
277         { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
278         { "Mod2", GDK_MOD2_MASK },
279         { "Mod3", GDK_MOD3_MASK },
280         { "Mod4", GDK_MOD4_MASK },
281         { "Mod5", GDK_MOD5_MASK },
282 #endif
283         { 0, 0 }
284 };
285
286
287 class KeyboardOptions : public OptionEditorBox
288 {
289 public:
290         KeyboardOptions () :
291                   _delete_button_adjustment (3, 1, 12),
292                   _delete_button_spin (_delete_button_adjustment),
293                   _edit_button_adjustment (3, 1, 5),
294                   _edit_button_spin (_edit_button_adjustment),
295                   _insert_note_button_adjustment (3, 1, 5),
296                   _insert_note_button_spin (_insert_note_button_adjustment)
297         {
298                 /* internationalize and prepare for use with combos */
299
300                 vector<string> dumb;
301                 for (int i = 0; modifiers[i].name; ++i) {
302                         dumb.push_back (S_(modifiers[i].name));
303                 }
304
305                 set_popdown_strings (_edit_modifier_combo, dumb);
306                 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
307
308                 for (int x = 0; modifiers[x].name; ++x) {
309                         if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
310                                 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
311                                 break;
312                         }
313                 }
314
315                 Table* t = manage (new Table (4, 4));
316                 t->set_spacings (4);
317
318                 Label* l = manage (left_aligned_label (_("Edit using:")));
319                 l->set_name ("OptionsLabel");
320
321                 t->attach (*l, 0, 1, 0, 1, FILL | EXPAND, FILL);
322                 t->attach (_edit_modifier_combo, 1, 2, 0, 1, FILL | EXPAND, FILL);
323
324                 l = manage (new Label (_("+ button")));
325                 l->set_name ("OptionsLabel");
326
327                 t->attach (*l, 3, 4, 0, 1, FILL | EXPAND, FILL);
328                 t->attach (_edit_button_spin, 4, 5, 0, 1, FILL | EXPAND, FILL);
329
330                 _edit_button_spin.set_name ("OptionsEntry");
331                 _edit_button_adjustment.set_value (Keyboard::edit_button());
332                 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
333
334                 set_popdown_strings (_delete_modifier_combo, dumb);
335                 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
336
337                 for (int x = 0; modifiers[x].name; ++x) {
338                         if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
339                                 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
340                                 break;
341                         }
342                 }
343
344                 l = manage (left_aligned_label (_("Delete using:")));
345                 l->set_name ("OptionsLabel");
346
347                 t->attach (*l, 0, 1, 1, 2, FILL | EXPAND, FILL);
348                 t->attach (_delete_modifier_combo, 1, 2, 1, 2, FILL | EXPAND, FILL);
349
350                 l = manage (new Label (_("+ button")));
351                 l->set_name ("OptionsLabel");
352
353                 t->attach (*l, 3, 4, 1, 2, FILL | EXPAND, FILL);
354                 t->attach (_delete_button_spin, 4, 5, 1, 2, FILL | EXPAND, FILL);
355
356                 _delete_button_spin.set_name ("OptionsEntry");
357                 _delete_button_adjustment.set_value (Keyboard::delete_button());
358                 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
359
360
361                 set_popdown_strings (_insert_note_modifier_combo, dumb);
362                 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
363
364                 for (int x = 0; modifiers[x].name; ++x) {
365                         if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
366                                 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
367                                 break;
368                         }
369                 }
370
371                 l = manage (left_aligned_label (_("Insert note using:")));
372                 l->set_name ("OptionsLabel");
373
374                 t->attach (*l, 0, 1, 2, 3, FILL | EXPAND, FILL);
375                 t->attach (_insert_note_modifier_combo, 1, 2, 2, 3, FILL | EXPAND, FILL);
376
377                 l = manage (new Label (_("+ button")));
378                 l->set_name ("OptionsLabel");
379
380                 t->attach (*l, 3, 4, 2, 3, FILL | EXPAND, FILL);
381                 t->attach (_insert_note_button_spin, 4, 5, 2, 3, FILL | EXPAND, FILL);
382
383                 _insert_note_button_spin.set_name ("OptionsEntry");
384                 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
385                 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
386
387
388                 set_popdown_strings (_snap_modifier_combo, dumb);
389                 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
390
391                 for (int x = 0; modifiers[x].name; ++x) {
392                         if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
393                                 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
394                                 break;
395                         }
396                 }
397
398                 l = manage (left_aligned_label (_("Toggle snap using:")));
399                 l->set_name ("OptionsLabel");
400
401                 t->attach (*l, 0, 1, 3, 4, FILL | EXPAND, FILL);
402                 t->attach (_snap_modifier_combo, 1, 2, 3, 4, FILL | EXPAND, FILL);
403
404                 vector<string> strs;
405
406                 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
407                         strs.push_back (bf->first);
408                 }
409
410                 set_popdown_strings (_keyboard_layout_selector, strs);
411                 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
412                 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
413
414                 l = manage (left_aligned_label (_("Keyboard layout:")));
415                 l->set_name ("OptionsLabel");
416
417                 t->attach (*l, 0, 1, 4, 5, FILL | EXPAND, FILL);
418                 t->attach (_keyboard_layout_selector, 1, 2, 4, 5, FILL | EXPAND, FILL);
419
420                 _box->pack_start (*t, false, false);
421         }
422
423         void parameter_changed (string const &)
424         {
425                 /* XXX: these aren't really config options... */
426         }
427
428         void set_state_from_config ()
429         {
430                 /* XXX: these aren't really config options... */
431         }
432
433 private:
434
435         void bindings_changed ()
436         {
437                 string const txt = _keyboard_layout_selector.get_active_text();
438
439                 /* XXX: config...?  for all this keyboard stuff */
440
441                 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
442                         if (txt == i->first) {
443                                 if (Keyboard::load_keybindings (i->second)) {
444                                         Keyboard::save_keybindings ();
445                                 }
446                         }
447                 }
448         }
449
450         void edit_modifier_chosen ()
451         {
452                 string const txt = _edit_modifier_combo.get_active_text();
453
454                 for (int i = 0; modifiers[i].name; ++i) {
455                         if (txt == _(modifiers[i].name)) {
456                                 Keyboard::set_edit_modifier (modifiers[i].modifier);
457                                 break;
458                         }
459                 }
460         }
461
462         void delete_modifier_chosen ()
463         {
464                 string const txt = _delete_modifier_combo.get_active_text();
465
466                 for (int i = 0; modifiers[i].name; ++i) {
467                         if (txt == _(modifiers[i].name)) {
468                                 Keyboard::set_delete_modifier (modifiers[i].modifier);
469                                 break;
470                         }
471                 }
472         }
473
474         void insert_note_modifier_chosen ()
475         {
476                 string const txt = _insert_note_modifier_combo.get_active_text();
477
478                 for (int i = 0; modifiers[i].name; ++i) {
479                         if (txt == _(modifiers[i].name)) {
480                                 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
481                                 break;
482                         }
483                 }
484         }
485
486         void snap_modifier_chosen ()
487         {
488                 string const txt = _snap_modifier_combo.get_active_text();
489
490                 for (int i = 0; modifiers[i].name; ++i) {
491                         if (txt == _(modifiers[i].name)) {
492                                 Keyboard::set_snap_modifier (modifiers[i].modifier);
493                                 break;
494                         }
495                 }
496         }
497
498         void delete_button_changed ()
499         {
500                 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
501         }
502
503         void edit_button_changed ()
504         {
505                 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
506         }
507
508         void insert_note_button_changed ()
509         {
510                 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
511         }
512
513         ComboBoxText _keyboard_layout_selector;
514         ComboBoxText _edit_modifier_combo;
515         ComboBoxText _delete_modifier_combo;
516         ComboBoxText _insert_note_modifier_combo;
517         ComboBoxText _snap_modifier_combo;
518         Adjustment _delete_button_adjustment;
519         SpinButton _delete_button_spin;
520         Adjustment _edit_button_adjustment;
521         SpinButton _edit_button_spin;
522         Adjustment _insert_note_button_adjustment;
523         SpinButton _insert_note_button_spin;
524
525 };
526
527 class FontScalingOptions : public OptionEditorBox
528 {
529 public:
530         FontScalingOptions (RCConfiguration* c) :
531                 _rc_config (c),
532                 _dpi_adjustment (50, 50, 250, 1, 10),
533                 _dpi_slider (_dpi_adjustment)
534         {
535                 _dpi_adjustment.set_value (_rc_config->get_font_scale () / 1024);
536
537                 Label* l = manage (new Label (_("Font scaling:")));
538                 l->set_name ("OptionsLabel");
539
540                 _dpi_slider.set_update_policy (UPDATE_DISCONTINUOUS);
541                 HBox* h = manage (new HBox);
542                 h->set_spacing (4);
543                 h->pack_start (*l, false, false);
544                 h->pack_start (_dpi_slider, true, true);
545
546                 _box->pack_start (*h, false, false);
547
548                 _dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
549         }
550
551         void parameter_changed (string const & p)
552         {
553                 if (p == "font-scale") {
554                         _dpi_adjustment.set_value (_rc_config->get_font_scale() / 1024);
555                 }
556         }
557
558         void set_state_from_config ()
559         {
560                 parameter_changed ("font-scale");
561         }
562
563 private:
564
565         void dpi_changed ()
566         {
567                 _rc_config->set_font_scale ((long) floor (_dpi_adjustment.get_value() * 1024));
568                 /* XXX: should be triggered from the parameter changed signal */
569                 reset_dpi ();
570         }
571
572         RCConfiguration* _rc_config;
573         Adjustment _dpi_adjustment;
574         HScale _dpi_slider;
575 };
576
577 class BufferingOptions : public OptionEditorBox
578 {
579 public:
580         BufferingOptions (RCConfiguration* c)
581                 : _rc_config (c)
582                 , _playback_adjustment (5, 1, 60, 1, 4)
583                 , _capture_adjustment (5, 1, 60, 1, 4)
584                 , _playback_slider (_playback_adjustment)
585                 , _capture_slider (_capture_adjustment)
586         {
587                 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
588
589                 Label* l = manage (new Label (_("Playback (seconds of buffering):")));
590                 l->set_name ("OptionsLabel");
591
592                 _playback_slider.set_update_policy (UPDATE_DISCONTINUOUS);
593                 HBox* h = manage (new HBox);
594                 h->set_spacing (4);
595                 h->pack_start (*l, false, false);
596                 h->pack_start (_playback_slider, true, true);
597
598                 _box->pack_start (*h, false, false);
599
600                 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
601
602                 l = manage (new Label (_("Recording (seconds of buffering):")));
603                 l->set_name ("OptionsLabel");
604
605                 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
606                 h = manage (new HBox);
607                 h->set_spacing (4);
608                 h->pack_start (*l, false, false);
609                 h->pack_start (_capture_slider, true, true);
610
611                 _box->pack_start (*h, false, false);
612
613                 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
614                 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
615         }
616
617         void parameter_changed (string const & p)
618         {
619                 if (p == "playback-buffer-seconds") {
620                         _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
621                 } else if (p == "capture-buffer-seconds") {
622                         _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
623                 }
624         }
625
626         void set_state_from_config ()
627         {
628                 parameter_changed ("playback-buffer-seconds");
629                 parameter_changed ("capture-buffer-seconds");
630         }
631
632 private:
633
634         void playback_changed ()
635         {
636                 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
637         }
638
639         void capture_changed ()
640         {
641                 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
642         }
643
644         RCConfiguration* _rc_config;
645         Adjustment _playback_adjustment;
646         Adjustment _capture_adjustment;
647         HScale _playback_slider;
648         HScale _capture_slider;
649 };
650
651 class ControlSurfacesOptions : public OptionEditorBox
652 {
653 public:
654         ControlSurfacesOptions (Gtk::Window& parent)
655                 : _parent (parent)
656         {
657                 _store = ListStore::create (_model);
658                 _view.set_model (_store);
659                 _view.append_column (_("Name"), _model.name);
660                 _view.get_column(0)->set_resizable (true);
661                 _view.get_column(0)->set_expand (true);
662                 _view.append_column_editable (_("Enabled"), _model.enabled);
663                 _view.append_column_editable (_("Feedback"), _model.feedback);
664
665                 _box->pack_start (_view, false, false);
666
667                 Label* label = manage (new Label);
668                 label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
669
670                 _box->pack_start (*label, false, false);
671                 label->show ();
672
673                 ControlProtocolManager& m = ControlProtocolManager::instance ();
674                 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
675                                                 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
676
677                 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
678                 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
679         }
680
681         void parameter_changed (std::string const &)
682         {
683
684         }
685
686         void set_state_from_config ()
687         {
688                 _store->clear ();
689
690                 ControlProtocolManager& m = ControlProtocolManager::instance ();
691                 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
692
693                         if (!(*i)->mandatory) {
694                                 TreeModel::Row r = *_store->append ();
695                                 r[_model.name] = (*i)->name;
696                                 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
697                                 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
698                                 r[_model.protocol_info] = *i;
699                         }
700                 }
701         }
702
703 private:
704
705         void protocol_status_changed (ControlProtocolInfo* cpi) {
706                 /* find the row */
707                 TreeModel::Children rows = _store->children();
708                 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
709                         if ((*x)[_model.protocol_info] == cpi) {
710                                 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
711                                 break;
712                         }
713                 }
714         }
715
716         void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
717         {
718                 TreeModel::Row r = *i;
719
720                 ControlProtocolInfo* cpi = r[_model.protocol_info];
721                 if (!cpi) {
722                         return;
723                 }
724
725                 bool const was_enabled = (cpi->protocol != 0);
726                 bool const is_enabled = r[_model.enabled];
727
728                 if (was_enabled != is_enabled) {
729                         if (!was_enabled) {
730                                 ControlProtocolManager::instance().instantiate (*cpi);
731                         } else {
732                                 Gtk::Window* win = r[_model.editor];
733                                 if (win) {
734                                         win->hide ();
735                                 }
736
737                                 ControlProtocolManager::instance().teardown (*cpi);
738                                         
739                                 if (win) {
740                                         delete win;
741                                 }
742                                 r[_model.editor] = 0;
743                                 cpi->requested = false;
744                         }
745                 }
746
747                 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
748                 bool const is_feedback = r[_model.feedback];
749
750                 if (was_feedback != is_feedback && cpi->protocol) {
751                         cpi->protocol->set_feedback (is_feedback);
752                 }
753         }
754
755         void edit_clicked (GdkEventButton* ev)
756         {
757                 if (ev->type != GDK_2BUTTON_PRESS) {
758                         return;
759                 }
760
761                 std::string name;
762                 ControlProtocolInfo* cpi;
763                 TreeModel::Row row;
764
765                 row = *(_view.get_selection()->get_selected());
766
767                 Window* win = row[_model.editor];
768                 if (win && !win->is_visible()) {
769                         win->present ();
770                 } else {
771                         cpi = row[_model.protocol_info];
772
773                         if (cpi && cpi->protocol && cpi->protocol->has_editor ()) {
774                                 Box* box = (Box*) cpi->protocol->get_gui ();
775                                 if (box) {
776                                         string title = row[_model.name];
777                                         ArdourWindow* win = new ArdourWindow (_parent, title);
778                                         win->set_title ("Control Protocol Options");
779                                         win->add (*box);
780                                         box->show ();
781                                         win->present ();
782                                         row[_model.editor] = win;
783                                 }
784                         }
785                 }
786         }
787
788         class ControlSurfacesModelColumns : public TreeModelColumnRecord
789         {
790         public:
791
792                 ControlSurfacesModelColumns ()
793                 {
794                         add (name);
795                         add (enabled);
796                         add (feedback);
797                         add (protocol_info);
798                         add (editor);
799                 }
800
801                 TreeModelColumn<string> name;
802                 TreeModelColumn<bool> enabled;
803                 TreeModelColumn<bool> feedback;
804                 TreeModelColumn<ControlProtocolInfo*> protocol_info;
805                 TreeModelColumn<Gtk::Window*> editor;
806         };
807
808         Glib::RefPtr<ListStore> _store;
809         ControlSurfacesModelColumns _model;
810         TreeView _view;
811         Gtk::Window& _parent;
812         PBD::ScopedConnection protocol_status_connection;
813 };
814
815 /** A class which allows control of visibility of some editor components usign
816  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
817  *  which has the correct members, but with null widget pointers.  This
818  *  class allows the user to set visibility of the members, the details
819  *  of which are stored in a configuration variable which can be watched
820  *  by parts of the editor that actually contain the widgets whose visibility
821  *  is being controlled.
822  */
823
824 class VisibilityOption : public Option
825 {
826 public:
827         /** @param name User-visible name for this group.
828          *  @param g `Dummy' VisibilityGroup (as described above).
829          *  @param get Method to get the value of the appropriate configuration variable.
830          *  @param set Method to set the value of the appropriate configuration variable.
831          */
832         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
833                 : Option (g->get_state_name(), name)
834                 , _heading (name)
835                 , _visibility_group (g)
836                 , _get (get)
837                 , _set (set)
838         {
839                 /* Watch for changes made by the user to our members */
840                 _visibility_group->VisibilityChanged.connect_same_thread (
841                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
842                         );
843         }
844
845         void set_state_from_config ()
846         {
847                 /* Set our state from the current configuration */
848                 _visibility_group->set_state (_get ());
849         }
850
851         void add_to_page (OptionEditorPage* p)
852         {
853                 _heading.add_to_page (p);
854                 add_widget_to_page (p, _visibility_group->list_view ());
855         }
856
857         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
858
859 private:
860         void changed ()
861         {
862                 /* The user has changed something, so reflect this change
863                    in the RCConfiguration.
864                 */
865                 _set (_visibility_group->get_state_value ());
866         }
867         
868         OptionEditorHeading _heading;
869         VisibilityGroup* _visibility_group;
870         sigc::slot<std::string> _get;
871         sigc::slot<bool, std::string> _set;
872         PBD::ScopedConnection _visibility_group_connection;
873 };
874
875
876 RCOptionEditor::RCOptionEditor ()
877         : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
878         , _rc_config (Config)
879         , _mixer_strip_visibility ("mixer-strip-visibility")
880 {
881         /* MISC */
882
883         uint32_t hwcpus = hardware_concurrency ();
884
885         if (hwcpus > 1) {
886                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
887
888                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
889                         "processor-usage",
890                         _("Signal processing uses"),
891                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
892                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
893                         );
894
895                 procs->add (-1, _("all but one processor"));
896                 procs->add (0, _("all available processors"));
897
898                 for (uint32_t i = 1; i <= hwcpus; ++i) {
899                         procs->add (i, string_compose (_("%1 processors"), i));
900                 }
901
902                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
903
904                 add_option (_("Misc"), procs);
905         }
906
907         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
908
909         add_option (_("Misc"), new UndoOptions (_rc_config));
910
911         add_option (_("Misc"),
912              new BoolOption (
913                      "verify-remove-last-capture",
914                      _("Verify removal of last capture"),
915                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
916                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
917                      ));
918
919         add_option (_("Misc"),
920              new BoolOption (
921                      "periodic-safety-backups",
922                      _("Make periodic backups of the session file"),
923                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
924                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
925                      ));
926
927         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
928
929         add_option (_("Misc"),
930              new BoolOption (
931                      "only-copy-imported-files",
932                      _("Always copy imported files"),
933                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_only_copy_imported_files),
934                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_only_copy_imported_files)
935                      ));
936
937         add_option (_("Misc"), new DirectoryOption (
938                             X_("default-session-parent-dir"),
939                             _("Default folder for new sessions:"),
940                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
941                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
942                             ));
943
944         add_option (_("Misc"),
945              new SpinOption<uint32_t> (
946                      "max-recent-sessions",
947                      _("Maximum number of recent sessions"),
948                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
949                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
950                      0, 1000, 1, 20
951                      ));
952
953         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
954
955         add_option (_("Misc"), new ClickOptions (_rc_config, this));
956
957         add_option (_("Misc"),
958              new FaderOption (
959                      "click-gain",
960                      _("Click gain level"),
961                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
962                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
963                      ));
964
965         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
966
967         add_option (_("Misc"),
968              new SpinOption<double> (
969                      "automation-thinning-factor",
970                      _("Thinning factor (larger value => less data)"),
971                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
972                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
973                      0, 1000, 1, 20
974                      ));
975
976         /* TRANSPORT */
977
978         BoolOption* tsf;
979
980         tsf = new BoolOption (
981                      "latched-record-enable",
982                      _("Keep record-enable engaged on stop"),
983                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
984                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
985                      );
986         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
987         add_option (_("Transport"), tsf);
988
989         tsf = new BoolOption (
990                      "stop-recording-on-xrun",
991                      _("Stop recording when an xrun occurs"),
992                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
993                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
994                      );
995         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> Ardour will stop recording if an over- or underrun is detected by the audio engine"));
996         add_option (_("Transport"), tsf);
997
998         tsf = new BoolOption (
999                      "create-xrun-marker",
1000                      _("Create markers where xruns occur"),
1001                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1002                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1003                      );
1004         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1005         add_option (_("Transport"), tsf);
1006
1007         tsf = new BoolOption (
1008                      "stop-at-session-end",
1009                      _("Stop at the end of the session"),
1010                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1011                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1012                      );
1013         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> if Ardour is <b>not recording</b>, it will stop the transport "
1014                                                    "when it reaches the current session end marker\n\n"
1015                                                    "<b>When disabled</b> Ardour will continue to roll past the session end marker at all times"));
1016         add_option (_("Transport"), tsf);
1017
1018         tsf = new BoolOption (
1019                      "seamless-loop",
1020                      _("Do seamless looping (not possible when slaved to MTC, JACK etc)"),
1021                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1022                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1023                      );
1024         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1025                                                    "preventing any need to do a transport locate at the end of the loop\n\n"
1026                                                    "<b>When disabled</b> looping is done by locating back to the start of the loop when Ardour reaches the end "
1027                                                    "which will often cause a small click or delay"));
1028         add_option (_("Transport"), tsf);
1029
1030         tsf = new BoolOption (
1031                      "disable-disarm-during-roll",
1032                      _("Disable per-track record disarm while rolling"),
1033                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1034                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1035                      );
1036         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> this will prevent you from accidentally stopping specific tracks recording during a take"));
1037         add_option (_("Transport"), tsf);
1038
1039         tsf = new BoolOption (
1040                      "quieten_at_speed",
1041                      _("12dB gain reduction during fast-forward and fast-rewind"),
1042                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1043                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1044                      );
1045         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1046                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1047         add_option (_("Transport"), tsf);
1048
1049         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1050
1051         _sync_source = new ComboOption<SyncSource> (
1052                 "sync-source",
1053                 _("External timecode source"),
1054                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1055                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1056                 );
1057
1058         populate_sync_options ();
1059         add_option (_("Transport"), _sync_source);
1060
1061         _sync_framerate = new BoolOption (
1062                      "timecode-sync-frame-rate",
1063                      _("Match session video frame rate to external timecode"),
1064                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1065                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1066                      );
1067         Gtkmm2ext::UI::instance()->set_tip 
1068                 (_sync_framerate->tip_widget(),
1069                  _("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1070                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1071                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1072                    "Instead the frame rate indication in the main clock will flash red and Ardour will convert between the external "
1073                    "timecode standard and the session standard"));
1074
1075         add_option (_("Transport"), _sync_framerate);
1076
1077         _sync_genlock = new BoolOption (
1078                 "timecode-source-is-synced",
1079                 _("External timecode is sync locked"),
1080                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1081                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1082                 );
1083         Gtkmm2ext::UI::instance()->set_tip 
1084                 (_sync_genlock->tip_widget(), 
1085                  _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface"));
1086
1087
1088         add_option (_("Transport"), _sync_genlock);
1089
1090         _ltc_port = new ComboStringOption (
1091                 "ltc-source-port",
1092                 _("LTC incoming port"),
1093                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1094                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1095                 );
1096
1097         vector<string> physical_inputs;
1098         physical_inputs.push_back (_("None"));
1099         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1100         _ltc_port->set_popdown_strings (physical_inputs);
1101
1102         add_option (_("Transport"), _ltc_port);
1103
1104 #ifdef HAVE_LTC
1105         // TODO; rather disable this button than not compile it..
1106         add_option (_("Transport"),
1107                     new BoolOption (
1108                             "send-ltc",
1109                             _("Generate Linear/Longitudinal Time Code"),
1110                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1111                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1112                             ));
1113 #endif
1114
1115         parameter_changed ("sync-source");
1116
1117         /* EDITOR */
1118
1119         add_option (_("Editor"),
1120              new BoolOption (
1121                      "link-region-and-track-selection",
1122                      _("Link selection of regions and tracks"),
1123                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1124                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1125                      ));
1126
1127         add_option (_("Editor"),
1128              new BoolOption (
1129                      "automation-follows-regions",
1130                      _("Move relevant automation when audio regions are moved"),
1131                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1132                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1133                      ));
1134
1135         add_option (_("Editor"),
1136              new BoolOption (
1137                      "show-track-meters",
1138                      _("Show meters on tracks in the editor"),
1139                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1140                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1141                      ));
1142
1143         add_option (_("Editor"),
1144              new BoolOption (
1145                      "use-overlap-equivalency",
1146                      _("Use overlap equivalency for regions"),
1147                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1148                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1149                      ));
1150
1151         add_option (_("Editor"),
1152              new BoolOption (
1153                      "rubberbanding-snaps-to-grid",
1154                      _("Make rubberband selection rectangle snap to the grid"),
1155                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1156                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1157                      ));
1158
1159         add_option (_("Editor"),
1160              new BoolOption (
1161                      "show-waveforms",
1162                      _("Show waveforms in regions"),
1163                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1164                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1165                      ));
1166
1167         add_option (_("Editor"),
1168              new BoolComboOption (
1169                      "show-region-gain-envelopes",
1170                      _("Show gain envelopes in audio regions"),
1171                      _("in all modes"),
1172                      _("only in region gain mode"),
1173                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1174                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1175                      ));
1176
1177         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1178                 "waveform-scale",
1179                 _("Waveform scale"),
1180                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1181                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1182                 );
1183
1184         wfs->add (Linear, _("linear"));
1185         wfs->add (Logarithmic, _("logarithmic"));
1186
1187         add_option (_("Editor"), wfs);
1188
1189         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1190                 "waveform-shape",
1191                 _("Waveform shape"),
1192                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1193                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1194                 );
1195
1196         wfsh->add (Traditional, _("traditional"));
1197         wfsh->add (Rectified, _("rectified"));
1198
1199         add_option (_("Editor"), wfsh);
1200
1201         add_option (_("Editor"),
1202              new BoolOption (
1203                      "show-waveforms-while-recording",
1204                      _("Show waveforms for audio while it is being recorded"),
1205                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1206                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1207                      ));
1208
1209         add_option (_("Editor"),
1210                     new BoolOption (
1211                             "show-zoom-tools",
1212                             _("Show zoom toolbar"),
1213                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1214                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1215                             ));
1216
1217         add_option (_("Editor"),
1218                     new BoolOption (
1219                             "color-regions-using-track-color",
1220                             _("Color regions using their track's color"),
1221                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_color_regions_using_track_color),
1222                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
1223                             ));
1224
1225         add_option (_("Editor"),
1226                     new BoolOption (
1227                             "update-editor-during-summary-drag",
1228                             _("Update editor window during drags of the summary"),
1229                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1230                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1231                             ));
1232
1233         add_option (_("Editor"),
1234              new BoolOption (
1235                      "sync-all-route-ordering",
1236                      _("Synchronise editor and mixer track order"),
1237                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
1238                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
1239                      ));
1240
1241         add_option (_("Editor"),
1242              new BoolOption (
1243                      "link-editor-and-mixer-selection",
1244                      _("Synchronise editor and mixer selection"),
1245                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1246                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1247                      ));
1248
1249         add_option (_("Editor"),
1250              new BoolOption (
1251                      "name-new-markers",
1252                      _("Name new markers"),
1253                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1254                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1255                      ));
1256
1257         add_option (_("Editor"),
1258             new BoolOption (
1259                     "autoscroll-editor",
1260                     _("Auto-scroll editor window when dragging near its edges"),
1261                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1262                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1263                     ));
1264
1265         /* AUDIO */
1266
1267         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1268
1269         add_option (_("Audio"), new BufferingOptions (_rc_config));
1270
1271         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1272
1273         add_option (_("Audio"),
1274              new BoolOption (
1275                      "use-monitor-bus",
1276                      _("Use a monitor bus (allows AFL/PFL and more control)"),
1277                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_monitor_bus),
1278                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_monitor_bus)
1279                      ));
1280
1281         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1282                 "monitoring-model",
1283                 _("Record monitoring handled by"),
1284                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1285                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1286                 );
1287
1288 #ifndef __APPLE__
1289         /* no JACK monitoring on CoreAudio */
1290         if (AudioEngine::instance()->can_request_hardware_monitoring()) {
1291                 mm->add (HardwareMonitoring, _("JACK"));
1292         }
1293 #endif
1294         mm->add (SoftwareMonitoring, _("ardour"));
1295         mm->add (ExternalMonitoring, _("audio hardware"));
1296
1297         add_option (_("Audio"), mm);
1298
1299         add_option (_("Audio"),
1300              new BoolOption (
1301                      "tape-machine-mode",
1302                      _("Tape machine mode"),
1303                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1304                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1305                      ));
1306
1307         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1308
1309         add_option (_("Audio"),
1310                     new BoolOption (
1311                             "auto-connect-standard-busses",
1312                             _("Auto-connect master/monitor busses"),
1313                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1314                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1315                             ));
1316
1317         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1318                 "input-auto-connect",
1319                 _("Connect track inputs"),
1320                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1321                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1322                 );
1323
1324         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1325         iac->add (ManualConnect, _("manually"));
1326
1327         add_option (_("Audio"), iac);
1328
1329         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1330                 "output-auto-connect",
1331                 _("Connect track and bus outputs"),
1332                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1333                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1334                 );
1335
1336         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1337         oac->add (AutoConnectMaster, _("automatically to master bus"));
1338         oac->add (ManualConnect, _("manually"));
1339
1340         add_option (_("Audio"), oac);
1341
1342         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1343
1344         add_option (_("Audio"),
1345              new BoolOption (
1346                      "denormal-protection",
1347                      _("Use DC bias to protect against denormals"),
1348                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1349                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1350                      ));
1351
1352         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1353                 "denormal-model",
1354                 _("Processor handling"),
1355                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1356                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1357                 );
1358
1359         dm->add (DenormalNone, _("no processor handling"));
1360
1361         FPU fpu;
1362
1363         if (fpu.has_flush_to_zero()) {
1364                 dm->add (DenormalFTZ, _("use FlushToZero"));
1365         }
1366
1367         if (fpu.has_denormals_are_zero()) {
1368                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1369         }
1370
1371         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1372                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1373         }
1374
1375         add_option (_("Audio"), dm);
1376
1377         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1378
1379         add_option (_("Audio"),
1380              new BoolOption (
1381                      "plugins-stop-with-transport",
1382                      _("Silence plugins when the transport is stopped"),
1383                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1384                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1385                      ));
1386
1387         add_option (_("Audio"),
1388              new BoolOption (
1389                      "do-not-record-plugins",
1390                      _("Disable plugins during recording"),
1391                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_do_not_record_plugins),
1392                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_do_not_record_plugins)
1393                      ));
1394
1395         add_option (_("Audio"),
1396              new BoolOption (
1397                      "new-plugins-active",
1398                      _("Make new plugins active"),
1399                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1400                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1401                      ));
1402
1403         add_option (_("Audio"),
1404              new BoolOption (
1405                      "auto-analyse-audio",
1406                      _("Enable automatic analysis of audio"),
1407                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1408                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1409                      ));
1410
1411         add_option (_("Audio"),
1412              new BoolOption (
1413                      "replicate-missing-region-channels",
1414                      _("Replicate missing region channels"),
1415                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1416                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1417                      ));
1418
1419         /* SOLO AND MUTE */
1420
1421         add_option (_("Solo / mute"),
1422              new FaderOption (
1423                      "solo-mute-gain",
1424                      _("Solo-in-place mute cut (dB)"),
1425                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1426                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1427                      ));
1428
1429         _solo_control_is_listen_control = new BoolOption (
1430                 "solo-control-is-listen-control",
1431                 _("Solo controls are Listen controls"),
1432                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1433                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1434                 );
1435
1436         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1437
1438         _listen_position = new ComboOption<ListenPosition> (
1439                 "listen-position",
1440                 _("Listen Position"),
1441                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1442                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1443                 );
1444
1445         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1446         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1447
1448         add_option (_("Solo / mute"), _listen_position);
1449
1450         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1451                 "pfl-position",
1452                 _("PFL signals come from"),
1453                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1454                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1455                 );
1456
1457         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1458         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1459
1460         add_option (_("Solo / mute"), pp);
1461
1462         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1463                 "afl-position",
1464                 _("AFL signals come from"),
1465                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1466                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1467                 );
1468
1469         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1470         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1471
1472         add_option (_("Solo / mute"), pa);
1473
1474         parameter_changed ("use-monitor-bus");
1475
1476         add_option (_("Solo / mute"),
1477              new BoolOption (
1478                      "exclusive-solo",
1479                      _("Exclusive solo"),
1480                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1481                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1482                      ));
1483
1484         add_option (_("Solo / mute"),
1485              new BoolOption (
1486                      "show-solo-mutes",
1487                      _("Show solo muting"),
1488                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1489                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1490                      ));
1491
1492         add_option (_("Solo / mute"),
1493              new BoolOption (
1494                      "solo-mute-override",
1495                      _("Soloing overrides muting"),
1496                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1497                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1498                      ));
1499
1500         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1501
1502         add_option (_("Solo / mute"),
1503              new BoolOption (
1504                      "mute-affects-pre-fader",
1505                      _("Mute affects pre-fader sends"),
1506                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1507                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1508                      ));
1509
1510         add_option (_("Solo / mute"),
1511              new BoolOption (
1512                      "mute-affects-post-fader",
1513                      _("Mute affects post-fader sends"),
1514                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1515                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1516                      ));
1517
1518         add_option (_("Solo / mute"),
1519              new BoolOption (
1520                      "mute-affects-control-outs",
1521                      _("Mute affects control outputs"),
1522                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1523                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1524                      ));
1525
1526         add_option (_("Solo / mute"),
1527              new BoolOption (
1528                      "mute-affects-main-outs",
1529                      _("Mute affects main outputs"),
1530                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1531                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1532                      ));
1533
1534         add_option (_("MIDI"),
1535                     new BoolOption (
1536                             "send-midi-clock",
1537                             _("Send MIDI Clock"),
1538                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1539                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1540                             ));
1541
1542         add_option (_("MIDI"),
1543                     new BoolOption (
1544                             "send-mtc",
1545                             _("Send MIDI Time Code"),
1546                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1547                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1548                             ));
1549
1550         add_option (_("MIDI"),
1551                     new SpinOption<int> (
1552                             "mtc-qf-speed-tolerance",
1553                             _("Percentage either side of normal transport speed to transmit MTC"),
1554                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1555                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1556                             0, 20, 1, 5
1557                             ));
1558
1559         add_option (_("MIDI"),
1560                     new BoolOption (
1561                             "mmc-control",
1562                             _("Obey MIDI Machine Control commands"),
1563                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1564                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1565                             ));
1566
1567         add_option (_("MIDI"),
1568                     new BoolOption (
1569                             "send-mmc",
1570                             _("Send MIDI Machine Control commands"),
1571                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1572                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1573                             ));
1574
1575         add_option (_("MIDI"),
1576                     new BoolOption (
1577                             "midi-feedback",
1578                             _("Send MIDI control feedback"),
1579                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1580                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1581                             ));
1582
1583         add_option (_("MIDI"),
1584              new SpinOption<uint8_t> (
1585                      "mmc-receive-device-id",
1586                      _("Inbound MMC device ID"),
1587                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1588                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1589                      0, 128, 1, 10
1590                      ));
1591
1592         add_option (_("MIDI"),
1593              new SpinOption<uint8_t> (
1594                      "mmc-send-device-id",
1595                      _("Outbound MMC device ID"),
1596                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1597                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1598                      0, 128, 1, 10
1599                      ));
1600
1601         add_option (_("MIDI"),
1602              new SpinOption<int32_t> (
1603                      "initial-program-change",
1604                      _("Initial program change"),
1605                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1606                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1607                      -1, 65536, 1, 10
1608                      ));
1609
1610         add_option (_("MIDI"),
1611                     new BoolOption (
1612                             "diplay-first-midi-bank-as-zero",
1613                             _("Display first MIDI bank/program as 0"),
1614                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1615                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1616                             ));
1617
1618         add_option (_("MIDI"),
1619              new BoolOption (
1620                      "never-display-periodic-midi",
1621                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1622                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1623                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1624                      ));
1625
1626         add_option (_("MIDI"),
1627              new BoolOption (
1628                      "sound-midi-notes",
1629                      _("Sound MIDI notes as they are selected"),
1630                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1631                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1632                      ));
1633
1634         /* USER INTERACTION */
1635
1636         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1637
1638         add_option (_("User interaction"), new KeyboardOptions);
1639
1640         add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
1641
1642         add_option (_("User interaction"), new ControlSurfacesOptions (*this));
1643
1644         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1645                 "remote-model",
1646                 _("Control surface remote ID"),
1647                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1648                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1649                 );
1650
1651         rm->add (UserOrdered, _("assigned by user"));
1652         rm->add (MixerOrdered, _("follows order of mixer"));
1653         rm->add (EditorOrdered, _("follows order of editor"));
1654
1655         add_option (_("User interaction"), rm);
1656
1657         /* INTERFACE */
1658
1659         add_option (S_("GUI"),
1660              new BoolOption (
1661                      "widget-prelight",
1662                      _("Graphically indicate mouse pointer hovering over various widgets"),
1663                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
1664                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
1665                      ));
1666
1667 #ifndef GTKOSX
1668         /* font scaling does nothing with GDK/Quartz */
1669         add_option (S_("GUI"), new FontScalingOptions (_rc_config));
1670 #endif
1671         add_option (S_("GUI"),
1672                     new BoolOption (
1673                             "use-own-plugin-gui",
1674                             _("Use plugins' own interfaces instead of Ardour's"),
1675                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
1676                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
1677                             ));
1678
1679         /* The names of these controls must be the same as those given in MixerStrip
1680            for the actual widgets being controlled.
1681         */
1682         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
1683         _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
1684         _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
1685         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
1686         _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
1687         _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
1688         
1689         add_option (
1690                 S_("GUI"),
1691                 new VisibilityOption (
1692                         _("Mixer Strip"),
1693                         &_mixer_strip_visibility,
1694                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
1695                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
1696                         )
1697                 );
1698
1699         add_option (S_("GUI"),
1700              new BoolOption (
1701                      "default-narrow_ms",
1702                      _("Use narrow strips in the mixer by default"),
1703                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
1704                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
1705                      ));
1706
1707         add_option (S_("GUI"), new OptionEditorHeading (_("Metering")));
1708
1709         ComboOption<float>* mht = new ComboOption<float> (
1710                 "meter-hold",
1711                 _("Meter hold time"),
1712                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
1713                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
1714                 );
1715
1716         mht->add (MeterHoldOff, _("off"));
1717         mht->add (MeterHoldShort, _("short"));
1718         mht->add (MeterHoldMedium, _("medium"));
1719         mht->add (MeterHoldLong, _("long"));
1720
1721         add_option (S_("GUI"), mht);
1722
1723         ComboOption<float>* mfo = new ComboOption<float> (
1724                 "meter-falloff",
1725                 _("Meter fall-off"),
1726                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
1727                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
1728                 );
1729
1730         mfo->add (METER_FALLOFF_OFF, _("off"));
1731         mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
1732         mfo->add (METER_FALLOFF_SLOW, _("slow"));
1733         mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
1734         mfo->add (METER_FALLOFF_FAST, _("fast"));
1735         mfo->add (METER_FALLOFF_FASTER, _("faster"));
1736         mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
1737
1738         add_option (S_("GUI"), mfo);
1739 }
1740
1741 void
1742 RCOptionEditor::parameter_changed (string const & p)
1743 {
1744         OptionEditor::parameter_changed (p);
1745
1746         if (p == "use-monitor-bus") {
1747                 bool const s = Config->get_use_monitor_bus ();
1748                 if (!s) {
1749                         /* we can't use this if we don't have a monitor bus */
1750                         Config->set_solo_control_is_listen_control (false);
1751                 }
1752                 _solo_control_is_listen_control->set_sensitive (s);
1753                 _listen_position->set_sensitive (s);
1754         } else if (p == "sync-source") {
1755                 switch(Config->get_sync_source()) {
1756                 case ARDOUR::MTC:
1757                 case ARDOUR::LTC:
1758                         _sync_genlock->set_sensitive (true);
1759                         _sync_framerate->set_sensitive (true);
1760                         break;
1761                 default:
1762                         _sync_genlock->set_sensitive (false);
1763                         _sync_framerate->set_sensitive (false);
1764                         break;
1765                 }
1766         }
1767 }
1768
1769 void
1770 RCOptionEditor::populate_sync_options ()
1771 {
1772         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
1773
1774         _sync_source->clear ();
1775
1776         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
1777                 _sync_source->add (*i, sync_source_to_string (*i));
1778         }
1779 }