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