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