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