Add Scrollbar to MIDI Port Option List
[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 OptionEditorPageBox
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                         Label* l = manage (new Label (string_compose ("<b>%1</b>", _("Control Surfaces"))));
1368                         l->set_alignment (0, 0.5);
1369                         l->set_use_markup (true);
1370                         _box->pack_start (*l, false, false);
1371                         _box->pack_start (_view, false, false);
1372
1373                         Gtk::HBox* edit_box = manage (new Gtk::HBox);
1374                         edit_box->set_spacing(3);
1375                         _box->pack_start (*edit_box, false, false);
1376                         edit_box->show ();
1377
1378                         Label* label = manage (new Label);
1379                         label->set_text (_("Edit the settings for selected protocol (it must be ENABLED first):"));
1380                         edit_box->pack_start (*label, false, false);
1381                         label->show ();
1382
1383                         edit_button = manage (new Button(_("Show Protocol Settings")));
1384                         edit_button->signal_clicked().connect (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_btn_clicked));
1385                         edit_box->pack_start (*edit_button, true, true);
1386                         edit_button->set_sensitive (false);
1387                         edit_button->show ();
1388
1389                         ControlProtocolManager& m = ControlProtocolManager::instance ();
1390                         m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
1391                                         boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
1392
1393                         _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
1394                         _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
1395                         _view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::selection_changed));
1396                 }
1397
1398                 void parameter_changed (std::string const &)
1399                 {
1400
1401                 }
1402
1403                 void set_state_from_config ()
1404                 {
1405                         _store->clear ();
1406
1407                         ControlProtocolManager& m = ControlProtocolManager::instance ();
1408                         for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
1409
1410                                 if (!(*i)->mandatory) {
1411                                         TreeModel::Row r = *_store->append ();
1412                                         r[_model.name] = (*i)->name;
1413                                         r[_model.enabled] = ((*i)->protocol || (*i)->requested);
1414                                         r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
1415                                         r[_model.protocol_info] = *i;
1416                                 }
1417                         }
1418                 }
1419
1420         private:
1421
1422                 void protocol_status_changed (ControlProtocolInfo* cpi) {
1423                         /* find the row */
1424                         TreeModel::Children rows = _store->children();
1425
1426                         for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
1427                                 string n = ((*x)[_model.name]);
1428
1429                                 if ((*x)[_model.protocol_info] == cpi) {
1430                                         _ignore_view_change++;
1431                                         (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
1432                                         _ignore_view_change--;
1433                                         break;
1434                                 }
1435                         }
1436                 }
1437
1438                 void selection_changed ()
1439                 {
1440                         //enable the Edit button when a row is selected for editing
1441                         TreeModel::Row row = *(_view.get_selection()->get_selected());
1442                         if (row && row[_model.enabled])
1443                                 edit_button->set_sensitive (true);
1444                         else
1445                                 edit_button->set_sensitive (false);
1446                 }
1447
1448                 void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
1449                 {
1450                         TreeModel::Row r = *i;
1451
1452                         if (_ignore_view_change) {
1453                                 return;
1454                         }
1455
1456                         ControlProtocolInfo* cpi = r[_model.protocol_info];
1457                         if (!cpi) {
1458                                 return;
1459                         }
1460
1461                         bool const was_enabled = (cpi->protocol != 0);
1462                         bool const is_enabled = r[_model.enabled];
1463
1464
1465                         if (was_enabled != is_enabled) {
1466
1467                                 if (!was_enabled) {
1468                                         ControlProtocolManager::instance().activate (*cpi);
1469                                 } else {
1470                                         ControlProtocolManager::instance().deactivate (*cpi);
1471                                 }
1472                         }
1473
1474                         bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
1475                         bool const is_feedback = r[_model.feedback];
1476
1477                         if (was_feedback != is_feedback && cpi->protocol) {
1478                                 cpi->protocol->set_feedback (is_feedback);
1479                         }
1480                         selection_changed ();
1481                 }
1482
1483                 void edit_btn_clicked ()
1484                 {
1485                         std::string name;
1486                         ControlProtocolInfo* cpi;
1487                         TreeModel::Row row;
1488
1489                         row = *(_view.get_selection()->get_selected());
1490                         if (!row[_model.enabled]) {
1491                                 return;
1492                         }
1493                         cpi = row[_model.protocol_info];
1494                         if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
1495                                 return;
1496                         }
1497                         Box* box = (Box*) cpi->protocol->get_gui ();
1498                         if (!box) {
1499                                 return;
1500                         }
1501                         if (box->get_parent()) {
1502                                 static_cast<ArdourWindow*>(box->get_parent())->present();
1503                                 return;
1504                         }
1505                         WindowTitle title (Glib::get_application_name());
1506                         title += row[_model.name];
1507                         title += _("Configuration");
1508                         /* once created, the window is managed by the surface itself (as ->get_parent())
1509                          * Surface's tear_down_gui() is called on session close, when de-activating
1510                          * or re-initializing a surface.
1511                          * tear_down_gui() hides an deletes the Window if it exists.
1512                          */
1513                         ArdourWindow* win = new ArdourWindow (*((Gtk::Window*) _view.get_toplevel()), title.get_string());
1514                         win->set_title ("Control Protocol Options");
1515                         win->add (*box);
1516                         box->show ();
1517                         win->present ();
1518                 }
1519
1520                 void edit_clicked (GdkEventButton* ev)
1521                 {
1522                         if (ev->type != GDK_2BUTTON_PRESS) {
1523                                 return;
1524                         }
1525
1526                         edit_btn_clicked();
1527                 }
1528
1529                 class ControlSurfacesModelColumns : public TreeModelColumnRecord
1530         {
1531                 public:
1532
1533                         ControlSurfacesModelColumns ()
1534                         {
1535                                 add (name);
1536                                 add (enabled);
1537                                 add (feedback);
1538                                 add (protocol_info);
1539                         }
1540
1541                         TreeModelColumn<string> name;
1542                         TreeModelColumn<bool> enabled;
1543                         TreeModelColumn<bool> feedback;
1544                         TreeModelColumn<ControlProtocolInfo*> protocol_info;
1545         };
1546
1547                 Glib::RefPtr<ListStore> _store;
1548                 ControlSurfacesModelColumns _model;
1549                 TreeView _view;
1550                 PBD::ScopedConnection protocol_status_connection;
1551                 uint32_t _ignore_view_change;
1552                 Gtk::Button* edit_button;
1553 };
1554
1555 class VideoTimelineOptions : public OptionEditorPageBox
1556 {
1557         public:
1558                 VideoTimelineOptions (RCConfiguration* c)
1559                         : _rc_config (c)
1560                         , _show_video_export_info_button (_("Show Video Export Info before export"))
1561                         , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
1562                         , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
1563                         , _xjadeo_browse_button (_("Browse..."))
1564         {
1565                 Table* t = manage (new Table (8, 4));
1566                 t->set_spacings (4);
1567
1568                 Label* l = manage (new Label (string_compose ("<b>%1</b>", _("Video Server"))));
1569                 l->set_use_markup (true);
1570                 l->set_alignment (0, 0.5);
1571                 t->attach (*l, 0, 4, 0, 1, EXPAND | FILL, FILL | EXPAND, 0, 0);
1572
1573                 t->attach (_video_advanced_setup_button, 1, 4, 1, 2);
1574                 _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
1575                 Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
1576                                 _("<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."));
1577
1578                 l = manage (new Label (_("Video Server URL:")));
1579                 l->set_alignment (0, 0.5);
1580                 t->attach (*l, 1, 2, 2, 3, FILL);
1581                 t->attach (_video_server_url_entry, 2, 4, 2, 3, FILL);
1582                 Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
1583                                 _("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"));
1584
1585                 l = manage (new Label (_("Video Folder:")));
1586                 l->set_alignment (0, 0.5);
1587                 t->attach (*l, 1, 2, 3, 4, FILL);
1588                 t->attach (_video_server_docroot_entry, 2, 4, 3, 4);
1589                 Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
1590                                 _("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."));
1591
1592                 t->attach (_show_video_export_info_button, 1, 4, 4, 5);
1593                 _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
1594                 Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
1595                                 _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
1596
1597                 t->attach (_show_video_server_dialog_button, 1, 4, 5, 6);
1598                 _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
1599                 Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
1600                                 _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
1601
1602                 l = manage (new Label (""));
1603                 t->attach (*l, 0, 4, 6, 7, EXPAND | FILL);
1604
1605                 l = manage (new Label (string_compose ("<b>%1</b>", _("Video Monitor"))));
1606                 l->set_use_markup (true);
1607                 l->set_alignment (0, 0.5);
1608                 t->attach (*l, 0, 4, 7, 8, EXPAND | FILL);
1609
1610                 l = manage (new Label (string_compose (_("Custom Path to Video Monitor (%1) - leave empty for default:"),
1611 #ifdef __APPLE__
1612                                                 "Jadeo.app"
1613 #elif defined PLATFORM_WINDOWS
1614                                                 "xjadeo.exe"
1615 #else
1616                                                 "xjadeo"
1617 #endif
1618                                                 )));
1619                 l->set_alignment (0, 0.5);
1620                 t->attach (*l, 1, 4, 8, 9, FILL);
1621                 t->attach (_custom_xjadeo_path, 2, 3, 9, 10);
1622                 Gtkmm2ext::UI::instance()->set_tip (_custom_xjadeo_path, _("Set a custom path to the Video Monitor Executable, changing this requires a restart."));
1623                 t->attach (_xjadeo_browse_button, 3, 4, 9, 10, FILL);
1624
1625                 _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1626                 _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1627                 _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1628                 _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1629                 _custom_xjadeo_path.signal_changed().connect (sigc::mem_fun (*this, &VideoTimelineOptions::custom_xjadeo_path_changed));
1630                 _xjadeo_browse_button.signal_clicked ().connect (sigc::mem_fun (*this, &VideoTimelineOptions::xjadeo_browse_clicked));
1631
1632                 // xjadeo-path is a UIConfig parameter
1633                 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &VideoTimelineOptions::parameter_changed));
1634
1635                 _box->pack_start (*t,true,true);
1636         }
1637
1638                 void server_url_changed ()
1639                 {
1640                         _rc_config->set_video_server_url (_video_server_url_entry.get_text());
1641                 }
1642
1643                 void server_docroot_changed ()
1644                 {
1645                         _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
1646                 }
1647
1648                 void show_video_export_info_toggled ()
1649                 {
1650                         bool const x = _show_video_export_info_button.get_active ();
1651                         _rc_config->set_show_video_export_info (x);
1652                 }
1653
1654                 void show_video_server_dialog_toggled ()
1655                 {
1656                         bool const x = _show_video_server_dialog_button.get_active ();
1657                         _rc_config->set_show_video_server_dialog (x);
1658                 }
1659
1660                 void video_advanced_setup_toggled ()
1661                 {
1662                         bool const x = _video_advanced_setup_button.get_active ();
1663                         _rc_config->set_video_advanced_setup(x);
1664                 }
1665
1666                 void custom_xjadeo_path_changed ()
1667                 {
1668                         UIConfiguration::instance().set_xjadeo_binary (_custom_xjadeo_path.get_text());
1669                 }
1670
1671                 void xjadeo_browse_clicked ()
1672                 {
1673                         Gtk::FileChooserDialog dialog(_("Set Video Monitor Executable"), Gtk::FILE_CHOOSER_ACTION_OPEN);
1674                         dialog.set_filename (UIConfiguration::instance().get_xjadeo_binary());
1675                         dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1676                         dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
1677                         if (dialog.run () == Gtk::RESPONSE_OK) {
1678                                 const std::string& filename = dialog.get_filename();
1679                                 if (!filename.empty() && (
1680 #ifdef __APPLE__
1681                                                         Glib::file_test (filename + "/Contents/MacOS/xjadeo", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE) ||
1682 #endif
1683                                                         Glib::file_test (filename, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE)
1684                                                         )) {
1685                                         UIConfiguration::instance().set_xjadeo_binary (filename);
1686                                 }
1687                         }
1688                 }
1689
1690                 void parameter_changed (string const & p)
1691                 {
1692                         if (p == "video-server-url") {
1693                                 _video_server_url_entry.set_text (_rc_config->get_video_server_url());
1694                         } else if (p == "video-server-docroot") {
1695                                 _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
1696                         } else if (p == "show-video-export-info") {
1697                                 bool const x = _rc_config->get_show_video_export_info();
1698                                 _show_video_export_info_button.set_active (x);
1699                         } else if (p == "show-video-server-dialog") {
1700                                 bool const x = _rc_config->get_show_video_server_dialog();
1701                                 _show_video_server_dialog_button.set_active (x);
1702                         } else if (p == "video-advanced-setup") {
1703                                 bool const x = _rc_config->get_video_advanced_setup();
1704                                 _video_advanced_setup_button.set_active(x);
1705                                 _video_server_docroot_entry.set_sensitive(x);
1706                                 _video_server_url_entry.set_sensitive(x);
1707                         } else if (p == "xjadeo-binary") {
1708                                 _custom_xjadeo_path.set_text (UIConfiguration::instance().get_xjadeo_binary());
1709                         }
1710                 }
1711
1712                 void set_state_from_config ()
1713                 {
1714                         parameter_changed ("video-server-url");
1715                         parameter_changed ("video-server-docroot");
1716                         parameter_changed ("video-monitor-setup-dialog");
1717                         parameter_changed ("show-video-export-info");
1718                         parameter_changed ("show-video-server-dialog");
1719                         parameter_changed ("video-advanced-setup");
1720                         parameter_changed ("xjadeo-binary");
1721                 }
1722
1723         private:
1724                 RCConfiguration* _rc_config;
1725                 Entry _video_server_url_entry;
1726                 Entry _video_server_docroot_entry;
1727                 Entry _custom_xjadeo_path;
1728                 CheckButton _show_video_export_info_button;
1729                 CheckButton _show_video_server_dialog_button;
1730                 CheckButton _video_advanced_setup_button;
1731                 Button _xjadeo_browse_button;
1732 };
1733
1734 class ColumVisibilityOption : public Option
1735 {
1736         public:
1737         ColumVisibilityOption (string id, string name, uint32_t n_col, sigc::slot<uint32_t> get, sigc::slot<bool, uint32_t> set)
1738                 : Option (id, name)
1739                 , _heading (name)
1740                 , _n_col (n_col)
1741                 , _get (get)
1742                 , _set (set)
1743         {
1744                 cb = (CheckButton**) malloc (sizeof (CheckButton*) * n_col);
1745                 for (uint32_t i = 0; i < n_col; ++i) {
1746                         CheckButton* col = manage (new CheckButton (string_compose (_("Column %1"), i + 1)));
1747                         col->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &ColumVisibilityOption::column_toggled), i));
1748                         _hbox.pack_start (*col);
1749                         cb[i] = col;
1750                 }
1751                 parameter_changed (id);
1752         }
1753
1754         ~ColumVisibilityOption () {
1755                 free (cb);
1756         }
1757
1758         Gtk::Widget& tip_widget() { return _hbox; }
1759
1760         void set_state_from_config ()
1761         {
1762                 uint32_t c = _get();
1763                 for (uint32_t i = 0; i < _n_col; ++i) {
1764                         bool en = (c & (1<<i)) ? true : false;
1765                         if (cb[i]->get_active () != en) {
1766                                 cb[i]->set_active (en);
1767                         }
1768                 }
1769         }
1770
1771         void add_to_page (OptionEditorPage* p)
1772         {
1773                 _heading.add_to_page (p);
1774                 add_widget_to_page (p, &_hbox);
1775         }
1776         private:
1777
1778         void column_toggled (int b) {
1779                 uint32_t c = _get();
1780                 uint32_t cc = c;
1781                 if (cb[b]->get_active ()) {
1782                         c |= (1<<b);
1783                 } else {
1784                         c &= ~(1<<b);
1785                 }
1786                 if (cc != c) {
1787                         _set (c);
1788                 }
1789         }
1790
1791         HBox _hbox;
1792         OptionEditorHeading _heading;
1793
1794         CheckButton** cb;
1795         uint32_t _n_col;
1796         sigc::slot<uint32_t> _get;
1797         sigc::slot<bool, uint32_t> _set;
1798 };
1799
1800
1801 /** A class which allows control of visibility of some editor components usign
1802  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
1803  *  which has the correct members, but with null widget pointers.  This
1804  *  class allows the user to set visibility of the members, the details
1805  *  of which are stored in a configuration variable which can be watched
1806  *  by parts of the editor that actually contain the widgets whose visibility
1807  *  is being controlled.
1808  */
1809
1810 class VisibilityOption : public Option
1811 {
1812 public:
1813         /** @param name User-visible name for this group.
1814          *  @param g `Dummy' VisibilityGroup (as described above).
1815          *  @param get Method to get the value of the appropriate configuration variable.
1816          *  @param set Method to set the value of the appropriate configuration variable.
1817          */
1818         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1819                 : Option (g->get_state_name(), name)
1820                 , _heading (name)
1821                 , _visibility_group (g)
1822                 , _get (get)
1823                 , _set (set)
1824         {
1825                 /* Watch for changes made by the user to our members */
1826                 _visibility_group->VisibilityChanged.connect_same_thread (
1827                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1828                         );
1829         }
1830
1831         void set_state_from_config ()
1832         {
1833                 /* Set our state from the current configuration */
1834                 _visibility_group->set_state (_get ());
1835         }
1836
1837         void add_to_page (OptionEditorPage* p)
1838         {
1839                 _heading.add_to_page (p);
1840                 add_widget_to_page (p, _visibility_group->list_view ());
1841         }
1842
1843         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1844
1845 private:
1846         void changed ()
1847         {
1848                 /* The user has changed something, so reflect this change
1849                    in the RCConfiguration.
1850                 */
1851                 _set (_visibility_group->get_state_value ());
1852         }
1853
1854         OptionEditorHeading _heading;
1855         VisibilityGroup* _visibility_group;
1856         sigc::slot<std::string> _get;
1857         sigc::slot<bool, std::string> _set;
1858         PBD::ScopedConnection _visibility_group_connection;
1859 };
1860
1861
1862 class MidiPortOptions : public OptionEditorBox, public sigc::trackable
1863 {
1864         public:
1865                 MidiPortOptions() {
1866
1867                         setup_midi_port_view (midi_output_view, false);
1868                         setup_midi_port_view (midi_input_view, true);
1869
1870
1871                         _box->pack_start (*manage (new Label("")), false, false);
1872                         input_label.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Inputs")));
1873                         _box->pack_start (input_label, false, false);
1874
1875                         Gtk::ScrolledWindow* scroller = manage (new Gtk::ScrolledWindow);
1876                         scroller->add (midi_input_view);
1877                         scroller->set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
1878                         scroller->set_size_request (-1, 180);
1879                         _box->pack_start (*scroller, false, false);
1880
1881                         _box->pack_start (*manage (new Label("")), false, false);
1882                         output_label.set_markup (string_compose ("<span size=\"large\" weight=\"bold\">%1</span>", _("MIDI Outputs")));
1883                         _box->pack_start (output_label, false, false);
1884
1885                         scroller = manage (new Gtk::ScrolledWindow);
1886                         scroller->add (midi_output_view);
1887                         scroller->set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
1888                         scroller->set_size_request (-1, 180);
1889                         _box->pack_start (*scroller, false, false);
1890
1891                         midi_output_view.show ();
1892                         midi_input_view.show ();
1893
1894                         _box->signal_show().connect (sigc::mem_fun (*this, &MidiPortOptions::on_show));
1895                 }
1896
1897                 void parameter_changed (string const&) {}
1898                 void set_state_from_config() {}
1899
1900                 void on_show () {
1901                         refill ();
1902
1903                         AudioEngine::instance()->PortRegisteredOrUnregistered.connect (connections,
1904                                         invalidator (*this),
1905                                         boost::bind (&MidiPortOptions::refill, this),
1906                                         gui_context());
1907                         AudioEngine::instance()->MidiPortInfoChanged.connect (connections,
1908                                         invalidator (*this),
1909                                         boost::bind (&MidiPortOptions::refill, this),
1910                                         gui_context());
1911                         AudioEngine::instance()->MidiSelectionPortsChanged.connect (connections,
1912                                         invalidator (*this),
1913                                         boost::bind (&MidiPortOptions::refill, this),
1914                                         gui_context());
1915                 }
1916
1917                 void refill () {
1918
1919                         if (refill_midi_ports (true, midi_input_view)) {
1920                                 input_label.show ();
1921                         } else {
1922                                 input_label.hide ();
1923                         }
1924                         if (refill_midi_ports (false, midi_output_view)) {
1925                                 output_label.show ();
1926                         } else {
1927                                 output_label.hide ();
1928                         }
1929                 }
1930
1931         private:
1932                 PBD::ScopedConnectionList connections;
1933
1934                 /* MIDI port management */
1935                 struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
1936
1937                         MidiPortColumns () {
1938                                 add (pretty_name);
1939                                 add (music_data);
1940                                 add (control_data);
1941                                 add (selection);
1942                                 add (name);
1943                                 add (filler);
1944                         }
1945
1946                         Gtk::TreeModelColumn<std::string> pretty_name;
1947                         Gtk::TreeModelColumn<bool> music_data;
1948                         Gtk::TreeModelColumn<bool> control_data;
1949                         Gtk::TreeModelColumn<bool> selection;
1950                         Gtk::TreeModelColumn<std::string> name;
1951                         Gtk::TreeModelColumn<std::string> filler;
1952                 };
1953
1954                 MidiPortColumns midi_port_columns;
1955                 Gtk::TreeView midi_input_view;
1956                 Gtk::TreeView midi_output_view;
1957                 Gtk::Label input_label;
1958                 Gtk::Label output_label;
1959
1960                 void setup_midi_port_view (Gtk::TreeView&, bool with_selection);
1961                 bool refill_midi_ports (bool for_input, Gtk::TreeView&);
1962                 void pretty_name_edit (std::string const & path, std::string const & new_text, Gtk::TreeView*);
1963                 void midi_music_column_toggled (std::string const & path, Gtk::TreeView*);
1964                 void midi_control_column_toggled (std::string const & path, Gtk::TreeView*);
1965                 void midi_selection_column_toggled (std::string const & path, Gtk::TreeView*);
1966 };
1967
1968 void
1969 MidiPortOptions::setup_midi_port_view (Gtk::TreeView& view, bool with_selection)
1970 {
1971         int pretty_name_column;
1972         int music_column;
1973         int control_column;
1974         int selection_column;
1975         TreeViewColumn* col;
1976         Gtk::Label* l;
1977
1978         pretty_name_column = view.append_column_editable (_("Name (click to edit)"), midi_port_columns.pretty_name) - 1;
1979
1980         col = manage (new TreeViewColumn ("", midi_port_columns.music_data));
1981         col->set_alignment (ALIGN_CENTER);
1982         l = manage (new Label (_("Music Data")));
1983         set_tooltip (*l, string_compose (_("If ticked, %1 will consider this port to be a source of music performance data."), PROGRAM_NAME));
1984         col->set_widget (*l);
1985         l->show ();
1986         music_column = view.append_column (*col) - 1;
1987
1988         col = manage (new TreeViewColumn ("", midi_port_columns.control_data));
1989         col->set_alignment (ALIGN_CENTER);
1990         l = manage (new Label (_("Control Data")));
1991         set_tooltip (*l, string_compose (_("If ticked, %1 will consider this port to be a source of control data."), PROGRAM_NAME));
1992         col->set_widget (*l);
1993         l->show ();
1994         control_column = view.append_column (*col) - 1;
1995
1996         if (with_selection) {
1997                 col = manage (new TreeViewColumn (_("Follow Selection"), midi_port_columns.selection));
1998                 selection_column = view.append_column (*col) - 1;
1999                 l = manage (new Label (_("Follow Selection")));
2000                 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));
2001                 col->set_widget (*l);
2002                 l->show ();
2003         }
2004
2005         /* filler column so that the last real column doesn't expand */
2006         view.append_column ("", midi_port_columns.filler);
2007
2008         CellRendererText* pretty_name_cell = dynamic_cast<CellRendererText*> (view.get_column_cell_renderer (pretty_name_column));
2009         pretty_name_cell->property_editable() = true;
2010         pretty_name_cell->signal_edited().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::pretty_name_edit), &view));
2011
2012         CellRendererToggle* toggle_cell;
2013
2014         toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (music_column));
2015         toggle_cell->property_activatable() = true;
2016         toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_music_column_toggled), &view));
2017
2018         toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (control_column));
2019         toggle_cell->property_activatable() = true;
2020         toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_control_column_toggled), &view));
2021
2022         if (with_selection) {
2023                 toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (selection_column));
2024                 toggle_cell->property_activatable() = true;
2025                 toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_selection_column_toggled), &view));
2026         }
2027
2028         view.get_selection()->set_mode (SELECTION_NONE);
2029         view.set_tooltip_column (4); /* port "real" name */
2030         view.get_column(0)->set_resizable (true);
2031         view.get_column(0)->set_expand (true);
2032 }
2033
2034 bool
2035 MidiPortOptions::refill_midi_ports (bool for_input, Gtk::TreeView& view)
2036 {
2037         using namespace ARDOUR;
2038
2039         std::vector<string> ports;
2040
2041         AudioEngine::instance()->get_known_midi_ports (ports);
2042
2043         if (ports.empty()) {
2044                 view.hide ();
2045                 return false;
2046         }
2047
2048         Glib::RefPtr<ListStore> model = Gtk::ListStore::create (midi_port_columns);
2049
2050         for (vector<string>::const_iterator s = ports.begin(); s != ports.end(); ++s) {
2051
2052                 if (AudioEngine::instance()->port_is_mine (*s)) {
2053                         continue;
2054                 }
2055
2056                 PortManager::MidiPortInformation mpi (AudioEngine::instance()->midi_port_information (*s));
2057
2058                 if (mpi.pretty_name.empty()) {
2059                         /* vanished since get_known_midi_ports() */
2060                         continue;
2061                 }
2062
2063                 if (for_input != mpi.input) {
2064                         continue;
2065                 }
2066
2067                 TreeModel::Row row = *(model->append());
2068
2069                 row[midi_port_columns.pretty_name] = mpi.pretty_name;
2070                 row[midi_port_columns.music_data] = mpi.properties & MidiPortMusic;
2071                 row[midi_port_columns.control_data] = mpi.properties & MidiPortControl;
2072                 row[midi_port_columns.selection] = mpi.properties & MidiPortSelection;
2073                 row[midi_port_columns.name] = *s;
2074         }
2075
2076         view.set_model (model);
2077
2078         return true;
2079 }
2080
2081 void
2082 MidiPortOptions::midi_music_column_toggled (string const & path, TreeView* view)
2083 {
2084         TreeIter iter = view->get_model()->get_iter (path);
2085
2086         if (!iter) {
2087                 return;
2088         }
2089
2090         bool new_value = ! bool ((*iter)[midi_port_columns.music_data]);
2091
2092         /* don't reset model - wait for MidiPortInfoChanged signal */
2093
2094         if (new_value) {
2095                 ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortMusic);
2096         } else {
2097                 ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortMusic);
2098         }
2099 }
2100
2101 void
2102 MidiPortOptions::midi_control_column_toggled (string const & path, TreeView* view)
2103 {
2104         TreeIter iter = view->get_model()->get_iter (path);
2105
2106         if (!iter) {
2107                 return;
2108         }
2109
2110         bool new_value = ! bool ((*iter)[midi_port_columns.control_data]);
2111
2112         /* don't reset model - wait for MidiPortInfoChanged signal */
2113
2114         if (new_value) {
2115                 ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortControl);
2116         } else {
2117                 ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortControl);
2118         }
2119 }
2120
2121 void
2122 MidiPortOptions::midi_selection_column_toggled (string const & path, TreeView* view)
2123 {
2124         TreeIter iter = view->get_model()->get_iter (path);
2125
2126         if (!iter) {
2127                 return;
2128         }
2129
2130         bool new_value = ! bool ((*iter)[midi_port_columns.selection]);
2131
2132         /* don't reset model - wait for MidiSelectionPortsChanged signal */
2133
2134         if (new_value) {
2135                 ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortSelection);
2136         } else {
2137                 ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortSelection);
2138         }
2139 }
2140
2141 void
2142 MidiPortOptions::pretty_name_edit (std::string const & path, string const & new_text, Gtk::TreeView* view)
2143 {
2144         TreeIter iter = view->get_model()->get_iter (path);
2145
2146         if (!iter) {
2147                 return;
2148         }
2149
2150         boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
2151         if (backend) {
2152                 ARDOUR::PortEngine::PortHandle ph = backend->get_port_by_name ((*iter)[midi_port_columns.name]);
2153                 if (ph) {
2154                         backend->set_port_property (ph, "http://jackaudio.org/metadata/pretty-name", new_text, "");
2155                         (*iter)[midi_port_columns.pretty_name] = new_text;
2156                 }
2157         }
2158 }
2159
2160 /*============*/
2161
2162
2163 RCOptionEditor::RCOptionEditor ()
2164         : OptionEditorContainer (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
2165         , Tabbable (*this, _("Preferences")) /* pack self-as-vbox into tabbable */
2166         , _rc_config (Config)
2167         , _mixer_strip_visibility ("mixer-element-visibility")
2168 {
2169         UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &RCOptionEditor::parameter_changed));
2170
2171         /* MISC */
2172
2173         uint32_t hwcpus = hardware_concurrency ();
2174         BoolOption* bo;
2175         BoolComboOption* bco;
2176
2177         if (hwcpus > 1) {
2178                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
2179
2180                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
2181                                 "processor-usage",
2182                                 _("Signal processing uses"),
2183                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
2184                                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
2185                                 );
2186
2187                 procs->add (-1, _("all but one processor"));
2188                 procs->add (0, _("all available processors"));
2189
2190                 for (uint32_t i = 1; i <= hwcpus; ++i) {
2191                         procs->add (i, string_compose (P_("%1 processor", "%1 processors", i), i));
2192                 }
2193
2194                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
2195
2196                 add_option (_("Misc"), procs);
2197         }
2198
2199         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
2200
2201         add_option (_("Misc"), new UndoOptions (_rc_config));
2202
2203         add_option (_("Misc"),
2204              new BoolOption (
2205                      "verify-remove-last-capture",
2206                      _("Verify removal of last capture"),
2207                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
2208                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
2209                      ));
2210
2211         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
2212
2213         add_option (_("Misc"),
2214              new BoolOption (
2215                      "periodic-safety-backups",
2216                      _("Make periodic backups of the session file"),
2217                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
2218                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
2219                      ));
2220
2221         add_option (_("Misc"),
2222              new BoolOption (
2223                      "only-copy-imported-files",
2224                      _("Always copy imported files"),
2225                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_only_copy_imported_files),
2226                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_only_copy_imported_files)
2227                      ));
2228
2229         add_option (_("Misc"), new DirectoryOption (
2230                             X_("default-session-parent-dir"),
2231                             _("Default folder for new sessions:"),
2232                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
2233                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
2234                             ));
2235
2236         add_option (_("Misc"),
2237              new SpinOption<uint32_t> (
2238                      "max-recent-sessions",
2239                      _("Maximum number of recent sessions"),
2240                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
2241                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
2242                      0, 1000, 1, 20
2243                      ));
2244
2245         add_option (_("Misc/Click"), new OptionEditorHeading (_("Click")));
2246
2247         add_option (_("Misc/Click"), new ClickOptions (_rc_config));
2248
2249         add_option (_("Misc/Click"),
2250              new FaderOption (
2251                      "click-gain",
2252                      _("Click gain level"),
2253                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
2254                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
2255                      ));
2256
2257         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
2258
2259         add_option (_("Misc"),
2260              new SpinOption<double> (
2261                      "automation-thinning-factor",
2262                      _("Thinning factor (larger value => less data)"),
2263                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
2264                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
2265                      0, 1000, 1, 20
2266                      ));
2267
2268         add_option (_("Misc"),
2269              new SpinOption<double> (
2270                      "automation-interval-msecs",
2271                      _("Automation sampling interval (milliseconds)"),
2272                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
2273                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
2274                      1, 1000, 1, 20
2275                      ));
2276
2277         add_option (_("Misc"), new OptionEditorHeading (_("Tempo")));
2278
2279         BoolOption* tsf;
2280
2281         tsf = new BoolOption (
2282                 "allow-non-quarter-pulse",
2283                 _("Allow non quarter-note pulse"),
2284                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_allow_non_quarter_pulse),
2285                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_allow_non_quarter_pulse)
2286                 );
2287         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
2288                                             string_compose (_("<b>When enabled</b> %1 will allow tempo to be expressed in divisions per minute\n"
2289                                                               "<b>When disabled</b> %1 will only allow tempo to be expressed in quarter notes per minute"),
2290                                                             PROGRAM_NAME));
2291         add_option (_("Misc"), tsf);
2292
2293         /* TRANSPORT */
2294
2295         add_option (_("Transport"), new OptionEditorHeading (S_("Transport Options")));
2296
2297         tsf = new BoolOption (
2298                      "latched-record-enable",
2299                      _("Keep record-enable engaged on stop"),
2300                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
2301                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
2302                      );
2303         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
2304         add_option (_("Transport"), tsf);
2305
2306         tsf = new BoolOption (
2307                      "loop-is-mode",
2308                      _("Play loop is a transport mode"),
2309                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
2310                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
2311                      );
2312         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
2313                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
2314                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
2315         add_option (_("Transport"), tsf);
2316
2317         tsf = new BoolOption (
2318                      "stop-recording-on-xrun",
2319                      _("Stop recording when an xrun occurs"),
2320                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
2321                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
2322                      );
2323         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
2324                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
2325                                                             PROGRAM_NAME));
2326         add_option (_("Transport"), tsf);
2327
2328         tsf = new BoolOption (
2329                      "create-xrun-marker",
2330                      _("Create markers where xruns occur"),
2331                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
2332                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
2333                      );
2334         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
2335         add_option (_("Transport"), tsf);
2336
2337         tsf = new BoolOption (
2338                      "stop-at-session-end",
2339                      _("Stop at the end of the session"),
2340                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
2341                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
2342                      );
2343         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
2344                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
2345                                                               "when it reaches the current session end marker\n\n"
2346                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
2347                                                             PROGRAM_NAME));
2348         add_option (_("Transport"), tsf);
2349
2350         tsf = new BoolOption (
2351                      "seamless-loop",
2352                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
2353                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
2354                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
2355                      );
2356         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
2357                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
2358                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
2359                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
2360                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
2361         add_option (_("Transport"), tsf);
2362
2363         tsf = new BoolOption (
2364                      "disable-disarm-during-roll",
2365                      _("Disable per-track record disarm while rolling"),
2366                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
2367                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
2368                      );
2369         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"));
2370         add_option (_("Transport"), tsf);
2371
2372         tsf = new BoolOption (
2373                      "quieten_at_speed",
2374                      _("12dB gain reduction during fast-forward and fast-rewind"),
2375                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
2376                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
2377                      );
2378         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
2379                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
2380         add_option (_("Transport"), tsf);
2381
2382         ComboOption<float>* psc = new ComboOption<float> (
2383                      "preroll-seconds",
2384                      _("Preroll"),
2385                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_preroll_seconds),
2386                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_preroll_seconds)
2387                      );
2388         Gtkmm2ext::UI::instance()->set_tip (psc->tip_widget(),
2389                                             (_("The amount of preroll (in seconds) to apply when <b>Play with Preroll</b> is initiated.\n\n"
2390                                                "If <b>Follow Edits</b> is enabled, the preroll is applied to the playhead position when a region is selected or trimmed.")));
2391         psc->add (0.0, _("0 (no pre-roll)"));
2392         psc->add (0.1, _("0.1 second"));
2393         psc->add (0.25, _("0.25 second"));
2394         psc->add (0.5, _("0.5 second"));
2395         psc->add (1.0, _("1.0 second"));
2396         psc->add (2.0, _("2.0 seconds"));
2397         add_option (_("Transport"), psc);
2398
2399         add_option (_("Transport/Sync"), new OptionEditorHeading (S_("Synchronization and Slave Options")));
2400
2401         _sync_source = new ComboOption<SyncSource> (
2402                 "sync-source",
2403                 _("External timecode source"),
2404                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
2405                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
2406                 );
2407
2408         add_option (_("Transport/Sync"), _sync_source);
2409
2410         _sync_framerate = new BoolOption (
2411                      "timecode-sync-frame-rate",
2412                      _("Match session video frame rate to external timecode"),
2413                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
2414                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
2415                      );
2416         Gtkmm2ext::UI::instance()->set_tip
2417                 (_sync_framerate->tip_widget(),
2418                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
2419                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
2420                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
2421                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
2422                                    "timecode standard and the session standard."), PROGRAM_NAME));
2423
2424         add_option (_("Transport/Sync"), _sync_framerate);
2425
2426         _sync_genlock = new BoolOption (
2427                 "timecode-source-is-synced",
2428                 _("Sync-lock timecode to clock (disable drift compensation)"),
2429                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
2430                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
2431                 );
2432         Gtkmm2ext::UI::instance()->set_tip
2433                 (_sync_genlock->tip_widget(),
2434                  string_compose (_("<b>When enabled</b> %1 will never varispeed when slaved to external timecode. "
2435                                    "Sync Lock indicates that the selected external timecode source shares clock-sync "
2436                                    "(Black &amp; Burst, Wordclock, etc) with the audio interface. "
2437                                    "This option disables drift compensation. The transport speed is fixed at 1.0. "
2438                                    "Vari-speed LTC will be ignored and cause drift."
2439                                    "\n\n"
2440                                    "<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
2441                                    "timecode sources shares clock sync."
2442                                   ), PROGRAM_NAME));
2443
2444
2445         add_option (_("Transport/Sync"), _sync_genlock);
2446
2447         _sync_source_2997 = new BoolOption (
2448                 "timecode-source-2997",
2449                 _("Lock to 29.9700 fps instead of 30000/1001"),
2450                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
2451                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
2452                 );
2453         Gtkmm2ext::UI::instance()->set_tip
2454                 (_sync_source_2997->tip_widget(),
2455                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
2456                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
2457                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
2458                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
2459                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
2460                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
2461                          ));
2462
2463         add_option (_("Transport/Sync"), _sync_source_2997);
2464
2465         add_option (_("Transport/Sync"), new OptionEditorHeading (S_("LTC Reader")));
2466
2467         _ltc_port = new ComboStringOption (
2468                 "ltc-source-port",
2469                 _("LTC incoming port"),
2470                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
2471                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
2472                 );
2473
2474         vector<string> physical_inputs;
2475         physical_inputs.push_back (_("None"));
2476         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
2477         _ltc_port->set_popdown_strings (physical_inputs);
2478
2479         populate_sync_options ();
2480         AudioEngine::instance()->Running.connect (engine_started_connection, MISSING_INVALIDATOR, boost::bind (&RCOptionEditor::populate_sync_options, this), gui_context());
2481
2482         add_option (_("Transport/Sync"), _ltc_port);
2483
2484         // TODO; rather disable this button than not compile it..
2485         add_option (_("Transport/Sync"), new OptionEditorHeading (S_("LTC Generator")));
2486
2487         add_option (_("Transport/Sync"),
2488                     new BoolOption (
2489                             "send-ltc",
2490                             _("Enable LTC generator"),
2491                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
2492                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
2493                             ));
2494
2495         _ltc_send_continuously = new BoolOption (
2496                             "ltc-send-continuously",
2497                             _("Send LTC while stopped"),
2498                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
2499                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
2500                             );
2501         Gtkmm2ext::UI::instance()->set_tip
2502                 (_ltc_send_continuously->tip_widget(),
2503                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
2504         add_option (_("Transport/Sync"), _ltc_send_continuously);
2505
2506         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
2507         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
2508         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
2509         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
2510
2511         Gtkmm2ext::UI::instance()->set_tip
2512                 (_ltc_volume_slider->tip_widget(),
2513                  _("Specify the Peak Volume of the generated LTC signal in dBFS. A good value is  0dBu ^= -18dBFS in an EBU calibrated system"));
2514
2515         add_option (_("Transport/Sync"), _ltc_volume_slider);
2516
2517         /* EDITOR */
2518
2519         add_option (_("Editor"), new OptionEditorHeading (_("Editor Settings")));
2520
2521         add_option (_("Editor"),
2522              new BoolOption (
2523                      "rubberbanding-snaps-to-grid",
2524                      _("Make rubberband selection rectangle snap to the grid"),
2525                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
2526                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
2527                      ));
2528
2529         bo = new BoolOption (
2530                      "name-new-markers",
2531                      _("Name new markers"),
2532                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
2533                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
2534                 );
2535         add_option (_("Editor"), bo);
2536         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."
2537                                                                 "\n\nYou can always rename markers by right-clicking on them"));
2538
2539         add_option (S_("Editor"),
2540              new BoolOption (
2541                      "draggable-playhead",
2542                      _("Allow dragging of playhead"),
2543                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead),
2544                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead)
2545                      ));
2546
2547 if (!Profile->get_mixbus()) {
2548         add_option (_("Editor"),
2549                     new BoolOption (
2550                             "show-zoom-tools",
2551                             _("Show zoom toolbar (if torn off)"),
2552                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_zoom_tools),
2553                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_zoom_tools)
2554                             ));
2555
2556         add_option (_("Editor"),
2557                     new BoolOption (
2558                             "use-mouse-position-as-zoom-focus-on-scroll",
2559                             _("Always use mouse cursor position as zoom focus when zooming using mouse scroll wheel"),
2560                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_mouse_position_as_zoom_focus_on_scroll),
2561                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_mouse_position_as_zoom_focus_on_scroll)
2562                             ));
2563 }  // !mixbus
2564
2565         add_option (_("Editor"),
2566                     new BoolOption (
2567                             "use-time-rulers-to-zoom-with-vertical-drag",
2568                             _("Use time rulers area to zoom when clicking and dragging vertically"),
2569                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_time_rulers_to_zoom_with_vertical_drag),
2570                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_time_rulers_to_zoom_with_vertical_drag)
2571                             ));
2572
2573         add_option (_("Editor"),
2574                     new BoolOption (
2575                             "use-double-click-to-zoom-to-selection",
2576                             _("Use double mouse click to zoom to selection"),
2577                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_double_click_to_zoom_to_selection),
2578                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_double_click_to_zoom_to_selection)
2579                             ));
2580
2581         add_option (_("Editor"),
2582                     new BoolOption (
2583                             "update-editor-during-summary-drag",
2584                             _("Update editor window during drags of the summary"),
2585                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
2586                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
2587                             ));
2588
2589         add_option (_("Editor"),
2590             new BoolOption (
2591                     "autoscroll-editor",
2592                     _("Auto-scroll editor window when dragging near its edges"),
2593                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
2594                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
2595                     ));
2596
2597         add_option (_("Editor"),
2598              new BoolComboOption (
2599                      "show-region-gain-envelopes",
2600                      _("Show gain envelopes in audio regions"),
2601                      _("in all modes"),
2602                      _("only in Draw and Internal Edit modes"),
2603                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
2604                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
2605                      ));
2606
2607         add_option (_("Editor"), new OptionEditorHeading (_("Editor Behavior")));
2608
2609         add_option (_("Editor"),
2610              new BoolOption (
2611                      "automation-follows-regions",
2612                      _("Move relevant automation when audio regions are moved"),
2613                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
2614                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
2615                      ));
2616
2617         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
2618                         "default-fade-shape",
2619                         _("Default fade shape"),
2620                         sigc::mem_fun (*_rc_config,
2621                                 &RCConfiguration::get_default_fade_shape),
2622                         sigc::mem_fun (*_rc_config,
2623                                 &RCConfiguration::set_default_fade_shape)
2624                         );
2625
2626         fadeshape->add (FadeLinear,
2627                         _("Linear (for highly correlated material)"));
2628         fadeshape->add (FadeConstantPower, _("Constant power"));
2629         fadeshape->add (FadeSymmetric, _("Symmetric"));
2630         fadeshape->add (FadeSlow, _("Slow"));
2631         fadeshape->add (FadeFast, _("Fast"));
2632
2633         add_option (_("Editor"), fadeshape);
2634
2635 #if 1
2636
2637         bco = new BoolComboOption (
2638                      "use-overlap-equivalency",
2639                      _("Regions in edit groups are edited together"),
2640                      _("whenever they overlap in time"),
2641                      _("only if they have identical length and position"),
2642                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
2643                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
2644                      );
2645
2646         add_option (_("Editor"), bco);
2647
2648 #endif
2649         ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
2650                 "layer-model",
2651                 _("Layering model"),
2652                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
2653                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
2654                 );
2655
2656         lm->add (LaterHigher, _("later is higher"));
2657         lm->add (Manual, _("manual layering"));
2658         add_option (_("Editor"), lm);
2659
2660         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
2661                     "region-selection-after-split",
2662                     _("After splitting selected regions, select"),
2663                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
2664                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
2665
2666         // TODO: decide which of these modes are really useful
2667         rsas->add(None, _("no regions"));
2668         // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
2669         // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
2670         rsas->add(NewlyCreatedBoth, _("newly-created regions"));
2671         // rsas->add(Existing, _("unmodified regions in the existing selection"));
2672         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
2673         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
2674         rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
2675
2676         add_option (_("Editor"), rsas);
2677
2678         add_option (_("Editor/Waveforms"), new OptionEditorHeading (_("Waveforms")));
2679
2680 if (!Profile->get_mixbus()) {
2681         add_option (_("Editor/Waveforms"),
2682              new BoolOption (
2683                      "show-waveforms",
2684                      _("Show waveforms in regions"),
2685                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
2686                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
2687                      ));
2688 }  // !mixbus
2689
2690         add_option (_("Editor/Waveforms"),
2691              new BoolOption (
2692                      "show-waveforms-while-recording",
2693                      _("Show waveforms for audio while it is being recorded"),
2694                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
2695                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
2696                      ));
2697
2698         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
2699                 "waveform-scale",
2700                 _("Waveform scale"),
2701                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_scale),
2702                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_scale)
2703                 );
2704
2705         wfs->add (Linear, _("linear"));
2706         wfs->add (Logarithmic, _("logarithmic"));
2707
2708         add_option (_("Editor/Waveforms"), wfs);
2709
2710         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
2711                 "waveform-shape",
2712                 _("Waveform shape"),
2713                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_shape),
2714                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_shape)
2715                 );
2716
2717         wfsh->add (Traditional, _("traditional"));
2718         wfsh->add (Rectified, _("rectified"));
2719
2720         add_option (_("Editor/Waveforms"), wfsh);
2721
2722         add_option (_("Editor/Waveforms"), new ClipLevelOptions ());
2723
2724
2725         /* AUDIO */
2726
2727         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
2728
2729         add_option (_("Audio"), new BufferingOptions (_rc_config));
2730
2731         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
2732
2733         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
2734                 "monitoring-model",
2735                 _("Record monitoring handled by"),
2736                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
2737                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
2738                 );
2739
2740         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
2741                 mm->add (HardwareMonitoring, _("via Audio Driver"));
2742         }
2743
2744         string prog (PROGRAM_NAME);
2745         boost::algorithm::to_lower (prog);
2746         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
2747         mm->add (ExternalMonitoring, _("audio hardware"));
2748
2749         add_option (_("Audio"), mm);
2750
2751         add_option (_("Audio"),
2752              new BoolOption (
2753                      "tape-machine-mode",
2754                      _("Tape machine mode"),
2755                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
2756                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
2757                      ));
2758
2759         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
2760 if (!Profile->get_mixbus()) {
2761
2762         add_option (_("Audio"),
2763                     new BoolOption (
2764                             "auto-connect-standard-busses",
2765                             _("Auto-connect master/monitor busses"),
2766                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
2767                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
2768                             ));
2769
2770         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
2771                 "input-auto-connect",
2772                 _("Connect track inputs"),
2773                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
2774                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
2775                 );
2776
2777         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
2778         iac->add (ManualConnect, _("manually"));
2779
2780         add_option (_("Audio"), iac);
2781
2782         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
2783                 "output-auto-connect",
2784                 _("Connect track and bus outputs"),
2785                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
2786                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
2787                 );
2788
2789         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
2790         oac->add (AutoConnectMaster, _("automatically to master bus"));
2791         oac->add (ManualConnect, _("manually"));
2792
2793         add_option (_("Audio"), oac);
2794
2795         bo = new BoolOption (
2796                         "strict-io",
2797                         _("Use 'Strict-I/O' for new tracks or Busses"),
2798                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_strict_io),
2799                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_strict_io)
2800                         );
2801
2802         add_option (_("Audio"), bo);
2803         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2804                         _("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."));
2805
2806 }  // !mixbus
2807
2808         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
2809
2810         add_option (_("Audio"),
2811              new BoolOption (
2812                      "denormal-protection",
2813                      _("Use DC bias to protect against denormals"),
2814                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
2815                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
2816                      ));
2817
2818         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
2819                 "denormal-model",
2820                 _("Processor handling"),
2821                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
2822                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
2823                 );
2824
2825         int dmsize = 1;
2826         dm->add (DenormalNone, _("no processor handling"));
2827
2828         FPU* fpu = FPU::instance();
2829
2830         if (fpu->has_flush_to_zero()) {
2831                 ++dmsize;
2832                 dm->add (DenormalFTZ, _("use FlushToZero"));
2833         } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
2834                 _rc_config->set_denormal_model(DenormalNone);
2835         }
2836
2837         if (fpu->has_denormals_are_zero()) {
2838                 ++dmsize;
2839                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
2840         } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
2841                 _rc_config->set_denormal_model(DenormalNone);
2842         }
2843
2844         if (fpu->has_flush_to_zero() && fpu->has_denormals_are_zero()) {
2845                 ++dmsize;
2846                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
2847         } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
2848                 _rc_config->set_denormal_model(DenormalNone);
2849         }
2850
2851         if (dmsize == 1) {
2852                 dm->set_sensitive(false);
2853         }
2854
2855         add_option (_("Audio"), dm);
2856
2857         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
2858
2859         add_option (_("Audio"),
2860              new BoolOption (
2861                      "auto-analyse-audio",
2862                      _("Enable automatic analysis of audio"),
2863                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
2864                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
2865                      ));
2866
2867         add_option (_("Audio"),
2868              new BoolOption (
2869                      "replicate-missing-region-channels",
2870                      _("Replicate missing region channels"),
2871                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
2872                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
2873                      ));
2874
2875         /* SOLO AND MUTE */
2876
2877         add_option (_("Solo & mute"), new OptionEditorHeading (_("Solo")));
2878
2879         _solo_control_is_listen_control = new BoolOption (
2880                 "solo-control-is-listen-control",
2881                 _("Solo controls are Listen controls"),
2882                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
2883                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
2884                 );
2885
2886         add_option (_("Solo & mute"), _solo_control_is_listen_control);
2887
2888         add_option (_("Solo & mute"),
2889              new BoolOption (
2890                      "exclusive-solo",
2891                      _("Exclusive solo"),
2892                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2893                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2894                      ));
2895
2896         add_option (_("Solo & mute"),
2897              new BoolOption (
2898                      "show-solo-mutes",
2899                      _("Show solo muting"),
2900                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2901                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2902                      ));
2903
2904         add_option (_("Solo & mute"),
2905              new BoolOption (
2906                      "solo-mute-override",
2907                      _("Soloing overrides muting"),
2908                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2909                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2910                      ));
2911
2912         add_option (_("Solo & mute"),
2913              new FaderOption (
2914                      "solo-mute-gain",
2915                      _("Solo-in-place mute cut (dB)"),
2916                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
2917                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
2918                      ));
2919
2920         _listen_position = new ComboOption<ListenPosition> (
2921                 "listen-position",
2922                 _("Listen Position"),
2923                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
2924                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
2925                 );
2926
2927         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
2928         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
2929
2930         add_option (_("Solo & mute"), _listen_position);
2931
2932         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
2933                 "pfl-position",
2934                 _("PFL signals come from"),
2935                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
2936                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
2937                 );
2938
2939         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2940         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2941
2942         add_option (_("Solo & mute"), pp);
2943
2944         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2945                 "afl-position",
2946                 _("AFL signals come from"),
2947                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2948                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2949                 );
2950
2951         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2952         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2953
2954         add_option (_("Solo & mute"), pa);
2955
2956         add_option (_("Solo & mute"), new OptionEditorHeading (_("Default track / bus muting options")));
2957
2958         add_option (_("Solo & mute"),
2959              new BoolOption (
2960                      "mute-affects-pre-fader",
2961                      _("Mute affects pre-fader sends"),
2962                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2963                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2964                      ));
2965
2966         add_option (_("Solo & mute"),
2967              new BoolOption (
2968                      "mute-affects-post-fader",
2969                      _("Mute affects post-fader sends"),
2970                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2971                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2972                      ));
2973
2974         add_option (_("Solo & mute"),
2975              new BoolOption (
2976                      "mute-affects-control-outs",
2977                      _("Mute affects control outputs"),
2978                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2979                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2980                      ));
2981
2982         add_option (_("Solo & mute"),
2983              new BoolOption (
2984                      "mute-affects-main-outs",
2985                      _("Mute affects main outputs"),
2986                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2987                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2988                      ));
2989
2990
2991 if (!ARDOUR::Profile->get_mixbus()) {
2992         add_option (_("Solo & mute"), new OptionEditorHeading (_("Send Routing")));
2993         add_option (_("Solo & mute"),
2994              new BoolOption (
2995                      "link-send-and-route-panner",
2996                      _("Link panners of Aux and External Sends with main panner by default"),
2997                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2998                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2999                      ));
3000 }
3001
3002         add_option (_("MIDI"), new OptionEditorHeading (_("MIDI Preferences")));
3003
3004         add_option (_("MIDI"),
3005                     new SpinOption<float> (
3006                             "midi-readahead",
3007                             _("MIDI read-ahead time (seconds)"),
3008                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
3009                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
3010                             0.1, 10, 0.1, 1,
3011                             "", 1.0, 1
3012                             ));
3013
3014         add_option (_("MIDI"),
3015              new SpinOption<int32_t> (
3016                      "initial-program-change",
3017                      _("Initial program change"),
3018                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
3019                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
3020                      -1, 65536, 1, 10
3021                      ));
3022
3023         add_option (_("MIDI"),
3024                     new BoolOption (
3025                             "display-first-midi-bank-as-zero",
3026                             _("Display first MIDI bank/program as 0"),
3027                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
3028                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
3029                             ));
3030
3031         add_option (_("MIDI"),
3032              new BoolOption (
3033                      "never-display-periodic-midi",
3034                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
3035                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
3036                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
3037                      ));
3038
3039         add_option (_("MIDI"),
3040              new BoolOption (
3041                      "sound-midi-notes",
3042                      _("Sound MIDI notes as they are selected in the editor"),
3043                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
3044                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
3045                      ));
3046
3047         add_option (_("MIDI"),
3048                     new BoolOption (
3049                             "midi-feedback",
3050                             _("Send MIDI control feedback"),
3051                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
3052                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
3053                             ));
3054
3055         add_option (_("MIDI/Ports"), new OptionEditorHeading (_("MIDI Port Options")));
3056
3057         add_option (_("MIDI/Ports"),
3058                     new BoolOption (
3059                             "get-midi-input-follows-selection",
3060                             _("MIDI input follows MIDI track selection"),
3061                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_input_follows_selection),
3062                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_input_follows_selection)
3063                             ));
3064
3065         add_option (_("MIDI/Ports"), new MidiPortOptions ());
3066
3067         add_option (_("MIDI/Sync"), new OptionEditorHeading (_("MIDI Clock")));
3068
3069         add_option (_("MIDI/Sync"),
3070                     new BoolOption (
3071                             "send-midi-clock",
3072                             _("Send MIDI Clock"),
3073                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
3074                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
3075                             ));
3076
3077         add_option (_("MIDI/Sync"), new OptionEditorHeading (_("MIDI Time Code (MTC)")));
3078
3079         add_option (_("MIDI/Sync"),
3080                     new BoolOption (
3081                             "send-mtc",
3082                             _("Send MIDI Time Code"),
3083                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
3084                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
3085                             ));
3086
3087         add_option (_("MIDI/Sync"),
3088                     new SpinOption<int> (
3089                             "mtc-qf-speed-tolerance",
3090                             _("Percentage either side of normal transport speed to transmit MTC"),
3091                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
3092                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
3093                             0, 20, 1, 5
3094                             ));
3095
3096         add_option (_("MIDI/Sync"), new OptionEditorHeading (_("Midi Machine Control (MMC)")));
3097
3098         add_option (_("MIDI/Sync"),
3099                     new BoolOption (
3100                             "mmc-control",
3101                             _("Obey MIDI Machine Control commands"),
3102                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
3103                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
3104                             ));
3105
3106         add_option (_("MIDI/Sync"),
3107                     new BoolOption (
3108                             "send-mmc",
3109                             _("Send MIDI Machine Control commands"),
3110                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
3111                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
3112                             ));
3113
3114         add_option (_("MIDI/Sync"),
3115              new SpinOption<uint8_t> (
3116                      "mmc-receive-device-id",
3117                      _("Inbound MMC device ID"),
3118                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
3119                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
3120                      0, 128, 1, 10
3121                      ));
3122
3123         add_option (_("MIDI/Sync"),
3124              new SpinOption<uint8_t> (
3125                      "mmc-send-device-id",
3126                      _("Outbound MMC device ID"),
3127                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
3128                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
3129                      0, 128, 1, 10
3130                      ));
3131
3132         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
3133
3134         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
3135                 "midi-audition-synth-uri",
3136                 _("Midi Audition Synth (LV2)"),
3137                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
3138                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
3139                 );
3140
3141         audition_synth->add(X_(""), _("None"));
3142         PluginInfoList all_plugs;
3143         PluginManager& manager (PluginManager::instance());
3144 #ifdef LV2_SUPPORT
3145         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
3146
3147         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
3148                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
3149                 if (!(*i)->is_instrument()) continue;
3150                 if ((*i)->type != ARDOUR::LV2) continue;
3151                 if ((*i)->name.length() > 46) {
3152                         audition_synth->add((*i)->unique_id, (*i)->name.substr (0, 44) + "...");
3153                 } else {
3154                         audition_synth->add((*i)->unique_id, (*i)->name);
3155                 }
3156         }
3157 #endif
3158
3159         add_option (_("MIDI"), audition_synth);
3160
3161         /* Control Surfaces */
3162
3163         add_option (_("Control Surfaces"), new ControlSurfacesOptions ());
3164
3165         /* VIDEO Timeline */
3166         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
3167
3168 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
3169         add_option (_("Plugins"), new OptionEditorHeading (_("Scan/Discover")));
3170         add_option (_("Plugins"),
3171                         new RcActionButton (_("Scan for Plugins"),
3172                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3173
3174 #endif
3175
3176         add_option (_("Plugins"), new OptionEditorHeading (_("General")));
3177
3178 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
3179         bo = new BoolOption (
3180                         "show-plugin-scan-window",
3181                         _("Always Display Plugin Scan Progress"),
3182                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_plugin_scan_window),
3183                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_plugin_scan_window)
3184                         );
3185         add_option (_("Plugins"), bo);
3186         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3187                         _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
3188 #endif
3189
3190         bo = new BoolOption (
3191                 "plugins-stop-with-transport",
3192                 _("Silence plugins when the transport is stopped"),
3193                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
3194                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
3195                 );
3196         add_option (_("Plugins"), bo);
3197         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3198                                             _("<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."));
3199
3200         bo = new BoolOption (
3201                 "new-plugins-active",
3202                         _("Make new plugins active"),
3203                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
3204                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
3205                         );
3206         add_option (_("Plugins"), bo);
3207         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3208                                             _("<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"));
3209
3210 #if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT)
3211         add_option (_("Plugins/VST"), new OptionEditorHeading (_("VST")));
3212         add_option (_("Plugins/VST"),
3213                         new RcActionButton (_("Scan for Plugins"),
3214                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3215
3216 #if (defined AUDIOUNIT_SUPPORT && defined MACVST_SUPPORT)
3217         bo = new BoolOption (
3218                         "",
3219                         _("Enable Mac VST support (requires restart or re-scan)"),
3220                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_macvst),
3221                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_macvst)
3222                         );
3223         add_option (_("Plugins/VST"), bo);
3224 #endif
3225
3226         bo = new BoolOption (
3227                         "discover-vst-on-start",
3228                         _("Scan for [new] VST Plugins on Application Start"),
3229                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_vst_on_start),
3230                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_vst_on_start)
3231                         );
3232         add_option (_("Plugins/VST"), bo);
3233         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3234                                             _("<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"));
3235
3236 #ifdef WINDOWS_VST_SUPPORT
3237         // currently verbose logging is only implemented for Windows VST.
3238         bo = new BoolOption (
3239                         "verbose-plugin-scan",
3240                         _("Verbose Plugin Scan"),
3241                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_verbose_plugin_scan),
3242                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_verbose_plugin_scan)
3243                         );
3244         add_option (_("Plugins/VST"), bo);
3245         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3246                                             _("<b>When enabled</b> additional information for every plugin is added to the Log Window."));
3247 #endif
3248
3249         add_option (_("Plugins/VST"), new VstTimeOutSliderOption (_rc_config));
3250
3251         add_option (_("Plugins/VST"),
3252                         new RcActionButton (_("Clear"),
3253                                 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_cache),
3254                                 _("VST Cache:")));
3255
3256         add_option (_("Plugins/VST"),
3257                         new RcActionButton (_("Clear"),
3258                                 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_blacklist),
3259                                 _("VST Blacklist:")));
3260 #endif
3261
3262 #ifdef LXVST_SUPPORT
3263         add_option (_("Plugins/VST"),
3264                         new RcActionButton (_("Edit"),
3265                                 sigc::mem_fun (*this, &RCOptionEditor::edit_lxvst_path),
3266                         _("Linux VST Path:")));
3267
3268         add_option (_("Plugins/VST"),
3269                         new RcConfigDisplay (
3270                                 "plugin-path-lxvst",
3271                                 _("Path:"),
3272                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_lxvst),
3273                                 0));
3274 #endif
3275
3276 #ifdef WINDOWS_VST_SUPPORT
3277         add_option (_("Plugins/VST"),
3278                         new RcActionButton (_("Edit"),
3279                                 sigc::mem_fun (*this, &RCOptionEditor::edit_vst_path),
3280                         _("Windows VST Path:")));
3281         add_option (_("Plugins"),
3282                         new RcConfigDisplay (
3283                                 "plugin-path-vst",
3284                                 _("Path:"),
3285                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_vst),
3286                                 ';'));
3287 #endif
3288
3289 #ifdef AUDIOUNIT_SUPPORT
3290
3291         add_option (_("Plugins/Audio Unit"), new OptionEditorHeading (_("Audio Unit")));
3292         add_option (_("Plugins/Audio Unit"),
3293                         new RcActionButton (_("Scan for Plugins"),
3294                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3295
3296         bo = new BoolOption (
3297                         "discover-audio-units",
3298                         _("Scan for [new] AudioUnit Plugins on Application Start"),
3299                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_audio_units),
3300                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_audio_units)
3301                         );
3302         add_option (_("Plugins/Audio Unit"), bo);
3303         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3304                                             _("<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."));
3305
3306         add_option (_("Plugins/Audio Unit"),
3307                         new RcActionButton (_("Clear"),
3308                                 sigc::mem_fun (*this, &RCOptionEditor::clear_au_cache),
3309                                 _("AU Cache:")));
3310
3311         add_option (_("Plugins/Audio Unit"),
3312                         new RcActionButton (_("Clear"),
3313                                 sigc::mem_fun (*this, &RCOptionEditor::clear_au_blacklist),
3314                                 _("AU Blacklist:")));
3315 #endif
3316
3317 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2)
3318         add_option (_("Plugins"), new OptionEditorHeading (_("Plugin GUI")));
3319         add_option (_("Plugins"),
3320              new BoolOption (
3321                      "open-gui-after-adding-plugin",
3322                      _("Automatically open the plugin GUI when adding a new plugin"),
3323                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_open_gui_after_adding_plugin),
3324                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_open_gui_after_adding_plugin)
3325                      ));
3326
3327 #if (defined LV2_SUPPORT && defined LV2_EXTENDED)
3328         add_option (_("Plugins"),
3329              new BoolOption (
3330                      "show-inline-display-by-default",
3331                      _("Show Plugin Inline Display on Mixerstrip by default"),
3332                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_inline_display_by_default),
3333                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_inline_display_by_default)
3334                      ));
3335
3336         _plugin_prefer_inline = new BoolOption (
3337                         "prefer-inline-over-gui",
3338                         _("Don't automatically open the plugin GUI when the plugin has an inline display mode"),
3339                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_prefer_inline_over_gui),
3340                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_prefer_inline_over_gui)
3341                         );
3342         add_option (_("Plugins"), _plugin_prefer_inline);
3343 #endif
3344
3345         add_option (_("Plugins"), new OptionEditorHeading (_("Instrument")));
3346
3347         bo = new BoolOption (
3348                         "ask-replace-instrument",
3349                         _("Ask to replace existing instrument plugin"),
3350                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_ask_replace_instrument),
3351                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_ask_replace_instrument)
3352                         );
3353         add_option (_("Plugins"), bo);
3354
3355         bo = new BoolOption (
3356                         "ask-setup_instrument",
3357                         _("Interactively configure instrument plugins on insert"),
3358                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_ask_setup_instrument),
3359                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_ask_setup_instrument)
3360                         );
3361         add_option (_("Plugins"), bo);
3362         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3363                         _("<b>When enabled</b> show a dialog to select instrument channel configuration before adding a multichannel plugin."));
3364
3365 #endif
3366
3367         /* INTERFACE */
3368 #if (defined OPTIONAL_CAIRO_IMAGE_SURFACE || defined CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE)
3369         add_option (S_("Preferences|GUI"), new OptionEditorHeading (_("Graphics Acceleration")));
3370 #endif
3371
3372 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
3373         BoolOption* bgc = new BoolOption (
3374                 "cairo-image-surface",
3375                 _("Disable Graphics Hardware Acceleration (requires restart)"),
3376                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_cairo_image_surface),
3377                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_cairo_image_surface)
3378                 );
3379
3380         Gtkmm2ext::UI::instance()->set_tip (bgc->tip_widget(), string_compose (
3381                                 _("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));
3382         add_option (S_("Preferences|GUI"), bgc);
3383 #endif
3384
3385 #ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
3386         BoolOption* bgo = new BoolOption (
3387                 "buggy-gradients",
3388                 _("Possibly improve slow graphical performance (requires restart)"),
3389                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_buggy_gradients),
3390                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_buggy_gradients)
3391                 );
3392
3393         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));
3394         add_option (S_("Preferences|GUI"), bgo);
3395 #endif
3396
3397         add_option (S_("Preferences|GUI"), new OptionEditorHeading (_("Graphical User Interface")));
3398         add_option (S_("Preferences|GUI"),
3399              new BoolOption (
3400                      "use-wm-visibility",
3401                      _("Use Window Manager/Desktop visibility information"),
3402                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_wm_visibility),
3403                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_wm_visibility)
3404                      ));
3405
3406         add_option (S_("Preferences|GUI"),
3407              new BoolOption (
3408                      "widget-prelight",
3409                      _("Graphically indicate mouse pointer hovering over various widgets"),
3410                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_widget_prelight),
3411                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_widget_prelight)
3412                      ));
3413
3414         add_option (S_("Preferences|GUI"),
3415              new BoolOption (
3416                      "use-tooltips",
3417                      _("Show tooltips if mouse hovers over a control"),
3418                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_tooltips),
3419                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_tooltips)
3420                      ));
3421
3422         add_option (S_("Preferences|GUI"),
3423              new BoolOption (
3424                      "show-name-highlight",
3425                      _("Use name highlight bars in region displays (requires a restart)"),
3426                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_name_highlight),
3427                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_name_highlight)
3428                      ));
3429
3430         add_option (S_("Preferences|GUI"),
3431                     new BoolOption (
3432                             "super-rapid-clock-update",
3433                             _("Update transport clock display at FPS instead of every 100ms"),
3434                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
3435                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
3436                             ));
3437
3438
3439 #ifndef __APPLE__
3440         /* font scaling does nothing with GDK/Quartz */
3441         add_option (S_("Preferences|GUI"), new FontScalingOptions ());
3442 #endif
3443
3444         /* Image cache size */
3445
3446         Gtk::Adjustment *ics = manage (new Gtk::Adjustment(0, 1, 1024, 10)); /* 1 MB to 1GB in steps of 10MB */
3447         HSliderOption *sics = new HSliderOption("waveform-cache-size",
3448                                                 _("Waveform image cache size (megabytes)"),
3449                                                 ics,
3450                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_cache_size),
3451                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_cache_size)
3452                         );
3453         sics->scale().set_digits (0);
3454         Gtkmm2ext::UI::instance()->set_tip
3455                 (sics->tip_widget(),
3456                  _("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
3457         add_option (S_("Preferences|GUI"), sics);
3458
3459 if (!ARDOUR::Profile->get_mixbus()) {
3460         /* Lock GUI timeout */
3461
3462         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
3463         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
3464                                                 _("Lock timeout (seconds)"),
3465                                                 lts,
3466                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_lock_gui_after_seconds),
3467                                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_lock_gui_after_seconds)
3468                         );
3469         slts->scale().set_digits (0);
3470         Gtkmm2ext::UI::instance()->set_tip
3471                 (slts->tip_widget(),
3472                  _("Lock GUI after this many idle seconds (zero to never lock)"));
3473         add_option (S_("Preferences|GUI"), slts);
3474 } // !mixbus
3475
3476         /* The names of these controls must be the same as those given in MixerStrip
3477            for the actual widgets being controlled.
3478         */
3479         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
3480         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
3481         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
3482         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
3483         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
3484         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
3485         _mixer_strip_visibility.add (0, X_("VCA"), _("VCA Assigns"));
3486
3487         add_option (
3488                 S_("Preferences|GUI"),
3489                 new VisibilityOption (
3490                         _("Mixer Strip"),
3491                         &_mixer_strip_visibility,
3492                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_mixer_strip_visibility),
3493                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_mixer_strip_visibility)
3494                         )
3495                 );
3496
3497         add_option (S_("Preferences|GUI"),
3498              new BoolOption (
3499                      "default-narrow_ms",
3500                      _("Use narrow strips in the mixer by default"),
3501                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_default_narrow_ms),
3502                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
3503                      ));
3504
3505 #ifdef ENABLE_NLS
3506         OptionEditorHeading* i18n_head = new OptionEditorHeading (_("Internationalization"));
3507         i18n_head->set_note (string_compose (_("These settings will only take effect after %1 is restarted (if available for your language preferences)."), PROGRAM_NAME));
3508
3509         add_option (_("GUI/Translation"), i18n_head);
3510
3511         bo = new BoolOption (
3512                         "enable-translation",
3513                         _("Use translations"),
3514                         sigc::ptr_fun (ARDOUR::translations_are_enabled),
3515                         sigc::ptr_fun (ARDOUR::set_translations_enabled)
3516                         );
3517
3518         add_option (_("GUI/Translation"), bo);
3519
3520         _l10n = new ComboOption<ARDOUR::LocaleMode> (
3521                 "locale-mode",
3522                 _("Localization"),
3523                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_locale_mode),
3524                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_locale_mode)
3525                 );
3526
3527         _l10n->add (ARDOUR::SET_LC_ALL, _("Set complete locale"));
3528         _l10n->add (ARDOUR::SET_LC_MESSAGES, _("Enable only message translation"));
3529         _l10n->add (ARDOUR::SET_LC_MESSAGES_AND_LC_NUMERIC, _("Translate messages and format numeric format"));
3530         _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."));
3531
3532         add_option (_("GUI/Translation"), _l10n);
3533         parameter_changed ("enable-translation");
3534 #endif // ENABLE_NLS
3535
3536         add_option (_("GUI/Keyboard"), new OptionEditorHeading (_("Keyboard")));
3537         add_option (_("GUI/Keyboard"), new KeyboardOptions);
3538
3539         add_option (_("GUI/Toolbar"), new OptionEditorHeading (_("Main Transport Items")));
3540
3541         add_option (_("GUI/Toolbar"),
3542              new BoolOption (
3543                      "show-toolbar-selclock",
3544                      _("Display Selection Clock in the Toolbar"),
3545                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_selclock),
3546                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_selclock)
3547                      ));
3548
3549         if (!ARDOUR::Profile->get_small_screen()) {
3550                 add_option (_("GUI/Toolbar"),
3551                                 new BoolOption (
3552                                         "show-secondary-clock",
3553                                         _("Display Secondary Clock in the Toolbar"),
3554                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_secondary_clock),
3555                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_secondary_clock)
3556                                         ));
3557         }
3558
3559         add_option (_("GUI/Toolbar"),
3560              new BoolOption (
3561                      "show-mini-timeline",
3562                      _("Display Navigation Timeline in the Toolbar"),
3563                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_mini_timeline),
3564                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_mini_timeline)
3565                      ));
3566
3567         add_option (_("GUI/Toolbar"),
3568              new BoolOption (
3569                      "show-editor-meter",
3570                      _("Display Master Level Meter in the Toolbar"),
3571                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
3572                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
3573                      ));
3574
3575         add_option (_("GUI/Toolbar"),
3576                         new ColumVisibilityOption (
3577                                 "action-table-columns", _("Action Script Button Visibility"), 4,
3578                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_action_table_columns),
3579                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_action_table_columns)
3580                                 )
3581                         );
3582
3583
3584         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
3585
3586         ComboOption<float>* mht = new ComboOption<float> (
3587                 "meter-hold",
3588                 _("Peak hold time"),
3589                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_hold),
3590                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_hold)
3591                 );
3592
3593         mht->add (MeterHoldOff, _("off"));
3594         mht->add (MeterHoldShort, _("short"));
3595         mht->add (MeterHoldMedium, _("medium"));
3596         mht->add (MeterHoldLong, _("long"));
3597
3598         add_option (S_("Preferences|Metering"), mht);
3599
3600         ComboOption<float>* mfo = new ComboOption<float> (
3601                 "meter-falloff",
3602                 _("DPM fall-off"),
3603                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
3604                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
3605                 );
3606
3607         mfo->add (METER_FALLOFF_OFF,      _("off"));
3608         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
3609         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
3610         mfo->add (METER_FALLOFF_SLOWISH,  _("moderate [12.0dB/sec] (DIN)"));
3611         mfo->add (METER_FALLOFF_MODERATE, _("medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
3612         mfo->add (METER_FALLOFF_MEDIUM,   _("fast [20dB/sec]"));
3613         mfo->add (METER_FALLOFF_FAST,     _("very fast [32dB/sec]"));
3614
3615         add_option (S_("Preferences|Metering"), mfo);
3616
3617         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
3618                 "meter-line-up-level",
3619                 _("Meter line-up level; 0dBu"),
3620                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_level),
3621                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_level)
3622                 );
3623
3624         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
3625         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
3626         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
3627         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3628
3629         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."));
3630
3631         add_option (S_("Preferences|Metering"), mlu);
3632
3633         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
3634                 "meter-line-up-din",
3635                 _("IEC1/DIN Meter line-up level; 0dBu"),
3636                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_din),
3637                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_din)
3638                 );
3639
3640         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
3641         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
3642         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
3643         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3644
3645         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
3646
3647         add_option (S_("Preferences|Metering"), mld);
3648
3649         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
3650                 "meter-vu-standard",
3651                 _("VU Meter standard"),
3652                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_vu_standard),
3653                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_vu_standard)
3654                 );
3655
3656         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
3657         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
3658         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
3659         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
3660
3661         add_option (S_("Preferences|Metering"), mvu);
3662
3663         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
3664         HSliderOption *mpks = new HSliderOption("meter-peak",
3665                         _("Peak threshold [dBFS]"),
3666                         mpk,
3667                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_peak),
3668                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_peak)
3669                         );
3670
3671
3672         ComboOption<MeterType>* mtm = new ComboOption<MeterType> (
3673                 "meter-type-master",
3674                 _("Default Meter Type for Master Bus"),
3675                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_master),
3676                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_master)
3677                 );
3678         mtm->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3679         mtm->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3680         mtm->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3681         mtm->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3682         mtm->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3683         mtm->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3684         mtm->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3685         mtm->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3686
3687         add_option (S_("Preferences|Metering"), mtm);
3688
3689
3690         ComboOption<MeterType>* mtb = new ComboOption<MeterType> (
3691                 "meter-type-bus",
3692                 _("Default Meter Type for Busses"),
3693                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_bus),
3694                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_bus)
3695                 );
3696         mtb->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3697         mtb->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3698         mtb->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3699         mtb->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3700         mtb->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3701         mtb->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3702         mtb->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3703         mtb->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3704
3705         add_option (S_("Preferences|Metering"), mtb);
3706
3707         ComboOption<MeterType>* mtt = new ComboOption<MeterType> (
3708                 "meter-type-track",
3709                 _("Default Meter Type for Tracks"),
3710                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_track),
3711                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_track)
3712                 );
3713         mtt->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3714         mtt->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
3715
3716         add_option (S_("Preferences|Metering"), mtt);
3717
3718
3719         Gtkmm2ext::UI::instance()->set_tip
3720                 (mpks->tip_widget(),
3721                  _("Specify the audio signal level in dBFS at and above which the meter-peak indicator will flash red."));
3722
3723         add_option (S_("Preferences|Metering"), mpks);
3724
3725         add_option (S_("Preferences|Metering"),
3726              new BoolOption (
3727                      "meter-style-led",
3728                      _("LED meter style"),
3729                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_style_led),
3730                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_style_led)
3731                      ));
3732
3733         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Editor Meters")));
3734
3735         add_option (S_("Preferences|Metering"),
3736              new BoolOption (
3737                      "show-track-meters",
3738                      _("Show meters on tracks in the editor"),
3739                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
3740                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_track_meters)
3741                      ));
3742
3743         add_option (S_("Preferences|Metering"),
3744              new BoolOption (
3745                      "editor-stereo-only-meters",
3746                      _("Show at most stereo meters in the track-header"),
3747                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_editor_stereo_only_meters),
3748                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_editor_stereo_only_meters)
3749                      ));
3750
3751         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Post Export Analysis")));
3752
3753         add_option (S_("Preferences|Metering"),
3754              new BoolOption (
3755                      "save-export-analysis-image",
3756                      _("Save loudness analysis as image file"),
3757                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_save_export_analysis_image),
3758                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_save_export_analysis_image)
3759                      ));
3760
3761         /* and now the theme manager */
3762
3763         ThemeManager* tm = manage (new ThemeManager);
3764         add_option (_("Theme"), new OptionEditorHeading (_("Theme")));
3765         add_page (_("Theme"), *tm);
3766
3767         add_option (_("Theme/Colors"), new ColorThemeManager);
3768
3769         Widget::show_all ();
3770
3771         //trigger some parameter-changed messages which affect widget-visibility or -sensitivity
3772         parameter_changed ("send-ltc");
3773         parameter_changed ("sync-source");
3774         parameter_changed ("use-monitor-bus");
3775         parameter_changed ("open-gui-after-adding-plugin");
3776
3777         XMLNode* node = ARDOUR_UI::instance()->preferences_settings();
3778         if (node) {
3779                 /* gcc4 complains about ambiguity with Gtk::Widget::set_state
3780                    (Gtk::StateType) here !!!
3781                 */
3782                 Tabbable::set_state (*node, Stateful::loading_state_version);
3783         }
3784 }
3785
3786 void
3787 RCOptionEditor::parameter_changed (string const & p)
3788 {
3789         OptionEditor::parameter_changed (p);
3790
3791         if (p == "use-monitor-bus") {
3792                 bool const s = Config->get_use_monitor_bus ();
3793                 if (!s) {
3794                         /* we can't use this if we don't have a monitor bus */
3795                         Config->set_solo_control_is_listen_control (false);
3796                 }
3797                 _solo_control_is_listen_control->set_sensitive (s);
3798                 _listen_position->set_sensitive (s);
3799         } else if (p == "sync-source") {
3800                 _sync_source->set_sensitive (true);
3801                 if (_session) {
3802                         _sync_source->set_sensitive (!_session->config.get_external_sync());
3803                 }
3804                 switch(Config->get_sync_source()) {
3805                 case ARDOUR::MTC:
3806                 case ARDOUR::LTC:
3807                         _sync_genlock->set_sensitive (true);
3808                         _sync_framerate->set_sensitive (true);
3809                         _sync_source_2997->set_sensitive (true);
3810                         break;
3811                 default:
3812                         _sync_genlock->set_sensitive (false);
3813                         _sync_framerate->set_sensitive (false);
3814                         _sync_source_2997->set_sensitive (false);
3815                         break;
3816                 }
3817         } else if (p == "send-ltc") {
3818                 bool const s = Config->get_send_ltc ();
3819                 _ltc_send_continuously->set_sensitive (s);
3820                 _ltc_volume_slider->set_sensitive (s);
3821         } else if (p == "open-gui-after-adding-plugin" || p == "show-inline-display-by-default") {
3822 #if (defined LV2_SUPPORT && defined LV2_EXTENDED)
3823                 _plugin_prefer_inline->set_sensitive (UIConfiguration::instance().get_open_gui_after_adding_plugin() && UIConfiguration::instance().get_show_inline_display_by_default());
3824 #endif
3825 #ifdef ENABLE_NLS
3826         } else if (p == "enable-translation") {
3827                 _l10n->set_sensitive (ARDOUR::translations_are_enabled ());
3828 #endif
3829         }
3830 }
3831
3832 void RCOptionEditor::ltc_generator_volume_changed () {
3833         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
3834 }
3835
3836 void RCOptionEditor::plugin_scan_refresh () {
3837         PluginManager::instance().refresh();
3838 }
3839
3840 void RCOptionEditor::clear_vst_cache () {
3841         PluginManager::instance().clear_vst_cache();
3842 }
3843
3844 void RCOptionEditor::clear_vst_blacklist () {
3845         PluginManager::instance().clear_vst_blacklist();
3846 }
3847
3848 void RCOptionEditor::clear_au_cache () {
3849         PluginManager::instance().clear_au_cache();
3850 }
3851
3852 void RCOptionEditor::clear_au_blacklist () {
3853         PluginManager::instance().clear_au_blacklist();
3854 }
3855
3856 void RCOptionEditor::edit_lxvst_path () {
3857         Glib::RefPtr<Gdk::Window> win = get_parent_window ();
3858         Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
3859                 *current_toplevel(), _("Set Linux VST Search Path"),
3860                 _rc_config->get_plugin_path_lxvst(),
3861                 PluginManager::instance().get_default_lxvst_path()
3862                 );
3863         ResponseType r = (ResponseType) pd->run ();
3864         pd->hide();
3865         if (r == RESPONSE_ACCEPT) {
3866                 _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
3867         }
3868         delete pd;
3869 }
3870
3871 void RCOptionEditor::edit_vst_path () {
3872         Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
3873                 *current_toplevel(), _("Set Windows VST Search Path"),
3874                 _rc_config->get_plugin_path_vst(),
3875                 PluginManager::instance().get_default_windows_vst_path()
3876                 );
3877         ResponseType r = (ResponseType) pd->run ();
3878         pd->hide();
3879         if (r == RESPONSE_ACCEPT) {
3880                 _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
3881         }
3882         delete pd;
3883 }
3884
3885
3886 void
3887 RCOptionEditor::populate_sync_options ()
3888 {
3889         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
3890
3891         _sync_source->clear ();
3892
3893         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
3894                 _sync_source->add (*i, sync_source_to_string (*i));
3895         }
3896
3897         if (sync_opts.empty()) {
3898                 _sync_source->set_sensitive(false);
3899         } else {
3900                 if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
3901                         _rc_config->set_sync_source(sync_opts.front());
3902                 }
3903         }
3904
3905         parameter_changed ("sync-source");
3906 }
3907
3908 Gtk::Window*
3909 RCOptionEditor::use_own_window (bool and_fill_it)
3910 {
3911         bool new_window = !own_window ();
3912
3913         Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
3914
3915         if (win && new_window) {
3916                 win->set_name ("PreferencesWindow");
3917                 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Preferences"), this);
3918         }
3919
3920         return win;
3921 }
3922
3923 XMLNode&
3924 RCOptionEditor::get_state ()
3925 {
3926         XMLNode* node = new XMLNode (X_("Preferences"));
3927         node->add_child_nocopy (Tabbable::get_state());
3928         return *node;
3929 }