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