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