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