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