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