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