f9b9b3784052bf17bc77c80eba473197ab27cced
[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 SpinOption<float> (
2071                             "midi-readahead",
2072                             _("MIDI read-ahead time (seconds)"),
2073                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2074                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2075                             0.1, 10, 0.1, 1,
2076                             "", 1.0, 1
2077                             ));
2078
2079         add_option (_("MIDI"),
2080                     new BoolOption (
2081                             "send-midi-clock",
2082                             _("Send MIDI Clock"),
2083                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2084                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2085                             ));
2086
2087         add_option (_("MIDI"),
2088                     new BoolOption (
2089                             "send-mtc",
2090                             _("Send MIDI Time Code"),
2091                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2092                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2093                             ));
2094
2095         add_option (_("MIDI"),
2096                     new SpinOption<int> (
2097                             "mtc-qf-speed-tolerance",
2098                             _("Percentage either side of normal transport speed to transmit MTC"),
2099                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2100                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2101                             0, 20, 1, 5
2102                             ));
2103
2104         add_option (_("MIDI"),
2105                     new BoolOption (
2106                             "mmc-control",
2107                             _("Obey MIDI Machine Control commands"),
2108                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2109                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2110                             ));
2111
2112         add_option (_("MIDI"),
2113                     new BoolOption (
2114                             "send-mmc",
2115                             _("Send MIDI Machine Control commands"),
2116                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2117                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2118                             ));
2119
2120         add_option (_("MIDI"),
2121                     new BoolOption (
2122                             "midi-feedback",
2123                             _("Send MIDI control feedback"),
2124                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2125                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2126                             ));
2127
2128         add_option (_("MIDI"),
2129              new SpinOption<uint8_t> (
2130                      "mmc-receive-device-id",
2131                      _("Inbound MMC device ID"),
2132                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2133                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2134                      0, 128, 1, 10
2135                      ));
2136
2137         add_option (_("MIDI"),
2138              new SpinOption<uint8_t> (
2139                      "mmc-send-device-id",
2140                      _("Outbound MMC device ID"),
2141                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2142                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2143                      0, 128, 1, 10
2144                      ));
2145
2146         add_option (_("MIDI"),
2147              new SpinOption<int32_t> (
2148                      "initial-program-change",
2149                      _("Initial program change"),
2150                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2151                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2152                      -1, 65536, 1, 10
2153                      ));
2154
2155         add_option (_("MIDI"),
2156                     new BoolOption (
2157                             "display-first-midi-bank-as-zero",
2158                             _("Display first MIDI bank/program as 0"),
2159                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2160                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2161                             ));
2162
2163         add_option (_("MIDI"),
2164              new BoolOption (
2165                      "never-display-periodic-midi",
2166                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2167                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_never_display_periodic_midi),
2168                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_never_display_periodic_midi)
2169                      ));
2170
2171         add_option (_("MIDI"),
2172              new BoolOption (
2173                      "sound-midi-notes",
2174                      _("Sound MIDI notes as they are selected"),
2175                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_sound_midi_notes),
2176                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_sound_midi_notes)
2177                      ));
2178
2179         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2180
2181         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2182                 "midi-audition-synth-uri",
2183                 _("Midi Audition Synth (LV2)"),
2184                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2185                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2186                 );
2187
2188         audition_synth->add(X_(""), _("None"));
2189         PluginInfoList all_plugs;
2190         PluginManager& manager (PluginManager::instance());
2191 #ifdef LV2_SUPPORT
2192         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2193
2194         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2195                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2196                 if (!(*i)->is_instrument()) continue;
2197                 if ((*i)->type != ARDOUR::LV2) continue;
2198                 audition_synth->add((*i)->unique_id, (*i)->name);
2199         }
2200 #endif
2201
2202         add_option (_("MIDI"), audition_synth);
2203
2204         /* USER INTERACTION */
2205
2206         if (getenv ("ARDOUR_BUNDLED")) {
2207                 add_option (_("User interaction"), 
2208                             new BoolOption (
2209                                     "enable-translation",
2210                                     string_compose (_("Use translations of %1 messages\n"
2211                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2212                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2213                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2214                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2215         }
2216
2217         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2218
2219         add_option (_("User interaction"), new KeyboardOptions);
2220
2221         /* Control Surfaces */
2222
2223         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2224
2225         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2226                 "remote-model",
2227                 _("Control surface remote ID"),
2228                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2229                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2230                 );
2231
2232         rm->add (UserOrdered, _("assigned by user"));
2233         rm->add (MixerOrdered, _("follows order of mixer"));
2234
2235         add_option (_("Control Surfaces"), rm);
2236
2237         /* VIDEO Timeline */
2238         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2239
2240 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2241         /* Plugin options (currrently VST only) */
2242         add_option (_("Plugins"), new PluginOptions (_rc_config, _ui_config));
2243 #endif
2244
2245         /* INTERFACE */
2246
2247         add_option (S_("Preferences|GUI"),
2248              new BoolOption (
2249                      "widget-prelight",
2250                      _("Graphically indicate mouse pointer hovering over various widgets"),
2251                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_widget_prelight),
2252                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_widget_prelight)
2253                      ));
2254
2255 #ifdef TOOLTIPS_GOT_FIXED
2256         add_option (S_("Preferences|GUI"),
2257              new BoolOption (
2258                      "use-tooltips",
2259                      _("Show tooltips if mouse hovers over a control"),
2260                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_use_tooltips),
2261                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_use_tooltips)
2262                      ));
2263 #endif
2264
2265         add_option (S_("Preferences|GUI"),
2266              new BoolOption (
2267                      "show-name-highlight",
2268                      _("Use name highlight bars in region displays (requires a restart)"),
2269                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_name_highlight),
2270                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_name_highlight)
2271                      ));
2272
2273 #ifndef GTKOSX
2274         /* font scaling does nothing with GDK/Quartz */
2275         add_option (S_("Preferences|GUI"), new FontScalingOptions (_ui_config));
2276 #endif
2277
2278         add_option (S_("GUI"),
2279                     new BoolOption (
2280                             "super-rapid-clock-update",
2281                             _("update transport clock display at FPS instead of every 100ms"),
2282                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_super_rapid_clock_update),
2283                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_super_rapid_clock_update)
2284                             ));
2285
2286         /* Lock GUI timeout */
2287
2288         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2289         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2290                                                 _("Lock timeout (seconds)"),
2291                                                 lts,
2292                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_lock_gui_after_seconds),
2293                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_lock_gui_after_seconds)
2294                         );
2295         slts->scale().set_digits (0);
2296         Gtkmm2ext::UI::instance()->set_tip
2297                 (slts->tip_widget(),
2298                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2299         add_option (S_("Preferences|GUI"), slts);
2300
2301         /* The names of these controls must be the same as those given in MixerStrip
2302            for the actual widgets being controlled.
2303         */
2304         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2305         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2306         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2307         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2308         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2309         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2310         
2311         add_option (
2312                 S_("Preferences|GUI"),
2313                 new VisibilityOption (
2314                         _("Mixer Strip"),
2315                         &_mixer_strip_visibility,
2316                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_mixer_strip_visibility),
2317                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_mixer_strip_visibility)
2318                         )
2319                 );
2320
2321         add_option (S_("Preferences|GUI"),
2322              new BoolOption (
2323                      "default-narrow_ms",
2324                      _("Use narrow strips in the mixer by default"),
2325                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_default_narrow_ms),
2326                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_default_narrow_ms)
2327                      ));
2328
2329         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2330
2331         ComboOption<float>* mht = new ComboOption<float> (
2332                 "meter-hold",
2333                 _("Peak hold time"),
2334                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_hold),
2335                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_hold)
2336                 );
2337
2338         mht->add (MeterHoldOff, _("off"));
2339         mht->add (MeterHoldShort, _("short"));
2340         mht->add (MeterHoldMedium, _("medium"));
2341         mht->add (MeterHoldLong, _("long"));
2342
2343         add_option (S_("Preferences|Metering"), mht);
2344
2345         ComboOption<float>* mfo = new ComboOption<float> (
2346                 "meter-falloff",
2347                 _("DPM fall-off"),
2348                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2349                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2350                 );
2351
2352         mfo->add (METER_FALLOFF_OFF,      _("off"));
2353         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2354         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2355         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2356         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2357         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2358         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2359         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2360         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2361
2362         add_option (S_("Preferences|Metering"), mfo);
2363
2364         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2365                 "meter-line-up-level",
2366                 _("Meter line-up level; 0dBu"),
2367                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_level),
2368                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_level)
2369                 );
2370
2371         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2372         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2373         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2374         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2375
2376         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."));
2377
2378         add_option (S_("Preferences|Metering"), mlu);
2379
2380         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2381                 "meter-line-up-din",
2382                 _("IEC1/DIN Meter line-up level; 0dBu"),
2383                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_din),
2384                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_din)
2385                 );
2386
2387         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2388         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2389         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2390         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2391
2392         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2393
2394         add_option (S_("Preferences|Metering"), mld);
2395
2396         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2397                 "meter-vu-standard",
2398                 _("VU Meter standard"),
2399                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_vu_standard),
2400                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_vu_standard)
2401                 );
2402
2403         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2404         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2405         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2406         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2407
2408         add_option (S_("Preferences|Metering"), mvu);
2409
2410         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2411         HSliderOption *mpks = new HSliderOption("meter-peak",
2412                         _("Peak threshold [dBFS]"),
2413                         mpk,
2414                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_peak),
2415                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_peak)
2416                         );
2417
2418         Gtkmm2ext::UI::instance()->set_tip
2419                 (mpks->tip_widget(),
2420                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2421
2422         add_option (S_("Preferences|Metering"), mpks);
2423
2424         add_option (S_("Preferences|Metering"),
2425              new BoolOption (
2426                      "meter-style-led",
2427                      _("LED meter style"),
2428                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_style_led),
2429                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_style_led)
2430                      ));
2431
2432         /* and now the theme manager */
2433
2434         ThemeManager* tm = manage (new ThemeManager);
2435         add_page (_("Theme"), *tm);
2436 }
2437
2438 void
2439 RCOptionEditor::parameter_changed (string const & p)
2440 {
2441         OptionEditor::parameter_changed (p);
2442
2443         if (p == "use-monitor-bus") {
2444                 bool const s = Config->get_use_monitor_bus ();
2445                 if (!s) {
2446                         /* we can't use this if we don't have a monitor bus */
2447                         Config->set_solo_control_is_listen_control (false);
2448                 }
2449                 _solo_control_is_listen_control->set_sensitive (s);
2450                 _listen_position->set_sensitive (s);
2451         } else if (p == "sync-source") {
2452                 _sync_source->set_sensitive (true);
2453                 if (_session) {
2454                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2455                 }
2456                 switch(Config->get_sync_source()) {
2457                 case ARDOUR::MTC:
2458                 case ARDOUR::LTC:
2459                         _sync_genlock->set_sensitive (true);
2460                         _sync_framerate->set_sensitive (true);
2461                         _sync_source_2997->set_sensitive (true);
2462                         break;
2463                 default:
2464                         _sync_genlock->set_sensitive (false);
2465                         _sync_framerate->set_sensitive (false);
2466                         _sync_source_2997->set_sensitive (false);
2467                         break;
2468                 }
2469         } else if (p == "send-ltc") {
2470                 bool const s = Config->get_send_ltc ();
2471                 _ltc_send_continuously->set_sensitive (s);
2472                 _ltc_volume_slider->set_sensitive (s);
2473         }
2474 }
2475
2476 void RCOptionEditor::ltc_generator_volume_changed () {
2477         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2478 }
2479
2480 void
2481 RCOptionEditor::populate_sync_options ()
2482 {
2483         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2484
2485         _sync_source->clear ();
2486
2487         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2488                 _sync_source->add (*i, sync_source_to_string (*i));
2489         }
2490 }