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