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