move theme manager into preferences window
[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 <boost/algorithm/string.hpp>    
25
26 #include <gtkmm/liststore.h>
27 #include <gtkmm/stock.h>
28 #include <gtkmm/scale.h>
29
30 #include <gtkmm2ext/utils.h>
31 #include <gtkmm2ext/slider_controller.h>
32 #include <gtkmm2ext/gtk_ui.h>
33 #include <gtkmm2ext/paths_dialog.h>
34
35 #include "pbd/fpu.h"
36 #include "pbd/cpus.h"
37
38 #include "ardour/audioengine.h"
39 #include "ardour/dB.h"
40 #include "ardour/rc_configuration.h"
41 #include "ardour/control_protocol_manager.h"
42 #include "ardour/plugin_manager.h"
43 #include "control_protocol/control_protocol.h"
44
45 #include "canvas/wave_view.h"
46
47 #include "ardour_ui.h"
48 #include "ardour_window.h"
49 #include "ardour_dialog.h"
50 #include "gui_thread.h"
51 #include "midi_tracer.h"
52 #include "rc_option_editor.h"
53 #include "utils.h"
54 #include "midi_port_dialog.h"
55 #include "sfdb_ui.h"
56 #include "keyboard.h"
57 #include "theme_manager.h"
58 #include "i18n.h"
59
60 using namespace std;
61 using namespace Gtk;
62 using namespace Gtkmm2ext;
63 using namespace PBD;
64 using namespace ARDOUR;
65 using namespace ARDOUR_UI_UTILS;
66
67 class ClickOptions : public OptionEditorBox
68 {
69 public:
70         ClickOptions (RCConfiguration* c, Gtk::Window* p)
71                 : _rc_config (c)
72         {
73                 Table* t = manage (new Table (2, 3));
74                 t->set_spacings (4);
75
76                 Label* l = manage (left_aligned_label (_("Click audio file:")));
77                 t->attach (*l, 0, 1, 0, 1, FILL);
78                 t->attach (_click_path_entry, 1, 2, 0, 1, FILL);
79                 Button* b = manage (new Button (_("Browse...")));
80                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
81                 t->attach (*b, 2, 3, 0, 1, FILL);
82
83                 l = manage (left_aligned_label (_("Click emphasis audio file:")));
84                 t->attach (*l, 0, 1, 1, 2, FILL);
85                 t->attach (_click_emphasis_path_entry, 1, 2, 1, 2, FILL);
86                 b = manage (new Button (_("Browse...")));
87                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
88                 t->attach (*b, 2, 3, 1, 2, FILL);
89                 
90                 _box->pack_start (*t, false, false);
91
92                 _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));      
93                 _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
94         }
95
96         void parameter_changed (string const & p)
97         {
98                 if (p == "click-sound") {
99                         _click_path_entry.set_text (_rc_config->get_click_sound());
100                 } else if (p == "click-emphasis-sound") {
101                         _click_emphasis_path_entry.set_text (_rc_config->get_click_emphasis_sound());
102                 }
103         }
104
105         void set_state_from_config ()
106         {
107                 parameter_changed ("click-sound");
108                 parameter_changed ("click-emphasis-sound");
109         }
110
111 private:
112
113         void click_browse_clicked ()
114         {
115                 SoundFileChooser sfdb (_("Choose Click"));
116
117                 if (sfdb.run () == RESPONSE_OK) {
118                         click_chosen (sfdb.get_filename());
119                 }
120         }
121
122         void click_chosen (string const & path)
123         {
124                 _click_path_entry.set_text (path);
125                 _rc_config->set_click_sound (path);
126         }
127
128         void click_changed ()
129         {
130                 click_chosen (_click_path_entry.get_text ());
131         }
132         
133         void click_emphasis_browse_clicked ()
134         {
135                 SoundFileChooser sfdb (_("Choose Click Emphasis"));
136
137                 sfdb.show_all ();
138                 sfdb.present ();
139
140                 if (sfdb.run () == RESPONSE_OK) {
141                         click_emphasis_chosen (sfdb.get_filename());
142                 }
143         }
144
145         void click_emphasis_chosen (string const & path)
146         {
147                 _click_emphasis_path_entry.set_text (path);
148                 _rc_config->set_click_emphasis_sound (path);
149         }
150
151         void click_emphasis_changed ()
152         {
153                 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
154         }
155
156         RCConfiguration* _rc_config;
157         Entry _click_path_entry;
158         Entry _click_emphasis_path_entry;
159 };
160
161 class UndoOptions : public OptionEditorBox
162 {
163 public:
164         UndoOptions (RCConfiguration* c) :
165                 _rc_config (c),
166                 _limit_undo_button (_("Limit undo history to")),
167                 _save_undo_button (_("Save undo history of"))
168         {
169                 Table* t = new Table (2, 3);
170                 t->set_spacings (4);
171
172                 t->attach (_limit_undo_button, 0, 1, 0, 1, FILL);
173                 _limit_undo_spin.set_range (0, 512);
174                 _limit_undo_spin.set_increments (1, 10);
175                 t->attach (_limit_undo_spin, 1, 2, 0, 1, FILL | EXPAND);
176                 Label* l = manage (left_aligned_label (_("commands")));
177                 t->attach (*l, 2, 3, 0, 1);
178
179                 t->attach (_save_undo_button, 0, 1, 1, 2, FILL);
180                 _save_undo_spin.set_range (0, 512);
181                 _save_undo_spin.set_increments (1, 10);
182                 t->attach (_save_undo_spin, 1, 2, 1, 2, FILL | EXPAND);
183                 l = manage (left_aligned_label (_("commands")));
184                 t->attach (*l, 2, 3, 1, 2);
185
186                 _box->pack_start (*t);
187
188                 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
189                 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
190                 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
191                 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
192         }
193
194         void parameter_changed (string const & p)
195         {
196                 if (p == "history-depth") {
197                         int32_t const d = _rc_config->get_history_depth();
198                         _limit_undo_button.set_active (d != 0);
199                         _limit_undo_spin.set_sensitive (d != 0);
200                         _limit_undo_spin.set_value (d);
201                 } else if (p == "save-history") {
202                         bool const x = _rc_config->get_save_history ();
203                         _save_undo_button.set_active (x);
204                         _save_undo_spin.set_sensitive (x);
205                 } else if (p == "save-history-depth") {
206                         _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
207                 }
208         }
209
210         void set_state_from_config ()
211         {
212                 parameter_changed ("save-history");
213                 parameter_changed ("history-depth");
214                 parameter_changed ("save-history-depth");
215         }
216
217         void limit_undo_toggled ()
218         {
219                 bool const x = _limit_undo_button.get_active ();
220                 _limit_undo_spin.set_sensitive (x);
221                 int32_t const n = x ? 16 : 0;
222                 _limit_undo_spin.set_value (n);
223                 _rc_config->set_history_depth (n);
224         }
225
226         void limit_undo_changed ()
227         {
228                 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
229         }
230
231         void save_undo_toggled ()
232         {
233                 bool const x = _save_undo_button.get_active ();
234                 _rc_config->set_save_history (x);
235         }
236
237         void save_undo_changed ()
238         {
239                 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
240         }
241
242 private:
243         RCConfiguration* _rc_config;
244         CheckButton _limit_undo_button;
245         SpinButton _limit_undo_spin;
246         CheckButton _save_undo_button;
247         SpinButton _save_undo_spin;
248 };
249
250
251
252 static const struct {
253     const char *name;
254     guint modifier;
255 } modifiers[] = {
256
257         { "Unmodified", 0 },
258
259 #ifdef GTKOSX
260
261         /* Command = Meta
262            Option/Alt = Mod1
263         */
264         { "Key|Shift", GDK_SHIFT_MASK },
265         { "Command", GDK_META_MASK },
266         { "Control", GDK_CONTROL_MASK },
267         { "Option", GDK_MOD1_MASK },
268         { "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
269         { "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
270         { "Shift-Option", GDK_SHIFT_MASK|GDK_MOD1_MASK },
271         { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
272
273 #else
274         { "Key|Shift", GDK_SHIFT_MASK },
275         { "Control", GDK_CONTROL_MASK },
276         { "Alt (Mod1)", GDK_MOD1_MASK },
277         { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
278         { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
279         { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
280         { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
281         { "Mod2", GDK_MOD2_MASK },
282         { "Mod3", GDK_MOD3_MASK },
283         { "Mod4", GDK_MOD4_MASK },
284         { "Mod5", GDK_MOD5_MASK },
285 #endif
286         { 0, 0 }
287 };
288
289
290 class KeyboardOptions : public OptionEditorBox
291 {
292 public:
293         KeyboardOptions () :
294                   _delete_button_adjustment (3, 1, 12),
295                   _delete_button_spin (_delete_button_adjustment),
296                   _edit_button_adjustment (3, 1, 5),
297                   _edit_button_spin (_edit_button_adjustment),
298                   _insert_note_button_adjustment (3, 1, 5),
299                   _insert_note_button_spin (_insert_note_button_adjustment)
300         {
301                 /* internationalize and prepare for use with combos */
302
303                 vector<string> dumb;
304                 for (int i = 0; modifiers[i].name; ++i) {
305                         dumb.push_back (S_(modifiers[i].name));
306                 }
307
308                 set_popdown_strings (_edit_modifier_combo, dumb);
309                 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
310
311                 for (int x = 0; modifiers[x].name; ++x) {
312                         if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
313                                 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
314                                 break;
315                         }
316                 }
317
318                 Table* t = manage (new Table (4, 4));
319                 t->set_spacings (4);
320
321                 Label* l = manage (left_aligned_label (_("Edit using:")));
322                 l->set_name ("OptionsLabel");
323
324                 t->attach (*l, 0, 1, 0, 1, FILL | EXPAND, FILL);
325                 t->attach (_edit_modifier_combo, 1, 2, 0, 1, FILL | EXPAND, FILL);
326
327                 l = manage (new Label (_("+ button")));
328                 l->set_name ("OptionsLabel");
329
330                 t->attach (*l, 3, 4, 0, 1, FILL | EXPAND, FILL);
331                 t->attach (_edit_button_spin, 4, 5, 0, 1, FILL | EXPAND, FILL);
332
333                 _edit_button_spin.set_name ("OptionsEntry");
334                 _edit_button_adjustment.set_value (Keyboard::edit_button());
335                 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
336
337                 set_popdown_strings (_delete_modifier_combo, dumb);
338                 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
339
340                 for (int x = 0; modifiers[x].name; ++x) {
341                         if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
342                                 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
343                                 break;
344                         }
345                 }
346
347                 l = manage (left_aligned_label (_("Delete using:")));
348                 l->set_name ("OptionsLabel");
349
350                 t->attach (*l, 0, 1, 1, 2, FILL | EXPAND, FILL);
351                 t->attach (_delete_modifier_combo, 1, 2, 1, 2, FILL | EXPAND, FILL);
352
353                 l = manage (new Label (_("+ button")));
354                 l->set_name ("OptionsLabel");
355
356                 t->attach (*l, 3, 4, 1, 2, FILL | EXPAND, FILL);
357                 t->attach (_delete_button_spin, 4, 5, 1, 2, FILL | EXPAND, FILL);
358
359                 _delete_button_spin.set_name ("OptionsEntry");
360                 _delete_button_adjustment.set_value (Keyboard::delete_button());
361                 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
362
363
364                 set_popdown_strings (_insert_note_modifier_combo, dumb);
365                 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
366
367                 for (int x = 0; modifiers[x].name; ++x) {
368                         if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
369                                 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
370                                 break;
371                         }
372                 }
373
374                 l = manage (left_aligned_label (_("Insert note using:")));
375                 l->set_name ("OptionsLabel");
376
377                 t->attach (*l, 0, 1, 2, 3, FILL | EXPAND, FILL);
378                 t->attach (_insert_note_modifier_combo, 1, 2, 2, 3, FILL | EXPAND, FILL);
379
380                 l = manage (new Label (_("+ button")));
381                 l->set_name ("OptionsLabel");
382
383                 t->attach (*l, 3, 4, 2, 3, FILL | EXPAND, FILL);
384                 t->attach (_insert_note_button_spin, 4, 5, 2, 3, FILL | EXPAND, FILL);
385
386                 _insert_note_button_spin.set_name ("OptionsEntry");
387                 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
388                 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
389
390
391                 set_popdown_strings (_snap_modifier_combo, dumb);
392                 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
393
394                 for (int x = 0; modifiers[x].name; ++x) {
395                         if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
396                                 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
397                                 break;
398                         }
399                 }
400
401                 l = manage (left_aligned_label (_("Ignore snap using:")));
402                 l->set_name ("OptionsLabel");
403
404                 t->attach (*l, 0, 1, 3, 4, FILL | EXPAND, FILL);
405                 t->attach (_snap_modifier_combo, 1, 2, 3, 4, FILL | EXPAND, FILL);
406
407                 vector<string> strs;
408
409                 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
410                         strs.push_back (bf->first);
411                 }
412
413                 set_popdown_strings (_keyboard_layout_selector, strs);
414                 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
415                 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
416
417                 l = manage (left_aligned_label (_("Keyboard layout:")));
418                 l->set_name ("OptionsLabel");
419
420                 t->attach (*l, 0, 1, 4, 5, FILL | EXPAND, FILL);
421                 t->attach (_keyboard_layout_selector, 1, 2, 4, 5, FILL | EXPAND, FILL);
422
423                 _box->pack_start (*t, false, false);
424         }
425
426         void parameter_changed (string const &)
427         {
428                 /* XXX: these aren't really config options... */
429         }
430
431         void set_state_from_config ()
432         {
433                 /* XXX: these aren't really config options... */
434         }
435
436 private:
437
438         void bindings_changed ()
439         {
440                 string const txt = _keyboard_layout_selector.get_active_text();
441
442                 /* XXX: config...?  for all this keyboard stuff */
443
444                 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
445                         if (txt == i->first) {
446                                 if (Keyboard::load_keybindings (i->second)) {
447                                         Keyboard::save_keybindings ();
448                                 }
449                         }
450                 }
451         }
452
453         void edit_modifier_chosen ()
454         {
455                 string const txt = _edit_modifier_combo.get_active_text();
456
457                 for (int i = 0; modifiers[i].name; ++i) {
458                         if (txt == _(modifiers[i].name)) {
459                                 Keyboard::set_edit_modifier (modifiers[i].modifier);
460                                 break;
461                         }
462                 }
463         }
464
465         void delete_modifier_chosen ()
466         {
467                 string const txt = _delete_modifier_combo.get_active_text();
468
469                 for (int i = 0; modifiers[i].name; ++i) {
470                         if (txt == _(modifiers[i].name)) {
471                                 Keyboard::set_delete_modifier (modifiers[i].modifier);
472                                 break;
473                         }
474                 }
475         }
476
477         void insert_note_modifier_chosen ()
478         {
479                 string const txt = _insert_note_modifier_combo.get_active_text();
480
481                 for (int i = 0; modifiers[i].name; ++i) {
482                         if (txt == _(modifiers[i].name)) {
483                                 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
484                                 break;
485                         }
486                 }
487         }
488
489         void snap_modifier_chosen ()
490         {
491                 string const txt = _snap_modifier_combo.get_active_text();
492
493                 for (int i = 0; modifiers[i].name; ++i) {
494                         if (txt == _(modifiers[i].name)) {
495                                 Keyboard::set_snap_modifier (modifiers[i].modifier);
496                                 break;
497                         }
498                 }
499         }
500
501         void delete_button_changed ()
502         {
503                 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
504         }
505
506         void edit_button_changed ()
507         {
508                 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
509         }
510
511         void insert_note_button_changed ()
512         {
513                 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
514         }
515
516         ComboBoxText _keyboard_layout_selector;
517         ComboBoxText _edit_modifier_combo;
518         ComboBoxText _delete_modifier_combo;
519         ComboBoxText _insert_note_modifier_combo;
520         ComboBoxText _snap_modifier_combo;
521         Adjustment _delete_button_adjustment;
522         SpinButton _delete_button_spin;
523         Adjustment _edit_button_adjustment;
524         SpinButton _edit_button_spin;
525         Adjustment _insert_note_button_adjustment;
526         SpinButton _insert_note_button_spin;
527
528 };
529
530 class FontScalingOptions : public OptionEditorBox
531 {
532 public:
533         FontScalingOptions (RCConfiguration* c) :
534                 _rc_config (c),
535                 _dpi_adjustment (50, 50, 250, 1, 10),
536                 _dpi_slider (_dpi_adjustment)
537         {
538                 _dpi_adjustment.set_value (floor ((double)(_rc_config->get_font_scale () / 1024)));
539
540                 Label* l = manage (new Label (_("Font scaling:")));
541                 l->set_name ("OptionsLabel");
542
543                 _dpi_slider.set_update_policy (UPDATE_DISCONTINUOUS);
544                 HBox* h = manage (new HBox);
545                 h->set_spacing (4);
546                 h->pack_start (*l, false, false);
547                 h->pack_start (_dpi_slider, true, true);
548
549                 _box->pack_start (*h, false, false);
550
551                 _dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
552         }
553
554         void parameter_changed (string const & p)
555         {
556                 if (p == "font-scale") {
557                         _dpi_adjustment.set_value (floor ((double)(_rc_config->get_font_scale() / 1024)));
558                 }
559         }
560
561         void set_state_from_config ()
562         {
563                 parameter_changed ("font-scale");
564         }
565
566 private:
567
568         void dpi_changed ()
569         {
570                 _rc_config->set_font_scale ((long) floor (_dpi_adjustment.get_value() * 1024));
571                 /* XXX: should be triggered from the parameter changed signal */
572                 reset_dpi ();
573         }
574
575         RCConfiguration* _rc_config;
576         Adjustment _dpi_adjustment;
577         HScale _dpi_slider;
578 };
579
580 class ClipLevelOptions : public OptionEditorBox
581 {
582 public:
583         ClipLevelOptions (RCConfiguration* c) 
584                 : _rc_config (c)
585                 , _clip_level_adjustment (-.5, -50.0, 0.0, 0.1, 1.0) /* units of dB */
586                 , _clip_level_slider (_clip_level_adjustment)
587         {
588                 _clip_level_adjustment.set_value (_rc_config->get_waveform_clip_level ());
589
590                 Label* l = manage (new Label (_("Waveform Clip Level (dBFS):")));
591                 l->set_name ("OptionsLabel");
592
593                 _clip_level_slider.set_update_policy (UPDATE_DISCONTINUOUS);
594                 HBox* h = manage (new HBox);
595                 h->set_spacing (4);
596                 h->pack_start (*l, false, false);
597                 h->pack_start (_clip_level_slider, true, true);
598
599                 _box->pack_start (*h, false, false);
600
601                 _clip_level_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &ClipLevelOptions::clip_level_changed));
602         }
603
604         void parameter_changed (string const & p)
605         {
606                 if (p == "waveform-clip-level") {
607                         _clip_level_adjustment.set_value (_rc_config->get_waveform_clip_level());
608                 }
609         }
610
611         void set_state_from_config ()
612         {
613                 parameter_changed ("waveform-clip-level");
614         }
615
616 private:
617
618         void clip_level_changed ()
619         {
620                 _rc_config->set_waveform_clip_level (_clip_level_adjustment.get_value());
621                 /* XXX: should be triggered from the parameter changed signal */
622                 ArdourCanvas::WaveView::set_clip_level (_clip_level_adjustment.get_value());
623         }
624
625         RCConfiguration* _rc_config;
626         Adjustment _clip_level_adjustment;
627         HScale _clip_level_slider;
628 };
629
630 class BufferingOptions : public OptionEditorBox
631 {
632 public:
633         BufferingOptions (RCConfiguration* c)
634                 : _rc_config (c)
635                 , _playback_adjustment (5, 1, 60, 1, 4)
636                 , _capture_adjustment (5, 1, 60, 1, 4)
637                 , _playback_slider (_playback_adjustment)
638                 , _capture_slider (_capture_adjustment)
639         {
640                 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
641
642                 Label* l = manage (new Label (_("Playback (seconds of buffering):")));
643                 l->set_name ("OptionsLabel");
644
645                 _playback_slider.set_update_policy (UPDATE_DISCONTINUOUS);
646                 HBox* h = manage (new HBox);
647                 h->set_spacing (4);
648                 h->pack_start (*l, false, false);
649                 h->pack_start (_playback_slider, true, true);
650
651                 _box->pack_start (*h, false, false);
652
653                 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
654
655                 l = manage (new Label (_("Recording (seconds of buffering):")));
656                 l->set_name ("OptionsLabel");
657
658                 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
659                 h = manage (new HBox);
660                 h->set_spacing (4);
661                 h->pack_start (*l, false, false);
662                 h->pack_start (_capture_slider, true, true);
663
664                 _box->pack_start (*h, false, false);
665
666                 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
667                 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
668         }
669
670         void parameter_changed (string const & p)
671         {
672                 if (p == "playback-buffer-seconds") {
673                         _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
674                 } else if (p == "capture-buffer-seconds") {
675                         _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
676                 }
677         }
678
679         void set_state_from_config ()
680         {
681                 parameter_changed ("playback-buffer-seconds");
682                 parameter_changed ("capture-buffer-seconds");
683         }
684
685 private:
686
687         void playback_changed ()
688         {
689                 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
690         }
691
692         void capture_changed ()
693         {
694                 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
695         }
696
697         RCConfiguration* _rc_config;
698         Adjustment _playback_adjustment;
699         Adjustment _capture_adjustment;
700         HScale _playback_slider;
701         HScale _capture_slider;
702 };
703
704 class ControlSurfacesOptions : public OptionEditorBox
705 {
706 public:
707         ControlSurfacesOptions (Gtk::Window& parent)
708                 : _parent (parent)
709                 , _ignore_view_change (0)
710         {
711                 _store = ListStore::create (_model);
712                 _view.set_model (_store);
713                 _view.append_column (_("Control Surface Protocol"), _model.name);
714                 _view.get_column(0)->set_resizable (true);
715                 _view.get_column(0)->set_expand (true);
716                 _view.append_column_editable (_("Enabled"), _model.enabled);
717                 _view.append_column_editable (_("Feedback"), _model.feedback);
718
719                 _box->pack_start (_view, false, false);
720
721                 Label* label = manage (new Label);
722                 label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
723
724                 _box->pack_start (*label, false, false);
725                 label->show ();
726
727                 ControlProtocolManager& m = ControlProtocolManager::instance ();
728                 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
729                                                 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
730
731                 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
732                 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
733         }
734
735         void parameter_changed (std::string const &)
736         {
737
738         }
739
740         void set_state_from_config ()
741         {
742                 _store->clear ();
743
744                 ControlProtocolManager& m = ControlProtocolManager::instance ();
745                 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
746
747                         if (!(*i)->mandatory) {
748                                 TreeModel::Row r = *_store->append ();
749                                 r[_model.name] = (*i)->name;
750                                 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
751                                 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
752                                 r[_model.protocol_info] = *i;
753                         }
754                 }
755         }
756
757 private:
758
759         void protocol_status_changed (ControlProtocolInfo* cpi) {
760                 /* find the row */
761                 TreeModel::Children rows = _store->children();
762                 
763                 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
764                         string n = ((*x)[_model.name]);
765
766                         if ((*x)[_model.protocol_info] == cpi) {
767                                 _ignore_view_change++;
768                                 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
769                                 _ignore_view_change--;
770                                 break;
771                         }
772                 }
773         }
774
775         void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
776         {
777                 TreeModel::Row r = *i;
778
779                 if (_ignore_view_change) {
780                         return;
781                 }
782
783                 ControlProtocolInfo* cpi = r[_model.protocol_info];
784                 if (!cpi) {
785                         return;
786                 }
787
788                 bool const was_enabled = (cpi->protocol != 0);
789                 bool const is_enabled = r[_model.enabled];
790
791
792                 if (was_enabled != is_enabled) {
793
794                         if (!was_enabled) {
795                                 ControlProtocolManager::instance().activate (*cpi);
796                         } else {
797                                 ControlProtocolManager::instance().deactivate (*cpi);
798                         }
799                 }
800
801                 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
802                 bool const is_feedback = r[_model.feedback];
803
804                 if (was_feedback != is_feedback && cpi->protocol) {
805                         cpi->protocol->set_feedback (is_feedback);
806                 }
807         }
808
809         void edit_clicked (GdkEventButton* ev)
810         {
811                 if (ev->type != GDK_2BUTTON_PRESS) {
812                         return;
813                 }
814
815                 std::string name;
816                 ControlProtocolInfo* cpi;
817                 TreeModel::Row row;
818
819                 row = *(_view.get_selection()->get_selected());
820                 if (!row[_model.enabled]) {
821                         return;
822                 }
823                 cpi = row[_model.protocol_info];
824                 if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
825                         return;
826                 }
827                 Box* box = (Box*) cpi->protocol->get_gui ();
828                 if (!box) {
829                         return;
830                 }
831                 if (box->get_parent()) {
832                         static_cast<ArdourWindow*>(box->get_parent())->present();
833                         return;
834                 }
835                 string title = row[_model.name];
836                 /* once created, the window is managed by the surface itself (as ->get_parent())
837                  * Surface's tear_down_gui() is called on session close, when de-activating
838                  * or re-initializing a surface.
839                  * tear_down_gui() hides an deletes the Window if it exists.
840                  */
841                 ArdourWindow* win = new ArdourWindow (_parent, title);
842                 win->set_title ("Control Protocol Options");
843                 win->add (*box);
844                 box->show ();
845                 win->present ();
846         }
847
848         class ControlSurfacesModelColumns : public TreeModelColumnRecord
849         {
850         public:
851
852                 ControlSurfacesModelColumns ()
853                 {
854                         add (name);
855                         add (enabled);
856                         add (feedback);
857                         add (protocol_info);
858                 }
859
860                 TreeModelColumn<string> name;
861                 TreeModelColumn<bool> enabled;
862                 TreeModelColumn<bool> feedback;
863                 TreeModelColumn<ControlProtocolInfo*> protocol_info;
864         };
865
866         Glib::RefPtr<ListStore> _store;
867         ControlSurfacesModelColumns _model;
868         TreeView _view;
869         Gtk::Window& _parent;
870         PBD::ScopedConnection protocol_status_connection;
871         uint32_t _ignore_view_change;
872 };
873
874 class VideoTimelineOptions : public OptionEditorBox
875 {
876 public:
877         VideoTimelineOptions (RCConfiguration* c)
878                 : _rc_config (c)
879                 , _show_video_export_info_button (_("Show Video Export Info before export"))
880                 , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
881                 , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
882         {
883                 Table* t = manage (new Table (2, 6));
884                 t->set_spacings (4);
885
886                 t->attach (_video_advanced_setup_button, 0, 2, 0, 1);
887                 _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
888                 Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
889                                             _("<b>When enabled</b> you can speficify a custom video-server URL and docroot. - Do not enable this option unless you know what you are doing."));
890
891                 Label* l = manage (new Label (_("Video Server URL:")));
892                 l->set_alignment (0, 0.5);
893                 t->attach (*l, 0, 1, 1, 2, FILL);
894                 t->attach (_video_server_url_entry, 1, 2, 1, 2, FILL);
895                 Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
896                                             _("Base URL of the video-server including http prefix. This is usually 'http://hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when the video-server is running locally"));
897
898                 l = manage (new Label (_("Video Folder:")));
899                 l->set_alignment (0, 0.5);
900                 t->attach (*l, 0, 1, 2, 3, FILL);
901                 t->attach (_video_server_docroot_entry, 1, 2, 2, 3);
902                 Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
903                                             _("Local path to the video-server document-root. Only files below this directory will be accessible by the video-server. If the server run on a remote host, it should point to a network mounted folder of the server's docroot or be left empty if it is unvailable. It is used for the local video-monitor and file-browsing when opening/adding a video file."));
904
905                 /* small vspace  y=3..4 */
906
907                 t->attach (_show_video_export_info_button, 0, 2, 4, 5);
908                 _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
909                 Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
910                                             _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
911
912                 t->attach (_show_video_server_dialog_button, 0, 2, 5, 6);
913                 _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
914                 Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
915                                             _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
916
917                 _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
918                 _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
919                 _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
920                 _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
921
922                 _box->pack_start (*t,true,true);
923         }
924
925         void server_url_changed ()
926         {
927                 _rc_config->set_video_server_url (_video_server_url_entry.get_text());
928         }
929
930         void server_docroot_changed ()
931         {
932                 _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
933         }
934
935         void show_video_export_info_toggled ()
936         {
937                 bool const x = _show_video_export_info_button.get_active ();
938                 _rc_config->set_show_video_export_info (x);
939         }
940
941         void show_video_server_dialog_toggled ()
942         {
943                 bool const x = _show_video_server_dialog_button.get_active ();
944                 _rc_config->set_show_video_server_dialog (x);
945         }
946
947         void video_advanced_setup_toggled ()
948         {
949                 bool const x = _video_advanced_setup_button.get_active ();
950                 _rc_config->set_video_advanced_setup(x);
951         }
952
953         void parameter_changed (string const & p)
954         {
955                 if (p == "video-server-url") {
956                         _video_server_url_entry.set_text (_rc_config->get_video_server_url());
957                 } else if (p == "video-server-docroot") {
958                         _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
959                 } else if (p == "show-video-export-info") {
960                         bool const x = _rc_config->get_show_video_export_info();
961                         _show_video_export_info_button.set_active (x);
962                 } else if (p == "show-video-server-dialog") {
963                         bool const x = _rc_config->get_show_video_server_dialog();
964                         _show_video_server_dialog_button.set_active (x);
965                 } else if (p == "video-advanced-setup") {
966                         bool const x = _rc_config->get_video_advanced_setup();
967                         _video_advanced_setup_button.set_active(x);
968                         _video_server_docroot_entry.set_sensitive(x);
969                         _video_server_url_entry.set_sensitive(x);
970                 }
971         }
972
973         void set_state_from_config ()
974         {
975                 parameter_changed ("video-server-url");
976                 parameter_changed ("video-server-docroot");
977                 parameter_changed ("video-monitor-setup-dialog");
978                 parameter_changed ("show-video-export-info");
979                 parameter_changed ("show-video-server-dialog");
980                 parameter_changed ("video-advanced-setup");
981         }
982
983 private:
984         RCConfiguration* _rc_config;
985         Entry _video_server_url_entry;
986         Entry _video_server_docroot_entry;
987         CheckButton _show_video_export_info_button;
988         CheckButton _show_video_server_dialog_button;
989         CheckButton _video_advanced_setup_button;
990 };
991
992 class PluginOptions : public OptionEditorBox
993 {
994 public:
995         PluginOptions (RCConfiguration* c)
996                 : _rc_config (c)
997                 , _display_plugin_scan_progress (_("Always Display Plugin Scan Progress"))
998                 , _discover_vst_on_start (_("Scan for [new] VST Plugins on Application Start"))
999                 , _discover_au_on_start (_("Scan for AudioUnit Plugins on Application Start"))
1000                 , _timeout_adjustment (0, 0, 3000, 50, 50)
1001                 , _timeout_slider (_timeout_adjustment)
1002         {
1003                 Label *l;
1004                 std::stringstream ss;
1005                 Table* t = manage (new Table (2, 6));
1006                 t->set_spacings (4);
1007                 Button* b;
1008                 int n = 0;
1009
1010                 ss << "<b>" << _("General") << "</b>";
1011                 l = manage (left_aligned_label (ss.str()));
1012                 l->set_use_markup (true);
1013                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1014                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1015
1016                 b = manage (new Button (_("Scan for Plugins")));
1017                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::refresh_clicked));
1018                 t->attach (*b, 0, 2, n, n+1, FILL); ++n;
1019
1020                 t->attach (_display_plugin_scan_progress, 0, 2, n, n+1); ++n;
1021                 _display_plugin_scan_progress.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::display_plugin_scan_progress_toggled));
1022                 Gtkmm2ext::UI::instance()->set_tip (_display_plugin_scan_progress,
1023                                             _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
1024
1025 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
1026                 _timeout_slider.set_digits (0);
1027                 _timeout_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &PluginOptions::timeout_changed));
1028
1029                 Gtkmm2ext::UI::instance()->set_tip(_timeout_slider,
1030                          _("Specify the default timeout for plugin instantiation in 1/10 seconds. Plugins that require more time to load will be blacklisted. A value of 0 disables the timeout."));
1031
1032                 l = manage (left_aligned_label (_("Scan Time Out [deciseconds]")));;
1033                 HBox* h = manage (new HBox);
1034                 h->set_spacing (4);
1035                 h->pack_start (*l, false, false);
1036                 h->pack_start (_timeout_slider, true, true);
1037                 t->attach (*h, 0, 2, n, n+1); ++n;
1038
1039                 ss.str("");
1040                 ss << "<b>" << _("VST") << "</b>";
1041                 l = manage (left_aligned_label (ss.str()));
1042                 l->set_use_markup (true);
1043                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1044                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1045
1046                 b = manage (new Button (_("Clear VST Cache")));
1047                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_cache_clicked));
1048                 t->attach (*b, 0, 1, n, n+1, FILL);
1049
1050                 b = manage (new Button (_("Clear VST Blacklist")));
1051                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_blacklist_clicked));
1052                 t->attach (*b, 1, 2, n, n+1, FILL);
1053                 ++n;
1054
1055                 t->attach (_discover_vst_on_start, 0, 2, n, n+1); ++n;
1056                 _discover_vst_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_vst_on_start_toggled));
1057                 Gtkmm2ext::UI::instance()->set_tip (_discover_vst_on_start,
1058                                             _("<b>When enabled</b> new VST plugins are searched, tested and added to the cache index on application start. When disabled new plugins will only be available after triggering a 'Scan' manually"));
1059
1060 #ifdef LXVST_SUPPORT
1061                 t->attach (*manage (left_aligned_label (_("Linux VST Path:"))), 0, 1, n, n+1);
1062                 b = manage (new Button (_("Edit")));
1063                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_lxvst_path_clicked));
1064                 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1065 #endif
1066
1067 #ifdef WINDOWS_VST_SUPPORT
1068                 t->attach (*manage (left_aligned_label (_("Windows VST Path:"))), 0, 1, n, n+1);
1069                 b = manage (new Button (_("Edit")));
1070                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_vst_path_clicked));
1071                 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1072 #endif
1073 #endif // any VST
1074
1075 #ifdef AUDIOUNIT_SUPPORT
1076                 t->attach (_discover_au_on_start, 0, 2, n, n+1); ++n;
1077                 _discover_au_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_au_on_start_toggled));
1078                 Gtkmm2ext::UI::instance()->set_tip (_discover_au_on_start,
1079                                             _("<b>When enabled</b> Audio Unit Plugins are discovered on application start. When disabled AU plugins will only be available after triggering a 'Scan' manually. The first successful scan will enable AU auto-scan, Any crash during plugin discovery will disable it."));
1080 #endif
1081
1082                 _box->pack_start (*t,true,true);
1083         }
1084
1085         void parameter_changed (string const & p) {
1086                 if (p == "show-plugin-scan-window") {
1087                         bool const x = _rc_config->get_show_plugin_scan_window();
1088                         _display_plugin_scan_progress.set_active (x);
1089                 }
1090                 else if (p == "discover-vst-on-start") {
1091                         bool const x = _rc_config->get_discover_vst_on_start();
1092                         _discover_vst_on_start.set_active (x);
1093                 }
1094                 else if (p == "vst-scan-timeout") {
1095                         int const x = _rc_config->get_vst_scan_timeout();
1096                         _timeout_adjustment.set_value (x);
1097                 }
1098                 else if (p == "discover-audio-units") {
1099                         bool const x = _rc_config->get_discover_audio_units();
1100                         _discover_au_on_start.set_active (x);
1101                 }
1102         }
1103
1104         void set_state_from_config () {
1105                 parameter_changed ("show-plugin-scan-window");
1106                 parameter_changed ("discover-vst-on-start");
1107                 parameter_changed ("vst-scan-timeout");
1108                 parameter_changed ("discover-audio-units");
1109         }
1110
1111 private:
1112         RCConfiguration* _rc_config;
1113         CheckButton _display_plugin_scan_progress;
1114         CheckButton _discover_vst_on_start;
1115         CheckButton _discover_au_on_start;
1116         Adjustment _timeout_adjustment;
1117         HScale _timeout_slider;
1118
1119         void display_plugin_scan_progress_toggled () {
1120                 bool const x = _display_plugin_scan_progress.get_active();
1121                 _rc_config->set_show_plugin_scan_window(x);
1122         }
1123
1124         void discover_vst_on_start_toggled () {
1125                 bool const x = _discover_vst_on_start.get_active();
1126                 _rc_config->set_discover_vst_on_start(x);
1127         }
1128
1129         void discover_au_on_start_toggled () {
1130                 bool const x = _discover_au_on_start.get_active();
1131                 _rc_config->set_discover_audio_units(x);
1132         }
1133
1134         void timeout_changed () {
1135                 int x = floor(_timeout_adjustment.get_value());
1136                 _rc_config->set_vst_scan_timeout(x);
1137         }
1138
1139         void clear_vst_cache_clicked () {
1140                 PluginManager::instance().clear_vst_cache();
1141         }
1142
1143         void clear_vst_blacklist_clicked () {
1144                 PluginManager::instance().clear_vst_blacklist();
1145         }
1146
1147         void edit_vst_path_clicked () {
1148                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1149                                 _("Set Windows VST Search Path"),
1150                                 _rc_config->get_plugin_path_vst(),
1151                                 PluginManager::instance().get_default_windows_vst_path()
1152                                 );
1153                 ResponseType r = (ResponseType) pd->run ();
1154                 pd->hide();
1155                 if (r == RESPONSE_ACCEPT) {
1156                         _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
1157                 }
1158                 delete pd;
1159         }
1160
1161         // todo consolidate with edit_vst_path_clicked..
1162         void edit_lxvst_path_clicked () {
1163                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1164                                 _("Set Linux VST Search Path"),
1165                                 _rc_config->get_plugin_path_lxvst(),
1166                                 PluginManager::instance().get_default_lxvst_path()
1167                                 );
1168                 ResponseType r = (ResponseType) pd->run ();
1169                 pd->hide();
1170                 if (r == RESPONSE_ACCEPT) {
1171                         _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
1172                 }
1173                 delete pd;
1174         }
1175
1176         void refresh_clicked () {
1177                 PluginManager::instance().refresh();
1178         }
1179 };
1180
1181
1182 /** A class which allows control of visibility of some editor components usign
1183  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
1184  *  which has the correct members, but with null widget pointers.  This
1185  *  class allows the user to set visibility of the members, the details
1186  *  of which are stored in a configuration variable which can be watched
1187  *  by parts of the editor that actually contain the widgets whose visibility
1188  *  is being controlled.
1189  */
1190
1191 class VisibilityOption : public Option
1192 {
1193 public:
1194         /** @param name User-visible name for this group.
1195          *  @param g `Dummy' VisibilityGroup (as described above).
1196          *  @param get Method to get the value of the appropriate configuration variable.
1197          *  @param set Method to set the value of the appropriate configuration variable.
1198          */
1199         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1200                 : Option (g->get_state_name(), name)
1201                 , _heading (name)
1202                 , _visibility_group (g)
1203                 , _get (get)
1204                 , _set (set)
1205         {
1206                 /* Watch for changes made by the user to our members */
1207                 _visibility_group->VisibilityChanged.connect_same_thread (
1208                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1209                         );
1210         }
1211
1212         void set_state_from_config ()
1213         {
1214                 /* Set our state from the current configuration */
1215                 _visibility_group->set_state (_get ());
1216         }
1217
1218         void add_to_page (OptionEditorPage* p)
1219         {
1220                 _heading.add_to_page (p);
1221                 add_widget_to_page (p, _visibility_group->list_view ());
1222         }
1223
1224         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1225
1226 private:
1227         void changed ()
1228         {
1229                 /* The user has changed something, so reflect this change
1230                    in the RCConfiguration.
1231                 */
1232                 _set (_visibility_group->get_state_value ());
1233         }
1234         
1235         OptionEditorHeading _heading;
1236         VisibilityGroup* _visibility_group;
1237         sigc::slot<std::string> _get;
1238         sigc::slot<bool, std::string> _set;
1239         PBD::ScopedConnection _visibility_group_connection;
1240 };
1241
1242
1243
1244 RCOptionEditor::RCOptionEditor ()
1245         : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
1246         , _rc_config (Config)
1247         , _mixer_strip_visibility ("mixer-element-visibility")
1248 {
1249         /* MISC */
1250
1251         uint32_t hwcpus = hardware_concurrency ();
1252         BoolOption* bo;
1253         BoolComboOption* bco;
1254
1255         if (hwcpus > 1) {
1256                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
1257
1258                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
1259                         "processor-usage",
1260                         _("Signal processing uses"),
1261                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
1262                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
1263                         );
1264
1265                 procs->add (-1, _("all but one processor"));
1266                 procs->add (0, _("all available processors"));
1267
1268                 for (uint32_t i = 1; i <= hwcpus; ++i) {
1269                         procs->add (i, string_compose (_("%1 processors"), i));
1270                 }
1271
1272                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
1273
1274                 add_option (_("Misc"), procs);
1275         }
1276
1277         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
1278
1279         add_option (_("Misc"), new UndoOptions (_rc_config));
1280
1281         add_option (_("Misc"),
1282              new BoolOption (
1283                      "verify-remove-last-capture",
1284                      _("Verify removal of last capture"),
1285                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
1286                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
1287                      ));
1288
1289         add_option (_("Misc"),
1290              new BoolOption (
1291                      "periodic-safety-backups",
1292                      _("Make periodic backups of the session file"),
1293                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1294                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1295                      ));
1296
1297         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
1298
1299         add_option (_("Misc"),
1300              new BoolOption (
1301                      "only-copy-imported-files",
1302                      _("Always copy imported files"),
1303                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_only_copy_imported_files),
1304                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_only_copy_imported_files)
1305                      ));
1306
1307         add_option (_("Misc"), new DirectoryOption (
1308                             X_("default-session-parent-dir"),
1309                             _("Default folder for new sessions:"),
1310                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
1311                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
1312                             ));
1313
1314         add_option (_("Misc"),
1315              new SpinOption<uint32_t> (
1316                      "max-recent-sessions",
1317                      _("Maximum number of recent sessions"),
1318                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
1319                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
1320                      0, 1000, 1, 20
1321                      ));
1322
1323         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
1324
1325         add_option (_("Misc"), new ClickOptions (_rc_config, this));
1326
1327         add_option (_("Misc"),
1328              new FaderOption (
1329                      "click-gain",
1330                      _("Click gain level"),
1331                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
1332                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
1333                      ));
1334
1335         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
1336
1337         add_option (_("Misc"),
1338              new SpinOption<double> (
1339                      "automation-thinning-factor",
1340                      _("Thinning factor (larger value => less data)"),
1341                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
1342                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
1343                      0, 1000, 1, 20
1344                      ));
1345
1346         add_option (_("Misc"),
1347              new SpinOption<double> (
1348                      "automation-interval-msecs",
1349                      _("Automation sampling interval (milliseconds)"),
1350                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
1351                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
1352                      1, 1000, 1, 20
1353                      ));
1354
1355         /* TRANSPORT */
1356
1357         BoolOption* tsf;
1358
1359         tsf = new BoolOption (
1360                      "latched-record-enable",
1361                      _("Keep record-enable engaged on stop"),
1362                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
1363                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
1364                      );
1365         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1366         add_option (_("Transport"), tsf);
1367
1368         tsf = new BoolOption (
1369                      "stop-recording-on-xrun",
1370                      _("Stop recording when an xrun occurs"),
1371                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1372                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1373                      );
1374         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1375                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
1376                                                             PROGRAM_NAME));
1377         add_option (_("Transport"), tsf);
1378
1379         tsf = new BoolOption (
1380                      "loop-is-mode",
1381                      _("Play loop is a transport mode"),
1382                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
1383                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
1384                      );
1385         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1386                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
1387                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
1388         add_option (_("Transport"), tsf);
1389         
1390         tsf = new BoolOption (
1391                      "create-xrun-marker",
1392                      _("Create markers where xruns occur"),
1393                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1394                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1395                      );
1396         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1397         add_option (_("Transport"), tsf);
1398
1399         tsf = new BoolOption (
1400                      "stop-at-session-end",
1401                      _("Stop at the end of the session"),
1402                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1403                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1404                      );
1405         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1406                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1407                                                               "when it reaches the current session end marker\n\n"
1408                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1409                                                             PROGRAM_NAME));
1410         add_option (_("Transport"), tsf);
1411
1412         tsf = new BoolOption (
1413                      "seamless-loop",
1414                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1415                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1416                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1417                      );
1418         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1419                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1420                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
1421                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
1422                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
1423         add_option (_("Transport"), tsf);
1424
1425         tsf = new BoolOption (
1426                      "disable-disarm-during-roll",
1427                      _("Disable per-track record disarm while rolling"),
1428                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1429                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1430                      );
1431         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"));
1432         add_option (_("Transport"), tsf);
1433
1434         tsf = new BoolOption (
1435                      "quieten_at_speed",
1436                      _("12dB gain reduction during fast-forward and fast-rewind"),
1437                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1438                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1439                      );
1440         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1441                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1442         add_option (_("Transport"), tsf);
1443
1444         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1445
1446         _sync_source = new ComboOption<SyncSource> (
1447                 "sync-source",
1448                 _("External timecode source"),
1449                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1450                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1451                 );
1452
1453         populate_sync_options ();
1454         add_option (_("Transport"), _sync_source);
1455
1456         _sync_framerate = new BoolOption (
1457                      "timecode-sync-frame-rate",
1458                      _("Match session video frame rate to external timecode"),
1459                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1460                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1461                      );
1462         Gtkmm2ext::UI::instance()->set_tip 
1463                 (_sync_framerate->tip_widget(),
1464                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1465                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1466                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1467                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1468                                    "timecode standard and the session standard."), PROGRAM_NAME));
1469
1470         add_option (_("Transport"), _sync_framerate);
1471
1472         _sync_genlock = new BoolOption (
1473                 "timecode-source-is-synced",
1474                 _("External timecode is sync locked"),
1475                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1476                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1477                 );
1478         Gtkmm2ext::UI::instance()->set_tip 
1479                 (_sync_genlock->tip_widget(), 
1480                  _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface."));
1481
1482
1483         add_option (_("Transport"), _sync_genlock);
1484
1485         _sync_source_2997 = new BoolOption (
1486                 "timecode-source-2997",
1487                 _("Lock to 29.9700 fps instead of 30000/1001"),
1488                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1489                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1490                 );
1491         Gtkmm2ext::UI::instance()->set_tip
1492                 (_sync_source_2997->tip_widget(),
1493                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1494                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1495                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1496                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1497                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1498                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1499                          ));
1500
1501         add_option (_("Transport"), _sync_source_2997);
1502
1503         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1504
1505         _ltc_port = new ComboStringOption (
1506                 "ltc-source-port",
1507                 _("LTC incoming port"),
1508                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1509                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1510                 );
1511
1512         vector<string> physical_inputs;
1513         physical_inputs.push_back (_("None"));
1514         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1515         _ltc_port->set_popdown_strings (physical_inputs);
1516
1517         add_option (_("Transport"), _ltc_port);
1518
1519         // TODO; rather disable this button than not compile it..
1520         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1521
1522         add_option (_("Transport"),
1523                     new BoolOption (
1524                             "send-ltc",
1525                             _("Enable LTC generator"),
1526                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1527                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1528                             ));
1529
1530         _ltc_send_continuously = new BoolOption (
1531                             "ltc-send-continuously",
1532                             _("Send LTC while stopped"),
1533                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1534                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1535                             );
1536         Gtkmm2ext::UI::instance()->set_tip
1537                 (_ltc_send_continuously->tip_widget(),
1538                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
1539         add_option (_("Transport"), _ltc_send_continuously);
1540
1541         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1542         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1543         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1544         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1545
1546         Gtkmm2ext::UI::instance()->set_tip
1547                 (_ltc_volume_slider->tip_widget(),
1548                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1549
1550         add_option (_("Transport"), _ltc_volume_slider);
1551         parameter_changed ("send-ltc");
1552
1553         parameter_changed ("sync-source");
1554
1555         /* EDITOR */
1556
1557         add_option (S_("Editor"),
1558              new BoolOption (
1559                      "draggable-playhead",
1560                      _("Allow dragging of playhead"),
1561                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_draggable_playhead),
1562                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_draggable_playhead)
1563                      ));
1564
1565         add_option (_("Editor"),
1566              new BoolOption (
1567                      "automation-follows-regions",
1568                      _("Move relevant automation when audio regions are moved"),
1569                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1570                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1571                      ));
1572
1573         add_option (_("Editor"),
1574              new BoolOption (
1575                      "show-track-meters",
1576                      _("Show meters on tracks in the editor"),
1577                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1578                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1579                      ));
1580
1581         add_option (_("Editor"),
1582              new BoolOption (
1583                      "show-editor-meter",
1584                      _("Display master-meter in the toolbar"),
1585                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_editor_meter),
1586                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_editor_meter)
1587                      ));
1588
1589         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
1590                         "default-fade-shape",
1591                         _("Default fade shape"),
1592                         sigc::mem_fun (*_rc_config,
1593                                 &RCConfiguration::get_default_fade_shape),
1594                         sigc::mem_fun (*_rc_config,
1595                                 &RCConfiguration::set_default_fade_shape)
1596                         );
1597
1598         fadeshape->add (FadeLinear,
1599                         _("Linear (for highly correlated material)"));
1600         fadeshape->add (FadeConstantPower, _("Constant power"));
1601         fadeshape->add (FadeSymmetric, _("Symmetric"));
1602         fadeshape->add (FadeSlow, _("Slow"));
1603         fadeshape->add (FadeFast, _("Fast"));
1604
1605         add_option (_("Editor"), fadeshape);
1606
1607
1608         bco = new BoolComboOption (
1609                      "use-overlap-equivalency",
1610                      _("Regions in active edit groups are edited together"),
1611                      _("whenever they overlap in time"),
1612                      _("only if they have identical length, position and origin"),
1613                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1614                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1615                      );
1616
1617         add_option (_("Editor"), bco);
1618
1619         add_option (_("Editor"),
1620              new BoolOption (
1621                      "rubberbanding-snaps-to-grid",
1622                      _("Make rubberband selection rectangle snap to the grid"),
1623                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1624                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1625                      ));
1626
1627         add_option (_("Editor"),
1628              new BoolOption (
1629                      "show-waveforms",
1630                      _("Show waveforms in regions"),
1631                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1632                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1633                      ));
1634
1635         add_option (_("Editor"),
1636              new BoolComboOption (
1637                      "show-region-gain-envelopes",
1638                      _("Show gain envelopes in audio regions"),
1639                      _("in all modes"),
1640                      _("only in region gain mode"),
1641                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1642                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1643                      ));
1644
1645         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1646                 "waveform-scale",
1647                 _("Waveform scale"),
1648                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1649                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1650                 );
1651
1652         wfs->add (Linear, _("linear"));
1653         wfs->add (Logarithmic, _("logarithmic"));
1654
1655         add_option (_("Editor"), wfs);
1656
1657         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1658                 "waveform-shape",
1659                 _("Waveform shape"),
1660                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1661                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1662                 );
1663
1664         wfsh->add (Traditional, _("traditional"));
1665         wfsh->add (Rectified, _("rectified"));
1666
1667         add_option (_("Editor"), wfsh);
1668
1669         add_option (_("Editor"), new ClipLevelOptions (_rc_config));
1670
1671         add_option (_("Editor"),
1672              new BoolOption (
1673                      "show-waveforms-while-recording",
1674                      _("Show waveforms for audio while it is being recorded"),
1675                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1676                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1677                      ));
1678
1679         add_option (_("Editor"),
1680                     new BoolOption (
1681                             "show-zoom-tools",
1682                             _("Show zoom toolbar"),
1683                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1684                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1685                             ));
1686
1687         add_option (_("Editor"),
1688                     new BoolOption (
1689                             "update-editor-during-summary-drag",
1690                             _("Update editor window during drags of the summary"),
1691                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1692                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1693                             ));
1694
1695         add_option (_("Editor"),
1696              new BoolOption (
1697                      "link-editor-and-mixer-selection",
1698                      _("Synchronise editor and mixer selection"),
1699                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1700                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1701                      ));
1702
1703         bo = new BoolOption (
1704                      "name-new-markers",
1705                      _("Name new markers"),
1706                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1707                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1708                 );
1709         
1710         add_option (_("Editor"), bo);
1711         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."
1712                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1713
1714         add_option (_("Editor"),
1715             new BoolOption (
1716                     "autoscroll-editor",
1717                     _("Auto-scroll editor window when dragging near its edges"),
1718                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1719                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1720                     ));
1721
1722         /* AUDIO */
1723
1724         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1725
1726         add_option (_("Audio"), new BufferingOptions (_rc_config));
1727
1728         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1729
1730         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1731                 "monitoring-model",
1732                 _("Record monitoring handled by"),
1733                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1734                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1735                 );
1736
1737         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
1738                 mm->add (HardwareMonitoring, _("via Audio Driver"));
1739         }
1740
1741         string prog (PROGRAM_NAME);
1742         boost::algorithm::to_lower (prog);
1743         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
1744         mm->add (ExternalMonitoring, _("audio hardware"));
1745
1746         add_option (_("Audio"), mm);
1747
1748         add_option (_("Audio"),
1749              new BoolOption (
1750                      "tape-machine-mode",
1751                      _("Tape machine mode"),
1752                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1753                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1754                      ));
1755
1756         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1757
1758         add_option (_("Audio"),
1759                     new BoolOption (
1760                             "auto-connect-standard-busses",
1761                             _("Auto-connect master/monitor busses"),
1762                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1763                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1764                             ));
1765
1766         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1767                 "input-auto-connect",
1768                 _("Connect track inputs"),
1769                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1770                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1771                 );
1772
1773         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1774         iac->add (ManualConnect, _("manually"));
1775
1776         add_option (_("Audio"), iac);
1777
1778         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1779                 "output-auto-connect",
1780                 _("Connect track and bus outputs"),
1781                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1782                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1783                 );
1784
1785         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1786         oac->add (AutoConnectMaster, _("automatically to master bus"));
1787         oac->add (ManualConnect, _("manually"));
1788
1789         add_option (_("Audio"), oac);
1790
1791         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1792
1793         add_option (_("Audio"),
1794              new BoolOption (
1795                      "denormal-protection",
1796                      _("Use DC bias to protect against denormals"),
1797                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1798                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1799                      ));
1800
1801         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1802                 "denormal-model",
1803                 _("Processor handling"),
1804                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1805                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1806                 );
1807
1808         dm->add (DenormalNone, _("no processor handling"));
1809
1810         FPU fpu;
1811
1812         if (fpu.has_flush_to_zero()) {
1813                 dm->add (DenormalFTZ, _("use FlushToZero"));
1814         }
1815
1816         if (fpu.has_denormals_are_zero()) {
1817                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1818         }
1819
1820         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1821                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1822         }
1823
1824         add_option (_("Audio"), dm);
1825
1826         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1827
1828         add_option (_("Audio"),
1829              new BoolOption (
1830                      "plugins-stop-with-transport",
1831                      _("Silence plugins when the transport is stopped"),
1832                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1833                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1834                      ));
1835
1836         add_option (_("Audio"),
1837              new BoolOption (
1838                      "new-plugins-active",
1839                      _("Make new plugins active"),
1840                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1841                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1842                      ));
1843
1844         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
1845
1846         add_option (_("Audio"),
1847              new BoolOption (
1848                      "auto-analyse-audio",
1849                      _("Enable automatic analysis of audio"),
1850                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1851                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1852                      ));
1853
1854         add_option (_("Audio"),
1855              new BoolOption (
1856                      "replicate-missing-region-channels",
1857                      _("Replicate missing region channels"),
1858                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1859                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1860                      ));
1861
1862         /* SOLO AND MUTE */
1863
1864         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
1865
1866         add_option (_("Solo / mute"),
1867              new FaderOption (
1868                      "solo-mute-gain",
1869                      _("Solo-in-place mute cut (dB)"),
1870                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1871                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1872                      ));
1873
1874         _solo_control_is_listen_control = new BoolOption (
1875                 "solo-control-is-listen-control",
1876                 _("Solo controls are Listen controls"),
1877                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1878                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1879                 );
1880
1881         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1882
1883         _listen_position = new ComboOption<ListenPosition> (
1884                 "listen-position",
1885                 _("Listen Position"),
1886                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1887                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1888                 );
1889
1890         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1891         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1892
1893         add_option (_("Solo / mute"), _listen_position);
1894
1895         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1896                 "pfl-position",
1897                 _("PFL signals come from"),
1898                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1899                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1900                 );
1901
1902         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1903         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1904
1905         add_option (_("Solo / mute"), pp);
1906
1907         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1908                 "afl-position",
1909                 _("AFL signals come from"),
1910                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1911                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1912                 );
1913
1914         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1915         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1916
1917         add_option (_("Solo / mute"), pa);
1918
1919         parameter_changed ("use-monitor-bus");
1920
1921         add_option (_("Solo / mute"),
1922              new BoolOption (
1923                      "exclusive-solo",
1924                      _("Exclusive solo"),
1925                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1926                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1927                      ));
1928
1929         add_option (_("Solo / mute"),
1930              new BoolOption (
1931                      "show-solo-mutes",
1932                      _("Show solo muting"),
1933                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1934                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1935                      ));
1936
1937         add_option (_("Solo / mute"),
1938              new BoolOption (
1939                      "solo-mute-override",
1940                      _("Soloing overrides muting"),
1941                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1942                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1943                      ));
1944
1945         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1946
1947         add_option (_("Solo / mute"),
1948              new BoolOption (
1949                      "mute-affects-pre-fader",
1950                      _("Mute affects pre-fader sends"),
1951                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1952                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1953                      ));
1954
1955         add_option (_("Solo / mute"),
1956              new BoolOption (
1957                      "mute-affects-post-fader",
1958                      _("Mute affects post-fader sends"),
1959                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1960                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1961                      ));
1962
1963         add_option (_("Solo / mute"),
1964              new BoolOption (
1965                      "mute-affects-control-outs",
1966                      _("Mute affects control outputs"),
1967                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1968                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1969                      ));
1970
1971         add_option (_("Solo / mute"),
1972              new BoolOption (
1973                      "mute-affects-main-outs",
1974                      _("Mute affects main outputs"),
1975                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1976                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1977                      ));
1978
1979         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
1980
1981         add_option (_("Solo / mute"),
1982              new BoolOption (
1983                      "link-send-and-route-panner",
1984                      _("Link panners of Aux and External Sends with main panner by default"),
1985                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
1986                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
1987                      ));
1988
1989         add_option (_("MIDI"),
1990                     new BoolOption (
1991                             "send-midi-clock",
1992                             _("Send MIDI Clock"),
1993                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1994                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1995                             ));
1996
1997         add_option (_("MIDI"),
1998                     new BoolOption (
1999                             "send-mtc",
2000                             _("Send MIDI Time Code"),
2001                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2002                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2003                             ));
2004
2005         add_option (_("MIDI"),
2006                     new SpinOption<int> (
2007                             "mtc-qf-speed-tolerance",
2008                             _("Percentage either side of normal transport speed to transmit MTC"),
2009                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2010                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2011                             0, 20, 1, 5
2012                             ));
2013
2014         add_option (_("MIDI"),
2015                     new BoolOption (
2016                             "mmc-control",
2017                             _("Obey MIDI Machine Control commands"),
2018                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2019                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2020                             ));
2021
2022         add_option (_("MIDI"),
2023                     new BoolOption (
2024                             "send-mmc",
2025                             _("Send MIDI Machine Control commands"),
2026                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2027                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2028                             ));
2029
2030         add_option (_("MIDI"),
2031                     new BoolOption (
2032                             "midi-feedback",
2033                             _("Send MIDI control feedback"),
2034                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2035                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2036                             ));
2037
2038         add_option (_("MIDI"),
2039              new SpinOption<uint8_t> (
2040                      "mmc-receive-device-id",
2041                      _("Inbound MMC device ID"),
2042                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2043                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2044                      0, 128, 1, 10
2045                      ));
2046
2047         add_option (_("MIDI"),
2048              new SpinOption<uint8_t> (
2049                      "mmc-send-device-id",
2050                      _("Outbound MMC device ID"),
2051                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2052                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2053                      0, 128, 1, 10
2054                      ));
2055
2056         add_option (_("MIDI"),
2057              new SpinOption<int32_t> (
2058                      "initial-program-change",
2059                      _("Initial program change"),
2060                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2061                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2062                      -1, 65536, 1, 10
2063                      ));
2064
2065         add_option (_("MIDI"),
2066                     new BoolOption (
2067                             "display-first-midi-bank-as-zero",
2068                             _("Display first MIDI bank/program as 0"),
2069                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2070                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2071                             ));
2072
2073         add_option (_("MIDI"),
2074              new BoolOption (
2075                      "never-display-periodic-midi",
2076                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2077                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
2078                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
2079                      ));
2080
2081         add_option (_("MIDI"),
2082              new BoolOption (
2083                      "sound-midi-notes",
2084                      _("Sound MIDI notes as they are selected"),
2085                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
2086                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
2087                      ));
2088
2089         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2090
2091         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2092                 "midi-audition-synth-uri",
2093                 _("Midi Audition Synth (LV2)"),
2094                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2095                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2096                 );
2097
2098         audition_synth->add(X_(""), _("None"));
2099         PluginInfoList all_plugs;
2100         PluginManager& manager (PluginManager::instance());
2101 #ifdef LV2_SUPPORT
2102         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2103
2104         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2105                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2106                 if (!(*i)->is_instrument()) continue;
2107                 if ((*i)->type != ARDOUR::LV2) continue;
2108                 audition_synth->add((*i)->unique_id, (*i)->name);
2109         }
2110 #endif
2111
2112         add_option (_("MIDI"), audition_synth);
2113
2114         /* USER INTERACTION */
2115
2116         if (getenv ("ARDOUR_BUNDLED")) {
2117                 add_option (_("User interaction"), 
2118                             new BoolOption (
2119                                     "enable-translation",
2120                                     string_compose (_("Use translations of %1 messages\n"
2121                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2122                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2123                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2124                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2125         }
2126
2127         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2128
2129         add_option (_("User interaction"), new KeyboardOptions);
2130
2131         /* Control Surfaces */
2132
2133         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2134
2135         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2136                 "remote-model",
2137                 _("Control surface remote ID"),
2138                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2139                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2140                 );
2141
2142         rm->add (UserOrdered, _("assigned by user"));
2143         rm->add (MixerOrdered, _("follows order of mixer"));
2144
2145         add_option (_("Control Surfaces"), rm);
2146
2147         /* VIDEO Timeline */
2148         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2149
2150 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2151         /* Plugin options (currrently VST only) */
2152         add_option (_("Plugins"), new PluginOptions (_rc_config));
2153 #endif
2154
2155         /* INTERFACE */
2156
2157         add_option (S_("Preferences|GUI"),
2158              new BoolOption (
2159                      "widget-prelight",
2160                      _("Graphically indicate mouse pointer hovering over various widgets"),
2161                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
2162                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
2163                      ));
2164
2165         add_option (S_("Preferences|GUI"),
2166              new BoolOption (
2167                      "use-tooltips",
2168                      _("Show tooltips if mouse hovers over a control"),
2169                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
2170                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
2171                      ));
2172
2173         add_option (S_("Preferences|GUI"),
2174              new BoolOption (
2175                      "show-name-highlight",
2176                      _("Use name highlight bars in region displays"),
2177                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_name_highlight),
2178                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_name_highlight)
2179                      ));
2180
2181 #ifndef GTKOSX
2182         /* font scaling does nothing with GDK/Quartz */
2183         add_option (S_("Preferences|GUI"), new FontScalingOptions (_rc_config));
2184 #endif
2185
2186         add_option (S_("GUI"),
2187                     new BoolOption (
2188                             "super-rapid-clock-update",
2189                             _("update transport clock display at FPS instead of every 100ms"),
2190                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_super_rapid_clock_update),
2191                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_super_rapid_clock_update)
2192                             ));
2193
2194         /* Lock GUI timeout */
2195
2196         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2197         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2198                                                 _("Lock timeout (seconds)"),
2199                                                 lts,
2200                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_lock_gui_after_seconds),
2201                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_lock_gui_after_seconds)
2202                         );
2203         slts->scale().set_digits (0);
2204         Gtkmm2ext::UI::instance()->set_tip
2205                 (slts->tip_widget(),
2206                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2207         add_option (S_("Preferences|GUI"), slts);
2208
2209         /* The names of these controls must be the same as those given in MixerStrip
2210            for the actual widgets being controlled.
2211         */
2212         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2213         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2214         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2215         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2216         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2217         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2218         
2219         add_option (
2220                 S_("Preferences|GUI"),
2221                 new VisibilityOption (
2222                         _("Mixer Strip"),
2223                         &_mixer_strip_visibility,
2224                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
2225                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
2226                         )
2227                 );
2228
2229         add_option (S_("Preferences|GUI"),
2230              new BoolOption (
2231                      "default-narrow_ms",
2232                      _("Use narrow strips in the mixer by default"),
2233                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
2234                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
2235                      ));
2236
2237         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2238
2239         ComboOption<float>* mht = new ComboOption<float> (
2240                 "meter-hold",
2241                 _("Peak hold time"),
2242                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
2243                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
2244                 );
2245
2246         mht->add (MeterHoldOff, _("off"));
2247         mht->add (MeterHoldShort, _("short"));
2248         mht->add (MeterHoldMedium, _("medium"));
2249         mht->add (MeterHoldLong, _("long"));
2250
2251         add_option (S_("Preferences|Metering"), mht);
2252
2253         ComboOption<float>* mfo = new ComboOption<float> (
2254                 "meter-falloff",
2255                 _("DPM fall-off"),
2256                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2257                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2258                 );
2259
2260         mfo->add (METER_FALLOFF_OFF,      _("off"));
2261         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2262         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2263         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2264         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2265         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2266         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2267         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2268         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2269
2270         add_option (S_("Preferences|Metering"), mfo);
2271
2272         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2273                 "meter-line-up-level",
2274                 _("Meter line-up level; 0dBu"),
2275                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_level),
2276                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_level)
2277                 );
2278
2279         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2280         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2281         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2282         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2283
2284         Gtkmm2ext::UI::instance()->set_tip (mlu->tip_widget(), _("Configure meter-marks and color-knee point for dBFS scale DPM, set reference level for IEC1/Nordic, IEC2 PPM and VU meter."));
2285
2286         add_option (S_("Preferences|Metering"), mlu);
2287
2288         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2289                 "meter-line-up-din",
2290                 _("IEC1/DIN Meter line-up level; 0dBu"),
2291                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_din),
2292                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_din)
2293                 );
2294
2295         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2296         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2297         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2298         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2299
2300         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2301
2302         add_option (S_("Preferences|Metering"), mld);
2303
2304         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2305                 "meter-vu-standard",
2306                 _("VU Meter standard"),
2307                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_vu_standard),
2308                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_vu_standard)
2309                 );
2310
2311         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2312         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2313         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2314         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2315
2316         add_option (S_("Preferences|Metering"), mvu);
2317
2318         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2319         HSliderOption *mpks = new HSliderOption("meter-peak",
2320                         _("Peak threshold [dBFS]"),
2321                         mpk,
2322                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_peak),
2323                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_peak)
2324                         );
2325
2326         Gtkmm2ext::UI::instance()->set_tip
2327                 (mpks->tip_widget(),
2328                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2329
2330         add_option (S_("Preferences|Metering"), mpks);
2331
2332         add_option (S_("Preferences|Metering"),
2333              new BoolOption (
2334                      "meter-style-led",
2335                      _("LED meter style"),
2336                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_style_led),
2337                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_style_led)
2338                      ));
2339
2340         /* and now the theme manager */
2341
2342         ThemeManager* tm = manage (new ThemeManager);
2343         add_page (_("Theme"), *tm);
2344 }
2345
2346 void
2347 RCOptionEditor::parameter_changed (string const & p)
2348 {
2349         OptionEditor::parameter_changed (p);
2350
2351         if (p == "use-monitor-bus") {
2352                 bool const s = Config->get_use_monitor_bus ();
2353                 if (!s) {
2354                         /* we can't use this if we don't have a monitor bus */
2355                         Config->set_solo_control_is_listen_control (false);
2356                 }
2357                 _solo_control_is_listen_control->set_sensitive (s);
2358                 _listen_position->set_sensitive (s);
2359         } else if (p == "sync-source") {
2360                 _sync_source->set_sensitive (true);
2361                 if (_session) {
2362                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2363                 }
2364                 switch(Config->get_sync_source()) {
2365                 case ARDOUR::MTC:
2366                 case ARDOUR::LTC:
2367                         _sync_genlock->set_sensitive (true);
2368                         _sync_framerate->set_sensitive (true);
2369                         _sync_source_2997->set_sensitive (true);
2370                         break;
2371                 default:
2372                         _sync_genlock->set_sensitive (false);
2373                         _sync_framerate->set_sensitive (false);
2374                         _sync_source_2997->set_sensitive (false);
2375                         break;
2376                 }
2377         } else if (p == "send-ltc") {
2378                 bool const s = Config->get_send_ltc ();
2379                 _ltc_send_continuously->set_sensitive (s);
2380                 _ltc_volume_slider->set_sensitive (s);
2381         }
2382 }
2383
2384 void RCOptionEditor::ltc_generator_volume_changed () {
2385         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2386 }
2387
2388 void
2389 RCOptionEditor::populate_sync_options ()
2390 {
2391         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2392
2393         _sync_source->clear ();
2394
2395         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2396                 _sync_source->add (*i, sync_source_to_string (*i));
2397         }
2398 }