add mixbus profile checks to prefs panel, to simplify future merges
[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 #if !defined USE_CAIRO_IMAGE_SURFACE && !defined NDEBUG
25 #define OPTIONAL_CAIRO_IMAGE_SURFACE
26 #endif
27
28 #include <cairo/cairo.h>
29
30 #include <boost/algorithm/string.hpp>
31
32 #include <gtkmm/liststore.h>
33 #include <gtkmm/stock.h>
34 #include <gtkmm/scale.h>
35
36 #include <gtkmm2ext/utils.h>
37 #include <gtkmm2ext/slider_controller.h>
38 #include <gtkmm2ext/gtk_ui.h>
39 #include <gtkmm2ext/paths_dialog.h>
40
41 #include "pbd/fpu.h"
42 #include "pbd/cpus.h"
43
44 #include "ardour/audioengine.h"
45 #include "ardour/profile.h"
46 #include "ardour/dB.h"
47 #include "ardour/rc_configuration.h"
48 #include "ardour/control_protocol_manager.h"
49 #include "ardour/plugin_manager.h"
50 #include "control_protocol/control_protocol.h"
51
52 #include "canvas/wave_view.h"
53
54 #include "ardour_window.h"
55 #include "ardour_dialog.h"
56 #include "gui_thread.h"
57 #include "meter_patterns.h"
58 #include "midi_tracer.h"
59 #include "rc_option_editor.h"
60 #include "utils.h"
61 #include "midi_port_dialog.h"
62 #include "sfdb_ui.h"
63 #include "keyboard.h"
64 #include "theme_manager.h"
65 #include "ui_config.h"
66 #include "i18n.h"
67
68 using namespace std;
69 using namespace Gtk;
70 using namespace Gtkmm2ext;
71 using namespace PBD;
72 using namespace ARDOUR;
73 using namespace ARDOUR_UI_UTILS;
74
75 class ClickOptions : public OptionEditorBox
76 {
77 public:
78         ClickOptions (RCConfiguration* c, Gtk::Window* p)
79                 : _rc_config (c)
80                 , _click_browse_button (_("Browse..."))
81                 , _click_emphasis_browse_button (_("Browse..."))
82         {
83                 Table* t = manage (new Table (4, 3));
84                 t->set_spacings (4);
85
86                 Label* l = manage (left_aligned_label (_("Emphasis on first beat:")));
87                 t->attach (*l, 0, 1, 1, 2, FILL);
88                 t->attach (_use_emphasis_on_click_check_button, 1, 2, 1, 2, FILL);
89                 _use_emphasis_on_click_check_button.signal_toggled().connect (
90                     sigc::mem_fun (*this, &ClickOptions::use_emphasis_on_click_toggled));
91
92                 l = manage (left_aligned_label (_("Use default Click:")));
93                 t->attach (*l, 0, 1, 0, 1, FILL);
94                 t->attach (_use_default_click_check_button, 1, 2, 0, 1, FILL);
95                 _use_default_click_check_button.signal_toggled().connect (
96                     sigc::mem_fun (*this, &ClickOptions::use_default_click_toggled));
97
98                 l = manage (left_aligned_label (_("Click audio file:")));
99                 t->attach (*l, 0, 1, 2, 3, FILL);
100                 t->attach (_click_path_entry, 1, 2, 2, 3, FILL);
101                 _click_browse_button.signal_clicked ().connect (
102                     sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
103                 t->attach (_click_browse_button, 2, 3, 2, 3, FILL);
104
105                 l = manage (left_aligned_label (_("Click emphasis audio file:")));
106                 t->attach (*l, 0, 1, 3, 4, FILL);
107                 t->attach (_click_emphasis_path_entry, 1, 2, 3, 4, FILL);
108                 _click_emphasis_browse_button.signal_clicked ().connect (
109                     sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
110                 t->attach (_click_emphasis_browse_button, 2, 3, 3, 4, FILL);
111
112                 _box->pack_start (*t, false, false);
113
114                 _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));
115                 _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
116
117                 if (_rc_config->get_click_sound ().empty() &&
118                     _rc_config->get_click_emphasis_sound().empty()) {
119                         _use_default_click_check_button.set_active (true);
120                         _use_emphasis_on_click_check_button.set_active (true);
121
122                 } else {
123                         _use_default_click_check_button.set_active (false);
124                         _use_emphasis_on_click_check_button.set_active (false);
125                 }
126         }
127
128         void parameter_changed (string const & p)
129         {
130                 if (p == "click-sound") {
131                         _click_path_entry.set_text (_rc_config->get_click_sound());
132                 } else if (p == "click-emphasis-sound") {
133                         _click_emphasis_path_entry.set_text (_rc_config->get_click_emphasis_sound());
134                 } else if (p == "use-click-emphasis") {
135                         bool x = _rc_config->get_use_click_emphasis ();
136                         _use_emphasis_on_click_check_button.set_active (x);
137                 }
138         }
139
140         void set_state_from_config ()
141         {
142                 parameter_changed ("click-sound");
143                 parameter_changed ("click-emphasis-sound");
144                 parameter_changed ("use-click-emphasis");
145         }
146
147 private:
148
149         void click_browse_clicked ()
150         {
151                 SoundFileChooser sfdb (_("Choose Click"));
152
153                 sfdb.show_all ();
154                 sfdb.present ();
155
156                 if (sfdb.run () == RESPONSE_OK) {
157                         click_chosen (sfdb.get_filename());
158                 }
159         }
160
161         void click_chosen (string const & path)
162         {
163                 _click_path_entry.set_text (path);
164                 _rc_config->set_click_sound (path);
165         }
166
167         void click_changed ()
168         {
169                 click_chosen (_click_path_entry.get_text ());
170         }
171
172         void click_emphasis_browse_clicked ()
173         {
174                 SoundFileChooser sfdb (_("Choose Click Emphasis"));
175
176                 sfdb.show_all ();
177                 sfdb.present ();
178
179                 if (sfdb.run () == RESPONSE_OK) {
180                         click_emphasis_chosen (sfdb.get_filename());
181                 }
182         }
183
184         void click_emphasis_chosen (string const & path)
185         {
186                 _click_emphasis_path_entry.set_text (path);
187                 _rc_config->set_click_emphasis_sound (path);
188         }
189
190         void click_emphasis_changed ()
191         {
192                 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
193         }
194
195         void use_default_click_toggled ()
196         {
197                 if (_use_default_click_check_button.get_active ()) {
198                         _rc_config->set_click_sound ("");
199                         _rc_config->set_click_emphasis_sound ("");
200                         _click_path_entry.set_sensitive (false);
201                         _click_emphasis_path_entry.set_sensitive (false);
202                         _click_browse_button.set_sensitive (false);
203                         _click_emphasis_browse_button.set_sensitive (false);
204                 } else {
205                         _click_path_entry.set_sensitive (true);
206                         _click_emphasis_path_entry.set_sensitive (true);
207                         _click_browse_button.set_sensitive (true);
208                         _click_emphasis_browse_button.set_sensitive (true);
209                 }
210         }
211
212         void use_emphasis_on_click_toggled ()
213         {
214                 if (_use_emphasis_on_click_check_button.get_active ()) {
215                         _rc_config->set_use_click_emphasis(true);
216                 } else {
217                         _rc_config->set_use_click_emphasis(false);
218                 }
219         }
220
221         RCConfiguration* _rc_config;
222         CheckButton _use_default_click_check_button;
223         CheckButton _use_emphasis_on_click_check_button;
224         Entry _click_path_entry;
225         Entry _click_emphasis_path_entry;
226         Button _click_browse_button;
227         Button _click_emphasis_browse_button;
228 };
229
230 class UndoOptions : public OptionEditorBox
231 {
232 public:
233         UndoOptions (RCConfiguration* c) :
234                 _rc_config (c),
235                 _limit_undo_button (_("Limit undo history to")),
236                 _save_undo_button (_("Save undo history of"))
237         {
238                 Table* t = new Table (2, 3);
239                 t->set_spacings (4);
240
241                 t->attach (_limit_undo_button, 0, 1, 0, 1, FILL);
242                 _limit_undo_spin.set_range (0, 512);
243                 _limit_undo_spin.set_increments (1, 10);
244                 t->attach (_limit_undo_spin, 1, 2, 0, 1, FILL | EXPAND);
245                 Label* l = manage (left_aligned_label (_("commands")));
246                 t->attach (*l, 2, 3, 0, 1);
247
248                 t->attach (_save_undo_button, 0, 1, 1, 2, FILL);
249                 _save_undo_spin.set_range (0, 512);
250                 _save_undo_spin.set_increments (1, 10);
251                 t->attach (_save_undo_spin, 1, 2, 1, 2, FILL | EXPAND);
252                 l = manage (left_aligned_label (_("commands")));
253                 t->attach (*l, 2, 3, 1, 2);
254
255                 _box->pack_start (*t);
256
257                 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
258                 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
259                 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
260                 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
261         }
262
263         void parameter_changed (string const & p)
264         {
265                 if (p == "history-depth") {
266                         int32_t const d = _rc_config->get_history_depth();
267                         _limit_undo_button.set_active (d != 0);
268                         _limit_undo_spin.set_sensitive (d != 0);
269                         _limit_undo_spin.set_value (d);
270                 } else if (p == "save-history") {
271                         bool const x = _rc_config->get_save_history ();
272                         _save_undo_button.set_active (x);
273                         _save_undo_spin.set_sensitive (x);
274                 } else if (p == "save-history-depth") {
275                         _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
276                 }
277         }
278
279         void set_state_from_config ()
280         {
281                 parameter_changed ("save-history");
282                 parameter_changed ("history-depth");
283                 parameter_changed ("save-history-depth");
284         }
285
286         void limit_undo_toggled ()
287         {
288                 bool const x = _limit_undo_button.get_active ();
289                 _limit_undo_spin.set_sensitive (x);
290                 int32_t const n = x ? 16 : 0;
291                 _limit_undo_spin.set_value (n);
292                 _rc_config->set_history_depth (n);
293         }
294
295         void limit_undo_changed ()
296         {
297                 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
298         }
299
300         void save_undo_toggled ()
301         {
302                 bool const x = _save_undo_button.get_active ();
303                 _rc_config->set_save_history (x);
304         }
305
306         void save_undo_changed ()
307         {
308                 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
309         }
310
311 private:
312         RCConfiguration* _rc_config;
313         CheckButton _limit_undo_button;
314         SpinButton _limit_undo_spin;
315         CheckButton _save_undo_button;
316         SpinButton _save_undo_spin;
317 };
318
319
320
321 static const struct {
322     const char *name;
323     guint modifier;
324 } modifiers[] = {
325
326         { "Unmodified", 0 },
327
328 #ifdef GTKOSX
329
330         /* Command = Meta
331            Option/Alt = Mod1
332         */
333         { "Key|Shift", GDK_SHIFT_MASK },
334         { "Command", GDK_MOD2_MASK },
335         { "Control", GDK_CONTROL_MASK },
336         { "Option", GDK_MOD1_MASK },
337         { "Command-Shift", GDK_MOD2_MASK|GDK_SHIFT_MASK },
338         { "Command-Option", GDK_MOD2_MASK|GDK_MOD1_MASK },
339         { "Command-Option-Control", GDK_MOD2_MASK|GDK_MOD1_MASK|GDK_CONTROL_MASK },
340         { "Option-Control", GDK_MOD1_MASK|GDK_CONTROL_MASK },
341         { "Option-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
342         { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
343         { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_MOD2_MASK },
344
345 #else
346         { "Key|Shift", GDK_SHIFT_MASK },
347         { "Control", GDK_CONTROL_MASK },
348         { "Alt", GDK_MOD1_MASK },
349         { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
350         { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
351         { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
352         { "Alt-Windows", GDK_MOD1_MASK|GDK_MOD4_MASK },
353         { "Alt-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
354         { "Alt-Shift-Windows", GDK_MOD1_MASK|GDK_SHIFT_MASK|GDK_MOD4_MASK },
355         { "Mod2", GDK_MOD2_MASK },
356         { "Mod3", GDK_MOD3_MASK },
357         { "Windows", GDK_MOD4_MASK },
358         { "Mod5", GDK_MOD5_MASK },
359 #endif
360         { 0, 0 }
361 };
362
363
364 class KeyboardOptions : public OptionEditorBox
365 {
366 public:
367         KeyboardOptions () :
368                   _delete_button_adjustment (3, 1, 12),
369                   _delete_button_spin (_delete_button_adjustment),
370                   _edit_button_adjustment (3, 1, 5),
371                   _edit_button_spin (_edit_button_adjustment),
372                   _insert_note_button_adjustment (3, 1, 5),
373                   _insert_note_button_spin (_insert_note_button_adjustment)
374         {
375                 const Glib::ustring restart_msg = _("\nChanges to this setting will only persist after your project has been saved.");
376                 /* internationalize and prepare for use with combos */
377
378                 vector<string> dumb;
379                 for (int i = 0; modifiers[i].name; ++i) {
380                         dumb.push_back (S_(modifiers[i].name));
381                 }
382
383                 set_popdown_strings (_edit_modifier_combo, dumb);
384                 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
385                 Gtkmm2ext::UI::instance()->set_tip (_edit_modifier_combo,
386                                                     (string_compose (_("<b>Recommended Setting: %1 + button 3 (right mouse button)</b>%2"),  Keyboard::primary_modifier_name (), restart_msg)));
387                 for (int x = 0; modifiers[x].name; ++x) {
388                         if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
389                                 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
390                                 break;
391                         }
392                 }
393
394                 Table* t = manage (new Table (5, 11));
395                 t->set_spacings (4);
396
397                 int row = 0;
398                 int col = 0;
399
400                 Label* l = manage (left_aligned_label (_("Select Keyboard layout:")));
401                 l->set_name ("OptionsLabel");
402
403                 vector<string> strs;
404
405                 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
406                         strs.push_back (bf->first);
407                 }
408
409                 set_popdown_strings (_keyboard_layout_selector, strs);
410                 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
411                 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
412
413                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
414                 t->attach (_keyboard_layout_selector, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
415
416                 ++row;
417                 col = 0;
418
419                 l = manage (left_aligned_label (_("When Clicking:")));
420                 l->set_name ("OptionEditorHeading");
421                 t->attach (*l, col, col + 2, row, row + 1, FILL | EXPAND, FILL);
422
423                 ++row;
424                 col = 1;
425
426                 l = manage (left_aligned_label (_("Edit using:")));
427                 l->set_name ("OptionsLabel");
428
429                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
430                 t->attach (_edit_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
431
432                 l = manage (new Label (_("+ button")));
433                 l->set_name ("OptionsLabel");
434
435                 t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
436                 t->attach (_edit_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
437
438                 _edit_button_spin.set_name ("OptionsEntry");
439                 _edit_button_adjustment.set_value (Keyboard::edit_button());
440                 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
441
442                 ++row;
443                 col = 1;
444
445                 set_popdown_strings (_delete_modifier_combo, dumb);
446                 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
447                 Gtkmm2ext::UI::instance()->set_tip (_delete_modifier_combo,
448                                                     (string_compose (_("<b>Recommended Setting: %1 + button 3 (right mouse button)</b>%2"), Keyboard::tertiary_modifier_name (), restart_msg)));
449                 for (int x = 0; modifiers[x].name; ++x) {
450                         if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
451                                 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
452                                 break;
453                         }
454                 }
455
456                 l = manage (left_aligned_label (_("Delete using:")));
457                 l->set_name ("OptionsLabel");
458
459                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
460                 t->attach (_delete_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
461
462                 l = manage (new Label (_("+ button")));
463                 l->set_name ("OptionsLabel");
464
465                 t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
466                 t->attach (_delete_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
467
468                 _delete_button_spin.set_name ("OptionsEntry");
469                 _delete_button_adjustment.set_value (Keyboard::delete_button());
470                 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
471
472                 ++row;
473                 col = 1;
474
475                 set_popdown_strings (_insert_note_modifier_combo, dumb);
476                 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
477                 Gtkmm2ext::UI::instance()->set_tip (_insert_note_modifier_combo,
478                                                     (string_compose (_("<b>Recommended Setting: %1 + button 1 (left mouse button)</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
479                 for (int x = 0; modifiers[x].name; ++x) {
480                         if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
481                                 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
482                                 break;
483                         }
484                 }
485
486                 l = manage (left_aligned_label (_("Insert note using:")));
487                 l->set_name ("OptionsLabel");
488
489                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
490                 t->attach (_insert_note_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
491
492                 l = manage (new Label (_("+ button")));
493                 l->set_name ("OptionsLabel");
494
495                 t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
496                 t->attach (_insert_note_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
497
498                 _insert_note_button_spin.set_name ("OptionsEntry");
499                 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
500                 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
501
502                 ++row;
503
504                 l = manage (left_aligned_label (_("When Beginning a Drag:")));
505                 l->set_name ("OptionEditorHeading");
506                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
507
508                 ++row;
509                 col = 1;
510
511                 /* copy modifier */
512                 set_popdown_strings (_copy_modifier_combo, dumb);
513                 _copy_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::copy_modifier_chosen));
514                 Gtkmm2ext::UI::instance()->set_tip (_copy_modifier_combo,
515                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"),
516 #ifdef GTKOSX
517                                                                      Keyboard::secondary_modifier_name (),
518 #else
519                                                                      Keyboard::primary_modifier_name (),
520 #endif
521                                                                      restart_msg)));
522                 for (int x = 0; modifiers[x].name; ++x) {
523                         if (modifiers[x].modifier == (guint) Keyboard::CopyModifier) {
524                                 _copy_modifier_combo.set_active_text (S_(modifiers[x].name));
525                                 break;
526                         }
527                 }
528
529                 l = manage (left_aligned_label (_("Copy items using:")));
530                 l->set_name ("OptionsLabel");
531
532                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
533                 t->attach (_copy_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
534
535                                 ++row;
536                 col = 1;
537
538                 /* constraint modifier */
539                 set_popdown_strings (_constraint_modifier_combo, dumb);
540                 _constraint_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::constraint_modifier_chosen));
541                 Gtkmm2ext::UI::instance()->set_tip (_constraint_modifier_combo,
542                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"),
543 #ifdef GTKOSX
544                                                                      Keyboard::primary_modifier_name (),
545 #else
546                                                                      Keyboard::secondary_modifier_name (),
547 #endif
548                                                                      restart_msg)));
549                 for (int x = 0; modifiers[x].name; ++x) {
550                         if (modifiers[x].modifier == (guint) ArdourKeyboard::constraint_modifier ()) {
551                                 _constraint_modifier_combo.set_active_text (S_(modifiers[x].name));
552                                 break;
553                         }
554                 }
555
556                 l = manage (left_aligned_label (_("Constrain drag using:")));
557                 l->set_name ("OptionsLabel");
558
559                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
560                 t->attach (_constraint_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
561
562                 ++row;
563
564                 l = manage (left_aligned_label (_("When Beginning a Trim:")));
565                 l->set_name ("OptionEditorHeading");
566                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
567
568                 ++row;
569                 col = 1;
570
571                 /* trim_contents */
572                 set_popdown_strings (_trim_contents_combo, dumb);
573                 _trim_contents_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_contents_modifier_chosen));
574                 Gtkmm2ext::UI::instance()->set_tip (_trim_contents_combo,
575                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
576                 for (int x = 0; modifiers[x].name; ++x) {
577                         if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_contents_modifier ()) {
578                                 _trim_contents_combo.set_active_text (S_(modifiers[x].name));
579                                 break;
580                         }
581                 }
582
583                 l = manage (left_aligned_label (_("Trim contents using:")));
584                 l->set_name ("OptionsLabel");
585
586                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
587                 t->attach (_trim_contents_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
588
589                 ++row;
590                 col = 1;
591
592                 /* anchored trim */
593                 set_popdown_strings (_trim_anchored_combo, dumb);
594                 _trim_anchored_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_anchored_modifier_chosen));
595                 Gtkmm2ext::UI::instance()->set_tip (_trim_anchored_combo,
596                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::tertiary_modifier_name (), restart_msg)));
597                 for (int x = 0; modifiers[x].name; ++x) {
598                         if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_anchored_modifier ()) {
599                                 _trim_anchored_combo.set_active_text (S_(modifiers[x].name));
600                                 break;
601                         }
602                 }
603
604                 l = manage (left_aligned_label (_("Anchored trim using:")));
605                 l->set_name ("OptionsLabel");
606
607                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
608                 ++col;
609                 t->attach (_trim_anchored_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
610
611                 ++row;
612                 col = 1;
613
614                 /* jump trim disabled for now
615                 set_popdown_strings (_trim_jump_combo, dumb);
616                 _trim_jump_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_jump_modifier_chosen));
617
618                 for (int x = 0; modifiers[x].name; ++x) {
619                         if (modifiers[x].modifier == (guint) Keyboard::trim_jump_modifier ()) {
620                                 _trim_jump_combo.set_active_text (S_(modifiers[x].name));
621                                 break;
622                         }
623                 }
624
625                 l = manage (left_aligned_label (_("Jump after trim using:")));
626                 l->set_name ("OptionsLabel");
627
628                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
629                 ++col;
630                 t->attach (_trim_jump_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
631
632                 ++row;
633                 col = 1;
634                 */
635
636                 /* note resize relative */
637                 set_popdown_strings (_note_size_relative_combo, dumb);
638                 _note_size_relative_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::note_size_relative_modifier_chosen));
639                 Gtkmm2ext::UI::instance()->set_tip (_note_size_relative_combo,
640                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
641                 for (int x = 0; modifiers[x].name; ++x) {
642                         if (modifiers[x].modifier == (guint) ArdourKeyboard::note_size_relative_modifier ()) {
643                                 _note_size_relative_combo.set_active_text (S_(modifiers[x].name));
644                                 break;
645                         }
646                 }
647
648                 l = manage (left_aligned_label (_("Resize notes relatively using:")));
649                 l->set_name ("OptionsLabel");
650
651                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
652                 ++col;
653                 t->attach (_note_size_relative_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
654
655                 ++row;
656
657                 l = manage (left_aligned_label (_("While Dragging:")));
658                 l->set_name ("OptionEditorHeading");
659                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
660
661                 ++row;
662                 col = 1;
663
664                 /* ignore snap */
665                 set_popdown_strings (_snap_modifier_combo, dumb);
666                 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
667 #ifdef GTKOSX
668                 Glib::ustring mod_str = string_compose (X_("%1-%2"), Keyboard::level4_modifier_name (), Keyboard::tertiary_modifier_name ());
669 #else
670                 Glib::ustring mod_str = Keyboard::secondary_modifier_name();
671 #endif
672                 Gtkmm2ext::UI::instance()->set_tip (_snap_modifier_combo,
673                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
674                 for (int x = 0; modifiers[x].name; ++x) {
675                         if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
676                                 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
677                                 break;
678                         }
679                 }
680
681                 l = manage (left_aligned_label (_("Ignore snap using:")));
682                 l->set_name ("OptionsLabel");
683
684                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
685                 t->attach (_snap_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
686
687                 ++row;
688                 col = 1;
689
690                 /* snap delta */
691                 set_popdown_strings (_snap_delta_combo, dumb);
692                 _snap_delta_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_delta_modifier_chosen));
693 #ifdef GTKOSX
694                 mod_str = Keyboard::level4_modifier_name ();
695 #else
696                 mod_str = string_compose (X_("%1-%2"), Keyboard::secondary_modifier_name (), Keyboard::level4_modifier_name ());
697 #endif
698                 Gtkmm2ext::UI::instance()->set_tip (_snap_delta_combo,
699                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
700                 for (int x = 0; modifiers[x].name; ++x) {
701                         if (modifiers[x].modifier == (guint) Keyboard::snap_delta_modifier ()) {
702                                 _snap_delta_combo.set_active_text (S_(modifiers[x].name));
703                                 break;
704                         }
705                 }
706
707                 l = manage (left_aligned_label (_("Snap relatively using:")));
708                 l->set_name ("OptionsLabel");
709
710                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
711                 t->attach (_snap_delta_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
712
713                 ++row;
714
715                 l = manage (left_aligned_label (_("While Trimming:")));
716                 l->set_name ("OptionEditorHeading");
717                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
718
719                 ++row;
720                 col = 1;
721
722                 /* trim_overlap */
723                 set_popdown_strings (_trim_overlap_combo, dumb);
724                 _trim_overlap_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_overlap_modifier_chosen));
725
726                 Gtkmm2ext::UI::instance()->set_tip (_trim_overlap_combo,
727                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::tertiary_modifier_name (), restart_msg)));
728                 for (int x = 0; modifiers[x].name; ++x) {
729                         if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_overlap_modifier ()) {
730                                 _trim_overlap_combo.set_active_text (S_(modifiers[x].name));
731                                 break;
732                         }
733                 }
734
735                 l = manage (left_aligned_label (_("Resize overlapped regions using:")));
736                 l->set_name ("OptionsLabel");
737
738                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
739                 t->attach (_trim_overlap_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
740
741                 ++row;
742
743                 l = manage (left_aligned_label (_("While Dragging Control Points:")));
744                 l->set_name ("OptionEditorHeading");
745                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
746
747                 ++row;
748                 col = 1;
749
750                 /* fine adjust */
751                 set_popdown_strings (_fine_adjust_combo, dumb);
752                 _fine_adjust_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::fine_adjust_modifier_chosen));
753
754                 mod_str = string_compose (X_("%1-%2"), Keyboard::secondary_modifier_name (), Keyboard::tertiary_modifier_name ());
755                 Gtkmm2ext::UI::instance()->set_tip (_fine_adjust_combo,
756                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
757                 for (int x = 0; modifiers[x].name; ++x) {
758                         if (modifiers[x].modifier == (guint) ArdourKeyboard::fine_adjust_modifier ()) {
759                                 _fine_adjust_combo.set_active_text (S_(modifiers[x].name));
760                                 break;
761                         }
762                 }
763
764                 l = manage (left_aligned_label (_("Fine adjust using:")));
765                 l->set_name ("OptionsLabel");
766
767                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
768                 t->attach (_fine_adjust_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
769
770                 ++row;
771                 col = 1;
772
773                 /* push points */
774                 set_popdown_strings (_push_points_combo, dumb);
775                 _push_points_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::push_points_modifier_chosen));
776
777                 Gtkmm2ext::UI::instance()->set_tip (_push_points_combo,
778                                                     (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
779                 for (int x = 0; modifiers[x].name; ++x) {
780                         if (modifiers[x].modifier == (guint) ArdourKeyboard::push_points_modifier ()) {
781                                 _push_points_combo.set_active_text (S_(modifiers[x].name));
782                                 break;
783                         }
784                 }
785
786                 l = manage (left_aligned_label (_("Push points using:")));
787                 l->set_name ("OptionsLabel");
788
789                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
790                 t->attach (_push_points_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
791
792                 _box->pack_start (*t, false, false);
793         }
794
795         void parameter_changed (string const &)
796         {
797                 /* XXX: these aren't really config options... */
798         }
799
800         void set_state_from_config ()
801         {
802                 /* XXX: these aren't really config options... */
803         }
804
805 private:
806
807         void bindings_changed ()
808         {
809                 string const txt = _keyboard_layout_selector.get_active_text();
810
811                 /* XXX: config...?  for all this keyboard stuff */
812
813                 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
814                         if (txt == i->first) {
815                                 if (Keyboard::load_keybindings (i->second)) {
816                                         Keyboard::save_keybindings ();
817                                 }
818                         }
819                 }
820         }
821
822         void edit_modifier_chosen ()
823         {
824                 string const txt = _edit_modifier_combo.get_active_text();
825
826                 for (int i = 0; modifiers[i].name; ++i) {
827                         if (txt == _(modifiers[i].name)) {
828                                 Keyboard::set_edit_modifier (modifiers[i].modifier);
829                                 break;
830                         }
831                 }
832         }
833
834         void delete_modifier_chosen ()
835         {
836                 string const txt = _delete_modifier_combo.get_active_text();
837
838                 for (int i = 0; modifiers[i].name; ++i) {
839                         if (txt == _(modifiers[i].name)) {
840                                 Keyboard::set_delete_modifier (modifiers[i].modifier);
841                                 break;
842                         }
843                 }
844         }
845
846         void copy_modifier_chosen ()
847         {
848                 string const txt = _copy_modifier_combo.get_active_text();
849
850                 for (int i = 0; modifiers[i].name; ++i) {
851                         if (txt == _(modifiers[i].name)) {
852                                 Keyboard::set_copy_modifier (modifiers[i].modifier);
853                                 break;
854                         }
855                 }
856         }
857
858         void insert_note_modifier_chosen ()
859         {
860                 string const txt = _insert_note_modifier_combo.get_active_text();
861
862                 for (int i = 0; modifiers[i].name; ++i) {
863                         if (txt == _(modifiers[i].name)) {
864                                 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
865                                 break;
866                         }
867                 }
868         }
869
870         void snap_modifier_chosen ()
871         {
872                 string const txt = _snap_modifier_combo.get_active_text();
873
874                 for (int i = 0; modifiers[i].name; ++i) {
875                         if (txt == _(modifiers[i].name)) {
876                                 Keyboard::set_snap_modifier (modifiers[i].modifier);
877                                 break;
878                         }
879                 }
880         }
881
882         void snap_delta_modifier_chosen ()
883         {
884                 string const txt = _snap_delta_combo.get_active_text();
885
886                 for (int i = 0; modifiers[i].name; ++i) {
887                         if (txt == _(modifiers[i].name)) {
888                                 Keyboard::set_snap_delta_modifier (modifiers[i].modifier);
889                                 break;
890                         }
891                 }
892         }
893
894         void constraint_modifier_chosen ()
895         {
896                 string const txt = _constraint_modifier_combo.get_active_text();
897
898                 for (int i = 0; modifiers[i].name; ++i) {
899                         if (txt == _(modifiers[i].name)) {
900                                 ArdourKeyboard::set_constraint_modifier (modifiers[i].modifier);
901                                 break;
902                         }
903                 }
904         }
905
906         void trim_contents_modifier_chosen ()
907         {
908                 string const txt = _trim_contents_combo.get_active_text();
909
910                 for (int i = 0; modifiers[i].name; ++i) {
911                         if (txt == _(modifiers[i].name)) {
912                                 ArdourKeyboard::set_trim_contents_modifier (modifiers[i].modifier);
913                                 break;
914                         }
915                 }
916         }
917
918         void trim_overlap_modifier_chosen ()
919         {
920                 string const txt = _trim_overlap_combo.get_active_text();
921
922                 for (int i = 0; modifiers[i].name; ++i) {
923                         if (txt == _(modifiers[i].name)) {
924                                 ArdourKeyboard::set_trim_overlap_modifier (modifiers[i].modifier);
925                                 break;
926                         }
927                 }
928         }
929
930         void trim_anchored_modifier_chosen ()
931         {
932                 string const txt = _trim_anchored_combo.get_active_text();
933
934                 for (int i = 0; modifiers[i].name; ++i) {
935                         if (txt == _(modifiers[i].name)) {
936                                 ArdourKeyboard::set_trim_anchored_modifier (modifiers[i].modifier);
937                                 break;
938                         }
939                 }
940         }
941
942         void fine_adjust_modifier_chosen ()
943         {
944                 string const txt = _fine_adjust_combo.get_active_text();
945
946                 for (int i = 0; modifiers[i].name; ++i) {
947                         if (txt == _(modifiers[i].name)) {
948                                 ArdourKeyboard::set_fine_adjust_modifier (modifiers[i].modifier);
949                                 break;
950                         }
951                 }
952         }
953
954         void push_points_modifier_chosen ()
955         {
956                 string const txt = _push_points_combo.get_active_text();
957
958                 for (int i = 0; modifiers[i].name; ++i) {
959                         if (txt == _(modifiers[i].name)) {
960                                 ArdourKeyboard::set_push_points_modifier (modifiers[i].modifier);
961                                 break;
962                         }
963                 }
964         }
965
966         void note_size_relative_modifier_chosen ()
967         {
968                 string const txt = _note_size_relative_combo.get_active_text();
969
970                 for (int i = 0; modifiers[i].name; ++i) {
971                         if (txt == _(modifiers[i].name)) {
972                                 ArdourKeyboard::set_note_size_relative_modifier (modifiers[i].modifier);
973                                 break;
974                         }
975                 }
976         }
977
978         void delete_button_changed ()
979         {
980                 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
981         }
982
983         void edit_button_changed ()
984         {
985                 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
986         }
987
988         void insert_note_button_changed ()
989         {
990                 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
991         }
992
993         ComboBoxText _keyboard_layout_selector;
994         ComboBoxText _edit_modifier_combo;
995         ComboBoxText _delete_modifier_combo;
996         ComboBoxText _copy_modifier_combo;
997         ComboBoxText _insert_note_modifier_combo;
998         ComboBoxText _snap_modifier_combo;
999         ComboBoxText _snap_delta_combo;
1000         ComboBoxText _constraint_modifier_combo;
1001         ComboBoxText _trim_contents_combo;
1002         ComboBoxText _trim_overlap_combo;
1003         ComboBoxText _trim_anchored_combo;
1004         ComboBoxText _trim_jump_combo;
1005         ComboBoxText _fine_adjust_combo;
1006         ComboBoxText _push_points_combo;
1007         ComboBoxText _note_size_relative_combo;
1008         Adjustment _delete_button_adjustment;
1009         SpinButton _delete_button_spin;
1010         Adjustment _edit_button_adjustment;
1011         SpinButton _edit_button_spin;
1012         Adjustment _insert_note_button_adjustment;
1013         SpinButton _insert_note_button_spin;
1014
1015 };
1016
1017 class FontScalingOptions : public OptionEditorBox
1018 {
1019 public:
1020         FontScalingOptions () :
1021                 _dpi_adjustment (100, 50, 250, 1, 5),
1022                 _dpi_slider (_dpi_adjustment)
1023         {
1024                 _dpi_adjustment.set_value (UIConfiguration::instance().get_font_scale() / 1024.);
1025
1026                 Label* l = manage (new Label (_("GUI and Font scaling:")));
1027                 l->set_name ("OptionsLabel");
1028
1029                  const Glib::ustring dflt = _("Default");
1030                  const Glib::ustring empty = X_(""); // despite gtk-doc saying so, NULL does not work as reference
1031
1032                 _dpi_slider.set_name("FontScaleSlider");
1033                 _dpi_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1034                 _dpi_slider.set_draw_value(false);
1035                 _dpi_slider.add_mark(50,  Gtk::POS_TOP, empty);
1036                 _dpi_slider.add_mark(60,  Gtk::POS_TOP, empty);
1037                 _dpi_slider.add_mark(70,  Gtk::POS_TOP, empty);
1038                 _dpi_slider.add_mark(80,  Gtk::POS_TOP, empty);
1039                 _dpi_slider.add_mark(90,  Gtk::POS_TOP, empty);
1040                 _dpi_slider.add_mark(100, Gtk::POS_TOP, dflt);
1041                 _dpi_slider.add_mark(125, Gtk::POS_TOP, empty);
1042                 _dpi_slider.add_mark(150, Gtk::POS_TOP, empty);
1043                 _dpi_slider.add_mark(175, Gtk::POS_TOP, empty);
1044                 _dpi_slider.add_mark(200, Gtk::POS_TOP, empty);
1045                 _dpi_slider.add_mark(225, Gtk::POS_TOP, empty);
1046                 _dpi_slider.add_mark(250, Gtk::POS_TOP, empty);
1047
1048                 HBox* h = manage (new HBox);
1049                 h->set_spacing (4);
1050                 h->pack_start (*l, false, false);
1051                 h->pack_start (_dpi_slider, true, true);
1052
1053                 _box->pack_start (*h, false, false);
1054
1055                 set_note (_("Adjusting the scale require an application restart to re-layout."));
1056
1057                 _dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
1058         }
1059
1060         void parameter_changed (string const & p)
1061         {
1062                 if (p == "font-scale") {
1063                         _dpi_adjustment.set_value (UIConfiguration::instance().get_font_scale() / 1024.);
1064                 }
1065         }
1066
1067         void set_state_from_config ()
1068         {
1069                 parameter_changed ("font-scale");
1070         }
1071
1072 private:
1073
1074         void dpi_changed ()
1075         {
1076                 UIConfiguration::instance().set_font_scale ((long) floor (_dpi_adjustment.get_value() * 1024.));
1077                 /* XXX: should be triggered from the parameter changed signal */
1078                 UIConfiguration::instance().reset_dpi ();
1079         }
1080
1081         Adjustment _dpi_adjustment;
1082         HScale _dpi_slider;
1083 };
1084
1085 class ClipLevelOptions : public OptionEditorBox
1086 {
1087 public:
1088         ClipLevelOptions ()
1089                 : _clip_level_adjustment (-.5, -50.0, 0.0, 0.1, 1.0) /* units of dB */
1090                 , _clip_level_slider (_clip_level_adjustment)
1091         {
1092                 _clip_level_adjustment.set_value (UIConfiguration::instance().get_waveform_clip_level ());
1093
1094                 Label* l = manage (new Label (_("Waveform Clip Level (dBFS):")));
1095                 l->set_name ("OptionsLabel");
1096
1097                 _clip_level_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1098                 HBox* h = manage (new HBox);
1099                 h->set_spacing (4);
1100                 h->pack_start (*l, false, false);
1101                 h->pack_start (_clip_level_slider, true, true);
1102
1103                 _box->pack_start (*h, false, false);
1104
1105                 _clip_level_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &ClipLevelOptions::clip_level_changed));
1106         }
1107
1108         void parameter_changed (string const & p)
1109         {
1110                 if (p == "waveform-clip-level") {
1111                         _clip_level_adjustment.set_value (UIConfiguration::instance().get_waveform_clip_level());
1112                 }
1113         }
1114
1115         void set_state_from_config ()
1116         {
1117                 parameter_changed ("waveform-clip-level");
1118         }
1119
1120 private:
1121
1122         void clip_level_changed ()
1123         {
1124                 UIConfiguration::instance().set_waveform_clip_level (_clip_level_adjustment.get_value());
1125                 /* XXX: should be triggered from the parameter changed signal */
1126                 ArdourCanvas::WaveView::set_clip_level (_clip_level_adjustment.get_value());
1127         }
1128
1129         Adjustment _clip_level_adjustment;
1130         HScale _clip_level_slider;
1131 };
1132
1133 class BufferingOptions : public OptionEditorBox
1134 {
1135 public:
1136         BufferingOptions (RCConfiguration* c)
1137                 : _rc_config (c)
1138                 , _playback_adjustment (5, 1, 60, 1, 4)
1139                 , _capture_adjustment (5, 1, 60, 1, 4)
1140                 , _playback_slider (_playback_adjustment)
1141                 , _capture_slider (_capture_adjustment)
1142         {
1143                 vector<string> presets;
1144
1145                 /* these must match the order of the enums for BufferingPreset */
1146
1147                 presets.push_back (_("Small sessions (4-16 tracks)"));
1148                 presets.push_back (_("Medium sessions (16-64 tracks)"));
1149                 presets.push_back (_("Large sessions (64+ tracks)"));
1150                 presets.push_back (_("Custom (set by sliders below)"));
1151
1152                 set_popdown_strings (_buffering_presets_combo, presets);
1153
1154                 Label* l = manage (new Label (_("Preset:")));
1155                 l->set_name ("OptionsLabel");
1156                 HBox* h = manage (new HBox);
1157                 h->set_spacing (12);
1158                 h->pack_start (*l, false, false);
1159                 h->pack_start (_buffering_presets_combo, true, true);
1160                 _box->pack_start (*h, false, false);
1161
1162                 _buffering_presets_combo.signal_changed().connect (sigc::mem_fun (*this, &BufferingOptions::preset_changed));
1163
1164                 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
1165
1166                 l = manage (new Label (_("Playback (seconds of buffering):")));
1167                 l->set_name ("OptionsLabel");
1168
1169                 _playback_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1170                 h = manage (new HBox);
1171                 h->set_spacing (4);
1172                 h->pack_start (*l, false, false);
1173                 h->pack_start (_playback_slider, true, true);
1174
1175                 _box->pack_start (*h, false, false);
1176
1177                 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
1178
1179                 l = manage (new Label (_("Recording (seconds of buffering):")));
1180                 l->set_name ("OptionsLabel");
1181
1182                 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1183                 h = manage (new HBox);
1184                 h->set_spacing (4);
1185                 h->pack_start (*l, false, false);
1186                 h->pack_start (_capture_slider, true, true);
1187
1188                 _box->pack_start (*h, false, false);
1189
1190                 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
1191                 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
1192         }
1193
1194         void parameter_changed (string const & p)
1195         {
1196                 if (p == "buffering-preset") {
1197                         switch (_rc_config->get_buffering_preset()) {
1198                         case Small:
1199                                 _playback_slider.set_sensitive (false);
1200                                 _capture_slider.set_sensitive (false);
1201                                 _buffering_presets_combo.set_active (0);
1202                                 break;
1203                         case Medium:
1204                                 _playback_slider.set_sensitive (false);
1205                                 _capture_slider.set_sensitive (false);
1206                                 _buffering_presets_combo.set_active (1);
1207                                 break;
1208                         case Large:
1209                                 _playback_slider.set_sensitive (false);
1210                                 _capture_slider.set_sensitive (false);
1211                                 _buffering_presets_combo.set_active (2);
1212                                 break;
1213                         case Custom:
1214                                 _playback_slider.set_sensitive (true);
1215                                 _capture_slider.set_sensitive (true);
1216                                 _buffering_presets_combo.set_active (3);
1217                                 break;
1218                         }
1219                 }
1220
1221                 if (p == "playback-buffer-seconds") {
1222                         _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
1223                 } else if (p == "capture-buffer-seconds") {
1224                         _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
1225                 }
1226         }
1227
1228         void set_state_from_config ()
1229         {
1230                 parameter_changed ("buffering-preset");
1231                 parameter_changed ("playback-buffer-seconds");
1232                 parameter_changed ("capture-buffer-seconds");
1233         }
1234
1235 private:
1236
1237         void preset_changed ()
1238         {
1239                 int index = _buffering_presets_combo.get_active_row_number ();
1240                 if (index < 0) {
1241                         return;
1242                 }
1243                 switch (index) {
1244                 case 0:
1245                         _rc_config->set_buffering_preset (Small);
1246                         break;
1247                 case 1:
1248                         _rc_config->set_buffering_preset (Medium);
1249                         break;
1250                 case 2:
1251                         _rc_config->set_buffering_preset (Large);
1252                         break;
1253                 case 3:
1254                         _rc_config->set_buffering_preset (Custom);
1255                         break;
1256                 default:
1257                         error << string_compose (_("programming error: unknown buffering preset string, index = %1"), index) << endmsg;
1258                         break;
1259                 }
1260         }
1261
1262         void playback_changed ()
1263         {
1264                 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
1265         }
1266
1267         void capture_changed ()
1268         {
1269                 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
1270         }
1271
1272         RCConfiguration* _rc_config;
1273         Adjustment _playback_adjustment;
1274         Adjustment _capture_adjustment;
1275         HScale _playback_slider;
1276         HScale _capture_slider;
1277         ComboBoxText _buffering_presets_combo;
1278 };
1279
1280 class ControlSurfacesOptions : public OptionEditorBox
1281 {
1282 public:
1283         ControlSurfacesOptions (Gtk::Window& parent)
1284                 : _parent (parent)
1285                 , _ignore_view_change (0)
1286         {
1287                 _store = ListStore::create (_model);
1288                 _view.set_model (_store);
1289                 _view.append_column (_("Control Surface Protocol"), _model.name);
1290                 _view.get_column(0)->set_resizable (true);
1291                 _view.get_column(0)->set_expand (true);
1292                 _view.append_column_editable (_("Enabled"), _model.enabled);
1293                 _view.append_column_editable (_("Feedback"), _model.feedback);
1294
1295                 _box->pack_start (_view, false, false);
1296
1297                 Label* label = manage (new Label);
1298                 label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
1299
1300                 _box->pack_start (*label, false, false);
1301                 label->show ();
1302
1303                 ControlProtocolManager& m = ControlProtocolManager::instance ();
1304                 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
1305                                                 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
1306
1307                 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
1308                 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
1309         }
1310
1311         void parameter_changed (std::string const &)
1312         {
1313
1314         }
1315
1316         void set_state_from_config ()
1317         {
1318                 _store->clear ();
1319
1320                 ControlProtocolManager& m = ControlProtocolManager::instance ();
1321                 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
1322
1323                         if (!(*i)->mandatory) {
1324                                 TreeModel::Row r = *_store->append ();
1325                                 r[_model.name] = (*i)->name;
1326                                 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
1327                                 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
1328                                 r[_model.protocol_info] = *i;
1329                         }
1330                 }
1331         }
1332
1333 private:
1334
1335         void protocol_status_changed (ControlProtocolInfo* cpi) {
1336                 /* find the row */
1337                 TreeModel::Children rows = _store->children();
1338
1339                 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
1340                         string n = ((*x)[_model.name]);
1341
1342                         if ((*x)[_model.protocol_info] == cpi) {
1343                                 _ignore_view_change++;
1344                                 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
1345                                 _ignore_view_change--;
1346                                 break;
1347                         }
1348                 }
1349         }
1350
1351         void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
1352         {
1353                 TreeModel::Row r = *i;
1354
1355                 if (_ignore_view_change) {
1356                         return;
1357                 }
1358
1359                 ControlProtocolInfo* cpi = r[_model.protocol_info];
1360                 if (!cpi) {
1361                         return;
1362                 }
1363
1364                 bool const was_enabled = (cpi->protocol != 0);
1365                 bool const is_enabled = r[_model.enabled];
1366
1367
1368                 if (was_enabled != is_enabled) {
1369
1370                         if (!was_enabled) {
1371                                 ControlProtocolManager::instance().activate (*cpi);
1372                         } else {
1373                                 ControlProtocolManager::instance().deactivate (*cpi);
1374                         }
1375                 }
1376
1377                 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
1378                 bool const is_feedback = r[_model.feedback];
1379
1380                 if (was_feedback != is_feedback && cpi->protocol) {
1381                         cpi->protocol->set_feedback (is_feedback);
1382                 }
1383         }
1384
1385         void edit_clicked (GdkEventButton* ev)
1386         {
1387                 if (ev->type != GDK_2BUTTON_PRESS) {
1388                         return;
1389                 }
1390
1391                 std::string name;
1392                 ControlProtocolInfo* cpi;
1393                 TreeModel::Row row;
1394
1395                 row = *(_view.get_selection()->get_selected());
1396                 if (!row[_model.enabled]) {
1397                         return;
1398                 }
1399                 cpi = row[_model.protocol_info];
1400                 if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
1401                         return;
1402                 }
1403                 Box* box = (Box*) cpi->protocol->get_gui ();
1404                 if (!box) {
1405                         return;
1406                 }
1407                 if (box->get_parent()) {
1408                         static_cast<ArdourWindow*>(box->get_parent())->present();
1409                         return;
1410                 }
1411                 string title = row[_model.name];
1412                 /* once created, the window is managed by the surface itself (as ->get_parent())
1413                  * Surface's tear_down_gui() is called on session close, when de-activating
1414                  * or re-initializing a surface.
1415                  * tear_down_gui() hides an deletes the Window if it exists.
1416                  */
1417                 ArdourWindow* win = new ArdourWindow (_parent, title);
1418                 win->set_title ("Control Protocol Options");
1419                 win->add (*box);
1420                 box->show ();
1421                 win->present ();
1422         }
1423
1424         class ControlSurfacesModelColumns : public TreeModelColumnRecord
1425         {
1426         public:
1427
1428                 ControlSurfacesModelColumns ()
1429                 {
1430                         add (name);
1431                         add (enabled);
1432                         add (feedback);
1433                         add (protocol_info);
1434                 }
1435
1436                 TreeModelColumn<string> name;
1437                 TreeModelColumn<bool> enabled;
1438                 TreeModelColumn<bool> feedback;
1439                 TreeModelColumn<ControlProtocolInfo*> protocol_info;
1440         };
1441
1442         Glib::RefPtr<ListStore> _store;
1443         ControlSurfacesModelColumns _model;
1444         TreeView _view;
1445         Gtk::Window& _parent;
1446         PBD::ScopedConnection protocol_status_connection;
1447         uint32_t _ignore_view_change;
1448 };
1449
1450 class VideoTimelineOptions : public OptionEditorBox
1451 {
1452 public:
1453         VideoTimelineOptions (RCConfiguration* c)
1454                 : _rc_config (c)
1455                 , _show_video_export_info_button (_("Show Video Export Info before export"))
1456                 , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
1457                 , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
1458         {
1459                 Table* t = manage (new Table (2, 6));
1460                 t->set_spacings (4);
1461
1462                 t->attach (_video_advanced_setup_button, 0, 2, 0, 1);
1463                 _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
1464                 Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
1465                                             _("<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."));
1466
1467                 Label* l = manage (new Label (_("Video Server URL:")));
1468                 l->set_alignment (0, 0.5);
1469                 t->attach (*l, 0, 1, 1, 2, FILL);
1470                 t->attach (_video_server_url_entry, 1, 2, 1, 2, FILL);
1471                 Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
1472                                             _("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"));
1473
1474                 l = manage (new Label (_("Video Folder:")));
1475                 l->set_alignment (0, 0.5);
1476                 t->attach (*l, 0, 1, 2, 3, FILL);
1477                 t->attach (_video_server_docroot_entry, 1, 2, 2, 3);
1478                 Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
1479                                             _("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."));
1480
1481                 /* small vspace  y=3..4 */
1482
1483                 t->attach (_show_video_export_info_button, 0, 2, 4, 5);
1484                 _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
1485                 Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
1486                                             _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
1487
1488                 t->attach (_show_video_server_dialog_button, 0, 2, 5, 6);
1489                 _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
1490                 Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
1491                                             _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
1492
1493                 _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1494                 _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1495                 _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1496                 _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1497
1498                 _box->pack_start (*t,true,true);
1499         }
1500
1501         void server_url_changed ()
1502         {
1503                 _rc_config->set_video_server_url (_video_server_url_entry.get_text());
1504         }
1505
1506         void server_docroot_changed ()
1507         {
1508                 _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
1509         }
1510
1511         void show_video_export_info_toggled ()
1512         {
1513                 bool const x = _show_video_export_info_button.get_active ();
1514                 _rc_config->set_show_video_export_info (x);
1515         }
1516
1517         void show_video_server_dialog_toggled ()
1518         {
1519                 bool const x = _show_video_server_dialog_button.get_active ();
1520                 _rc_config->set_show_video_server_dialog (x);
1521         }
1522
1523         void video_advanced_setup_toggled ()
1524         {
1525                 bool const x = _video_advanced_setup_button.get_active ();
1526                 _rc_config->set_video_advanced_setup(x);
1527         }
1528
1529         void parameter_changed (string const & p)
1530         {
1531                 if (p == "video-server-url") {
1532                         _video_server_url_entry.set_text (_rc_config->get_video_server_url());
1533                 } else if (p == "video-server-docroot") {
1534                         _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
1535                 } else if (p == "show-video-export-info") {
1536                         bool const x = _rc_config->get_show_video_export_info();
1537                         _show_video_export_info_button.set_active (x);
1538                 } else if (p == "show-video-server-dialog") {
1539                         bool const x = _rc_config->get_show_video_server_dialog();
1540                         _show_video_server_dialog_button.set_active (x);
1541                 } else if (p == "video-advanced-setup") {
1542                         bool const x = _rc_config->get_video_advanced_setup();
1543                         _video_advanced_setup_button.set_active(x);
1544                         _video_server_docroot_entry.set_sensitive(x);
1545                         _video_server_url_entry.set_sensitive(x);
1546                 }
1547         }
1548
1549         void set_state_from_config ()
1550         {
1551                 parameter_changed ("video-server-url");
1552                 parameter_changed ("video-server-docroot");
1553                 parameter_changed ("video-monitor-setup-dialog");
1554                 parameter_changed ("show-video-export-info");
1555                 parameter_changed ("show-video-server-dialog");
1556                 parameter_changed ("video-advanced-setup");
1557         }
1558
1559 private:
1560         RCConfiguration* _rc_config;
1561         Entry _video_server_url_entry;
1562         Entry _video_server_docroot_entry;
1563         CheckButton _show_video_export_info_button;
1564         CheckButton _show_video_server_dialog_button;
1565         CheckButton _video_advanced_setup_button;
1566 };
1567
1568 class PluginOptions : public OptionEditorBox
1569 {
1570 public:
1571         PluginOptions (RCConfiguration* c)
1572                 : _rc_config (c)
1573                 , _display_plugin_scan_progress (_("Always Display Plugin Scan Progress"))
1574                 , _discover_vst_on_start (_("Scan for [new] VST Plugins on Application Start"))
1575                 , _discover_au_on_start (_("Scan for AudioUnit Plugins on Application Start"))
1576                 , _verbose_plugin_scan (_("Verbose Plugin Scan"))
1577                 , _timeout_adjustment (0, 0, 3000, 50, 50)
1578                 , _timeout_slider (_timeout_adjustment)
1579         {
1580                 Label *l;
1581                 std::stringstream ss;
1582                 Table* t = manage (new Table (2, 6));
1583                 t->set_spacings (4);
1584                 Button* b;
1585                 int n = 0;
1586
1587                 ss << "<b>" << _("General") << "</b>";
1588                 l = manage (left_aligned_label (ss.str()));
1589                 l->set_use_markup (true);
1590                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1591                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1592
1593                 b = manage (new Button (_("Scan for Plugins")));
1594                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::refresh_clicked));
1595                 t->attach (*b, 0, 2, n, n+1, FILL); ++n;
1596
1597                 t->attach (_display_plugin_scan_progress, 0, 2, n, n+1); ++n;
1598                 _display_plugin_scan_progress.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::display_plugin_scan_progress_toggled));
1599                 Gtkmm2ext::UI::instance()->set_tip (_display_plugin_scan_progress,
1600                                             _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
1601
1602 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
1603                 _timeout_slider.set_digits (0);
1604                 _timeout_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &PluginOptions::timeout_changed));
1605
1606                 Gtkmm2ext::UI::instance()->set_tip(_timeout_slider,
1607                          _("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."));
1608
1609                 l = manage (left_aligned_label (_("Scan Time Out [deciseconds]")));;
1610                 HBox* h = manage (new HBox);
1611                 h->set_spacing (4);
1612                 h->pack_start (*l, false, false);
1613                 h->pack_start (_timeout_slider, true, true);
1614                 t->attach (*h, 0, 2, n, n+1); ++n;
1615
1616                 ss.str("");
1617                 ss << "<b>" << _("VST") << "</b>";
1618                 l = manage (left_aligned_label (ss.str()));
1619                 l->set_use_markup (true);
1620                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1621                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1622
1623                 b = manage (new Button (_("Clear VST Cache")));
1624                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_cache_clicked));
1625                 t->attach (*b, 0, 1, n, n+1, FILL);
1626
1627                 b = manage (new Button (_("Clear VST Blacklist")));
1628                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_blacklist_clicked));
1629                 t->attach (*b, 1, 2, n, n+1, FILL);
1630                 ++n;
1631
1632                 t->attach (_discover_vst_on_start, 0, 2, n, n+1); ++n;
1633                 _discover_vst_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_vst_on_start_toggled));
1634                 Gtkmm2ext::UI::instance()->set_tip (_discover_vst_on_start,
1635                                             _("<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"));
1636
1637 #ifdef LXVST_SUPPORT
1638                 t->attach (*manage (right_aligned_label (_("Linux VST Path:"))), 0, 1, n, n+1);
1639                 b = manage (new Button (_("Edit")));
1640                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_lxvst_path_clicked));
1641                 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1642 #endif
1643
1644 #ifdef WINDOWS_VST_SUPPORT
1645                 t->attach (*manage (right_aligned_label (_("Windows VST Path:"))), 0, 1, n, n+1);
1646                 b = manage (new Button (_("Edit")));
1647                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_vst_path_clicked));
1648                 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1649
1650                 // currently verbose logging is only implemented for Windows VST.
1651                 t->attach (_verbose_plugin_scan, 0, 2, n, n+1); ++n;
1652                 _verbose_plugin_scan.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::verbose_plugin_scan_toggled));
1653                 Gtkmm2ext::UI::instance()->set_tip (_verbose_plugin_scan,
1654                                             _("<b>When enabled</b> additional information for every plugin is added to the Log Window."));
1655 #endif
1656 #endif // any VST
1657
1658 #ifdef AUDIOUNIT_SUPPORT
1659                 ss.str("");
1660                 ss << "<b>" << _("Audio Unit") << "</b>";
1661                 l = manage (left_aligned_label (ss.str()));
1662                 l->set_use_markup (true);
1663                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1664                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1665
1666                 t->attach (_discover_au_on_start, 0, 2, n, n+1); ++n;
1667                 _discover_au_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_au_on_start_toggled));
1668                 Gtkmm2ext::UI::instance()->set_tip (_discover_au_on_start,
1669                                             _("<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."));
1670
1671                 ++n;
1672                 b = manage (new Button (_("Clear AU Cache")));
1673                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_cache_clicked));
1674                 t->attach (*b, 0, 1, n, n+1, FILL);
1675
1676                 b = manage (new Button (_("Clear AU Blacklist")));
1677                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_blacklist_clicked));
1678                 t->attach (*b, 1, 2, n, n+1, FILL);
1679                 ++n;
1680 #endif
1681
1682                 _box->pack_start (*t,true,true);
1683         }
1684
1685         void parameter_changed (string const & p) {
1686                 if (p == "show-plugin-scan-window") {
1687                         bool const x = UIConfiguration::instance().get_show_plugin_scan_window();
1688                         _display_plugin_scan_progress.set_active (x);
1689                 }
1690                 else if (p == "discover-vst-on-start") {
1691                         bool const x = _rc_config->get_discover_vst_on_start();
1692                         _discover_vst_on_start.set_active (x);
1693                 }
1694                 else if (p == "vst-scan-timeout") {
1695                         int const x = _rc_config->get_vst_scan_timeout();
1696                         _timeout_adjustment.set_value (x);
1697                 }
1698                 else if (p == "discover-audio-units") {
1699                         bool const x = _rc_config->get_discover_audio_units();
1700                         _discover_au_on_start.set_active (x);
1701                 }
1702                 else if (p == "verbose-plugin-scan") {
1703                         bool const x = _rc_config->get_verbose_plugin_scan();
1704                         _verbose_plugin_scan.set_active (x);
1705                 }
1706         }
1707
1708         void set_state_from_config () {
1709                 parameter_changed ("show-plugin-scan-window");
1710                 parameter_changed ("discover-vst-on-start");
1711                 parameter_changed ("vst-scan-timeout");
1712                 parameter_changed ("discover-audio-units");
1713                 parameter_changed ("verbose-plugin-scan");
1714         }
1715
1716 private:
1717         RCConfiguration* _rc_config;
1718         CheckButton _display_plugin_scan_progress;
1719         CheckButton _discover_vst_on_start;
1720         CheckButton _discover_au_on_start;
1721         CheckButton _verbose_plugin_scan;
1722         Adjustment _timeout_adjustment;
1723         HScale _timeout_slider;
1724
1725         void display_plugin_scan_progress_toggled () {
1726                 bool const x = _display_plugin_scan_progress.get_active();
1727                 UIConfiguration::instance().set_show_plugin_scan_window(x);
1728         }
1729
1730         void discover_vst_on_start_toggled () {
1731                 bool const x = _discover_vst_on_start.get_active();
1732                 _rc_config->set_discover_vst_on_start(x);
1733         }
1734
1735         void discover_au_on_start_toggled () {
1736                 bool const x = _discover_au_on_start.get_active();
1737                 _rc_config->set_discover_audio_units(x);
1738         }
1739
1740         void verbose_plugin_scan_toggled () {
1741                 bool const x = _verbose_plugin_scan.get_active();
1742                 _rc_config->set_verbose_plugin_scan(x);
1743         }
1744
1745         void timeout_changed () {
1746                 int x = floor(_timeout_adjustment.get_value());
1747                 _rc_config->set_vst_scan_timeout(x);
1748         }
1749
1750         void clear_vst_cache_clicked () {
1751                 PluginManager::instance().clear_vst_cache();
1752         }
1753
1754         void clear_vst_blacklist_clicked () {
1755                 PluginManager::instance().clear_vst_blacklist();
1756         }
1757
1758         void clear_au_cache_clicked () {
1759                 PluginManager::instance().clear_au_cache();
1760         }
1761
1762         void clear_au_blacklist_clicked () {
1763                 PluginManager::instance().clear_au_blacklist();
1764         }
1765
1766
1767         void edit_vst_path_clicked () {
1768                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1769                                 _("Set Windows VST Search Path"),
1770                                 _rc_config->get_plugin_path_vst(),
1771                                 PluginManager::instance().get_default_windows_vst_path()
1772                         );
1773                 ResponseType r = (ResponseType) pd->run ();
1774                 pd->hide();
1775                 if (r == RESPONSE_ACCEPT) {
1776                         _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
1777                 }
1778                 delete pd;
1779         }
1780
1781         // todo consolidate with edit_vst_path_clicked..
1782         void edit_lxvst_path_clicked () {
1783                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1784                                 _("Set Linux VST Search Path"),
1785                                 _rc_config->get_plugin_path_lxvst(),
1786                                 PluginManager::instance().get_default_lxvst_path()
1787                                 );
1788                 ResponseType r = (ResponseType) pd->run ();
1789                 pd->hide();
1790                 if (r == RESPONSE_ACCEPT) {
1791                         _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
1792                 }
1793                 delete pd;
1794         }
1795
1796         void refresh_clicked () {
1797                 PluginManager::instance().refresh();
1798         }
1799 };
1800
1801
1802 /** A class which allows control of visibility of some editor components usign
1803  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
1804  *  which has the correct members, but with null widget pointers.  This
1805  *  class allows the user to set visibility of the members, the details
1806  *  of which are stored in a configuration variable which can be watched
1807  *  by parts of the editor that actually contain the widgets whose visibility
1808  *  is being controlled.
1809  */
1810
1811 class VisibilityOption : public Option
1812 {
1813 public:
1814         /** @param name User-visible name for this group.
1815          *  @param g `Dummy' VisibilityGroup (as described above).
1816          *  @param get Method to get the value of the appropriate configuration variable.
1817          *  @param set Method to set the value of the appropriate configuration variable.
1818          */
1819         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1820                 : Option (g->get_state_name(), name)
1821                 , _heading (name)
1822                 , _visibility_group (g)
1823                 , _get (get)
1824                 , _set (set)
1825         {
1826                 /* Watch for changes made by the user to our members */
1827                 _visibility_group->VisibilityChanged.connect_same_thread (
1828                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1829                         );
1830         }
1831
1832         void set_state_from_config ()
1833         {
1834                 /* Set our state from the current configuration */
1835                 _visibility_group->set_state (_get ());
1836         }
1837
1838         void add_to_page (OptionEditorPage* p)
1839         {
1840                 _heading.add_to_page (p);
1841                 add_widget_to_page (p, _visibility_group->list_view ());
1842         }
1843
1844         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1845
1846 private:
1847         void changed ()
1848         {
1849                 /* The user has changed something, so reflect this change
1850                    in the RCConfiguration.
1851                 */
1852                 _set (_visibility_group->get_state_value ());
1853         }
1854
1855         OptionEditorHeading _heading;
1856         VisibilityGroup* _visibility_group;
1857         sigc::slot<std::string> _get;
1858         sigc::slot<bool, std::string> _set;
1859         PBD::ScopedConnection _visibility_group_connection;
1860 };
1861
1862
1863
1864 RCOptionEditor::RCOptionEditor ()
1865         : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
1866         , _rc_config (Config)
1867         , _mixer_strip_visibility ("mixer-element-visibility")
1868 {
1869         /* MISC */
1870
1871         uint32_t hwcpus = hardware_concurrency ();
1872         BoolOption* bo;
1873         BoolComboOption* bco;
1874
1875         if (hwcpus > 1) {
1876                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
1877
1878                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
1879                         "processor-usage",
1880                         _("Signal processing uses"),
1881                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
1882                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
1883                         );
1884
1885                 procs->add (-1, _("all but one processor"));
1886                 procs->add (0, _("all available processors"));
1887
1888                 for (uint32_t i = 1; i <= hwcpus; ++i) {
1889                         procs->add (i, string_compose (_("%1 processors"), i));
1890                 }
1891
1892                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
1893
1894                 add_option (_("Misc"), procs);
1895         }
1896
1897         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
1898
1899         add_option (_("Misc"), new UndoOptions (_rc_config));
1900
1901         add_option (_("Misc"),
1902              new BoolOption (
1903                      "verify-remove-last-capture",
1904                      _("Verify removal of last capture"),
1905                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
1906                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
1907                      ));
1908
1909         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
1910
1911         add_option (_("Misc"),
1912              new BoolOption (
1913                      "periodic-safety-backups",
1914                      _("Make periodic backups of the session file"),
1915                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1916                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1917                      ));
1918
1919         add_option (_("Misc"),
1920              new BoolOption (
1921                      "only-copy-imported-files",
1922                      _("Always copy imported files"),
1923                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_only_copy_imported_files),
1924                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_only_copy_imported_files)
1925                      ));
1926
1927         add_option (_("Misc"), new DirectoryOption (
1928                             X_("default-session-parent-dir"),
1929                             _("Default folder for new sessions:"),
1930                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
1931                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
1932                             ));
1933
1934         add_option (_("Misc"),
1935              new SpinOption<uint32_t> (
1936                      "max-recent-sessions",
1937                      _("Maximum number of recent sessions"),
1938                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
1939                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
1940                      0, 1000, 1, 20
1941                      ));
1942
1943         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
1944
1945         add_option (_("Misc"), new ClickOptions (_rc_config, this));
1946
1947         add_option (_("Misc"),
1948              new FaderOption (
1949                      "click-gain",
1950                      _("Click gain level"),
1951                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
1952                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
1953                      ));
1954
1955         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
1956
1957         add_option (_("Misc"),
1958              new SpinOption<double> (
1959                      "automation-thinning-factor",
1960                      _("Thinning factor (larger value => less data)"),
1961                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
1962                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
1963                      0, 1000, 1, 20
1964                      ));
1965
1966         add_option (_("Misc"),
1967              new SpinOption<double> (
1968                      "automation-interval-msecs",
1969                      _("Automation sampling interval (milliseconds)"),
1970                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
1971                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
1972                      1, 1000, 1, 20
1973                      ));
1974
1975         /* TRANSPORT */
1976
1977         add_option (_("Transport"), new OptionEditorHeading (S_("Transport Options")));
1978
1979         BoolOption* tsf;
1980
1981         tsf = new BoolOption (
1982                      "latched-record-enable",
1983                      _("Keep record-enable engaged on stop"),
1984                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
1985                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
1986                      );
1987         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1988         add_option (_("Transport"), tsf);
1989
1990         tsf = new BoolOption (
1991                      "loop-is-mode",
1992                      _("Play loop is a transport mode"),
1993                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
1994                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
1995                      );
1996         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1997                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
1998                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
1999         add_option (_("Transport"), tsf);
2000
2001         tsf = new BoolOption (
2002                      "stop-recording-on-xrun",
2003                      _("Stop recording when an xrun occurs"),
2004                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
2005                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
2006                      );
2007         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
2008                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
2009                                                             PROGRAM_NAME));
2010         add_option (_("Transport"), tsf);
2011
2012         tsf = new BoolOption (
2013                      "create-xrun-marker",
2014                      _("Create markers where xruns occur"),
2015                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
2016                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
2017                      );
2018         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
2019         add_option (_("Transport"), tsf);
2020
2021         tsf = new BoolOption (
2022                      "stop-at-session-end",
2023                      _("Stop at the end of the session"),
2024                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
2025                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
2026                      );
2027         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
2028                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
2029                                                               "when it reaches the current session end marker\n\n"
2030                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
2031                                                             PROGRAM_NAME));
2032         add_option (_("Transport"), tsf);
2033
2034         tsf = new BoolOption (
2035                      "seamless-loop",
2036                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
2037                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
2038                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
2039                      );
2040         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
2041                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
2042                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
2043                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
2044                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
2045         add_option (_("Transport"), tsf);
2046
2047         tsf = new BoolOption (
2048                      "disable-disarm-during-roll",
2049                      _("Disable per-track record disarm while rolling"),
2050                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
2051                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
2052                      );
2053         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"));
2054         add_option (_("Transport"), tsf);
2055
2056         tsf = new BoolOption (
2057                      "quieten_at_speed",
2058                      _("12dB gain reduction during fast-forward and fast-rewind"),
2059                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
2060                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
2061                      );
2062         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
2063                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
2064         add_option (_("Transport"), tsf);
2065
2066         ComboOption<float>* psc = new ComboOption<float> (
2067                      "preroll-seconds",
2068                      _("Preroll"),
2069                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_preroll_seconds),
2070                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_preroll_seconds)
2071                      );
2072         Gtkmm2ext::UI::instance()->set_tip (psc->tip_widget(),
2073                                             (_("The amount of preroll (in seconds) to apply when <b>Play with Preroll</b> is initiated.\n\n"
2074                                                "If <b>Follow Edits</b> is enabled, the preroll is applied to the playhead position when a region is selected or trimmed.")));
2075         psc->add (0.0, _("0 (no pre-roll)"));
2076         psc->add (0.1, _("0.1 second"));
2077         psc->add (0.25, _("0.25 second"));
2078         psc->add (0.5, _("0.5 second"));
2079         psc->add (1.0, _("1.0 second"));
2080         psc->add (2.0, _("2.0 seconds"));
2081         add_option (_("Transport"), psc);
2082         
2083         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
2084
2085         _sync_source = new ComboOption<SyncSource> (
2086                 "sync-source",
2087                 _("External timecode source"),
2088                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
2089                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
2090                 );
2091
2092         add_option (_("Transport"), _sync_source);
2093
2094         _sync_framerate = new BoolOption (
2095                      "timecode-sync-frame-rate",
2096                      _("Match session video frame rate to external timecode"),
2097                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
2098                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
2099                      );
2100         Gtkmm2ext::UI::instance()->set_tip
2101                 (_sync_framerate->tip_widget(),
2102                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
2103                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
2104                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
2105                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
2106                                    "timecode standard and the session standard."), PROGRAM_NAME));
2107
2108         add_option (_("Transport"), _sync_framerate);
2109
2110         _sync_genlock = new BoolOption (
2111                 "timecode-source-is-synced",
2112                 _("Sync-lock timecode to clock (disable drift compensation)"),
2113                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
2114                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
2115                 );
2116         Gtkmm2ext::UI::instance()->set_tip
2117                 (_sync_genlock->tip_widget(),
2118                  string_compose (_("<b>When enabled</b> %1 will never varispeed when slaved to external timecode. "
2119                                    "Sync Lock indicates that the selected external timecode source shares clock-sync "
2120                                    "(Black &amp; Burst, Wordclock, etc) with the audio interface. "
2121                                    "This option disables drift compensation. The transport speed is fixed at 1.0. "
2122                                    "Vari-speed LTC will be ignored and cause drift."
2123                                    "\n\n"
2124                                    "<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
2125                                    "timecode sources shares clock sync."
2126                                   ), PROGRAM_NAME));
2127
2128
2129         add_option (_("Transport"), _sync_genlock);
2130
2131         _sync_source_2997 = new BoolOption (
2132                 "timecode-source-2997",
2133                 _("Lock to 29.9700 fps instead of 30000/1001"),
2134                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
2135                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
2136                 );
2137         Gtkmm2ext::UI::instance()->set_tip
2138                 (_sync_source_2997->tip_widget(),
2139                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
2140                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
2141                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
2142                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
2143                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
2144                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
2145                          ));
2146
2147         add_option (_("Transport"), _sync_source_2997);
2148
2149         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
2150
2151         _ltc_port = new ComboStringOption (
2152                 "ltc-source-port",
2153                 _("LTC incoming port"),
2154                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
2155                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
2156                 );
2157
2158         vector<string> physical_inputs;
2159         physical_inputs.push_back (_("None"));
2160         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
2161         _ltc_port->set_popdown_strings (physical_inputs);
2162
2163         populate_sync_options ();
2164
2165         add_option (_("Transport"), _ltc_port);
2166
2167         // TODO; rather disable this button than not compile it..
2168         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
2169
2170         add_option (_("Transport"),
2171                     new BoolOption (
2172                             "send-ltc",
2173                             _("Enable LTC generator"),
2174                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
2175                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
2176                             ));
2177
2178         _ltc_send_continuously = new BoolOption (
2179                             "ltc-send-continuously",
2180                             _("Send LTC while stopped"),
2181                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
2182                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
2183                             );
2184         Gtkmm2ext::UI::instance()->set_tip
2185                 (_ltc_send_continuously->tip_widget(),
2186                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
2187         add_option (_("Transport"), _ltc_send_continuously);
2188
2189         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
2190         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
2191         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
2192         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
2193
2194         Gtkmm2ext::UI::instance()->set_tip
2195                 (_ltc_volume_slider->tip_widget(),
2196                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
2197
2198         add_option (_("Transport"), _ltc_volume_slider);
2199
2200         /* EDITOR */
2201
2202         add_option (_("Editor"),
2203              new BoolOption (
2204                      "rubberbanding-snaps-to-grid",
2205                      _("Make rubberband selection rectangle snap to the grid"),
2206                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
2207                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
2208                      ));
2209
2210         bo = new BoolOption (
2211                      "name-new-markers",
2212                      _("Name new markers"),
2213                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
2214                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
2215                 );
2216         add_option (_("Editor"), bo);
2217         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."
2218                                                                 "\n\nYou can always rename markers by right-clicking on them"));
2219
2220         add_option (S_("Editor"),
2221              new BoolOption (
2222                      "draggable-playhead",
2223                      _("Allow dragging of playhead"),
2224                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead),
2225                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead)
2226                      ));
2227
2228         add_option (_("Editor"),
2229              new BoolOption (
2230                      "show-track-meters",
2231                      _("Show meters on tracks in the editor"),
2232                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
2233                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_track_meters)
2234                      ));
2235
2236         add_option (_("Editor"),
2237              new BoolOption (
2238                      "show-editor-meter",
2239                      _("Display master-meter in the toolbar"),
2240                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
2241                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
2242                      ));
2243
2244 if (!Profile->get_mixbus()) {
2245         add_option (_("Editor"),
2246                     new BoolOption (
2247                             "show-zoom-tools",
2248                             _("Show zoom toolbar (if torn off)"),
2249                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_zoom_tools),
2250                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_zoom_tools)
2251                             ));
2252 }  // !mixbus
2253
2254         add_option (_("Editor"),
2255                     new BoolOption (
2256                             "update-editor-during-summary-drag",
2257                             _("Update editor window during drags of the summary"),
2258                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
2259                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
2260                             ));
2261
2262         add_option (_("Editor"),
2263             new BoolOption (
2264                     "autoscroll-editor",
2265                     _("Auto-scroll editor window when dragging near its edges"),
2266                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
2267                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
2268                     ));
2269
2270         add_option (_("Editor"),
2271              new BoolComboOption (
2272                      "show-region-gain-envelopes",
2273                      _("Show gain envelopes in audio regions"),
2274                      _("in all modes"),
2275                      _("only in Draw and Internal Edit modes"),
2276                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
2277                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
2278                      ));
2279
2280         add_option (_("Editor"), new OptionEditorHeading (_("Editor Behavior")));
2281
2282         add_option (_("Editor"),
2283              new BoolOption (
2284                      "automation-follows-regions",
2285                      _("Move relevant automation when audio regions are moved"),
2286                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
2287                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
2288                      ));
2289
2290         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
2291                         "default-fade-shape",
2292                         _("Default fade shape"),
2293                         sigc::mem_fun (*_rc_config,
2294                                 &RCConfiguration::get_default_fade_shape),
2295                         sigc::mem_fun (*_rc_config,
2296                                 &RCConfiguration::set_default_fade_shape)
2297                         );
2298
2299         fadeshape->add (FadeLinear,
2300                         _("Linear (for highly correlated material)"));
2301         fadeshape->add (FadeConstantPower, _("Constant power"));
2302         fadeshape->add (FadeSymmetric, _("Symmetric"));
2303         fadeshape->add (FadeSlow, _("Slow"));
2304         fadeshape->add (FadeFast, _("Fast"));
2305
2306         add_option (_("Editor"), fadeshape);
2307
2308
2309         bco = new BoolComboOption (
2310                      "use-overlap-equivalency",
2311                      _("Regions in active edit groups are edited together"),
2312                      _("whenever they overlap in time"),
2313                      _("only if they have identical length, position and origin"),
2314                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
2315                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
2316                      );
2317
2318         add_option (_("Editor"), bco);
2319
2320         ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
2321                 "layer-model",
2322                 _("Layering model"),
2323                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
2324                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
2325                 );
2326
2327         lm->add (LaterHigher, _("later is higher"));
2328         lm->add (Manual, _("manual layering"));
2329         add_option (_("Editor"), lm);
2330
2331         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
2332                     "region-selection-after-split",
2333                     _("After splitting selected regions, select"),
2334                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
2335                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
2336
2337         // TODO: decide which of these modes are really useful
2338         rsas->add(None, _("no regions"));
2339         // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
2340         // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
2341         rsas->add(NewlyCreatedBoth, _("newly-created regions"));
2342         // rsas->add(Existing, _("unmodified regions in the existing selection"));
2343         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
2344         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
2345         rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
2346
2347         add_option (_("Editor"), rsas);
2348         
2349         add_option (_("Editor"), new OptionEditorHeading (_("Waveforms")));
2350
2351 if (!Profile->get_mixbus()) {
2352         add_option (_("Editor"),
2353              new BoolOption (
2354                      "show-waveforms",
2355                      _("Show waveforms in regions"),
2356                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
2357                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
2358                      ));
2359 }  // !mixbus
2360
2361         add_option (_("Editor"),
2362              new BoolOption (
2363                      "show-waveforms-while-recording",
2364                      _("Show waveforms for audio while it is being recorded"),
2365                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
2366                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
2367                      ));
2368
2369         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
2370                 "waveform-scale",
2371                 _("Waveform scale"),
2372                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_scale),
2373                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_scale)
2374                 );
2375
2376         wfs->add (Linear, _("linear"));
2377         wfs->add (Logarithmic, _("logarithmic"));
2378
2379         add_option (_("Editor"), wfs);
2380
2381         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
2382                 "waveform-shape",
2383                 _("Waveform shape"),
2384                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_shape),
2385                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_shape)
2386                 );
2387
2388         wfsh->add (Traditional, _("traditional"));
2389         wfsh->add (Rectified, _("rectified"));
2390
2391         add_option (_("Editor"), wfsh);
2392
2393         add_option (_("Editor"), new ClipLevelOptions ());
2394
2395
2396         /* AUDIO */
2397
2398         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
2399
2400         add_option (_("Audio"), new BufferingOptions (_rc_config));
2401
2402         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
2403
2404         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
2405                 "monitoring-model",
2406                 _("Record monitoring handled by"),
2407                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
2408                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
2409                 );
2410
2411         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
2412                 mm->add (HardwareMonitoring, _("via Audio Driver"));
2413         }
2414
2415         string prog (PROGRAM_NAME);
2416         boost::algorithm::to_lower (prog);
2417         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
2418         mm->add (ExternalMonitoring, _("audio hardware"));
2419
2420         add_option (_("Audio"), mm);
2421
2422         add_option (_("Audio"),
2423              new BoolOption (
2424                      "tape-machine-mode",
2425                      _("Tape machine mode"),
2426                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
2427                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
2428                      ));
2429
2430 if (!Profile->get_mixbus()) {
2431         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
2432
2433         add_option (_("Audio"),
2434                     new BoolOption (
2435                             "auto-connect-standard-busses",
2436                             _("Auto-connect master/monitor busses"),
2437                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
2438                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
2439                             ));
2440
2441         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
2442                 "input-auto-connect",
2443                 _("Connect track inputs"),
2444                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
2445                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
2446                 );
2447
2448         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
2449         iac->add (ManualConnect, _("manually"));
2450
2451         add_option (_("Audio"), iac);
2452
2453         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
2454                 "output-auto-connect",
2455                 _("Connect track and bus outputs"),
2456                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
2457                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
2458                 );
2459
2460         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
2461         oac->add (AutoConnectMaster, _("automatically to master bus"));
2462         oac->add (ManualConnect, _("manually"));
2463
2464         add_option (_("Audio"), oac);
2465 }  // !mixbus
2466
2467         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
2468
2469         add_option (_("Audio"),
2470              new BoolOption (
2471                      "denormal-protection",
2472                      _("Use DC bias to protect against denormals"),
2473                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
2474                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
2475                      ));
2476
2477         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
2478                 "denormal-model",
2479                 _("Processor handling"),
2480                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
2481                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
2482                 );
2483
2484         int dmsize = 1;
2485         dm->add (DenormalNone, _("no processor handling"));
2486
2487         FPU* fpu = FPU::instance();
2488
2489         if (fpu->has_flush_to_zero()) {
2490                 ++dmsize;
2491                 dm->add (DenormalFTZ, _("use FlushToZero"));
2492         } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
2493                 _rc_config->set_denormal_model(DenormalNone);
2494         }
2495
2496         if (fpu->has_denormals_are_zero()) {
2497                 ++dmsize;
2498                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
2499         } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
2500                 _rc_config->set_denormal_model(DenormalNone);
2501         }
2502
2503         if (fpu->has_flush_to_zero() && fpu->has_denormals_are_zero()) {
2504                 ++dmsize;
2505                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
2506         } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
2507                 _rc_config->set_denormal_model(DenormalNone);
2508         }
2509
2510         if (dmsize == 1) {
2511                 dm->set_sensitive(false);
2512         }
2513
2514         add_option (_("Audio"), dm);
2515
2516         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
2517
2518         add_option (_("Audio"),
2519              new BoolOption (
2520                      "plugins-stop-with-transport",
2521                      _("Silence plugins when the transport is stopped"),
2522                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
2523                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
2524                      ));
2525
2526         add_option (_("Audio"),
2527              new BoolOption (
2528                      "new-plugins-active",
2529                      _("Make new plugins active"),
2530                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
2531                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
2532                      ));
2533
2534         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
2535
2536         add_option (_("Audio"),
2537              new BoolOption (
2538                      "auto-analyse-audio",
2539                      _("Enable automatic analysis of audio"),
2540                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
2541                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
2542                      ));
2543
2544         add_option (_("Audio"),
2545              new BoolOption (
2546                      "replicate-missing-region-channels",
2547                      _("Replicate missing region channels"),
2548                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
2549                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
2550                      ));
2551
2552         /* SOLO AND MUTE */
2553
2554         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
2555
2556         _solo_control_is_listen_control = new BoolOption (
2557                 "solo-control-is-listen-control",
2558                 _("Solo controls are Listen controls"),
2559                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
2560                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
2561                 );
2562
2563         add_option (_("Solo / mute"), _solo_control_is_listen_control);
2564
2565         add_option (_("Solo / mute"),
2566              new BoolOption (
2567                      "exclusive-solo",
2568                      _("Exclusive solo"),
2569                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2570                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2571                      ));
2572
2573         add_option (_("Solo / mute"),
2574              new BoolOption (
2575                      "show-solo-mutes",
2576                      _("Show solo muting"),
2577                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2578                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2579                      ));
2580
2581         add_option (_("Solo / mute"),
2582              new BoolOption (
2583                      "solo-mute-override",
2584                      _("Soloing overrides muting"),
2585                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2586                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2587                      ));
2588
2589         add_option (_("Solo / mute"),
2590              new FaderOption (
2591                      "solo-mute-gain",
2592                      _("Solo-in-place mute cut (dB)"),
2593                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
2594                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
2595                      ));
2596
2597         _listen_position = new ComboOption<ListenPosition> (
2598                 "listen-position",
2599                 _("Listen Position"),
2600                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
2601                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
2602                 );
2603
2604         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
2605         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
2606
2607         add_option (_("Solo / mute"), _listen_position);
2608
2609         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
2610                 "pfl-position",
2611                 _("PFL signals come from"),
2612                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
2613                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
2614                 );
2615
2616         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2617         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2618
2619         add_option (_("Solo / mute"), pp);
2620
2621         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2622                 "afl-position",
2623                 _("AFL signals come from"),
2624                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2625                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2626                 );
2627
2628         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2629         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2630
2631         add_option (_("Solo / mute"), pa);
2632
2633         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
2634
2635         add_option (_("Solo / mute"),
2636              new BoolOption (
2637                      "mute-affects-pre-fader",
2638                      _("Mute affects pre-fader sends"),
2639                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2640                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2641                      ));
2642
2643         add_option (_("Solo / mute"),
2644              new BoolOption (
2645                      "mute-affects-post-fader",
2646                      _("Mute affects post-fader sends"),
2647                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2648                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2649                      ));
2650
2651         add_option (_("Solo / mute"),
2652              new BoolOption (
2653                      "mute-affects-control-outs",
2654                      _("Mute affects control outputs"),
2655                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2656                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2657                      ));
2658
2659         add_option (_("Solo / mute"),
2660              new BoolOption (
2661                      "mute-affects-main-outs",
2662                      _("Mute affects main outputs"),
2663                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2664                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2665                      ));
2666
2667         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
2668
2669         add_option (_("Solo / mute"),
2670              new BoolOption (
2671                      "link-send-and-route-panner",
2672                      _("Link panners of Aux and External Sends with main panner by default"),
2673                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2674                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2675                      ));
2676
2677         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Preferences")));
2678
2679         add_option (_("MIDI"),
2680                     new SpinOption<float> (
2681                             "midi-readahead",
2682                             _("MIDI read-ahead time (seconds)"),
2683                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2684                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2685                             0.1, 10, 0.1, 1,
2686                             "", 1.0, 1
2687                             ));
2688
2689         add_option (_("MIDI"),
2690              new SpinOption<int32_t> (
2691                      "initial-program-change",
2692                      _("Initial program change"),
2693                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2694                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2695                      -1, 65536, 1, 10
2696                      ));
2697
2698         add_option (_("MIDI"),
2699                     new BoolOption (
2700                             "display-first-midi-bank-as-zero",
2701                             _("Display first MIDI bank/program as 0"),
2702                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2703                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2704                             ));
2705
2706         add_option (_("MIDI"),
2707              new BoolOption (
2708                      "never-display-periodic-midi",
2709                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2710                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
2711                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
2712                      ));
2713
2714         add_option (_("MIDI"),
2715              new BoolOption (
2716                      "sound-midi-notes",
2717                      _("Sound MIDI notes as they are selected in the editor"),
2718                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
2719                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
2720                      ));
2721
2722         add_option (_("MIDI"),
2723                     new BoolOption (
2724                             "midi-feedback",
2725                             _("Send MIDI control feedback"),
2726                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2727                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2728                             ));
2729
2730         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Clock")));
2731
2732         add_option (_("MIDI"),
2733                     new BoolOption (
2734                             "send-midi-clock",
2735                             _("Send MIDI Clock"),
2736                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2737                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2738                             ));
2739
2740         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Time Code (MTC)")));
2741
2742         add_option (_("MIDI"),
2743                     new BoolOption (
2744                             "send-mtc",
2745                             _("Send MIDI Time Code"),
2746                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2747                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2748                             ));
2749
2750         add_option (_("MIDI"),
2751                     new SpinOption<int> (
2752                             "mtc-qf-speed-tolerance",
2753                             _("Percentage either side of normal transport speed to transmit MTC"),
2754                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2755                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2756                             0, 20, 1, 5
2757                             ));
2758
2759         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Machine Control (MMC)")));
2760
2761         add_option (_("MIDI"),
2762                     new BoolOption (
2763                             "mmc-control",
2764                             _("Obey MIDI Machine Control commands"),
2765                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2766                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2767                             ));
2768
2769         add_option (_("MIDI"),
2770                     new BoolOption (
2771                             "send-mmc",
2772                             _("Send MIDI Machine Control commands"),
2773                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2774                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2775                             ));
2776
2777         add_option (_("MIDI"),
2778              new SpinOption<uint8_t> (
2779                      "mmc-receive-device-id",
2780                      _("Inbound MMC device ID"),
2781                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2782                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2783                      0, 128, 1, 10
2784                      ));
2785
2786         add_option (_("MIDI"),
2787              new SpinOption<uint8_t> (
2788                      "mmc-send-device-id",
2789                      _("Outbound MMC device ID"),
2790                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2791                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2792                      0, 128, 1, 10
2793                      ));
2794
2795         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2796
2797         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2798                 "midi-audition-synth-uri",
2799                 _("Midi Audition Synth (LV2)"),
2800                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2801                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2802                 );
2803
2804         audition_synth->add(X_(""), _("None"));
2805         PluginInfoList all_plugs;
2806         PluginManager& manager (PluginManager::instance());
2807 #ifdef LV2_SUPPORT
2808         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2809
2810         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2811                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2812                 if (!(*i)->is_instrument()) continue;
2813                 if ((*i)->type != ARDOUR::LV2) continue;
2814                 audition_synth->add((*i)->unique_id, (*i)->name);
2815         }
2816 #endif
2817
2818         add_option (_("MIDI"), audition_synth);
2819
2820         /* USER INTERACTION */
2821
2822         if (
2823 #ifdef PLATFORM_WINDOWS
2824                         true
2825 #else
2826                         getenv ("ARDOUR_BUNDLED")
2827 #endif
2828            )
2829         {
2830                 add_option (_("User interaction"),
2831                             new BoolOption (
2832                                     "enable-translation",
2833                                     string_compose (_("Use translations of %1 messages\n"
2834                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2835                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2836                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2837                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2838         }
2839
2840         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2841
2842         add_option (_("User interaction"), new KeyboardOptions);
2843
2844         /* Control Surfaces */
2845
2846         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2847
2848         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2849                 "remote-model",
2850                 _("Control surface remote ID"),
2851                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2852                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2853                 );
2854
2855         rm->add (UserOrdered, _("assigned by user"));
2856         rm->add (MixerOrdered, _("follows order of mixer"));
2857
2858         add_option (_("Control Surfaces"), rm);
2859
2860         /* VIDEO Timeline */
2861         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2862
2863 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2864         /* Plugin options (currrently VST only) */
2865         add_option (_("Plugins"), new PluginOptions (_rc_config));
2866 #endif
2867
2868         /* INTERFACE */
2869
2870 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
2871         BoolOption* bgc = new BoolOption (
2872                 "cairo-image-surface",
2873                 _("Disable Graphics Hardware Acceleration (requires restart)"),
2874                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_cairo_image_surface),
2875                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_cairo_image_surface)
2876                 );
2877
2878         Gtkmm2ext::UI::instance()->set_tip (bgc->tip_widget(), string_compose (
2879                                 _("Render large parts of the application user-interface in software, instead of using 2D-graphics acceleration.\nThis requires restarting %1 before having an effect"), PROGRAM_NAME));
2880         add_option (S_("Preferences|GUI"), bgc);
2881 #endif
2882
2883 #ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
2884         BoolOption* bgo = new BoolOption (
2885                 "buggy-gradients",
2886                 _("Possibly improve slow graphical performance (requires restart)"),
2887                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_buggy_gradients),
2888                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_buggy_gradients)
2889                 );
2890
2891         Gtkmm2ext::UI::instance()->set_tip (bgo->tip_widget(), string_compose (_("Disables hardware gradient rendering on buggy video drivers (\"buggy gradients patch\").\nThis requires restarting %1 before having an effect"), PROGRAM_NAME));
2892         add_option (S_("Preferences|GUI"), bgo);
2893 #endif
2894
2895         add_option (S_("Preferences|GUI"),
2896              new BoolOption (
2897                      "widget-prelight",
2898                      _("Graphically indicate mouse pointer hovering over various widgets"),
2899                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_widget_prelight),
2900                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_widget_prelight)
2901                      ));
2902
2903 #ifdef TOOLTIPS_GOT_FIXED
2904         add_option (S_("Preferences|GUI"),
2905              new BoolOption (
2906                      "use-tooltips",
2907                      _("Show tooltips if mouse hovers over a control"),
2908                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_tooltips),
2909                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_tooltips)
2910                      ));
2911 #endif
2912
2913         add_option (S_("Preferences|GUI"),
2914              new BoolOption (
2915                      "show-name-highlight",
2916                      _("Use name highlight bars in region displays (requires a restart)"),
2917                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_name_highlight),
2918                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_name_highlight)
2919                      ));
2920
2921         add_option (S_("GUI"),
2922                     new BoolOption (
2923                             "super-rapid-clock-update",
2924                             _("Update transport clock display at FPS instead of every 100ms"),
2925                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
2926                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
2927                             ));
2928
2929
2930 #ifndef GTKOSX
2931         /* font scaling does nothing with GDK/Quartz */
2932         add_option (S_("Preferences|GUI"), new FontScalingOptions ());
2933 #endif
2934
2935         /* Image cache size */
2936
2937         Gtk::Adjustment *ics = manage (new Gtk::Adjustment(0, 1, 1024, 10)); /* 1 MB to 1GB in steps of 10MB */
2938         HSliderOption *sics = new HSliderOption("waveform-cache-size",
2939                                                 _("Waveform image cache size (megabytes)"),
2940                                                 ics,
2941                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_cache_size),
2942                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_cache_size)
2943                         );
2944         sics->scale().set_digits (0);
2945         Gtkmm2ext::UI::instance()->set_tip
2946                 (sics->tip_widget(),
2947                  _("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
2948         add_option (S_("Preferences|GUI"), sics);
2949
2950 if (!ARDOUR::Profile->get_mixbus()) {
2951         /* Lock GUI timeout */
2952
2953         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2954         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2955                                                 _("Lock timeout (seconds)"),
2956                                                 lts,
2957                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_lock_gui_after_seconds),
2958                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_lock_gui_after_seconds)
2959                         );
2960         slts->scale().set_digits (0);
2961         Gtkmm2ext::UI::instance()->set_tip
2962                 (slts->tip_widget(),
2963                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2964         add_option (S_("Preferences|GUI"), slts);
2965 } // !mixbus
2966
2967         /* The names of these controls must be the same as those given in MixerStrip
2968            for the actual widgets being controlled.
2969         */
2970         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2971         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2972         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2973         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2974         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2975         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2976
2977         add_option (
2978                 S_("Preferences|GUI"),
2979                 new VisibilityOption (
2980                         _("Mixer Strip"),
2981                         &_mixer_strip_visibility,
2982                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_mixer_strip_visibility),
2983                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_mixer_strip_visibility)
2984                         )
2985                 );
2986
2987         add_option (S_("Preferences|GUI"),
2988              new BoolOption (
2989                      "default-narrow_ms",
2990                      _("Use narrow strips in the mixer by default"),
2991                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_default_narrow_ms),
2992                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
2993                      ));
2994
2995         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2996
2997         ComboOption<float>* mht = new ComboOption<float> (
2998                 "meter-hold",
2999                 _("Peak hold time"),
3000                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_hold),
3001                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_hold)
3002                 );
3003
3004         mht->add (MeterHoldOff, _("off"));
3005         mht->add (MeterHoldShort, _("short"));
3006         mht->add (MeterHoldMedium, _("medium"));
3007         mht->add (MeterHoldLong, _("long"));
3008
3009         add_option (S_("Preferences|Metering"), mht);
3010
3011         ComboOption<float>* mfo = new ComboOption<float> (
3012                 "meter-falloff",
3013                 _("DPM fall-off"),
3014                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
3015                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
3016                 );
3017
3018         mfo->add (METER_FALLOFF_OFF,      _("off"));
3019         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
3020         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
3021         mfo->add (METER_FALLOFF_SLOWISH,  _("moderate [12.0dB/sec] (DIN)"));
3022         mfo->add (METER_FALLOFF_MODERATE, _("medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
3023         mfo->add (METER_FALLOFF_MEDIUM,   _("fast [20dB/sec]"));
3024         mfo->add (METER_FALLOFF_FAST,     _("very fast [32dB/sec]"));
3025
3026         add_option (S_("Preferences|Metering"), mfo);
3027
3028         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
3029                 "meter-line-up-level",
3030                 _("Meter line-up level; 0dBu"),
3031                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_level),
3032                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_level)
3033                 );
3034
3035         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
3036         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
3037         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
3038         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3039
3040         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."));
3041
3042         add_option (S_("Preferences|Metering"), mlu);
3043
3044         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
3045                 "meter-line-up-din",
3046                 _("IEC1/DIN Meter line-up level; 0dBu"),
3047                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_din),
3048                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_din)
3049                 );
3050
3051         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
3052         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
3053         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
3054         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3055
3056         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
3057
3058         add_option (S_("Preferences|Metering"), mld);
3059
3060         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
3061                 "meter-vu-standard",
3062                 _("VU Meter standard"),
3063                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_vu_standard),
3064                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_vu_standard)
3065                 );
3066
3067         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
3068         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
3069         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
3070         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
3071
3072         add_option (S_("Preferences|Metering"), mvu);
3073
3074         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
3075         HSliderOption *mpks = new HSliderOption("meter-peak",
3076                         _("Peak threshold [dBFS]"),
3077                         mpk,
3078                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_peak),
3079                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_peak)
3080                         );
3081
3082
3083         ComboOption<MeterType>* mtm = new ComboOption<MeterType> (
3084                 "meter-type-master",
3085                 _("Default Meter Type for Master Bus"),
3086                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_master),
3087                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_master)
3088                 );
3089         mtm->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3090         mtm->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3091         mtm->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3092         mtm->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3093         mtm->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3094         mtm->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3095         mtm->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3096         mtm->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3097
3098         add_option (S_("Preferences|Metering"), mtm);
3099
3100
3101         ComboOption<MeterType>* mtb = new ComboOption<MeterType> (
3102                 "meter-type-bus",
3103                 _("Default Meter Type for Busses"),
3104                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_bus),
3105                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_bus)
3106                 );
3107         mtb->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3108         mtb->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3109         mtb->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3110         mtb->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3111         mtb->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3112         mtb->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3113         mtb->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3114         mtb->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3115
3116         add_option (S_("Preferences|Metering"), mtb);
3117
3118         ComboOption<MeterType>* mtt = new ComboOption<MeterType> (
3119                 "meter-type-track",
3120                 _("Default Meter Type for Tracks"),
3121                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_track),
3122                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_track)
3123                 );
3124         mtt->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3125         mtt->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
3126
3127         add_option (S_("Preferences|Metering"), mtt);
3128
3129
3130         Gtkmm2ext::UI::instance()->set_tip
3131                 (mpks->tip_widget(),
3132                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
3133
3134         add_option (S_("Preferences|Metering"), mpks);
3135
3136         add_option (S_("Preferences|Metering"),
3137              new BoolOption (
3138                      "meter-style-led",
3139                      _("LED meter style"),
3140                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_style_led),
3141                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_style_led)
3142                      ));
3143
3144         /* and now the theme manager */
3145
3146         ThemeManager* tm = manage (new ThemeManager);
3147         add_page (_("Theme"), *tm);
3148
3149         //trigger some parameter-changed messages which affect widget-visibility or -sensitivity
3150         parameter_changed ("send-ltc");
3151         parameter_changed ("sync-source");
3152         parameter_changed ("use-monitor-bus");
3153 }
3154
3155 void
3156 RCOptionEditor::parameter_changed (string const & p)
3157 {
3158         OptionEditor::parameter_changed (p);
3159
3160         if (p == "use-monitor-bus") {
3161                 bool const s = Config->get_use_monitor_bus ();
3162                 if (!s) {
3163                         /* we can't use this if we don't have a monitor bus */
3164                         Config->set_solo_control_is_listen_control (false);
3165                 }
3166                 _solo_control_is_listen_control->set_sensitive (s);
3167                 _listen_position->set_sensitive (s);
3168         } else if (p == "sync-source") {
3169                 _sync_source->set_sensitive (true);
3170                 if (_session) {
3171                         _sync_source->set_sensitive (!_session->config.get_external_sync());
3172                 }
3173                 switch(Config->get_sync_source()) {
3174                 case ARDOUR::MTC:
3175                 case ARDOUR::LTC:
3176                         _sync_genlock->set_sensitive (true);
3177                         _sync_framerate->set_sensitive (true);
3178                         _sync_source_2997->set_sensitive (true);
3179                         break;
3180                 default:
3181                         _sync_genlock->set_sensitive (false);
3182                         _sync_framerate->set_sensitive (false);
3183                         _sync_source_2997->set_sensitive (false);
3184                         break;
3185                 }
3186         } else if (p == "send-ltc") {
3187                 bool const s = Config->get_send_ltc ();
3188                 _ltc_send_continuously->set_sensitive (s);
3189                 _ltc_volume_slider->set_sensitive (s);
3190         }
3191 }
3192
3193 void RCOptionEditor::ltc_generator_volume_changed () {
3194         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
3195 }
3196
3197 void
3198 RCOptionEditor::populate_sync_options ()
3199 {
3200         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
3201
3202         _sync_source->clear ();
3203
3204         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
3205                 _sync_source->add (*i, sync_source_to_string (*i));
3206         }
3207
3208         if (sync_opts.empty()) {
3209                 _sync_source->set_sensitive(false);
3210         } else {
3211                 if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
3212                         _rc_config->set_sync_source(sync_opts.front());
3213                 }
3214         }
3215 }