move utility functions into a dedicated namespace
[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
1364         tsf = new BoolOption (
1365                      "loop-is-mode",
1366                      _("Play loop is a transport mode"),
1367                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
1368                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
1369                      );
1370         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1371                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
1372                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
1373         add_option (_("Transport"), tsf);
1374         
1375         tsf = new BoolOption (
1376                      "create-xrun-marker",
1377                      _("Create markers where xruns occur"),
1378                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1379                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1380                      );
1381         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1382         add_option (_("Transport"), tsf);
1383
1384         tsf = new BoolOption (
1385                      "stop-at-session-end",
1386                      _("Stop at the end of the session"),
1387                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1388                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1389                      );
1390         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1391                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1392                                                               "when it reaches the current session end marker\n\n"
1393                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1394                                                             PROGRAM_NAME));
1395         add_option (_("Transport"), tsf);
1396
1397         tsf = new BoolOption (
1398                      "seamless-loop",
1399                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1400                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1401                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1402                      );
1403         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1404                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1405                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
1406                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
1407                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
1408         add_option (_("Transport"), tsf);
1409
1410         tsf = new BoolOption (
1411                      "disable-disarm-during-roll",
1412                      _("Disable per-track record disarm while rolling"),
1413                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1414                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1415                      );
1416         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"));
1417         add_option (_("Transport"), tsf);
1418
1419         tsf = new BoolOption (
1420                      "quieten_at_speed",
1421                      _("12dB gain reduction during fast-forward and fast-rewind"),
1422                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1423                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1424                      );
1425         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1426                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1427         add_option (_("Transport"), tsf);
1428
1429         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1430
1431         _sync_source = new ComboOption<SyncSource> (
1432                 "sync-source",
1433                 _("External timecode source"),
1434                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1435                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1436                 );
1437
1438         populate_sync_options ();
1439         add_option (_("Transport"), _sync_source);
1440
1441         _sync_framerate = new BoolOption (
1442                      "timecode-sync-frame-rate",
1443                      _("Match session video frame rate to external timecode"),
1444                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1445                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1446                      );
1447         Gtkmm2ext::UI::instance()->set_tip 
1448                 (_sync_framerate->tip_widget(),
1449                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1450                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1451                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1452                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1453                                    "timecode standard and the session standard."), PROGRAM_NAME));
1454
1455         add_option (_("Transport"), _sync_framerate);
1456
1457         _sync_genlock = new BoolOption (
1458                 "timecode-source-is-synced",
1459                 _("External timecode is sync locked"),
1460                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1461                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1462                 );
1463         Gtkmm2ext::UI::instance()->set_tip 
1464                 (_sync_genlock->tip_widget(), 
1465                  _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface."));
1466
1467
1468         add_option (_("Transport"), _sync_genlock);
1469
1470         _sync_source_2997 = new BoolOption (
1471                 "timecode-source-2997",
1472                 _("Lock to 29.9700 fps instead of 30000/1001"),
1473                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1474                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1475                 );
1476         Gtkmm2ext::UI::instance()->set_tip
1477                 (_sync_source_2997->tip_widget(),
1478                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1479                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1480                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1481                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1482                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1483                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1484                          ));
1485
1486         add_option (_("Transport"), _sync_source_2997);
1487
1488         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1489
1490         _ltc_port = new ComboStringOption (
1491                 "ltc-source-port",
1492                 _("LTC incoming port"),
1493                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1494                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1495                 );
1496
1497         vector<string> physical_inputs;
1498         physical_inputs.push_back (_("None"));
1499         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1500         _ltc_port->set_popdown_strings (physical_inputs);
1501
1502         add_option (_("Transport"), _ltc_port);
1503
1504         // TODO; rather disable this button than not compile it..
1505         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1506
1507         add_option (_("Transport"),
1508                     new BoolOption (
1509                             "send-ltc",
1510                             _("Enable LTC generator"),
1511                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1512                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1513                             ));
1514
1515         _ltc_send_continuously = new BoolOption (
1516                             "ltc-send-continuously",
1517                             _("Send LTC while stopped"),
1518                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1519                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1520                             );
1521         Gtkmm2ext::UI::instance()->set_tip
1522                 (_ltc_send_continuously->tip_widget(),
1523                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
1524         add_option (_("Transport"), _ltc_send_continuously);
1525
1526         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1527         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1528         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1529         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1530
1531         Gtkmm2ext::UI::instance()->set_tip
1532                 (_ltc_volume_slider->tip_widget(),
1533                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1534
1535         add_option (_("Transport"), _ltc_volume_slider);
1536         parameter_changed ("send-ltc");
1537
1538         parameter_changed ("sync-source");
1539
1540         /* EDITOR */
1541
1542         add_option (_("Editor"),
1543              new BoolOption (
1544                      "link-region-and-track-selection",
1545                      _("Link selection of regions and tracks"),
1546                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1547                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1548                      ));
1549
1550         add_option (_("Editor"),
1551              new BoolOption (
1552                      "automation-follows-regions",
1553                      _("Move relevant automation when audio regions are moved"),
1554                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1555                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1556                      ));
1557
1558         add_option (_("Editor"),
1559              new BoolOption (
1560                      "show-track-meters",
1561                      _("Show meters on tracks in the editor"),
1562                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1563                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1564                      ));
1565
1566         add_option (_("Editor"),
1567              new BoolOption (
1568                      "show-editor-meter",
1569                      _("Display master-meter in the toolbar"),
1570                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_editor_meter),
1571                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_editor_meter)
1572                      ));
1573
1574         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
1575                         "default-fade-shape",
1576                         _("Default fade shape"),
1577                         sigc::mem_fun (*_rc_config,
1578                                 &RCConfiguration::get_default_fade_shape),
1579                         sigc::mem_fun (*_rc_config,
1580                                 &RCConfiguration::set_default_fade_shape)
1581                         );
1582
1583         fadeshape->add (FadeLinear,
1584                         _("Linear (for highly correlated material)"));
1585         fadeshape->add (FadeConstantPower, _("Constant power"));
1586         fadeshape->add (FadeSymmetric, _("Symmetric"));
1587         fadeshape->add (FadeSlow, _("Slow"));
1588         fadeshape->add (FadeFast, _("Fast"));
1589
1590         add_option (_("Editor"), fadeshape);
1591
1592
1593         bco = new BoolComboOption (
1594                      "use-overlap-equivalency",
1595                      _("Regions in active edit groups are edited together"),
1596                      _("whenever they overlap in time"),
1597                      _("only if they have identical length, position and origin"),
1598                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1599                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1600                      );
1601
1602         add_option (_("Editor"), bco);
1603
1604         add_option (_("Editor"),
1605              new BoolOption (
1606                      "rubberbanding-snaps-to-grid",
1607                      _("Make rubberband selection rectangle snap to the grid"),
1608                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1609                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1610                      ));
1611
1612         add_option (_("Editor"),
1613              new BoolOption (
1614                      "show-waveforms",
1615                      _("Show waveforms in regions"),
1616                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1617                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1618                      ));
1619
1620         add_option (_("Editor"),
1621              new BoolComboOption (
1622                      "show-region-gain-envelopes",
1623                      _("Show gain envelopes in audio regions"),
1624                      _("in all modes"),
1625                      _("only in region gain mode"),
1626                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1627                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1628                      ));
1629
1630         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1631                 "waveform-scale",
1632                 _("Waveform scale"),
1633                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1634                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1635                 );
1636
1637         wfs->add (Linear, _("linear"));
1638         wfs->add (Logarithmic, _("logarithmic"));
1639
1640         add_option (_("Editor"), wfs);
1641
1642         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1643                 "waveform-shape",
1644                 _("Waveform shape"),
1645                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1646                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1647                 );
1648
1649         wfsh->add (Traditional, _("traditional"));
1650         wfsh->add (Rectified, _("rectified"));
1651
1652         add_option (_("Editor"), wfsh);
1653
1654         add_option (_("Editor"), new ClipLevelOptions (_rc_config));
1655
1656         add_option (_("Editor"),
1657              new BoolOption (
1658                      "show-waveforms-while-recording",
1659                      _("Show waveforms for audio while it is being recorded"),
1660                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1661                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1662                      ));
1663
1664         add_option (_("Editor"),
1665                     new BoolOption (
1666                             "show-zoom-tools",
1667                             _("Show zoom toolbar"),
1668                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1669                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1670                             ));
1671
1672         add_option (_("Editor"),
1673                     new BoolOption (
1674                             "update-editor-during-summary-drag",
1675                             _("Update editor window during drags of the summary"),
1676                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1677                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1678                             ));
1679
1680         add_option (_("Editor"),
1681              new BoolOption (
1682                      "link-editor-and-mixer-selection",
1683                      _("Synchronise editor and mixer selection"),
1684                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1685                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1686                      ));
1687
1688         bo = new BoolOption (
1689                      "name-new-markers",
1690                      _("Name new markers"),
1691                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1692                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1693                 );
1694         
1695         add_option (_("Editor"), bo);
1696         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."
1697                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1698
1699         add_option (_("Editor"),
1700             new BoolOption (
1701                     "autoscroll-editor",
1702                     _("Auto-scroll editor window when dragging near its edges"),
1703                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1704                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1705                     ));
1706
1707         /* AUDIO */
1708
1709         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1710
1711         add_option (_("Audio"), new BufferingOptions (_rc_config));
1712
1713         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1714
1715         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1716                 "monitoring-model",
1717                 _("Record monitoring handled by"),
1718                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1719                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1720                 );
1721
1722         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
1723                 mm->add (HardwareMonitoring, _("via Audio Driver"));
1724         }
1725
1726         string prog (PROGRAM_NAME);
1727         boost::algorithm::to_lower (prog);
1728         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
1729         mm->add (ExternalMonitoring, _("audio hardware"));
1730
1731         add_option (_("Audio"), mm);
1732
1733         add_option (_("Audio"),
1734              new BoolOption (
1735                      "tape-machine-mode",
1736                      _("Tape machine mode"),
1737                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1738                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1739                      ));
1740
1741         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1742
1743         add_option (_("Audio"),
1744                     new BoolOption (
1745                             "auto-connect-standard-busses",
1746                             _("Auto-connect master/monitor busses"),
1747                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1748                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1749                             ));
1750
1751         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1752                 "input-auto-connect",
1753                 _("Connect track inputs"),
1754                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1755                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1756                 );
1757
1758         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1759         iac->add (ManualConnect, _("manually"));
1760
1761         add_option (_("Audio"), iac);
1762
1763         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1764                 "output-auto-connect",
1765                 _("Connect track and bus outputs"),
1766                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1767                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1768                 );
1769
1770         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1771         oac->add (AutoConnectMaster, _("automatically to master bus"));
1772         oac->add (ManualConnect, _("manually"));
1773
1774         add_option (_("Audio"), oac);
1775
1776         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1777
1778         add_option (_("Audio"),
1779              new BoolOption (
1780                      "denormal-protection",
1781                      _("Use DC bias to protect against denormals"),
1782                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1783                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1784                      ));
1785
1786         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1787                 "denormal-model",
1788                 _("Processor handling"),
1789                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1790                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1791                 );
1792
1793         dm->add (DenormalNone, _("no processor handling"));
1794
1795         FPU fpu;
1796
1797         if (fpu.has_flush_to_zero()) {
1798                 dm->add (DenormalFTZ, _("use FlushToZero"));
1799         }
1800
1801         if (fpu.has_denormals_are_zero()) {
1802                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1803         }
1804
1805         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1806                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1807         }
1808
1809         add_option (_("Audio"), dm);
1810
1811         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1812
1813         add_option (_("Audio"),
1814              new BoolOption (
1815                      "plugins-stop-with-transport",
1816                      _("Silence plugins when the transport is stopped"),
1817                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1818                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1819                      ));
1820
1821         add_option (_("Audio"),
1822              new BoolOption (
1823                      "new-plugins-active",
1824                      _("Make new plugins active"),
1825                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1826                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1827                      ));
1828
1829         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
1830
1831         add_option (_("Audio"),
1832              new BoolOption (
1833                      "auto-analyse-audio",
1834                      _("Enable automatic analysis of audio"),
1835                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1836                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1837                      ));
1838
1839         add_option (_("Audio"),
1840              new BoolOption (
1841                      "replicate-missing-region-channels",
1842                      _("Replicate missing region channels"),
1843                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1844                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1845                      ));
1846
1847         /* SOLO AND MUTE */
1848
1849         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
1850
1851         add_option (_("Solo / mute"),
1852              new FaderOption (
1853                      "solo-mute-gain",
1854                      _("Solo-in-place mute cut (dB)"),
1855                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1856                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1857                      ));
1858
1859         _solo_control_is_listen_control = new BoolOption (
1860                 "solo-control-is-listen-control",
1861                 _("Solo controls are Listen controls"),
1862                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1863                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1864                 );
1865
1866         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1867
1868         _listen_position = new ComboOption<ListenPosition> (
1869                 "listen-position",
1870                 _("Listen Position"),
1871                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1872                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1873                 );
1874
1875         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1876         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1877
1878         add_option (_("Solo / mute"), _listen_position);
1879
1880         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1881                 "pfl-position",
1882                 _("PFL signals come from"),
1883                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1884                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1885                 );
1886
1887         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1888         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1889
1890         add_option (_("Solo / mute"), pp);
1891
1892         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1893                 "afl-position",
1894                 _("AFL signals come from"),
1895                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1896                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1897                 );
1898
1899         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1900         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1901
1902         add_option (_("Solo / mute"), pa);
1903
1904         parameter_changed ("use-monitor-bus");
1905
1906         add_option (_("Solo / mute"),
1907              new BoolOption (
1908                      "exclusive-solo",
1909                      _("Exclusive solo"),
1910                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1911                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1912                      ));
1913
1914         add_option (_("Solo / mute"),
1915              new BoolOption (
1916                      "show-solo-mutes",
1917                      _("Show solo muting"),
1918                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1919                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1920                      ));
1921
1922         add_option (_("Solo / mute"),
1923              new BoolOption (
1924                      "solo-mute-override",
1925                      _("Soloing overrides muting"),
1926                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1927                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1928                      ));
1929
1930         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1931
1932         add_option (_("Solo / mute"),
1933              new BoolOption (
1934                      "mute-affects-pre-fader",
1935                      _("Mute affects pre-fader sends"),
1936                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1937                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1938                      ));
1939
1940         add_option (_("Solo / mute"),
1941              new BoolOption (
1942                      "mute-affects-post-fader",
1943                      _("Mute affects post-fader sends"),
1944                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1945                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1946                      ));
1947
1948         add_option (_("Solo / mute"),
1949              new BoolOption (
1950                      "mute-affects-control-outs",
1951                      _("Mute affects control outputs"),
1952                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1953                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1954                      ));
1955
1956         add_option (_("Solo / mute"),
1957              new BoolOption (
1958                      "mute-affects-main-outs",
1959                      _("Mute affects main outputs"),
1960                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1961                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1962                      ));
1963
1964         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
1965
1966         add_option (_("Solo / mute"),
1967              new BoolOption (
1968                      "link-send-and-route-panner",
1969                      _("Link panners of Aux and External Sends with main panner by default"),
1970                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
1971                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
1972                      ));
1973
1974         add_option (_("MIDI"),
1975                     new BoolOption (
1976                             "send-midi-clock",
1977                             _("Send MIDI Clock"),
1978                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1979                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1980                             ));
1981
1982         add_option (_("MIDI"),
1983                     new BoolOption (
1984                             "send-mtc",
1985                             _("Send MIDI Time Code"),
1986                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1987                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1988                             ));
1989
1990         add_option (_("MIDI"),
1991                     new SpinOption<int> (
1992                             "mtc-qf-speed-tolerance",
1993                             _("Percentage either side of normal transport speed to transmit MTC"),
1994                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1995                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1996                             0, 20, 1, 5
1997                             ));
1998
1999         add_option (_("MIDI"),
2000                     new BoolOption (
2001                             "mmc-control",
2002                             _("Obey MIDI Machine Control commands"),
2003                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2004                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2005                             ));
2006
2007         add_option (_("MIDI"),
2008                     new BoolOption (
2009                             "send-mmc",
2010                             _("Send MIDI Machine Control commands"),
2011                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2012                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2013                             ));
2014
2015         add_option (_("MIDI"),
2016                     new BoolOption (
2017                             "midi-feedback",
2018                             _("Send MIDI control feedback"),
2019                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2020                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2021                             ));
2022
2023         add_option (_("MIDI"),
2024              new SpinOption<uint8_t> (
2025                      "mmc-receive-device-id",
2026                      _("Inbound MMC device ID"),
2027                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2028                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2029                      0, 128, 1, 10
2030                      ));
2031
2032         add_option (_("MIDI"),
2033              new SpinOption<uint8_t> (
2034                      "mmc-send-device-id",
2035                      _("Outbound MMC device ID"),
2036                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2037                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2038                      0, 128, 1, 10
2039                      ));
2040
2041         add_option (_("MIDI"),
2042              new SpinOption<int32_t> (
2043                      "initial-program-change",
2044                      _("Initial program change"),
2045                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2046                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2047                      -1, 65536, 1, 10
2048                      ));
2049
2050         add_option (_("MIDI"),
2051                     new BoolOption (
2052                             "display-first-midi-bank-as-zero",
2053                             _("Display first MIDI bank/program as 0"),
2054                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2055                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2056                             ));
2057
2058         add_option (_("MIDI"),
2059              new BoolOption (
2060                      "never-display-periodic-midi",
2061                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2062                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
2063                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
2064                      ));
2065
2066         add_option (_("MIDI"),
2067              new BoolOption (
2068                      "sound-midi-notes",
2069                      _("Sound MIDI notes as they are selected"),
2070                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
2071                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
2072                      ));
2073
2074         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2075
2076         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2077                 "midi-audition-synth-uri",
2078                 _("Midi Audition Synth (LV2)"),
2079                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2080                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2081                 );
2082
2083         audition_synth->add(X_(""), _("None"));
2084         PluginInfoList all_plugs;
2085         PluginManager& manager (PluginManager::instance());
2086 #ifdef LV2_SUPPORT
2087         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2088
2089         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2090                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2091                 if (!(*i)->is_instrument()) continue;
2092                 if ((*i)->type != ARDOUR::LV2) continue;
2093                 audition_synth->add((*i)->unique_id, (*i)->name);
2094         }
2095 #endif
2096
2097         add_option (_("MIDI"), audition_synth);
2098
2099         /* USER INTERACTION */
2100
2101         if (getenv ("ARDOUR_BUNDLED")) {
2102                 add_option (_("User interaction"), 
2103                             new BoolOption (
2104                                     "enable-translation",
2105                                     string_compose (_("Use translations of %1 messages\n"
2106                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2107                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2108                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2109                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2110         }
2111
2112         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2113
2114         add_option (_("User interaction"), new KeyboardOptions);
2115
2116         /* Control Surfaces */
2117
2118         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2119
2120         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2121                 "remote-model",
2122                 _("Control surface remote ID"),
2123                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2124                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2125                 );
2126
2127         rm->add (UserOrdered, _("assigned by user"));
2128         rm->add (MixerOrdered, _("follows order of mixer"));
2129
2130         add_option (_("Control Surfaces"), rm);
2131
2132         /* VIDEO Timeline */
2133         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2134
2135 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
2136         /* Plugin options (currrently VST only) */
2137         add_option (_("Plugins"), new PluginOptions (_rc_config));
2138 #endif
2139
2140         /* INTERFACE */
2141
2142         add_option (S_("Preferences|GUI"),
2143              new BoolOption (
2144                      "widget-prelight",
2145                      _("Graphically indicate mouse pointer hovering over various widgets"),
2146                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
2147                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
2148                      ));
2149
2150         add_option (S_("Preferences|GUI"),
2151              new BoolOption (
2152                      "use-tooltips",
2153                      _("Show tooltips if mouse hovers over a control"),
2154                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
2155                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
2156                      ));
2157
2158         add_option (S_("Preferences|GUI"),
2159              new BoolOption (
2160                      "show-name-highlight",
2161                      _("Use name highlight bars in region displays"),
2162                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_name_highlight),
2163                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_name_highlight)
2164                      ));
2165
2166 #ifndef GTKOSX
2167         /* font scaling does nothing with GDK/Quartz */
2168         add_option (S_("Preferences|GUI"), new FontScalingOptions (_rc_config));
2169 #endif
2170
2171         add_option (S_("GUI"),
2172                     new BoolOption (
2173                             "super-rapid-clock-update",
2174                             _("update transport clock display every 40ms instead of every 100ms"),
2175                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_super_rapid_clock_update),
2176                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_super_rapid_clock_update)
2177                             ));
2178
2179         /* Lock GUI timeout */
2180
2181         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2182         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2183                                                 _("Lock timeout (seconds)"),
2184                                                 lts,
2185                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_lock_gui_after_seconds),
2186                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_lock_gui_after_seconds)
2187                         );
2188         slts->scale().set_digits (0);
2189         Gtkmm2ext::UI::instance()->set_tip
2190                 (slts->tip_widget(),
2191                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2192         add_option (S_("Preferences|GUI"), slts);
2193
2194         /* The names of these controls must be the same as those given in MixerStrip
2195            for the actual widgets being controlled.
2196         */
2197         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2198         _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
2199         _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
2200         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2201         _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
2202         _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
2203         
2204         add_option (
2205                 S_("Preferences|GUI"),
2206                 new VisibilityOption (
2207                         _("Mixer Strip"),
2208                         &_mixer_strip_visibility,
2209                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
2210                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
2211                         )
2212                 );
2213
2214         add_option (S_("Preferences|GUI"),
2215              new BoolOption (
2216                      "default-narrow_ms",
2217                      _("Use narrow strips in the mixer by default"),
2218                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
2219                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
2220                      ));
2221
2222         add_option (S_("Preferences|GUI"), new OptionEditorHeading (_("Metering")));
2223
2224         ComboOption<float>* mht = new ComboOption<float> (
2225                 "meter-hold",
2226                 _("Peak hold time"),
2227                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
2228                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
2229                 );
2230
2231         mht->add (MeterHoldOff, _("off"));
2232         mht->add (MeterHoldShort, _("short"));
2233         mht->add (MeterHoldMedium, _("medium"));
2234         mht->add (MeterHoldLong, _("long"));
2235
2236         add_option (S_("Preferences|GUI"), mht);
2237
2238         ComboOption<float>* mfo = new ComboOption<float> (
2239                 "meter-falloff",
2240                 _("DPM fall-off"),
2241                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2242                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2243                 );
2244
2245         mfo->add (METER_FALLOFF_OFF,      _("off"));
2246         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2247         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2248         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2249         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2250         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2251         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2252         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2253         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2254
2255         add_option (S_("Preferences|GUI"), mfo);
2256
2257         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2258                 "meter-line-up-level",
2259                 _("Meter line-up level; 0dBu"),
2260                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_level),
2261                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_level)
2262                 );
2263
2264         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2265         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2266         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2267         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2268
2269         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."));
2270
2271         add_option (S_("Preferences|GUI"), mlu);
2272
2273         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2274                 "meter-line-up-din",
2275                 _("IEC1/DIN Meter line-up level; 0dBu"),
2276                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_din),
2277                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_din)
2278                 );
2279
2280         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2281         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2282         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2283         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2284
2285         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2286
2287         add_option (S_("Preferences|GUI"), mld);
2288
2289         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2290                 "meter-vu-standard",
2291                 _("VU Meter standard"),
2292                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_vu_standard),
2293                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_vu_standard)
2294                 );
2295
2296         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2297         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2298         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2299         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2300
2301         add_option (S_("Preferences|GUI"), mvu);
2302
2303         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2304         HSliderOption *mpks = new HSliderOption("meter-peak",
2305                         _("Peak threshold [dBFS]"),
2306                         mpk,
2307                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_peak),
2308                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_peak)
2309                         );
2310
2311         Gtkmm2ext::UI::instance()->set_tip
2312                 (mpks->tip_widget(),
2313                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2314
2315         add_option (S_("Preferences|GUI"), mpks);
2316
2317         add_option (S_("Preferences|GUI"),
2318              new BoolOption (
2319                      "meter-style-led",
2320                      _("LED meter style"),
2321                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_style_led),
2322                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_style_led)
2323                      ));
2324
2325 }
2326
2327 void
2328 RCOptionEditor::parameter_changed (string const & p)
2329 {
2330         OptionEditor::parameter_changed (p);
2331
2332         if (p == "use-monitor-bus") {
2333                 bool const s = Config->get_use_monitor_bus ();
2334                 if (!s) {
2335                         /* we can't use this if we don't have a monitor bus */
2336                         Config->set_solo_control_is_listen_control (false);
2337                 }
2338                 _solo_control_is_listen_control->set_sensitive (s);
2339                 _listen_position->set_sensitive (s);
2340         } else if (p == "sync-source") {
2341                 _sync_source->set_sensitive (true);
2342                 if (_session) {
2343                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2344                 }
2345                 switch(Config->get_sync_source()) {
2346                 case ARDOUR::MTC:
2347                 case ARDOUR::LTC:
2348                         _sync_genlock->set_sensitive (true);
2349                         _sync_framerate->set_sensitive (true);
2350                         _sync_source_2997->set_sensitive (true);
2351                         break;
2352                 default:
2353                         _sync_genlock->set_sensitive (false);
2354                         _sync_framerate->set_sensitive (false);
2355                         _sync_source_2997->set_sensitive (false);
2356                         break;
2357                 }
2358         } else if (p == "send-ltc") {
2359                 bool const s = Config->get_send_ltc ();
2360                 _ltc_send_continuously->set_sensitive (s);
2361                 _ltc_volume_slider->set_sensitive (s);
2362         }
2363 }
2364
2365 void RCOptionEditor::ltc_generator_volume_changed () {
2366         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2367 }
2368
2369 void
2370 RCOptionEditor::populate_sync_options ()
2371 {
2372         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2373
2374         _sync_source->clear ();
2375
2376         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2377                 _sync_source->add (*i, sync_source_to_string (*i));
2378         }
2379 }