fix empty/unset sync source preference.
[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         add_option (_("Transport"), _sync_source);
1507
1508         _sync_framerate = new BoolOption (
1509                      "timecode-sync-frame-rate",
1510                      _("Match session video frame rate to external timecode"),
1511                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1512                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1513                      );
1514         Gtkmm2ext::UI::instance()->set_tip 
1515                 (_sync_framerate->tip_widget(),
1516                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1517                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1518                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1519                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1520                                    "timecode standard and the session standard."), PROGRAM_NAME));
1521
1522         add_option (_("Transport"), _sync_framerate);
1523
1524         _sync_genlock = new BoolOption (
1525                 "timecode-source-is-synced",
1526                 _("Sync lock timecode to clock - Disable drift compensation."),
1527                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1528                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1529                 );
1530         Gtkmm2ext::UI::instance()->set_tip 
1531                 (_sync_genlock->tip_widget(),
1532                  string_compose (_("<b>When enabled</b> %1 will never varispeed when slaved to external timecode. "
1533                                    "Sync Lock indicates that the selected external timecode source shares clock-sync "
1534                                    "(Black &amp; Burst, Wordclock, etc) with the audio interface. "
1535                                    "This option disables drift compensation. The transport speed is fixed at 1.0."
1536                                    "Varispeed LTC will be ignored and cause drift."
1537                                    "\n\n"
1538                                    "<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
1539                                    "timecode sources shares clock sync."
1540                                   ), PROGRAM_NAME));
1541
1542
1543         add_option (_("Transport"), _sync_genlock);
1544
1545         _sync_source_2997 = new BoolOption (
1546                 "timecode-source-2997",
1547                 _("Lock to 29.9700 fps instead of 30000/1001"),
1548                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1549                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1550                 );
1551         Gtkmm2ext::UI::instance()->set_tip
1552                 (_sync_source_2997->tip_widget(),
1553                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1554                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1555                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1556                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1557                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1558                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1559                          ));
1560
1561         add_option (_("Transport"), _sync_source_2997);
1562
1563         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1564
1565         _ltc_port = new ComboStringOption (
1566                 "ltc-source-port",
1567                 _("LTC incoming port"),
1568                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1569                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1570                 );
1571
1572         vector<string> physical_inputs;
1573         physical_inputs.push_back (_("None"));
1574         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1575         _ltc_port->set_popdown_strings (physical_inputs);
1576
1577         populate_sync_options ();
1578
1579         add_option (_("Transport"), _ltc_port);
1580
1581         // TODO; rather disable this button than not compile it..
1582         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1583
1584         add_option (_("Transport"),
1585                     new BoolOption (
1586                             "send-ltc",
1587                             _("Enable LTC generator"),
1588                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1589                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1590                             ));
1591
1592         _ltc_send_continuously = new BoolOption (
1593                             "ltc-send-continuously",
1594                             _("Send LTC while stopped"),
1595                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1596                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1597                             );
1598         Gtkmm2ext::UI::instance()->set_tip
1599                 (_ltc_send_continuously->tip_widget(),
1600                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
1601         add_option (_("Transport"), _ltc_send_continuously);
1602
1603         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1604         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1605         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1606         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1607
1608         Gtkmm2ext::UI::instance()->set_tip
1609                 (_ltc_volume_slider->tip_widget(),
1610                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1611
1612         add_option (_("Transport"), _ltc_volume_slider);
1613         parameter_changed ("send-ltc");
1614
1615         parameter_changed ("sync-source");
1616
1617         /* EDITOR */
1618
1619         add_option (S_("Editor"),
1620              new BoolOption (
1621                      "draggable-playhead",
1622                      _("Allow dragging of playhead"),
1623                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_draggable_playhead),
1624                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_draggable_playhead)
1625                      ));
1626
1627         add_option (_("Editor"),
1628              new BoolOption (
1629                      "automation-follows-regions",
1630                      _("Move relevant automation when audio regions are moved"),
1631                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1632                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1633                      ));
1634
1635         add_option (_("Editor"),
1636              new BoolOption (
1637                      "show-track-meters",
1638                      _("Show meters on tracks in the editor"),
1639                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_track_meters),
1640                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_track_meters)
1641                      ));
1642
1643         add_option (_("Editor"),
1644              new BoolOption (
1645                      "show-editor-meter",
1646                      _("Display master-meter in the toolbar"),
1647                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_editor_meter),
1648                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_editor_meter)
1649                      ));
1650
1651         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
1652                         "default-fade-shape",
1653                         _("Default fade shape"),
1654                         sigc::mem_fun (*_rc_config,
1655                                 &RCConfiguration::get_default_fade_shape),
1656                         sigc::mem_fun (*_rc_config,
1657                                 &RCConfiguration::set_default_fade_shape)
1658                         );
1659
1660         fadeshape->add (FadeLinear,
1661                         _("Linear (for highly correlated material)"));
1662         fadeshape->add (FadeConstantPower, _("Constant power"));
1663         fadeshape->add (FadeSymmetric, _("Symmetric"));
1664         fadeshape->add (FadeSlow, _("Slow"));
1665         fadeshape->add (FadeFast, _("Fast"));
1666
1667         add_option (_("Editor"), fadeshape);
1668
1669
1670         bco = new BoolComboOption (
1671                      "use-overlap-equivalency",
1672                      _("Regions in active edit groups are edited together"),
1673                      _("whenever they overlap in time"),
1674                      _("only if they have identical length, position and origin"),
1675                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1676                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1677                      );
1678
1679         add_option (_("Editor"), bco);
1680
1681         add_option (_("Editor"),
1682              new BoolOption (
1683                      "rubberbanding-snaps-to-grid",
1684                      _("Make rubberband selection rectangle snap to the grid"),
1685                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_rubberbanding_snaps_to_grid),
1686                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_rubberbanding_snaps_to_grid)
1687                      ));
1688
1689         add_option (_("Editor"),
1690              new BoolOption (
1691                      "show-waveforms",
1692                      _("Show waveforms in regions"),
1693                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms),
1694                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms)
1695                      ));
1696
1697         add_option (_("Editor"),
1698              new BoolComboOption (
1699                      "show-region-gain-envelopes",
1700                      _("Show gain envelopes in audio regions"),
1701                      _("in all modes"),
1702                      _("only in region gain mode"),
1703                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_region_gain),
1704                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_region_gain)
1705                      ));
1706
1707         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1708                 "waveform-scale",
1709                 _("Waveform scale"),
1710                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_scale),
1711                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_scale)
1712                 );
1713
1714         wfs->add (Linear, _("linear"));
1715         wfs->add (Logarithmic, _("logarithmic"));
1716
1717         add_option (_("Editor"), wfs);
1718
1719         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1720                 "waveform-shape",
1721                 _("Waveform shape"),
1722                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_shape),
1723                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_shape)
1724                 );
1725
1726         wfsh->add (Traditional, _("traditional"));
1727         wfsh->add (Rectified, _("rectified"));
1728
1729         add_option (_("Editor"), wfsh);
1730
1731         add_option (_("Editor"), new ClipLevelOptions (_ui_config));
1732
1733         add_option (_("Editor"),
1734              new BoolOption (
1735                      "show-waveforms-while-recording",
1736                      _("Show waveforms for audio while it is being recorded"),
1737                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms_while_recording),
1738                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms_while_recording)
1739                      ));
1740
1741         add_option (_("Editor"),
1742                     new BoolOption (
1743                             "show-zoom-tools",
1744                             _("Show zoom toolbar"),
1745                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_zoom_tools),
1746                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_zoom_tools)
1747                             ));
1748
1749         add_option (_("Editor"),
1750                     new BoolOption (
1751                             "update-editor-during-summary-drag",
1752                             _("Update editor window during drags of the summary"),
1753                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_update_editor_during_summary_drag),
1754                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_update_editor_during_summary_drag)
1755                             ));
1756
1757         add_option (_("Editor"),
1758              new BoolOption (
1759                      "link-editor-and-mixer-selection",
1760                      _("Synchronise editor and mixer selection"),
1761                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_link_editor_and_mixer_selection),
1762                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_link_editor_and_mixer_selection)
1763                      ));
1764
1765         bo = new BoolOption (
1766                      "name-new-markers",
1767                      _("Name new markers"),
1768                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_name_new_markers),
1769                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_name_new_markers)
1770                 );
1771         
1772         add_option (_("Editor"), bo);
1773         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."
1774                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1775
1776         add_option (_("Editor"),
1777             new BoolOption (
1778                     "autoscroll-editor",
1779                     _("Auto-scroll editor window when dragging near its edges"),
1780                     sigc::mem_fun (*_ui_config, &UIConfiguration::get_autoscroll_editor),
1781                     sigc::mem_fun (*_ui_config, &UIConfiguration::set_autoscroll_editor)
1782                     ));
1783
1784         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
1785                     "region-selection-after-split",
1786                     _("After splitting selected regions, select"),
1787                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
1788                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
1789
1790         // TODO: decide which of these modes are really useful
1791         rsas->add(None, _("no regions"));
1792         // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
1793         // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
1794         rsas->add(NewlyCreatedBoth, _("newly-created regions"));
1795         // rsas->add(Existing, _("unmodified regions in the existing selection"));
1796         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
1797         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
1798         rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
1799
1800         add_option (_("Editor"), rsas);
1801
1802
1803         /* AUDIO */
1804
1805         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1806
1807         add_option (_("Audio"), new BufferingOptions (_rc_config));
1808
1809         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1810
1811         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1812                 "monitoring-model",
1813                 _("Record monitoring handled by"),
1814                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1815                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1816                 );
1817
1818         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
1819                 mm->add (HardwareMonitoring, _("via Audio Driver"));
1820         }
1821
1822         string prog (PROGRAM_NAME);
1823         boost::algorithm::to_lower (prog);
1824         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
1825         mm->add (ExternalMonitoring, _("audio hardware"));
1826
1827         add_option (_("Audio"), mm);
1828
1829         add_option (_("Audio"),
1830              new BoolOption (
1831                      "tape-machine-mode",
1832                      _("Tape machine mode"),
1833                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1834                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1835                      ));
1836
1837         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1838
1839         add_option (_("Audio"),
1840                     new BoolOption (
1841                             "auto-connect-standard-busses",
1842                             _("Auto-connect master/monitor busses"),
1843                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1844                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1845                             ));
1846
1847         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1848                 "input-auto-connect",
1849                 _("Connect track inputs"),
1850                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1851                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1852                 );
1853
1854         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1855         iac->add (ManualConnect, _("manually"));
1856
1857         add_option (_("Audio"), iac);
1858
1859         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1860                 "output-auto-connect",
1861                 _("Connect track and bus outputs"),
1862                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1863                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1864                 );
1865
1866         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1867         oac->add (AutoConnectMaster, _("automatically to master bus"));
1868         oac->add (ManualConnect, _("manually"));
1869
1870         add_option (_("Audio"), oac);
1871
1872         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1873
1874         add_option (_("Audio"),
1875              new BoolOption (
1876                      "denormal-protection",
1877                      _("Use DC bias to protect against denormals"),
1878                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1879                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1880                      ));
1881
1882         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1883                 "denormal-model",
1884                 _("Processor handling"),
1885                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1886                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1887                 );
1888
1889         int dmsize = 1;
1890         dm->add (DenormalNone, _("no processor handling"));
1891
1892         FPU fpu;
1893
1894         if (fpu.has_flush_to_zero()) {
1895                 ++dmsize;
1896                 dm->add (DenormalFTZ, _("use FlushToZero"));
1897         } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
1898                 _rc_config->set_denormal_model(DenormalNone);
1899         }
1900
1901         if (fpu.has_denormals_are_zero()) {
1902                 ++dmsize;
1903                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1904         } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
1905                 _rc_config->set_denormal_model(DenormalNone);
1906         }
1907
1908         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1909                 ++dmsize;
1910                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1911         } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
1912                 _rc_config->set_denormal_model(DenormalNone);
1913         }
1914
1915         if (dmsize == 1) {
1916                 dm->set_sensitive(false);
1917         }
1918
1919         add_option (_("Audio"), dm);
1920
1921         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1922
1923         add_option (_("Audio"),
1924              new BoolOption (
1925                      "plugins-stop-with-transport",
1926                      _("Silence plugins when the transport is stopped"),
1927                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1928                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1929                      ));
1930
1931         add_option (_("Audio"),
1932              new BoolOption (
1933                      "new-plugins-active",
1934                      _("Make new plugins active"),
1935                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1936                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1937                      ));
1938
1939         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
1940
1941         add_option (_("Audio"),
1942              new BoolOption (
1943                      "auto-analyse-audio",
1944                      _("Enable automatic analysis of audio"),
1945                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1946                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1947                      ));
1948
1949         add_option (_("Audio"),
1950              new BoolOption (
1951                      "replicate-missing-region-channels",
1952                      _("Replicate missing region channels"),
1953                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1954                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1955                      ));
1956
1957         /* SOLO AND MUTE */
1958
1959         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
1960
1961         add_option (_("Solo / mute"),
1962              new FaderOption (
1963                      "solo-mute-gain",
1964                      _("Solo-in-place mute cut (dB)"),
1965                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1966                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1967                      ));
1968
1969         _solo_control_is_listen_control = new BoolOption (
1970                 "solo-control-is-listen-control",
1971                 _("Solo controls are Listen controls"),
1972                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1973                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1974                 );
1975
1976         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1977
1978         _listen_position = new ComboOption<ListenPosition> (
1979                 "listen-position",
1980                 _("Listen Position"),
1981                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1982                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1983                 );
1984
1985         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1986         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1987
1988         add_option (_("Solo / mute"), _listen_position);
1989
1990         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1991                 "pfl-position",
1992                 _("PFL signals come from"),
1993                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1994                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1995                 );
1996
1997         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1998         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1999
2000         add_option (_("Solo / mute"), pp);
2001
2002         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2003                 "afl-position",
2004                 _("AFL signals come from"),
2005                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2006                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2007                 );
2008
2009         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2010         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2011
2012         add_option (_("Solo / mute"), pa);
2013
2014         parameter_changed ("use-monitor-bus");
2015
2016         add_option (_("Solo / mute"),
2017              new BoolOption (
2018                      "exclusive-solo",
2019                      _("Exclusive solo"),
2020                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2021                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2022                      ));
2023
2024         add_option (_("Solo / mute"),
2025              new BoolOption (
2026                      "show-solo-mutes",
2027                      _("Show solo muting"),
2028                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2029                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2030                      ));
2031
2032         add_option (_("Solo / mute"),
2033              new BoolOption (
2034                      "solo-mute-override",
2035                      _("Soloing overrides muting"),
2036                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2037                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2038                      ));
2039
2040         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
2041
2042         add_option (_("Solo / mute"),
2043              new BoolOption (
2044                      "mute-affects-pre-fader",
2045                      _("Mute affects pre-fader sends"),
2046                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2047                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2048                      ));
2049
2050         add_option (_("Solo / mute"),
2051              new BoolOption (
2052                      "mute-affects-post-fader",
2053                      _("Mute affects post-fader sends"),
2054                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2055                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2056                      ));
2057
2058         add_option (_("Solo / mute"),
2059              new BoolOption (
2060                      "mute-affects-control-outs",
2061                      _("Mute affects control outputs"),
2062                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2063                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2064                      ));
2065
2066         add_option (_("Solo / mute"),
2067              new BoolOption (
2068                      "mute-affects-main-outs",
2069                      _("Mute affects main outputs"),
2070                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2071                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2072                      ));
2073
2074         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
2075
2076         add_option (_("Solo / mute"),
2077              new BoolOption (
2078                      "link-send-and-route-panner",
2079                      _("Link panners of Aux and External Sends with main panner by default"),
2080                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2081                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2082                      ));
2083
2084         add_option (_("MIDI"),
2085                     new SpinOption<float> (
2086                             "midi-readahead",
2087                             _("MIDI read-ahead time (seconds)"),
2088                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2089                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2090                             0.1, 10, 0.1, 1,
2091                             "", 1.0, 1
2092                             ));
2093
2094         add_option (_("MIDI"),
2095                     new BoolOption (
2096                             "send-midi-clock",
2097                             _("Send MIDI Clock"),
2098                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2099                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2100                             ));
2101
2102         add_option (_("MIDI"),
2103                     new BoolOption (
2104                             "send-mtc",
2105                             _("Send MIDI Time Code"),
2106                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2107                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2108                             ));
2109
2110         add_option (_("MIDI"),
2111                     new SpinOption<int> (
2112                             "mtc-qf-speed-tolerance",
2113                             _("Percentage either side of normal transport speed to transmit MTC"),
2114                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2115                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2116                             0, 20, 1, 5
2117                             ));
2118
2119         add_option (_("MIDI"),
2120                     new BoolOption (
2121                             "mmc-control",
2122                             _("Obey MIDI Machine Control commands"),
2123                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2124                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2125                             ));
2126
2127         add_option (_("MIDI"),
2128                     new BoolOption (
2129                             "send-mmc",
2130                             _("Send MIDI Machine Control commands"),
2131                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2132                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2133                             ));
2134
2135         add_option (_("MIDI"),
2136                     new BoolOption (
2137                             "midi-feedback",
2138                             _("Send MIDI control feedback"),
2139                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2140                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2141                             ));
2142
2143         add_option (_("MIDI"),
2144              new SpinOption<uint8_t> (
2145                      "mmc-receive-device-id",
2146                      _("Inbound MMC device ID"),
2147                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2148                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2149                      0, 128, 1, 10
2150                      ));
2151
2152         add_option (_("MIDI"),
2153              new SpinOption<uint8_t> (
2154                      "mmc-send-device-id",
2155                      _("Outbound MMC device ID"),
2156                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2157                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2158                      0, 128, 1, 10
2159                      ));
2160
2161         add_option (_("MIDI"),
2162              new SpinOption<int32_t> (
2163                      "initial-program-change",
2164                      _("Initial program change"),
2165                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2166                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2167                      -1, 65536, 1, 10
2168                      ));
2169
2170         add_option (_("MIDI"),
2171                     new BoolOption (
2172                             "display-first-midi-bank-as-zero",
2173                             _("Display first MIDI bank/program as 0"),
2174                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2175                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2176                             ));
2177
2178         add_option (_("MIDI"),
2179              new BoolOption (
2180                      "never-display-periodic-midi",
2181                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2182                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_never_display_periodic_midi),
2183                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_never_display_periodic_midi)
2184                      ));
2185
2186         add_option (_("MIDI"),
2187              new BoolOption (
2188                      "sound-midi-notes",
2189                      _("Sound MIDI notes as they are selected"),
2190                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_sound_midi_notes),
2191                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_sound_midi_notes)
2192                      ));
2193
2194         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2195
2196         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2197                 "midi-audition-synth-uri",
2198                 _("Midi Audition Synth (LV2)"),
2199                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2200                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2201                 );
2202
2203         audition_synth->add(X_(""), _("None"));
2204         PluginInfoList all_plugs;
2205         PluginManager& manager (PluginManager::instance());
2206 #ifdef LV2_SUPPORT
2207         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2208
2209         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2210                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2211                 if (!(*i)->is_instrument()) continue;
2212                 if ((*i)->type != ARDOUR::LV2) continue;
2213                 audition_synth->add((*i)->unique_id, (*i)->name);
2214         }
2215 #endif
2216
2217         add_option (_("MIDI"), audition_synth);
2218
2219         /* USER INTERACTION */
2220
2221         if (
2222 #ifdef PLATFORM_WINDOWS
2223                         true
2224 #else
2225                         getenv ("ARDOUR_BUNDLED")
2226 #endif
2227            )
2228         {
2229                 add_option (_("User interaction"), 
2230                             new BoolOption (
2231                                     "enable-translation",
2232                                     string_compose (_("Use translations of %1 messages\n"
2233                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2234                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2235                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2236                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2237         }
2238
2239         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2240
2241         add_option (_("User interaction"), new KeyboardOptions);
2242
2243         /* Control Surfaces */
2244
2245         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2246
2247         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2248                 "remote-model",
2249                 _("Control surface remote ID"),
2250                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2251                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2252                 );
2253
2254         rm->add (UserOrdered, _("assigned by user"));
2255         rm->add (MixerOrdered, _("follows order of mixer"));
2256
2257         add_option (_("Control Surfaces"), rm);
2258
2259         /* VIDEO Timeline */
2260         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2261
2262 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2263         /* Plugin options (currrently VST only) */
2264         add_option (_("Plugins"), new PluginOptions (_rc_config, _ui_config));
2265 #endif
2266
2267         /* INTERFACE */
2268
2269         add_option (S_("Preferences|GUI"),
2270              new BoolOption (
2271                      "widget-prelight",
2272                      _("Graphically indicate mouse pointer hovering over various widgets"),
2273                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_widget_prelight),
2274                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_widget_prelight)
2275                      ));
2276
2277 #ifdef TOOLTIPS_GOT_FIXED
2278         add_option (S_("Preferences|GUI"),
2279              new BoolOption (
2280                      "use-tooltips",
2281                      _("Show tooltips if mouse hovers over a control"),
2282                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_use_tooltips),
2283                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_use_tooltips)
2284                      ));
2285 #endif
2286
2287         add_option (S_("Preferences|GUI"),
2288              new BoolOption (
2289                      "show-name-highlight",
2290                      _("Use name highlight bars in region displays (requires a restart)"),
2291                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_name_highlight),
2292                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_name_highlight)
2293                      ));
2294
2295 #ifndef GTKOSX
2296         /* font scaling does nothing with GDK/Quartz */
2297         add_option (S_("Preferences|GUI"), new FontScalingOptions (_ui_config));
2298 #endif
2299
2300         add_option (S_("GUI"),
2301                     new BoolOption (
2302                             "super-rapid-clock-update",
2303                             _("update transport clock display at FPS instead of every 100ms"),
2304                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_super_rapid_clock_update),
2305                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_super_rapid_clock_update)
2306                             ));
2307
2308         /* Lock GUI timeout */
2309
2310         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2311         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2312                                                 _("Lock timeout (seconds)"),
2313                                                 lts,
2314                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_lock_gui_after_seconds),
2315                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_lock_gui_after_seconds)
2316                         );
2317         slts->scale().set_digits (0);
2318         Gtkmm2ext::UI::instance()->set_tip
2319                 (slts->tip_widget(),
2320                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2321         add_option (S_("Preferences|GUI"), slts);
2322
2323         /* The names of these controls must be the same as those given in MixerStrip
2324            for the actual widgets being controlled.
2325         */
2326         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2327         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2328         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2329         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2330         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2331         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2332         
2333         add_option (
2334                 S_("Preferences|GUI"),
2335                 new VisibilityOption (
2336                         _("Mixer Strip"),
2337                         &_mixer_strip_visibility,
2338                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_mixer_strip_visibility),
2339                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_mixer_strip_visibility)
2340                         )
2341                 );
2342
2343         add_option (S_("Preferences|GUI"),
2344              new BoolOption (
2345                      "default-narrow_ms",
2346                      _("Use narrow strips in the mixer by default"),
2347                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_default_narrow_ms),
2348                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_default_narrow_ms)
2349                      ));
2350
2351         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2352
2353         ComboOption<float>* mht = new ComboOption<float> (
2354                 "meter-hold",
2355                 _("Peak hold time"),
2356                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_hold),
2357                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_hold)
2358                 );
2359
2360         mht->add (MeterHoldOff, _("off"));
2361         mht->add (MeterHoldShort, _("short"));
2362         mht->add (MeterHoldMedium, _("medium"));
2363         mht->add (MeterHoldLong, _("long"));
2364
2365         add_option (S_("Preferences|Metering"), mht);
2366
2367         ComboOption<float>* mfo = new ComboOption<float> (
2368                 "meter-falloff",
2369                 _("DPM fall-off"),
2370                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2371                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2372                 );
2373
2374         mfo->add (METER_FALLOFF_OFF,      _("off"));
2375         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2376         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2377         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2378         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2379         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2380         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2381         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2382         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2383
2384         add_option (S_("Preferences|Metering"), mfo);
2385
2386         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2387                 "meter-line-up-level",
2388                 _("Meter line-up level; 0dBu"),
2389                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_level),
2390                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_level)
2391                 );
2392
2393         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2394         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2395         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2396         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2397
2398         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."));
2399
2400         add_option (S_("Preferences|Metering"), mlu);
2401
2402         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2403                 "meter-line-up-din",
2404                 _("IEC1/DIN Meter line-up level; 0dBu"),
2405                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_din),
2406                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_din)
2407                 );
2408
2409         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2410         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2411         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2412         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2413
2414         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2415
2416         add_option (S_("Preferences|Metering"), mld);
2417
2418         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2419                 "meter-vu-standard",
2420                 _("VU Meter standard"),
2421                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_vu_standard),
2422                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_vu_standard)
2423                 );
2424
2425         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2426         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2427         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2428         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2429
2430         add_option (S_("Preferences|Metering"), mvu);
2431
2432         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2433         HSliderOption *mpks = new HSliderOption("meter-peak",
2434                         _("Peak threshold [dBFS]"),
2435                         mpk,
2436                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_peak),
2437                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_peak)
2438                         );
2439
2440         Gtkmm2ext::UI::instance()->set_tip
2441                 (mpks->tip_widget(),
2442                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2443
2444         add_option (S_("Preferences|Metering"), mpks);
2445
2446         add_option (S_("Preferences|Metering"),
2447              new BoolOption (
2448                      "meter-style-led",
2449                      _("LED meter style"),
2450                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_style_led),
2451                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_style_led)
2452                      ));
2453
2454         /* and now the theme manager */
2455
2456         ThemeManager* tm = manage (new ThemeManager);
2457         add_page (_("Theme"), *tm);
2458 }
2459
2460 void
2461 RCOptionEditor::parameter_changed (string const & p)
2462 {
2463         OptionEditor::parameter_changed (p);
2464
2465         if (p == "use-monitor-bus") {
2466                 bool const s = Config->get_use_monitor_bus ();
2467                 if (!s) {
2468                         /* we can't use this if we don't have a monitor bus */
2469                         Config->set_solo_control_is_listen_control (false);
2470                 }
2471                 _solo_control_is_listen_control->set_sensitive (s);
2472                 _listen_position->set_sensitive (s);
2473         } else if (p == "sync-source") {
2474                 _sync_source->set_sensitive (true);
2475                 if (_session) {
2476                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2477                 }
2478                 switch(Config->get_sync_source()) {
2479                 case ARDOUR::MTC:
2480                 case ARDOUR::LTC:
2481                         _sync_genlock->set_sensitive (true);
2482                         _sync_framerate->set_sensitive (true);
2483                         _sync_source_2997->set_sensitive (true);
2484                         break;
2485                 default:
2486                         _sync_genlock->set_sensitive (false);
2487                         _sync_framerate->set_sensitive (false);
2488                         _sync_source_2997->set_sensitive (false);
2489                         break;
2490                 }
2491         } else if (p == "send-ltc") {
2492                 bool const s = Config->get_send_ltc ();
2493                 _ltc_send_continuously->set_sensitive (s);
2494                 _ltc_volume_slider->set_sensitive (s);
2495         }
2496 }
2497
2498 void RCOptionEditor::ltc_generator_volume_changed () {
2499         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2500 }
2501
2502 void
2503 RCOptionEditor::populate_sync_options ()
2504 {
2505         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2506
2507         _sync_source->clear ();
2508
2509         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2510                 _sync_source->add (*i, sync_source_to_string (*i));
2511         }
2512
2513         if (sync_opts.empty()) {
2514                 _sync_source->set_sensitive(false);
2515         } else {
2516                 if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
2517                         _rc_config->set_sync_source(sync_opts.front());
2518                 }
2519         }
2520 }