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