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