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