Relative Snap -make it activated by the tertiary modifier during drag.
[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 (_("GUI and 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 (_("Adjusting the scale 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                 ss.str("");
1102                 ss << "<b>" << _("Audio Unit") << "</b>";
1103                 l = manage (left_aligned_label (ss.str()));
1104                 l->set_use_markup (true);
1105                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1106                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1107
1108                 t->attach (_discover_au_on_start, 0, 2, n, n+1); ++n;
1109                 _discover_au_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_au_on_start_toggled));
1110                 Gtkmm2ext::UI::instance()->set_tip (_discover_au_on_start,
1111                                             _("<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."));
1112
1113                 ++n;
1114                 b = manage (new Button (_("Clear AU Cache")));
1115                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_cache_clicked));
1116                 t->attach (*b, 0, 1, n, n+1, FILL);
1117
1118                 b = manage (new Button (_("Clear AU Blacklist")));
1119                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_blacklist_clicked));
1120                 t->attach (*b, 1, 2, n, n+1, FILL);
1121                 ++n;
1122 #endif
1123
1124                 _box->pack_start (*t,true,true);
1125         }
1126
1127         void parameter_changed (string const & p) {
1128                 if (p == "show-plugin-scan-window") {
1129                         bool const x = _ui_config->get_show_plugin_scan_window();
1130                         _display_plugin_scan_progress.set_active (x);
1131                 }
1132                 else if (p == "discover-vst-on-start") {
1133                         bool const x = _rc_config->get_discover_vst_on_start();
1134                         _discover_vst_on_start.set_active (x);
1135                 }
1136                 else if (p == "vst-scan-timeout") {
1137                         int const x = _rc_config->get_vst_scan_timeout();
1138                         _timeout_adjustment.set_value (x);
1139                 }
1140                 else if (p == "discover-audio-units") {
1141                         bool const x = _rc_config->get_discover_audio_units();
1142                         _discover_au_on_start.set_active (x);
1143                 }
1144         }
1145
1146         void set_state_from_config () {
1147                 parameter_changed ("show-plugin-scan-window");
1148                 parameter_changed ("discover-vst-on-start");
1149                 parameter_changed ("vst-scan-timeout");
1150                 parameter_changed ("discover-audio-units");
1151         }
1152
1153 private:
1154         RCConfiguration* _rc_config;
1155         UIConfiguration* _ui_config;
1156         CheckButton _display_plugin_scan_progress;
1157         CheckButton _discover_vst_on_start;
1158         CheckButton _discover_au_on_start;
1159         Adjustment _timeout_adjustment;
1160         HScale _timeout_slider;
1161
1162         void display_plugin_scan_progress_toggled () {
1163                 bool const x = _display_plugin_scan_progress.get_active();
1164                 _ui_config->set_show_plugin_scan_window(x);
1165         }
1166
1167         void discover_vst_on_start_toggled () {
1168                 bool const x = _discover_vst_on_start.get_active();
1169                 _rc_config->set_discover_vst_on_start(x);
1170         }
1171
1172         void discover_au_on_start_toggled () {
1173                 bool const x = _discover_au_on_start.get_active();
1174                 _rc_config->set_discover_audio_units(x);
1175         }
1176
1177         void timeout_changed () {
1178                 int x = floor(_timeout_adjustment.get_value());
1179                 _rc_config->set_vst_scan_timeout(x);
1180         }
1181
1182         void clear_vst_cache_clicked () {
1183                 PluginManager::instance().clear_vst_cache();
1184         }
1185
1186         void clear_vst_blacklist_clicked () {
1187                 PluginManager::instance().clear_vst_blacklist();
1188         }
1189
1190         void clear_au_cache_clicked () {
1191                 PluginManager::instance().clear_au_cache();
1192         }
1193
1194         void clear_au_blacklist_clicked () {
1195                 PluginManager::instance().clear_au_blacklist();
1196         }
1197
1198
1199         void edit_vst_path_clicked () {
1200                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1201                                 _("Set Windows VST Search Path"),
1202                                 _rc_config->get_plugin_path_vst(),
1203                                 PluginManager::instance().get_default_windows_vst_path()
1204                         );
1205                 ResponseType r = (ResponseType) pd->run ();
1206                 pd->hide();
1207                 if (r == RESPONSE_ACCEPT) {
1208                         _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
1209                 }
1210                 delete pd;
1211         }
1212
1213         // todo consolidate with edit_vst_path_clicked..
1214         void edit_lxvst_path_clicked () {
1215                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1216                                 _("Set Linux VST Search Path"),
1217                                 _rc_config->get_plugin_path_lxvst(),
1218                                 PluginManager::instance().get_default_lxvst_path()
1219                                 );
1220                 ResponseType r = (ResponseType) pd->run ();
1221                 pd->hide();
1222                 if (r == RESPONSE_ACCEPT) {
1223                         _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
1224                 }
1225                 delete pd;
1226         }
1227
1228         void refresh_clicked () {
1229                 PluginManager::instance().refresh();
1230         }
1231 };
1232
1233
1234 /** A class which allows control of visibility of some editor components usign
1235  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
1236  *  which has the correct members, but with null widget pointers.  This
1237  *  class allows the user to set visibility of the members, the details
1238  *  of which are stored in a configuration variable which can be watched
1239  *  by parts of the editor that actually contain the widgets whose visibility
1240  *  is being controlled.
1241  */
1242
1243 class VisibilityOption : public Option
1244 {
1245 public:
1246         /** @param name User-visible name for this group.
1247          *  @param g `Dummy' VisibilityGroup (as described above).
1248          *  @param get Method to get the value of the appropriate configuration variable.
1249          *  @param set Method to set the value of the appropriate configuration variable.
1250          */
1251         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1252                 : Option (g->get_state_name(), name)
1253                 , _heading (name)
1254                 , _visibility_group (g)
1255                 , _get (get)
1256                 , _set (set)
1257         {
1258                 /* Watch for changes made by the user to our members */
1259                 _visibility_group->VisibilityChanged.connect_same_thread (
1260                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1261                         );
1262         }
1263
1264         void set_state_from_config ()
1265         {
1266                 /* Set our state from the current configuration */
1267                 _visibility_group->set_state (_get ());
1268         }
1269
1270         void add_to_page (OptionEditorPage* p)
1271         {
1272                 _heading.add_to_page (p);
1273                 add_widget_to_page (p, _visibility_group->list_view ());
1274         }
1275
1276         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1277
1278 private:
1279         void changed ()
1280         {
1281                 /* The user has changed something, so reflect this change
1282                    in the RCConfiguration.
1283                 */
1284                 _set (_visibility_group->get_state_value ());
1285         }
1286         
1287         OptionEditorHeading _heading;
1288         VisibilityGroup* _visibility_group;
1289         sigc::slot<std::string> _get;
1290         sigc::slot<bool, std::string> _set;
1291         PBD::ScopedConnection _visibility_group_connection;
1292 };
1293
1294
1295
1296 RCOptionEditor::RCOptionEditor ()
1297         : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
1298         , _rc_config (Config)
1299         , _ui_config (ARDOUR_UI::config())
1300         , _mixer_strip_visibility ("mixer-element-visibility")
1301 {
1302         /* MISC */
1303
1304         uint32_t hwcpus = hardware_concurrency ();
1305         BoolOption* bo;
1306         BoolComboOption* bco;
1307
1308         if (hwcpus > 1) {
1309                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
1310
1311                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
1312                         "processor-usage",
1313                         _("Signal processing uses"),
1314                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
1315                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
1316                         );
1317
1318                 procs->add (-1, _("all but one processor"));
1319                 procs->add (0, _("all available processors"));
1320
1321                 for (uint32_t i = 1; i <= hwcpus; ++i) {
1322                         procs->add (i, string_compose (_("%1 processors"), i));
1323                 }
1324
1325                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
1326
1327                 add_option (_("Misc"), procs);
1328         }
1329
1330         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
1331
1332         add_option (_("Misc"), new UndoOptions (_rc_config));
1333
1334         add_option (_("Misc"),
1335              new BoolOption (
1336                      "verify-remove-last-capture",
1337                      _("Verify removal of last capture"),
1338                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
1339                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
1340                      ));
1341
1342         add_option (_("Misc"),
1343              new BoolOption (
1344                      "periodic-safety-backups",
1345                      _("Make periodic backups of the session file"),
1346                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1347                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1348                      ));
1349
1350         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
1351
1352         add_option (_("Misc"),
1353              new BoolOption (
1354                      "only-copy-imported-files",
1355                      _("Always copy imported files"),
1356                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_only_copy_imported_files),
1357                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_only_copy_imported_files)
1358                      ));
1359
1360         add_option (_("Misc"), new DirectoryOption (
1361                             X_("default-session-parent-dir"),
1362                             _("Default folder for new sessions:"),
1363                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
1364                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
1365                             ));
1366
1367         add_option (_("Misc"),
1368              new SpinOption<uint32_t> (
1369                      "max-recent-sessions",
1370                      _("Maximum number of recent sessions"),
1371                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
1372                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
1373                      0, 1000, 1, 20
1374                      ));
1375
1376         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
1377
1378         add_option (_("Misc"), new ClickOptions (_rc_config, this));
1379
1380         add_option (_("Misc"),
1381              new FaderOption (
1382                      "click-gain",
1383                      _("Click gain level"),
1384                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
1385                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
1386                      ));
1387
1388         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
1389
1390         add_option (_("Misc"),
1391              new SpinOption<double> (
1392                      "automation-thinning-factor",
1393                      _("Thinning factor (larger value => less data)"),
1394                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
1395                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
1396                      0, 1000, 1, 20
1397                      ));
1398
1399         add_option (_("Misc"),
1400              new SpinOption<double> (
1401                      "automation-interval-msecs",
1402                      _("Automation sampling interval (milliseconds)"),
1403                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
1404                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
1405                      1, 1000, 1, 20
1406                      ));
1407
1408         /* TRANSPORT */
1409
1410         BoolOption* tsf;
1411
1412         tsf = new BoolOption (
1413                      "latched-record-enable",
1414                      _("Keep record-enable engaged on stop"),
1415                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
1416                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
1417                      );
1418         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1419         add_option (_("Transport"), tsf);
1420
1421         tsf = new BoolOption (
1422                      "loop-is-mode",
1423                      _("Play loop is a transport mode"),
1424                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
1425                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
1426                      );
1427         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1428                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
1429                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
1430         add_option (_("Transport"), tsf);
1431         
1432         tsf = new BoolOption (
1433                      "stop-recording-on-xrun",
1434                      _("Stop recording when an xrun occurs"),
1435                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1436                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1437                      );
1438         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1439                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
1440                                                             PROGRAM_NAME));
1441         add_option (_("Transport"), tsf);
1442
1443         tsf = new BoolOption (
1444                      "create-xrun-marker",
1445                      _("Create markers where xruns occur"),
1446                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1447                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1448                      );
1449         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1450         add_option (_("Transport"), tsf);
1451
1452         tsf = new BoolOption (
1453                      "stop-at-session-end",
1454                      _("Stop at the end of the session"),
1455                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1456                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1457                      );
1458         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1459                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1460                                                               "when it reaches the current session end marker\n\n"
1461                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1462                                                             PROGRAM_NAME));
1463         add_option (_("Transport"), tsf);
1464
1465         tsf = new BoolOption (
1466                      "seamless-loop",
1467                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1468                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1469                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1470                      );
1471         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1472                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1473                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
1474                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
1475                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
1476         add_option (_("Transport"), tsf);
1477
1478         tsf = new BoolOption (
1479                      "disable-disarm-during-roll",
1480                      _("Disable per-track record disarm while rolling"),
1481                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1482                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1483                      );
1484         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"));
1485         add_option (_("Transport"), tsf);
1486
1487         tsf = new BoolOption (
1488                      "quieten_at_speed",
1489                      _("12dB gain reduction during fast-forward and fast-rewind"),
1490                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1491                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1492                      );
1493         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1494                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1495         add_option (_("Transport"), tsf);
1496
1497         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1498
1499         _sync_source = new ComboOption<SyncSource> (
1500                 "sync-source",
1501                 _("External timecode source"),
1502                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1503                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1504                 );
1505
1506         add_option (_("Transport"), _sync_source);
1507
1508         _sync_framerate = new BoolOption (
1509                      "timecode-sync-frame-rate",
1510                      _("Match session video frame rate to external timecode"),
1511                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1512                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1513                      );
1514         Gtkmm2ext::UI::instance()->set_tip 
1515                 (_sync_framerate->tip_widget(),
1516                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1517                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1518                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1519                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1520                                    "timecode standard and the session standard."), PROGRAM_NAME));
1521
1522         add_option (_("Transport"), _sync_framerate);
1523
1524         _sync_genlock = new BoolOption (
1525                 "timecode-source-is-synced",
1526                 _("Sync-lock timecode to clock (disable drift compensation)"),
1527                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1528                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1529                 );
1530         Gtkmm2ext::UI::instance()->set_tip 
1531                 (_sync_genlock->tip_widget(),
1532                  string_compose (_("<b>When enabled</b> %1 will never varispeed when slaved to external timecode. "
1533                                    "Sync Lock indicates that the selected external timecode source shares clock-sync "
1534                                    "(Black &amp; Burst, Wordclock, etc) with the audio interface. "
1535                                    "This option disables drift compensation. The transport speed is fixed at 1.0. "
1536                                    "Vari-speed LTC will be ignored and cause drift."
1537                                    "\n\n"
1538                                    "<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
1539                                    "timecode sources shares clock sync."
1540                                   ), PROGRAM_NAME));
1541
1542
1543         add_option (_("Transport"), _sync_genlock);
1544
1545         _sync_source_2997 = new BoolOption (
1546                 "timecode-source-2997",
1547                 _("Lock to 29.9700 fps instead of 30000/1001"),
1548                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1549                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1550                 );
1551         Gtkmm2ext::UI::instance()->set_tip
1552                 (_sync_source_2997->tip_widget(),
1553                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1554                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1555                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1556                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1557                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1558                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1559                          ));
1560
1561         add_option (_("Transport"), _sync_source_2997);
1562
1563         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1564
1565         _ltc_port = new ComboStringOption (
1566                 "ltc-source-port",
1567                 _("LTC incoming port"),
1568                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1569                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1570                 );
1571
1572         vector<string> physical_inputs;
1573         physical_inputs.push_back (_("None"));
1574         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1575         _ltc_port->set_popdown_strings (physical_inputs);
1576
1577         populate_sync_options ();
1578
1579         add_option (_("Transport"), _ltc_port);
1580
1581         // TODO; rather disable this button than not compile it..
1582         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1583
1584         add_option (_("Transport"),
1585                     new BoolOption (
1586                             "send-ltc",
1587                             _("Enable LTC generator"),
1588                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1589                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1590                             ));
1591
1592         _ltc_send_continuously = new BoolOption (
1593                             "ltc-send-continuously",
1594                             _("Send LTC while stopped"),
1595                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1596                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1597                             );
1598         Gtkmm2ext::UI::instance()->set_tip
1599                 (_ltc_send_continuously->tip_widget(),
1600                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
1601         add_option (_("Transport"), _ltc_send_continuously);
1602
1603         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1604         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1605         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1606         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1607
1608         Gtkmm2ext::UI::instance()->set_tip
1609                 (_ltc_volume_slider->tip_widget(),
1610                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1611
1612         add_option (_("Transport"), _ltc_volume_slider);
1613         parameter_changed ("send-ltc");
1614
1615         parameter_changed ("sync-source");
1616
1617         /* EDITOR */
1618
1619         add_option (S_("Editor"),
1620              new BoolOption (
1621                      "draggable-playhead",
1622                      _("Allow dragging of playhead"),
1623                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_draggable_playhead),
1624                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_draggable_playhead)
1625                      ));
1626
1627         add_option (_("Editor"),
1628              new BoolOption (
1629                      "automation-follows-regions",
1630                      _("Move relevant automation when audio regions are moved"),
1631                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1632                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1633                      ));
1634
1635         add_option (_("Editor"),
1636              new BoolOption (
1637                      "show-track-meters",
1638                      _("Show meters on tracks in the editor"),
1639                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_track_meters),
1640                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_track_meters)
1641                      ));
1642
1643         add_option (_("Editor"),
1644              new BoolOption (
1645                      "show-editor-meter",
1646                      _("Display master-meter in the toolbar"),
1647                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_editor_meter),
1648                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_editor_meter)
1649                      ));
1650
1651         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
1652                         "default-fade-shape",
1653                         _("Default fade shape"),
1654                         sigc::mem_fun (*_rc_config,
1655                                 &RCConfiguration::get_default_fade_shape),
1656                         sigc::mem_fun (*_rc_config,
1657                                 &RCConfiguration::set_default_fade_shape)
1658                         );
1659
1660         fadeshape->add (FadeLinear,
1661                         _("Linear (for highly correlated material)"));
1662         fadeshape->add (FadeConstantPower, _("Constant power"));
1663         fadeshape->add (FadeSymmetric, _("Symmetric"));
1664         fadeshape->add (FadeSlow, _("Slow"));
1665         fadeshape->add (FadeFast, _("Fast"));
1666
1667         add_option (_("Editor"), fadeshape);
1668
1669
1670         bco = new BoolComboOption (
1671                      "use-overlap-equivalency",
1672                      _("Regions in active edit groups are edited together"),
1673                      _("whenever they overlap in time"),
1674                      _("only if they have identical length, position and origin"),
1675                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1676                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1677                      );
1678
1679         add_option (_("Editor"), bco);
1680
1681         ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
1682                 "layer-model",
1683                 _("Layering model"),
1684                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
1685                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
1686                 );
1687
1688         lm->add (LaterHigher, _("later is higher"));
1689         lm->add (Manual, _("manual layering"));
1690         add_option (_("Editor"), lm);
1691
1692         add_option (_("Editor"),
1693              new BoolOption (
1694                      "rubberbanding-snaps-to-grid",
1695                      _("Make rubberband selection rectangle snap to the grid"),
1696                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_rubberbanding_snaps_to_grid),
1697                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_rubberbanding_snaps_to_grid)
1698                      ));
1699
1700         add_option (_("Editor"),
1701              new BoolOption (
1702                      "show-waveforms",
1703                      _("Show waveforms in regions"),
1704                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms),
1705                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms)
1706                      ));
1707
1708         add_option (_("Editor"),
1709              new BoolComboOption (
1710                      "show-region-gain-envelopes",
1711                      _("Show gain envelopes in audio regions"),
1712                      _("in all modes"),
1713                      _("only in region gain mode"),
1714                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_region_gain),
1715                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_region_gain)
1716                      ));
1717
1718         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1719                 "waveform-scale",
1720                 _("Waveform scale"),
1721                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_scale),
1722                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_scale)
1723                 );
1724
1725         wfs->add (Linear, _("linear"));
1726         wfs->add (Logarithmic, _("logarithmic"));
1727
1728         add_option (_("Editor"), wfs);
1729
1730         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1731                 "waveform-shape",
1732                 _("Waveform shape"),
1733                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_shape),
1734                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_shape)
1735                 );
1736
1737         wfsh->add (Traditional, _("traditional"));
1738         wfsh->add (Rectified, _("rectified"));
1739
1740         add_option (_("Editor"), wfsh);
1741
1742         add_option (_("Editor"), new ClipLevelOptions (_ui_config));
1743
1744         add_option (_("Editor"),
1745              new BoolOption (
1746                      "show-waveforms-while-recording",
1747                      _("Show waveforms for audio while it is being recorded"),
1748                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms_while_recording),
1749                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms_while_recording)
1750                      ));
1751
1752         add_option (_("Editor"),
1753                     new BoolOption (
1754                             "show-zoom-tools",
1755                             _("Show zoom toolbar"),
1756                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_zoom_tools),
1757                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_zoom_tools)
1758                             ));
1759
1760         add_option (_("Editor"),
1761                     new BoolOption (
1762                             "update-editor-during-summary-drag",
1763                             _("Update editor window during drags of the summary"),
1764                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_update_editor_during_summary_drag),
1765                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_update_editor_during_summary_drag)
1766                             ));
1767
1768         bo = new BoolOption (
1769                      "name-new-markers",
1770                      _("Name new markers"),
1771                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_name_new_markers),
1772                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_name_new_markers)
1773                 );
1774         
1775         add_option (_("Editor"), bo);
1776         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."
1777                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1778
1779         add_option (_("Editor"),
1780             new BoolOption (
1781                     "autoscroll-editor",
1782                     _("Auto-scroll editor window when dragging near its edges"),
1783                     sigc::mem_fun (*_ui_config, &UIConfiguration::get_autoscroll_editor),
1784                     sigc::mem_fun (*_ui_config, &UIConfiguration::set_autoscroll_editor)
1785                     ));
1786
1787         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
1788                     "region-selection-after-split",
1789                     _("After splitting selected regions, select"),
1790                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
1791                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
1792
1793         // TODO: decide which of these modes are really useful
1794         rsas->add(None, _("no regions"));
1795         // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
1796         // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
1797         rsas->add(NewlyCreatedBoth, _("newly-created regions"));
1798         // rsas->add(Existing, _("unmodified regions in the existing selection"));
1799         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
1800         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
1801         rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
1802
1803         add_option (_("Editor"), rsas);
1804
1805
1806         /* AUDIO */
1807
1808         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1809
1810         add_option (_("Audio"), new BufferingOptions (_rc_config));
1811
1812         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1813
1814         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1815                 "monitoring-model",
1816                 _("Record monitoring handled by"),
1817                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1818                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1819                 );
1820
1821         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
1822                 mm->add (HardwareMonitoring, _("via Audio Driver"));
1823         }
1824
1825         string prog (PROGRAM_NAME);
1826         boost::algorithm::to_lower (prog);
1827         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
1828         mm->add (ExternalMonitoring, _("audio hardware"));
1829
1830         add_option (_("Audio"), mm);
1831
1832         add_option (_("Audio"),
1833              new BoolOption (
1834                      "tape-machine-mode",
1835                      _("Tape machine mode"),
1836                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1837                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1838                      ));
1839
1840         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1841
1842         add_option (_("Audio"),
1843                     new BoolOption (
1844                             "auto-connect-standard-busses",
1845                             _("Auto-connect master/monitor busses"),
1846                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1847                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1848                             ));
1849
1850         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1851                 "input-auto-connect",
1852                 _("Connect track inputs"),
1853                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1854                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1855                 );
1856
1857         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1858         iac->add (ManualConnect, _("manually"));
1859
1860         add_option (_("Audio"), iac);
1861
1862         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1863                 "output-auto-connect",
1864                 _("Connect track and bus outputs"),
1865                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1866                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1867                 );
1868
1869         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1870         oac->add (AutoConnectMaster, _("automatically to master bus"));
1871         oac->add (ManualConnect, _("manually"));
1872
1873         add_option (_("Audio"), oac);
1874
1875         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1876
1877         add_option (_("Audio"),
1878              new BoolOption (
1879                      "denormal-protection",
1880                      _("Use DC bias to protect against denormals"),
1881                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1882                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1883                      ));
1884
1885         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1886                 "denormal-model",
1887                 _("Processor handling"),
1888                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1889                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1890                 );
1891
1892         int dmsize = 1;
1893         dm->add (DenormalNone, _("no processor handling"));
1894
1895         FPU fpu;
1896
1897         if (fpu.has_flush_to_zero()) {
1898                 ++dmsize;
1899                 dm->add (DenormalFTZ, _("use FlushToZero"));
1900         } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
1901                 _rc_config->set_denormal_model(DenormalNone);
1902         }
1903
1904         if (fpu.has_denormals_are_zero()) {
1905                 ++dmsize;
1906                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1907         } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
1908                 _rc_config->set_denormal_model(DenormalNone);
1909         }
1910
1911         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1912                 ++dmsize;
1913                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1914         } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
1915                 _rc_config->set_denormal_model(DenormalNone);
1916         }
1917
1918         if (dmsize == 1) {
1919                 dm->set_sensitive(false);
1920         }
1921
1922         add_option (_("Audio"), dm);
1923
1924         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1925
1926         add_option (_("Audio"),
1927              new BoolOption (
1928                      "plugins-stop-with-transport",
1929                      _("Silence plugins when the transport is stopped"),
1930                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1931                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1932                      ));
1933
1934         add_option (_("Audio"),
1935              new BoolOption (
1936                      "new-plugins-active",
1937                      _("Make new plugins active"),
1938                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1939                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1940                      ));
1941
1942         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
1943
1944         add_option (_("Audio"),
1945              new BoolOption (
1946                      "auto-analyse-audio",
1947                      _("Enable automatic analysis of audio"),
1948                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1949                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1950                      ));
1951
1952         add_option (_("Audio"),
1953              new BoolOption (
1954                      "replicate-missing-region-channels",
1955                      _("Replicate missing region channels"),
1956                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1957                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1958                      ));
1959
1960         /* SOLO AND MUTE */
1961
1962         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
1963
1964         add_option (_("Solo / mute"),
1965              new FaderOption (
1966                      "solo-mute-gain",
1967                      _("Solo-in-place mute cut (dB)"),
1968                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1969                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1970                      ));
1971
1972         _solo_control_is_listen_control = new BoolOption (
1973                 "solo-control-is-listen-control",
1974                 _("Solo controls are Listen controls"),
1975                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1976                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1977                 );
1978
1979         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1980
1981         _listen_position = new ComboOption<ListenPosition> (
1982                 "listen-position",
1983                 _("Listen Position"),
1984                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1985                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1986                 );
1987
1988         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1989         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1990
1991         add_option (_("Solo / mute"), _listen_position);
1992
1993         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1994                 "pfl-position",
1995                 _("PFL signals come from"),
1996                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1997                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1998                 );
1999
2000         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2001         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2002
2003         add_option (_("Solo / mute"), pp);
2004
2005         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2006                 "afl-position",
2007                 _("AFL signals come from"),
2008                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2009                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2010                 );
2011
2012         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2013         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2014
2015         add_option (_("Solo / mute"), pa);
2016
2017         parameter_changed ("use-monitor-bus");
2018
2019         add_option (_("Solo / mute"),
2020              new BoolOption (
2021                      "exclusive-solo",
2022                      _("Exclusive solo"),
2023                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2024                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2025                      ));
2026
2027         add_option (_("Solo / mute"),
2028              new BoolOption (
2029                      "show-solo-mutes",
2030                      _("Show solo muting"),
2031                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2032                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2033                      ));
2034
2035         add_option (_("Solo / mute"),
2036              new BoolOption (
2037                      "solo-mute-override",
2038                      _("Soloing overrides muting"),
2039                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2040                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2041                      ));
2042
2043         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
2044
2045         add_option (_("Solo / mute"),
2046              new BoolOption (
2047                      "mute-affects-pre-fader",
2048                      _("Mute affects pre-fader sends"),
2049                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2050                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2051                      ));
2052
2053         add_option (_("Solo / mute"),
2054              new BoolOption (
2055                      "mute-affects-post-fader",
2056                      _("Mute affects post-fader sends"),
2057                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2058                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2059                      ));
2060
2061         add_option (_("Solo / mute"),
2062              new BoolOption (
2063                      "mute-affects-control-outs",
2064                      _("Mute affects control outputs"),
2065                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2066                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2067                      ));
2068
2069         add_option (_("Solo / mute"),
2070              new BoolOption (
2071                      "mute-affects-main-outs",
2072                      _("Mute affects main outputs"),
2073                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2074                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2075                      ));
2076
2077         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
2078
2079         add_option (_("Solo / mute"),
2080              new BoolOption (
2081                      "link-send-and-route-panner",
2082                      _("Link panners of Aux and External Sends with main panner by default"),
2083                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2084                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2085                      ));
2086
2087         add_option (_("MIDI"),
2088                     new SpinOption<float> (
2089                             "midi-readahead",
2090                             _("MIDI read-ahead time (seconds)"),
2091                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2092                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2093                             0.1, 10, 0.1, 1,
2094                             "", 1.0, 1
2095                             ));
2096
2097         add_option (_("MIDI"),
2098                     new BoolOption (
2099                             "send-midi-clock",
2100                             _("Send MIDI Clock"),
2101                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2102                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2103                             ));
2104
2105         add_option (_("MIDI"),
2106                     new BoolOption (
2107                             "send-mtc",
2108                             _("Send MIDI Time Code"),
2109                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2110                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2111                             ));
2112
2113         add_option (_("MIDI"),
2114                     new SpinOption<int> (
2115                             "mtc-qf-speed-tolerance",
2116                             _("Percentage either side of normal transport speed to transmit MTC"),
2117                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2118                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2119                             0, 20, 1, 5
2120                             ));
2121
2122         add_option (_("MIDI"),
2123                     new BoolOption (
2124                             "mmc-control",
2125                             _("Obey MIDI Machine Control commands"),
2126                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2127                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2128                             ));
2129
2130         add_option (_("MIDI"),
2131                     new BoolOption (
2132                             "send-mmc",
2133                             _("Send MIDI Machine Control commands"),
2134                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2135                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2136                             ));
2137
2138         add_option (_("MIDI"),
2139                     new BoolOption (
2140                             "midi-feedback",
2141                             _("Send MIDI control feedback"),
2142                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2143                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2144                             ));
2145
2146         add_option (_("MIDI"),
2147              new SpinOption<uint8_t> (
2148                      "mmc-receive-device-id",
2149                      _("Inbound MMC device ID"),
2150                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2151                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2152                      0, 128, 1, 10
2153                      ));
2154
2155         add_option (_("MIDI"),
2156              new SpinOption<uint8_t> (
2157                      "mmc-send-device-id",
2158                      _("Outbound MMC device ID"),
2159                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2160                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2161                      0, 128, 1, 10
2162                      ));
2163
2164         add_option (_("MIDI"),
2165              new SpinOption<int32_t> (
2166                      "initial-program-change",
2167                      _("Initial program change"),
2168                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2169                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2170                      -1, 65536, 1, 10
2171                      ));
2172
2173         add_option (_("MIDI"),
2174                     new BoolOption (
2175                             "display-first-midi-bank-as-zero",
2176                             _("Display first MIDI bank/program as 0"),
2177                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2178                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2179                             ));
2180
2181         add_option (_("MIDI"),
2182              new BoolOption (
2183                      "never-display-periodic-midi",
2184                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2185                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_never_display_periodic_midi),
2186                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_never_display_periodic_midi)
2187                      ));
2188
2189         add_option (_("MIDI"),
2190              new BoolOption (
2191                      "sound-midi-notes",
2192                      _("Sound MIDI notes as they are selected"),
2193                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_sound_midi_notes),
2194                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_sound_midi_notes)
2195                      ));
2196
2197         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2198
2199         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2200                 "midi-audition-synth-uri",
2201                 _("Midi Audition Synth (LV2)"),
2202                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2203                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2204                 );
2205
2206         audition_synth->add(X_(""), _("None"));
2207         PluginInfoList all_plugs;
2208         PluginManager& manager (PluginManager::instance());
2209 #ifdef LV2_SUPPORT
2210         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2211
2212         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2213                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2214                 if (!(*i)->is_instrument()) continue;
2215                 if ((*i)->type != ARDOUR::LV2) continue;
2216                 audition_synth->add((*i)->unique_id, (*i)->name);
2217         }
2218 #endif
2219
2220         add_option (_("MIDI"), audition_synth);
2221
2222         /* USER INTERACTION */
2223
2224         if (
2225 #ifdef PLATFORM_WINDOWS
2226                         true
2227 #else
2228                         getenv ("ARDOUR_BUNDLED")
2229 #endif
2230            )
2231         {
2232                 add_option (_("User interaction"), 
2233                             new BoolOption (
2234                                     "enable-translation",
2235                                     string_compose (_("Use translations of %1 messages\n"
2236                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2237                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2238                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2239                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2240         }
2241
2242         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2243
2244         add_option (_("User interaction"), new KeyboardOptions);
2245
2246         /* Control Surfaces */
2247
2248         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2249
2250         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2251                 "remote-model",
2252                 _("Control surface remote ID"),
2253                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2254                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2255                 );
2256
2257         rm->add (UserOrdered, _("assigned by user"));
2258         rm->add (MixerOrdered, _("follows order of mixer"));
2259
2260         add_option (_("Control Surfaces"), rm);
2261
2262         /* VIDEO Timeline */
2263         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2264
2265 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2266         /* Plugin options (currrently VST only) */
2267         add_option (_("Plugins"), new PluginOptions (_rc_config, _ui_config));
2268 #endif
2269
2270         /* INTERFACE */
2271
2272         add_option (S_("Preferences|GUI"),
2273              new BoolOption (
2274                      "widget-prelight",
2275                      _("Graphically indicate mouse pointer hovering over various widgets"),
2276                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_widget_prelight),
2277                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_widget_prelight)
2278                      ));
2279
2280 #ifdef TOOLTIPS_GOT_FIXED
2281         add_option (S_("Preferences|GUI"),
2282              new BoolOption (
2283                      "use-tooltips",
2284                      _("Show tooltips if mouse hovers over a control"),
2285                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_use_tooltips),
2286                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_use_tooltips)
2287                      ));
2288 #endif
2289
2290         add_option (S_("Preferences|GUI"),
2291              new BoolOption (
2292                      "show-name-highlight",
2293                      _("Use name highlight bars in region displays (requires a restart)"),
2294                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_name_highlight),
2295                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_name_highlight)
2296                      ));
2297
2298 #ifndef GTKOSX
2299         /* font scaling does nothing with GDK/Quartz */
2300         add_option (S_("Preferences|GUI"), new FontScalingOptions (_ui_config));
2301 #endif
2302
2303         add_option (S_("GUI"),
2304                     new BoolOption (
2305                             "super-rapid-clock-update",
2306                             _("update transport clock display at FPS instead of every 100ms"),
2307                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_super_rapid_clock_update),
2308                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_super_rapid_clock_update)
2309                             ));
2310
2311         /* Lock GUI timeout */
2312
2313         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2314         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2315                                                 _("Lock timeout (seconds)"),
2316                                                 lts,
2317                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_lock_gui_after_seconds),
2318                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_lock_gui_after_seconds)
2319                         );
2320         slts->scale().set_digits (0);
2321         Gtkmm2ext::UI::instance()->set_tip
2322                 (slts->tip_widget(),
2323                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2324         add_option (S_("Preferences|GUI"), slts);
2325
2326         /* The names of these controls must be the same as those given in MixerStrip
2327            for the actual widgets being controlled.
2328         */
2329         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2330         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2331         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2332         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2333         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2334         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2335         
2336         add_option (
2337                 S_("Preferences|GUI"),
2338                 new VisibilityOption (
2339                         _("Mixer Strip"),
2340                         &_mixer_strip_visibility,
2341                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_mixer_strip_visibility),
2342                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_mixer_strip_visibility)
2343                         )
2344                 );
2345
2346         add_option (S_("Preferences|GUI"),
2347              new BoolOption (
2348                      "default-narrow_ms",
2349                      _("Use narrow strips in the mixer by default"),
2350                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_default_narrow_ms),
2351                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_default_narrow_ms)
2352                      ));
2353
2354         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2355
2356         ComboOption<float>* mht = new ComboOption<float> (
2357                 "meter-hold",
2358                 _("Peak hold time"),
2359                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_hold),
2360                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_hold)
2361                 );
2362
2363         mht->add (MeterHoldOff, _("off"));
2364         mht->add (MeterHoldShort, _("short"));
2365         mht->add (MeterHoldMedium, _("medium"));
2366         mht->add (MeterHoldLong, _("long"));
2367
2368         add_option (S_("Preferences|Metering"), mht);
2369
2370         ComboOption<float>* mfo = new ComboOption<float> (
2371                 "meter-falloff",
2372                 _("DPM fall-off"),
2373                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2374                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2375                 );
2376
2377         mfo->add (METER_FALLOFF_OFF,      _("off"));
2378         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2379         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2380         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2381         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2382         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2383         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2384         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2385         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2386
2387         add_option (S_("Preferences|Metering"), mfo);
2388
2389         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2390                 "meter-line-up-level",
2391                 _("Meter line-up level; 0dBu"),
2392                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_level),
2393                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_level)
2394                 );
2395
2396         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2397         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2398         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2399         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2400
2401         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."));
2402
2403         add_option (S_("Preferences|Metering"), mlu);
2404
2405         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2406                 "meter-line-up-din",
2407                 _("IEC1/DIN Meter line-up level; 0dBu"),
2408                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_din),
2409                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_din)
2410                 );
2411
2412         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2413         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2414         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2415         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2416
2417         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2418
2419         add_option (S_("Preferences|Metering"), mld);
2420
2421         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2422                 "meter-vu-standard",
2423                 _("VU Meter standard"),
2424                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_vu_standard),
2425                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_vu_standard)
2426                 );
2427
2428         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2429         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2430         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2431         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2432
2433         add_option (S_("Preferences|Metering"), mvu);
2434
2435         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2436         HSliderOption *mpks = new HSliderOption("meter-peak",
2437                         _("Peak threshold [dBFS]"),
2438                         mpk,
2439                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_peak),
2440                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_peak)
2441                         );
2442
2443         Gtkmm2ext::UI::instance()->set_tip
2444                 (mpks->tip_widget(),
2445                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2446
2447         add_option (S_("Preferences|Metering"), mpks);
2448
2449         add_option (S_("Preferences|Metering"),
2450              new BoolOption (
2451                      "meter-style-led",
2452                      _("LED meter style"),
2453                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_style_led),
2454                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_style_led)
2455                      ));
2456
2457         /* and now the theme manager */
2458
2459         ThemeManager* tm = manage (new ThemeManager);
2460         add_page (_("Theme"), *tm);
2461 }
2462
2463 void
2464 RCOptionEditor::parameter_changed (string const & p)
2465 {
2466         OptionEditor::parameter_changed (p);
2467
2468         if (p == "use-monitor-bus") {
2469                 bool const s = Config->get_use_monitor_bus ();
2470                 if (!s) {
2471                         /* we can't use this if we don't have a monitor bus */
2472                         Config->set_solo_control_is_listen_control (false);
2473                 }
2474                 _solo_control_is_listen_control->set_sensitive (s);
2475                 _listen_position->set_sensitive (s);
2476         } else if (p == "sync-source") {
2477                 _sync_source->set_sensitive (true);
2478                 if (_session) {
2479                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2480                 }
2481                 switch(Config->get_sync_source()) {
2482                 case ARDOUR::MTC:
2483                 case ARDOUR::LTC:
2484                         _sync_genlock->set_sensitive (true);
2485                         _sync_framerate->set_sensitive (true);
2486                         _sync_source_2997->set_sensitive (true);
2487                         break;
2488                 default:
2489                         _sync_genlock->set_sensitive (false);
2490                         _sync_framerate->set_sensitive (false);
2491                         _sync_source_2997->set_sensitive (false);
2492                         break;
2493                 }
2494         } else if (p == "send-ltc") {
2495                 bool const s = Config->get_send_ltc ();
2496                 _ltc_send_continuously->set_sensitive (s);
2497                 _ltc_volume_slider->set_sensitive (s);
2498         }
2499 }
2500
2501 void RCOptionEditor::ltc_generator_volume_changed () {
2502         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2503 }
2504
2505 void
2506 RCOptionEditor::populate_sync_options ()
2507 {
2508         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2509
2510         _sync_source->clear ();
2511
2512         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2513                 _sync_source->add (*i, sync_source_to_string (*i));
2514         }
2515
2516         if (sync_opts.empty()) {
2517                 _sync_source->set_sensitive(false);
2518         } else {
2519                 if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
2520                         _rc_config->set_sync_source(sync_opts.front());
2521                 }
2522         }
2523 }