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