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