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