first compilable version of tabbable design.
[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)
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 requires 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 VstTimeOutSliderOption : public OptionEditorBox
1087 {
1088 public:
1089         VstTimeOutSliderOption (RCConfiguration* c)
1090                 : _rc_config (c)
1091                 , _timeout_adjustment (0, 0, 3000, 50, 50)
1092                 , _timeout_slider (_timeout_adjustment)
1093         {
1094                 _timeout_slider.set_digits (0);
1095                 _timeout_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &VstTimeOutSliderOption::timeout_changed));
1096
1097                 _timeout_slider.set_draw_value(false);
1098                 _timeout_slider.add_mark(   0,  Gtk::POS_TOP, _("\u221e")); // infinity
1099                 _timeout_slider.add_mark( 300,  Gtk::POS_TOP, _("30 sec"));
1100                 _timeout_slider.add_mark( 600,  Gtk::POS_TOP, _("1 min"));
1101                 _timeout_slider.add_mark(1200,  Gtk::POS_TOP, _("2 mins"));
1102                 _timeout_slider.add_mark(1800,  Gtk::POS_TOP, _("3 mins"));
1103                 _timeout_slider.add_mark(2400,  Gtk::POS_TOP, _("4 mins"));
1104                 _timeout_slider.add_mark(3000,  Gtk::POS_TOP, _("5 mins"));
1105
1106                 Gtkmm2ext::UI::instance()->set_tip(_timeout_slider,
1107                          _("Specify the default timeout for plugin instantiation. Plugins that require more time to load will be blacklisted. A value of 0 disables the timeout."));
1108
1109                 Label* l = manage (left_aligned_label (_("Scan Time Out:")));
1110                 HBox* h = manage (new HBox);
1111                 h->set_spacing (4);
1112                 h->pack_start (*l, false, false);
1113                 h->pack_start (_timeout_slider, true, true);
1114
1115                 _box->pack_start (*h, false, false);
1116         }
1117
1118         void parameter_changed (string const & p)
1119         {
1120                 if (p == "vst-scan-timeout") {
1121                         int const x = _rc_config->get_vst_scan_timeout();
1122                         _timeout_adjustment.set_value (x);
1123                 }
1124         }
1125
1126         void set_state_from_config ()
1127         {
1128                 parameter_changed ("vst-scan-timeout");
1129         }
1130
1131 private:
1132
1133         void timeout_changed ()
1134         {
1135                 int x = floor(_timeout_adjustment.get_value());
1136                 _rc_config->set_vst_scan_timeout(x);
1137         }
1138
1139         RCConfiguration* _rc_config;
1140         Adjustment _timeout_adjustment;
1141         HScale _timeout_slider;
1142 };
1143
1144
1145
1146
1147
1148 class ClipLevelOptions : public OptionEditorBox
1149 {
1150 public:
1151         ClipLevelOptions ()
1152                 : _clip_level_adjustment (-.5, -50.0, 0.0, 0.1, 1.0) /* units of dB */
1153                 , _clip_level_slider (_clip_level_adjustment)
1154         {
1155                 _clip_level_adjustment.set_value (UIConfiguration::instance().get_waveform_clip_level ());
1156
1157                 Label* l = manage (new Label (_("Waveform Clip Level (dBFS):")));
1158                 l->set_name ("OptionsLabel");
1159
1160                 _clip_level_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1161                 HBox* h = manage (new HBox);
1162                 h->set_spacing (4);
1163                 h->pack_start (*l, false, false);
1164                 h->pack_start (_clip_level_slider, true, true);
1165
1166                 _box->pack_start (*h, false, false);
1167
1168                 _clip_level_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &ClipLevelOptions::clip_level_changed));
1169         }
1170
1171         void parameter_changed (string const & p)
1172         {
1173                 if (p == "waveform-clip-level") {
1174                         _clip_level_adjustment.set_value (UIConfiguration::instance().get_waveform_clip_level());
1175                 }
1176         }
1177
1178         void set_state_from_config ()
1179         {
1180                 parameter_changed ("waveform-clip-level");
1181         }
1182
1183 private:
1184
1185         void clip_level_changed ()
1186         {
1187                 UIConfiguration::instance().set_waveform_clip_level (_clip_level_adjustment.get_value());
1188                 /* XXX: should be triggered from the parameter changed signal */
1189                 ArdourCanvas::WaveView::set_clip_level (_clip_level_adjustment.get_value());
1190         }
1191
1192         Adjustment _clip_level_adjustment;
1193         HScale _clip_level_slider;
1194 };
1195
1196 class BufferingOptions : public OptionEditorBox
1197 {
1198 public:
1199         BufferingOptions (RCConfiguration* c)
1200                 : _rc_config (c)
1201                 , _playback_adjustment (5, 1, 60, 1, 4)
1202                 , _capture_adjustment (5, 1, 60, 1, 4)
1203                 , _playback_slider (_playback_adjustment)
1204                 , _capture_slider (_capture_adjustment)
1205         {
1206                 vector<string> presets;
1207
1208                 /* these must match the order of the enums for BufferingPreset */
1209
1210                 presets.push_back (_("Small sessions (4-16 tracks)"));
1211                 presets.push_back (_("Medium sessions (16-64 tracks)"));
1212                 presets.push_back (_("Large sessions (64+ tracks)"));
1213                 presets.push_back (_("Custom (set by sliders below)"));
1214
1215                 set_popdown_strings (_buffering_presets_combo, presets);
1216
1217                 Label* l = manage (new Label (_("Preset:")));
1218                 l->set_name ("OptionsLabel");
1219                 HBox* h = manage (new HBox);
1220                 h->set_spacing (12);
1221                 h->pack_start (*l, false, false);
1222                 h->pack_start (_buffering_presets_combo, true, true);
1223                 _box->pack_start (*h, false, false);
1224
1225                 _buffering_presets_combo.signal_changed().connect (sigc::mem_fun (*this, &BufferingOptions::preset_changed));
1226
1227                 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
1228
1229                 l = manage (new Label (_("Playback (seconds of buffering):")));
1230                 l->set_name ("OptionsLabel");
1231
1232                 _playback_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1233                 h = manage (new HBox);
1234                 h->set_spacing (4);
1235                 h->pack_start (*l, false, false);
1236                 h->pack_start (_playback_slider, true, true);
1237
1238                 _box->pack_start (*h, false, false);
1239
1240                 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
1241
1242                 l = manage (new Label (_("Recording (seconds of buffering):")));
1243                 l->set_name ("OptionsLabel");
1244
1245                 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1246                 h = manage (new HBox);
1247                 h->set_spacing (4);
1248                 h->pack_start (*l, false, false);
1249                 h->pack_start (_capture_slider, true, true);
1250
1251                 _box->pack_start (*h, false, false);
1252
1253                 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
1254                 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
1255         }
1256
1257         void parameter_changed (string const & p)
1258         {
1259                 if (p == "buffering-preset") {
1260                         switch (_rc_config->get_buffering_preset()) {
1261                         case Small:
1262                                 _playback_slider.set_sensitive (false);
1263                                 _capture_slider.set_sensitive (false);
1264                                 _buffering_presets_combo.set_active (0);
1265                                 break;
1266                         case Medium:
1267                                 _playback_slider.set_sensitive (false);
1268                                 _capture_slider.set_sensitive (false);
1269                                 _buffering_presets_combo.set_active (1);
1270                                 break;
1271                         case Large:
1272                                 _playback_slider.set_sensitive (false);
1273                                 _capture_slider.set_sensitive (false);
1274                                 _buffering_presets_combo.set_active (2);
1275                                 break;
1276                         case Custom:
1277                                 _playback_slider.set_sensitive (true);
1278                                 _capture_slider.set_sensitive (true);
1279                                 _buffering_presets_combo.set_active (3);
1280                                 break;
1281                         }
1282                 }
1283
1284                 if (p == "playback-buffer-seconds") {
1285                         _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
1286                 } else if (p == "capture-buffer-seconds") {
1287                         _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
1288                 }
1289         }
1290
1291         void set_state_from_config ()
1292         {
1293                 parameter_changed ("buffering-preset");
1294                 parameter_changed ("playback-buffer-seconds");
1295                 parameter_changed ("capture-buffer-seconds");
1296         }
1297
1298 private:
1299
1300         void preset_changed ()
1301         {
1302                 int index = _buffering_presets_combo.get_active_row_number ();
1303                 if (index < 0) {
1304                         return;
1305                 }
1306                 switch (index) {
1307                 case 0:
1308                         _rc_config->set_buffering_preset (Small);
1309                         break;
1310                 case 1:
1311                         _rc_config->set_buffering_preset (Medium);
1312                         break;
1313                 case 2:
1314                         _rc_config->set_buffering_preset (Large);
1315                         break;
1316                 case 3:
1317                         _rc_config->set_buffering_preset (Custom);
1318                         break;
1319                 default:
1320                         error << string_compose (_("programming error: unknown buffering preset string, index = %1"), index) << endmsg;
1321                         break;
1322                 }
1323         }
1324
1325         void playback_changed ()
1326         {
1327                 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
1328         }
1329
1330         void capture_changed ()
1331         {
1332                 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
1333         }
1334
1335         RCConfiguration* _rc_config;
1336         Adjustment _playback_adjustment;
1337         Adjustment _capture_adjustment;
1338         HScale _playback_slider;
1339         HScale _capture_slider;
1340         ComboBoxText _buffering_presets_combo;
1341 };
1342
1343 class ControlSurfacesOptions : public OptionEditorBox
1344 {
1345 public:
1346         ControlSurfacesOptions ()
1347                 : _ignore_view_change (0)
1348         {
1349                 _store = ListStore::create (_model);
1350                 _view.set_model (_store);
1351                 _view.append_column (_("Control Surface Protocol"), _model.name);
1352                 _view.get_column(0)->set_resizable (true);
1353                 _view.get_column(0)->set_expand (true);
1354                 _view.append_column_editable (_("Enabled"), _model.enabled);
1355                 _view.append_column_editable (_("Feedback"), _model.feedback);
1356
1357                 _box->pack_start (_view, false, false);
1358
1359                 Gtk::HBox* edit_box = manage (new Gtk::HBox);
1360                 edit_box->set_spacing(3);
1361                 _box->pack_start (*edit_box, false, false);
1362                 edit_box->show ();
1363                 
1364                 Label* label = manage (new Label);
1365                 label->set_text (_("Click to edit the settings for selected protocol ( it must be ENABLED first ):"));
1366                 edit_box->pack_start (*label, false, false);
1367                 label->show ();
1368
1369                 edit_button = manage (new Button(_("Show Protocol Settings")));
1370                 edit_button->signal_clicked().connect (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_btn_clicked));
1371                 edit_box->pack_start (*edit_button, true, true);
1372                 edit_button->set_sensitive (false);
1373                 edit_button->show ();
1374
1375                 ControlProtocolManager& m = ControlProtocolManager::instance ();
1376                 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
1377                                                 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
1378
1379                 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
1380                 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
1381                 _view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::selection_changed));
1382         }
1383
1384         void parameter_changed (std::string const &)
1385         {
1386
1387         }
1388
1389         void set_state_from_config ()
1390         {
1391                 _store->clear ();
1392
1393                 ControlProtocolManager& m = ControlProtocolManager::instance ();
1394                 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
1395
1396                         if (!(*i)->mandatory) {
1397                                 TreeModel::Row r = *_store->append ();
1398                                 r[_model.name] = (*i)->name;
1399                                 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
1400                                 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
1401                                 r[_model.protocol_info] = *i;
1402                         }
1403                 }
1404         }
1405
1406 private:
1407
1408         void protocol_status_changed (ControlProtocolInfo* cpi) {
1409                 /* find the row */
1410                 TreeModel::Children rows = _store->children();
1411
1412                 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
1413                         string n = ((*x)[_model.name]);
1414
1415                         if ((*x)[_model.protocol_info] == cpi) {
1416                                 _ignore_view_change++;
1417                                 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
1418                                 _ignore_view_change--;
1419                                 break;
1420                         }
1421                 }
1422         }
1423
1424         void selection_changed ()
1425         {
1426                 //enable the Edit button when a row is selected for editing
1427                 TreeModel::Row row = *(_view.get_selection()->get_selected());
1428                 if (row && row[_model.enabled])
1429                         edit_button->set_sensitive (true);
1430                 else
1431                         edit_button->set_sensitive (false);
1432         }
1433         
1434         void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
1435         {
1436                 TreeModel::Row r = *i;
1437
1438                 if (_ignore_view_change) {
1439                         return;
1440                 }
1441
1442                 ControlProtocolInfo* cpi = r[_model.protocol_info];
1443                 if (!cpi) {
1444                         return;
1445                 }
1446
1447                 bool const was_enabled = (cpi->protocol != 0);
1448                 bool const is_enabled = r[_model.enabled];
1449
1450
1451                 if (was_enabled != is_enabled) {
1452
1453                         if (!was_enabled) {
1454                                 ControlProtocolManager::instance().activate (*cpi);
1455                         } else {
1456                                 ControlProtocolManager::instance().deactivate (*cpi);
1457                         }
1458                 }
1459
1460                 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
1461                 bool const is_feedback = r[_model.feedback];
1462
1463                 if (was_feedback != is_feedback && cpi->protocol) {
1464                         cpi->protocol->set_feedback (is_feedback);
1465                 }
1466         }
1467
1468         void edit_btn_clicked ()
1469         {
1470                 std::string name;
1471                 ControlProtocolInfo* cpi;
1472                 TreeModel::Row row;
1473
1474                 row = *(_view.get_selection()->get_selected());
1475                 if (!row[_model.enabled]) {
1476                         return;
1477                 }
1478                 cpi = row[_model.protocol_info];
1479                 if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
1480                         return;
1481                 }
1482                 Box* box = (Box*) cpi->protocol->get_gui ();
1483                 if (!box) {
1484                         return;
1485                 }
1486                 if (box->get_parent()) {
1487                         static_cast<ArdourWindow*>(box->get_parent())->present();
1488                         return;
1489                 }
1490                 WindowTitle title (Glib::get_application_name());
1491                 title += row[_model.name];
1492                 title += _("Configuration");
1493                 /* once created, the window is managed by the surface itself (as ->get_parent())
1494                  * Surface's tear_down_gui() is called on session close, when de-activating
1495                  * or re-initializing a surface.
1496                  * tear_down_gui() hides an deletes the Window if it exists.
1497                  */
1498                 ArdourWindow* win = new ArdourWindow (*((Gtk::Window*) _view.get_toplevel()), title.get_string());
1499                 win->set_title ("Control Protocol Options");
1500                 win->add (*box);
1501                 box->show ();
1502                 win->present ();
1503         }
1504
1505         void edit_clicked (GdkEventButton* ev)
1506         {
1507                 if (ev->type != GDK_2BUTTON_PRESS) {
1508                         return;
1509                 }
1510
1511                 edit_btn_clicked();
1512         }
1513
1514         class ControlSurfacesModelColumns : public TreeModelColumnRecord
1515         {
1516         public:
1517
1518                 ControlSurfacesModelColumns ()
1519                 {
1520                         add (name);
1521                         add (enabled);
1522                         add (feedback);
1523                         add (protocol_info);
1524                 }
1525
1526                 TreeModelColumn<string> name;
1527                 TreeModelColumn<bool> enabled;
1528                 TreeModelColumn<bool> feedback;
1529                 TreeModelColumn<ControlProtocolInfo*> protocol_info;
1530         };
1531
1532         Glib::RefPtr<ListStore> _store;
1533         ControlSurfacesModelColumns _model;
1534         TreeView _view;
1535         PBD::ScopedConnection protocol_status_connection;
1536         uint32_t _ignore_view_change;
1537         Gtk::Button* edit_button;
1538 };
1539
1540 class VideoTimelineOptions : public OptionEditorBox
1541 {
1542 public:
1543         VideoTimelineOptions (RCConfiguration* c)
1544                 : _rc_config (c)
1545                 , _show_video_export_info_button (_("Show Video Export Info before export"))
1546                 , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
1547                 , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
1548         {
1549                 Table* t = manage (new Table (2, 6));
1550                 t->set_spacings (4);
1551
1552                 t->attach (_video_advanced_setup_button, 0, 2, 0, 1);
1553                 _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
1554                 Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
1555                                             _("<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."));
1556
1557                 Label* l = manage (new Label (_("Video Server URL:")));
1558                 l->set_alignment (0, 0.5);
1559                 t->attach (*l, 0, 1, 1, 2, FILL);
1560                 t->attach (_video_server_url_entry, 1, 2, 1, 2, FILL);
1561                 Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
1562                                             _("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"));
1563
1564                 l = manage (new Label (_("Video Folder:")));
1565                 l->set_alignment (0, 0.5);
1566                 t->attach (*l, 0, 1, 2, 3, FILL);
1567                 t->attach (_video_server_docroot_entry, 1, 2, 2, 3);
1568                 Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
1569                                             _("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."));
1570
1571                 /* small vspace  y=3..4 */
1572
1573                 t->attach (_show_video_export_info_button, 0, 2, 4, 5);
1574                 _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
1575                 Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
1576                                             _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
1577
1578                 t->attach (_show_video_server_dialog_button, 0, 2, 5, 6);
1579                 _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
1580                 Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
1581                                             _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
1582
1583                 _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1584                 _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1585                 _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1586                 _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1587
1588                 _box->pack_start (*t,true,true);
1589         }
1590
1591         void server_url_changed ()
1592         {
1593                 _rc_config->set_video_server_url (_video_server_url_entry.get_text());
1594         }
1595
1596         void server_docroot_changed ()
1597         {
1598                 _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
1599         }
1600
1601         void show_video_export_info_toggled ()
1602         {
1603                 bool const x = _show_video_export_info_button.get_active ();
1604                 _rc_config->set_show_video_export_info (x);
1605         }
1606
1607         void show_video_server_dialog_toggled ()
1608         {
1609                 bool const x = _show_video_server_dialog_button.get_active ();
1610                 _rc_config->set_show_video_server_dialog (x);
1611         }
1612
1613         void video_advanced_setup_toggled ()
1614         {
1615                 bool const x = _video_advanced_setup_button.get_active ();
1616                 _rc_config->set_video_advanced_setup(x);
1617         }
1618
1619         void parameter_changed (string const & p)
1620         {
1621                 if (p == "video-server-url") {
1622                         _video_server_url_entry.set_text (_rc_config->get_video_server_url());
1623                 } else if (p == "video-server-docroot") {
1624                         _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
1625                 } else if (p == "show-video-export-info") {
1626                         bool const x = _rc_config->get_show_video_export_info();
1627                         _show_video_export_info_button.set_active (x);
1628                 } else if (p == "show-video-server-dialog") {
1629                         bool const x = _rc_config->get_show_video_server_dialog();
1630                         _show_video_server_dialog_button.set_active (x);
1631                 } else if (p == "video-advanced-setup") {
1632                         bool const x = _rc_config->get_video_advanced_setup();
1633                         _video_advanced_setup_button.set_active(x);
1634                         _video_server_docroot_entry.set_sensitive(x);
1635                         _video_server_url_entry.set_sensitive(x);
1636                 }
1637         }
1638
1639         void set_state_from_config ()
1640         {
1641                 parameter_changed ("video-server-url");
1642                 parameter_changed ("video-server-docroot");
1643                 parameter_changed ("video-monitor-setup-dialog");
1644                 parameter_changed ("show-video-export-info");
1645                 parameter_changed ("show-video-server-dialog");
1646                 parameter_changed ("video-advanced-setup");
1647         }
1648
1649 private:
1650         RCConfiguration* _rc_config;
1651         Entry _video_server_url_entry;
1652         Entry _video_server_docroot_entry;
1653         CheckButton _show_video_export_info_button;
1654         CheckButton _show_video_server_dialog_button;
1655         CheckButton _video_advanced_setup_button;
1656 };
1657
1658
1659 /** A class which allows control of visibility of some editor components usign
1660  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
1661  *  which has the correct members, but with null widget pointers.  This
1662  *  class allows the user to set visibility of the members, the details
1663  *  of which are stored in a configuration variable which can be watched
1664  *  by parts of the editor that actually contain the widgets whose visibility
1665  *  is being controlled.
1666  */
1667
1668 class VisibilityOption : public Option
1669 {
1670 public:
1671         /** @param name User-visible name for this group.
1672          *  @param g `Dummy' VisibilityGroup (as described above).
1673          *  @param get Method to get the value of the appropriate configuration variable.
1674          *  @param set Method to set the value of the appropriate configuration variable.
1675          */
1676         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1677                 : Option (g->get_state_name(), name)
1678                 , _heading (name)
1679                 , _visibility_group (g)
1680                 , _get (get)
1681                 , _set (set)
1682         {
1683                 /* Watch for changes made by the user to our members */
1684                 _visibility_group->VisibilityChanged.connect_same_thread (
1685                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1686                         );
1687         }
1688
1689         void set_state_from_config ()
1690         {
1691                 /* Set our state from the current configuration */
1692                 _visibility_group->set_state (_get ());
1693         }
1694
1695         void add_to_page (OptionEditorPage* p)
1696         {
1697                 _heading.add_to_page (p);
1698                 add_widget_to_page (p, _visibility_group->list_view ());
1699         }
1700
1701         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1702
1703 private:
1704         void changed ()
1705         {
1706                 /* The user has changed something, so reflect this change
1707                    in the RCConfiguration.
1708                 */
1709                 _set (_visibility_group->get_state_value ());
1710         }
1711
1712         OptionEditorHeading _heading;
1713         VisibilityGroup* _visibility_group;
1714         sigc::slot<std::string> _get;
1715         sigc::slot<bool, std::string> _set;
1716         PBD::ScopedConnection _visibility_group_connection;
1717 };
1718
1719
1720
1721 RCOptionEditor::RCOptionEditor ()
1722         : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
1723         , Tabbable (*this, _("Preferences"))
1724         , _rc_config (Config)
1725         , _mixer_strip_visibility ("mixer-element-visibility")
1726 {
1727         /* MISC */
1728
1729         uint32_t hwcpus = hardware_concurrency ();
1730         BoolOption* bo;
1731         BoolComboOption* bco;
1732
1733         if (hwcpus > 1) {
1734                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
1735
1736                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
1737                         "processor-usage",
1738                         _("Signal processing uses"),
1739                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
1740                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
1741                         );
1742
1743                 procs->add (-1, _("all but one processor"));
1744                 procs->add (0, _("all available processors"));
1745
1746                 for (uint32_t i = 1; i <= hwcpus; ++i) {
1747                         procs->add (i, string_compose (_("%1 processors"), i));
1748                 }
1749
1750                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
1751
1752                 add_option (_("Misc"), procs);
1753         }
1754
1755         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
1756
1757         add_option (_("Misc"), new UndoOptions (_rc_config));
1758
1759         add_option (_("Misc"),
1760              new BoolOption (
1761                      "verify-remove-last-capture",
1762                      _("Verify removal of last capture"),
1763                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
1764                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
1765                      ));
1766
1767         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
1768
1769         add_option (_("Misc"),
1770              new BoolOption (
1771                      "periodic-safety-backups",
1772                      _("Make periodic backups of the session file"),
1773                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1774                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1775                      ));
1776
1777         add_option (_("Misc"),
1778              new BoolOption (
1779                      "only-copy-imported-files",
1780                      _("Always copy imported files"),
1781                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_only_copy_imported_files),
1782                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_only_copy_imported_files)
1783                      ));
1784
1785         add_option (_("Misc"), new DirectoryOption (
1786                             X_("default-session-parent-dir"),
1787                             _("Default folder for new sessions:"),
1788                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
1789                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
1790                             ));
1791
1792         add_option (_("Misc"),
1793              new SpinOption<uint32_t> (
1794                      "max-recent-sessions",
1795                      _("Maximum number of recent sessions"),
1796                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
1797                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
1798                      0, 1000, 1, 20
1799                      ));
1800
1801         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
1802
1803         add_option (_("Misc"), new ClickOptions (_rc_config));
1804
1805         add_option (_("Misc"),
1806              new FaderOption (
1807                      "click-gain",
1808                      _("Click gain level"),
1809                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
1810                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
1811                      ));
1812
1813         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
1814
1815         add_option (_("Misc"),
1816              new SpinOption<double> (
1817                      "automation-thinning-factor",
1818                      _("Thinning factor (larger value => less data)"),
1819                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
1820                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
1821                      0, 1000, 1, 20
1822                      ));
1823
1824         add_option (_("Misc"),
1825              new SpinOption<double> (
1826                      "automation-interval-msecs",
1827                      _("Automation sampling interval (milliseconds)"),
1828                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
1829                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
1830                      1, 1000, 1, 20
1831                      ));
1832
1833         /* TRANSPORT */
1834
1835         add_option (_("Transport"), new OptionEditorHeading (S_("Playhead Behaviour")));
1836         add_option (_("Transport"), new OptionEditorHeading (S_("Transport Options")));
1837
1838         BoolOption* tsf;
1839
1840         tsf = new BoolOption (
1841                      "latched-record-enable",
1842                      _("Keep record-enable engaged on stop"),
1843                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
1844                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
1845                      );
1846         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1847         add_option (_("Transport"), tsf);
1848
1849         tsf = new BoolOption (
1850                      "loop-is-mode",
1851                      _("Play loop is a transport mode"),
1852                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
1853                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
1854                      );
1855         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1856                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
1857                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
1858         add_option (_("Transport"), tsf);
1859
1860         tsf = new BoolOption (
1861                      "stop-recording-on-xrun",
1862                      _("Stop recording when an xrun occurs"),
1863                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1864                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1865                      );
1866         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1867                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
1868                                                             PROGRAM_NAME));
1869         add_option (_("Transport"), tsf);
1870
1871         tsf = new BoolOption (
1872                      "create-xrun-marker",
1873                      _("Create markers where xruns occur"),
1874                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1875                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1876                      );
1877         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1878         add_option (_("Transport"), tsf);
1879
1880         tsf = new BoolOption (
1881                      "stop-at-session-end",
1882                      _("Stop at the end of the session"),
1883                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1884                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1885                      );
1886         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1887                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1888                                                               "when it reaches the current session end marker\n\n"
1889                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1890                                                             PROGRAM_NAME));
1891         add_option (_("Transport"), tsf);
1892
1893         tsf = new BoolOption (
1894                      "seamless-loop",
1895                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1896                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1897                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1898                      );
1899         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1900                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1901                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
1902                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
1903                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
1904         add_option (_("Transport"), tsf);
1905
1906         tsf = new BoolOption (
1907                      "disable-disarm-during-roll",
1908                      _("Disable per-track record disarm while rolling"),
1909                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1910                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1911                      );
1912         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"));
1913         add_option (_("Transport"), tsf);
1914
1915         tsf = new BoolOption (
1916                      "quieten_at_speed",
1917                      _("12dB gain reduction during fast-forward and fast-rewind"),
1918                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1919                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1920                      );
1921         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1922                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1923         add_option (_("Transport"), tsf);
1924
1925         ComboOption<float>* psc = new ComboOption<float> (
1926                      "preroll-seconds",
1927                      _("Preroll"),
1928                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_preroll_seconds),
1929                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_preroll_seconds)
1930                      );
1931         Gtkmm2ext::UI::instance()->set_tip (psc->tip_widget(),
1932                                             (_("The amount of preroll (in seconds) to apply when <b>Play with Preroll</b> is initiated.\n\n"
1933                                                "If <b>Follow Edits</b> is enabled, the preroll is applied to the playhead position when a region is selected or trimmed.")));
1934         psc->add (0.0, _("0 (no pre-roll)"));
1935         psc->add (0.1, _("0.1 second"));
1936         psc->add (0.25, _("0.25 second"));
1937         psc->add (0.5, _("0.5 second"));
1938         psc->add (1.0, _("1.0 second"));
1939         psc->add (2.0, _("2.0 seconds"));
1940         add_option (_("Transport"), psc);
1941         
1942         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1943
1944         _sync_source = new ComboOption<SyncSource> (
1945                 "sync-source",
1946                 _("External timecode source"),
1947                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1948                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1949                 );
1950
1951         add_option (_("Transport"), _sync_source);
1952
1953         _sync_framerate = new BoolOption (
1954                      "timecode-sync-frame-rate",
1955                      _("Match session video frame rate to external timecode"),
1956                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1957                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1958                      );
1959         Gtkmm2ext::UI::instance()->set_tip
1960                 (_sync_framerate->tip_widget(),
1961                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1962                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1963                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1964                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1965                                    "timecode standard and the session standard."), PROGRAM_NAME));
1966
1967         add_option (_("Transport"), _sync_framerate);
1968
1969         _sync_genlock = new BoolOption (
1970                 "timecode-source-is-synced",
1971                 _("Sync-lock timecode to clock (disable drift compensation)"),
1972                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1973                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1974                 );
1975         Gtkmm2ext::UI::instance()->set_tip
1976                 (_sync_genlock->tip_widget(),
1977                  string_compose (_("<b>When enabled</b> %1 will never varispeed when slaved to external timecode. "
1978                                    "Sync Lock indicates that the selected external timecode source shares clock-sync "
1979                                    "(Black &amp; Burst, Wordclock, etc) with the audio interface. "
1980                                    "This option disables drift compensation. The transport speed is fixed at 1.0. "
1981                                    "Vari-speed LTC will be ignored and cause drift."
1982                                    "\n\n"
1983                                    "<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
1984                                    "timecode sources shares clock sync."
1985                                   ), PROGRAM_NAME));
1986
1987
1988         add_option (_("Transport"), _sync_genlock);
1989
1990         _sync_source_2997 = new BoolOption (
1991                 "timecode-source-2997",
1992                 _("Lock to 29.9700 fps instead of 30000/1001"),
1993                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1994                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1995                 );
1996         Gtkmm2ext::UI::instance()->set_tip
1997                 (_sync_source_2997->tip_widget(),
1998                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1999                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
2000                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
2001                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
2002                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
2003                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
2004                          ));
2005
2006         add_option (_("Transport"), _sync_source_2997);
2007
2008         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
2009
2010         _ltc_port = new ComboStringOption (
2011                 "ltc-source-port",
2012                 _("LTC incoming port"),
2013                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
2014                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
2015                 );
2016
2017         vector<string> physical_inputs;
2018         physical_inputs.push_back (_("None"));
2019         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
2020         _ltc_port->set_popdown_strings (physical_inputs);
2021
2022         populate_sync_options ();
2023         AudioEngine::instance()->Running.connect (engine_started_connection, MISSING_INVALIDATOR, boost::bind (&RCOptionEditor::populate_sync_options, this), gui_context());
2024
2025         add_option (_("Transport"), _ltc_port);
2026
2027         // TODO; rather disable this button than not compile it..
2028         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
2029
2030         add_option (_("Transport"),
2031                     new BoolOption (
2032                             "send-ltc",
2033                             _("Enable LTC generator"),
2034                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
2035                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
2036                             ));
2037
2038         _ltc_send_continuously = new BoolOption (
2039                             "ltc-send-continuously",
2040                             _("Send LTC while stopped"),
2041                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
2042                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
2043                             );
2044         Gtkmm2ext::UI::instance()->set_tip
2045                 (_ltc_send_continuously->tip_widget(),
2046                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
2047         add_option (_("Transport"), _ltc_send_continuously);
2048
2049         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
2050         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
2051         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
2052         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
2053
2054         Gtkmm2ext::UI::instance()->set_tip
2055                 (_ltc_volume_slider->tip_widget(),
2056                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
2057
2058         add_option (_("Transport"), _ltc_volume_slider);
2059
2060         /* EDITOR */
2061
2062         add_option (_("Editor"),
2063              new BoolOption (
2064                      "rubberbanding-snaps-to-grid",
2065                      _("Make rubberband selection rectangle snap to the grid"),
2066                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
2067                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
2068                      ));
2069
2070         bo = new BoolOption (
2071                      "name-new-markers",
2072                      _("Name new markers"),
2073                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
2074                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
2075                 );
2076         add_option (_("Editor"), bo);
2077         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."
2078                                                                 "\n\nYou can always rename markers by right-clicking on them"));
2079
2080         add_option (S_("Editor"),
2081              new BoolOption (
2082                      "draggable-playhead",
2083                      _("Allow dragging of playhead"),
2084                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead),
2085                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead)
2086                      ));
2087
2088         add_option (_("Editor"),
2089              new BoolOption (
2090                      "show-track-meters",
2091                      _("Show meters on tracks in the editor"),
2092                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
2093                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_track_meters)
2094                      ));
2095
2096         add_option (_("Editor"),
2097              new BoolOption (
2098                      "show-editor-meter",
2099                      _("Display master-meter in the toolbar"),
2100                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
2101                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
2102                      ));
2103
2104 if (!Profile->get_mixbus()) {
2105         add_option (_("Editor"),
2106                     new BoolOption (
2107                             "show-zoom-tools",
2108                             _("Show zoom toolbar (if torn off)"),
2109                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_zoom_tools),
2110                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_zoom_tools)
2111                             ));
2112
2113         add_option (_("Editor"),
2114                     new BoolOption (
2115                             "use-mouse-position-as-zoom-focus-on-scroll",
2116                             _("Always use mouse cursor position as zoom focus when zooming using mouse scroll wheel"),
2117                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_mouse_position_as_zoom_focus_on_scroll),
2118                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_mouse_position_as_zoom_focus_on_scroll)
2119                             ));
2120 }  // !mixbus
2121
2122         add_option (_("Editor"),
2123                     new BoolOption (
2124                             "update-editor-during-summary-drag",
2125                             _("Update editor window during drags of the summary"),
2126                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
2127                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
2128                             ));
2129
2130         add_option (_("Editor"),
2131             new BoolOption (
2132                     "autoscroll-editor",
2133                     _("Auto-scroll editor window when dragging near its edges"),
2134                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
2135                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
2136                     ));
2137
2138         add_option (_("Editor"),
2139              new BoolComboOption (
2140                      "show-region-gain-envelopes",
2141                      _("Show gain envelopes in audio regions"),
2142                      _("in all modes"),
2143                      _("only in Draw and Internal Edit modes"),
2144                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
2145                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
2146                      ));
2147
2148         add_option (_("Editor"), new OptionEditorHeading (_("Editor Behavior")));
2149
2150         add_option (_("Editor"),
2151              new BoolOption (
2152                      "automation-follows-regions",
2153                      _("Move relevant automation when audio regions are moved"),
2154                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
2155                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
2156                      ));
2157
2158         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
2159                         "default-fade-shape",
2160                         _("Default fade shape"),
2161                         sigc::mem_fun (*_rc_config,
2162                                 &RCConfiguration::get_default_fade_shape),
2163                         sigc::mem_fun (*_rc_config,
2164                                 &RCConfiguration::set_default_fade_shape)
2165                         );
2166
2167         fadeshape->add (FadeLinear,
2168                         _("Linear (for highly correlated material)"));
2169         fadeshape->add (FadeConstantPower, _("Constant power"));
2170         fadeshape->add (FadeSymmetric, _("Symmetric"));
2171         fadeshape->add (FadeSlow, _("Slow"));
2172         fadeshape->add (FadeFast, _("Fast"));
2173
2174         add_option (_("Editor"), fadeshape);
2175
2176
2177         bco = new BoolComboOption (
2178                      "use-overlap-equivalency",
2179                      _("Regions in active edit groups are edited together"),
2180                      _("whenever they overlap in time"),
2181                      _("only if they have identical length, position and origin"),
2182                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
2183                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
2184                      );
2185
2186         add_option (_("Editor"), bco);
2187
2188         ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
2189                 "layer-model",
2190                 _("Layering model"),
2191                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
2192                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
2193                 );
2194
2195         lm->add (LaterHigher, _("later is higher"));
2196         lm->add (Manual, _("manual layering"));
2197         add_option (_("Editor"), lm);
2198
2199         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
2200                     "region-selection-after-split",
2201                     _("After splitting selected regions, select"),
2202                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
2203                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
2204
2205         // TODO: decide which of these modes are really useful
2206         rsas->add(None, _("no regions"));
2207         // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
2208         // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
2209         rsas->add(NewlyCreatedBoth, _("newly-created regions"));
2210         // rsas->add(Existing, _("unmodified regions in the existing selection"));
2211         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
2212         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
2213         rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
2214
2215         add_option (_("Editor"), rsas);
2216         
2217         add_option (_("Editor"), new OptionEditorHeading (_("Waveforms")));
2218
2219 if (!Profile->get_mixbus()) {
2220         add_option (_("Editor"),
2221              new BoolOption (
2222                      "show-waveforms",
2223                      _("Show waveforms in regions"),
2224                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
2225                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
2226                      ));
2227 }  // !mixbus
2228
2229         add_option (_("Editor"),
2230              new BoolOption (
2231                      "show-waveforms-while-recording",
2232                      _("Show waveforms for audio while it is being recorded"),
2233                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
2234                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
2235                      ));
2236
2237         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
2238                 "waveform-scale",
2239                 _("Waveform scale"),
2240                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_scale),
2241                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_scale)
2242                 );
2243
2244         wfs->add (Linear, _("linear"));
2245         wfs->add (Logarithmic, _("logarithmic"));
2246
2247         add_option (_("Editor"), wfs);
2248
2249         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
2250                 "waveform-shape",
2251                 _("Waveform shape"),
2252                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_shape),
2253                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_shape)
2254                 );
2255
2256         wfsh->add (Traditional, _("traditional"));
2257         wfsh->add (Rectified, _("rectified"));
2258
2259         add_option (_("Editor"), wfsh);
2260
2261         add_option (_("Editor"), new ClipLevelOptions ());
2262
2263
2264         /* AUDIO */
2265
2266         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
2267
2268         add_option (_("Audio"), new BufferingOptions (_rc_config));
2269
2270         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
2271
2272         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
2273                 "monitoring-model",
2274                 _("Record monitoring handled by"),
2275                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
2276                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
2277                 );
2278
2279         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
2280                 mm->add (HardwareMonitoring, _("via Audio Driver"));
2281         }
2282
2283         string prog (PROGRAM_NAME);
2284         boost::algorithm::to_lower (prog);
2285         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
2286         mm->add (ExternalMonitoring, _("audio hardware"));
2287
2288         add_option (_("Audio"), mm);
2289
2290         add_option (_("Audio"),
2291              new BoolOption (
2292                      "tape-machine-mode",
2293                      _("Tape machine mode"),
2294                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
2295                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
2296                      ));
2297
2298 if (!Profile->get_mixbus()) {
2299         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
2300
2301         add_option (_("Audio"),
2302                     new BoolOption (
2303                             "auto-connect-standard-busses",
2304                             _("Auto-connect master/monitor busses"),
2305                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
2306                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
2307                             ));
2308
2309         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
2310                 "input-auto-connect",
2311                 _("Connect track inputs"),
2312                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
2313                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
2314                 );
2315
2316         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
2317         iac->add (ManualConnect, _("manually"));
2318
2319         add_option (_("Audio"), iac);
2320
2321         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
2322                 "output-auto-connect",
2323                 _("Connect track and bus outputs"),
2324                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
2325                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
2326                 );
2327
2328         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
2329         oac->add (AutoConnectMaster, _("automatically to master bus"));
2330         oac->add (ManualConnect, _("manually"));
2331
2332         add_option (_("Audio"), oac);
2333 }  // !mixbus
2334
2335         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
2336
2337         add_option (_("Audio"),
2338              new BoolOption (
2339                      "denormal-protection",
2340                      _("Use DC bias to protect against denormals"),
2341                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
2342                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
2343                      ));
2344
2345         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
2346                 "denormal-model",
2347                 _("Processor handling"),
2348                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
2349                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
2350                 );
2351
2352         int dmsize = 1;
2353         dm->add (DenormalNone, _("no processor handling"));
2354
2355         FPU* fpu = FPU::instance();
2356
2357         if (fpu->has_flush_to_zero()) {
2358                 ++dmsize;
2359                 dm->add (DenormalFTZ, _("use FlushToZero"));
2360         } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
2361                 _rc_config->set_denormal_model(DenormalNone);
2362         }
2363
2364         if (fpu->has_denormals_are_zero()) {
2365                 ++dmsize;
2366                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
2367         } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
2368                 _rc_config->set_denormal_model(DenormalNone);
2369         }
2370
2371         if (fpu->has_flush_to_zero() && fpu->has_denormals_are_zero()) {
2372                 ++dmsize;
2373                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
2374         } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
2375                 _rc_config->set_denormal_model(DenormalNone);
2376         }
2377
2378         if (dmsize == 1) {
2379                 dm->set_sensitive(false);
2380         }
2381
2382         add_option (_("Audio"), dm);
2383
2384         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
2385
2386         add_option (_("Audio"),
2387              new BoolOption (
2388                      "plugins-stop-with-transport",
2389                      _("Silence plugins when the transport is stopped"),
2390                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
2391                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
2392                      ));
2393
2394         add_option (_("Audio"),
2395              new BoolOption (
2396                      "new-plugins-active",
2397                      _("Make new plugins active"),
2398                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
2399                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
2400                      ));
2401
2402         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
2403
2404         add_option (_("Audio"),
2405              new BoolOption (
2406                      "auto-analyse-audio",
2407                      _("Enable automatic analysis of audio"),
2408                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
2409                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
2410                      ));
2411
2412         add_option (_("Audio"),
2413              new BoolOption (
2414                      "replicate-missing-region-channels",
2415                      _("Replicate missing region channels"),
2416                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
2417                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
2418                      ));
2419
2420         /* SOLO AND MUTE */
2421
2422         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
2423
2424         _solo_control_is_listen_control = new BoolOption (
2425                 "solo-control-is-listen-control",
2426                 _("Solo controls are Listen controls"),
2427                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
2428                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
2429                 );
2430
2431         add_option (_("Solo / mute"), _solo_control_is_listen_control);
2432
2433         add_option (_("Solo / mute"),
2434              new BoolOption (
2435                      "exclusive-solo",
2436                      _("Exclusive solo"),
2437                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2438                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2439                      ));
2440
2441         add_option (_("Solo / mute"),
2442              new BoolOption (
2443                      "show-solo-mutes",
2444                      _("Show solo muting"),
2445                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2446                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2447                      ));
2448
2449         add_option (_("Solo / mute"),
2450              new BoolOption (
2451                      "solo-mute-override",
2452                      _("Soloing overrides muting"),
2453                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2454                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2455                      ));
2456
2457         add_option (_("Solo / mute"),
2458              new FaderOption (
2459                      "solo-mute-gain",
2460                      _("Solo-in-place mute cut (dB)"),
2461                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
2462                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
2463                      ));
2464
2465         _listen_position = new ComboOption<ListenPosition> (
2466                 "listen-position",
2467                 _("Listen Position"),
2468                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
2469                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
2470                 );
2471
2472         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
2473         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
2474
2475         add_option (_("Solo / mute"), _listen_position);
2476
2477         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
2478                 "pfl-position",
2479                 _("PFL signals come from"),
2480                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
2481                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
2482                 );
2483
2484         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2485         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2486
2487         add_option (_("Solo / mute"), pp);
2488
2489         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2490                 "afl-position",
2491                 _("AFL signals come from"),
2492                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2493                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2494                 );
2495
2496         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2497         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2498
2499         add_option (_("Solo / mute"), pa);
2500
2501         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
2502
2503         add_option (_("Solo / mute"),
2504              new BoolOption (
2505                      "mute-affects-pre-fader",
2506                      _("Mute affects pre-fader sends"),
2507                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2508                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2509                      ));
2510
2511         add_option (_("Solo / mute"),
2512              new BoolOption (
2513                      "mute-affects-post-fader",
2514                      _("Mute affects post-fader sends"),
2515                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2516                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2517                      ));
2518
2519         add_option (_("Solo / mute"),
2520              new BoolOption (
2521                      "mute-affects-control-outs",
2522                      _("Mute affects control outputs"),
2523                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2524                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2525                      ));
2526
2527         add_option (_("Solo / mute"),
2528              new BoolOption (
2529                      "mute-affects-main-outs",
2530                      _("Mute affects main outputs"),
2531                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2532                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2533                      ));
2534
2535         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
2536
2537         add_option (_("Solo / mute"),
2538              new BoolOption (
2539                      "link-send-and-route-panner",
2540                      _("Link panners of Aux and External Sends with main panner by default"),
2541                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2542                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2543                      ));
2544
2545         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Preferences")));
2546
2547         add_option (_("MIDI"),
2548                     new SpinOption<float> (
2549                             "midi-readahead",
2550                             _("MIDI read-ahead time (seconds)"),
2551                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2552                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2553                             0.1, 10, 0.1, 1,
2554                             "", 1.0, 1
2555                             ));
2556
2557         add_option (_("MIDI"),
2558              new SpinOption<int32_t> (
2559                      "initial-program-change",
2560                      _("Initial program change"),
2561                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2562                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2563                      -1, 65536, 1, 10
2564                      ));
2565
2566         add_option (_("MIDI"),
2567                     new BoolOption (
2568                             "display-first-midi-bank-as-zero",
2569                             _("Display first MIDI bank/program as 0"),
2570                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2571                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2572                             ));
2573
2574         add_option (_("MIDI"),
2575              new BoolOption (
2576                      "never-display-periodic-midi",
2577                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2578                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
2579                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
2580                      ));
2581
2582         add_option (_("MIDI"),
2583              new BoolOption (
2584                      "sound-midi-notes",
2585                      _("Sound MIDI notes as they are selected in the editor"),
2586                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
2587                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
2588                      ));
2589
2590         add_option (_("MIDI"),
2591                     new BoolOption (
2592                             "midi-feedback",
2593                             _("Send MIDI control feedback"),
2594                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2595                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2596                             ));
2597
2598         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Clock")));
2599
2600         add_option (_("MIDI"),
2601                     new BoolOption (
2602                             "send-midi-clock",
2603                             _("Send MIDI Clock"),
2604                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2605                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2606                             ));
2607
2608         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Time Code (MTC)")));
2609
2610         add_option (_("MIDI"),
2611                     new BoolOption (
2612                             "send-mtc",
2613                             _("Send MIDI Time Code"),
2614                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2615                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2616                             ));
2617
2618         add_option (_("MIDI"),
2619                     new SpinOption<int> (
2620                             "mtc-qf-speed-tolerance",
2621                             _("Percentage either side of normal transport speed to transmit MTC"),
2622                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2623                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2624                             0, 20, 1, 5
2625                             ));
2626
2627         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Machine Control (MMC)")));
2628
2629         add_option (_("MIDI"),
2630                     new BoolOption (
2631                             "mmc-control",
2632                             _("Obey MIDI Machine Control commands"),
2633                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2634                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2635                             ));
2636
2637         add_option (_("MIDI"),
2638                     new BoolOption (
2639                             "send-mmc",
2640                             _("Send MIDI Machine Control commands"),
2641                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2642                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2643                             ));
2644
2645         add_option (_("MIDI"),
2646              new SpinOption<uint8_t> (
2647                      "mmc-receive-device-id",
2648                      _("Inbound MMC device ID"),
2649                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2650                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2651                      0, 128, 1, 10
2652                      ));
2653
2654         add_option (_("MIDI"),
2655              new SpinOption<uint8_t> (
2656                      "mmc-send-device-id",
2657                      _("Outbound MMC device ID"),
2658                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2659                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2660                      0, 128, 1, 10
2661                      ));
2662
2663         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2664
2665         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2666                 "midi-audition-synth-uri",
2667                 _("Midi Audition Synth (LV2)"),
2668                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2669                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2670                 );
2671
2672         audition_synth->add(X_(""), _("None"));
2673         PluginInfoList all_plugs;
2674         PluginManager& manager (PluginManager::instance());
2675 #ifdef LV2_SUPPORT
2676         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2677
2678         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2679                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2680                 if (!(*i)->is_instrument()) continue;
2681                 if ((*i)->type != ARDOUR::LV2) continue;
2682                 audition_synth->add((*i)->unique_id, (*i)->name);
2683         }
2684 #endif
2685
2686         add_option (_("MIDI"), audition_synth);
2687
2688         /* USER INTERACTION */
2689
2690         if (
2691 #ifdef PLATFORM_WINDOWS
2692                         true
2693 #else
2694                         getenv ("ARDOUR_BUNDLED")
2695 #endif
2696            )
2697         {
2698                 add_option (_("User interaction"),
2699                             new BoolOption (
2700                                     "enable-translation",
2701                                     string_compose (_("Use translations of %1 messages\n"
2702                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2703                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2704                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2705                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2706         }
2707
2708         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2709
2710         add_option (_("User interaction"), new KeyboardOptions);
2711
2712         /* Control Surfaces */
2713
2714         add_option (_("Control Surfaces"), new ControlSurfacesOptions);
2715
2716         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2717                 "remote-model",
2718                 _("Control surface remote ID"),
2719                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2720                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2721                 );
2722
2723         rm->add (UserOrdered, _("assigned by user"));
2724         rm->add (MixerOrdered, _("follows order of mixer"));
2725
2726         add_option (_("Control Surfaces"), rm);
2727
2728         /* VIDEO Timeline */
2729         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2730
2731 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2732         add_option (_("Plugins"), new OptionEditorHeading (_("General")));
2733
2734         add_option (_("Plugins"),
2735                         new RcActionButton (_("Scan for Plugins"),
2736                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
2737
2738         bo = new BoolOption (
2739                         "show-plugin-scan-window",
2740                         _("Always Display Plugin Scan Progress"),
2741                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_plugin_scan_window),
2742                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_plugin_scan_window)
2743                         );
2744         add_option (_("Plugins"), bo);
2745         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2746                         _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
2747
2748 #endif
2749
2750 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
2751         add_option (_("Plugins"), new OptionEditorHeading (_("VST")));
2752
2753         bo = new BoolOption (
2754                         "discover-vst-on-start",
2755                         _("Scan for [new] VST Plugins on Application Start"),
2756                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_vst_on_start),
2757                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_vst_on_start)
2758                         );
2759         add_option (_("Plugins"), bo);
2760         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2761                                             _("<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"));
2762
2763 #ifdef WINDOWS_VST_SUPPORT
2764         // currently verbose logging is only implemented for Windows VST.
2765         bo = new BoolOption (
2766                         "verbose-plugin-scan",
2767                         _("Verbose Plugin Scan"),
2768                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_verbose_plugin_scan),
2769                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_verbose_plugin_scan)
2770                         );
2771         add_option (_("Plugins"), bo);
2772         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2773                                             _("<b>When enabled</b> additional information for every plugin is added to the Log Window."));
2774 #endif
2775
2776         add_option (_("Plugins"), new VstTimeOutSliderOption (_rc_config));
2777
2778         add_option (_("Plugins"),
2779                         new RcActionButton (_("Clear"),
2780                                 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_cache),
2781                                 _("VST Cache:")));
2782
2783         add_option (_("Plugins"),
2784                         new RcActionButton (_("Clear"),
2785                                 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_blacklist),
2786                                 _("VST Blacklist:")));
2787 #endif
2788
2789 #ifdef LXVST_SUPPORT
2790         add_option (_("Plugins"),
2791                         new RcActionButton (_("Edit"),
2792                                 sigc::mem_fun (*this, &RCOptionEditor::edit_lxvst_path),
2793                         _("Linux VST Path:")));
2794
2795         add_option (_("Plugins"),
2796                         new RcConfigDisplay (
2797                                 "plugin-path-lxvst",
2798                                 _("Path:"),
2799                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_lxvst),
2800                                 ':'));
2801 #endif
2802
2803 #ifdef WINDOWS_VST_SUPPORT
2804         add_option (_("Plugins"),
2805                         new RcActionButton (_("Edit"),
2806                                 sigc::mem_fun (*this, &RCOptionEditor::edit_vst_path),
2807                         _("Windows VST Path:")));
2808         add_option (_("Plugins"),
2809                         new RcConfigDisplay (
2810                                 "plugin-path-vst",
2811                                 _("Path:"),
2812                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_vst),
2813                                 ';'));
2814 #endif
2815
2816 #ifdef AUDIOUNIT_SUPPORT
2817         add_option (_("Plugins"), new OptionEditorHeading (_("Audio Unit")));
2818
2819         bo = new BoolOption (
2820                         "discover-audio-units",
2821                         _("Scan for AudioUnit Plugins on Application Start"),
2822                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_audio_units),
2823                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_audio_units)
2824                         );
2825         add_option (_("Plugins"), bo);
2826         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2827                                             _("<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."));
2828
2829         add_option (_("Plugins"),
2830                         new RcActionButton (_("Clear"),
2831                                 sigc::mem_fun (*this, &RCOptionEditor::clear_au_cache),
2832                                 _("AU Cache:")));
2833
2834         add_option (_("Plugins"),
2835                         new RcActionButton (_("Clear"),
2836                                 sigc::mem_fun (*this, &RCOptionEditor::clear_au_blacklist),
2837                                 _("AU Blacklist:")));
2838 #endif
2839
2840 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2)
2841         add_option (_("Plugins"), new OptionEditorHeading (_("Plugin GUI")));
2842         add_option (_("Plugins"),
2843              new BoolOption (
2844                      "open-gui-after-adding-plugin",
2845                      _("Automatically open the plugin GUI when adding a new plugin"),
2846                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_open_gui_after_adding_plugin),
2847                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_open_gui_after_adding_plugin)
2848                      ));
2849 #endif
2850
2851         /* INTERFACE */
2852
2853 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
2854         BoolOption* bgc = new BoolOption (
2855                 "cairo-image-surface",
2856                 _("Disable Graphics Hardware Acceleration (requires restart)"),
2857                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_cairo_image_surface),
2858                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_cairo_image_surface)
2859                 );
2860
2861         Gtkmm2ext::UI::instance()->set_tip (bgc->tip_widget(), string_compose (
2862                                 _("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));
2863         add_option (S_("Preferences|GUI"), bgc);
2864 #endif
2865
2866 #ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
2867         BoolOption* bgo = new BoolOption (
2868                 "buggy-gradients",
2869                 _("Possibly improve slow graphical performance (requires restart)"),
2870                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_buggy_gradients),
2871                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_buggy_gradients)
2872                 );
2873
2874         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));
2875         add_option (S_("Preferences|GUI"), bgo);
2876 #endif
2877
2878         add_option (S_("Preferences|GUI"),
2879              new BoolOption (
2880                      "widget-prelight",
2881                      _("Graphically indicate mouse pointer hovering over various widgets"),
2882                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_widget_prelight),
2883                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_widget_prelight)
2884                      ));
2885
2886 #ifdef TOOLTIPS_GOT_FIXED
2887         add_option (S_("Preferences|GUI"),
2888              new BoolOption (
2889                      "use-tooltips",
2890                      _("Show tooltips if mouse hovers over a control"),
2891                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_tooltips),
2892                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_tooltips)
2893                      ));
2894 #endif
2895
2896         add_option (S_("Preferences|GUI"),
2897              new BoolOption (
2898                      "show-name-highlight",
2899                      _("Use name highlight bars in region displays (requires a restart)"),
2900                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_name_highlight),
2901                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_name_highlight)
2902                      ));
2903
2904         add_option (S_("GUI"),
2905                     new BoolOption (
2906                             "super-rapid-clock-update",
2907                             _("Update transport clock display at FPS instead of every 100ms"),
2908                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
2909                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
2910                             ));
2911
2912
2913 #ifndef GTKOSX
2914         /* font scaling does nothing with GDK/Quartz */
2915         add_option (S_("Preferences|GUI"), new FontScalingOptions ());
2916 #endif
2917
2918         /* Image cache size */
2919
2920         Gtk::Adjustment *ics = manage (new Gtk::Adjustment(0, 1, 1024, 10)); /* 1 MB to 1GB in steps of 10MB */
2921         HSliderOption *sics = new HSliderOption("waveform-cache-size",
2922                                                 _("Waveform image cache size (megabytes)"),
2923                                                 ics,
2924                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_cache_size),
2925                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_cache_size)
2926                         );
2927         sics->scale().set_digits (0);
2928         Gtkmm2ext::UI::instance()->set_tip
2929                 (sics->tip_widget(),
2930                  _("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
2931         add_option (S_("Preferences|GUI"), sics);
2932
2933 if (!ARDOUR::Profile->get_mixbus()) {
2934         /* Lock GUI timeout */
2935
2936         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2937         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2938                                                 _("Lock timeout (seconds)"),
2939                                                 lts,
2940                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_lock_gui_after_seconds),
2941                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_lock_gui_after_seconds)
2942                         );
2943         slts->scale().set_digits (0);
2944         Gtkmm2ext::UI::instance()->set_tip
2945                 (slts->tip_widget(),
2946                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2947         add_option (S_("Preferences|GUI"), slts);
2948 } // !mixbus
2949
2950         /* The names of these controls must be the same as those given in MixerStrip
2951            for the actual widgets being controlled.
2952         */
2953         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2954         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2955         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2956         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2957         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2958         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2959
2960         add_option (
2961                 S_("Preferences|GUI"),
2962                 new VisibilityOption (
2963                         _("Mixer Strip"),
2964                         &_mixer_strip_visibility,
2965                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_mixer_strip_visibility),
2966                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_mixer_strip_visibility)
2967                         )
2968                 );
2969
2970         add_option (S_("Preferences|GUI"),
2971              new BoolOption (
2972                      "default-narrow_ms",
2973                      _("Use narrow strips in the mixer by default"),
2974                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_default_narrow_ms),
2975                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
2976                      ));
2977
2978         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2979
2980         ComboOption<float>* mht = new ComboOption<float> (
2981                 "meter-hold",
2982                 _("Peak hold time"),
2983                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_hold),
2984                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_hold)
2985                 );
2986
2987         mht->add (MeterHoldOff, _("off"));
2988         mht->add (MeterHoldShort, _("short"));
2989         mht->add (MeterHoldMedium, _("medium"));
2990         mht->add (MeterHoldLong, _("long"));
2991
2992         add_option (S_("Preferences|Metering"), mht);
2993
2994         ComboOption<float>* mfo = new ComboOption<float> (
2995                 "meter-falloff",
2996                 _("DPM fall-off"),
2997                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2998                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2999                 );
3000
3001         mfo->add (METER_FALLOFF_OFF,      _("off"));
3002         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
3003         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
3004         mfo->add (METER_FALLOFF_SLOWISH,  _("moderate [12.0dB/sec] (DIN)"));
3005         mfo->add (METER_FALLOFF_MODERATE, _("medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
3006         mfo->add (METER_FALLOFF_MEDIUM,   _("fast [20dB/sec]"));
3007         mfo->add (METER_FALLOFF_FAST,     _("very fast [32dB/sec]"));
3008
3009         add_option (S_("Preferences|Metering"), mfo);
3010
3011         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
3012                 "meter-line-up-level",
3013                 _("Meter line-up level; 0dBu"),
3014                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_level),
3015                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_level)
3016                 );
3017
3018         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
3019         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
3020         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
3021         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3022
3023         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."));
3024
3025         add_option (S_("Preferences|Metering"), mlu);
3026
3027         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
3028                 "meter-line-up-din",
3029                 _("IEC1/DIN Meter line-up level; 0dBu"),
3030                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_din),
3031                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_din)
3032                 );
3033
3034         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
3035         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
3036         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
3037         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3038
3039         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
3040
3041         add_option (S_("Preferences|Metering"), mld);
3042
3043         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
3044                 "meter-vu-standard",
3045                 _("VU Meter standard"),
3046                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_vu_standard),
3047                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_vu_standard)
3048                 );
3049
3050         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
3051         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
3052         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
3053         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
3054
3055         add_option (S_("Preferences|Metering"), mvu);
3056
3057         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
3058         HSliderOption *mpks = new HSliderOption("meter-peak",
3059                         _("Peak threshold [dBFS]"),
3060                         mpk,
3061                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_peak),
3062                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_peak)
3063                         );
3064
3065
3066         ComboOption<MeterType>* mtm = new ComboOption<MeterType> (
3067                 "meter-type-master",
3068                 _("Default Meter Type for Master Bus"),
3069                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_master),
3070                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_master)
3071                 );
3072         mtm->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3073         mtm->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3074         mtm->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3075         mtm->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3076         mtm->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3077         mtm->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3078         mtm->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3079         mtm->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3080
3081         add_option (S_("Preferences|Metering"), mtm);
3082
3083
3084         ComboOption<MeterType>* mtb = new ComboOption<MeterType> (
3085                 "meter-type-bus",
3086                 _("Default Meter Type for Busses"),
3087                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_bus),
3088                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_bus)
3089                 );
3090         mtb->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3091         mtb->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3092         mtb->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3093         mtb->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3094         mtb->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3095         mtb->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3096         mtb->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3097         mtb->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3098
3099         add_option (S_("Preferences|Metering"), mtb);
3100
3101         ComboOption<MeterType>* mtt = new ComboOption<MeterType> (
3102                 "meter-type-track",
3103                 _("Default Meter Type for Tracks"),
3104                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_track),
3105                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_track)
3106                 );
3107         mtt->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3108         mtt->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
3109
3110         add_option (S_("Preferences|Metering"), mtt);
3111
3112
3113         Gtkmm2ext::UI::instance()->set_tip
3114                 (mpks->tip_widget(),
3115                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
3116
3117         add_option (S_("Preferences|Metering"), mpks);
3118
3119         add_option (S_("Preferences|Metering"),
3120              new BoolOption (
3121                      "meter-style-led",
3122                      _("LED meter style"),
3123                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_style_led),
3124                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_style_led)
3125                      ));
3126
3127         /* and now the theme manager */
3128
3129         ThemeManager* tm = manage (new ThemeManager);
3130         add_page (_("Theme"), *tm);
3131
3132         //trigger some parameter-changed messages which affect widget-visibility or -sensitivity
3133         parameter_changed ("send-ltc");
3134         parameter_changed ("sync-source");
3135         parameter_changed ("use-monitor-bus");
3136 }
3137
3138 void
3139 RCOptionEditor::parameter_changed (string const & p)
3140 {
3141         OptionEditor::parameter_changed (p);
3142
3143         if (p == "use-monitor-bus") {
3144                 bool const s = Config->get_use_monitor_bus ();
3145                 if (!s) {
3146                         /* we can't use this if we don't have a monitor bus */
3147                         Config->set_solo_control_is_listen_control (false);
3148                 }
3149                 _solo_control_is_listen_control->set_sensitive (s);
3150                 _listen_position->set_sensitive (s);
3151         } else if (p == "sync-source") {
3152                 _sync_source->set_sensitive (true);
3153                 if (_session) {
3154                         _sync_source->set_sensitive (!_session->config.get_external_sync());
3155                 }
3156                 switch(Config->get_sync_source()) {
3157                 case ARDOUR::MTC:
3158                 case ARDOUR::LTC:
3159                         _sync_genlock->set_sensitive (true);
3160                         _sync_framerate->set_sensitive (true);
3161                         _sync_source_2997->set_sensitive (true);
3162                         break;
3163                 default:
3164                         _sync_genlock->set_sensitive (false);
3165                         _sync_framerate->set_sensitive (false);
3166                         _sync_source_2997->set_sensitive (false);
3167                         break;
3168                 }
3169         } else if (p == "send-ltc") {
3170                 bool const s = Config->get_send_ltc ();
3171                 _ltc_send_continuously->set_sensitive (s);
3172                 _ltc_volume_slider->set_sensitive (s);
3173         }
3174 }
3175
3176 void RCOptionEditor::ltc_generator_volume_changed () {
3177         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
3178 }
3179
3180 void RCOptionEditor::plugin_scan_refresh () {
3181         PluginManager::instance().refresh();
3182 }
3183
3184 void RCOptionEditor::clear_vst_cache () {
3185         PluginManager::instance().clear_vst_cache();
3186 }
3187
3188 void RCOptionEditor::clear_vst_blacklist () {
3189         PluginManager::instance().clear_vst_blacklist();
3190 }
3191
3192 void RCOptionEditor::clear_au_cache () {
3193         PluginManager::instance().clear_au_cache();
3194 }
3195
3196 void RCOptionEditor::clear_au_blacklist () {
3197         PluginManager::instance().clear_au_blacklist();
3198 }
3199
3200 void RCOptionEditor::edit_lxvst_path () {
3201         Glib::RefPtr<Gdk::Window> win = get_parent_window ();
3202         Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
3203                         *this, _("Set Linux VST Search Path"),
3204                         _rc_config->get_plugin_path_lxvst(),
3205                         PluginManager::instance().get_default_lxvst_path()
3206                         );
3207         ResponseType r = (ResponseType) pd->run ();
3208         pd->hide();
3209         if (r == RESPONSE_ACCEPT) {
3210                 _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
3211         }
3212         delete pd;
3213 }
3214
3215 void RCOptionEditor::edit_vst_path () {
3216         Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
3217                         *this, _("Set Windows VST Search Path"),
3218                         _rc_config->get_plugin_path_vst(),
3219                         PluginManager::instance().get_default_windows_vst_path()
3220                         );
3221         ResponseType r = (ResponseType) pd->run ();
3222         pd->hide();
3223         if (r == RESPONSE_ACCEPT) {
3224                 _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
3225         }
3226         delete pd;
3227 }
3228
3229
3230 void
3231 RCOptionEditor::populate_sync_options ()
3232 {
3233         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
3234
3235         _sync_source->clear ();
3236
3237         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
3238                 _sync_source->add (*i, sync_source_to_string (*i));
3239         }
3240
3241         if (sync_opts.empty()) {
3242                 _sync_source->set_sensitive(false);
3243         } else {
3244                 if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
3245                         _rc_config->set_sync_source(sync_opts.front());
3246                 }
3247         }
3248
3249         parameter_changed ("sync-source");
3250 }