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