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