0275922437766c7aa308a582e1c6ae9f07c0eb72
[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(), _("<b>When enabled</b> Ardour will stop recording if an over- or underrun is detected by the audio engine"));
1004         add_option (_("Transport"), tsf);
1005
1006         tsf = new BoolOption (
1007                      "create-xrun-marker",
1008                      _("Create markers where xruns occur"),
1009                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1010                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1011                      );
1012         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1013         add_option (_("Transport"), tsf);
1014
1015         tsf = new BoolOption (
1016                      "stop-at-session-end",
1017                      _("Stop at the end of the session"),
1018                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1019                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1020                      );
1021         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> if Ardour is <b>not recording</b>, it will stop the transport "
1022                                                    "when it reaches the current session end marker\n\n"
1023                                                    "<b>When disabled</b> Ardour will continue to roll past the session end marker at all times"));
1024         add_option (_("Transport"), tsf);
1025
1026         tsf = new BoolOption (
1027                      "seamless-loop",
1028                      _("Do seamless looping (not possible when slaved to MTC, JACK etc)"),
1029                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1030                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1031                      );
1032         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, "
1033                                                    "preventing any need to do a transport locate at the end of the loop\n\n"
1034                                                    "<b>When disabled</b> looping is done by locating back to the start of the loop when Ardour reaches the end "
1035                                                    "which will often cause a small click or delay"));
1036         add_option (_("Transport"), tsf);
1037
1038         tsf = new BoolOption (
1039                      "disable-disarm-during-roll",
1040                      _("Disable per-track record disarm while rolling"),
1041                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1042                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1043                      );
1044         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"));
1045         add_option (_("Transport"), tsf);
1046
1047         tsf = new BoolOption (
1048                      "quieten_at_speed",
1049                      _("12dB gain reduction during fast-forward and fast-rewind"),
1050                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1051                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1052                      );
1053         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1054                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1055         add_option (_("Transport"), tsf);
1056
1057         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1058
1059         _sync_source = new ComboOption<SyncSource> (
1060                 "sync-source",
1061                 _("External timecode source"),
1062                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1063                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1064                 );
1065
1066         populate_sync_options ();
1067         add_option (_("Transport"), _sync_source);
1068
1069         _sync_framerate = new BoolOption (
1070                      "timecode-sync-frame-rate",
1071                      _("Match session video frame rate to external timecode"),
1072                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1073                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1074                      );
1075         Gtkmm2ext::UI::instance()->set_tip 
1076                 (_sync_framerate->tip_widget(),
1077                  _("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1078                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1079                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1080                    "Instead the frame rate indication in the main clock will flash red and Ardour will convert between the external "
1081                    "timecode standard and the session standard."));
1082
1083         add_option (_("Transport"), _sync_framerate);
1084
1085         _sync_genlock = new BoolOption (
1086                 "timecode-source-is-synced",
1087                 _("External timecode is sync locked"),
1088                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1089                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1090                 );
1091         Gtkmm2ext::UI::instance()->set_tip 
1092                 (_sync_genlock->tip_widget(), 
1093                  _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface."));
1094
1095
1096         add_option (_("Transport"), _sync_genlock);
1097
1098         _sync_source_2997 = new BoolOption (
1099                 "timecode-source-2997",
1100                 _("Lock to 29.9700 fps instead of 30000/1001"),
1101                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1102                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1103                 );
1104         Gtkmm2ext::UI::instance()->set_tip
1105                 (_sync_source_2997->tip_widget(),
1106                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1107                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1108                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1109                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1110                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1111                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1112                          ));
1113
1114         add_option (_("Transport"), _sync_source_2997);
1115
1116         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1117
1118         _ltc_port = new ComboStringOption (
1119                 "ltc-source-port",
1120                 _("LTC incoming port"),
1121                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1122                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1123                 );
1124
1125         vector<string> physical_inputs;
1126         physical_inputs.push_back (_("None"));
1127         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1128         _ltc_port->set_popdown_strings (physical_inputs);
1129
1130         add_option (_("Transport"), _ltc_port);
1131
1132         // TODO; rather disable this button than not compile it..
1133         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1134
1135         add_option (_("Transport"),
1136                     new BoolOption (
1137                             "send-ltc",
1138                             _("Enable LTC generator"),
1139                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1140                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1141                             ));
1142
1143         _ltc_send_continuously = new BoolOption (
1144                             "ltc-send-continuously",
1145                             _("send LTC while stopped"),
1146                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1147                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1148                             );
1149         Gtkmm2ext::UI::instance()->set_tip
1150                 (_ltc_send_continuously->tip_widget(),
1151                  _("<b>When enabled</b> Ardour will continue to send LTC information even when the transport (playhead) is not moving"));
1152         add_option (_("Transport"), _ltc_send_continuously);
1153
1154         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1155         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1156         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1157         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1158
1159         Gtkmm2ext::UI::instance()->set_tip
1160                 (_ltc_volume_slider->tip_widget(),
1161                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1162
1163         add_option (_("Transport"), _ltc_volume_slider);
1164         parameter_changed ("send-ltc");
1165
1166         parameter_changed ("sync-source");
1167
1168         /* EDITOR */
1169
1170         add_option (_("Editor"),
1171              new BoolOption (
1172                      "link-region-and-track-selection",
1173                      _("Link selection of regions and tracks"),
1174                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1175                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1176                      ));
1177
1178         add_option (_("Editor"),
1179              new BoolOption (
1180                      "automation-follows-regions",
1181                      _("Move relevant automation when audio regions are moved"),
1182                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1183                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1184                      ));
1185
1186         add_option (_("Editor"),
1187              new BoolOption (
1188                      "show-track-meters",
1189                      _("Show meters on tracks in the editor"),
1190                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1191                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1192                      ));
1193
1194         bco = new BoolComboOption (
1195                      "use-overlap-equivalency",
1196                      _("Regions in active edit groups are edited together"),
1197                      _("whenever they overlap in time"),
1198                      _("only if they have identical length, position and origin"),
1199                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1200                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1201                      );
1202
1203         add_option (_("Editor"), bco);
1204
1205         add_option (_("Editor"),
1206              new BoolOption (
1207                      "rubberbanding-snaps-to-grid",
1208                      _("Make rubberband selection rectangle snap to the grid"),
1209                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1210                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1211                      ));
1212
1213         add_option (_("Editor"),
1214              new BoolOption (
1215                      "show-waveforms",
1216                      _("Show waveforms in regions"),
1217                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1218                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1219                      ));
1220
1221         add_option (_("Editor"),
1222              new BoolComboOption (
1223                      "show-region-gain-envelopes",
1224                      _("Show gain envelopes in audio regions"),
1225                      _("in all modes"),
1226                      _("only in region gain mode"),
1227                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1228                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1229                      ));
1230
1231         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1232                 "waveform-scale",
1233                 _("Waveform scale"),
1234                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1235                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1236                 );
1237
1238         wfs->add (Linear, _("linear"));
1239         wfs->add (Logarithmic, _("logarithmic"));
1240
1241         add_option (_("Editor"), wfs);
1242
1243         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1244                 "waveform-shape",
1245                 _("Waveform shape"),
1246                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1247                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1248                 );
1249
1250         wfsh->add (Traditional, _("traditional"));
1251         wfsh->add (Rectified, _("rectified"));
1252
1253         add_option (_("Editor"), wfsh);
1254
1255         add_option (_("Editor"),
1256              new BoolOption (
1257                      "show-waveforms-while-recording",
1258                      _("Show waveforms for audio while it is being recorded"),
1259                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1260                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1261                      ));
1262
1263         add_option (_("Editor"),
1264                     new BoolOption (
1265                             "show-zoom-tools",
1266                             _("Show zoom toolbar"),
1267                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1268                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1269                             ));
1270
1271         add_option (_("Editor"),
1272                     new BoolOption (
1273                             "color-regions-using-track-color",
1274                             _("Color regions using their track's color"),
1275                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_color_regions_using_track_color),
1276                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
1277                             ));
1278
1279         add_option (_("Editor"),
1280                     new BoolOption (
1281                             "update-editor-during-summary-drag",
1282                             _("Update editor window during drags of the summary"),
1283                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1284                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1285                             ));
1286
1287         add_option (_("Editor"),
1288              new BoolOption (
1289                      "sync-all-route-ordering",
1290                      _("Synchronise editor and mixer track order"),
1291                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
1292                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
1293                      ));
1294
1295         add_option (_("Editor"),
1296              new BoolOption (
1297                      "link-editor-and-mixer-selection",
1298                      _("Synchronise editor and mixer selection"),
1299                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1300                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1301                      ));
1302
1303         bo = new BoolOption (
1304                      "name-new-markers",
1305                      _("Name new markers"),
1306                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1307                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1308                 );
1309         
1310         add_option (_("Editor"), bo);
1311         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."
1312                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1313
1314         add_option (_("Editor"),
1315             new BoolOption (
1316                     "autoscroll-editor",
1317                     _("Auto-scroll editor window when dragging near its edges"),
1318                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1319                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1320                     ));
1321
1322         /* AUDIO */
1323
1324         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1325
1326         add_option (_("Audio"), new BufferingOptions (_rc_config));
1327
1328         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1329
1330         add_option (_("Audio"),
1331              new BoolOption (
1332                      "use-monitor-bus",
1333                      _("Use a monitor bus (allows AFL/PFL and more control)"),
1334                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_monitor_bus),
1335                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_monitor_bus)
1336                      ));
1337
1338         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1339                 "monitoring-model",
1340                 _("Record monitoring handled by"),
1341                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1342                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1343                 );
1344
1345 #ifndef __APPLE__
1346         /* no JACK monitoring on CoreAudio */
1347         if (AudioEngine::instance()->can_request_hardware_monitoring()) {
1348                 mm->add (HardwareMonitoring, _("JACK"));
1349         }
1350 #endif
1351         mm->add (SoftwareMonitoring, _("ardour"));
1352         mm->add (ExternalMonitoring, _("audio hardware"));
1353
1354         add_option (_("Audio"), mm);
1355
1356         add_option (_("Audio"),
1357              new BoolOption (
1358                      "tape-machine-mode",
1359                      _("Tape machine mode"),
1360                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1361                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1362                      ));
1363
1364         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1365
1366         add_option (_("Audio"),
1367                     new BoolOption (
1368                             "auto-connect-standard-busses",
1369                             _("Auto-connect master/monitor busses"),
1370                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1371                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1372                             ));
1373
1374         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1375                 "input-auto-connect",
1376                 _("Connect track inputs"),
1377                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1378                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1379                 );
1380
1381         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1382         iac->add (ManualConnect, _("manually"));
1383
1384         add_option (_("Audio"), iac);
1385
1386         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1387                 "output-auto-connect",
1388                 _("Connect track and bus outputs"),
1389                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1390                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1391                 );
1392
1393         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1394         oac->add (AutoConnectMaster, _("automatically to master bus"));
1395         oac->add (ManualConnect, _("manually"));
1396
1397         add_option (_("Audio"), oac);
1398
1399         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1400
1401         add_option (_("Audio"),
1402              new BoolOption (
1403                      "denormal-protection",
1404                      _("Use DC bias to protect against denormals"),
1405                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1406                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1407                      ));
1408
1409         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1410                 "denormal-model",
1411                 _("Processor handling"),
1412                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1413                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1414                 );
1415
1416         dm->add (DenormalNone, _("no processor handling"));
1417
1418         FPU fpu;
1419
1420         if (fpu.has_flush_to_zero()) {
1421                 dm->add (DenormalFTZ, _("use FlushToZero"));
1422         }
1423
1424         if (fpu.has_denormals_are_zero()) {
1425                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1426         }
1427
1428         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1429                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1430         }
1431
1432         add_option (_("Audio"), dm);
1433
1434         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1435
1436         add_option (_("Audio"),
1437              new BoolOption (
1438                      "plugins-stop-with-transport",
1439                      _("Silence plugins when the transport is stopped"),
1440                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1441                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1442                      ));
1443
1444         add_option (_("Audio"),
1445              new BoolOption (
1446                      "new-plugins-active",
1447                      _("Make new plugins active"),
1448                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1449                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1450                      ));
1451
1452         add_option (_("Audio"),
1453              new BoolOption (
1454                      "auto-analyse-audio",
1455                      _("Enable automatic analysis of audio"),
1456                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1457                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1458                      ));
1459
1460         add_option (_("Audio"),
1461              new BoolOption (
1462                      "replicate-missing-region-channels",
1463                      _("Replicate missing region channels"),
1464                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1465                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1466                      ));
1467
1468         /* SOLO AND MUTE */
1469
1470         add_option (_("Solo / mute"),
1471              new FaderOption (
1472                      "solo-mute-gain",
1473                      _("Solo-in-place mute cut (dB)"),
1474                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1475                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1476                      ));
1477
1478         _solo_control_is_listen_control = new BoolOption (
1479                 "solo-control-is-listen-control",
1480                 _("Solo controls are Listen controls"),
1481                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1482                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1483                 );
1484
1485         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1486
1487         _listen_position = new ComboOption<ListenPosition> (
1488                 "listen-position",
1489                 _("Listen Position"),
1490                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1491                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1492                 );
1493
1494         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1495         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1496
1497         add_option (_("Solo / mute"), _listen_position);
1498
1499         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1500                 "pfl-position",
1501                 _("PFL signals come from"),
1502                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1503                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1504                 );
1505
1506         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1507         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1508
1509         add_option (_("Solo / mute"), pp);
1510
1511         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1512                 "afl-position",
1513                 _("AFL signals come from"),
1514                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1515                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1516                 );
1517
1518         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1519         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1520
1521         add_option (_("Solo / mute"), pa);
1522
1523         parameter_changed ("use-monitor-bus");
1524
1525         add_option (_("Solo / mute"),
1526              new BoolOption (
1527                      "exclusive-solo",
1528                      _("Exclusive solo"),
1529                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1530                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1531                      ));
1532
1533         add_option (_("Solo / mute"),
1534              new BoolOption (
1535                      "show-solo-mutes",
1536                      _("Show solo muting"),
1537                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1538                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1539                      ));
1540
1541         add_option (_("Solo / mute"),
1542              new BoolOption (
1543                      "solo-mute-override",
1544                      _("Soloing overrides muting"),
1545                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1546                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1547                      ));
1548
1549         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1550
1551         add_option (_("Solo / mute"),
1552              new BoolOption (
1553                      "mute-affects-pre-fader",
1554                      _("Mute affects pre-fader sends"),
1555                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1556                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1557                      ));
1558
1559         add_option (_("Solo / mute"),
1560              new BoolOption (
1561                      "mute-affects-post-fader",
1562                      _("Mute affects post-fader sends"),
1563                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1564                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1565                      ));
1566
1567         add_option (_("Solo / mute"),
1568              new BoolOption (
1569                      "mute-affects-control-outs",
1570                      _("Mute affects control outputs"),
1571                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1572                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1573                      ));
1574
1575         add_option (_("Solo / mute"),
1576              new BoolOption (
1577                      "mute-affects-main-outs",
1578                      _("Mute affects main outputs"),
1579                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1580                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1581                      ));
1582
1583         add_option (_("MIDI"),
1584                     new BoolOption (
1585                             "send-midi-clock",
1586                             _("Send MIDI Clock"),
1587                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1588                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1589                             ));
1590
1591         add_option (_("MIDI"),
1592                     new BoolOption (
1593                             "send-mtc",
1594                             _("Send MIDI Time Code"),
1595                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1596                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1597                             ));
1598
1599         add_option (_("MIDI"),
1600                     new SpinOption<int> (
1601                             "mtc-qf-speed-tolerance",
1602                             _("Percentage either side of normal transport speed to transmit MTC"),
1603                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1604                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1605                             0, 20, 1, 5
1606                             ));
1607
1608         add_option (_("MIDI"),
1609                     new BoolOption (
1610                             "mmc-control",
1611                             _("Obey MIDI Machine Control commands"),
1612                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1613                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1614                             ));
1615
1616         add_option (_("MIDI"),
1617                     new BoolOption (
1618                             "send-mmc",
1619                             _("Send MIDI Machine Control commands"),
1620                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1621                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1622                             ));
1623
1624         add_option (_("MIDI"),
1625                     new BoolOption (
1626                             "midi-feedback",
1627                             _("Send MIDI control feedback"),
1628                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1629                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1630                             ));
1631
1632         add_option (_("MIDI"),
1633              new SpinOption<uint8_t> (
1634                      "mmc-receive-device-id",
1635                      _("Inbound MMC device ID"),
1636                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1637                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1638                      0, 128, 1, 10
1639                      ));
1640
1641         add_option (_("MIDI"),
1642              new SpinOption<uint8_t> (
1643                      "mmc-send-device-id",
1644                      _("Outbound MMC device ID"),
1645                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1646                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1647                      0, 128, 1, 10
1648                      ));
1649
1650         add_option (_("MIDI"),
1651              new SpinOption<int32_t> (
1652                      "initial-program-change",
1653                      _("Initial program change"),
1654                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1655                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1656                      -1, 65536, 1, 10
1657                      ));
1658
1659         add_option (_("MIDI"),
1660                     new BoolOption (
1661                             "diplay-first-midi-bank-as-zero",
1662                             _("Display first MIDI bank/program as 0"),
1663                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1664                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1665                             ));
1666
1667         add_option (_("MIDI"),
1668              new BoolOption (
1669                      "never-display-periodic-midi",
1670                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1671                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1672                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1673                      ));
1674
1675         add_option (_("MIDI"),
1676              new BoolOption (
1677                      "sound-midi-notes",
1678                      _("Sound MIDI notes as they are selected"),
1679                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1680                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1681                      ));
1682
1683         /* USER INTERACTION */
1684
1685         if (getenv ("ARDOUR_BUNDLED")) {
1686                 add_option (_("User interaction"), 
1687                             new BoolOption (
1688                                     "enable-translation",
1689                                     string_compose (_("Use translations of %1 messages\n"
1690                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
1691                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
1692                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
1693                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
1694         }
1695
1696         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1697
1698         add_option (_("User interaction"), new KeyboardOptions);
1699
1700         add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
1701
1702         add_option (_("User interaction"), new ControlSurfacesOptions (*this));
1703
1704         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1705                 "remote-model",
1706                 _("Control surface remote ID"),
1707                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1708                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1709                 );
1710
1711         rm->add (UserOrdered, _("assigned by user"));
1712         rm->add (MixerOrdered, _("follows order of mixer"));
1713         rm->add (EditorOrdered, _("follows order of editor"));
1714
1715         add_option (_("User interaction"), rm);
1716
1717         /* INTERFACE */
1718
1719         add_option (S_("GUI"),
1720              new BoolOption (
1721                      "widget-prelight",
1722                      _("Graphically indicate mouse pointer hovering over various widgets"),
1723                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
1724                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
1725                      ));
1726
1727         add_option (S_("GUI"),
1728              new BoolOption (
1729                      "use-tooltips",
1730                      _("Show tooltips if mouse hovers over a control"),
1731                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
1732                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
1733                      ));
1734
1735 #ifndef GTKOSX
1736         /* font scaling does nothing with GDK/Quartz */
1737         add_option (S_("GUI"), new FontScalingOptions (_rc_config));
1738 #endif
1739         add_option (S_("GUI"),
1740                     new BoolOption (
1741                             "use-own-plugin-gui",
1742                             _("Use plugins' own interfaces instead of Ardour's"),
1743                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
1744                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
1745                             ));
1746
1747         /* The names of these controls must be the same as those given in MixerStrip
1748            for the actual widgets being controlled.
1749         */
1750         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
1751         _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
1752         _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
1753         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
1754         _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
1755         
1756         add_option (
1757                 S_("GUI"),
1758                 new VisibilityOption (
1759                         _("Mixer Strip"),
1760                         &_mixer_strip_visibility,
1761                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
1762                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
1763                         )
1764                 );
1765
1766         add_option (S_("GUI"),
1767              new BoolOption (
1768                      "default-narrow_ms",
1769                      _("Use narrow strips in the mixer by default"),
1770                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
1771                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
1772                      ));
1773
1774         add_option (S_("GUI"), new OptionEditorHeading (_("Metering")));
1775
1776         ComboOption<float>* mht = new ComboOption<float> (
1777                 "meter-hold",
1778                 _("Meter hold time"),
1779                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
1780                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
1781                 );
1782
1783         mht->add (MeterHoldOff, _("off"));
1784         mht->add (MeterHoldShort, _("short"));
1785         mht->add (MeterHoldMedium, _("medium"));
1786         mht->add (MeterHoldLong, _("long"));
1787
1788         add_option (S_("GUI"), mht);
1789
1790         ComboOption<float>* mfo = new ComboOption<float> (
1791                 "meter-falloff",
1792                 _("Meter fall-off"),
1793                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
1794                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
1795                 );
1796
1797         mfo->add (METER_FALLOFF_OFF, _("off"));
1798         mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
1799         mfo->add (METER_FALLOFF_SLOW, _("slow"));
1800         mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
1801         mfo->add (METER_FALLOFF_FAST, _("fast"));
1802         mfo->add (METER_FALLOFF_FASTER, _("faster"));
1803         mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
1804
1805         add_option (S_("GUI"), mfo);
1806 }
1807
1808 void
1809 RCOptionEditor::parameter_changed (string const & p)
1810 {
1811         OptionEditor::parameter_changed (p);
1812
1813         if (p == "use-monitor-bus") {
1814                 bool const s = Config->get_use_monitor_bus ();
1815                 if (!s) {
1816                         /* we can't use this if we don't have a monitor bus */
1817                         Config->set_solo_control_is_listen_control (false);
1818                 }
1819                 _solo_control_is_listen_control->set_sensitive (s);
1820                 _listen_position->set_sensitive (s);
1821         } else if (p == "sync-source") {
1822                 _sync_source->set_sensitive (true);
1823                 if (_session) {
1824                         _sync_source->set_sensitive (!_session->config.get_external_sync());
1825                 }
1826                 switch(Config->get_sync_source()) {
1827                 case ARDOUR::MTC:
1828                 case ARDOUR::LTC:
1829                         _sync_genlock->set_sensitive (true);
1830                         _sync_framerate->set_sensitive (true);
1831                         _sync_source_2997->set_sensitive (true);
1832                         break;
1833                 default:
1834                         _sync_genlock->set_sensitive (false);
1835                         _sync_framerate->set_sensitive (false);
1836                         _sync_source_2997->set_sensitive (false);
1837                         break;
1838                 }
1839         } else if (p == "send-ltc") {
1840                 bool const s = Config->get_send_ltc ();
1841                 _ltc_send_continuously->set_sensitive (s);
1842                 _ltc_volume_slider->set_sensitive (s);
1843         }
1844 }
1845
1846 void RCOptionEditor::ltc_generator_volume_changed () {
1847         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
1848 }
1849
1850 void
1851 RCOptionEditor::populate_sync_options ()
1852 {
1853         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
1854
1855         _sync_source->clear ();
1856
1857         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
1858                 _sync_source->add (*i, sync_source_to_string (*i));
1859         }
1860 }