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