Improve the layout of Preferences widgets:
[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 (_("Emphasis on first beat:")));
86                 t->attach (*l, 0, 1, 1, 2, FILL);
87                 t->attach (_use_emphasis_on_click_check_button, 1, 2, 1, 2, FILL);
88                 _use_emphasis_on_click_check_button.signal_toggled().connect (
89                     sigc::mem_fun (*this, &ClickOptions::use_emphasis_on_click_toggled));
90
91                 l = manage (left_aligned_label (_("Use default Click:")));
92                 t->attach (*l, 0, 1, 0, 1, FILL);
93                 t->attach (_use_default_click_check_button, 1, 2, 0, 1, FILL);
94                 _use_default_click_check_button.signal_toggled().connect (
95                     sigc::mem_fun (*this, &ClickOptions::use_default_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"), new OptionEditorHeading (_("Session Management")));
1909
1910         add_option (_("Misc"),
1911              new BoolOption (
1912                      "periodic-safety-backups",
1913                      _("Make periodic backups of the session file"),
1914                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1915                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1916                      ));
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 (psc->tip_widget(),
2072                                             (_("The amount of preroll (in seconds) to apply when <b>Play with Preroll</b> 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
2199         /* EDITOR */
2200
2201         add_option (_("Editor"),
2202              new BoolOption (
2203                      "rubberbanding-snaps-to-grid",
2204                      _("Make rubberband selection rectangle snap to the grid"),
2205                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
2206                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
2207                      ));
2208
2209         bo = new BoolOption (
2210                      "name-new-markers",
2211                      _("Name new markers"),
2212                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
2213                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
2214                 );
2215         add_option (_("Editor"), bo);
2216         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."
2217                                                                 "\n\nYou can always rename markers by right-clicking on them"));
2218
2219         add_option (S_("Editor"),
2220              new BoolOption (
2221                      "draggable-playhead",
2222                      _("Allow dragging of playhead"),
2223                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead),
2224                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead)
2225                      ));
2226
2227         add_option (_("Editor"),
2228              new BoolOption (
2229                      "show-track-meters",
2230                      _("Show meters on tracks in the editor"),
2231                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
2232                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_track_meters)
2233                      ));
2234
2235         add_option (_("Editor"),
2236              new BoolOption (
2237                      "show-editor-meter",
2238                      _("Display master-meter in the toolbar"),
2239                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
2240                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
2241                      ));
2242
2243         add_option (_("Editor"),
2244                     new BoolOption (
2245                             "show-zoom-tools",
2246                             _("Show zoom toolbar (if torn off)"),
2247                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_zoom_tools),
2248                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_zoom_tools)
2249                             ));
2250
2251         add_option (_("Editor"),
2252                     new BoolOption (
2253                             "update-editor-during-summary-drag",
2254                             _("Update editor window during drags of the summary"),
2255                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
2256                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
2257                             ));
2258
2259         add_option (_("Editor"),
2260             new BoolOption (
2261                     "autoscroll-editor",
2262                     _("Auto-scroll editor window when dragging near its edges"),
2263                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
2264                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
2265                     ));
2266
2267         add_option (_("Editor"),
2268              new BoolComboOption (
2269                      "show-region-gain-envelopes",
2270                      _("Show gain envelopes in audio regions"),
2271                      _("in all modes"),
2272                      _("only in Draw and Internal Edit modes"),
2273                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
2274                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
2275                      ));
2276
2277         add_option (_("Editor"), new OptionEditorHeading (_("Editor Behavior")));
2278
2279         add_option (_("Editor"),
2280              new BoolOption (
2281                      "automation-follows-regions",
2282                      _("Move relevant automation when audio regions are moved"),
2283                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
2284                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
2285                      ));
2286
2287         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
2288                         "default-fade-shape",
2289                         _("Default fade shape"),
2290                         sigc::mem_fun (*_rc_config,
2291                                 &RCConfiguration::get_default_fade_shape),
2292                         sigc::mem_fun (*_rc_config,
2293                                 &RCConfiguration::set_default_fade_shape)
2294                         );
2295
2296         fadeshape->add (FadeLinear,
2297                         _("Linear (for highly correlated material)"));
2298         fadeshape->add (FadeConstantPower, _("Constant power"));
2299         fadeshape->add (FadeSymmetric, _("Symmetric"));
2300         fadeshape->add (FadeSlow, _("Slow"));
2301         fadeshape->add (FadeFast, _("Fast"));
2302
2303         add_option (_("Editor"), fadeshape);
2304
2305
2306         bco = new BoolComboOption (
2307                      "use-overlap-equivalency",
2308                      _("Regions in active edit groups are edited together"),
2309                      _("whenever they overlap in time"),
2310                      _("only if they have identical length, position and origin"),
2311                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
2312                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
2313                      );
2314
2315         add_option (_("Editor"), bco);
2316
2317         ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
2318                 "layer-model",
2319                 _("Layering model"),
2320                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
2321                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
2322                 );
2323
2324         lm->add (LaterHigher, _("later is higher"));
2325         lm->add (Manual, _("manual layering"));
2326         add_option (_("Editor"), lm);
2327
2328         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
2329                     "region-selection-after-split",
2330                     _("After splitting selected regions, select"),
2331                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
2332                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
2333
2334         // TODO: decide which of these modes are really useful
2335         rsas->add(None, _("no regions"));
2336         // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
2337         // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
2338         rsas->add(NewlyCreatedBoth, _("newly-created regions"));
2339         // rsas->add(Existing, _("unmodified regions in the existing selection"));
2340         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
2341         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
2342         rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
2343
2344         add_option (_("Editor"), rsas);
2345         
2346         add_option (_("Editor"), new OptionEditorHeading (_("Waveforms")));
2347
2348         add_option (_("Editor"),
2349              new BoolOption (
2350                      "show-waveforms",
2351                      _("Show waveforms in regions"),
2352                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
2353                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
2354                      ));
2355
2356         add_option (_("Editor"),
2357              new BoolOption (
2358                      "show-waveforms-while-recording",
2359                      _("Show waveforms for audio while it is being recorded"),
2360                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
2361                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
2362                      ));
2363
2364         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
2365                 "waveform-scale",
2366                 _("Waveform scale"),
2367                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_scale),
2368                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_scale)
2369                 );
2370
2371         wfs->add (Linear, _("linear"));
2372         wfs->add (Logarithmic, _("logarithmic"));
2373
2374         add_option (_("Editor"), wfs);
2375
2376         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
2377                 "waveform-shape",
2378                 _("Waveform shape"),
2379                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_shape),
2380                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_shape)
2381                 );
2382
2383         wfsh->add (Traditional, _("traditional"));
2384         wfsh->add (Rectified, _("rectified"));
2385
2386         add_option (_("Editor"), wfsh);
2387
2388         add_option (_("Editor"), new ClipLevelOptions ());
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         _solo_control_is_listen_control = new BoolOption (
2550                 "solo-control-is-listen-control",
2551                 _("Solo controls are Listen controls"),
2552                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
2553                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
2554                 );
2555
2556         add_option (_("Solo / mute"), _solo_control_is_listen_control);
2557
2558         add_option (_("Solo / mute"),
2559              new BoolOption (
2560                      "exclusive-solo",
2561                      _("Exclusive solo"),
2562                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2563                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2564                      ));
2565
2566         add_option (_("Solo / mute"),
2567              new BoolOption (
2568                      "show-solo-mutes",
2569                      _("Show solo muting"),
2570                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2571                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2572                      ));
2573
2574         add_option (_("Solo / mute"),
2575              new BoolOption (
2576                      "solo-mute-override",
2577                      _("Soloing overrides muting"),
2578                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2579                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2580                      ));
2581
2582         add_option (_("Solo / mute"),
2583              new FaderOption (
2584                      "solo-mute-gain",
2585                      _("Solo-in-place mute cut (dB)"),
2586                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
2587                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
2588                      ));
2589
2590         _listen_position = new ComboOption<ListenPosition> (
2591                 "listen-position",
2592                 _("Listen Position"),
2593                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
2594                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
2595                 );
2596
2597         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
2598         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
2599
2600         add_option (_("Solo / mute"), _listen_position);
2601
2602         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
2603                 "pfl-position",
2604                 _("PFL signals come from"),
2605                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
2606                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
2607                 );
2608
2609         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2610         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2611
2612         add_option (_("Solo / mute"), pp);
2613
2614         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2615                 "afl-position",
2616                 _("AFL signals come from"),
2617                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2618                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2619                 );
2620
2621         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2622         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2623
2624         add_option (_("Solo / mute"), pa);
2625
2626         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
2627
2628         add_option (_("Solo / mute"),
2629              new BoolOption (
2630                      "mute-affects-pre-fader",
2631                      _("Mute affects pre-fader sends"),
2632                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2633                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2634                      ));
2635
2636         add_option (_("Solo / mute"),
2637              new BoolOption (
2638                      "mute-affects-post-fader",
2639                      _("Mute affects post-fader sends"),
2640                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2641                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2642                      ));
2643
2644         add_option (_("Solo / mute"),
2645              new BoolOption (
2646                      "mute-affects-control-outs",
2647                      _("Mute affects control outputs"),
2648                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2649                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2650                      ));
2651
2652         add_option (_("Solo / mute"),
2653              new BoolOption (
2654                      "mute-affects-main-outs",
2655                      _("Mute affects main outputs"),
2656                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2657                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2658                      ));
2659
2660         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
2661
2662         add_option (_("Solo / mute"),
2663              new BoolOption (
2664                      "link-send-and-route-panner",
2665                      _("Link panners of Aux and External Sends with main panner by default"),
2666                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2667                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2668                      ));
2669
2670         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Preferences")));
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 SpinOption<int32_t> (
2684                      "initial-program-change",
2685                      _("Initial program change"),
2686                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2687                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2688                      -1, 65536, 1, 10
2689                      ));
2690
2691         add_option (_("MIDI"),
2692                     new BoolOption (
2693                             "display-first-midi-bank-as-zero",
2694                             _("Display first MIDI bank/program as 0"),
2695                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2696                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2697                             ));
2698
2699         add_option (_("MIDI"),
2700              new BoolOption (
2701                      "never-display-periodic-midi",
2702                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2703                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
2704                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
2705                      ));
2706
2707         add_option (_("MIDI"),
2708              new BoolOption (
2709                      "sound-midi-notes",
2710                      _("Sound MIDI notes as they are selected in the editor"),
2711                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
2712                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
2713                      ));
2714
2715         add_option (_("MIDI"),
2716                     new BoolOption (
2717                             "midi-feedback",
2718                             _("Send MIDI control feedback"),
2719                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2720                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2721                             ));
2722
2723         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Clock")));
2724
2725         add_option (_("MIDI"),
2726                     new BoolOption (
2727                             "send-midi-clock",
2728                             _("Send MIDI Clock"),
2729                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2730                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2731                             ));
2732
2733         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Time Code (MTC)")));
2734
2735         add_option (_("MIDI"),
2736                     new BoolOption (
2737                             "send-mtc",
2738                             _("Send MIDI Time Code"),
2739                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2740                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2741                             ));
2742
2743         add_option (_("MIDI"),
2744                     new SpinOption<int> (
2745                             "mtc-qf-speed-tolerance",
2746                             _("Percentage either side of normal transport speed to transmit MTC"),
2747                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2748                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2749                             0, 20, 1, 5
2750                             ));
2751
2752         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Machine Control (MMC)")));
2753
2754         add_option (_("MIDI"),
2755                     new BoolOption (
2756                             "mmc-control",
2757                             _("Obey MIDI Machine Control commands"),
2758                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2759                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2760                             ));
2761
2762         add_option (_("MIDI"),
2763                     new BoolOption (
2764                             "send-mmc",
2765                             _("Send MIDI Machine Control commands"),
2766                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2767                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2768                             ));
2769
2770         add_option (_("MIDI"),
2771              new SpinOption<uint8_t> (
2772                      "mmc-receive-device-id",
2773                      _("Inbound MMC device ID"),
2774                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2775                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2776                      0, 128, 1, 10
2777                      ));
2778
2779         add_option (_("MIDI"),
2780              new SpinOption<uint8_t> (
2781                      "mmc-send-device-id",
2782                      _("Outbound MMC device ID"),
2783                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2784                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2785                      0, 128, 1, 10
2786                      ));
2787
2788         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2789
2790         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2791                 "midi-audition-synth-uri",
2792                 _("Midi Audition Synth (LV2)"),
2793                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2794                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2795                 );
2796
2797         audition_synth->add(X_(""), _("None"));
2798         PluginInfoList all_plugs;
2799         PluginManager& manager (PluginManager::instance());
2800 #ifdef LV2_SUPPORT
2801         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2802
2803         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2804                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2805                 if (!(*i)->is_instrument()) continue;
2806                 if ((*i)->type != ARDOUR::LV2) continue;
2807                 audition_synth->add((*i)->unique_id, (*i)->name);
2808         }
2809 #endif
2810
2811         add_option (_("MIDI"), audition_synth);
2812
2813         /* USER INTERACTION */
2814
2815         if (
2816 #ifdef PLATFORM_WINDOWS
2817                         true
2818 #else
2819                         getenv ("ARDOUR_BUNDLED")
2820 #endif
2821            )
2822         {
2823                 add_option (_("User interaction"),
2824                             new BoolOption (
2825                                     "enable-translation",
2826                                     string_compose (_("Use translations of %1 messages\n"
2827                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2828                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2829                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2830                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2831         }
2832
2833         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2834
2835         add_option (_("User interaction"), new KeyboardOptions);
2836
2837         /* Control Surfaces */
2838
2839         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2840
2841         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2842                 "remote-model",
2843                 _("Control surface remote ID"),
2844                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2845                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2846                 );
2847
2848         rm->add (UserOrdered, _("assigned by user"));
2849         rm->add (MixerOrdered, _("follows order of mixer"));
2850
2851         add_option (_("Control Surfaces"), rm);
2852
2853         /* VIDEO Timeline */
2854         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2855
2856 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2857         /* Plugin options (currrently VST only) */
2858         add_option (_("Plugins"), new PluginOptions (_rc_config));
2859 #endif
2860
2861         /* INTERFACE */
2862
2863 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
2864         BoolOption* bgc = new BoolOption (
2865                 "cairo-image-surface",
2866                 _("Disable Graphics Hardware Acceleration (requires restart)"),
2867                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_cairo_image_surface),
2868                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_cairo_image_surface)
2869                 );
2870
2871         Gtkmm2ext::UI::instance()->set_tip (bgc->tip_widget(), string_compose (
2872                                 _("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));
2873         add_option (S_("Preferences|GUI"), bgc);
2874 #endif
2875
2876 #ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
2877         BoolOption* bgo = new BoolOption (
2878                 "buggy-gradients",
2879                 _("Possibly improve slow graphical performance (requires restart)"),
2880                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_buggy_gradients),
2881                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_buggy_gradients)
2882                 );
2883
2884         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));
2885         add_option (S_("Preferences|GUI"), bgo);
2886 #endif
2887
2888         add_option (S_("Preferences|GUI"),
2889              new BoolOption (
2890                      "widget-prelight",
2891                      _("Graphically indicate mouse pointer hovering over various widgets"),
2892                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_widget_prelight),
2893                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_widget_prelight)
2894                      ));
2895
2896 #ifdef TOOLTIPS_GOT_FIXED
2897         add_option (S_("Preferences|GUI"),
2898              new BoolOption (
2899                      "use-tooltips",
2900                      _("Show tooltips if mouse hovers over a control"),
2901                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_tooltips),
2902                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_tooltips)
2903                      ));
2904 #endif
2905
2906         add_option (S_("Preferences|GUI"),
2907              new BoolOption (
2908                      "show-name-highlight",
2909                      _("Use name highlight bars in region displays (requires a restart)"),
2910                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_name_highlight),
2911                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_name_highlight)
2912                      ));
2913
2914         add_option (S_("GUI"),
2915                     new BoolOption (
2916                             "super-rapid-clock-update",
2917                             _("Update transport clock display at FPS instead of every 100ms"),
2918                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
2919                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
2920                             ));
2921
2922
2923 #ifndef GTKOSX
2924         /* font scaling does nothing with GDK/Quartz */
2925         add_option (S_("Preferences|GUI"), new FontScalingOptions ());
2926 #endif
2927
2928         /* Image cache size */
2929
2930         Gtk::Adjustment *ics = manage (new Gtk::Adjustment(0, 1, 1024, 10)); /* 1 MB to 1GB in steps of 10MB */
2931         HSliderOption *sics = new HSliderOption("waveform-cache-size",
2932                                                 _("Waveform image cache size (megabytes)"),
2933                                                 ics,
2934                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_cache_size),
2935                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_cache_size)
2936                         );
2937         sics->scale().set_digits (0);
2938         Gtkmm2ext::UI::instance()->set_tip
2939                 (sics->tip_widget(),
2940                  _("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
2941         add_option (S_("Preferences|GUI"), sics);
2942
2943         /* Lock GUI timeout */
2944
2945         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2946         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2947                                                 _("Lock timeout (seconds)"),
2948                                                 lts,
2949                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_lock_gui_after_seconds),
2950                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_lock_gui_after_seconds)
2951                         );
2952         slts->scale().set_digits (0);
2953         Gtkmm2ext::UI::instance()->set_tip
2954                 (slts->tip_widget(),
2955                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2956         add_option (S_("Preferences|GUI"), slts);
2957
2958         /* The names of these controls must be the same as those given in MixerStrip
2959            for the actual widgets being controlled.
2960         */
2961         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2962         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2963         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2964         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2965         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2966         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2967
2968         add_option (
2969                 S_("Preferences|GUI"),
2970                 new VisibilityOption (
2971                         _("Mixer Strip"),
2972                         &_mixer_strip_visibility,
2973                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_mixer_strip_visibility),
2974                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_mixer_strip_visibility)
2975                         )
2976                 );
2977
2978         add_option (S_("Preferences|GUI"),
2979              new BoolOption (
2980                      "default-narrow_ms",
2981                      _("Use narrow strips in the mixer by default"),
2982                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_default_narrow_ms),
2983                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
2984                      ));
2985
2986         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2987
2988         ComboOption<float>* mht = new ComboOption<float> (
2989                 "meter-hold",
2990                 _("Peak hold time"),
2991                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_hold),
2992                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_hold)
2993                 );
2994
2995         mht->add (MeterHoldOff, _("off"));
2996         mht->add (MeterHoldShort, _("short"));
2997         mht->add (MeterHoldMedium, _("medium"));
2998         mht->add (MeterHoldLong, _("long"));
2999
3000         add_option (S_("Preferences|Metering"), mht);
3001
3002         ComboOption<float>* mfo = new ComboOption<float> (
3003                 "meter-falloff",
3004                 _("DPM fall-off"),
3005                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
3006                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
3007                 );
3008
3009         mfo->add (METER_FALLOFF_OFF,      _("off"));
3010         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
3011         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
3012         mfo->add (METER_FALLOFF_SLOWISH,  _("moderate [12.0dB/sec] (DIN)"));
3013         mfo->add (METER_FALLOFF_MODERATE, _("medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
3014         mfo->add (METER_FALLOFF_MEDIUM,   _("fast [20dB/sec]"));
3015         mfo->add (METER_FALLOFF_FAST,     _("very fast [32dB/sec]"));
3016
3017         add_option (S_("Preferences|Metering"), mfo);
3018
3019         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
3020                 "meter-line-up-level",
3021                 _("Meter line-up level; 0dBu"),
3022                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_level),
3023                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_level)
3024                 );
3025
3026         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
3027         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
3028         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
3029         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3030
3031         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."));
3032
3033         add_option (S_("Preferences|Metering"), mlu);
3034
3035         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
3036                 "meter-line-up-din",
3037                 _("IEC1/DIN Meter line-up level; 0dBu"),
3038                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_din),
3039                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_din)
3040                 );
3041
3042         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
3043         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
3044         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
3045         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3046
3047         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
3048
3049         add_option (S_("Preferences|Metering"), mld);
3050
3051         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
3052                 "meter-vu-standard",
3053                 _("VU Meter standard"),
3054                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_vu_standard),
3055                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_vu_standard)
3056                 );
3057
3058         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
3059         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
3060         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
3061         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
3062
3063         add_option (S_("Preferences|Metering"), mvu);
3064
3065         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
3066         HSliderOption *mpks = new HSliderOption("meter-peak",
3067                         _("Peak threshold [dBFS]"),
3068                         mpk,
3069                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_peak),
3070                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_peak)
3071                         );
3072
3073
3074         ComboOption<MeterType>* mtm = new ComboOption<MeterType> (
3075                 "meter-type-master",
3076                 _("Default Meter Type for Master Bus"),
3077                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_master),
3078                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_master)
3079                 );
3080         mtm->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3081         mtm->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3082         mtm->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3083         mtm->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3084         mtm->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3085         mtm->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3086         mtm->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3087         mtm->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3088
3089         add_option (S_("Preferences|Metering"), mtm);
3090
3091
3092         ComboOption<MeterType>* mtb = new ComboOption<MeterType> (
3093                 "meter-type-bus",
3094                 _("Default Meter Type for Busses"),
3095                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_bus),
3096                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_bus)
3097                 );
3098         mtb->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3099         mtb->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3100         mtb->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3101         mtb->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3102         mtb->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3103         mtb->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3104         mtb->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3105         mtb->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3106
3107         add_option (S_("Preferences|Metering"), mtb);
3108
3109         ComboOption<MeterType>* mtt = new ComboOption<MeterType> (
3110                 "meter-type-track",
3111                 _("Default Meter Type for Tracks"),
3112                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_track),
3113                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_track)
3114                 );
3115         mtt->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3116         mtt->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
3117
3118         add_option (S_("Preferences|Metering"), mtt);
3119
3120
3121         Gtkmm2ext::UI::instance()->set_tip
3122                 (mpks->tip_widget(),
3123                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
3124
3125         add_option (S_("Preferences|Metering"), mpks);
3126
3127         add_option (S_("Preferences|Metering"),
3128              new BoolOption (
3129                      "meter-style-led",
3130                      _("LED meter style"),
3131                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_style_led),
3132                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_style_led)
3133                      ));
3134
3135         /* and now the theme manager */
3136
3137         ThemeManager* tm = manage (new ThemeManager);
3138         add_page (_("Theme"), *tm);
3139
3140         //trigger some parameter-changed messages which affect widget-visibility or -sensitivity
3141         parameter_changed ("send-ltc");
3142         parameter_changed ("sync-source");
3143         parameter_changed ("use-monitor-bus");
3144 }
3145
3146 void
3147 RCOptionEditor::parameter_changed (string const & p)
3148 {
3149         OptionEditor::parameter_changed (p);
3150
3151         if (p == "use-monitor-bus") {
3152                 bool const s = Config->get_use_monitor_bus ();
3153                 if (!s) {
3154                         /* we can't use this if we don't have a monitor bus */
3155                         Config->set_solo_control_is_listen_control (false);
3156                 }
3157                 _solo_control_is_listen_control->set_sensitive (s);
3158                 _listen_position->set_sensitive (s);
3159         } else if (p == "sync-source") {
3160                 _sync_source->set_sensitive (true);
3161                 if (_session) {
3162                         _sync_source->set_sensitive (!_session->config.get_external_sync());
3163                 }
3164                 switch(Config->get_sync_source()) {
3165                 case ARDOUR::MTC:
3166                 case ARDOUR::LTC:
3167                         _sync_genlock->set_sensitive (true);
3168                         _sync_framerate->set_sensitive (true);
3169                         _sync_source_2997->set_sensitive (true);
3170                         break;
3171                 default:
3172                         _sync_genlock->set_sensitive (false);
3173                         _sync_framerate->set_sensitive (false);
3174                         _sync_source_2997->set_sensitive (false);
3175                         break;
3176                 }
3177         } else if (p == "send-ltc") {
3178                 bool const s = Config->get_send_ltc ();
3179                 _ltc_send_continuously->set_sensitive (s);
3180                 _ltc_volume_slider->set_sensitive (s);
3181         }
3182 }
3183
3184 void RCOptionEditor::ltc_generator_volume_changed () {
3185         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
3186 }
3187
3188 void
3189 RCOptionEditor::populate_sync_options ()
3190 {
3191         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
3192
3193         _sync_source->clear ();
3194
3195         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
3196                 _sync_source->add (*i, sync_source_to_string (*i));
3197         }
3198
3199         if (sync_opts.empty()) {
3200                 _sync_source->set_sensitive(false);
3201         } else {
3202                 if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
3203                         _rc_config->set_sync_source(sync_opts.front());
3204                 }
3205         }
3206 }