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