class 'PBD::Configuration' doesn't actually get exported from libpbd - so make sure...
[ardour.git] / gtk2_ardour / rc_option_editor.cc
1 /*
2     Copyright (C) 2001-2011 Paul Davis
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 #ifdef WAF_BUILD
21 #include "gtk2ardour-config.h"
22 #endif
23
24 #include <boost/algorithm/string.hpp>    
25
26 #include <gtkmm/liststore.h>
27 #include <gtkmm/stock.h>
28 #include <gtkmm/scale.h>
29
30 #include <gtkmm2ext/utils.h>
31 #include <gtkmm2ext/slider_controller.h>
32 #include <gtkmm2ext/gtk_ui.h>
33 #include <gtkmm2ext/paths_dialog.h>
34
35 #include "pbd/fpu.h"
36 #include "pbd/cpus.h"
37
38 #include "ardour/audioengine.h"
39 #include "ardour/dB.h"
40 #include "ardour/rc_configuration.h"
41 #include "ardour/control_protocol_manager.h"
42 #include "ardour/plugin_manager.h"
43 #include "control_protocol/control_protocol.h"
44
45 #include "canvas/wave_view.h"
46
47 #include "ardour_ui.h"
48 #include "ardour_window.h"
49 #include "ardour_dialog.h"
50 #include "gui_thread.h"
51 #include "midi_tracer.h"
52 #include "rc_option_editor.h"
53 #include "utils.h"
54 #include "midi_port_dialog.h"
55 #include "sfdb_ui.h"
56 #include "keyboard.h"
57 #include "theme_manager.h"
58 #include "ui_config.h"
59 #include "i18n.h"
60
61 using namespace std;
62 using namespace Gtk;
63 using namespace Gtkmm2ext;
64 using namespace PBD;
65 using namespace ARDOUR;
66 using namespace ARDOUR_UI_UTILS;
67
68 class ClickOptions : public OptionEditorBox
69 {
70 public:
71         ClickOptions (RCConfiguration* c, Gtk::Window* p)
72                 : _rc_config (c)
73         {
74                 Table* t = manage (new Table (2, 3));
75                 t->set_spacings (4);
76
77                 Label* l = manage (left_aligned_label (_("Click audio file:")));
78                 t->attach (*l, 0, 1, 0, 1, FILL);
79                 t->attach (_click_path_entry, 1, 2, 0, 1, FILL);
80                 Button* b = manage (new Button (_("Browse...")));
81                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
82                 t->attach (*b, 2, 3, 0, 1, FILL);
83
84                 l = manage (left_aligned_label (_("Click emphasis audio file:")));
85                 t->attach (*l, 0, 1, 1, 2, FILL);
86                 t->attach (_click_emphasis_path_entry, 1, 2, 1, 2, FILL);
87                 b = manage (new Button (_("Browse...")));
88                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
89                 t->attach (*b, 2, 3, 1, 2, FILL);
90                 
91                 _box->pack_start (*t, false, false);
92
93                 _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));      
94                 _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
95         }
96
97         void parameter_changed (string const & p)
98         {
99                 if (p == "click-sound") {
100                         _click_path_entry.set_text (_rc_config->get_click_sound());
101                 } else if (p == "click-emphasis-sound") {
102                         _click_emphasis_path_entry.set_text (_rc_config->get_click_emphasis_sound());
103                 }
104         }
105
106         void set_state_from_config ()
107         {
108                 parameter_changed ("click-sound");
109                 parameter_changed ("click-emphasis-sound");
110         }
111
112 private:
113
114         void click_browse_clicked ()
115         {
116                 SoundFileChooser sfdb (_("Choose Click"));
117
118                 if (sfdb.run () == RESPONSE_OK) {
119                         click_chosen (sfdb.get_filename());
120                 }
121         }
122
123         void click_chosen (string const & path)
124         {
125                 _click_path_entry.set_text (path);
126                 _rc_config->set_click_sound (path);
127         }
128
129         void click_changed ()
130         {
131                 click_chosen (_click_path_entry.get_text ());
132         }
133         
134         void click_emphasis_browse_clicked ()
135         {
136                 SoundFileChooser sfdb (_("Choose Click Emphasis"));
137
138                 sfdb.show_all ();
139                 sfdb.present ();
140
141                 if (sfdb.run () == RESPONSE_OK) {
142                         click_emphasis_chosen (sfdb.get_filename());
143                 }
144         }
145
146         void click_emphasis_chosen (string const & path)
147         {
148                 _click_emphasis_path_entry.set_text (path);
149                 _rc_config->set_click_emphasis_sound (path);
150         }
151
152         void click_emphasis_changed ()
153         {
154                 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
155         }
156
157         RCConfiguration* _rc_config;
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 (UIConfiguration* uic) :
535                 _ui_config (uic),
536                 _dpi_adjustment (50, 50, 250, 1, 10),
537                 _dpi_slider (_dpi_adjustment)
538         {
539                 _dpi_adjustment.set_value (floor ((double)(uic->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)(_ui_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                 _ui_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         UIConfiguration* _ui_config;
577         Adjustment _dpi_adjustment;
578         HScale _dpi_slider;
579 };
580
581 class ClipLevelOptions : public OptionEditorBox
582 {
583 public:
584         ClipLevelOptions (UIConfiguration* c) 
585                 : _ui_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 (_ui_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 (_ui_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                 _ui_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         UIConfiguration* _ui_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, UIConfiguration* uic)
997                 : _rc_config (c)
998                 , _ui_config (uic)
999                 , _display_plugin_scan_progress (_("Always Display Plugin Scan Progress"))
1000                 , _discover_vst_on_start (_("Scan for [new] VST Plugins on Application Start"))
1001                 , _discover_au_on_start (_("Scan for AudioUnit Plugins on Application Start"))
1002                 , _timeout_adjustment (0, 0, 3000, 50, 50)
1003                 , _timeout_slider (_timeout_adjustment)
1004         {
1005                 Label *l;
1006                 std::stringstream ss;
1007                 Table* t = manage (new Table (2, 6));
1008                 t->set_spacings (4);
1009                 Button* b;
1010                 int n = 0;
1011
1012                 ss << "<b>" << _("General") << "</b>";
1013                 l = manage (left_aligned_label (ss.str()));
1014                 l->set_use_markup (true);
1015                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1016                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1017
1018                 b = manage (new Button (_("Scan for Plugins")));
1019                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::refresh_clicked));
1020                 t->attach (*b, 0, 2, n, n+1, FILL); ++n;
1021
1022                 t->attach (_display_plugin_scan_progress, 0, 2, n, n+1); ++n;
1023                 _display_plugin_scan_progress.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::display_plugin_scan_progress_toggled));
1024                 Gtkmm2ext::UI::instance()->set_tip (_display_plugin_scan_progress,
1025                                             _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
1026
1027 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
1028                 _timeout_slider.set_digits (0);
1029                 _timeout_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &PluginOptions::timeout_changed));
1030
1031                 Gtkmm2ext::UI::instance()->set_tip(_timeout_slider,
1032                          _("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."));
1033
1034                 l = manage (left_aligned_label (_("Scan Time Out [deciseconds]")));;
1035                 HBox* h = manage (new HBox);
1036                 h->set_spacing (4);
1037                 h->pack_start (*l, false, false);
1038                 h->pack_start (_timeout_slider, true, true);
1039                 t->attach (*h, 0, 2, n, n+1); ++n;
1040
1041                 ss.str("");
1042                 ss << "<b>" << _("VST") << "</b>";
1043                 l = manage (left_aligned_label (ss.str()));
1044                 l->set_use_markup (true);
1045                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1046                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1047
1048                 b = manage (new Button (_("Clear VST Cache")));
1049                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_cache_clicked));
1050                 t->attach (*b, 0, 1, n, n+1, FILL);
1051
1052                 b = manage (new Button (_("Clear VST Blacklist")));
1053                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_blacklist_clicked));
1054                 t->attach (*b, 1, 2, n, n+1, FILL);
1055                 ++n;
1056
1057                 t->attach (_discover_vst_on_start, 0, 2, n, n+1); ++n;
1058                 _discover_vst_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_vst_on_start_toggled));
1059                 Gtkmm2ext::UI::instance()->set_tip (_discover_vst_on_start,
1060                                             _("<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"));
1061
1062 #ifdef LXVST_SUPPORT
1063                 t->attach (*manage (left_aligned_label (_("Linux VST Path:"))), 0, 1, n, n+1);
1064                 b = manage (new Button (_("Edit")));
1065                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_lxvst_path_clicked));
1066                 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1067 #endif
1068
1069 #ifdef WINDOWS_VST_SUPPORT
1070                 t->attach (*manage (left_aligned_label (_("Windows VST Path:"))), 0, 1, n, n+1);
1071                 b = manage (new Button (_("Edit")));
1072                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_vst_path_clicked));
1073                 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1074 #endif
1075 #endif // any VST
1076
1077 #ifdef AUDIOUNIT_SUPPORT
1078                 t->attach (_discover_au_on_start, 0, 2, n, n+1); ++n;
1079                 _discover_au_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_au_on_start_toggled));
1080                 Gtkmm2ext::UI::instance()->set_tip (_discover_au_on_start,
1081                                             _("<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."));
1082 #endif
1083
1084                 _box->pack_start (*t,true,true);
1085         }
1086
1087         void parameter_changed (string const & p) {
1088                 if (p == "show-plugin-scan-window") {
1089                         bool const x = _ui_config->get_show_plugin_scan_window();
1090                         _display_plugin_scan_progress.set_active (x);
1091                 }
1092                 else if (p == "discover-vst-on-start") {
1093                         bool const x = _rc_config->get_discover_vst_on_start();
1094                         _discover_vst_on_start.set_active (x);
1095                 }
1096                 else if (p == "vst-scan-timeout") {
1097                         int const x = _rc_config->get_vst_scan_timeout();
1098                         _timeout_adjustment.set_value (x);
1099                 }
1100                 else if (p == "discover-audio-units") {
1101                         bool const x = _rc_config->get_discover_audio_units();
1102                         _discover_au_on_start.set_active (x);
1103                 }
1104         }
1105
1106         void set_state_from_config () {
1107                 parameter_changed ("show-plugin-scan-window");
1108                 parameter_changed ("discover-vst-on-start");
1109                 parameter_changed ("vst-scan-timeout");
1110                 parameter_changed ("discover-audio-units");
1111         }
1112
1113 private:
1114         RCConfiguration* _rc_config;
1115         UIConfiguration* _ui_config;
1116         CheckButton _display_plugin_scan_progress;
1117         CheckButton _discover_vst_on_start;
1118         CheckButton _discover_au_on_start;
1119         Adjustment _timeout_adjustment;
1120         HScale _timeout_slider;
1121
1122         void display_plugin_scan_progress_toggled () {
1123                 bool const x = _display_plugin_scan_progress.get_active();
1124                 _ui_config->set_show_plugin_scan_window(x);
1125         }
1126
1127         void discover_vst_on_start_toggled () {
1128                 bool const x = _discover_vst_on_start.get_active();
1129                 _rc_config->set_discover_vst_on_start(x);
1130         }
1131
1132         void discover_au_on_start_toggled () {
1133                 bool const x = _discover_au_on_start.get_active();
1134                 _rc_config->set_discover_audio_units(x);
1135         }
1136
1137         void timeout_changed () {
1138                 int x = floor(_timeout_adjustment.get_value());
1139                 _rc_config->set_vst_scan_timeout(x);
1140         }
1141
1142         void clear_vst_cache_clicked () {
1143                 PluginManager::instance().clear_vst_cache();
1144         }
1145
1146         void clear_vst_blacklist_clicked () {
1147                 PluginManager::instance().clear_vst_blacklist();
1148         }
1149
1150         void edit_vst_path_clicked () {
1151                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1152                                 _("Set Windows VST Search Path"),
1153                                 _rc_config->get_plugin_path_vst(),
1154                                 PluginManager::instance().get_default_windows_vst_path()
1155                         );
1156                 ResponseType r = (ResponseType) pd->run ();
1157                 pd->hide();
1158                 if (r == RESPONSE_ACCEPT) {
1159                         _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
1160                 }
1161                 delete pd;
1162         }
1163
1164         // todo consolidate with edit_vst_path_clicked..
1165         void edit_lxvst_path_clicked () {
1166                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1167                                 _("Set Linux VST Search Path"),
1168                                 _rc_config->get_plugin_path_lxvst(),
1169                                 PluginManager::instance().get_default_lxvst_path()
1170                                 );
1171                 ResponseType r = (ResponseType) pd->run ();
1172                 pd->hide();
1173                 if (r == RESPONSE_ACCEPT) {
1174                         _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
1175                 }
1176                 delete pd;
1177         }
1178
1179         void refresh_clicked () {
1180                 PluginManager::instance().refresh();
1181         }
1182 };
1183
1184
1185 /** A class which allows control of visibility of some editor components usign
1186  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
1187  *  which has the correct members, but with null widget pointers.  This
1188  *  class allows the user to set visibility of the members, the details
1189  *  of which are stored in a configuration variable which can be watched
1190  *  by parts of the editor that actually contain the widgets whose visibility
1191  *  is being controlled.
1192  */
1193
1194 class VisibilityOption : public Option
1195 {
1196 public:
1197         /** @param name User-visible name for this group.
1198          *  @param g `Dummy' VisibilityGroup (as described above).
1199          *  @param get Method to get the value of the appropriate configuration variable.
1200          *  @param set Method to set the value of the appropriate configuration variable.
1201          */
1202         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1203                 : Option (g->get_state_name(), name)
1204                 , _heading (name)
1205                 , _visibility_group (g)
1206                 , _get (get)
1207                 , _set (set)
1208         {
1209                 /* Watch for changes made by the user to our members */
1210                 _visibility_group->VisibilityChanged.connect_same_thread (
1211                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1212                         );
1213         }
1214
1215         void set_state_from_config ()
1216         {
1217                 /* Set our state from the current configuration */
1218                 _visibility_group->set_state (_get ());
1219         }
1220
1221         void add_to_page (OptionEditorPage* p)
1222         {
1223                 _heading.add_to_page (p);
1224                 add_widget_to_page (p, _visibility_group->list_view ());
1225         }
1226
1227         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1228
1229 private:
1230         void changed ()
1231         {
1232                 /* The user has changed something, so reflect this change
1233                    in the RCConfiguration.
1234                 */
1235                 _set (_visibility_group->get_state_value ());
1236         }
1237         
1238         OptionEditorHeading _heading;
1239         VisibilityGroup* _visibility_group;
1240         sigc::slot<std::string> _get;
1241         sigc::slot<bool, std::string> _set;
1242         PBD::ScopedConnection _visibility_group_connection;
1243 };
1244
1245
1246
1247 RCOptionEditor::RCOptionEditor ()
1248         : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
1249         , _rc_config (Config)
1250         , _ui_config (ARDOUR_UI::config())
1251         , _mixer_strip_visibility ("mixer-element-visibility")
1252 {
1253         /* MISC */
1254
1255         uint32_t hwcpus = hardware_concurrency ();
1256         BoolOption* bo;
1257         BoolComboOption* bco;
1258
1259         if (hwcpus > 1) {
1260                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
1261
1262                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
1263                         "processor-usage",
1264                         _("Signal processing uses"),
1265                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
1266                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
1267                         );
1268
1269                 procs->add (-1, _("all but one processor"));
1270                 procs->add (0, _("all available processors"));
1271
1272                 for (uint32_t i = 1; i <= hwcpus; ++i) {
1273                         procs->add (i, string_compose (_("%1 processors"), i));
1274                 }
1275
1276                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
1277
1278                 add_option (_("Misc"), procs);
1279         }
1280
1281         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
1282
1283         add_option (_("Misc"), new UndoOptions (_rc_config));
1284
1285         add_option (_("Misc"),
1286              new BoolOption (
1287                      "verify-remove-last-capture",
1288                      _("Verify removal of last capture"),
1289                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
1290                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
1291                      ));
1292
1293         add_option (_("Misc"),
1294              new BoolOption (
1295                      "periodic-safety-backups",
1296                      _("Make periodic backups of the session file"),
1297                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1298                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1299                      ));
1300
1301         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
1302
1303         add_option (_("Misc"),
1304              new BoolOption (
1305                      "only-copy-imported-files",
1306                      _("Always copy imported files"),
1307                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_only_copy_imported_files),
1308                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_only_copy_imported_files)
1309                      ));
1310
1311         add_option (_("Misc"), new DirectoryOption (
1312                             X_("default-session-parent-dir"),
1313                             _("Default folder for new sessions:"),
1314                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
1315                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
1316                             ));
1317
1318         add_option (_("Misc"),
1319              new SpinOption<uint32_t> (
1320                      "max-recent-sessions",
1321                      _("Maximum number of recent sessions"),
1322                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
1323                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
1324                      0, 1000, 1, 20
1325                      ));
1326
1327         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
1328
1329         add_option (_("Misc"), new ClickOptions (_rc_config, this));
1330
1331         add_option (_("Misc"),
1332              new FaderOption (
1333                      "click-gain",
1334                      _("Click gain level"),
1335                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
1336                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
1337                      ));
1338
1339         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
1340
1341         add_option (_("Misc"),
1342              new SpinOption<double> (
1343                      "automation-thinning-factor",
1344                      _("Thinning factor (larger value => less data)"),
1345                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
1346                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
1347                      0, 1000, 1, 20
1348                      ));
1349
1350         add_option (_("Misc"),
1351              new SpinOption<double> (
1352                      "automation-interval-msecs",
1353                      _("Automation sampling interval (milliseconds)"),
1354                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
1355                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
1356                      1, 1000, 1, 20
1357                      ));
1358
1359         /* TRANSPORT */
1360
1361         BoolOption* tsf;
1362
1363         tsf = new BoolOption (
1364                      "latched-record-enable",
1365                      _("Keep record-enable engaged on stop"),
1366                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
1367                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
1368                      );
1369         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1370         add_option (_("Transport"), tsf);
1371
1372         tsf = new BoolOption (
1373                      "stop-recording-on-xrun",
1374                      _("Stop recording when an xrun occurs"),
1375                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1376                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1377                      );
1378         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1379                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
1380                                                             PROGRAM_NAME));
1381         add_option (_("Transport"), tsf);
1382
1383         tsf = new BoolOption (
1384                      "loop-is-mode",
1385                      _("Play loop is a transport mode"),
1386                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
1387                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
1388                      );
1389         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1390                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
1391                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
1392         add_option (_("Transport"), tsf);
1393         
1394         tsf = new BoolOption (
1395                      "create-xrun-marker",
1396                      _("Create markers where xruns occur"),
1397                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1398                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1399                      );
1400         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1401         add_option (_("Transport"), tsf);
1402
1403         tsf = new BoolOption (
1404                      "stop-at-session-end",
1405                      _("Stop at the end of the session"),
1406                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1407                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1408                      );
1409         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1410                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1411                                                               "when it reaches the current session end marker\n\n"
1412                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1413                                                             PROGRAM_NAME));
1414         add_option (_("Transport"), tsf);
1415
1416         tsf = new BoolOption (
1417                      "seamless-loop",
1418                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1419                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1420                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1421                      );
1422         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1423                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1424                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
1425                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
1426                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
1427         add_option (_("Transport"), tsf);
1428
1429         tsf = new BoolOption (
1430                      "disable-disarm-during-roll",
1431                      _("Disable per-track record disarm while rolling"),
1432                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1433                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1434                      );
1435         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"));
1436         add_option (_("Transport"), tsf);
1437
1438         tsf = new BoolOption (
1439                      "quieten_at_speed",
1440                      _("12dB gain reduction during fast-forward and fast-rewind"),
1441                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1442                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1443                      );
1444         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1445                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1446         add_option (_("Transport"), tsf);
1447
1448         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1449
1450         _sync_source = new ComboOption<SyncSource> (
1451                 "sync-source",
1452                 _("External timecode source"),
1453                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1454                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1455                 );
1456
1457         populate_sync_options ();
1458         add_option (_("Transport"), _sync_source);
1459
1460         _sync_framerate = new BoolOption (
1461                      "timecode-sync-frame-rate",
1462                      _("Match session video frame rate to external timecode"),
1463                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1464                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1465                      );
1466         Gtkmm2ext::UI::instance()->set_tip 
1467                 (_sync_framerate->tip_widget(),
1468                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1469                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1470                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1471                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1472                                    "timecode standard and the session standard."), PROGRAM_NAME));
1473
1474         add_option (_("Transport"), _sync_framerate);
1475
1476         _sync_genlock = new BoolOption (
1477                 "timecode-source-is-synced",
1478                 _("External timecode is sync locked"),
1479                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1480                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1481                 );
1482         Gtkmm2ext::UI::instance()->set_tip 
1483                 (_sync_genlock->tip_widget(), 
1484                  _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface."));
1485
1486
1487         add_option (_("Transport"), _sync_genlock);
1488
1489         _sync_source_2997 = new BoolOption (
1490                 "timecode-source-2997",
1491                 _("Lock to 29.9700 fps instead of 30000/1001"),
1492                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1493                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1494                 );
1495         Gtkmm2ext::UI::instance()->set_tip
1496                 (_sync_source_2997->tip_widget(),
1497                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1498                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1499                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1500                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1501                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1502                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1503                          ));
1504
1505         add_option (_("Transport"), _sync_source_2997);
1506
1507         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1508
1509         _ltc_port = new ComboStringOption (
1510                 "ltc-source-port",
1511                 _("LTC incoming port"),
1512                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1513                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1514                 );
1515
1516         vector<string> physical_inputs;
1517         physical_inputs.push_back (_("None"));
1518         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1519         _ltc_port->set_popdown_strings (physical_inputs);
1520
1521         add_option (_("Transport"), _ltc_port);
1522
1523         // TODO; rather disable this button than not compile it..
1524         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1525
1526         add_option (_("Transport"),
1527                     new BoolOption (
1528                             "send-ltc",
1529                             _("Enable LTC generator"),
1530                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1531                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1532                             ));
1533
1534         _ltc_send_continuously = new BoolOption (
1535                             "ltc-send-continuously",
1536                             _("Send LTC while stopped"),
1537                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1538                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1539                             );
1540         Gtkmm2ext::UI::instance()->set_tip
1541                 (_ltc_send_continuously->tip_widget(),
1542                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
1543         add_option (_("Transport"), _ltc_send_continuously);
1544
1545         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1546         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1547         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1548         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1549
1550         Gtkmm2ext::UI::instance()->set_tip
1551                 (_ltc_volume_slider->tip_widget(),
1552                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1553
1554         add_option (_("Transport"), _ltc_volume_slider);
1555         parameter_changed ("send-ltc");
1556
1557         parameter_changed ("sync-source");
1558
1559         /* EDITOR */
1560
1561         add_option (S_("Editor"),
1562              new BoolOption (
1563                      "draggable-playhead",
1564                      _("Allow dragging of playhead"),
1565                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_draggable_playhead),
1566                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_draggable_playhead)
1567                      ));
1568
1569         add_option (_("Editor"),
1570              new BoolOption (
1571                      "automation-follows-regions",
1572                      _("Move relevant automation when audio regions are moved"),
1573                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1574                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1575                      ));
1576
1577         add_option (_("Editor"),
1578              new BoolOption (
1579                      "show-track-meters",
1580                      _("Show meters on tracks in the editor"),
1581                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_track_meters),
1582                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_track_meters)
1583                      ));
1584
1585         add_option (_("Editor"),
1586              new BoolOption (
1587                      "show-editor-meter",
1588                      _("Display master-meter in the toolbar"),
1589                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_editor_meter),
1590                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_editor_meter)
1591                      ));
1592
1593         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
1594                         "default-fade-shape",
1595                         _("Default fade shape"),
1596                         sigc::mem_fun (*_rc_config,
1597                                 &RCConfiguration::get_default_fade_shape),
1598                         sigc::mem_fun (*_rc_config,
1599                                 &RCConfiguration::set_default_fade_shape)
1600                         );
1601
1602         fadeshape->add (FadeLinear,
1603                         _("Linear (for highly correlated material)"));
1604         fadeshape->add (FadeConstantPower, _("Constant power"));
1605         fadeshape->add (FadeSymmetric, _("Symmetric"));
1606         fadeshape->add (FadeSlow, _("Slow"));
1607         fadeshape->add (FadeFast, _("Fast"));
1608
1609         add_option (_("Editor"), fadeshape);
1610
1611
1612         bco = new BoolComboOption (
1613                      "use-overlap-equivalency",
1614                      _("Regions in active edit groups are edited together"),
1615                      _("whenever they overlap in time"),
1616                      _("only if they have identical length, position and origin"),
1617                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1618                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1619                      );
1620
1621         add_option (_("Editor"), bco);
1622
1623         add_option (_("Editor"),
1624              new BoolOption (
1625                      "rubberbanding-snaps-to-grid",
1626                      _("Make rubberband selection rectangle snap to the grid"),
1627                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_rubberbanding_snaps_to_grid),
1628                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_rubberbanding_snaps_to_grid)
1629                      ));
1630
1631         add_option (_("Editor"),
1632              new BoolOption (
1633                      "show-waveforms",
1634                      _("Show waveforms in regions"),
1635                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms),
1636                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms)
1637                      ));
1638
1639         add_option (_("Editor"),
1640              new BoolComboOption (
1641                      "show-region-gain-envelopes",
1642                      _("Show gain envelopes in audio regions"),
1643                      _("in all modes"),
1644                      _("only in region gain mode"),
1645                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_region_gain),
1646                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_region_gain)
1647                      ));
1648
1649         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1650                 "waveform-scale",
1651                 _("Waveform scale"),
1652                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_scale),
1653                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_scale)
1654                 );
1655
1656         wfs->add (Linear, _("linear"));
1657         wfs->add (Logarithmic, _("logarithmic"));
1658
1659         add_option (_("Editor"), wfs);
1660
1661         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1662                 "waveform-shape",
1663                 _("Waveform shape"),
1664                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_shape),
1665                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_shape)
1666                 );
1667
1668         wfsh->add (Traditional, _("traditional"));
1669         wfsh->add (Rectified, _("rectified"));
1670
1671         add_option (_("Editor"), wfsh);
1672
1673         add_option (_("Editor"), new ClipLevelOptions (_ui_config));
1674
1675         add_option (_("Editor"),
1676              new BoolOption (
1677                      "show-waveforms-while-recording",
1678                      _("Show waveforms for audio while it is being recorded"),
1679                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms_while_recording),
1680                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms_while_recording)
1681                      ));
1682
1683         add_option (_("Editor"),
1684                     new BoolOption (
1685                             "show-zoom-tools",
1686                             _("Show zoom toolbar"),
1687                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_zoom_tools),
1688                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_zoom_tools)
1689                             ));
1690
1691         add_option (_("Editor"),
1692                     new BoolOption (
1693                             "update-editor-during-summary-drag",
1694                             _("Update editor window during drags of the summary"),
1695                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_update_editor_during_summary_drag),
1696                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_update_editor_during_summary_drag)
1697                             ));
1698
1699         add_option (_("Editor"),
1700              new BoolOption (
1701                      "link-editor-and-mixer-selection",
1702                      _("Synchronise editor and mixer selection"),
1703                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_link_editor_and_mixer_selection),
1704                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_link_editor_and_mixer_selection)
1705                      ));
1706
1707         bo = new BoolOption (
1708                      "name-new-markers",
1709                      _("Name new markers"),
1710                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_name_new_markers),
1711                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_name_new_markers)
1712                 );
1713         
1714         add_option (_("Editor"), bo);
1715         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."
1716                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1717
1718         add_option (_("Editor"),
1719             new BoolOption (
1720                     "autoscroll-editor",
1721                     _("Auto-scroll editor window when dragging near its edges"),
1722                     sigc::mem_fun (*_ui_config, &UIConfiguration::get_autoscroll_editor),
1723                     sigc::mem_fun (*_ui_config, &UIConfiguration::set_autoscroll_editor)
1724                     ));
1725
1726         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
1727                     "region-selection-after-split",
1728                     _("After splitting selected regions, select"),
1729                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
1730                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
1731
1732         // TODO: decide which of these modes are really useful
1733         rsas->add(None, _("no regions"));
1734         // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
1735         // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
1736         rsas->add(NewlyCreatedBoth, _("newly-created regions"));
1737         // rsas->add(Existing, _("unmodified regions in the existing selection"));
1738         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
1739         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
1740         rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
1741
1742         add_option (_("Editor"), rsas);
1743
1744
1745         /* AUDIO */
1746
1747         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1748
1749         add_option (_("Audio"), new BufferingOptions (_rc_config));
1750
1751         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1752
1753         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1754                 "monitoring-model",
1755                 _("Record monitoring handled by"),
1756                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1757                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1758                 );
1759
1760         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
1761                 mm->add (HardwareMonitoring, _("via Audio Driver"));
1762         }
1763
1764         string prog (PROGRAM_NAME);
1765         boost::algorithm::to_lower (prog);
1766         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
1767         mm->add (ExternalMonitoring, _("audio hardware"));
1768
1769         add_option (_("Audio"), mm);
1770
1771         add_option (_("Audio"),
1772              new BoolOption (
1773                      "tape-machine-mode",
1774                      _("Tape machine mode"),
1775                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1776                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1777                      ));
1778
1779         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1780
1781         add_option (_("Audio"),
1782                     new BoolOption (
1783                             "auto-connect-standard-busses",
1784                             _("Auto-connect master/monitor busses"),
1785                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1786                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1787                             ));
1788
1789         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1790                 "input-auto-connect",
1791                 _("Connect track inputs"),
1792                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1793                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1794                 );
1795
1796         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1797         iac->add (ManualConnect, _("manually"));
1798
1799         add_option (_("Audio"), iac);
1800
1801         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1802                 "output-auto-connect",
1803                 _("Connect track and bus outputs"),
1804                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1805                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1806                 );
1807
1808         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1809         oac->add (AutoConnectMaster, _("automatically to master bus"));
1810         oac->add (ManualConnect, _("manually"));
1811
1812         add_option (_("Audio"), oac);
1813
1814         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1815
1816         add_option (_("Audio"),
1817              new BoolOption (
1818                      "denormal-protection",
1819                      _("Use DC bias to protect against denormals"),
1820                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1821                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1822                      ));
1823
1824         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1825                 "denormal-model",
1826                 _("Processor handling"),
1827                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1828                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1829                 );
1830
1831         dm->add (DenormalNone, _("no processor handling"));
1832
1833         FPU fpu;
1834
1835         if (fpu.has_flush_to_zero()) {
1836                 dm->add (DenormalFTZ, _("use FlushToZero"));
1837         }
1838
1839         if (fpu.has_denormals_are_zero()) {
1840                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1841         }
1842
1843         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1844                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1845         }
1846
1847         add_option (_("Audio"), dm);
1848
1849         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1850
1851         add_option (_("Audio"),
1852              new BoolOption (
1853                      "plugins-stop-with-transport",
1854                      _("Silence plugins when the transport is stopped"),
1855                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1856                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1857                      ));
1858
1859         add_option (_("Audio"),
1860              new BoolOption (
1861                      "new-plugins-active",
1862                      _("Make new plugins active"),
1863                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1864                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1865                      ));
1866
1867         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
1868
1869         add_option (_("Audio"),
1870              new BoolOption (
1871                      "auto-analyse-audio",
1872                      _("Enable automatic analysis of audio"),
1873                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1874                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1875                      ));
1876
1877         add_option (_("Audio"),
1878              new BoolOption (
1879                      "replicate-missing-region-channels",
1880                      _("Replicate missing region channels"),
1881                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1882                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1883                      ));
1884
1885         /* SOLO AND MUTE */
1886
1887         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
1888
1889         add_option (_("Solo / mute"),
1890              new FaderOption (
1891                      "solo-mute-gain",
1892                      _("Solo-in-place mute cut (dB)"),
1893                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1894                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1895                      ));
1896
1897         _solo_control_is_listen_control = new BoolOption (
1898                 "solo-control-is-listen-control",
1899                 _("Solo controls are Listen controls"),
1900                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1901                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1902                 );
1903
1904         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1905
1906         _listen_position = new ComboOption<ListenPosition> (
1907                 "listen-position",
1908                 _("Listen Position"),
1909                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1910                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1911                 );
1912
1913         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1914         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1915
1916         add_option (_("Solo / mute"), _listen_position);
1917
1918         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1919                 "pfl-position",
1920                 _("PFL signals come from"),
1921                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1922                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1923                 );
1924
1925         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1926         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1927
1928         add_option (_("Solo / mute"), pp);
1929
1930         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1931                 "afl-position",
1932                 _("AFL signals come from"),
1933                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1934                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1935                 );
1936
1937         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1938         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1939
1940         add_option (_("Solo / mute"), pa);
1941
1942         parameter_changed ("use-monitor-bus");
1943
1944         add_option (_("Solo / mute"),
1945              new BoolOption (
1946                      "exclusive-solo",
1947                      _("Exclusive solo"),
1948                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1949                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1950                      ));
1951
1952         add_option (_("Solo / mute"),
1953              new BoolOption (
1954                      "show-solo-mutes",
1955                      _("Show solo muting"),
1956                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1957                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1958                      ));
1959
1960         add_option (_("Solo / mute"),
1961              new BoolOption (
1962                      "solo-mute-override",
1963                      _("Soloing overrides muting"),
1964                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1965                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1966                      ));
1967
1968         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1969
1970         add_option (_("Solo / mute"),
1971              new BoolOption (
1972                      "mute-affects-pre-fader",
1973                      _("Mute affects pre-fader sends"),
1974                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1975                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1976                      ));
1977
1978         add_option (_("Solo / mute"),
1979              new BoolOption (
1980                      "mute-affects-post-fader",
1981                      _("Mute affects post-fader sends"),
1982                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1983                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1984                      ));
1985
1986         add_option (_("Solo / mute"),
1987              new BoolOption (
1988                      "mute-affects-control-outs",
1989                      _("Mute affects control outputs"),
1990                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1991                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1992                      ));
1993
1994         add_option (_("Solo / mute"),
1995              new BoolOption (
1996                      "mute-affects-main-outs",
1997                      _("Mute affects main outputs"),
1998                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1999                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2000                      ));
2001
2002         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
2003
2004         add_option (_("Solo / mute"),
2005              new BoolOption (
2006                      "link-send-and-route-panner",
2007                      _("Link panners of Aux and External Sends with main panner by default"),
2008                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2009                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2010                      ));
2011
2012         add_option (_("MIDI"),
2013                     new BoolOption (
2014                             "send-midi-clock",
2015                             _("Send MIDI Clock"),
2016                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2017                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2018                             ));
2019
2020         add_option (_("MIDI"),
2021                     new BoolOption (
2022                             "send-mtc",
2023                             _("Send MIDI Time Code"),
2024                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2025                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2026                             ));
2027
2028         add_option (_("MIDI"),
2029                     new SpinOption<int> (
2030                             "mtc-qf-speed-tolerance",
2031                             _("Percentage either side of normal transport speed to transmit MTC"),
2032                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2033                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2034                             0, 20, 1, 5
2035                             ));
2036
2037         add_option (_("MIDI"),
2038                     new BoolOption (
2039                             "mmc-control",
2040                             _("Obey MIDI Machine Control commands"),
2041                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2042                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2043                             ));
2044
2045         add_option (_("MIDI"),
2046                     new BoolOption (
2047                             "send-mmc",
2048                             _("Send MIDI Machine Control commands"),
2049                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2050                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2051                             ));
2052
2053         add_option (_("MIDI"),
2054                     new BoolOption (
2055                             "midi-feedback",
2056                             _("Send MIDI control feedback"),
2057                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2058                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2059                             ));
2060
2061         add_option (_("MIDI"),
2062              new SpinOption<uint8_t> (
2063                      "mmc-receive-device-id",
2064                      _("Inbound MMC device ID"),
2065                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2066                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2067                      0, 128, 1, 10
2068                      ));
2069
2070         add_option (_("MIDI"),
2071              new SpinOption<uint8_t> (
2072                      "mmc-send-device-id",
2073                      _("Outbound MMC device ID"),
2074                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2075                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2076                      0, 128, 1, 10
2077                      ));
2078
2079         add_option (_("MIDI"),
2080              new SpinOption<int32_t> (
2081                      "initial-program-change",
2082                      _("Initial program change"),
2083                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2084                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2085                      -1, 65536, 1, 10
2086                      ));
2087
2088         add_option (_("MIDI"),
2089                     new BoolOption (
2090                             "display-first-midi-bank-as-zero",
2091                             _("Display first MIDI bank/program as 0"),
2092                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2093                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2094                             ));
2095
2096         add_option (_("MIDI"),
2097              new BoolOption (
2098                      "never-display-periodic-midi",
2099                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2100                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_never_display_periodic_midi),
2101                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_never_display_periodic_midi)
2102                      ));
2103
2104         add_option (_("MIDI"),
2105              new BoolOption (
2106                      "sound-midi-notes",
2107                      _("Sound MIDI notes as they are selected"),
2108                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_sound_midi_notes),
2109                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_sound_midi_notes)
2110                      ));
2111
2112         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2113
2114         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2115                 "midi-audition-synth-uri",
2116                 _("Midi Audition Synth (LV2)"),
2117                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2118                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2119                 );
2120
2121         audition_synth->add(X_(""), _("None"));
2122         PluginInfoList all_plugs;
2123         PluginManager& manager (PluginManager::instance());
2124 #ifdef LV2_SUPPORT
2125         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2126
2127         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2128                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2129                 if (!(*i)->is_instrument()) continue;
2130                 if ((*i)->type != ARDOUR::LV2) continue;
2131                 audition_synth->add((*i)->unique_id, (*i)->name);
2132         }
2133 #endif
2134
2135         add_option (_("MIDI"), audition_synth);
2136
2137         /* USER INTERACTION */
2138
2139         if (getenv ("ARDOUR_BUNDLED")) {
2140                 add_option (_("User interaction"), 
2141                             new BoolOption (
2142                                     "enable-translation",
2143                                     string_compose (_("Use translations of %1 messages\n"
2144                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2145                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2146                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2147                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2148         }
2149
2150         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2151
2152         add_option (_("User interaction"), new KeyboardOptions);
2153
2154         /* Control Surfaces */
2155
2156         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2157
2158         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2159                 "remote-model",
2160                 _("Control surface remote ID"),
2161                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2162                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2163                 );
2164
2165         rm->add (UserOrdered, _("assigned by user"));
2166         rm->add (MixerOrdered, _("follows order of mixer"));
2167
2168         add_option (_("Control Surfaces"), rm);
2169
2170         /* VIDEO Timeline */
2171         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2172
2173 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2174         /* Plugin options (currrently VST only) */
2175         add_option (_("Plugins"), new PluginOptions (_rc_config, _ui_config));
2176 #endif
2177
2178         /* INTERFACE */
2179
2180         add_option (S_("Preferences|GUI"),
2181              new BoolOption (
2182                      "widget-prelight",
2183                      _("Graphically indicate mouse pointer hovering over various widgets"),
2184                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_widget_prelight),
2185                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_widget_prelight)
2186                      ));
2187
2188         add_option (S_("Preferences|GUI"),
2189              new BoolOption (
2190                      "use-tooltips",
2191                      _("Show tooltips if mouse hovers over a control"),
2192                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_use_tooltips),
2193                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_use_tooltips)
2194                      ));
2195
2196         add_option (S_("Preferences|GUI"),
2197              new BoolOption (
2198                      "show-name-highlight",
2199                      _("Use name highlight bars in region displays"),
2200                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_name_highlight),
2201                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_name_highlight)
2202                      ));
2203
2204 #ifndef GTKOSX
2205         /* font scaling does nothing with GDK/Quartz */
2206         add_option (S_("Preferences|GUI"), new FontScalingOptions (_ui_config));
2207 #endif
2208
2209         add_option (S_("GUI"),
2210                     new BoolOption (
2211                             "super-rapid-clock-update",
2212                             _("update transport clock display at FPS instead of every 100ms"),
2213                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_super_rapid_clock_update),
2214                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_super_rapid_clock_update)
2215                             ));
2216
2217         /* Lock GUI timeout */
2218
2219         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2220         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2221                                                 _("Lock timeout (seconds)"),
2222                                                 lts,
2223                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_lock_gui_after_seconds),
2224                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_lock_gui_after_seconds)
2225                         );
2226         slts->scale().set_digits (0);
2227         Gtkmm2ext::UI::instance()->set_tip
2228                 (slts->tip_widget(),
2229                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2230         add_option (S_("Preferences|GUI"), slts);
2231
2232         /* The names of these controls must be the same as those given in MixerStrip
2233            for the actual widgets being controlled.
2234         */
2235         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2236         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2237         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2238         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2239         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2240         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2241         
2242         add_option (
2243                 S_("Preferences|GUI"),
2244                 new VisibilityOption (
2245                         _("Mixer Strip"),
2246                         &_mixer_strip_visibility,
2247                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_mixer_strip_visibility),
2248                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_mixer_strip_visibility)
2249                         )
2250                 );
2251
2252         add_option (S_("Preferences|GUI"),
2253              new BoolOption (
2254                      "default-narrow_ms",
2255                      _("Use narrow strips in the mixer by default"),
2256                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_default_narrow_ms),
2257                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_default_narrow_ms)
2258                      ));
2259
2260         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2261
2262         ComboOption<float>* mht = new ComboOption<float> (
2263                 "meter-hold",
2264                 _("Peak hold time"),
2265                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_hold),
2266                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_hold)
2267                 );
2268
2269         mht->add (MeterHoldOff, _("off"));
2270         mht->add (MeterHoldShort, _("short"));
2271         mht->add (MeterHoldMedium, _("medium"));
2272         mht->add (MeterHoldLong, _("long"));
2273
2274         add_option (S_("Preferences|Metering"), mht);
2275
2276         ComboOption<float>* mfo = new ComboOption<float> (
2277                 "meter-falloff",
2278                 _("DPM fall-off"),
2279                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2280                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2281                 );
2282
2283         mfo->add (METER_FALLOFF_OFF,      _("off"));
2284         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2285         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2286         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2287         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2288         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2289         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2290         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2291         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2292
2293         add_option (S_("Preferences|Metering"), mfo);
2294
2295         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2296                 "meter-line-up-level",
2297                 _("Meter line-up level; 0dBu"),
2298                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_level),
2299                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_level)
2300                 );
2301
2302         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2303         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2304         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2305         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2306
2307         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."));
2308
2309         add_option (S_("Preferences|Metering"), mlu);
2310
2311         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2312                 "meter-line-up-din",
2313                 _("IEC1/DIN Meter line-up level; 0dBu"),
2314                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_din),
2315                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_din)
2316                 );
2317
2318         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2319         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2320         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2321         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2322
2323         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2324
2325         add_option (S_("Preferences|Metering"), mld);
2326
2327         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2328                 "meter-vu-standard",
2329                 _("VU Meter standard"),
2330                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_vu_standard),
2331                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_vu_standard)
2332                 );
2333
2334         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2335         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2336         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2337         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2338
2339         add_option (S_("Preferences|Metering"), mvu);
2340
2341         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2342         HSliderOption *mpks = new HSliderOption("meter-peak",
2343                         _("Peak threshold [dBFS]"),
2344                         mpk,
2345                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_peak),
2346                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_peak)
2347                         );
2348
2349         Gtkmm2ext::UI::instance()->set_tip
2350                 (mpks->tip_widget(),
2351                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2352
2353         add_option (S_("Preferences|Metering"), mpks);
2354
2355         add_option (S_("Preferences|Metering"),
2356              new BoolOption (
2357                      "meter-style-led",
2358                      _("LED meter style"),
2359                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_style_led),
2360                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_style_led)
2361                      ));
2362
2363         /* and now the theme manager */
2364
2365         ThemeManager* tm = manage (new ThemeManager);
2366         add_page (_("Theme"), *tm);
2367 }
2368
2369 void
2370 RCOptionEditor::parameter_changed (string const & p)
2371 {
2372         OptionEditor::parameter_changed (p);
2373
2374         if (p == "use-monitor-bus") {
2375                 bool const s = Config->get_use_monitor_bus ();
2376                 if (!s) {
2377                         /* we can't use this if we don't have a monitor bus */
2378                         Config->set_solo_control_is_listen_control (false);
2379                 }
2380                 _solo_control_is_listen_control->set_sensitive (s);
2381                 _listen_position->set_sensitive (s);
2382         } else if (p == "sync-source") {
2383                 _sync_source->set_sensitive (true);
2384                 if (_session) {
2385                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2386                 }
2387                 switch(Config->get_sync_source()) {
2388                 case ARDOUR::MTC:
2389                 case ARDOUR::LTC:
2390                         _sync_genlock->set_sensitive (true);
2391                         _sync_framerate->set_sensitive (true);
2392                         _sync_source_2997->set_sensitive (true);
2393                         break;
2394                 default:
2395                         _sync_genlock->set_sensitive (false);
2396                         _sync_framerate->set_sensitive (false);
2397                         _sync_source_2997->set_sensitive (false);
2398                         break;
2399                 }
2400         } else if (p == "send-ltc") {
2401                 bool const s = Config->get_send_ltc ();
2402                 _ltc_send_continuously->set_sensitive (s);
2403                 _ltc_volume_slider->set_sensitive (s);
2404         }
2405 }
2406
2407 void RCOptionEditor::ltc_generator_volume_changed () {
2408         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2409 }
2410
2411 void
2412 RCOptionEditor::populate_sync_options ()
2413 {
2414         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2415
2416         _sync_source->clear ();
2417
2418         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2419                 _sync_source->add (*i, sync_source_to_string (*i));
2420         }
2421 }