Selection-after-split behavior (gtk2 part)
[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 OptionEditorComponent
1158 {
1159 public:
1160         ClipLevelOptions ()
1161                 : _clip_level_adjustment (-.5, -50.0, 0.0, 0.1, 1.0) /* units of dB */
1162                 , _clip_level_slider (_clip_level_adjustment)
1163                 , _label (_("Waveform Clip Level (dBFS):"))
1164         {
1165                 _label.set_name ("OptionsLabel");
1166
1167                 _clip_level_adjustment.set_value (UIConfiguration::instance().get_waveform_clip_level ());
1168
1169                 _clip_level_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1170
1171                 _clip_level_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &ClipLevelOptions::clip_level_changed));
1172         }
1173
1174         void parameter_changed (string const & p)
1175         {
1176                 if (p == "waveform-clip-level") {
1177                         _clip_level_adjustment.set_value (UIConfiguration::instance().get_waveform_clip_level());
1178                 }
1179                 if (p == "show-waveform-clipping") {
1180                         _clip_level_slider.set_sensitive (UIConfiguration::instance().get_show_waveform_clipping ());
1181                 }
1182         }
1183
1184         void set_state_from_config ()
1185         {
1186                 parameter_changed ("waveform-clip-level");
1187                 parameter_changed ("show-waveform-clipping");
1188         }
1189
1190         void add_to_page (OptionEditorPage* p) {
1191                 add_widgets_to_page (p, &_label, &_clip_level_slider);
1192         }
1193
1194         Gtk::Widget& tip_widget() {
1195                 return _clip_level_slider;
1196         }
1197
1198 private:
1199
1200         void clip_level_changed ()
1201         {
1202                 UIConfiguration::instance().set_waveform_clip_level (_clip_level_adjustment.get_value());
1203                 /* XXX: should be triggered from the parameter changed signal */
1204                 ArdourWaveView::WaveView::set_clip_level (_clip_level_adjustment.get_value());
1205         }
1206
1207         Adjustment _clip_level_adjustment;
1208         HScale _clip_level_slider;
1209         Label _label;
1210 };
1211
1212 class BufferingOptions : public OptionEditorComponent
1213 {
1214         public:
1215                 BufferingOptions (RCConfiguration* c)
1216                         : _rc_config (c)
1217                         , _label (_("Preset:"))
1218                         , _playback ("playback-buffer-seconds", _("Playback (seconds of buffering)"),
1219                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_audio_playback_buffer_seconds),
1220                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_audio_playback_buffer_seconds),
1221                                         1, 60, 1, 4)
1222                         , _capture ("capture-buffer-seconds", _("Recording (seconds of buffering)"),
1223                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_audio_capture_buffer_seconds),
1224                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_audio_capture_buffer_seconds),
1225                                         1, 60, 1, 4)
1226                 {
1227                         // TODO use  ComboOption
1228                         vector<string> presets;
1229
1230                         /* these must match the order of the enums for BufferingPreset */
1231                         presets.push_back (_("Small sessions (4-16 tracks)"));
1232                         presets.push_back (_("Medium sessions (16-64 tracks)"));
1233                         presets.push_back (_("Large sessions (64+ tracks)"));
1234                         presets.push_back (_("Custom (set by sliders below)"));
1235
1236                         set_popdown_strings (_buffering_presets_combo, presets);
1237                         _buffering_presets_combo.signal_changed().connect (sigc::mem_fun (*this, &BufferingOptions::preset_changed));
1238
1239                         _label.set_name ("OptionsLabel");
1240                         _label.set_alignment (0, 0.5);
1241                 }
1242
1243                 void
1244                 add_to_page (OptionEditorPage* p)
1245                 {
1246                         add_widgets_to_page (p, &_label, &_buffering_presets_combo);
1247                         _playback.add_to_page (p);
1248                         _capture.add_to_page (p);
1249                 }
1250
1251                 void parameter_changed (string const & p)
1252                 {
1253                         if (p == "buffering-preset") {
1254                                 switch (_rc_config->get_buffering_preset()) {
1255                                         case Small:
1256                                                 _playback.set_sensitive (false);
1257                                                 _capture.set_sensitive (false);
1258                                                 _buffering_presets_combo.set_active (0);
1259                                                 break;
1260                                         case Medium:
1261                                                 _playback.set_sensitive (false);
1262                                                 _capture.set_sensitive (false);
1263                                                 _buffering_presets_combo.set_active (1);
1264                                                 break;
1265                                         case Large:
1266                                                 _playback.set_sensitive (false);
1267                                                 _capture.set_sensitive (false);
1268                                                 _buffering_presets_combo.set_active (2);
1269                                                 break;
1270                                         case Custom:
1271                                                 _playback.set_sensitive (true);
1272                                                 _capture.set_sensitive (true);
1273                                                 _buffering_presets_combo.set_active (3);
1274                                                 break;
1275                                 }
1276                         }
1277                         _playback.parameter_changed (p);
1278                         _capture.parameter_changed (p);
1279                 }
1280
1281                 void set_state_from_config ()
1282                 {
1283                         parameter_changed ("buffering-preset");
1284                         _playback.set_state_from_config();
1285                         _capture.set_state_from_config();
1286                 }
1287
1288                 Gtk::Widget& tip_widget() { return _buffering_presets_combo; }
1289
1290         private:
1291
1292                 void preset_changed ()
1293                 {
1294                         int index = _buffering_presets_combo.get_active_row_number ();
1295                         if (index < 0) {
1296                                 return;
1297                         }
1298                         switch (index) {
1299                                 case 0:
1300                                         _rc_config->set_buffering_preset (Small);
1301                                         break;
1302                                 case 1:
1303                                         _rc_config->set_buffering_preset (Medium);
1304                                         break;
1305                                 case 2:
1306                                         _rc_config->set_buffering_preset (Large);
1307                                         break;
1308                                 case 3:
1309                                         _rc_config->set_buffering_preset (Custom);
1310                                         break;
1311                                 default:
1312                                         error << string_compose (_("programming error: unknown buffering preset string, index = %1"), index) << endmsg;
1313                                         break;
1314                         }
1315                 }
1316
1317                 RCConfiguration* _rc_config;
1318                 Label         _label;
1319                 HSliderOption _playback;
1320                 HSliderOption _capture;
1321                 ComboBoxText  _buffering_presets_combo;
1322 };
1323
1324 class ControlSurfacesOptions : public OptionEditorMiniPage
1325 {
1326         public:
1327                 ControlSurfacesOptions ()
1328                         : _ignore_view_change (0)
1329                 {
1330                         _store = ListStore::create (_model);
1331                         _view.set_model (_store);
1332                         _view.append_column (_("Control Surface Protocol"), _model.name);
1333                         _view.get_column(0)->set_resizable (true);
1334                         _view.get_column(0)->set_expand (true);
1335                         _view.append_column_editable (_("Enable"), _model.enabled);
1336
1337                         Gtk::HBox* edit_box = manage (new Gtk::HBox);
1338                         edit_box->set_spacing(3);
1339                         edit_box->show ();
1340
1341                         Label* label = manage (new Label);
1342                         label->set_text (_("Edit the settings for selected protocol (it must be ENABLED first):"));
1343                         edit_box->pack_start (*label, false, false);
1344                         label->show ();
1345
1346                         edit_button = manage (new Button(_("Show Protocol Settings")));
1347                         edit_button->signal_clicked().connect (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_btn_clicked));
1348                         edit_box->pack_start (*edit_button, true, true);
1349                         edit_button->set_sensitive (false);
1350                         edit_button->show ();
1351
1352                         int const n = table.property_n_rows();
1353                         table.resize (n + 2, 3);
1354                         table.attach (_view, 0, 3, n, n + 1);
1355                         table.attach (*edit_box, 0, 3, n + 1, n + 2);
1356
1357                         ControlProtocolManager& m = ControlProtocolManager::instance ();
1358                         m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
1359                                         boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
1360
1361                         _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
1362                         _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
1363                         _view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::selection_changed));
1364                 }
1365
1366                 void parameter_changed (std::string const &)
1367                 {
1368
1369                 }
1370
1371                 void set_state_from_config ()
1372                 {
1373                         _store->clear ();
1374
1375                         ControlProtocolManager& m = ControlProtocolManager::instance ();
1376                         for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
1377
1378                                 if (!(*i)->mandatory) {
1379                                         TreeModel::Row r = *_store->append ();
1380                                         r[_model.name] = (*i)->name;
1381                                         r[_model.enabled] = 0 != (*i)->protocol;
1382                                         r[_model.protocol_info] = *i;
1383                                 }
1384                         }
1385                 }
1386
1387         private:
1388
1389                 void protocol_status_changed (ControlProtocolInfo* cpi) {
1390                         /* find the row */
1391                         TreeModel::Children rows = _store->children();
1392
1393                         for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
1394                                 string n = ((*x)[_model.name]);
1395
1396                                 if ((*x)[_model.protocol_info] == cpi) {
1397                                         _ignore_view_change++;
1398                                         (*x)[_model.enabled] = 0 != cpi->protocol;
1399                                         _ignore_view_change--;
1400                                         selection_changed (); // update sensitivity
1401                                         break;
1402                                 }
1403                         }
1404                 }
1405
1406                 void selection_changed ()
1407                 {
1408                         //enable the Edit button when a row is selected for editing
1409                         TreeModel::Row row = *(_view.get_selection()->get_selected());
1410                         if (row && row[_model.enabled]) {
1411                                 ControlProtocolInfo* cpi = row[_model.protocol_info];
1412                                 edit_button->set_sensitive (cpi && cpi->protocol && cpi->protocol->has_editor ());
1413                         } else {
1414                                 edit_button->set_sensitive (false);
1415                         }
1416                 }
1417
1418                 void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
1419                 {
1420                         TreeModel::Row r = *i;
1421
1422                         if (_ignore_view_change) {
1423                                 return;
1424                         }
1425
1426                         ControlProtocolInfo* cpi = r[_model.protocol_info];
1427                         if (!cpi) {
1428                                 return;
1429                         }
1430
1431                         bool const was_enabled = (cpi->protocol != 0);
1432                         bool const is_enabled = r[_model.enabled];
1433
1434
1435                         if (was_enabled != is_enabled) {
1436
1437                                 if (!was_enabled) {
1438                                         ControlProtocolManager::instance().activate (*cpi);
1439                                 } else {
1440                                         ControlProtocolManager::instance().deactivate (*cpi);
1441                                 }
1442                         }
1443
1444                         selection_changed ();
1445                 }
1446
1447                 void edit_btn_clicked ()
1448                 {
1449                         std::string name;
1450                         ControlProtocolInfo* cpi;
1451                         TreeModel::Row row;
1452
1453                         row = *(_view.get_selection()->get_selected());
1454                         if (!row[_model.enabled]) {
1455                                 return;
1456                         }
1457                         cpi = row[_model.protocol_info];
1458                         if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
1459                                 return;
1460                         }
1461                         Box* box = (Box*) cpi->protocol->get_gui ();
1462                         if (!box) {
1463                                 return;
1464                         }
1465                         if (box->get_parent()) {
1466                                 static_cast<ArdourWindow*>(box->get_parent())->present();
1467                                 return;
1468                         }
1469                         WindowTitle title (Glib::get_application_name());
1470                         title += row[_model.name];
1471                         title += _("Configuration");
1472                         /* once created, the window is managed by the surface itself (as ->get_parent())
1473                          * Surface's tear_down_gui() is called on session close, when de-activating
1474                          * or re-initializing a surface.
1475                          * tear_down_gui() hides an deletes the Window if it exists.
1476                          */
1477                         ArdourWindow* win = new ArdourWindow (*((Gtk::Window*) _view.get_toplevel()), title.get_string());
1478                         win->set_title (_("Control Protocol Settings"));
1479                         win->add (*box);
1480                         box->show ();
1481                         win->present ();
1482                 }
1483
1484                 void edit_clicked (GdkEventButton* ev)
1485                 {
1486                         if (ev->type != GDK_2BUTTON_PRESS) {
1487                                 return;
1488                         }
1489
1490                         edit_btn_clicked();
1491                 }
1492
1493                 class ControlSurfacesModelColumns : public TreeModelColumnRecord
1494         {
1495                 public:
1496
1497                         ControlSurfacesModelColumns ()
1498                         {
1499                                 add (name);
1500                                 add (enabled);
1501                                 add (protocol_info);
1502                         }
1503
1504                         TreeModelColumn<string> name;
1505                         TreeModelColumn<bool> enabled;
1506                         TreeModelColumn<ControlProtocolInfo*> protocol_info;
1507         };
1508
1509                 Glib::RefPtr<ListStore> _store;
1510                 ControlSurfacesModelColumns _model;
1511                 TreeView _view;
1512                 PBD::ScopedConnection protocol_status_connection;
1513                 uint32_t _ignore_view_change;
1514                 Gtk::Button* edit_button;
1515 };
1516
1517 class VideoTimelineOptions : public OptionEditorMiniPage
1518 {
1519         public:
1520                 VideoTimelineOptions (RCConfiguration* c)
1521                         : _rc_config (c)
1522                         , _show_video_export_info_button (_("Show Video Export Info before export"))
1523                         , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
1524                         , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
1525                         , _xjadeo_browse_button (_("Browse..."))
1526                 {
1527                         Table* t = &table;
1528                         int n = table.property_n_rows();
1529
1530                         t->attach (_show_video_export_info_button, 1, 4, n, n + 1);
1531                         _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
1532                         Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
1533                                         _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
1534                         ++n;
1535
1536                         t->attach (_show_video_server_dialog_button, 1, 4, n, n + 1);
1537                         _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
1538                         Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
1539                                         _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
1540                         ++n;
1541
1542                         t->attach (_video_advanced_setup_button, 1, 4, n, n + 1, FILL);
1543                         _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
1544                         Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
1545                                         _("<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."));
1546                         ++n;
1547
1548                         Label* l = manage (new Label (_("Video Server URL:")));
1549                         l->set_alignment (0, 0.5);
1550                         t->attach (*l, 1, 2, n, n + 1, FILL);
1551                         t->attach (_video_server_url_entry, 2, 4, n, n + 1, FILL);
1552                         Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
1553                                         _("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"));
1554                         ++n;
1555
1556                         l = manage (new Label (_("Video Folder:")));
1557                         l->set_alignment (0, 0.5);
1558                         t->attach (*l, 1, 2, n, n + 1, FILL);
1559                         t->attach (_video_server_docroot_entry, 2, 4, n, n + 1);
1560                         Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
1561                                         _("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."));
1562                         ++n;
1563
1564                         l = manage (new Label (""));
1565                         t->attach (*l, 0, 4, n, n + 1, EXPAND | FILL);
1566                         ++n;
1567
1568                         l = manage (new Label (string_compose ("<b>%1</b>", _("Video Monitor"))));
1569                         l->set_use_markup (true);
1570                         l->set_alignment (0, 0.5);
1571                         t->attach (*l, 0, 4, n, n + 1, EXPAND | FILL);
1572                         ++n;
1573
1574                         l = manage (new Label (string_compose (_("Custom Path to Video Monitor (%1) - leave empty for default:"),
1575 #ifdef __APPLE__
1576                                                         "Jadeo.app"
1577 #elif defined PLATFORM_WINDOWS
1578                                                         "xjadeo.exe"
1579 #else
1580                                                         "xjadeo"
1581 #endif
1582                                                         )));
1583                         l->set_alignment (0, 0.5);
1584                         t->attach (*l, 1, 4, n, n + 1, FILL);
1585                         ++n;
1586
1587                         t->attach (_custom_xjadeo_path, 2, 3, n, n + 1, EXPAND|FILL);
1588                         Gtkmm2ext::UI::instance()->set_tip (_custom_xjadeo_path, _("Set a custom path to the Video Monitor Executable, changing this requires a restart."));
1589                         t->attach (_xjadeo_browse_button, 3, 4, n, n + 1, FILL);
1590
1591                         _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1592                         _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1593                         _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1594                         _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1595                         _custom_xjadeo_path.signal_changed().connect (sigc::mem_fun (*this, &VideoTimelineOptions::custom_xjadeo_path_changed));
1596                         _xjadeo_browse_button.signal_clicked ().connect (sigc::mem_fun (*this, &VideoTimelineOptions::xjadeo_browse_clicked));
1597                 }
1598
1599                 void server_url_changed ()
1600                 {
1601                         _rc_config->set_video_server_url (_video_server_url_entry.get_text());
1602                 }
1603
1604                 void server_docroot_changed ()
1605                 {
1606                         _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
1607                 }
1608
1609                 void show_video_export_info_toggled ()
1610                 {
1611                         bool const x = _show_video_export_info_button.get_active ();
1612                         _rc_config->set_show_video_export_info (x);
1613                 }
1614
1615                 void show_video_server_dialog_toggled ()
1616                 {
1617                         bool const x = _show_video_server_dialog_button.get_active ();
1618                         _rc_config->set_show_video_server_dialog (x);
1619                 }
1620
1621                 void video_advanced_setup_toggled ()
1622                 {
1623                         bool const x = _video_advanced_setup_button.get_active ();
1624                         _rc_config->set_video_advanced_setup(x);
1625                 }
1626
1627                 void custom_xjadeo_path_changed ()
1628                 {
1629                         _rc_config->set_xjadeo_binary (_custom_xjadeo_path.get_text());
1630                 }
1631
1632                 void xjadeo_browse_clicked ()
1633                 {
1634                         Gtk::FileChooserDialog dialog(_("Set Video Monitor Executable"), Gtk::FILE_CHOOSER_ACTION_OPEN);
1635                         dialog.set_filename (_rc_config->get_xjadeo_binary());
1636                         dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1637                         dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
1638                         if (dialog.run () == Gtk::RESPONSE_OK) {
1639                                 const std::string& filename = dialog.get_filename();
1640                                 if (!filename.empty() && (
1641 #ifdef __APPLE__
1642                                                         Glib::file_test (filename + "/Contents/MacOS/xjadeo", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE) ||
1643 #endif
1644                                                         Glib::file_test (filename, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE)
1645                                                         )) {
1646                                         _rc_config->set_xjadeo_binary (filename);
1647                                 }
1648                         }
1649                 }
1650
1651                 void parameter_changed (string const & p)
1652                 {
1653                         if (p == "video-server-url") {
1654                                 _video_server_url_entry.set_text (_rc_config->get_video_server_url());
1655                         } else if (p == "video-server-docroot") {
1656                                 _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
1657                         } else if (p == "show-video-export-info") {
1658                                 bool const x = _rc_config->get_show_video_export_info();
1659                                 _show_video_export_info_button.set_active (x);
1660                         } else if (p == "show-video-server-dialog") {
1661                                 bool const x = _rc_config->get_show_video_server_dialog();
1662                                 _show_video_server_dialog_button.set_active (x);
1663                         } else if (p == "video-advanced-setup") {
1664                                 bool const x = _rc_config->get_video_advanced_setup();
1665                                 _video_advanced_setup_button.set_active(x);
1666                                 _video_server_docroot_entry.set_sensitive(x);
1667                                 _video_server_url_entry.set_sensitive(x);
1668                         } else if (p == "xjadeo-binary") {
1669                                 _custom_xjadeo_path.set_text (_rc_config->get_xjadeo_binary());
1670                         }
1671                 }
1672
1673                 void set_state_from_config ()
1674                 {
1675                         parameter_changed ("video-server-url");
1676                         parameter_changed ("video-server-docroot");
1677                         parameter_changed ("video-monitor-setup-dialog");
1678                         parameter_changed ("show-video-export-info");
1679                         parameter_changed ("show-video-server-dialog");
1680                         parameter_changed ("video-advanced-setup");
1681                         parameter_changed ("xjadeo-binary");
1682                 }
1683
1684         private:
1685                 RCConfiguration* _rc_config;
1686                 Entry _video_server_url_entry;
1687                 Entry _video_server_docroot_entry;
1688                 Entry _custom_xjadeo_path;
1689                 CheckButton _show_video_export_info_button;
1690                 CheckButton _show_video_server_dialog_button;
1691                 CheckButton _video_advanced_setup_button;
1692                 Button _xjadeo_browse_button;
1693 };
1694
1695 class ColumVisibilityOption : public Option
1696 {
1697         public:
1698         ColumVisibilityOption (string id, string name, uint32_t n_col, sigc::slot<uint32_t> get, sigc::slot<bool, uint32_t> set)
1699                 : Option (id, name)
1700                 , _heading (name)
1701                 , _n_col (n_col)
1702                 , _get (get)
1703                 , _set (set)
1704         {
1705                 cb = (CheckButton**) malloc (sizeof (CheckButton*) * n_col);
1706                 for (uint32_t i = 0; i < n_col; ++i) {
1707                         CheckButton* col = manage (new CheckButton (string_compose (_("Column %1"), i + 1)));
1708                         col->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &ColumVisibilityOption::column_toggled), i));
1709                         _hbox.pack_start (*col);
1710                         cb[i] = col;
1711                 }
1712                 parameter_changed (id);
1713         }
1714
1715         ~ColumVisibilityOption () {
1716                 free (cb);
1717         }
1718
1719         Gtk::Widget& tip_widget() { return _hbox; }
1720
1721         void set_state_from_config ()
1722         {
1723                 uint32_t c = _get();
1724                 for (uint32_t i = 0; i < _n_col; ++i) {
1725                         bool en = (c & (1<<i)) ? true : false;
1726                         if (cb[i]->get_active () != en) {
1727                                 cb[i]->set_active (en);
1728                         }
1729                 }
1730         }
1731
1732         void add_to_page (OptionEditorPage* p)
1733         {
1734                 _heading.add_to_page (p);
1735                 add_widget_to_page (p, &_hbox);
1736         }
1737         private:
1738
1739         void column_toggled (int b) {
1740                 uint32_t c = _get();
1741                 uint32_t cc = c;
1742                 if (cb[b]->get_active ()) {
1743                         c |= (1<<b);
1744                 } else {
1745                         c &= ~(1<<b);
1746                 }
1747                 if (cc != c) {
1748                         _set (c);
1749                 }
1750         }
1751
1752         HBox _hbox;
1753         OptionEditorHeading _heading;
1754
1755         CheckButton** cb;
1756         uint32_t _n_col;
1757         sigc::slot<uint32_t> _get;
1758         sigc::slot<bool, uint32_t> _set;
1759 };
1760
1761
1762 /** A class which allows control of visibility of some editor components usign
1763  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
1764  *  which has the correct members, but with null widget pointers.  This
1765  *  class allows the user to set visibility of the members, the details
1766  *  of which are stored in a configuration variable which can be watched
1767  *  by parts of the editor that actually contain the widgets whose visibility
1768  *  is being controlled.
1769  */
1770
1771 class VisibilityOption : public Option
1772 {
1773 public:
1774         /** @param name User-visible name for this group.
1775          *  @param g `Dummy' VisibilityGroup (as described above).
1776          *  @param get Method to get the value of the appropriate configuration variable.
1777          *  @param set Method to set the value of the appropriate configuration variable.
1778          */
1779         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1780                 : Option (g->get_state_name(), name)
1781                 , _heading (name)
1782                 , _visibility_group (g)
1783                 , _get (get)
1784                 , _set (set)
1785         {
1786                 /* Watch for changes made by the user to our members */
1787                 _visibility_group->VisibilityChanged.connect_same_thread (
1788                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1789                         );
1790         }
1791
1792         void set_state_from_config ()
1793         {
1794                 /* Set our state from the current configuration */
1795                 _visibility_group->set_state (_get ());
1796         }
1797
1798         void add_to_page (OptionEditorPage* p)
1799         {
1800                 _heading.add_to_page (p);
1801                 add_widget_to_page (p, _visibility_group->list_view ());
1802         }
1803
1804         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1805
1806 private:
1807         void changed ()
1808         {
1809                 /* The user has changed something, so reflect this change
1810                    in the RCConfiguration.
1811                 */
1812                 _set (_visibility_group->get_state_value ());
1813         }
1814
1815         OptionEditorHeading _heading;
1816         VisibilityGroup* _visibility_group;
1817         sigc::slot<std::string> _get;
1818         sigc::slot<bool, std::string> _set;
1819         PBD::ScopedConnection _visibility_group_connection;
1820 };
1821
1822
1823 class MidiPortOptions : public OptionEditorMiniPage, public sigc::trackable
1824 {
1825         public:
1826                 MidiPortOptions() {
1827
1828                         setup_midi_port_view (midi_output_view, false);
1829                         setup_midi_port_view (midi_input_view, true);
1830
1831                         OptionEditorHeading* h = new OptionEditorHeading (_("MIDI Inputs"));
1832                         h->add_to_page (this);
1833
1834                         Gtk::ScrolledWindow* scroller = manage (new Gtk::ScrolledWindow);
1835                         scroller->add (midi_input_view);
1836                         scroller->set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
1837                         scroller->set_size_request (-1, 180);
1838
1839                         int n = table.property_n_rows();
1840                         table.attach (*scroller, 0, 3, n, n + 1, FILL | EXPAND);
1841
1842                         h = new OptionEditorHeading (_("MIDI Outputs"));
1843                         h->add_to_page (this);
1844
1845                         scroller = manage (new Gtk::ScrolledWindow);
1846                         scroller->add (midi_output_view);
1847                         scroller->set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
1848                         scroller->set_size_request (-1, 180);
1849
1850                         n = table.property_n_rows();
1851                         table.attach (*scroller, 0, 3, n, n + 1, FILL | EXPAND);
1852
1853                         midi_output_view.show ();
1854                         midi_input_view.show ();
1855
1856                         table.signal_show().connect (sigc::mem_fun (*this, &MidiPortOptions::on_show));
1857                 }
1858
1859                 void parameter_changed (string const&) {}
1860                 void set_state_from_config() {}
1861
1862                 void on_show () {
1863                         refill ();
1864
1865                         AudioEngine::instance()->PortRegisteredOrUnregistered.connect (connections,
1866                                         invalidator (*this),
1867                                         boost::bind (&MidiPortOptions::refill, this),
1868                                         gui_context());
1869                         AudioEngine::instance()->MidiPortInfoChanged.connect (connections,
1870                                         invalidator (*this),
1871                                         boost::bind (&MidiPortOptions::refill, this),
1872                                         gui_context());
1873                         AudioEngine::instance()->MidiSelectionPortsChanged.connect (connections,
1874                                         invalidator (*this),
1875                                         boost::bind (&MidiPortOptions::refill, this),
1876                                         gui_context());
1877                 }
1878
1879                 void refill () {
1880
1881                         if (refill_midi_ports (true, midi_input_view)) {
1882                                 input_label.show ();
1883                         } else {
1884                                 input_label.hide ();
1885                         }
1886                         if (refill_midi_ports (false, midi_output_view)) {
1887                                 output_label.show ();
1888                         } else {
1889                                 output_label.hide ();
1890                         }
1891                 }
1892
1893         private:
1894                 PBD::ScopedConnectionList connections;
1895
1896                 /* MIDI port management */
1897                 struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
1898
1899                         MidiPortColumns () {
1900                                 add (pretty_name);
1901                                 add (music_data);
1902                                 add (control_data);
1903                                 add (selection);
1904                                 add (name);
1905                                 add (filler);
1906                         }
1907
1908                         Gtk::TreeModelColumn<std::string> pretty_name;
1909                         Gtk::TreeModelColumn<bool> music_data;
1910                         Gtk::TreeModelColumn<bool> control_data;
1911                         Gtk::TreeModelColumn<bool> selection;
1912                         Gtk::TreeModelColumn<std::string> name;
1913                         Gtk::TreeModelColumn<std::string> filler;
1914                 };
1915
1916                 MidiPortColumns midi_port_columns;
1917                 Gtk::TreeView midi_input_view;
1918                 Gtk::TreeView midi_output_view;
1919                 Gtk::Label input_label;
1920                 Gtk::Label output_label;
1921
1922                 void setup_midi_port_view (Gtk::TreeView&, bool with_selection);
1923                 bool refill_midi_ports (bool for_input, Gtk::TreeView&);
1924                 void pretty_name_edit (std::string const & path, std::string const & new_text, Gtk::TreeView*);
1925                 void midi_music_column_toggled (std::string const & path, Gtk::TreeView*);
1926                 void midi_control_column_toggled (std::string const & path, Gtk::TreeView*);
1927                 void midi_selection_column_toggled (std::string const & path, Gtk::TreeView*);
1928 };
1929
1930 void
1931 MidiPortOptions::setup_midi_port_view (Gtk::TreeView& view, bool with_selection)
1932 {
1933         int pretty_name_column;
1934         int music_column;
1935         int control_column;
1936         int selection_column;
1937         TreeViewColumn* col;
1938         Gtk::Label* l;
1939
1940         pretty_name_column = view.append_column_editable (_("Name (click to edit)"), midi_port_columns.pretty_name) - 1;
1941
1942         col = manage (new TreeViewColumn ("", midi_port_columns.music_data));
1943         col->set_alignment (ALIGN_CENTER);
1944         l = manage (new Label (_("Music Data")));
1945         set_tooltip (*l, string_compose (_("If ticked, %1 will consider this port to be a source of music performance data."), PROGRAM_NAME));
1946         col->set_widget (*l);
1947         l->show ();
1948         music_column = view.append_column (*col) - 1;
1949
1950         col = manage (new TreeViewColumn ("", midi_port_columns.control_data));
1951         col->set_alignment (ALIGN_CENTER);
1952         l = manage (new Label (_("Control Data")));
1953         set_tooltip (*l, string_compose (_("If ticked, %1 will consider this port to be a source of control data."), PROGRAM_NAME));
1954         col->set_widget (*l);
1955         l->show ();
1956         control_column = view.append_column (*col) - 1;
1957
1958         if (with_selection) {
1959                 col = manage (new TreeViewColumn (_("Follow Selection"), midi_port_columns.selection));
1960                 selection_column = view.append_column (*col) - 1;
1961                 l = manage (new Label (_("Follow Selection")));
1962                 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));
1963                 col->set_widget (*l);
1964                 l->show ();
1965         }
1966
1967         /* filler column so that the last real column doesn't expand */
1968         view.append_column ("", midi_port_columns.filler);
1969
1970         CellRendererText* pretty_name_cell = dynamic_cast<CellRendererText*> (view.get_column_cell_renderer (pretty_name_column));
1971         pretty_name_cell->property_editable() = true;
1972         pretty_name_cell->signal_edited().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::pretty_name_edit), &view));
1973
1974         CellRendererToggle* toggle_cell;
1975
1976         toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (music_column));
1977         toggle_cell->property_activatable() = true;
1978         toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_music_column_toggled), &view));
1979
1980         toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (control_column));
1981         toggle_cell->property_activatable() = true;
1982         toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_control_column_toggled), &view));
1983
1984         if (with_selection) {
1985                 toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (selection_column));
1986                 toggle_cell->property_activatable() = true;
1987                 toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_selection_column_toggled), &view));
1988         }
1989
1990         view.get_selection()->set_mode (SELECTION_NONE);
1991         view.set_tooltip_column (4); /* port "real" name */
1992         view.get_column(0)->set_resizable (true);
1993         view.get_column(0)->set_expand (true);
1994 }
1995
1996 bool
1997 MidiPortOptions::refill_midi_ports (bool for_input, Gtk::TreeView& view)
1998 {
1999         using namespace ARDOUR;
2000
2001         std::vector<string> ports;
2002
2003         AudioEngine::instance()->get_known_midi_ports (ports);
2004
2005         if (ports.empty()) {
2006                 view.hide ();
2007                 return false;
2008         }
2009
2010         Glib::RefPtr<ListStore> model = Gtk::ListStore::create (midi_port_columns);
2011
2012         for (vector<string>::const_iterator s = ports.begin(); s != ports.end(); ++s) {
2013
2014                 if (AudioEngine::instance()->port_is_mine (*s)) {
2015                         continue;
2016                 }
2017
2018                 PortManager::MidiPortInformation mpi (AudioEngine::instance()->midi_port_information (*s));
2019
2020                 if (mpi.pretty_name.empty()) {
2021                         /* vanished since get_known_midi_ports() */
2022                         continue;
2023                 }
2024
2025                 if (for_input != mpi.input) {
2026                         continue;
2027                 }
2028
2029                 TreeModel::Row row = *(model->append());
2030
2031                 row[midi_port_columns.pretty_name] = mpi.pretty_name;
2032                 row[midi_port_columns.music_data] = mpi.properties & MidiPortMusic;
2033                 row[midi_port_columns.control_data] = mpi.properties & MidiPortControl;
2034                 row[midi_port_columns.selection] = mpi.properties & MidiPortSelection;
2035                 row[midi_port_columns.name] = *s;
2036         }
2037
2038         view.set_model (model);
2039
2040         return true;
2041 }
2042
2043 void
2044 MidiPortOptions::midi_music_column_toggled (string const & path, TreeView* view)
2045 {
2046         TreeIter iter = view->get_model()->get_iter (path);
2047
2048         if (!iter) {
2049                 return;
2050         }
2051
2052         bool new_value = ! bool ((*iter)[midi_port_columns.music_data]);
2053
2054         /* don't reset model - wait for MidiPortInfoChanged signal */
2055
2056         if (new_value) {
2057                 ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortMusic);
2058         } else {
2059                 ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortMusic);
2060         }
2061 }
2062
2063 void
2064 MidiPortOptions::midi_control_column_toggled (string const & path, TreeView* view)
2065 {
2066         TreeIter iter = view->get_model()->get_iter (path);
2067
2068         if (!iter) {
2069                 return;
2070         }
2071
2072         bool new_value = ! bool ((*iter)[midi_port_columns.control_data]);
2073
2074         /* don't reset model - wait for MidiPortInfoChanged signal */
2075
2076         if (new_value) {
2077                 ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortControl);
2078         } else {
2079                 ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortControl);
2080         }
2081 }
2082
2083 void
2084 MidiPortOptions::midi_selection_column_toggled (string const & path, TreeView* view)
2085 {
2086         TreeIter iter = view->get_model()->get_iter (path);
2087
2088         if (!iter) {
2089                 return;
2090         }
2091
2092         bool new_value = ! bool ((*iter)[midi_port_columns.selection]);
2093
2094         /* don't reset model - wait for MidiSelectionPortsChanged signal */
2095
2096         if (new_value) {
2097                 ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortSelection);
2098         } else {
2099                 ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.name], MidiPortSelection);
2100         }
2101 }
2102
2103 void
2104 MidiPortOptions::pretty_name_edit (std::string const & path, string const & new_text, Gtk::TreeView* view)
2105 {
2106         TreeIter iter = view->get_model()->get_iter (path);
2107
2108         if (!iter) {
2109                 return;
2110         }
2111
2112         AudioEngine::instance()->set_midi_port_pretty_name ((*iter)[midi_port_columns.name], new_text);
2113 }
2114
2115 /*============*/
2116
2117
2118 RCOptionEditor::RCOptionEditor ()
2119         : OptionEditorContainer (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
2120         , Tabbable (*this, _("Preferences")
2121 #ifdef MIXBUS
2122                         , false // detached by default (first start, no instant.xml)
2123 #endif
2124                         ) /* pack self-as-vbox into tabbable */
2125         , _rc_config (Config)
2126         , _mixer_strip_visibility ("mixer-element-visibility")
2127 {
2128         UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &RCOptionEditor::parameter_changed));
2129
2130         /* MISC */
2131
2132         uint32_t hwcpus = hardware_concurrency ();
2133         BoolOption* bo;
2134
2135         if (hwcpus > 1) {
2136                 add_option (_("General"), new OptionEditorHeading (_("DSP CPU Utilization")));
2137
2138                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
2139                                 "processor-usage",
2140                                 _("Signal processing uses"),
2141                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
2142                                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
2143                                 );
2144
2145                 procs->add (-1, _("all but one processor"));
2146                 procs->add (0, _("all available processors"));
2147
2148                 for (uint32_t i = 1; i <= hwcpus; ++i) {
2149                         procs->add (i, string_compose (P_("%1 processor", "%1 processors", i), i));
2150                 }
2151
2152                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
2153
2154                 add_option (_("General"), procs);
2155         }
2156
2157         /* Image cache size */
2158         add_option (_("General"), new OptionEditorHeading (_("Memory Usage")));
2159
2160         HSliderOption *sics = new HSliderOption ("waveform-cache-size",
2161                         _("Waveform image cache size (megabytes)"),
2162                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_cache_size),
2163                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_cache_size),
2164                         1, 1024, 10 /* 1 MB to 1GB in steps of 10MB */
2165                         );
2166         sics->scale().set_digits (0);
2167         Gtkmm2ext::UI::instance()->set_tip (
2168                         sics->tip_widget(),
2169                  _("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
2170         add_option (_("General"), sics);
2171
2172         add_option (_("General"), new OptionEditorHeading (_("Engine")));
2173
2174         add_option (_("General"),
2175              new BoolOption (
2176                      "try-autostart-engine",
2177                      _("Try to auto-launch audio/midi engine"),
2178                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_try_autostart_engine),
2179                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_try_autostart_engine)
2180                      ));
2181
2182         add_option (_("General"), new OptionEditorHeading (_("Automation")));
2183
2184         add_option (_("General"),
2185              new SpinOption<double> (
2186                      "automation-thinning-factor",
2187                      _("Thinning factor (larger value => less data)"),
2188                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
2189                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
2190                      0, 1000, 1, 20
2191                      ));
2192
2193         add_option (_("General"),
2194              new SpinOption<double> (
2195                      "automation-interval-msecs",
2196                      _("Automation sampling interval (milliseconds)"),
2197                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
2198                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
2199                      1, 1000, 1, 20
2200                      ));
2201
2202         add_option (_("General"), new OptionEditorHeading (_("Tempo")));
2203
2204         bo = new BoolOption (
2205                 "allow-non-quarter-pulse",
2206                 _("Allow non quarter-note pulse"),
2207                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_allow_non_quarter_pulse),
2208                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_allow_non_quarter_pulse)
2209                 );
2210         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2211                                             string_compose (_("<b>When enabled</b> %1 will allow tempo to be expressed in divisions per minute\n"
2212                                                               "<b>When disabled</b> %1 will only allow tempo to be expressed in quarter notes per minute"),
2213                                                             PROGRAM_NAME));
2214         add_option (_("General"), bo);
2215
2216         if (!ARDOUR::Profile->get_mixbus()) {
2217                 add_option (_("General"), new OptionEditorHeading (_("GUI Lock")));
2218                 /* Lock GUI timeout */
2219
2220                 HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2221                                 _("Lock timeout (seconds)"),
2222                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_lock_gui_after_seconds),
2223                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_lock_gui_after_seconds),
2224                                 0, 1000, 1, 10
2225                                 );
2226                 slts->scale().set_digits (0);
2227                 Gtkmm2ext::UI::instance()->set_tip (
2228                                 slts->tip_widget(),
2229                                 _("Lock GUI after this many idle seconds (zero to never lock)"));
2230                 add_option (_("General"), slts);
2231         } // !mixbus
2232
2233         add_option (_("General/Session"), new OptionEditorHeading (S_("Options|Undo")));
2234
2235         add_option (_("General/Session"), new UndoOptions (_rc_config));
2236
2237         add_option (_("General/Session"),
2238              new BoolOption (
2239                      "verify-remove-last-capture",
2240                      _("Verify removal of last capture"),
2241                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
2242                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
2243                      ));
2244
2245         add_option (_("General/Session"), new OptionEditorHeading (_("Session Management")));
2246
2247         add_option (_("General/Session"),
2248              new BoolOption (
2249                      "periodic-safety-backups",
2250                      _("Make periodic backups of the session file"),
2251                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
2252                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
2253                      ));
2254
2255         add_option (_("General/Session"),
2256              new BoolOption (
2257                      "only-copy-imported-files",
2258                      _("Always copy imported files"),
2259                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_only_copy_imported_files),
2260                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_only_copy_imported_files)
2261                      ));
2262
2263         add_option (_("General/Session"), new DirectoryOption (
2264                             X_("default-session-parent-dir"),
2265                             _("Default folder for new sessions:"),
2266                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
2267                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
2268                             ));
2269
2270         add_option (_("General/Session"),
2271              new SpinOption<uint32_t> (
2272                      "max-recent-sessions",
2273                      _("Maximum number of recent sessions"),
2274                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
2275                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
2276                      0, 1000, 1, 20
2277                      ));
2278
2279
2280 #if ENABLE_NLS
2281
2282         add_option (_("General/Translation"), new OptionEditorHeading (_("Internationalization")));
2283
2284         bo = new BoolOption (
2285                         "enable-translation",
2286                         _("Use translations"),
2287                         sigc::ptr_fun (ARDOUR::translations_are_enabled),
2288                         sigc::ptr_fun (ARDOUR::set_translations_enabled)
2289                         );
2290
2291         bo->set_note (string_compose (_("These settings will only take effect after %1 is restarted (if available for your language preferences)."), PROGRAM_NAME));
2292
2293         add_option (_("General/Translation"), bo);
2294
2295         parameter_changed ("enable-translation");
2296 #endif // ENABLE_NLS
2297
2298
2299         /* EDITOR */
2300
2301         add_option (_("Editor"), new OptionEditorHeading (_("General")));
2302
2303         bo = new BoolOption (
2304                      "name-new-markers",
2305                      _("Prompt for new marker names"),
2306                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
2307                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
2308                 );
2309         add_option (_("Editor"), bo);
2310         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."
2311                                                                 "\n\nYou can always rename markers by right-clicking on them"));
2312
2313         add_option (_("Editor"),
2314              new BoolOption (
2315                      "draggable-playhead",
2316                      _("Allow dragging of playhead"),
2317                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead),
2318                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead)
2319                      ));
2320
2321         ComboOption<float>* dps = new ComboOption<float> (
2322                      "draggable-playhead-speed",
2323                      _("Playhead dragging speed (%)"),
2324                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead_speed),
2325                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead_speed)
2326                      );
2327         dps->add (0.05, _("5%"));
2328         dps->add (0.1, _("10%"));
2329         dps->add (0.25, _("25%"));
2330         dps->add (0.5, _("50%"));
2331         dps->add (1.0, _("100%"));
2332         add_option (_("Editor"), dps);
2333
2334         ComboOption<float>* eet = new ComboOption<float> (
2335                      "extra-ui-extents-time",
2336                      _("Limit zooming & summary view to X minutes beyond session extents"),
2337                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_extra_ui_extents_time),
2338                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_extra_ui_extents_time)
2339                      );
2340         eet->add (1, _("1 minute"));
2341         eet->add (2, _("2 minutes"));
2342         eet->add (20, _("20 minutes"));
2343         eet->add (60, _("1 hour"));
2344         eet->add (60*2, _("2 hours"));
2345         eet->add (60*24, _("24 hours"));
2346         add_option (_("Editor"), eet);
2347
2348         if (!Profile->get_mixbus()) {
2349
2350                 add_option (_("Editor"),
2351                                 new BoolOption (
2352                                         "use-mouse-position-as-zoom-focus-on-scroll",
2353                                         _("Zoom to mouse position when zooming with scroll wheel"),
2354                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_mouse_position_as_zoom_focus_on_scroll),
2355                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_mouse_position_as_zoom_focus_on_scroll)
2356                                         ));
2357         }  // !mixbus
2358
2359         add_option (_("Editor"),
2360                     new BoolOption (
2361                             "use-time-rulers-to-zoom-with-vertical-drag",
2362                             _("Zoom with vertical drag in rulers"),
2363                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_time_rulers_to_zoom_with_vertical_drag),
2364                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_time_rulers_to_zoom_with_vertical_drag)
2365                             ));
2366
2367         add_option (_("Editor"),
2368                     new BoolOption (
2369                             "use-double-click-to-zoom-to-selection",
2370                             _("Double click zooms to selection"),
2371                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_double_click_to_zoom_to_selection),
2372                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_double_click_to_zoom_to_selection)
2373                             ));
2374
2375         add_option (_("Editor"),
2376                     new BoolOption (
2377                             "update-editor-during-summary-drag",
2378                             _("Update editor window during drags of the summary"),
2379                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
2380                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
2381                             ));
2382
2383         add_option (_("Editor"),
2384             new BoolOption (
2385                     "autoscroll-editor",
2386                     _("Auto-scroll editor window when dragging near its edges"),
2387                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
2388                     sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
2389                     ));
2390
2391         add_option (_("Editor"),
2392              new BoolComboOption (
2393                      "show-region-gain-envelopes",
2394                      _("Show gain envelopes in audio regions"),
2395                      _("in all modes"),
2396                      _("only in Draw and Internal Edit modes"),
2397                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
2398                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
2399                      ));
2400
2401         add_option (_("Editor"), new OptionEditorHeading (_("Editor Behavior")));
2402
2403         add_option (_("Editor"),
2404              new BoolOption (
2405                      "automation-follows-regions",
2406                      _("Move relevant automation when audio regions are moved"),
2407                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
2408                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
2409                      ));
2410
2411         bo = new BoolOption (
2412                      "new-automation-points-on-lane",
2413                      _("Ignore Y-axis click position when adding new automation-points"),
2414                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_new_automation_points_on_lane),
2415                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_new_automation_points_on_lane)
2416                      );
2417         add_option (_("Editor"), bo);
2418         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2419                         _("<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."));
2420
2421         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
2422                         "default-fade-shape",
2423                         _("Default fade shape"),
2424                         sigc::mem_fun (*_rc_config,
2425                                 &RCConfiguration::get_default_fade_shape),
2426                         sigc::mem_fun (*_rc_config,
2427                                 &RCConfiguration::set_default_fade_shape)
2428                         );
2429
2430         fadeshape->add (FadeLinear,
2431                         _("Linear (for highly correlated material)"));
2432         fadeshape->add (FadeConstantPower, _("Constant power"));
2433         fadeshape->add (FadeSymmetric, _("Symmetric"));
2434         fadeshape->add (FadeSlow, _("Slow"));
2435         fadeshape->add (FadeFast, _("Fast"));
2436
2437         add_option (_("Editor"), fadeshape);
2438
2439         ComboOption<RegionEquivalence> *eqv = new ComboOption<RegionEquivalence> (
2440                      "region-equivalence",
2441                      _("Regions in active edit groups are edited together"),
2442                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_equivalence),
2443                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_equivalence)
2444                      );
2445
2446         eqv->add (Overlap, _("whenever they overlap in time"));
2447         eqv->add (Enclosed, _("if either encloses the other"));
2448         eqv->add (Exact, _("only if they have identical length, position and origin"));
2449
2450         add_option (_("Editor"), eqv);
2451
2452         ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
2453                 "layer-model",
2454                 _("Layering model"),
2455                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
2456                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
2457                 );
2458
2459         lm->add (LaterHigher, _("later is higher"));
2460         lm->add (Manual, _("manual layering"));
2461         add_option (_("Editor"), lm);
2462
2463         add_option (_("Editor"), new OptionEditorHeading (_("Split/Separate")));
2464
2465         ComboOption<RangeSelectionAfterSplit> *rras = new ComboOption<RangeSelectionAfterSplit> (
2466                     "range-selection-after-separate",
2467                     _("After a Separate operation, in Range mode"),
2468                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_range_selection_after_split),
2469                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_range_selection_after_split));
2470
2471         rras->add(ClearSel, _("Clear the Range Selection"));
2472         rras->add(PreserveSel, _("Preserve the Range Selection"));
2473         rras->add(ForceSel, _("Force-Select the regions under the range. (this might cause a tool change)"));
2474         add_option (_("Editor"), rras);
2475
2476         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
2477                     "region-selection-after-split",
2478                     _("After a Split operation, in Object mode"),
2479                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
2480                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
2481
2482         // TODO: decide which of these modes are really useful
2483         rsas->add(None, _("Clear the Selected Regions"));
2484         rsas->add(NewlyCreatedLeft, _("Select only the newly-created regions BEFORE the split point"));
2485         rsas->add(NewlyCreatedRight, _("Select only the newly-created regions AFTER the split point"));
2486         rsas->add(NewlyCreatedBoth, _("Select the newly-created regions"));
2487         // rsas->add(Existing, _("unmodified regions in the existing selection"));
2488         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
2489         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
2490         rsas->add(ExistingNewlyCreatedBoth, _("Preserve the existing selection, AND select all newly-created regions"));
2491
2492         add_option (_("Editor"), rsas);
2493
2494         add_option (_("Editor/Snap"), new OptionEditorHeading (_("General Snap options:")));
2495
2496         add_option (_("Editor/Snap"),
2497                     new SpinOption<uint32_t> (
2498                             "snap-threshold",
2499                             _("Snap Threshold (pixels)"),
2500                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_threshold),
2501                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_threshold),
2502                             10, 200,
2503                             1, 10
2504                             ));
2505
2506         add_option (_("Editor/Snap"),
2507              new BoolOption (
2508                      "show-snapped-cursor",
2509                      _("Show \"snapped cursor\""),
2510                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_snapped_cursor),
2511                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_snapped_cursor)
2512                      ));
2513
2514         add_option (_("Editor/Snap"),
2515              new BoolOption (
2516                      "rubberbanding-snaps-to-grid",
2517                      _("Snap rubberband selection to grid"),
2518                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
2519                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
2520                      ));
2521
2522         add_option (_("Editor/Snap"),
2523              new BoolOption (
2524                      "grid-follows-internal",
2525                      _("Grid switches to alternate selection for Internal Edit tools"),
2526                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_grid_follows_internal),
2527                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_grid_follows_internal)
2528                      ));
2529
2530         add_option (_("Editor/Snap"),
2531              new BoolOption (
2532                      "rulers-follow-grid",
2533                      _("Rulers automatically change to follow the Grid mode selection"),
2534                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rulers_follow_grid),
2535                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rulers_follow_grid)
2536                      ));
2537
2538         add_option (_("Editor/Snap"), new OptionEditorHeading (_("When \"Snap\" is enabled, snap to:")));
2539
2540
2541         add_option (_("Editor/Snap"),
2542              new BoolOption (
2543                      "snap-to-marks",
2544                      _("Markers"),
2545                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_marks),
2546                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_marks)
2547                      ));
2548
2549         add_option (_("Editor/Snap"),
2550              new BoolOption (
2551                      "snap-to-region-sync",
2552                      _("Region Sync Points"),
2553                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_sync),
2554                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_sync)
2555                      ));
2556
2557         add_option (_("Editor/Snap"),
2558              new BoolOption (
2559                      "snap-to-region-start",
2560                      _("Region Starts"),
2561                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_start),
2562                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_start)
2563                      ));
2564
2565         add_option (_("Editor/Snap"),
2566              new BoolOption (
2567                      "snap-to-region-end",
2568                      _("Region Ends"),
2569                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_end),
2570                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_end)
2571                      ));
2572
2573         add_option (_("Editor/Snap"),
2574              new BoolOption (
2575                      "snap-to-grid",
2576                      _("Grid"),
2577                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_grid),
2578                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_grid)
2579                      ));
2580
2581         add_option (_("Editor/Modifiers"), new OptionEditorHeading (_("Keyboard Modifiers")));
2582         add_option (_("Editor/Modifiers"), new KeyboardOptions);
2583         add_option (_("Editor/Modifiers"), new OptionEditorBlank ());
2584
2585         /* MIXER -- SOLO AND MUTE */
2586
2587         add_option (_("Mixer"), new OptionEditorHeading (_("Solo")));
2588
2589         _solo_control_is_listen_control = new BoolOption (
2590                 "solo-control-is-listen-control",
2591                 _("Solo controls are Listen controls"),
2592                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
2593                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
2594                 );
2595
2596         add_option (_("Mixer"), _solo_control_is_listen_control);
2597
2598         add_option (_("Mixer"),
2599              new BoolOption (
2600                      "exclusive-solo",
2601                      _("Exclusive solo"),
2602                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2603                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2604                      ));
2605
2606         add_option (_("Mixer"),
2607              new BoolOption (
2608                      "show-solo-mutes",
2609                      _("Show solo muting"),
2610                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2611                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2612                      ));
2613
2614         add_option (_("Mixer"),
2615              new BoolOption (
2616                      "solo-mute-override",
2617                      _("Soloing overrides muting"),
2618                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2619                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2620                      ));
2621
2622         add_option (_("Mixer"),
2623              new FaderOption (
2624                      "solo-mute-gain",
2625                      _("Solo-in-place mute cut (dB)"),
2626                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
2627                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
2628                      ));
2629
2630         _listen_position = new ComboOption<ListenPosition> (
2631                 "listen-position",
2632                 _("Listen Position"),
2633                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
2634                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
2635                 );
2636
2637         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
2638         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
2639
2640         add_option (_("Mixer"), _listen_position);
2641
2642         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
2643                 "pfl-position",
2644                 _("PFL signals come from"),
2645                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
2646                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
2647                 );
2648
2649         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2650         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2651
2652         add_option (_("Mixer"), pp);
2653
2654         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2655                 "afl-position",
2656                 _("AFL signals come from"),
2657                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2658                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2659                 );
2660
2661         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2662         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2663
2664         add_option (_("Mixer"), pa);
2665
2666         add_option (_("Mixer"), new OptionEditorHeading (_("Default Track / Bus Muting Options")));
2667
2668         add_option (_("Mixer"),
2669              new BoolOption (
2670                      "mute-affects-pre-fader",
2671                      _("Mute affects pre-fader sends"),
2672                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2673                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2674                      ));
2675
2676         add_option (_("Mixer"),
2677              new BoolOption (
2678                      "mute-affects-post-fader",
2679                      _("Mute affects post-fader sends"),
2680                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2681                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2682                      ));
2683
2684         add_option (_("Mixer"),
2685              new BoolOption (
2686                      "mute-affects-control-outs",
2687                      _("Mute affects control outputs"),
2688                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2689                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2690                      ));
2691
2692         add_option (_("Mixer"),
2693              new BoolOption (
2694                      "mute-affects-main-outs",
2695                      _("Mute affects main outputs"),
2696                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2697                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2698                      ));
2699
2700
2701         if (!ARDOUR::Profile->get_mixbus()) {
2702                 add_option (_("Mixer"), new OptionEditorHeading (_("Send Routing")));
2703                 add_option (_("Mixer"),
2704                                 new BoolOption (
2705                                         "link-send-and-route-panner",
2706                                         _("Link panners of Aux and External Sends with main panner by default"),
2707                                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2708                                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2709                                         ));
2710         }
2711
2712         /* Signal Flow */
2713
2714         add_option (_("Signal Flow"), new OptionEditorHeading (_("Monitoring")));
2715
2716         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
2717                 "monitoring-model",
2718                 _("Record monitoring handled by"),
2719                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
2720                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
2721                 );
2722
2723         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
2724                 mm->add (HardwareMonitoring, _("via Audio Driver"));
2725         }
2726
2727         string prog (PROGRAM_NAME);
2728         boost::algorithm::to_lower (prog);
2729         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
2730         mm->add (ExternalMonitoring, _("audio hardware"));
2731
2732         add_option (_("Signal Flow"), mm);
2733
2734         bo = new BoolOption (
2735                      "tape-machine-mode",
2736                      _("Tape machine mode"),
2737                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
2738                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
2739                      );
2740         add_option (_("Signal Flow"), bo);
2741         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2742                         string_compose (_("<b>When enabled</b> %1 will not monitor a track's input if the transport is stopped."),
2743                                         PROGRAM_NAME));
2744
2745         if (!Profile->get_mixbus()) {
2746
2747                 add_option (_("Signal Flow"), new OptionEditorHeading (_("Track and Bus Connections")));
2748
2749                 bo = new BoolOption (
2750                                         "auto-connect-standard-busses",
2751                                         _("Auto-connect main output (master or monitor) bus to physical ports"),
2752                                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
2753                                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
2754                                         );
2755                 add_option (_("Signal Flow"), bo);
2756                 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2757                         _("<b>When enabled</b> the main output bus is auto-connected to the first N physical ports. "
2758                                 "If the session has a monitor-section, the monitor-bus output is conneced the the hardware playback ports, "
2759                                 "otherwise the master-bus output is directly used for playback."));
2760
2761                 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
2762                                 "input-auto-connect",
2763                                 _("Connect track inputs"),
2764                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
2765                                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
2766                                 );
2767
2768                 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
2769                 iac->add (ManualConnect, _("manually"));
2770
2771                 add_option (_("Signal Flow"), iac);
2772
2773                 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
2774                                 "output-auto-connect",
2775                                 _("Connect track and bus outputs"),
2776                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
2777                                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
2778                                 );
2779
2780                 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
2781                 oac->add (AutoConnectMaster, _("automatically to master bus"));
2782                 oac->add (ManualConnect, _("manually"));
2783
2784                 add_option (_("Signal Flow"), oac);
2785
2786                 bo = new BoolOption (
2787                                 "strict-io",
2788                                 _("Use 'Strict-I/O' for new tracks or busses"),
2789                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_strict_io),
2790                                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_strict_io)
2791                                 );
2792
2793                 add_option (_("Signal Flow"), bo);
2794                 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2795                                 _("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."));
2796
2797         }  // !mixbus
2798
2799
2800         /* AUDIO */
2801
2802         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
2803
2804         add_option (_("Audio"), new BufferingOptions (_rc_config));
2805
2806         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
2807
2808         add_option (_("Audio"),
2809              new BoolOption (
2810                      "denormal-protection",
2811                      _("Use DC bias to protect against denormals"),
2812                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
2813                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
2814                      ));
2815
2816         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
2817                 "denormal-model",
2818                 _("Processor handling"),
2819                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
2820                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
2821                 );
2822
2823         int dmsize = 1;
2824         dm->add (DenormalNone, _("no processor handling"));
2825
2826         FPU* fpu = FPU::instance();
2827
2828         if (fpu->has_flush_to_zero()) {
2829                 ++dmsize;
2830                 dm->add (DenormalFTZ, _("use FlushToZero"));
2831         } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
2832                 _rc_config->set_denormal_model(DenormalNone);
2833         }
2834
2835         if (fpu->has_denormals_are_zero()) {
2836                 ++dmsize;
2837                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
2838         } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
2839                 _rc_config->set_denormal_model(DenormalNone);
2840         }
2841
2842         if (fpu->has_flush_to_zero() && fpu->has_denormals_are_zero()) {
2843                 ++dmsize;
2844                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
2845         } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
2846                 _rc_config->set_denormal_model(DenormalNone);
2847         }
2848
2849         if (dmsize == 1) {
2850                 dm->set_sensitive(false);
2851         }
2852
2853         add_option (_("Audio"), dm);
2854
2855         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
2856
2857         add_option (_("Audio"),
2858              new BoolOption (
2859                      "auto-analyse-audio",
2860                      _("Enable automatic analysis of audio"),
2861                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
2862                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
2863                      ));
2864
2865         add_option (_("Audio"),
2866              new BoolOption (
2867                      "replicate-missing-region-channels",
2868                      _("Replicate missing region channels"),
2869                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
2870                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
2871                      ));
2872
2873         /* MIDI */
2874
2875         add_option (_("MIDI"), new OptionEditorHeading (_("Buffering")));
2876
2877         add_option (_("MIDI"),
2878                     new SpinOption<float> (
2879                             "midi-readahead",
2880                             _("MIDI read-ahead time (seconds)"),
2881                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2882                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2883                             0.1, 10, 0.05, 1,
2884                             "", 1.0, 2
2885                             ));
2886
2887         add_option (_("MIDI"), new OptionEditorHeading (_("Session")));
2888
2889         add_option (_("MIDI"),
2890              new SpinOption<int32_t> (
2891                      "initial-program-change",
2892                      _("Initial program change"),
2893                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2894                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2895                      -1, 65536, 1, 10
2896                      ));
2897
2898         add_option (_("MIDI"), new OptionEditorHeading (_("Audition")));
2899
2900         add_option (_("MIDI"),
2901              new BoolOption (
2902                      "sound-midi-notes",
2903                      _("Sound MIDI notes as they are selected in the editor"),
2904                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
2905                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
2906                      ));
2907
2908         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2909                 "midi-audition-synth-uri",
2910                 _("MIDI Audition Synth (LV2)"),
2911                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2912                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2913                 );
2914
2915         audition_synth->add(X_(""), _("None"));
2916         PluginInfoList all_plugs;
2917         PluginManager& manager (PluginManager::instance());
2918 #ifdef LV2_SUPPORT
2919         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2920
2921         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2922                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2923                 if (!(*i)->is_instrument()) continue;
2924                 if ((*i)->type != ARDOUR::LV2) continue;
2925                 if ((*i)->name.length() > 46) {
2926                         audition_synth->add((*i)->unique_id, (*i)->name.substr (0, 44) + "...");
2927                 } else {
2928                         audition_synth->add((*i)->unique_id, (*i)->name);
2929                 }
2930         }
2931 #endif
2932
2933         add_option (_("MIDI"), audition_synth);
2934
2935         /* Click */
2936
2937         add_option (_("Metronome"), new OptionEditorHeading (_("Metronome")));
2938         add_option (_("Metronome"), new ClickOptions (_rc_config));
2939         add_option (_("Metronome"), new OptionEditorHeading (_("Options")));
2940
2941         bo = new BoolOption (
2942                         "click-record-only",
2943                         _("Enable metronome only while recording"),
2944                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_record_only),
2945                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_record_only)
2946                         );
2947
2948         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2949                         string_compose (_("<b>When enabled</b> the metronome will remain silent if %1 is <b>not recording</b>."), PROGRAM_NAME));
2950         add_option (_("Metronome"), bo);
2951         add_option (_("Metronome"), new OptionEditorBlank ());
2952
2953
2954         /* Meters */
2955
2956         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2957
2958         ComboOption<float>* mht = new ComboOption<float> (
2959                 "meter-hold",
2960                 _("Peak hold time"),
2961                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_hold),
2962                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_hold)
2963                 );
2964
2965         mht->add (MeterHoldOff, _("off"));
2966         mht->add (MeterHoldShort, _("short"));
2967         mht->add (MeterHoldMedium, _("medium"));
2968         mht->add (MeterHoldLong, _("long"));
2969
2970         add_option (S_("Preferences|Metering"), mht);
2971
2972         ComboOption<float>* mfo = new ComboOption<float> (
2973                 "meter-falloff",
2974                 _("DPM fall-off"),
2975                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2976                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2977                 );
2978
2979         mfo->add (METER_FALLOFF_OFF,      _("off"));
2980         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2981         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2982         mfo->add (METER_FALLOFF_SLOWISH,  _("moderate [12.0dB/sec] (DIN)"));
2983         mfo->add (METER_FALLOFF_MODERATE, _("medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2984         mfo->add (METER_FALLOFF_MEDIUM,   _("fast [20dB/sec]"));
2985         mfo->add (METER_FALLOFF_FAST,     _("very fast [32dB/sec]"));
2986
2987         add_option (S_("Preferences|Metering"), mfo);
2988
2989         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2990                 "meter-line-up-level",
2991                 _("Meter line-up level; 0dBu"),
2992                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_level),
2993                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_level)
2994                 );
2995
2996         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2997         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2998         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2999         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3000
3001         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."));
3002
3003         add_option (S_("Preferences|Metering"), mlu);
3004
3005         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
3006                 "meter-line-up-din",
3007                 _("IEC1/DIN Meter line-up level; 0dBu"),
3008                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_din),
3009                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_din)
3010                 );
3011
3012         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
3013         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
3014         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
3015         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
3016
3017         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
3018
3019         add_option (S_("Preferences|Metering"), mld);
3020
3021         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
3022                 "meter-vu-standard",
3023                 _("VU Meter standard"),
3024                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_vu_standard),
3025                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_vu_standard)
3026                 );
3027
3028         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
3029         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
3030         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
3031         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
3032
3033         add_option (S_("Preferences|Metering"), mvu);
3034
3035         HSliderOption *mpks = new HSliderOption("meter-peak",
3036                         _("Peak indicator threshold [dBFS]"),
3037                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_peak),
3038                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_peak),
3039                         -10, 0, .1, .1
3040                         );
3041
3042         Gtkmm2ext::UI::instance()->set_tip (
3043                         mpks->tip_widget(),
3044                         _("Specify the audio signal level in dBFS at and above which the meter-peak indicator will flash red."));
3045
3046         add_option (S_("Preferences|Metering"), mpks);
3047
3048         OptionEditorHeading* default_meter_head = new OptionEditorHeading (_("Default Meter Types"));
3049         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."));
3050
3051         add_option (S_("Preferences|Metering"), default_meter_head);
3052
3053         ComboOption<MeterType>* mtm = new ComboOption<MeterType> (
3054                 "meter-type-master",
3055                 _("Default Meter Type for Master Bus"),
3056                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_master),
3057                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_master)
3058                 );
3059         mtm->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3060         mtm->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3061         mtm->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3062         mtm->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3063         mtm->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3064         mtm->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3065         mtm->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3066         mtm->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3067
3068         add_option (S_("Preferences|Metering"), mtm);
3069
3070
3071         ComboOption<MeterType>* mtb = new ComboOption<MeterType> (
3072                 "meter-type-bus",
3073                 _("Default meter type for busses"),
3074                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_bus),
3075                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_bus)
3076                 );
3077         mtb->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3078         mtb->add (MeterK20,     ArdourMeter::meter_type_string(MeterK20));
3079         mtb->add (MeterK14,     ArdourMeter::meter_type_string(MeterK14));
3080         mtb->add (MeterK12,     ArdourMeter::meter_type_string(MeterK12));
3081         mtb->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3082         mtb->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3083         mtb->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3084         mtb->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3085
3086         add_option (S_("Preferences|Metering"), mtb);
3087
3088         ComboOption<MeterType>* mtt = new ComboOption<MeterType> (
3089                 "meter-type-track",
3090                 _("Default meter type for tracks"),
3091                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_track),
3092                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_track)
3093                 );
3094         mtt->add (MeterPeak,    ArdourMeter::meter_type_string(MeterPeak));
3095         mtt->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
3096
3097         add_option (S_("Preferences|Metering"), mtt);
3098
3099         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Post Export Analysis")));
3100
3101         add_option (S_("Preferences|Metering"),
3102              new BoolOption (
3103                      "save-export-analysis-image",
3104                      _("Save loudness analysis as image file"),
3105                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_save_export_analysis_image),
3106                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_save_export_analysis_image)
3107                      ));
3108
3109         /* TRANSPORT & Sync */
3110
3111         add_option (_("Transport"), new OptionEditorHeading (_("General")));
3112
3113         bo = new BoolOption (
3114                      "stop-at-session-end",
3115                      _("Stop at the end of the session"),
3116                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
3117                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
3118                      );
3119         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3120                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
3121                                                               "when it reaches the current session end marker\n\n"
3122                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
3123                                                             PROGRAM_NAME));
3124         add_option (_("Transport"), bo);
3125
3126         bo = new BoolOption (
3127                      "latched-record-enable",
3128                      _("Keep record-enable engaged on stop"),
3129                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
3130                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
3131                      );
3132         add_option (_("Transport"), bo);
3133         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3134                         _("<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."));
3135
3136         bo = new BoolOption (
3137                      "disable-disarm-during-roll",
3138                      _("Disable per-track record disarm while rolling"),
3139                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
3140                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
3141                      );
3142         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."));
3143         add_option (_("Transport"), bo);
3144
3145         bo = new BoolOption (
3146                      "quieten_at_speed",
3147                      _("12dB gain reduction during fast-forward and fast-rewind"),
3148                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
3149                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
3150                      );
3151         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3152                         _("<b>When enabled</b> this will reduce the unpleasant increase in perceived volume "
3153                                 "that occurs when fast-forwarding or rewinding through some kinds of audio"));
3154         add_option (_("Transport"), bo);
3155
3156         ComboOption<float>* psc = new ComboOption<float> (
3157                      "preroll-seconds",
3158                      _("Preroll"),
3159                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_preroll_seconds),
3160                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_preroll_seconds)
3161                      );
3162         Gtkmm2ext::UI::instance()->set_tip (psc->tip_widget(),
3163                                             (_("The amount of preroll to apply when <b>Play with Preroll</b> or <b>Record with Preroll</b>is initiated.\n\n"
3164                                                "If <b>Follow Edits</b> is enabled, the preroll is applied to the playhead position when a region is selected or trimmed.")));
3165         psc->add (-4.0, _("4 Bars"));
3166         psc->add (-2.0, _("2 Bars"));
3167         psc->add (-1.0, _("1 Bar"));
3168         psc->add (0.0, _("0 (no pre-roll)"));
3169         psc->add (0.1, _("0.1 second"));
3170         psc->add (0.25, _("0.25 second"));
3171         psc->add (0.5, _("0.5 second"));
3172         psc->add (1.0, _("1.0 second"));
3173         psc->add (2.0, _("2.0 seconds"));
3174         add_option (_("Transport"), psc);
3175
3176
3177         add_option (_("Transport"), new OptionEditorHeading (_("Looping")));
3178
3179         bo = new BoolOption (
3180                      "loop-is-mode",
3181                      _("Play loop is a transport mode"),
3182                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
3183                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
3184                      );
3185         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3186                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
3187                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
3188         add_option (_("Transport"), bo);
3189
3190         bo = new BoolOption (
3191                      "seamless-loop",
3192                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
3193                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
3194                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
3195                      );
3196         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3197                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
3198                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
3199                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
3200                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
3201         add_option (_("Transport"), bo);
3202
3203         add_option (_("Transport"), new OptionEditorHeading (_("Dropout (xrun) Handling")));
3204         bo = new BoolOption (
3205                      "stop-recording-on-xrun",
3206                      _("Stop recording when an xrun occurs"),
3207                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
3208                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
3209                      );
3210         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3211                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
3212                                                             PROGRAM_NAME));
3213         add_option (_("Transport"), bo);
3214
3215         bo = new BoolOption (
3216                      "create-xrun-marker",
3217                      _("Create markers where xruns occur"),
3218                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
3219                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
3220                      );
3221         add_option (_("Transport"), bo);
3222
3223
3224         /* SYNC */
3225
3226         add_option (_("Sync"), new OptionEditorHeading (_("Transport Masters")));
3227
3228         add_option (_("Sync"), new WidgetOption (X_("foo"), X_("Transport Masters"), _transport_masters_widget));
3229
3230         _sync_framerate = new BoolOption (
3231                      "timecode-sync-frame-rate",
3232                      _("Match session video frame rate to external timecode"),
3233                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
3234                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
3235                      );
3236         Gtkmm2ext::UI::instance()->set_tip
3237                 (_sync_framerate->tip_widget(),
3238                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
3239                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
3240                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
3241                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
3242                                    "timecode standard and the session standard."), PROGRAM_NAME));
3243
3244         add_option (_("Sync"), _sync_framerate);
3245
3246         add_option (_("Sync/LTC"), new OptionEditorHeading (_("Linear Timecode (LTC) Generator")));
3247
3248         add_option (_("Sync/LTC"),
3249                     new BoolOption (
3250                             "send-ltc",
3251                             _("Enable LTC generator"),
3252                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
3253                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
3254                             ));
3255
3256         _ltc_send_continuously = new BoolOption (
3257                             "ltc-send-continuously",
3258                             _("Send LTC while stopped"),
3259                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
3260                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
3261                             );
3262         Gtkmm2ext::UI::instance()->set_tip
3263                 (_ltc_send_continuously->tip_widget(),
3264                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
3265         add_option (_("Sync/LTC"), _ltc_send_continuously);
3266
3267         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level [dBFS]"),
3268                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_output_volume),
3269                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_output_volume),
3270                                         -50, 0, .5, 5,
3271                                         .05, true);
3272
3273         Gtkmm2ext::UI::instance()->set_tip
3274                 (_ltc_volume_slider->tip_widget(),
3275                  _("Specify the Peak Volume of the generated LTC signal in dBFS. A good value is  0dBu ^= -18dBFS in an EBU calibrated system"));
3276
3277         add_option (_("Sync/LTC"), _ltc_volume_slider);
3278
3279
3280         add_option (_("Sync/MIDI"), new OptionEditorHeading (_("MIDI Beat Clock (Mclk) Generator")));
3281
3282         add_option (_("Sync/MIDI"),
3283                     new BoolOption (
3284                             "send-midi-clock",
3285                             _("Enable Mclk generator"),
3286                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
3287                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
3288                             ));
3289
3290         add_option (_("Sync/MIDI"), new OptionEditorHeading (_("MIDI Time Code (MTC) Generator")));
3291
3292         add_option (_("Sync/MIDI"),
3293                     new BoolOption (
3294                             "send-mtc",
3295                             _("Enable MTC Generator"),
3296                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
3297                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
3298                             ));
3299
3300         add_option (_("Sync/MIDI"),
3301                     new SpinOption<int> (
3302                             "mtc-qf-speed-tolerance",
3303                             _("Percentage either side of normal transport speed to transmit MTC"),
3304                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
3305                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
3306                             0, 20, 1, 5
3307                             ));
3308
3309         add_option (_("Sync/MIDI"), new OptionEditorHeading (_("MIDI Machine Control (MMC)")));
3310
3311         add_option (_("Sync/MIDI"),
3312                     new BoolOption (
3313                             "mmc-control",
3314                             _("Respond to MMC commands"),
3315                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
3316                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
3317                             ));
3318
3319         add_option (_("Sync/MIDI"),
3320                     new BoolOption (
3321                             "send-mmc",
3322                             _("Send MMC commands"),
3323                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
3324                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
3325                             ));
3326
3327         add_option (_("Sync/MIDI"),
3328              new SpinOption<uint8_t> (
3329                      "mmc-receive-device-id",
3330                      _("Inbound MMC device ID"),
3331                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
3332                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
3333                      0, 127, 1, 10
3334                      ));
3335
3336         add_option (_("Sync/MIDI"),
3337              new SpinOption<uint8_t> (
3338                      "mmc-send-device-id",
3339                      _("Outbound MMC device ID"),
3340                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
3341                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
3342                      0, 127, 1, 10
3343                      ));
3344
3345
3346         /* Control Surfaces */
3347
3348         add_option (_("Control Surfaces"), new OptionEditorHeading (_("Control Surfaces")));
3349         add_option (_("Control Surfaces"), new ControlSurfacesOptions ());
3350
3351         /* MIDI PORTs */
3352         add_option (_("MIDI Ports"), new OptionEditorHeading (_("MIDI Port Options")));
3353
3354         add_option (_("MIDI Ports"),
3355                     new BoolOption (
3356                             "midi-input-follows-selection",
3357                             _("MIDI input follows MIDI track selection"),
3358                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_input_follows_selection),
3359                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_input_follows_selection)
3360                             ));
3361
3362         add_option (_("MIDI Ports"), new MidiPortOptions ());
3363         add_option (_("MIDI Ports"), new OptionEditorBlank ());
3364
3365         /* PLUGINS */
3366
3367 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
3368         add_option (_("Plugins"), new OptionEditorHeading (_("Scan/Discover")));
3369         add_option (_("Plugins"),
3370                         new RcActionButton (_("Scan for Plugins"),
3371                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3372
3373 #endif
3374
3375         add_option (_("Plugins"), new OptionEditorHeading (_("General")));
3376
3377 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
3378         bo = new BoolOption (
3379                         "show-plugin-scan-window",
3380                         _("Always Display Plugin Scan Progress"),
3381                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_plugin_scan_window),
3382                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_plugin_scan_window)
3383                         );
3384         add_option (_("Plugins"), bo);
3385         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3386                         _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
3387 #endif
3388
3389         bo = new BoolOption (
3390                 "plugins-stop-with-transport",
3391                 _("Silence plugins when the transport is stopped"),
3392                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
3393                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
3394                 );
3395         add_option (_("Plugins"), bo);
3396         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3397                                             _("<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."));
3398
3399         bo = new BoolOption (
3400                 "new-plugins-active",
3401                         _("Make new plugins active"),
3402                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
3403                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
3404                         );
3405         add_option (_("Plugins"), bo);
3406         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3407                                             _("<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"));
3408
3409         ComboOption<uint32_t>* lna = new ComboOption<uint32_t> (
3410                      "limit-n-automatables",
3411                      _("Limit automatable parameters per plugin"),
3412                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_limit_n_automatables),
3413                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_limit_n_automatables)
3414                      );
3415         lna->add (0, _("Unlimited"));
3416         lna->add (64,  _("64 parameters"));
3417         lna->add (128, _("128 parameters"));
3418         lna->add (256, _("256 parameters"));
3419         lna->add (512, _("512 parameters"));
3420         lna->add (999, _("999 parameters"));
3421         add_option (_("Plugins"), lna);
3422         Gtkmm2ext::UI::instance()->set_tip (lna->tip_widget(),
3423                                             _("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."));
3424
3425
3426 #if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT)
3427         add_option (_("Plugins/VST"), new OptionEditorHeading (_("VST")));
3428 #if 0
3429         add_option (_("Plugins/VST"),
3430                         new RcActionButton (_("Scan for Plugins"),
3431                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3432 #endif
3433
3434 #if (defined AUDIOUNIT_SUPPORT && defined MACVST_SUPPORT)
3435         bo = new BoolOption (
3436                         "",
3437                         _("Enable Mac VST support (requires restart or re-scan)"),
3438                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_macvst),
3439                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_macvst)
3440                         );
3441         add_option (_("Plugins/VST"), bo);
3442 #endif
3443
3444         bo = new BoolOption (
3445                         "discover-vst-on-start",
3446                         _("Scan for [new] VST Plugins on Application Start"),
3447                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_vst_on_start),
3448                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_vst_on_start)
3449                         );
3450         add_option (_("Plugins/VST"), bo);
3451         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3452                                             _("<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"));
3453
3454 #ifdef WINDOWS_VST_SUPPORT
3455         // currently verbose logging is only implemented for Windows VST.
3456         bo = new BoolOption (
3457                         "verbose-plugin-scan",
3458                         _("Verbose Plugin Scan"),
3459                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_verbose_plugin_scan),
3460                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_verbose_plugin_scan)
3461                         );
3462         add_option (_("Plugins/VST"), bo);
3463         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3464                                             _("<b>When enabled</b> additional information for every plugin is added to the Log Window."));
3465 #endif
3466
3467         add_option (_("Plugins/VST"), new VstTimeOutSliderOption (_rc_config));
3468
3469         add_option (_("Plugins/VST"),
3470                         new RcActionButton (_("Clear"),
3471                                 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_cache),
3472                                 _("VST Cache:")));
3473
3474         add_option (_("Plugins/VST"),
3475                         new RcActionButton (_("Clear"),
3476                                 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_blacklist),
3477                                 _("VST Blacklist:")));
3478 #endif
3479
3480 #ifdef LXVST_SUPPORT
3481         add_option (_("Plugins/VST"),
3482                         new RcActionButton (_("Edit"),
3483                                 sigc::mem_fun (*this, &RCOptionEditor::edit_lxvst_path),
3484                         _("Linux VST Path:")));
3485
3486         add_option (_("Plugins/VST"),
3487                         new RcConfigDisplay (
3488                                 "plugin-path-lxvst",
3489                                 _("Path:"),
3490                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_lxvst),
3491                                 0));
3492 #endif
3493
3494 #ifdef WINDOWS_VST_SUPPORT
3495         add_option (_("Plugins/VST"),
3496                         new RcActionButton (_("Edit"),
3497                                 sigc::mem_fun (*this, &RCOptionEditor::edit_vst_path),
3498                         _("Windows VST Path:")));
3499         add_option (_("Plugins/VST"),
3500                         new RcConfigDisplay (
3501                                 "plugin-path-vst",
3502                                 _("Path:"),
3503                                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_vst),
3504                                 ';'));
3505 #endif
3506
3507 #ifdef AUDIOUNIT_SUPPORT
3508
3509         add_option (_("Plugins/Audio Unit"), new OptionEditorHeading (_("Audio Unit")));
3510 #if 0
3511         add_option (_("Plugins/Audio Unit"),
3512                         new RcActionButton (_("Scan for Plugins"),
3513                                 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3514 #endif
3515
3516         bo = new BoolOption (
3517                         "discover-audio-units",
3518                         _("Scan for [new] AudioUnit Plugins on Application Start"),
3519                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_audio_units),
3520                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_audio_units)
3521                         );
3522         add_option (_("Plugins/Audio Unit"), bo);
3523         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3524                                             _("<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."));
3525
3526         add_option (_("Plugins/Audio Unit"),
3527                         new RcActionButton (_("Clear"),
3528                                 sigc::mem_fun (*this, &RCOptionEditor::clear_au_cache),
3529                                 _("AU Cache:")));
3530
3531         add_option (_("Plugins/Audio Unit"),
3532                         new RcActionButton (_("Clear"),
3533                                 sigc::mem_fun (*this, &RCOptionEditor::clear_au_blacklist),
3534                                 _("AU Blacklist:")));
3535 #endif
3536
3537 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2)
3538         add_option (_("Plugins"), new OptionEditorHeading (_("Plugin GUI")));
3539         add_option (_("Plugins"),
3540              new BoolOption (
3541                      "open-gui-after-adding-plugin",
3542                      _("Automatically open the plugin GUI when adding a new plugin"),
3543                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_open_gui_after_adding_plugin),
3544                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_open_gui_after_adding_plugin)
3545                      ));
3546
3547 #if (defined LV2_SUPPORT && defined LV2_EXTENDED)
3548         add_option (_("Plugins"),
3549              new BoolOption (
3550                      "show-inline-display-by-default",
3551                      _("Show Plugin Inline Display on Mixerstrip by default"),
3552                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_inline_display_by_default),
3553                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_inline_display_by_default)
3554                      ));
3555
3556         _plugin_prefer_inline = new BoolOption (
3557                         "prefer-inline-over-gui",
3558                         _("Don't automatically open the plugin GUI when the plugin has an inline display mode"),
3559                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_prefer_inline_over_gui),
3560                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_prefer_inline_over_gui)
3561                         );
3562         add_option (_("Plugins"), _plugin_prefer_inline);
3563 #endif
3564
3565         add_option (_("Plugins"), new OptionEditorHeading (_("Instrument")));
3566
3567         bo = new BoolOption (
3568                         "ask-replace-instrument",
3569                         _("Ask to replace existing instrument plugin"),
3570                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_ask_replace_instrument),
3571                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_ask_replace_instrument)
3572                         );
3573         add_option (_("Plugins"), bo);
3574
3575         bo = new BoolOption (
3576                         "ask-setup_instrument",
3577                         _("Interactively configure instrument plugins on insert"),
3578                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_ask_setup_instrument),
3579                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_ask_setup_instrument)
3580                         );
3581         add_option (_("Plugins"), bo);
3582         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3583                         _("<b>When enabled</b> show a dialog to select instrument channel configuration before adding a multichannel plugin."));
3584
3585 #endif
3586         add_option (_("Plugins"), new OptionEditorBlank ());
3587
3588         /* INTERFACE */
3589 #if (defined OPTIONAL_CAIRO_IMAGE_SURFACE || defined CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE)
3590         add_option (_("Appearance"), new OptionEditorHeading (_("Graphics Acceleration")));
3591 #endif
3592
3593 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
3594         BoolOption* bgc = new BoolOption (
3595                 "cairo-image-surface",
3596                 _("Disable Graphics Hardware Acceleration (requires restart)"),
3597                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_cairo_image_surface),
3598                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_cairo_image_surface)
3599                 );
3600
3601         Gtkmm2ext::UI::instance()->set_tip (bgc->tip_widget(), string_compose (
3602                                 _("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));
3603         add_option (_("Appearance"), bgc);
3604 #endif
3605
3606 #ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
3607         BoolOption* bgo = new BoolOption (
3608                 "buggy-gradients",
3609                 _("Possibly improve slow graphical performance (requires restart)"),
3610                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_buggy_gradients),
3611                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_buggy_gradients)
3612                 );
3613
3614         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));
3615         add_option (_("Appearance"), bgo);
3616 #endif
3617         add_option (_("Appearance"), new OptionEditorHeading (_("Graphical User Interface")));
3618
3619         add_option (_("Appearance"),
3620              new BoolOption (
3621                      "widget-prelight",
3622                      _("Highlight widgets on mouseover"),
3623                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_widget_prelight),
3624                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_widget_prelight)
3625                      ));
3626
3627         add_option (_("Appearance"),
3628              new BoolOption (
3629                      "use-tooltips",
3630                      _("Show tooltips if mouse hovers over a control"),
3631                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_tooltips),
3632                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_tooltips)
3633                      ));
3634
3635         bo = new BoolOption (
3636                         "super-rapid-clock-update",
3637                         _("Update clocks at TC Frame rate"),
3638                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
3639                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
3640                         );
3641         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3642                         _("<b>When enabled</b> clock displays are updated every Timecode Frame (fps).\n\n"
3643                                 "<b>When disabled</b> clock displays are updated only every 100ms."
3644                          ));
3645         add_option (_("Appearance"), bo);
3646
3647         add_option (_("Appearance"),
3648                         new BoolOption (
3649                                 "blink-rec-arm",
3650                                 _("Blink Rec-Arm buttons"),
3651                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_blink_rec_arm),
3652                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_blink_rec_arm)
3653                                 ));
3654
3655         add_option (_("Appearance"),
3656                         new BoolOption (
3657                                 "blink-alert-indicators",
3658                                 _("Blink Alert Indicators"),
3659                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_blink_alert_indicators),
3660                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_blink_alert_indicators)
3661                                 ));
3662
3663
3664 #ifndef __APPLE__
3665         /* font scaling does nothing with GDK/Quartz */
3666         add_option (_("Appearance"), new FontScalingOptions ());
3667 #endif
3668         add_option (_("Appearance/Editor"), new OptionEditorHeading (_("General")));
3669         add_option (_("Appearance/Editor"),
3670              new BoolOption (
3671                      "show-name-highlight",
3672                      _("Use name highlight bars in region displays (requires a restart)"),
3673                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_name_highlight),
3674                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_name_highlight)
3675                      ));
3676
3677         add_option (_("Appearance/Editor"),
3678                         new BoolOption (
3679                         "color-regions-using-track-color",
3680                         _("Region color follows track color"),
3681                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_color_regions_using_track_color),
3682                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_color_regions_using_track_color)
3683                         ));
3684
3685         add_option (_("Appearance/Editor"), new OptionEditorHeading (_("Waveforms")));
3686
3687         if (!Profile->get_mixbus()) {
3688                 add_option (_("Appearance/Editor"),
3689                                 new BoolOption (
3690                                         "show-waveforms",
3691                                         _("Show waveforms in regions"),
3692                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
3693                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
3694                                         ));
3695         }  // !mixbus
3696
3697         add_option (_("Appearance/Editor"),
3698              new BoolOption (
3699                      "show-waveforms-while-recording",
3700                      _("Show waveforms while recording"),
3701                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
3702                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
3703                      ));
3704
3705         add_option (_("Appearance/Editor"),
3706                         new BoolOption (
3707                         "show-waveform-clipping",
3708                         _("Show waveform clipping"),
3709                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveform_clipping),
3710                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveform_clipping)
3711                         ));
3712
3713         add_option (_("Appearance/Editor"), new ClipLevelOptions ());
3714
3715         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
3716                 "waveform-scale",
3717                 _("Waveform scale"),
3718                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_scale),
3719                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_scale)
3720                 );
3721
3722         wfs->add (Linear, _("linear"));
3723         wfs->add (Logarithmic, _("logarithmic"));
3724
3725         add_option (_("Appearance/Editor"), wfs);
3726
3727         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
3728                 "waveform-shape",
3729                 _("Waveform shape"),
3730                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_shape),
3731                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_shape)
3732                 );
3733
3734         wfsh->add (Traditional, _("traditional"));
3735         wfsh->add (Rectified, _("rectified"));
3736
3737         add_option (_("Appearance/Editor"), wfsh);
3738
3739         add_option (_("Appearance/Editor"), new OptionEditorHeading (_("Editor Meters")));
3740
3741         add_option (_("Appearance/Editor"),
3742              new BoolOption (
3743                      "show-track-meters",
3744                      _("Show meters in track headers"),
3745                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
3746                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_track_meters)
3747                      ));
3748
3749         add_option (_("Appearance/Editor"),
3750              new BoolOption (
3751                      "editor-stereo-only-meters",
3752                      _("Limit track header meters to stereo"),
3753                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_editor_stereo_only_meters),
3754                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_editor_stereo_only_meters)
3755                      ));
3756
3757         add_option (_("Appearance/Editor"), new OptionEditorHeading (_("MIDI Regions")));
3758
3759         add_option (_("Appearance/Editor"),
3760                     new BoolOption (
3761                             "display-first-midi-bank-as-zero",
3762                             _("Display first MIDI bank/program as 0"),
3763                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
3764                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
3765                             ));
3766
3767         add_option (_("Appearance/Editor"),
3768              new BoolOption (
3769                      "never-display-periodic-midi",
3770                      _("Don't display periodic (MTC, MMC) SysEx messages in MIDI Regions"),
3771                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
3772                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
3773                      ));
3774
3775
3776         add_option (_("Appearance/Editor"),
3777                     new BoolOption (
3778                             "use-note-bars-for-velocity",
3779                             _("Show velocity horizontally inside notes"),
3780                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_note_bars_for_velocity),
3781                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_note_bars_for_velocity)
3782                             ));
3783
3784         add_option (_("Appearance/Editor"),
3785                     new BoolOption (
3786                             "use-note-color-for-velocity",
3787                             _("Use colors to show note velocity"),
3788                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_note_color_for_velocity),
3789                             sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_note_color_for_velocity)
3790                             ));
3791
3792         add_option (_("Appearance/Editor"), new OptionEditorBlank ());
3793
3794         /* The names of these controls must be the same as those given in MixerStrip
3795            for the actual widgets being controlled.
3796         */
3797         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
3798         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
3799         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
3800         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
3801         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
3802         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
3803         _mixer_strip_visibility.add (0, X_("VCA"), _("VCA Assigns"));
3804
3805         add_option (_("Appearance/Mixer"),
3806                 new VisibilityOption (
3807                         _("Mixer Strip"),
3808                         &_mixer_strip_visibility,
3809                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_mixer_strip_visibility),
3810                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_mixer_strip_visibility)
3811                         )
3812                 );
3813
3814         add_option (_("Appearance/Mixer"),
3815              new BoolOption (
3816                      "default-narrow_ms",
3817                      _("Use narrow strips in the mixer for new strips by default"),
3818                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_default_narrow_ms),
3819                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
3820                      ));
3821
3822         ComboOption<uint32_t>* mic = new ComboOption<uint32_t> (
3823                      "max-inline-controls",
3824                      _("Limit inline-mixer-strip controls per plugin"),
3825                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_max_inline_controls),
3826                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_max_inline_controls)
3827                      );
3828         mic->add (0, _("Unlimited"));
3829         mic->add (16,  _("16 parameters"));
3830         mic->add (32,  _("32 parameters"));
3831         mic->add (64,  _("64 parameters"));
3832         mic->add (128, _("128 parameters"));
3833         add_option (_("Appearance/Mixer"), mic);
3834
3835         add_option (_("Appearance/Mixer"), new OptionEditorBlank ());
3836
3837         add_option (_("Appearance/Toolbar"), new OptionEditorHeading (_("Main Transport Toolbar Items")));
3838
3839         add_option (_("Appearance/Toolbar"),
3840              new BoolOption (
3841                      "show-toolbar-recpunch",
3842                      _("Display Record/Punch Options"),
3843                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_recpunch),
3844                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_recpunch)
3845                      ));
3846
3847         add_option (_("Appearance/Toolbar"),
3848              new BoolOption (
3849                      "show-toolbar-monitoring",
3850                      _("Display Monitor Options"),
3851                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_monitoring),
3852                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_monitoring)
3853                      ));
3854
3855         add_option (_("Appearance/Toolbar"),
3856              new BoolOption (
3857                      "show-toolbar-selclock",
3858                      _("Display Selection Clock"),
3859                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_selclock),
3860                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_selclock)
3861                      ));
3862
3863         if (!ARDOUR::Profile->get_small_screen()) {
3864                 add_option (_("Appearance/Toolbar"),
3865                                 new BoolOption (
3866                                         "show-secondary-clock",
3867                                         _("Display Secondary Clock"),
3868                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_secondary_clock),
3869                                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_secondary_clock)
3870                                         ));
3871         }
3872
3873         add_option (_("Appearance/Toolbar"),
3874              new BoolOption (
3875                      "show-mini-timeline",
3876                      _("Display Navigation Timeline"),
3877                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_mini_timeline),
3878                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_mini_timeline)
3879                      ));
3880
3881         add_option (_("Appearance/Toolbar"),
3882              new BoolOption (
3883                      "show-editor-meter",
3884                      _("Display Master Level Meter"),
3885                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
3886                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
3887                      ));
3888
3889         add_option (_("Appearance/Toolbar"),
3890                         new ColumVisibilityOption (
3891                                 "action-table-columns", _("Display Action-Buttons"), 4,
3892                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_action_table_columns),
3893                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_action_table_columns)
3894                                 )
3895                         );
3896         add_option (_("Appearance/Toolbar"), new OptionEditorBlank ());
3897
3898
3899         /* and now the theme manager */
3900
3901         add_option (_("Appearance/Theme"), new OptionEditorHeading (_("Theme")));
3902
3903         add_option (_("Appearance/Theme"), new BoolOption (
3904                                 "flat-buttons",
3905                                 _("Draw \"flat\" buttons"),
3906                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_flat_buttons),
3907                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_flat_buttons)
3908                                 ));
3909
3910         add_option (_("Appearance/Theme"), new BoolOption (
3911                                 "boxy-buttons",
3912                                 _("Draw \"boxy\" buttons"),
3913                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_boxy_buttons),
3914                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_boxy_buttons)
3915                                 ));
3916
3917         add_option (_("Appearance/Theme"), new BoolOption (
3918                                 "meter-style-led",
3919                                 _("LED meter style"),
3920                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_style_led),
3921                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_style_led)
3922                                 ));
3923
3924
3925         HSliderOption *gui_hs = new HSliderOption(
3926                         "timeline-item-gradient-depth",
3927                         _("Waveforms color gradient depth"),
3928                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_gradient_depth),
3929                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_gradient_depth),
3930                         0, 1.0, 0.05
3931                         );
3932         gui_hs->scale().set_update_policy (Gtk::UPDATE_DELAYED);
3933         add_option (_("Appearance/Theme"), gui_hs);
3934
3935         gui_hs = new HSliderOption(
3936                         "timeline-item-gradient-depth",
3937                         _("Timeline item gradient depth"),
3938                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_timeline_item_gradient_depth),
3939                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_timeline_item_gradient_depth),
3940                         0, 1.0, 0.05
3941                         );
3942         gui_hs->scale().set_update_policy (Gtk::UPDATE_DELAYED);
3943         add_option (_("Appearance/Theme"), gui_hs);
3944
3945         vector<string> icon_sets = ::get_icon_sets ();
3946         if (icon_sets.size() > 1) {
3947                 ComboOption<std::string>* io = new ComboOption<std::string> (
3948                                 "icon-set", _("Icon Set"),
3949                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_icon_set),
3950                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_icon_set)
3951                                 );
3952                 for (vector<string>::const_iterator i = icon_sets.begin (); i != icon_sets.end (); ++i) {
3953                         io->add (*i, *i);
3954                 }
3955                 add_option (_("Appearance/Theme"), io);
3956         }
3957
3958         add_option (_("Appearance/Colors"), new OptionEditorHeading (_("Colors")));
3959         add_option (_("Appearance/Colors"), new ColorThemeManager);
3960         add_option (_("Appearance/Colors"), new OptionEditorBlank ());
3961
3962         /* Quirks */
3963
3964         OptionEditorHeading* quirks_head = new OptionEditorHeading (_("Various Workarounds for Windowing Systems"));
3965
3966         quirks_head->set_note (string_compose (_("Rules for closing, minimizing, maximizing, and stay-on-top can vary \
3967 with each version of your OS, and the preferences that you've set in your OS.\n\n\
3968 You can adjust the options, below, to change how %1's windows and dialogs behave.\n\n\
3969 These settings will only take effect after %1 is restarted.\n\
3970         "), PROGRAM_NAME));
3971
3972         add_option (_("Appearance/Quirks"), quirks_head);
3973
3974         bo = new BoolOption (
3975                      "use-wm-visibility",
3976                      _("Use visibility information provided by your Window Manager/Desktop"),
3977                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_wm_visibility),
3978                      sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_wm_visibility)
3979                      );
3980         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
3981                                 _("If you have trouble toggling between hidden Editor and Mixer windows, try changing this setting."));
3982         add_option (_("Appearance/Quirks"), bo);
3983
3984 #ifndef __APPLE__
3985         bo = new BoolOption (
3986                         "all-floating-windows-are-dialogs",
3987                         _("All floating windows are dialogs"),
3988                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_all_floating_windows_are_dialogs),
3989                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_all_floating_windows_are_dialogs)
3990                         );
3991         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
3992                         _("Mark all floating windows to be type \"Dialog\" rather than using \"Utility\" for some.\nThis may help with some window managers."));
3993         add_option (_("Appearance/Quirks"), bo);
3994
3995         bo = new BoolOption (
3996                         "transients-follow-front",
3997                         _("Transient windows follow front window."),
3998                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_transients_follow_front),
3999                         sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_transients_follow_front)
4000                         );
4001         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4002                                 _("Make transient windows follow the front window when toggling between the editor and mixer."));
4003         add_option (_("Appearance/Quirks"), bo);
4004 #endif
4005
4006         if (!Profile->get_mixbus()) {
4007                 bo = new BoolOption (
4008                                 "floating-monitor-section",
4009                                 _("Float detached monitor-section window"),
4010                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_floating_monitor_section),
4011                                 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_floating_monitor_section)
4012                                 );
4013                 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4014                                         _("When detaching the monitoring section, mark it as \"Utility\" window to stay in front."));
4015                 add_option (_("Appearance/Quirks"), bo);
4016         }
4017
4018         add_option (_("Appearance/Quirks"), new OptionEditorBlank ());
4019
4020         /* VIDEO Timeline */
4021         add_option (_("Video"), new OptionEditorHeading (_("Video Server")));
4022         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
4023
4024         Widget::show_all ();
4025
4026         //trigger some parameter-changed messages which affect widget-visibility or -sensitivity
4027         parameter_changed ("send-ltc");
4028         parameter_changed ("sync-source");
4029         parameter_changed ("use-monitor-bus");
4030         parameter_changed ("open-gui-after-adding-plugin");
4031
4032         XMLNode* node = ARDOUR_UI::instance()->preferences_settings();
4033         if (node) {
4034                 /* gcc4 complains about ambiguity with Gtk::Widget::set_state
4035                    (Gtk::StateType) here !!!
4036                 */
4037                 Tabbable::set_state (*node, Stateful::loading_state_version);
4038         }
4039
4040         set_current_page (_("General"));
4041 }
4042
4043 void
4044 RCOptionEditor::set_session (Session *s)
4045 {
4046         SessionHandlePtr::set_session (s);
4047         _transport_masters_widget.set_session (s);
4048 }
4049
4050 void
4051 RCOptionEditor::parameter_changed (string const & p)
4052 {
4053         OptionEditor::parameter_changed (p);
4054
4055         if (p == "use-monitor-bus") {
4056                 bool const s = Config->get_use_monitor_bus ();
4057                 if (!s) {
4058                         /* we can't use this if we don't have a monitor bus */
4059                         Config->set_solo_control_is_listen_control (false);
4060                 }
4061                 _solo_control_is_listen_control->set_sensitive (s);
4062                 _listen_position->set_sensitive (s);
4063         } else if (p == "sync-source") {
4064                 boost::shared_ptr<TransportMaster> tm (TransportMasterManager::instance().current());
4065                 if (boost::dynamic_pointer_cast<TimecodeTransportMaster> (tm)) {
4066                         _sync_framerate->set_sensitive (true);
4067                 } else {
4068                         _sync_framerate->set_sensitive (false);
4069                 }
4070         } else if (p == "send-ltc") {
4071                 bool const s = Config->get_send_ltc ();
4072                 _ltc_send_continuously->set_sensitive (s);
4073                 _ltc_volume_slider->set_sensitive (s);
4074         } else if (p == "open-gui-after-adding-plugin" || p == "show-inline-display-by-default") {
4075 #if (defined LV2_SUPPORT && defined LV2_EXTENDED)
4076                 _plugin_prefer_inline->set_sensitive (UIConfiguration::instance().get_open_gui_after_adding_plugin() && UIConfiguration::instance().get_show_inline_display_by_default());
4077 #endif
4078         }
4079 }
4080
4081 void RCOptionEditor::plugin_scan_refresh () {
4082         PluginManager::instance().refresh();
4083 }
4084
4085 void RCOptionEditor::clear_vst_cache () {
4086         PluginManager::instance().clear_vst_cache();
4087 }
4088
4089 void RCOptionEditor::clear_vst_blacklist () {
4090         PluginManager::instance().clear_vst_blacklist();
4091 }
4092
4093 void RCOptionEditor::clear_au_cache () {
4094         PluginManager::instance().clear_au_cache();
4095 }
4096
4097 void RCOptionEditor::clear_au_blacklist () {
4098         PluginManager::instance().clear_au_blacklist();
4099 }
4100
4101 void RCOptionEditor::edit_lxvst_path () {
4102         Glib::RefPtr<Gdk::Window> win = get_parent_window ();
4103         PathsDialog *pd = new PathsDialog (
4104                 *current_toplevel(), _("Set Linux VST Search Path"),
4105                 _rc_config->get_plugin_path_lxvst(),
4106                 PluginManager::instance().get_default_lxvst_path()
4107                 );
4108         ResponseType r = (ResponseType) pd->run ();
4109         pd->hide();
4110         if (r == RESPONSE_ACCEPT) {
4111                 _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
4112
4113                 MessageDialog msg (_("Re-scan Plugins now?"),
4114                                 false /*no markup*/, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true /*modal*/);
4115                 msg.set_default_response (Gtk::RESPONSE_YES);
4116                 if (msg.run() == Gtk::RESPONSE_YES) {
4117                         msg.hide ();
4118                         plugin_scan_refresh ();
4119                 }
4120         }
4121         delete pd;
4122 }
4123
4124 void RCOptionEditor::edit_vst_path () {
4125         PathsDialog *pd = new PathsDialog (
4126                 *current_toplevel(), _("Set Windows VST Search Path"),
4127                 _rc_config->get_plugin_path_vst(),
4128                 PluginManager::instance().get_default_windows_vst_path()
4129                 );
4130         ResponseType r = (ResponseType) pd->run ();
4131         pd->hide();
4132         if (r == RESPONSE_ACCEPT) {
4133                 _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
4134                 MessageDialog msg (_("Re-scan Plugins now?"),
4135                                 false /*no markup*/, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true /*modal*/);
4136                 msg.set_default_response (Gtk::RESPONSE_YES);
4137                 if (msg.run() == Gtk::RESPONSE_YES) {
4138                         msg.hide ();
4139                         plugin_scan_refresh ();
4140                 }
4141         }
4142         delete pd;
4143 }
4144
4145 Gtk::Window*
4146 RCOptionEditor::use_own_window (bool and_fill_it)
4147 {
4148         bool new_window = !own_window ();
4149
4150         Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
4151
4152         if (win && new_window) {
4153                 win->set_name ("PreferencesWindow");
4154                 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Preferences"), this);
4155                 win->resize (1, 1);
4156                 win->set_resizable (false);
4157         }
4158
4159         return win;
4160 }
4161
4162 XMLNode&
4163 RCOptionEditor::get_state ()
4164 {
4165         XMLNode* node = new XMLNode (X_("Preferences"));
4166         node->add_child_nocopy (Tabbable::get_state());
4167         return *node;
4168 }