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