Monitor new signal to rebuild sendlist
[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
2227                 ComboOption<ScreenSaverMode>* scsvr = new ComboOption<ScreenSaverMode> (
2228                                 "screen-saver-mode",
2229                                 _("System Screensaver Mode"),
2230                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_screen_saver_mode),
2231                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_screen_saver_mode)
2232                                 );
2233
2234                 scsvr->add (InhibitNever, _("Never Inhibit"));
2235                 scsvr->add (InhibitWhileRecording, _("Inhibit while Recording"));
2236                 scsvr->add (InhibitAlways, string_compose (_("Inhibit while %1 is running"), PROGRAM_NAME));
2237
2238                 add_option (_("General"), scsvr);
2239
2240
2241         } // !mixbus
2242
2243         add_option (_("General/Session"), new OptionEditorHeading (S_("Options|Undo")));
2244
2245         add_option (_("General/Session"), new UndoOptions (_rc_config));
2246
2247         add_option (_("General/Session"),
2248              new BoolOption (
2249                      "verify-remove-last-capture",
2250                      _("Verify removal of last capture"),
2251                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
2252                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
2253                      ));
2254
2255         add_option (_("General/Session"), new OptionEditorHeading (_("Session Management")));
2256
2257         add_option (_("General/Session"),
2258              new BoolOption (
2259                      "periodic-safety-backups",
2260                      _("Make periodic backups of the session file"),
2261                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
2262                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
2263                      ));
2264
2265         add_option (_("General/Session"),
2266              new BoolOption (
2267                      "only-copy-imported-files",
2268                      _("Always copy imported files"),
2269                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_only_copy_imported_files),
2270                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_only_copy_imported_files)
2271                      ));
2272
2273         add_option (_("General/Session"), new DirectoryOption (
2274                             X_("default-session-parent-dir"),
2275                             _("Default folder for new sessions:"),
2276                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
2277                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
2278                             ));
2279
2280         add_option (_("General/Session"),
2281              new SpinOption<uint32_t> (
2282                      "max-recent-sessions",
2283                      _("Maximum number of recent sessions"),
2284                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
2285                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
2286                      0, 1000, 1, 20
2287                      ));
2288
2289
2290 #if ENABLE_NLS
2291
2292         add_option (_("General/Translation"), new OptionEditorHeading (_("Internationalization")));
2293
2294         bo = new BoolOption (
2295                         "enable-translation",
2296                         _("Use translations"),
2297                         sigc::ptr_fun (ARDOUR::translations_are_enabled),
2298                         sigc::ptr_fun (ARDOUR::set_translations_enabled)
2299                         );
2300
2301         bo->set_note (string_compose (_("These settings will only take effect after %1 is restarted (if available for your language preferences)."), PROGRAM_NAME));
2302
2303         add_option (_("General/Translation"), bo);
2304
2305         parameter_changed ("enable-translation");
2306 #endif // ENABLE_NLS
2307
2308
2309         /* EDITOR */
2310
2311         add_option (_("Editor"), new OptionEditorHeading (_("General")));
2312
2313         bo = new BoolOption (
2314                      "name-new-markers",
2315                      _("Prompt for new marker names"),
2316                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
2317                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
2318                 );
2319         add_option (_("Editor"), bo);
2320         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."
2321                                                                 "\n\nYou can always rename markers by right-clicking on them"));
2322
2323         add_option (_("Editor"),
2324              new BoolOption (
2325                      "draggable-playhead",
2326                      _("Allow dragging of playhead"),
2327                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead),
2328                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead)
2329                      ));
2330
2331         ComboOption<float>* dps = new ComboOption<float> (
2332                      "draggable-playhead-speed",
2333                      _("Playhead dragging speed (%)"),
2334                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead_speed),
2335                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead_speed)
2336                      );
2337         dps->add (0.05, _("5%"));
2338         dps->add (0.1, _("10%"));
2339         dps->add (0.25, _("25%"));
2340         dps->add (0.5, _("50%"));
2341         dps->add (1.0, _("100%"));
2342         add_option (_("Editor"), dps);
2343
2344         ComboOption<float>* eet = new ComboOption<float> (
2345                      "extra-ui-extents-time",
2346                      _("Limit zooming & summary view to X minutes beyond session extents"),
2347                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_extra_ui_extents_time),
2348                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_extra_ui_extents_time)
2349                      );
2350         eet->add (1, _("1 minute"));
2351         eet->add (2, _("2 minutes"));
2352         eet->add (20, _("20 minutes"));
2353         eet->add (60, _("1 hour"));
2354         eet->add (60*2, _("2 hours"));
2355         eet->add (60*24, _("24 hours"));
2356         add_option (_("Editor"), eet);
2357
2358         if (!Profile->get_mixbus()) {
2359
2360                 add_option (_("Editor"),
2361                                 new BoolOption (
2362                                         "use-mouse-position-as-zoom-focus-on-scroll",
2363                                         _("Zoom to mouse position when zooming with scroll wheel"),
2364                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_mouse_position_as_zoom_focus_on_scroll),
2365                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_mouse_position_as_zoom_focus_on_scroll)
2366                                         ));
2367         }  // !mixbus
2368
2369         add_option (_("Editor"),
2370                     new BoolOption (
2371                             "use-time-rulers-to-zoom-with-vertical-drag",
2372                             _("Zoom with vertical drag in rulers"),
2373                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_time_rulers_to_zoom_with_vertical_drag),
2374                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_time_rulers_to_zoom_with_vertical_drag)
2375                             ));
2376
2377         add_option (_("Editor"),
2378                     new BoolOption (
2379                             "use-double-click-to-zoom-to-selection",
2380                             _("Double click zooms to selection"),
2381                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_double_click_to_zoom_to_selection),
2382                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_double_click_to_zoom_to_selection)
2383                             ));
2384
2385         add_option (_("Editor"),
2386                     new BoolOption (
2387                             "update-editor-during-summary-drag",
2388                             _("Update editor window during drags of the summary"),
2389                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
2390                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
2391                             ));
2392
2393         add_option (_("Editor"),
2394             new BoolOption (
2395                     "autoscroll-editor",
2396                     _("Auto-scroll editor window when dragging near its edges"),
2397                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
2398                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
2399                     ));
2400
2401         add_option (_("Editor"),
2402              new BoolComboOption (
2403                      "show-region-gain-envelopes",
2404                      _("Show gain envelopes in audio regions"),
2405                      _("in all modes"),
2406                      _("only in Draw and Internal Edit modes"),
2407                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
2408                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
2409                      ));
2410
2411         add_option (_("Editor"), new OptionEditorHeading (_("Editor Behavior")));
2412
2413         add_option (_("Editor"),
2414              new BoolOption (
2415                      "automation-follows-regions",
2416                      _("Move relevant automation when audio regions are moved"),
2417                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
2418                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
2419                      ));
2420
2421         bo = new BoolOption (
2422                      "new-automation-points-on-lane",
2423                      _("Ignore Y-axis click position when adding new automation-points"),
2424                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_new_automation_points_on_lane),
2425                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_new_automation_points_on_lane)
2426                      );
2427         add_option (_("Editor"), bo);
2428         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2429                         _("<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."));
2430
2431         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
2432                         "default-fade-shape",
2433                         _("Default fade shape"),
2434                         sigc::mem_fun (*_rc_config,
2435                                 &RCConfiguration::get_default_fade_shape),
2436                         sigc::mem_fun (*_rc_config,
2437                                 &RCConfiguration::set_default_fade_shape)
2438                         );
2439
2440         fadeshape->add (FadeLinear,
2441                         _("Linear (for highly correlated material)"));
2442         fadeshape->add (FadeConstantPower, _("Constant power"));
2443         fadeshape->add (FadeSymmetric, _("Symmetric"));
2444         fadeshape->add (FadeSlow, _("Slow"));
2445         fadeshape->add (FadeFast, _("Fast"));
2446
2447         add_option (_("Editor"), fadeshape);
2448
2449         ComboOption<RegionEquivalence> *eqv = new ComboOption<RegionEquivalence> (
2450                      "region-equivalency",
2451                      _("Regions in active edit groups are edited together"),
2452                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_equivalence),
2453                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_equivalence)
2454                      );
2455
2456         eqv->add (Overlap, _("whenever they overlap in time"));
2457         eqv->add (Enclosed, _("if either encloses the other"));
2458         eqv->add (Exact, _("only if they have identical length, position and origin"));
2459         eqv->add (LayerTime, _("only if they have identical length, position and layer"));
2460
2461         add_option (_("Editor"), eqv);
2462
2463         ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
2464                 "layer-model",
2465                 _("Layering model"),
2466                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
2467                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
2468                 );
2469
2470         lm->add (LaterHigher, _("later is higher"));
2471         lm->add (Manual, _("manual layering"));
2472         add_option (_("Editor"), lm);
2473
2474         add_option (_("Editor"), new OptionEditorHeading (_("Split/Separate")));
2475
2476         ComboOption<RangeSelectionAfterSplit> *rras = new ComboOption<RangeSelectionAfterSplit> (
2477                     "range-selection-after-separate",
2478                     _("After a Separate operation, in Range mode"),
2479                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_range_selection_after_split),
2480                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_range_selection_after_split));
2481
2482         rras->add(ClearSel, _("Clear the Range Selection"));
2483         rras->add(PreserveSel, _("Preserve the Range Selection"));
2484         rras->add(ForceSel, _("Force-Select the regions under the range. (this might cause a tool change)"));
2485         add_option (_("Editor"), rras);
2486
2487         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
2488                     "region-selection-after-split",
2489                     _("After a Split operation, in Object mode"),
2490                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
2491                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
2492
2493         // TODO: decide which of these modes are really useful
2494         rsas->add(None, _("Clear the Selected Regions"));
2495         rsas->add(NewlyCreatedLeft, _("Select only the newly-created regions BEFORE the split point"));
2496         rsas->add(NewlyCreatedRight, _("Select only the newly-created regions AFTER the split point"));
2497         rsas->add(NewlyCreatedBoth, _("Select the newly-created regions"));
2498         // rsas->add(Existing, _("unmodified regions in the existing selection"));
2499         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
2500         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
2501         rsas->add(ExistingNewlyCreatedBoth, _("Preserve the existing selection, AND select all newly-created regions"));
2502
2503         add_option (_("Editor"), rsas);
2504
2505         add_option (_("Editor/Snap"), new OptionEditorHeading (_("General Snap options:")));
2506
2507         add_option (_("Editor/Snap"),
2508                     new SpinOption<uint32_t> (
2509                             "snap-threshold",
2510                             _("Snap Threshold (pixels)"),
2511                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_threshold),
2512                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_threshold),
2513                             10, 200,
2514                             1, 10
2515                             ));
2516
2517         add_option (_("Editor/Snap"),
2518              new BoolOption (
2519                      "show-snapped-cursor",
2520                      _("Show \"snapped cursor\""),
2521                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_snapped_cursor),
2522                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_snapped_cursor)
2523                      ));
2524
2525         add_option (_("Editor/Snap"),
2526              new BoolOption (
2527                      "rubberbanding-snaps-to-grid",
2528                      _("Snap rubberband selection to grid"),
2529                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
2530                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
2531                      ));
2532
2533         add_option (_("Editor/Snap"),
2534              new BoolOption (
2535                      "grid-follows-internal",
2536                      _("Grid switches to alternate selection for Internal Edit tools"),
2537                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_grid_follows_internal),
2538                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_grid_follows_internal)
2539                      ));
2540
2541         add_option (_("Editor/Snap"),
2542              new BoolOption (
2543                      "rulers-follow-grid",
2544                      _("Rulers automatically change to follow the Grid mode selection"),
2545                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rulers_follow_grid),
2546                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rulers_follow_grid)
2547                      ));
2548
2549         add_option (_("Editor/Snap"), new OptionEditorHeading (_("When \"Snap\" is enabled, snap to:")));
2550
2551
2552         add_option (_("Editor/Snap"),
2553              new BoolOption (
2554                      "snap-to-marks",
2555                      _("Markers"),
2556                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_marks),
2557                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_marks)
2558                      ));
2559
2560         add_option (_("Editor/Snap"),
2561              new BoolOption (
2562                      "snap-to-region-sync",
2563                      _("Region Sync Points"),
2564                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_sync),
2565                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_sync)
2566                      ));
2567
2568         add_option (_("Editor/Snap"),
2569              new BoolOption (
2570                      "snap-to-region-start",
2571                      _("Region Starts"),
2572                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_start),
2573                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_start)
2574                      ));
2575
2576         add_option (_("Editor/Snap"),
2577              new BoolOption (
2578                      "snap-to-region-end",
2579                      _("Region Ends"),
2580                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_end),
2581                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_end)
2582                      ));
2583
2584         add_option (_("Editor/Snap"),
2585              new BoolOption (
2586                      "snap-to-grid",
2587                      _("Grid"),
2588                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_grid),
2589                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_grid)
2590                      ));
2591
2592         add_option (_("Editor/Modifiers"), new OptionEditorHeading (_("Keyboard Modifiers")));
2593         add_option (_("Editor/Modifiers"), new KeyboardOptions);
2594         add_option (_("Editor/Modifiers"), new OptionEditorBlank ());
2595
2596         /* MIXER -- SOLO AND MUTE */
2597
2598         add_option (_("Mixer"), new OptionEditorHeading (_("Solo")));
2599
2600         _solo_control_is_listen_control = new BoolOption (
2601                 "solo-control-is-listen-control",
2602                 _("Solo controls are Listen controls"),
2603                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
2604                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
2605                 );
2606
2607         add_option (_("Mixer"), _solo_control_is_listen_control);
2608
2609         add_option (_("Mixer"),
2610              new BoolOption (
2611                      "exclusive-solo",
2612                      _("Exclusive solo"),
2613                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2614                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2615                      ));
2616
2617         add_option (_("Mixer"),
2618              new BoolOption (
2619                      "show-solo-mutes",
2620                      _("Show solo muting"),
2621                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2622                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2623                      ));
2624
2625         add_option (_("Mixer"),
2626              new BoolOption (
2627                      "solo-mute-override",
2628                      _("Soloing overrides muting"),
2629                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2630                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2631                      ));
2632
2633         add_option (_("Mixer"),
2634              new FaderOption (
2635                      "solo-mute-gain",
2636                      _("Solo-in-place mute cut (dB)"),
2637                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
2638                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
2639                      ));
2640
2641         _listen_position = new ComboOption<ListenPosition> (
2642                 "listen-position",
2643                 _("Listen Position"),
2644                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
2645                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
2646                 );
2647
2648         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
2649         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
2650
2651         add_option (_("Mixer"), _listen_position);
2652
2653         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
2654                 "pfl-position",
2655                 _("PFL signals come from"),
2656                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
2657                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
2658                 );
2659
2660         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2661         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2662
2663         add_option (_("Mixer"), pp);
2664
2665         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2666                 "afl-position",
2667                 _("AFL signals come from"),
2668                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2669                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2670                 );
2671
2672         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2673         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2674
2675         add_option (_("Mixer"), pa);
2676
2677         add_option (_("Mixer"), new OptionEditorHeading (_("Default Track / Bus Muting Options")));
2678
2679         add_option (_("Mixer"),
2680              new BoolOption (
2681                      "mute-affects-pre-fader",
2682                      _("Mute affects pre-fader sends"),
2683                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2684                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2685                      ));
2686
2687         add_option (_("Mixer"),
2688              new BoolOption (
2689                      "mute-affects-post-fader",
2690                      _("Mute affects post-fader sends"),
2691                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2692                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2693                      ));
2694
2695         add_option (_("Mixer"),
2696              new BoolOption (
2697                      "mute-affects-control-outs",
2698                      _("Mute affects control outputs"),
2699                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2700                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2701                      ));
2702
2703         add_option (_("Mixer"),
2704              new BoolOption (
2705                      "mute-affects-main-outs",
2706                      _("Mute affects main outputs"),
2707                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2708                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2709                      ));
2710
2711
2712         if (!ARDOUR::Profile->get_mixbus()) {
2713                 add_option (_("Mixer"), new OptionEditorHeading (_("Send Routing")));
2714                 add_option (_("Mixer"),
2715                                 new BoolOption (
2716                                         "link-send-and-route-panner",
2717                                         _("Link panners of Aux and External Sends with main panner by default"),
2718                                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2719                                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2720                                         ));
2721         }
2722
2723         /* Signal Flow */
2724
2725         add_option (_("Signal Flow"), new OptionEditorHeading (_("Monitoring")));
2726
2727         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
2728                 "monitoring-model",
2729                 _("Record monitoring handled by"),
2730                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
2731                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
2732                 );
2733
2734         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
2735                 mm->add (HardwareMonitoring, _("via Audio Driver"));
2736         }
2737
2738         string prog (PROGRAM_NAME);
2739         boost::algorithm::to_lower (prog);
2740         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
2741         mm->add (ExternalMonitoring, _("audio hardware"));
2742
2743         add_option (_("Signal Flow"), mm);
2744
2745         bo = new BoolOption (
2746                      "tape-machine-mode",
2747                      _("Tape machine mode"),
2748                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
2749                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
2750                      );
2751         add_option (_("Signal Flow"), bo);
2752         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2753                         string_compose (_("<b>When enabled</b> %1 will not monitor a track's input if the transport is stopped."),
2754                                         PROGRAM_NAME));
2755
2756         if (!Profile->get_mixbus()) {
2757
2758                 add_option (_("Signal Flow"), new OptionEditorHeading (_("Track and Bus Connections")));
2759
2760                 bo = new BoolOption (
2761                                         "auto-connect-standard-busses",
2762                                         _("Auto-connect main output (master or monitor) bus to physical ports"),
2763                                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
2764                                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
2765                                         );
2766                 add_option (_("Signal Flow"), bo);
2767                 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2768                         _("<b>When enabled</b> the main output bus is auto-connected to the first N physical ports. "
2769                                 "If the session has a monitor-section, the monitor-bus output is conneced the the hardware playback ports, "
2770                                 "otherwise the master-bus output is directly used for playback."));
2771
2772                 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
2773                                 "input-auto-connect",
2774                                 _("Connect track inputs"),
2775                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
2776                                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
2777                                 );
2778
2779                 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
2780                 iac->add (ManualConnect, _("manually"));
2781
2782                 add_option (_("Signal Flow"), iac);
2783
2784                 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
2785                                 "output-auto-connect",
2786                                 _("Connect track and bus outputs"),
2787                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
2788                                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
2789                                 );
2790
2791                 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
2792                 oac->add (AutoConnectMaster, _("automatically to master bus"));
2793                 oac->add (ManualConnect, _("manually"));
2794
2795                 add_option (_("Signal Flow"), oac);
2796
2797                 bo = new BoolOption (
2798                                 "strict-io",
2799                                 _("Use 'Strict-I/O' for new tracks or busses"),
2800                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_strict_io),
2801                                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_strict_io)
2802                                 );
2803
2804                 add_option (_("Signal Flow"), bo);
2805                 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2806                                 _("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."));
2807
2808         }  // !mixbus
2809
2810
2811         /* AUDIO */
2812
2813         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
2814
2815         add_option (_("Audio"), new BufferingOptions (_rc_config));
2816
2817         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
2818
2819         add_option (_("Audio"),
2820              new BoolOption (
2821                      "denormal-protection",
2822                      _("Use DC bias to protect against denormals"),
2823                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
2824                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
2825                      ));
2826
2827         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
2828                 "denormal-model",
2829                 _("Processor handling"),
2830                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
2831                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
2832                 );
2833
2834         int dmsize = 1;
2835         dm->add (DenormalNone, _("no processor handling"));
2836
2837         FPU* fpu = FPU::instance();
2838
2839         if (fpu->has_flush_to_zero()) {
2840                 ++dmsize;
2841                 dm->add (DenormalFTZ, _("use FlushToZero"));
2842         } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
2843                 _rc_config->set_denormal_model(DenormalNone);
2844         }
2845
2846         if (fpu->has_denormals_are_zero()) {
2847                 ++dmsize;
2848                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
2849         } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
2850                 _rc_config->set_denormal_model(DenormalNone);
2851         }
2852
2853         if (fpu->has_flush_to_zero() && fpu->has_denormals_are_zero()) {
2854                 ++dmsize;
2855                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
2856         } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
2857                 _rc_config->set_denormal_model(DenormalNone);
2858         }
2859
2860         if (dmsize == 1) {
2861                 dm->set_sensitive(false);
2862         }
2863
2864         add_option (_("Audio"), dm);
2865
2866         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
2867
2868         add_option (_("Audio"),
2869              new BoolOption (
2870                      "auto-analyse-audio",
2871                      _("Enable automatic analysis of audio"),
2872                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
2873                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
2874                      ));
2875
2876         add_option (_("Audio"),
2877              new BoolOption (
2878                      "replicate-missing-region-channels",
2879                      _("Replicate missing region channels"),
2880                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
2881                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
2882                      ));
2883
2884         /* MIDI */
2885
2886         add_option (_("MIDI"), new OptionEditorHeading (_("Buffering")));
2887
2888         add_option (_("MIDI"),
2889                     new SpinOption<float> (
2890                             "midi-readahead",
2891                             _("MIDI read-ahead time (seconds)"),
2892                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2893                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2894                             0.1, 10, 0.05, 1,
2895                             "", 1.0, 2
2896                             ));
2897
2898         add_option (_("MIDI"), new OptionEditorHeading (_("Session")));
2899
2900         add_option (_("MIDI"),
2901              new SpinOption<int32_t> (
2902                      "initial-program-change",
2903                      _("Initial program change"),
2904                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2905                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2906                      -1, 65536, 1, 10
2907                      ));
2908
2909         add_option (_("MIDI"), new OptionEditorHeading (_("Audition")));
2910
2911         add_option (_("MIDI"),
2912              new BoolOption (
2913                      "sound-midi-notes",
2914                      _("Sound MIDI notes as they are selected in the editor"),
2915                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
2916                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
2917                      ));
2918
2919         /* Click */
2920
2921         add_option (_("Metronome"), new OptionEditorHeading (_("Metronome")));
2922         add_option (_("Metronome"), new ClickOptions (_rc_config));
2923         add_option (_("Metronome"), new OptionEditorHeading (_("Options")));
2924
2925         bo = new BoolOption (
2926                         "click-record-only",
2927                         _("Enable metronome only while recording"),
2928                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_record_only),
2929                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_record_only)
2930                         );
2931
2932         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2933                         string_compose (_("<b>When enabled</b> the metronome will remain silent if %1 is <b>not recording</b>."), PROGRAM_NAME));
2934         add_option (_("Metronome"), bo);
2935         add_option (_("Metronome"), new OptionEditorBlank ());
2936
2937
2938         /* Meters */
2939
2940         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2941
2942         ComboOption<float>* mht = new ComboOption<float> (
2943                 "meter-hold",
2944                 _("Peak hold time"),
2945                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_hold),
2946                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_hold)
2947                 );
2948
2949         mht->add (MeterHoldOff, _("off"));
2950         mht->add (MeterHoldShort, _("short"));
2951         mht->add (MeterHoldMedium, _("medium"));
2952         mht->add (MeterHoldLong, _("long"));
2953
2954         add_option (S_("Preferences|Metering"), mht);
2955
2956         ComboOption<float>* mfo = new ComboOption<float> (
2957                 "meter-falloff",
2958                 _("DPM fall-off"),
2959                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2960                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2961                 );
2962
2963         mfo->add (METER_FALLOFF_OFF,      _("off"));
2964         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2965         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2966         mfo->add (METER_FALLOFF_SLOWISH,  _("moderate [12.0dB/sec] (DIN)"));
2967         mfo->add (METER_FALLOFF_MODERATE, _("medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2968         mfo->add (METER_FALLOFF_MEDIUM,   _("fast [20dB/sec]"));
2969         mfo->add (METER_FALLOFF_FAST,     _("very fast [32dB/sec]"));
2970
2971         add_option (S_("Preferences|Metering"), mfo);
2972
2973         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2974                 "meter-line-up-level",
2975                 _("Meter line-up level; 0dBu"),
2976                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_level),
2977                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_level)
2978                 );
2979
2980         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2981         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2982         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2983         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2984
2985         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."));
2986
2987         add_option (S_("Preferences|Metering"), mlu);
2988
2989         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2990                 "meter-line-up-din",
2991                 _("IEC1/DIN Meter line-up level; 0dBu"),
2992                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_din),
2993                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_din)
2994                 );
2995
2996         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2997         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2998         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2999         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3000
3001         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
3002
3003         add_option (S_("Preferences|Metering"), mld);
3004
3005         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
3006                 "meter-vu-standard",
3007                 _("VU Meter standard"),
3008                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_vu_standard),
3009                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_vu_standard)
3010                 );
3011
3012         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
3013         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
3014         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
3015         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
3016
3017         add_option (S_("Preferences|Metering"), mvu);
3018
3019         HSliderOption *mpks = new HSliderOption("meter-peak",
3020                         _("Peak indicator threshold [dBFS]"),
3021                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_peak),
3022                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_peak),
3023                         -10, 0, .1, .1
3024                         );
3025
3026         Gtkmm2ext::UI::instance()->set_tip (
3027                         mpks->tip_widget(),
3028                         _("Specify the audio signal level in dBFS at and above which the meter-peak indicator will flash red."));
3029
3030         add_option (S_("Preferences|Metering"), mpks);
3031
3032         OptionEditorHeading* default_meter_head = new OptionEditorHeading (_("Default Meter Types"));
3033         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."));
3034
3035         add_option (S_("Preferences|Metering"), default_meter_head);
3036
3037         ComboOption<MeterType>* mtm = new ComboOption<MeterType> (
3038                 "meter-type-master",
3039                 _("Default Meter Type for Master Bus"),
3040                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_master),
3041                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_master)
3042                 );
3043         mtm->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3044         mtm->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3045         mtm->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3046         mtm->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3047         mtm->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3048         mtm->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3049         mtm->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3050         mtm->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3051
3052         add_option (S_("Preferences|Metering"), mtm);
3053
3054
3055         ComboOption<MeterType>* mtb = new ComboOption<MeterType> (
3056                 "meter-type-bus",
3057                 _("Default meter type for busses"),
3058                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_bus),
3059                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_bus)
3060                 );
3061         mtb->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3062         mtb->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3063         mtb->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3064         mtb->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3065         mtb->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3066         mtb->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3067         mtb->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3068         mtb->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3069
3070         add_option (S_("Preferences|Metering"), mtb);
3071
3072         ComboOption<MeterType>* mtt = new ComboOption<MeterType> (
3073                 "meter-type-track",
3074                 _("Default meter type for tracks"),
3075                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_track),
3076                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_track)
3077                 );
3078         mtt->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3079         mtt->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
3080
3081         add_option (S_("Preferences|Metering"), mtt);
3082
3083         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Post Export Analysis")));
3084
3085         add_option (S_("Preferences|Metering"),
3086              new BoolOption (
3087                      "save-export-analysis-image",
3088                      _("Save loudness analysis as image file after export"),
3089                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_save_export_analysis_image),
3090                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_save_export_analysis_image)
3091                      ));
3092
3093         add_option (S_("Preferences|Metering"),
3094              new BoolOption (
3095                      "save-export-mixer-screenshot",
3096                      _("Save Mixer screenshot after export"),
3097                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_save_export_mixer_screenshot),
3098                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_save_export_mixer_screenshot)
3099                      ));
3100
3101         /* TRANSPORT & Sync */
3102
3103         add_option (_("Transport"), new OptionEditorHeading (_("General")));
3104
3105         bo = new BoolOption (
3106                      "stop-at-session-end",
3107                      _("Stop at the end of the session"),
3108                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
3109                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
3110                      );
3111         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3112                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
3113                                                               "when it reaches the current session end marker\n\n"
3114                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
3115                                                             PROGRAM_NAME));
3116         add_option (_("Transport"), bo);
3117
3118         bo = new BoolOption (
3119                      "latched-record-enable",
3120                      _("Keep record-enable engaged on stop"),
3121                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
3122                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
3123                      );
3124         add_option (_("Transport"), bo);
3125         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3126                         _("<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."));
3127
3128         bo = new BoolOption (
3129                      "disable-disarm-during-roll",
3130                      _("Disable per-track record disarm while rolling"),
3131                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
3132                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
3133                      );
3134         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."));
3135         add_option (_("Transport"), bo);
3136
3137         bo = new BoolOption (
3138                      "quieten_at_speed",
3139                      _("12dB gain reduction during fast-forward and fast-rewind"),
3140                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
3141                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
3142                      );
3143         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3144                         _("<b>When enabled</b> this will reduce the unpleasant increase in perceived volume "
3145                                 "that occurs when fast-forwarding or rewinding through some kinds of audio"));
3146         add_option (_("Transport"), bo);
3147
3148         ComboOption<float>* psc = new ComboOption<float> (
3149                      "preroll-seconds",
3150                      _("Preroll"),
3151                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_preroll_seconds),
3152                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_preroll_seconds)
3153                      );
3154         Gtkmm2ext::UI::instance()->set_tip (psc->tip_widget(),
3155                                             (_("The amount of preroll to apply when <b>Play with Preroll</b> or <b>Record with Preroll</b>is initiated.\n\n"
3156                                                "If <b>Follow Edits</b> is enabled, the preroll is applied to the playhead position when a region is selected or trimmed.")));
3157         psc->add (-4.0, _("4 Bars"));
3158         psc->add (-2.0, _("2 Bars"));
3159         psc->add (-1.0, _("1 Bar"));
3160         psc->add (0.0, _("0 (no pre-roll)"));
3161         psc->add (0.1, _("0.1 second"));
3162         psc->add (0.25, _("0.25 second"));
3163         psc->add (0.5, _("0.5 second"));
3164         psc->add (1.0, _("1.0 second"));
3165         psc->add (2.0, _("2.0 seconds"));
3166         add_option (_("Transport"), psc);
3167
3168
3169         add_option (_("Transport"), new OptionEditorHeading (_("Looping")));
3170
3171         bo = new BoolOption (
3172                      "loop-is-mode",
3173                      _("Play loop is a transport mode"),
3174                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
3175                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
3176                      );
3177         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3178                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
3179                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
3180         add_option (_("Transport"), bo);
3181
3182         bo = new BoolOption (
3183                      "seamless-loop",
3184                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
3185                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
3186                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
3187                      );
3188         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3189                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
3190                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
3191                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
3192                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
3193         add_option (_("Transport"), bo);
3194
3195         add_option (_("Transport"), new OptionEditorHeading (_("Dropout (xrun) Handling")));
3196         bo = new BoolOption (
3197                      "stop-recording-on-xrun",
3198                      _("Stop recording when an xrun occurs"),
3199                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
3200                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
3201                      );
3202         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3203                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
3204                                                             PROGRAM_NAME));
3205         add_option (_("Transport"), bo);
3206
3207         bo = new BoolOption (
3208                      "create-xrun-marker",
3209                      _("Create markers where xruns occur"),
3210                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
3211                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
3212                      );
3213         add_option (_("Transport"), bo);
3214
3215
3216         /* SYNC */
3217
3218         add_option (_("Sync"), new OptionEditorHeading (_("Transport Masters")));
3219
3220         add_option (_("Sync"), new WidgetOption (X_("foo"), X_("Transport Masters"), _transport_masters_widget));
3221
3222         _sync_framerate = new BoolOption (
3223                      "timecode-sync-frame-rate",
3224                      _("Match session video frame rate to external timecode"),
3225                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
3226                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
3227                      );
3228         Gtkmm2ext::UI::instance()->set_tip
3229                 (_sync_framerate->tip_widget(),
3230                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
3231                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
3232                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
3233                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
3234                                    "timecode standard and the session standard."), PROGRAM_NAME));
3235
3236         add_option (_("Sync"), _sync_framerate);
3237
3238         add_option (_("Sync/LTC"), new OptionEditorHeading (_("Linear Timecode (LTC) Generator")));
3239
3240         add_option (_("Sync/LTC"),
3241                     new BoolOption (
3242                             "send-ltc",
3243                             _("Enable LTC generator"),
3244                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
3245                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
3246                             ));
3247
3248         _ltc_send_continuously = new BoolOption (
3249                             "ltc-send-continuously",
3250                             _("Send LTC while stopped"),
3251                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
3252                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
3253                             );
3254         Gtkmm2ext::UI::instance()->set_tip
3255                 (_ltc_send_continuously->tip_widget(),
3256                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
3257         add_option (_("Sync/LTC"), _ltc_send_continuously);
3258
3259         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level [dBFS]"),
3260                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_output_volume),
3261                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_output_volume),
3262                                         -50, 0, .5, 5,
3263                                         .05, true);
3264
3265         Gtkmm2ext::UI::instance()->set_tip
3266                 (_ltc_volume_slider->tip_widget(),
3267                  _("Specify the Peak Volume of the generated LTC signal in dBFS. A good value is  0dBu ^= -18dBFS in an EBU calibrated system"));
3268
3269         add_option (_("Sync/LTC"), _ltc_volume_slider);
3270
3271         add_option (_("Sync/MIDI"), new OptionEditorHeading (_("MIDI Beat Clock (Mclk) Generator")));
3272
3273         add_option (_("Sync/MIDI"),
3274                     new BoolOption (
3275                             "send-midi-clock",
3276                             _("Enable Mclk generator"),
3277                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
3278                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
3279                             ));
3280
3281         add_option (_("Sync/MIDI"), new OptionEditorHeading (_("MIDI Time Code (MTC) Generator")));
3282
3283         add_option (_("Sync/MIDI"),
3284                     new BoolOption (
3285                             "send-mtc",
3286                             _("Enable MTC Generator"),
3287                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
3288                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
3289                             ));
3290
3291         add_option (_("Sync/MIDI"),
3292                     new SpinOption<int> (
3293                             "mtc-qf-speed-tolerance",
3294                             _("Percentage either side of normal transport speed to transmit MTC"),
3295                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
3296                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
3297                             0, 20, 1, 5
3298                             ));
3299
3300         add_option (_("Sync/MIDI"), new OptionEditorHeading (_("MIDI Machine Control (MMC)")));
3301
3302         add_option (_("Sync/MIDI"),
3303                     new BoolOption (
3304                             "mmc-control",
3305                             _("Respond to MMC commands"),
3306                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
3307                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
3308                             ));
3309
3310         add_option (_("Sync/MIDI"),
3311                     new BoolOption (
3312                             "send-mmc",
3313                             _("Send MMC commands"),
3314                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
3315                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
3316                             ));
3317
3318         add_option (_("Sync/MIDI"),
3319              new SpinOption<uint8_t> (
3320                      "mmc-receive-device-id",
3321                      _("Inbound MMC device ID"),
3322                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
3323                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
3324                      0, 127, 1, 10
3325                      ));
3326
3327         add_option (_("Sync/MIDI"),
3328              new SpinOption<uint8_t> (
3329                      "mmc-send-device-id",
3330                      _("Outbound MMC device ID"),
3331                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
3332                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
3333                      0, 127, 1, 10
3334                      ));
3335
3336
3337         /* Control Surfaces */
3338
3339         add_option (_("Control Surfaces"), new OptionEditorHeading (_("Control Surfaces")));
3340         add_option (_("Control Surfaces"), new ControlSurfacesOptions ());
3341
3342         /* MIDI PORTs */
3343         add_option (_("MIDI Ports"), new OptionEditorHeading (_("MIDI Port Options")));
3344
3345         add_option (_("MIDI Ports"),
3346                     new BoolOption (
3347                             "midi-input-follows-selection",
3348                             _("MIDI input follows MIDI track selection"),
3349                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_input_follows_selection),
3350                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_input_follows_selection)
3351                             ));
3352
3353         add_option (_("MIDI Ports"), new MidiPortOptions ());
3354         add_option (_("MIDI Ports"), new OptionEditorBlank ());
3355
3356         /* PLUGINS */
3357
3358 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
3359         add_option (_("Plugins"), new OptionEditorHeading (_("Scan/Discover")));
3360         add_option (_("Plugins"),
3361                         new RcActionButton (_("Scan for Plugins"),
3362                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3363
3364 #endif
3365
3366         add_option (_("Plugins"), new OptionEditorHeading (_("General")));
3367
3368 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
3369         bo = new BoolOption (
3370                         "show-plugin-scan-window",
3371                         _("Always Display Plugin Scan Progress"),
3372                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_plugin_scan_window),
3373                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_plugin_scan_window)
3374                         );
3375         add_option (_("Plugins"), bo);
3376         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3377                         _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
3378 #endif
3379
3380         bo = new BoolOption (
3381                 "plugins-stop-with-transport",
3382                 _("Silence plugins when the transport is stopped"),
3383                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
3384                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
3385                 );
3386         add_option (_("Plugins"), bo);
3387         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3388                                             _("<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."));
3389
3390         bo = new BoolOption (
3391                 "new-plugins-active",
3392                         _("Make new plugins active"),
3393                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
3394                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
3395                         );
3396         add_option (_("Plugins"), bo);
3397         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3398                                             _("<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"));
3399
3400         ComboOption<uint32_t>* lna = new ComboOption<uint32_t> (
3401                      "limit-n-automatables",
3402                      _("Limit automatable parameters per plugin"),
3403                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_limit_n_automatables),
3404                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_limit_n_automatables)
3405                      );
3406         lna->add (0, _("Unlimited"));
3407         lna->add (64,  _("64 parameters"));
3408         lna->add (128, _("128 parameters"));
3409         lna->add (256, _("256 parameters"));
3410         lna->add (512, _("512 parameters"));
3411         lna->add (999, _("999 parameters"));
3412         add_option (_("Plugins"), lna);
3413         Gtkmm2ext::UI::instance()->set_tip (lna->tip_widget(),
3414                                             _("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."));
3415
3416
3417 #if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT)
3418         add_option (_("Plugins/VST"), new OptionEditorHeading (_("VST")));
3419 #if 0
3420         add_option (_("Plugins/VST"),
3421                         new RcActionButton (_("Scan for Plugins"),
3422                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3423 #endif
3424
3425 #if (defined AUDIOUNIT_SUPPORT && defined MACVST_SUPPORT)
3426         bo = new BoolOption (
3427                         "",
3428                         _("Enable Mac VST support (requires restart or re-scan)"),
3429                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_macvst),
3430                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_macvst)
3431                         );
3432         add_option (_("Plugins/VST"), bo);
3433 #endif
3434
3435         bo = new BoolOption (
3436                         "discover-vst-on-start",
3437                         _("Scan for [new] VST Plugins on Application Start"),
3438                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_vst_on_start),
3439                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_vst_on_start)
3440                         );
3441         add_option (_("Plugins/VST"), bo);
3442         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3443                                             _("<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"));
3444
3445 #ifdef WINDOWS_VST_SUPPORT
3446         // currently verbose logging is only implemented for Windows VST.
3447         bo = new BoolOption (
3448                         "verbose-plugin-scan",
3449                         _("Verbose Plugin Scan"),
3450                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_verbose_plugin_scan),
3451                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_verbose_plugin_scan)
3452                         );
3453         add_option (_("Plugins/VST"), bo);
3454         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3455                                             _("<b>When enabled</b> additional information for every plugin is added to the Log Window."));
3456 #endif
3457
3458         add_option (_("Plugins/VST"), new VstTimeOutSliderOption (_rc_config));
3459
3460         add_option (_("Plugins/VST"),
3461                         new RcActionButton (_("Clear"),
3462                                 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_cache),
3463                                 _("VST Cache:")));
3464
3465         add_option (_("Plugins/VST"),
3466                         new RcActionButton (_("Clear"),
3467                                 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_blacklist),
3468                                 _("VST Blacklist:")));
3469 #endif
3470
3471 #ifdef LXVST_SUPPORT
3472         add_option (_("Plugins/VST"),
3473                         new RcActionButton (_("Edit"),
3474                                 sigc::mem_fun (*this, &RCOptionEditor::edit_lxvst_path),
3475                         _("Linux VST Path:")));
3476
3477         add_option (_("Plugins/VST"),
3478                         new RcConfigDisplay (
3479                                 "plugin-path-lxvst",
3480                                 _("Path:"),
3481                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_lxvst),
3482                                 0));
3483 #endif
3484
3485 #ifdef WINDOWS_VST_SUPPORT
3486         add_option (_("Plugins/VST"),
3487                         new RcActionButton (_("Edit"),
3488                                 sigc::mem_fun (*this, &RCOptionEditor::edit_vst_path),
3489                         _("Windows VST Path:")));
3490         add_option (_("Plugins/VST"),
3491                         new RcConfigDisplay (
3492                                 "plugin-path-vst",
3493                                 _("Path:"),
3494                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_vst),
3495                                 ';'));
3496 #endif
3497
3498 #ifdef AUDIOUNIT_SUPPORT
3499
3500         add_option (_("Plugins/Audio Unit"), new OptionEditorHeading (_("Audio Unit")));
3501 #if 0
3502         add_option (_("Plugins/Audio Unit"),
3503                         new RcActionButton (_("Scan for Plugins"),
3504                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3505 #endif
3506
3507         bo = new BoolOption (
3508                         "discover-audio-units",
3509                         _("Scan for [new] AudioUnit Plugins on Application Start"),
3510                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_audio_units),
3511                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_audio_units)
3512                         );
3513         add_option (_("Plugins/Audio Unit"), bo);
3514         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3515                                             _("<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."));
3516
3517         add_option (_("Plugins/Audio Unit"),
3518                         new RcActionButton (_("Clear"),
3519                                 sigc::mem_fun (*this, &RCOptionEditor::clear_au_cache),
3520                                 _("AU Cache:")));
3521
3522         add_option (_("Plugins/Audio Unit"),
3523                         new RcActionButton (_("Clear"),
3524                                 sigc::mem_fun (*this, &RCOptionEditor::clear_au_blacklist),
3525                                 _("AU Blacklist:")));
3526 #endif
3527
3528 #ifdef HAVE_LV2
3529         add_option (_("Plugins"), new OptionEditorHeading (_("LV1/LV2")));
3530         add_option (_("Plugins"),
3531              new BoolOption (
3532                      "conceal-lv1-if-lv2-exists",
3533                      _("Conceal LADSPA (LV1) Plugins if matching LV2 exists"),
3534                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_conceal_lv1_if_lv2_exists),
3535                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_conceal_lv1_if_lv2_exists)
3536                      ));
3537 #endif
3538
3539 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2)
3540         add_option (_("Plugins"), new OptionEditorHeading (_("Plugin GUI")));
3541         add_option (_("Plugins"),
3542              new BoolOption (
3543                      "open-gui-after-adding-plugin",
3544                      _("Automatically open the plugin GUI when adding a new plugin"),
3545                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_open_gui_after_adding_plugin),
3546                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_open_gui_after_adding_plugin)
3547                      ));
3548
3549 #if (defined LV2_SUPPORT && defined LV2_EXTENDED)
3550         add_option (_("Plugins"),
3551              new BoolOption (
3552                      "show-inline-display-by-default",
3553                      _("Show Plugin Inline Display on Mixerstrip by default"),
3554                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_inline_display_by_default),
3555                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_inline_display_by_default)
3556                      ));
3557
3558         _plugin_prefer_inline = new BoolOption (
3559                         "prefer-inline-over-gui",
3560                         _("Don't automatically open the plugin GUI when the plugin has an inline display mode"),
3561                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_prefer_inline_over_gui),
3562                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_prefer_inline_over_gui)
3563                         );
3564         add_option (_("Plugins"), _plugin_prefer_inline);
3565 #endif
3566
3567         add_option (_("Plugins"), new OptionEditorHeading (_("Instrument")));
3568
3569         bo = new BoolOption (
3570                         "ask-replace-instrument",
3571                         _("Ask to replace existing instrument plugin"),
3572                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_ask_replace_instrument),
3573                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_ask_replace_instrument)
3574                         );
3575         add_option (_("Plugins"), bo);
3576
3577         bo = new BoolOption (
3578                         "ask-setup_instrument",
3579                         _("Interactively configure instrument plugins on insert"),
3580                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_ask_setup_instrument),
3581                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_ask_setup_instrument)
3582                         );
3583         add_option (_("Plugins"), bo);
3584         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3585                         _("<b>When enabled</b> show a dialog to select instrument channel configuration before adding a multichannel plugin."));
3586
3587 #endif
3588         add_option (_("Plugins"), new OptionEditorBlank ());
3589
3590         /* INTERFACE */
3591 #if (defined OPTIONAL_CAIRO_IMAGE_SURFACE || defined CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE)
3592         add_option (_("Appearance"), new OptionEditorHeading (_("Graphics Acceleration")));
3593 #endif
3594
3595 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
3596         BoolOption* bgc = new BoolOption (
3597                 "cairo-image-surface",
3598                 _("Disable Graphics Hardware Acceleration (requires restart)"),
3599                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_cairo_image_surface),
3600                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_cairo_image_surface)
3601                 );
3602
3603         Gtkmm2ext::UI::instance()->set_tip (bgc->tip_widget(), string_compose (
3604                                 _("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));
3605         add_option (_("Appearance"), bgc);
3606 #endif
3607
3608 #ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
3609         BoolOption* bgo = new BoolOption (
3610                 "buggy-gradients",
3611                 _("Possibly improve slow graphical performance (requires restart)"),
3612                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_buggy_gradients),
3613                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_buggy_gradients)
3614                 );
3615
3616         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));
3617         add_option (_("Appearance"), bgo);
3618 #endif
3619         add_option (_("Appearance"), new OptionEditorHeading (_("Graphical User Interface")));
3620
3621         add_option (_("Appearance"),
3622              new BoolOption (
3623                      "widget-prelight",
3624                      _("Highlight widgets on mouseover"),
3625                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_widget_prelight),
3626                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_widget_prelight)
3627                      ));
3628
3629         add_option (_("Appearance"),
3630              new BoolOption (
3631                      "use-tooltips",
3632                      _("Show tooltips if mouse hovers over a control"),
3633                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_tooltips),
3634                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_tooltips)
3635                      ));
3636
3637         bo = new BoolOption (
3638                         "super-rapid-clock-update",
3639                         _("Update clocks at TC Frame rate"),
3640                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
3641                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
3642                         );
3643         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3644                         _("<b>When enabled</b> clock displays are updated every Timecode Frame (fps).\n\n"
3645                                 "<b>When disabled</b> clock displays are updated only every 100ms."
3646                          ));
3647         add_option (_("Appearance"), bo);
3648
3649         add_option (_("Appearance"),
3650                         new BoolOption (
3651                                 "blink-rec-arm",
3652                                 _("Blink Rec-Arm buttons"),
3653                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_blink_rec_arm),
3654                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_blink_rec_arm)
3655                                 ));
3656
3657         add_option (_("Appearance"),
3658                         new BoolOption (
3659                                 "blink-alert-indicators",
3660                                 _("Blink Alert Indicators"),
3661                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_blink_alert_indicators),
3662                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_blink_alert_indicators)
3663                                 ));
3664
3665
3666 #ifndef __APPLE__
3667         /* font scaling does nothing with GDK/Quartz */
3668         add_option (_("Appearance"), new FontScalingOptions ());
3669 #endif
3670         add_option (_("Appearance/Editor"), new OptionEditorHeading (_("General")));
3671         add_option (_("Appearance/Editor"),
3672              new BoolOption (
3673                      "show-name-highlight",
3674                      _("Use name highlight bars in region displays (requires a restart)"),
3675                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_name_highlight),
3676                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_name_highlight)
3677                      ));
3678
3679         add_option (_("Appearance/Editor"),
3680                         new BoolOption (
3681                         "color-regions-using-track-color",
3682                         _("Region color follows track color"),
3683                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_color_regions_using_track_color),
3684                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_color_regions_using_track_color)
3685                         ));
3686
3687         add_option (_("Appearance/Editor"),
3688                         new BoolOption (
3689                         "show-region-names",
3690                         _("Show Region Names"),
3691                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_name),
3692                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_name)
3693                         ));
3694
3695 #ifndef MIXBUS // hide this setting in Mixbus. Always on, 4px
3696         ComboOption<uint32_t>* gap = new ComboOption<uint32_t> (
3697                      "vertical-region-gap",
3698                      _("Add a visual gap below Audio Regions"),
3699                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_vertical_region_gap),
3700                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_vertical_region_gap)
3701                      );
3702         gap->add (0, _("None"));
3703         gap->add (2, _("Small"));
3704         gap->add (4, _("Large"));
3705         add_option (_("Appearance/Editor"), gap);
3706 #endif
3707
3708         add_option (_("Appearance/Editor"), new OptionEditorHeading (_("Waveforms")));
3709
3710         if (!Profile->get_mixbus()) {
3711                 add_option (_("Appearance/Editor"),
3712                                 new BoolOption (
3713                                         "show-waveforms",
3714                                         _("Show waveforms in regions"),
3715                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
3716                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
3717                                         ));
3718         }  // !mixbus
3719
3720         add_option (_("Appearance/Editor"),
3721              new BoolOption (
3722                      "show-waveforms-while-recording",
3723                      _("Show waveforms while recording"),
3724                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
3725                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
3726                      ));
3727
3728         add_option (_("Appearance/Editor"),
3729                         new BoolOption (
3730                         "show-waveform-clipping",
3731                         _("Show waveform clipping"),
3732                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveform_clipping),
3733                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveform_clipping)
3734                         ));
3735
3736         add_option (_("Appearance/Editor"), new ClipLevelOptions ());
3737
3738         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
3739                 "waveform-scale",
3740                 _("Waveform scale"),
3741                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_scale),
3742                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_scale)
3743                 );
3744
3745         wfs->add (Linear, _("linear"));
3746         wfs->add (Logarithmic, _("logarithmic"));
3747
3748         add_option (_("Appearance/Editor"), wfs);
3749
3750         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
3751                 "waveform-shape",
3752                 _("Waveform shape"),
3753                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_shape),
3754                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_shape)
3755                 );
3756
3757         wfsh->add (Traditional, _("traditional"));
3758         wfsh->add (Rectified, _("rectified"));
3759
3760         add_option (_("Appearance/Editor"), wfsh);
3761
3762         add_option (_("Appearance/Editor"), new OptionEditorHeading (_("Editor Meters")));
3763
3764         add_option (_("Appearance/Editor"),
3765              new BoolOption (
3766                      "show-track-meters",
3767                      _("Show meters in track headers"),
3768                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
3769                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_track_meters)
3770                      ));
3771
3772         add_option (_("Appearance/Editor"),
3773              new BoolOption (
3774                      "editor-stereo-only-meters",
3775                      _("Limit track header meters to stereo"),
3776                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_editor_stereo_only_meters),
3777                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_editor_stereo_only_meters)
3778                      ));
3779
3780         add_option (_("Appearance/Editor"), new OptionEditorHeading (_("MIDI Regions")));
3781
3782         add_option (_("Appearance/Editor"),
3783                     new BoolOption (
3784                             "display-first-midi-bank-as-zero",
3785                             _("Display first MIDI bank/program as 0"),
3786                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
3787                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
3788                             ));
3789
3790         add_option (_("Appearance/Editor"),
3791              new BoolOption (
3792                      "never-display-periodic-midi",
3793                      _("Don't display periodic (MTC, MMC) SysEx messages in MIDI Regions"),
3794                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
3795                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
3796                      ));
3797
3798
3799         add_option (_("Appearance/Editor"),
3800                     new BoolOption (
3801                             "use-note-bars-for-velocity",
3802                             _("Show velocity horizontally inside notes"),
3803                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_note_bars_for_velocity),
3804                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_note_bars_for_velocity)
3805                             ));
3806
3807         add_option (_("Appearance/Editor"),
3808                     new BoolOption (
3809                             "use-note-color-for-velocity",
3810                             _("Use colors to show note velocity"),
3811                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_note_color_for_velocity),
3812                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_note_color_for_velocity)
3813                             ));
3814
3815         add_option (_("Appearance/Editor"), new OptionEditorBlank ());
3816
3817         /* The names of these controls must be the same as those given in MixerStrip
3818            for the actual widgets being controlled.
3819         */
3820         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
3821         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
3822         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
3823         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
3824         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
3825         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
3826         _mixer_strip_visibility.add (0, X_("VCA"), _("VCA Assigns"));
3827
3828         add_option (_("Appearance/Mixer"),
3829                 new VisibilityOption (
3830                         _("Mixer Strip"),
3831                         &_mixer_strip_visibility,
3832                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_mixer_strip_visibility),
3833                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_mixer_strip_visibility)
3834                         )
3835                 );
3836
3837         add_option (_("Appearance/Mixer"),
3838              new BoolOption (
3839                      "default-narrow_ms",
3840                      _("Use narrow strips in the mixer for new strips by default"),
3841                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_default_narrow_ms),
3842                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
3843                      ));
3844
3845         ComboOption<uint32_t>* mic = new ComboOption<uint32_t> (
3846                      "max-inline-controls",
3847                      _("Limit inline-mixer-strip controls per plugin"),
3848                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_max_inline_controls),
3849                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_max_inline_controls)
3850                      );
3851         mic->add (0, _("Unlimited"));
3852         mic->add (16,  _("16 parameters"));
3853         mic->add (32,  _("32 parameters"));
3854         mic->add (64,  _("64 parameters"));
3855         mic->add (128, _("128 parameters"));
3856         add_option (_("Appearance/Mixer"), mic);
3857
3858         add_option (_("Appearance/Mixer"), new OptionEditorBlank ());
3859
3860         add_option (_("Appearance/Toolbar"), new OptionEditorHeading (_("Main Transport Toolbar Items")));
3861
3862         add_option (_("Appearance/Toolbar"),
3863              new BoolOption (
3864                      "show-toolbar-recpunch",
3865                      _("Display Record/Punch Options"),
3866                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_recpunch),
3867                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_recpunch)
3868                      ));
3869
3870         add_option (_("Appearance/Toolbar"),
3871              new BoolOption (
3872                      "show-toolbar-monitoring",
3873                      _("Display Monitor Options"),
3874                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_monitoring),
3875                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_monitoring)
3876                      ));
3877
3878         add_option (_("Appearance/Toolbar"),
3879              new BoolOption (
3880                      "show-toolbar-selclock",
3881                      _("Display Selection Clock"),
3882                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_selclock),
3883                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_selclock)
3884                      ));
3885
3886         if (!ARDOUR::Profile->get_small_screen()) {
3887                 add_option (_("Appearance/Toolbar"),
3888                                 new BoolOption (
3889                                         "show-secondary-clock",
3890                                         _("Display Secondary Clock"),
3891                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_secondary_clock),
3892                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_secondary_clock)
3893                                         ));
3894         }
3895
3896         add_option (_("Appearance/Toolbar"),
3897              new BoolOption (
3898                      "show-mini-timeline",
3899                      _("Display Navigation Timeline"),
3900                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_mini_timeline),
3901                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_mini_timeline)
3902                      ));
3903
3904         add_option (_("Appearance/Toolbar"),
3905              new BoolOption (
3906                      "show-editor-meter",
3907                      _("Display Master Level Meter"),
3908                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
3909                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
3910                      ));
3911
3912         add_option (_("Appearance/Toolbar"),
3913                         new ColumVisibilityOption (
3914                                 "action-table-columns", _("Display Action-Buttons"), 4,
3915                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_action_table_columns),
3916                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_action_table_columns)
3917                                 )
3918                         );
3919         add_option (_("Appearance/Toolbar"), new OptionEditorBlank ());
3920
3921
3922         /* and now the theme manager */
3923
3924         add_option (_("Appearance/Theme"), new OptionEditorHeading (_("Theme")));
3925
3926         add_option (_("Appearance/Theme"), new BoolOption (
3927                                 "flat-buttons",
3928                                 _("Draw \"flat\" buttons"),
3929                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_flat_buttons),
3930                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_flat_buttons)
3931                                 ));
3932
3933         add_option (_("Appearance/Theme"), new BoolOption (
3934                                 "boxy-buttons",
3935                                 _("Draw \"boxy\" buttons"),
3936                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_boxy_buttons),
3937                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_boxy_buttons)
3938                                 ));
3939
3940         add_option (_("Appearance/Theme"), new BoolOption (
3941                                 "meter-style-led",
3942                                 _("LED meter style"),
3943                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_style_led),
3944                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_style_led)
3945                                 ));
3946
3947
3948         HSliderOption *gui_hs = new HSliderOption(
3949                         "timeline-item-gradient-depth",
3950                         _("Waveforms color gradient depth"),
3951                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_gradient_depth),
3952                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_gradient_depth),
3953                         0, 1.0, 0.05
3954                         );
3955         gui_hs->scale().set_update_policy (Gtk::UPDATE_DELAYED);
3956         add_option (_("Appearance/Theme"), gui_hs);
3957
3958         gui_hs = new HSliderOption(
3959                         "timeline-item-gradient-depth",
3960                         _("Timeline item gradient depth"),
3961                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_timeline_item_gradient_depth),
3962                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_timeline_item_gradient_depth),
3963                         0, 1.0, 0.05
3964                         );
3965         gui_hs->scale().set_update_policy (Gtk::UPDATE_DELAYED);
3966         add_option (_("Appearance/Theme"), gui_hs);
3967
3968         vector<string> icon_sets = ::get_icon_sets ();
3969         if (icon_sets.size() > 1) {
3970                 ComboOption<std::string>* io = new ComboOption<std::string> (
3971                                 "icon-set", _("Icon Set"),
3972                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_icon_set),
3973                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_icon_set)
3974                                 );
3975                 for (vector<string>::const_iterator i = icon_sets.begin (); i != icon_sets.end (); ++i) {
3976                         io->add (*i, *i);
3977                 }
3978                 add_option (_("Appearance/Theme"), io);
3979         }
3980
3981         add_option (_("Appearance/Colors"), new OptionEditorHeading (_("Colors")));
3982         add_option (_("Appearance/Colors"), new ColorThemeManager);
3983         add_option (_("Appearance/Colors"), new OptionEditorBlank ());
3984
3985         /* Quirks */
3986
3987         OptionEditorHeading* quirks_head = new OptionEditorHeading (_("Various Workarounds for Windowing Systems"));
3988
3989         quirks_head->set_note (string_compose (_("Rules for closing, minimizing, maximizing, and stay-on-top can vary \
3990 with each version of your OS, and the preferences that you've set in your OS.\n\n\
3991 You can adjust the options, below, to change how %1's windows and dialogs behave.\n\n\
3992 These settings will only take effect after %1 is restarted.\n\
3993         "), PROGRAM_NAME));
3994
3995         add_option (_("Appearance/Quirks"), quirks_head);
3996
3997         bo = new BoolOption (
3998                      "use-wm-visibility",
3999                      _("Use visibility information provided by your Window Manager/Desktop"),
4000                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_wm_visibility),
4001                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_wm_visibility)
4002                      );
4003         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4004                                 _("If you have trouble toggling between hidden Editor and Mixer windows, try changing this setting."));
4005         add_option (_("Appearance/Quirks"), bo);
4006
4007 #ifndef __APPLE__
4008         bo = new BoolOption (
4009                         "all-floating-windows-are-dialogs",
4010                         _("All floating windows are dialogs"),
4011                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_all_floating_windows_are_dialogs),
4012                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_all_floating_windows_are_dialogs)
4013                         );
4014         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4015                         _("Mark all floating windows to be type \"Dialog\" rather than using \"Utility\" for some.\nThis may help with some window managers."));
4016         add_option (_("Appearance/Quirks"), bo);
4017
4018         bo = new BoolOption (
4019                         "transients-follow-front",
4020                         _("Transient windows follow front window."),
4021                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_transients_follow_front),
4022                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_transients_follow_front)
4023                         );
4024         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4025                                 _("Make transient windows follow the front window when toggling between the editor and mixer."));
4026         add_option (_("Appearance/Quirks"), bo);
4027 #endif
4028
4029         if (!Profile->get_mixbus()) {
4030                 bo = new BoolOption (
4031                                 "floating-monitor-section",
4032                                 _("Float detached monitor-section window"),
4033                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_floating_monitor_section),
4034                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_floating_monitor_section)
4035                                 );
4036                 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4037                                         _("When detaching the monitoring section, mark it as \"Utility\" window to stay in front."));
4038                 add_option (_("Appearance/Quirks"), bo);
4039         }
4040
4041         add_option (_("Appearance/Quirks"), new OptionEditorBlank ());
4042
4043         /* VIDEO Timeline */
4044         add_option (_("Video"), new OptionEditorHeading (_("Video Server")));
4045         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
4046
4047         Widget::show_all ();
4048
4049         //trigger some parameter-changed messages which affect widget-visibility or -sensitivity
4050         parameter_changed ("send-ltc");
4051         parameter_changed ("sync-source");
4052         parameter_changed ("open-gui-after-adding-plugin");
4053
4054         XMLNode* node = ARDOUR_UI::instance()->preferences_settings();
4055         if (node) {
4056                 /* gcc4 complains about ambiguity with Gtk::Widget::set_state
4057                    (Gtk::StateType) here !!!
4058                 */
4059                 Tabbable::set_state (*node, Stateful::loading_state_version);
4060         }
4061
4062         set_current_page (_("General"));
4063 }
4064
4065 void
4066 RCOptionEditor::set_session (Session *s)
4067 {
4068         SessionHandlePtr::set_session (s);
4069         _transport_masters_widget.set_session (s);
4070 }
4071
4072 void
4073 RCOptionEditor::parameter_changed (string const & p)
4074 {
4075         OptionEditor::parameter_changed (p);
4076
4077         if (p == "use-monitor-bus") {
4078                 bool const s = Config->get_use_monitor_bus ();
4079                 if (!s) {
4080                         /* we can't use this if we don't have a monitor bus */
4081                         Config->set_solo_control_is_listen_control (false); // XXX
4082                 }
4083                 _solo_control_is_listen_control->set_sensitive (s);
4084                 _listen_position->set_sensitive (s);
4085         } else if (p == "sync-source") {
4086                 boost::shared_ptr<TransportMaster> tm (TransportMasterManager::instance().current());
4087                 if (boost::dynamic_pointer_cast<TimecodeTransportMaster> (tm)) {
4088                         _sync_framerate->set_sensitive (true);
4089                 } else {
4090                         _sync_framerate->set_sensitive (false);
4091                 }
4092         } else if (p == "send-ltc") {
4093                 bool const s = Config->get_send_ltc ();
4094                 _ltc_send_continuously->set_sensitive (s);
4095                 _ltc_volume_slider->set_sensitive (s);
4096         } else if (p == "open-gui-after-adding-plugin" || p == "show-inline-display-by-default") {
4097 #if (defined LV2_SUPPORT && defined LV2_EXTENDED)
4098                 _plugin_prefer_inline->set_sensitive (UIConfiguration::instance().get_open_gui_after_adding_plugin() && UIConfiguration::instance().get_show_inline_display_by_default());
4099 #endif
4100         } else if (p == "conceal-lv1-if-lv2-exists") {
4101                 PluginManager::instance().refresh (true);
4102         }
4103 }
4104
4105 void RCOptionEditor::plugin_scan_refresh () {
4106         PluginManager::instance().refresh();
4107 }
4108
4109 void RCOptionEditor::clear_vst_cache () {
4110         PluginManager::instance().clear_vst_cache();
4111 }
4112
4113 void RCOptionEditor::clear_vst_blacklist () {
4114         PluginManager::instance().clear_vst_blacklist();
4115 }
4116
4117 void RCOptionEditor::clear_au_cache () {
4118         PluginManager::instance().clear_au_cache();
4119 }
4120
4121 void RCOptionEditor::clear_au_blacklist () {
4122         PluginManager::instance().clear_au_blacklist();
4123 }
4124
4125 void RCOptionEditor::edit_lxvst_path () {
4126         Glib::RefPtr<Gdk::Window> win = get_parent_window ();
4127         PathsDialog *pd = new PathsDialog (
4128                 *current_toplevel(), _("Set Linux VST Search Path"),
4129                 _rc_config->get_plugin_path_lxvst(),
4130                 PluginManager::instance().get_default_lxvst_path()
4131                 );
4132         ResponseType r = (ResponseType) pd->run ();
4133         pd->hide();
4134         if (r == RESPONSE_ACCEPT) {
4135                 _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
4136
4137                 MessageDialog msg (_("Re-scan Plugins now?"),
4138                                 false /*no markup*/, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true /*modal*/);
4139                 msg.set_default_response (Gtk::RESPONSE_YES);
4140                 if (msg.run() == Gtk::RESPONSE_YES) {
4141                         msg.hide ();
4142                         plugin_scan_refresh ();
4143                 }
4144         }
4145         delete pd;
4146 }
4147
4148 void RCOptionEditor::edit_vst_path () {
4149         PathsDialog *pd = new PathsDialog (
4150                 *current_toplevel(), _("Set Windows VST Search Path"),
4151                 _rc_config->get_plugin_path_vst(),
4152                 PluginManager::instance().get_default_windows_vst_path()
4153                 );
4154         ResponseType r = (ResponseType) pd->run ();
4155         pd->hide();
4156         if (r == RESPONSE_ACCEPT) {
4157                 _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
4158                 MessageDialog msg (_("Re-scan Plugins now?"),
4159                                 false /*no markup*/, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true /*modal*/);
4160                 msg.set_default_response (Gtk::RESPONSE_YES);
4161                 if (msg.run() == Gtk::RESPONSE_YES) {
4162                         msg.hide ();
4163                         plugin_scan_refresh ();
4164                 }
4165         }
4166         delete pd;
4167 }
4168
4169 Gtk::Window*
4170 RCOptionEditor::use_own_window (bool and_fill_it)
4171 {
4172         bool new_window = !own_window ();
4173
4174         Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
4175
4176         if (win && new_window) {
4177                 win->set_name ("PreferencesWindow");
4178                 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Preferences"), this);
4179                 win->resize (1, 1);
4180                 win->set_resizable (false);
4181         }
4182
4183         return win;
4184 }
4185
4186 XMLNode&
4187 RCOptionEditor::get_state ()
4188 {
4189         XMLNode* node = new XMLNode (X_("Preferences"));
4190         node->add_child_nocopy (Tabbable::get_state());
4191         return *node;
4192 }