Fix up modifier behaviour
[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 #include <boost/algorithm/string.hpp>    
25
26 #include <gtkmm/liststore.h>
27 #include <gtkmm/stock.h>
28 #include <gtkmm/scale.h>
29
30 #include <gtkmm2ext/utils.h>
31 #include <gtkmm2ext/slider_controller.h>
32 #include <gtkmm2ext/gtk_ui.h>
33 #include <gtkmm2ext/paths_dialog.h>
34
35 #include "pbd/fpu.h"
36 #include "pbd/cpus.h"
37
38 #include "ardour/audioengine.h"
39 #include "ardour/dB.h"
40 #include "ardour/rc_configuration.h"
41 #include "ardour/control_protocol_manager.h"
42 #include "ardour/plugin_manager.h"
43 #include "control_protocol/control_protocol.h"
44
45 #include "canvas/wave_view.h"
46
47 #include "ardour_ui.h"
48 #include "ardour_window.h"
49 #include "ardour_dialog.h"
50 #include "gui_thread.h"
51 #include "midi_tracer.h"
52 #include "rc_option_editor.h"
53 #include "utils.h"
54 #include "midi_port_dialog.h"
55 #include "sfdb_ui.h"
56 #include "keyboard.h"
57 #include "theme_manager.h"
58 #include "ui_config.h"
59 #include "i18n.h"
60
61 using namespace std;
62 using namespace Gtk;
63 using namespace Gtkmm2ext;
64 using namespace PBD;
65 using namespace ARDOUR;
66 using namespace ARDOUR_UI_UTILS;
67
68 class ClickOptions : public OptionEditorBox
69 {
70 public:
71         ClickOptions (RCConfiguration* c, Gtk::Window* p)
72                 : _rc_config (c)
73         {
74                 Table* t = manage (new Table (2, 3));
75                 t->set_spacings (4);
76
77                 Label* l = manage (left_aligned_label (_("Click audio file:")));
78                 t->attach (*l, 0, 1, 0, 1, FILL);
79                 t->attach (_click_path_entry, 1, 2, 0, 1, FILL);
80                 Button* b = manage (new Button (_("Browse...")));
81                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
82                 t->attach (*b, 2, 3, 0, 1, FILL);
83
84                 l = manage (left_aligned_label (_("Click emphasis audio file:")));
85                 t->attach (*l, 0, 1, 1, 2, FILL);
86                 t->attach (_click_emphasis_path_entry, 1, 2, 1, 2, FILL);
87                 b = manage (new Button (_("Browse...")));
88                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
89                 t->attach (*b, 2, 3, 1, 2, FILL);
90                 
91                 _box->pack_start (*t, false, false);
92
93                 _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));      
94                 _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
95         }
96
97         void parameter_changed (string const & p)
98         {
99                 if (p == "click-sound") {
100                         _click_path_entry.set_text (_rc_config->get_click_sound());
101                 } else if (p == "click-emphasis-sound") {
102                         _click_emphasis_path_entry.set_text (_rc_config->get_click_emphasis_sound());
103                 }
104         }
105
106         void set_state_from_config ()
107         {
108                 parameter_changed ("click-sound");
109                 parameter_changed ("click-emphasis-sound");
110         }
111
112 private:
113
114         void click_browse_clicked ()
115         {
116                 SoundFileChooser sfdb (_("Choose Click"));
117
118                 sfdb.show_all ();
119                 sfdb.present ();
120
121                 if (sfdb.run () == RESPONSE_OK) {
122                         click_chosen (sfdb.get_filename());
123                 }
124         }
125
126         void click_chosen (string const & path)
127         {
128                 _click_path_entry.set_text (path);
129                 _rc_config->set_click_sound (path);
130         }
131
132         void click_changed ()
133         {
134                 click_chosen (_click_path_entry.get_text ());
135         }
136         
137         void click_emphasis_browse_clicked ()
138         {
139                 SoundFileChooser sfdb (_("Choose Click Emphasis"));
140
141                 sfdb.show_all ();
142                 sfdb.present ();
143
144                 if (sfdb.run () == RESPONSE_OK) {
145                         click_emphasis_chosen (sfdb.get_filename());
146                 }
147         }
148
149         void click_emphasis_chosen (string const & path)
150         {
151                 _click_emphasis_path_entry.set_text (path);
152                 _rc_config->set_click_emphasis_sound (path);
153         }
154
155         void click_emphasis_changed ()
156         {
157                 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
158         }
159
160         RCConfiguration* _rc_config;
161         Entry _click_path_entry;
162         Entry _click_emphasis_path_entry;
163 };
164
165 class UndoOptions : public OptionEditorBox
166 {
167 public:
168         UndoOptions (RCConfiguration* c) :
169                 _rc_config (c),
170                 _limit_undo_button (_("Limit undo history to")),
171                 _save_undo_button (_("Save undo history of"))
172         {
173                 Table* t = new Table (2, 3);
174                 t->set_spacings (4);
175
176                 t->attach (_limit_undo_button, 0, 1, 0, 1, FILL);
177                 _limit_undo_spin.set_range (0, 512);
178                 _limit_undo_spin.set_increments (1, 10);
179                 t->attach (_limit_undo_spin, 1, 2, 0, 1, FILL | EXPAND);
180                 Label* l = manage (left_aligned_label (_("commands")));
181                 t->attach (*l, 2, 3, 0, 1);
182
183                 t->attach (_save_undo_button, 0, 1, 1, 2, FILL);
184                 _save_undo_spin.set_range (0, 512);
185                 _save_undo_spin.set_increments (1, 10);
186                 t->attach (_save_undo_spin, 1, 2, 1, 2, FILL | EXPAND);
187                 l = manage (left_aligned_label (_("commands")));
188                 t->attach (*l, 2, 3, 1, 2);
189
190                 _box->pack_start (*t);
191
192                 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
193                 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
194                 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
195                 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
196         }
197
198         void parameter_changed (string const & p)
199         {
200                 if (p == "history-depth") {
201                         int32_t const d = _rc_config->get_history_depth();
202                         _limit_undo_button.set_active (d != 0);
203                         _limit_undo_spin.set_sensitive (d != 0);
204                         _limit_undo_spin.set_value (d);
205                 } else if (p == "save-history") {
206                         bool const x = _rc_config->get_save_history ();
207                         _save_undo_button.set_active (x);
208                         _save_undo_spin.set_sensitive (x);
209                 } else if (p == "save-history-depth") {
210                         _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
211                 }
212         }
213
214         void set_state_from_config ()
215         {
216                 parameter_changed ("save-history");
217                 parameter_changed ("history-depth");
218                 parameter_changed ("save-history-depth");
219         }
220
221         void limit_undo_toggled ()
222         {
223                 bool const x = _limit_undo_button.get_active ();
224                 _limit_undo_spin.set_sensitive (x);
225                 int32_t const n = x ? 16 : 0;
226                 _limit_undo_spin.set_value (n);
227                 _rc_config->set_history_depth (n);
228         }
229
230         void limit_undo_changed ()
231         {
232                 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
233         }
234
235         void save_undo_toggled ()
236         {
237                 bool const x = _save_undo_button.get_active ();
238                 _rc_config->set_save_history (x);
239         }
240
241         void save_undo_changed ()
242         {
243                 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
244         }
245
246 private:
247         RCConfiguration* _rc_config;
248         CheckButton _limit_undo_button;
249         SpinButton _limit_undo_spin;
250         CheckButton _save_undo_button;
251         SpinButton _save_undo_spin;
252 };
253
254
255
256 static const struct {
257     const char *name;
258     guint modifier;
259 } modifiers[] = {
260
261         { "Unmodified", 0 },
262
263 #ifdef GTKOSX
264
265         /* Command = Meta
266            Option/Alt = Mod1
267         */
268         { "Key|Shift", GDK_SHIFT_MASK },
269         { "Command", GDK_META_MASK },
270         { "Control", GDK_CONTROL_MASK },
271         { "Option", GDK_MOD1_MASK },
272         { "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
273         { "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
274         { "Option-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
275         { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
276         { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
277
278 #else
279         { "Key|Shift", GDK_SHIFT_MASK },
280         { "Control", GDK_CONTROL_MASK },
281         { "Alt", GDK_MOD1_MASK },
282         { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
283         { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
284         { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
285         { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
286         { "Alt-Windows", GDK_MOD1_MASK|GDK_MOD4_MASK },
287         { "Mod2", GDK_MOD2_MASK },
288         { "Mod3", GDK_MOD3_MASK },
289         { "Windows", GDK_MOD4_MASK },
290         { "Mod5", GDK_MOD5_MASK },
291 #endif
292         { 0, 0 }
293 };
294
295
296 class KeyboardOptions : public OptionEditorBox
297 {
298 public:
299         KeyboardOptions () :
300                   _delete_button_adjustment (3, 1, 12),
301                   _delete_button_spin (_delete_button_adjustment),
302                   _edit_button_adjustment (3, 1, 5),
303                   _edit_button_spin (_edit_button_adjustment),
304                   _insert_note_button_adjustment (3, 1, 5),
305                   _insert_note_button_spin (_insert_note_button_adjustment)
306         {
307                 /* internationalize and prepare for use with combos */
308
309                 vector<string> dumb;
310                 for (int i = 0; modifiers[i].name; ++i) {
311                         dumb.push_back (S_(modifiers[i].name));
312                 }
313
314                 set_popdown_strings (_edit_modifier_combo, dumb);
315                 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
316
317                 for (int x = 0; modifiers[x].name; ++x) {
318                         if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
319                                 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
320                                 break;
321                         }
322                 }
323
324                 Table* t = manage (new Table (5, 11));
325                 t->set_spacings (4);
326
327                 int row = 0;
328                 int col = 0;
329
330                 Label* l = manage (left_aligned_label (_("Select Keyboard layout:")));
331                 l->set_name ("OptionsLabel");
332
333                 vector<string> strs;
334
335                 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
336                         strs.push_back (bf->first);
337                 }
338
339                 set_popdown_strings (_keyboard_layout_selector, strs);
340                 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
341                 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
342
343                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
344                 t->attach (_keyboard_layout_selector, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
345
346                 ++row;
347                 col = 0;
348
349                 l = manage (left_aligned_label (_("When Clicking:")));
350                 l->set_name ("OptionEditorHeading");
351                 t->attach (*l, col, col + 2, row, row + 1, FILL | EXPAND, FILL);
352
353                 ++row;
354                 col = 1;
355
356                 l = manage (left_aligned_label (_("Edit using:")));
357                 l->set_name ("OptionsLabel");
358
359                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
360                 t->attach (_edit_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
361
362                 l = manage (new Label (_("+ button")));
363                 l->set_name ("OptionsLabel");
364
365                 t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
366                 t->attach (_edit_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
367
368                 _edit_button_spin.set_name ("OptionsEntry");
369                 _edit_button_adjustment.set_value (Keyboard::edit_button());
370                 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
371
372                 ++row;
373                 col = 1;
374
375                 set_popdown_strings (_delete_modifier_combo, dumb);
376                 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
377
378                 for (int x = 0; modifiers[x].name; ++x) {
379                         if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
380                                 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
381                                 break;
382                         }
383                 }
384
385                 l = manage (left_aligned_label (_("Delete using:")));
386                 l->set_name ("OptionsLabel");
387
388                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
389                 t->attach (_delete_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
390
391                 l = manage (new Label (_("+ button")));
392                 l->set_name ("OptionsLabel");
393
394                 t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
395                 t->attach (_delete_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
396
397                 _delete_button_spin.set_name ("OptionsEntry");
398                 _delete_button_adjustment.set_value (Keyboard::delete_button());
399                 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
400
401                 ++row;
402                 col = 1;
403
404                 set_popdown_strings (_insert_note_modifier_combo, dumb);
405                 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
406
407                 for (int x = 0; modifiers[x].name; ++x) {
408                         if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
409                                 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
410                                 break;
411                         }
412                 }
413
414                 l = manage (left_aligned_label (_("Insert note using:")));
415                 l->set_name ("OptionsLabel");
416
417                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
418                 t->attach (_insert_note_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
419
420                 l = manage (new Label (_("+ button")));
421                 l->set_name ("OptionsLabel");
422
423                 t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
424                 t->attach (_insert_note_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
425
426                 _insert_note_button_spin.set_name ("OptionsEntry");
427                 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
428                 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
429
430                 ++row;
431
432                 l = manage (left_aligned_label (_("When Beginning a Drag:")));
433                 l->set_name ("OptionEditorHeading");
434                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
435
436                 ++row;
437                 col = 1;
438
439                 /* copy modifier */
440                 set_popdown_strings (_copy_modifier_combo, dumb);
441                 _copy_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::copy_modifier_chosen));
442
443                 for (int x = 0; modifiers[x].name; ++x) {
444                         if (modifiers[x].modifier == (guint) Keyboard::CopyModifier) {
445                                 _copy_modifier_combo.set_active_text (S_(modifiers[x].name));
446                                 break;
447                         }
448                 }
449
450                 l = manage (left_aligned_label (_("Copy items using:")));
451                 l->set_name ("OptionsLabel");
452
453                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
454                 t->attach (_copy_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
455
456                 ++row;
457
458                 l = manage (left_aligned_label (_("When Beginning a Trim:")));
459                 l->set_name ("OptionEditorHeading");
460                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
461
462                 ++row;
463                 col = 1;
464
465                 /* trim_contents */
466                 set_popdown_strings (_trim_contents_combo, dumb);
467                 _trim_contents_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_contents_modifier_chosen));
468
469                 for (int x = 0; modifiers[x].name; ++x) {
470                         if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_contents_modifier ()) {
471                                 _trim_contents_combo.set_active_text (S_(modifiers[x].name));
472                                 break;
473                         }
474                 }
475
476                 l = manage (left_aligned_label (_("Trim contents using:")));
477                 l->set_name ("OptionsLabel");
478
479                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
480                 t->attach (_trim_contents_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
481
482                 ++row;
483                 col = 1;
484
485                 /* anchored trim */
486                 set_popdown_strings (_trim_anchored_combo, dumb);
487                 _trim_anchored_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_anchored_modifier_chosen));
488
489                 for (int x = 0; modifiers[x].name; ++x) {
490                         if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_anchored_modifier ()) {
491                                 _trim_anchored_combo.set_active_text (S_(modifiers[x].name));
492                                 break;
493                         }
494                 }
495
496                 l = manage (left_aligned_label (_("Anchored trim using:")));
497                 l->set_name ("OptionsLabel");
498
499                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
500                 ++col;
501                 t->attach (_trim_anchored_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
502
503                 ++row;
504                 col = 1;
505
506                 /* jump trim disabled for now
507                 set_popdown_strings (_trim_jump_combo, dumb);
508                 _trim_jump_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_jump_modifier_chosen));
509
510                 for (int x = 0; modifiers[x].name; ++x) {
511                         if (modifiers[x].modifier == (guint) Keyboard::trim_jump_modifier ()) {
512                                 _trim_jump_combo.set_active_text (S_(modifiers[x].name));
513                                 break;
514                         }
515                 }
516
517                 l = manage (left_aligned_label (_("Jump after trim using:")));
518                 l->set_name ("OptionsLabel");
519
520                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
521                 ++col;
522                 t->attach (_trim_jump_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
523
524                 ++row;
525                 col = 1;
526                 */
527
528                 /* note resize relative */
529                 set_popdown_strings (_note_size_relative_combo, dumb);
530                 _note_size_relative_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::note_size_relative_modifier_chosen));
531
532                 for (int x = 0; modifiers[x].name; ++x) {
533                         if (modifiers[x].modifier == (guint) ArdourKeyboard::note_size_relative_modifier ()) {
534                                 _note_size_relative_combo.set_active_text (S_(modifiers[x].name));
535                                 break;
536                         }
537                 }
538
539                 l = manage (left_aligned_label (_("Resize notes relatively using:")));
540                 l->set_name ("OptionsLabel");
541
542                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
543                 ++col;
544                 t->attach (_note_size_relative_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
545
546                 ++row;
547
548                 l = manage (left_aligned_label (_("While Dragging:")));
549                 l->set_name ("OptionEditorHeading");
550                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
551
552                 ++row;
553                 col = 1;
554
555                 /* ignore snap */
556                 set_popdown_strings (_snap_modifier_combo, dumb);
557                 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
558
559                 for (int x = 0; modifiers[x].name; ++x) {
560                         if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
561                                 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
562                                 break;
563                         }
564                 }
565
566                 l = manage (left_aligned_label (_("Ignore snap using:")));
567                 l->set_name ("OptionsLabel");
568
569                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
570                 t->attach (_snap_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
571
572                 ++row;
573                 col = 1;
574
575                 /* snap delta */
576                 set_popdown_strings (_snap_delta_combo, dumb);
577                 _snap_delta_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_delta_modifier_chosen));
578
579                 for (int x = 0; modifiers[x].name; ++x) {
580                         if (modifiers[x].modifier == (guint) Keyboard::snap_delta_modifier ()) {
581                                 _snap_delta_combo.set_active_text (S_(modifiers[x].name));
582                                 break;
583                         }
584                 }
585
586                 l = manage (left_aligned_label (_("Snap to absolute using:")));
587                 l->set_name ("OptionsLabel");
588
589                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
590                 t->attach (_snap_delta_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
591
592                 ++row;
593
594                 l = manage (left_aligned_label (_("While Trimming:")));
595                 l->set_name ("OptionEditorHeading");
596                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
597
598                 ++row;
599                 col = 1;
600
601                 /* trim_overlap */
602                 set_popdown_strings (_trim_overlap_combo, dumb);
603                 _trim_overlap_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_overlap_modifier_chosen));
604
605                 for (int x = 0; modifiers[x].name; ++x) {
606                         if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_overlap_modifier ()) {
607                                 _trim_overlap_combo.set_active_text (S_(modifiers[x].name));
608                                 break;
609                         }
610                 }
611
612                 l = manage (left_aligned_label (_("Resize overlaped regions using:")));
613                 l->set_name ("OptionsLabel");
614
615                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
616                 t->attach (_trim_overlap_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
617
618                 ++row;
619
620                 l = manage (left_aligned_label (_("While Dragging Control Points:")));
621                 l->set_name ("OptionEditorHeading");
622                 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
623
624                 ++row;
625                 col = 1;
626
627                 /* fine adjust */
628                 set_popdown_strings (_fine_adjust_combo, dumb);
629                 _fine_adjust_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::fine_adjust_modifier_chosen));
630
631                 for (int x = 0; modifiers[x].name; ++x) {
632                         if (modifiers[x].modifier == (guint) ArdourKeyboard::fine_adjust_modifier ()) {
633                                 _fine_adjust_combo.set_active_text (S_(modifiers[x].name));
634                                 break;
635                         }
636                 }
637
638                 l = manage (left_aligned_label (_("Fine adjust using:")));
639                 l->set_name ("OptionsLabel");
640
641                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
642                 t->attach (_fine_adjust_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
643
644                 ++row;
645                 col = 1;
646
647                 /* push points */
648                 set_popdown_strings (_push_points_combo, dumb);
649                 _push_points_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::push_points_modifier_chosen));
650
651                 for (int x = 0; modifiers[x].name; ++x) {
652                         if (modifiers[x].modifier == (guint) ArdourKeyboard::push_points_modifier ()) {
653                                 _push_points_combo.set_active_text (S_(modifiers[x].name));
654                                 break;
655                         }
656                 }
657
658                 l = manage (left_aligned_label (_("Push points using:")));
659                 l->set_name ("OptionsLabel");
660
661                 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
662                 t->attach (_push_points_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
663
664                 _box->pack_start (*t, false, false);
665         }
666
667         void parameter_changed (string const &)
668         {
669                 /* XXX: these aren't really config options... */
670         }
671
672         void set_state_from_config ()
673         {
674                 /* XXX: these aren't really config options... */
675         }
676
677 private:
678
679         void bindings_changed ()
680         {
681                 string const txt = _keyboard_layout_selector.get_active_text();
682
683                 /* XXX: config...?  for all this keyboard stuff */
684
685                 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
686                         if (txt == i->first) {
687                                 if (Keyboard::load_keybindings (i->second)) {
688                                         Keyboard::save_keybindings ();
689                                 }
690                         }
691                 }
692         }
693
694         void edit_modifier_chosen ()
695         {
696                 string const txt = _edit_modifier_combo.get_active_text();
697
698                 for (int i = 0; modifiers[i].name; ++i) {
699                         if (txt == _(modifiers[i].name)) {
700                                 Keyboard::set_edit_modifier (modifiers[i].modifier);
701                                 break;
702                         }
703                 }
704         }
705
706         void delete_modifier_chosen ()
707         {
708                 string const txt = _delete_modifier_combo.get_active_text();
709
710                 for (int i = 0; modifiers[i].name; ++i) {
711                         if (txt == _(modifiers[i].name)) {
712                                 Keyboard::set_delete_modifier (modifiers[i].modifier);
713                                 break;
714                         }
715                 }
716         }
717
718         void copy_modifier_chosen ()
719         {
720                 string const txt = _copy_modifier_combo.get_active_text();
721
722                 for (int i = 0; modifiers[i].name; ++i) {
723                         if (txt == _(modifiers[i].name)) {
724                                 Keyboard::set_copy_modifier (modifiers[i].modifier);
725                                 break;
726                         }
727                 }
728         }
729
730         void insert_note_modifier_chosen ()
731         {
732                 string const txt = _insert_note_modifier_combo.get_active_text();
733
734                 for (int i = 0; modifiers[i].name; ++i) {
735                         if (txt == _(modifiers[i].name)) {
736                                 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
737                                 break;
738                         }
739                 }
740         }
741
742         void snap_modifier_chosen ()
743         {
744                 string const txt = _snap_modifier_combo.get_active_text();
745
746                 for (int i = 0; modifiers[i].name; ++i) {
747                         if (txt == _(modifiers[i].name)) {
748                                 Keyboard::set_snap_modifier (modifiers[i].modifier);
749                                 break;
750                         }
751                 }
752         }
753
754         void snap_delta_modifier_chosen ()
755         {
756                 string const txt = _snap_delta_combo.get_active_text();
757
758                 for (int i = 0; modifiers[i].name; ++i) {
759                         if (txt == _(modifiers[i].name)) {
760                                 Keyboard::set_snap_delta_modifier (modifiers[i].modifier);
761                                 break;
762                         }
763                 }
764         }
765
766         void trim_contents_modifier_chosen ()
767         {
768                 string const txt = _trim_contents_combo.get_active_text();
769
770                 for (int i = 0; modifiers[i].name; ++i) {
771                         if (txt == _(modifiers[i].name)) {
772                                 ArdourKeyboard::set_trim_contents_modifier (modifiers[i].modifier);
773                                 break;
774                         }
775                 }
776         }
777
778         void trim_overlap_modifier_chosen ()
779         {
780                 string const txt = _trim_overlap_combo.get_active_text();
781
782                 for (int i = 0; modifiers[i].name; ++i) {
783                         if (txt == _(modifiers[i].name)) {
784                                 ArdourKeyboard::set_trim_overlap_modifier (modifiers[i].modifier);
785                                 break;
786                         }
787                 }
788         }
789
790         void trim_anchored_modifier_chosen ()
791         {
792                 string const txt = _trim_anchored_combo.get_active_text();
793
794                 for (int i = 0; modifiers[i].name; ++i) {
795                         if (txt == _(modifiers[i].name)) {
796                                 ArdourKeyboard::set_trim_anchored_modifier (modifiers[i].modifier);
797                                 break;
798                         }
799                 }
800         }
801
802         void fine_adjust_modifier_chosen ()
803         {
804                 string const txt = _fine_adjust_combo.get_active_text();
805
806                 for (int i = 0; modifiers[i].name; ++i) {
807                         if (txt == _(modifiers[i].name)) {
808                                 ArdourKeyboard::set_fine_adjust_modifier (modifiers[i].modifier);
809                                 break;
810                         }
811                 }
812         }
813
814         void push_points_modifier_chosen ()
815         {
816                 string const txt = _push_points_combo.get_active_text();
817
818                 for (int i = 0; modifiers[i].name; ++i) {
819                         if (txt == _(modifiers[i].name)) {
820                                 ArdourKeyboard::set_push_points_modifier (modifiers[i].modifier);
821                                 break;
822                         }
823                 }
824         }
825
826         void note_size_relative_modifier_chosen ()
827         {
828                 string const txt = _note_size_relative_combo.get_active_text();
829
830                 for (int i = 0; modifiers[i].name; ++i) {
831                         if (txt == _(modifiers[i].name)) {
832                                 ArdourKeyboard::set_note_size_relative_modifier (modifiers[i].modifier);
833                                 break;
834                         }
835                 }
836         }
837
838         void delete_button_changed ()
839         {
840                 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
841         }
842
843         void edit_button_changed ()
844         {
845                 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
846         }
847
848         void insert_note_button_changed ()
849         {
850                 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
851         }
852
853         ComboBoxText _keyboard_layout_selector;
854         ComboBoxText _edit_modifier_combo;
855         ComboBoxText _delete_modifier_combo;
856         ComboBoxText _copy_modifier_combo;
857         ComboBoxText _insert_note_modifier_combo;
858         ComboBoxText _snap_modifier_combo;
859         ComboBoxText _snap_delta_combo;
860         ComboBoxText _trim_contents_combo;
861         ComboBoxText _trim_overlap_combo;
862         ComboBoxText _trim_anchored_combo;
863         ComboBoxText _trim_jump_combo;
864         ComboBoxText _fine_adjust_combo;
865         ComboBoxText _push_points_combo;
866         ComboBoxText _note_size_relative_combo;
867         Adjustment _delete_button_adjustment;
868         SpinButton _delete_button_spin;
869         Adjustment _edit_button_adjustment;
870         SpinButton _edit_button_spin;
871         Adjustment _insert_note_button_adjustment;
872         SpinButton _insert_note_button_spin;
873
874 };
875
876 class FontScalingOptions : public OptionEditorBox
877 {
878 public:
879         FontScalingOptions (UIConfiguration* uic) :
880                 _ui_config (uic),
881                 _dpi_adjustment (100, 50, 250, 1, 5),
882                 _dpi_slider (_dpi_adjustment)
883         {
884                 _dpi_adjustment.set_value (_ui_config->get_font_scale() / 1024.);
885
886                 Label* l = manage (new Label (_("GUI and Font scaling:")));
887                 l->set_name ("OptionsLabel");
888
889                  const Glib::ustring dflt = _("Default");
890                  const Glib::ustring empty = X_(""); // despite gtk-doc saying so, NULL does not work as reference
891
892                 _dpi_slider.set_name("FontScaleSlider");
893                 _dpi_slider.set_update_policy (UPDATE_DISCONTINUOUS);
894                 _dpi_slider.set_draw_value(false);
895                 _dpi_slider.add_mark(50,  Gtk::POS_TOP, empty);
896                 _dpi_slider.add_mark(60,  Gtk::POS_TOP, empty);
897                 _dpi_slider.add_mark(70,  Gtk::POS_TOP, empty);
898                 _dpi_slider.add_mark(80,  Gtk::POS_TOP, empty);
899                 _dpi_slider.add_mark(90,  Gtk::POS_TOP, empty);
900                 _dpi_slider.add_mark(100, Gtk::POS_TOP, dflt);
901                 _dpi_slider.add_mark(125, Gtk::POS_TOP, empty);
902                 _dpi_slider.add_mark(150, Gtk::POS_TOP, empty);
903                 _dpi_slider.add_mark(175, Gtk::POS_TOP, empty);
904                 _dpi_slider.add_mark(200, Gtk::POS_TOP, empty);
905                 _dpi_slider.add_mark(225, Gtk::POS_TOP, empty);
906                 _dpi_slider.add_mark(250, Gtk::POS_TOP, empty);
907
908                 HBox* h = manage (new HBox);
909                 h->set_spacing (4);
910                 h->pack_start (*l, false, false);
911                 h->pack_start (_dpi_slider, true, true);
912
913                 _box->pack_start (*h, false, false);
914
915                 set_note (_("Adjusting the scale require an application restart to re-layout."));
916
917                 _dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
918         }
919
920         void parameter_changed (string const & p)
921         {
922                 if (p == "font-scale") {
923                         _dpi_adjustment.set_value (_ui_config->get_font_scale() / 1024.);
924                 }
925         }
926
927         void set_state_from_config ()
928         {
929                 parameter_changed ("font-scale");
930         }
931
932 private:
933
934         void dpi_changed ()
935         {
936                 _ui_config->set_font_scale ((long) floor (_dpi_adjustment.get_value() * 1024.));
937                 /* XXX: should be triggered from the parameter changed signal */
938                 reset_dpi ();
939         }
940
941         UIConfiguration* _ui_config;
942         Adjustment _dpi_adjustment;
943         HScale _dpi_slider;
944 };
945
946 class ClipLevelOptions : public OptionEditorBox
947 {
948 public:
949         ClipLevelOptions (UIConfiguration* c) 
950                 : _ui_config (c)
951                 , _clip_level_adjustment (-.5, -50.0, 0.0, 0.1, 1.0) /* units of dB */
952                 , _clip_level_slider (_clip_level_adjustment)
953         {
954                 _clip_level_adjustment.set_value (_ui_config->get_waveform_clip_level ());
955
956                 Label* l = manage (new Label (_("Waveform Clip Level (dBFS):")));
957                 l->set_name ("OptionsLabel");
958
959                 _clip_level_slider.set_update_policy (UPDATE_DISCONTINUOUS);
960                 HBox* h = manage (new HBox);
961                 h->set_spacing (4);
962                 h->pack_start (*l, false, false);
963                 h->pack_start (_clip_level_slider, true, true);
964
965                 _box->pack_start (*h, false, false);
966
967                 _clip_level_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &ClipLevelOptions::clip_level_changed));
968         }
969
970         void parameter_changed (string const & p)
971         {
972                 if (p == "waveform-clip-level") {
973                         _clip_level_adjustment.set_value (_ui_config->get_waveform_clip_level());
974                 }
975         }
976
977         void set_state_from_config ()
978         {
979                 parameter_changed ("waveform-clip-level");
980         }
981
982 private:
983
984         void clip_level_changed ()
985         {
986                 _ui_config->set_waveform_clip_level (_clip_level_adjustment.get_value());
987                 /* XXX: should be triggered from the parameter changed signal */
988                 ArdourCanvas::WaveView::set_clip_level (_clip_level_adjustment.get_value());
989         }
990
991         UIConfiguration* _ui_config;
992         Adjustment _clip_level_adjustment;
993         HScale _clip_level_slider;
994 };
995
996 class BufferingOptions : public OptionEditorBox
997 {
998 public:
999         BufferingOptions (RCConfiguration* c)
1000                 : _rc_config (c)
1001                 , _playback_adjustment (5, 1, 60, 1, 4)
1002                 , _capture_adjustment (5, 1, 60, 1, 4)
1003                 , _playback_slider (_playback_adjustment)
1004                 , _capture_slider (_capture_adjustment)
1005         {
1006                 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
1007
1008                 Label* l = manage (new Label (_("Playback (seconds of buffering):")));
1009                 l->set_name ("OptionsLabel");
1010
1011                 _playback_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1012                 HBox* h = manage (new HBox);
1013                 h->set_spacing (4);
1014                 h->pack_start (*l, false, false);
1015                 h->pack_start (_playback_slider, true, true);
1016
1017                 _box->pack_start (*h, false, false);
1018
1019                 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
1020
1021                 l = manage (new Label (_("Recording (seconds of buffering):")));
1022                 l->set_name ("OptionsLabel");
1023
1024                 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1025                 h = manage (new HBox);
1026                 h->set_spacing (4);
1027                 h->pack_start (*l, false, false);
1028                 h->pack_start (_capture_slider, true, true);
1029
1030                 _box->pack_start (*h, false, false);
1031
1032                 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
1033                 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
1034         }
1035
1036         void parameter_changed (string const & p)
1037         {
1038                 if (p == "playback-buffer-seconds") {
1039                         _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
1040                 } else if (p == "capture-buffer-seconds") {
1041                         _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
1042                 }
1043         }
1044
1045         void set_state_from_config ()
1046         {
1047                 parameter_changed ("playback-buffer-seconds");
1048                 parameter_changed ("capture-buffer-seconds");
1049         }
1050
1051 private:
1052
1053         void playback_changed ()
1054         {
1055                 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
1056         }
1057
1058         void capture_changed ()
1059         {
1060                 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
1061         }
1062
1063         RCConfiguration* _rc_config;
1064         Adjustment _playback_adjustment;
1065         Adjustment _capture_adjustment;
1066         HScale _playback_slider;
1067         HScale _capture_slider;
1068 };
1069
1070 class ControlSurfacesOptions : public OptionEditorBox
1071 {
1072 public:
1073         ControlSurfacesOptions (Gtk::Window& parent)
1074                 : _parent (parent)
1075                 , _ignore_view_change (0)
1076         {
1077                 _store = ListStore::create (_model);
1078                 _view.set_model (_store);
1079                 _view.append_column (_("Control Surface Protocol"), _model.name);
1080                 _view.get_column(0)->set_resizable (true);
1081                 _view.get_column(0)->set_expand (true);
1082                 _view.append_column_editable (_("Enabled"), _model.enabled);
1083                 _view.append_column_editable (_("Feedback"), _model.feedback);
1084
1085                 _box->pack_start (_view, false, false);
1086
1087                 Label* label = manage (new Label);
1088                 label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
1089
1090                 _box->pack_start (*label, false, false);
1091                 label->show ();
1092
1093                 ControlProtocolManager& m = ControlProtocolManager::instance ();
1094                 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
1095                                                 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
1096
1097                 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
1098                 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
1099         }
1100
1101         void parameter_changed (std::string const &)
1102         {
1103
1104         }
1105
1106         void set_state_from_config ()
1107         {
1108                 _store->clear ();
1109
1110                 ControlProtocolManager& m = ControlProtocolManager::instance ();
1111                 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
1112
1113                         if (!(*i)->mandatory) {
1114                                 TreeModel::Row r = *_store->append ();
1115                                 r[_model.name] = (*i)->name;
1116                                 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
1117                                 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
1118                                 r[_model.protocol_info] = *i;
1119                         }
1120                 }
1121         }
1122
1123 private:
1124
1125         void protocol_status_changed (ControlProtocolInfo* cpi) {
1126                 /* find the row */
1127                 TreeModel::Children rows = _store->children();
1128                 
1129                 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
1130                         string n = ((*x)[_model.name]);
1131
1132                         if ((*x)[_model.protocol_info] == cpi) {
1133                                 _ignore_view_change++;
1134                                 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
1135                                 _ignore_view_change--;
1136                                 break;
1137                         }
1138                 }
1139         }
1140
1141         void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
1142         {
1143                 TreeModel::Row r = *i;
1144
1145                 if (_ignore_view_change) {
1146                         return;
1147                 }
1148
1149                 ControlProtocolInfo* cpi = r[_model.protocol_info];
1150                 if (!cpi) {
1151                         return;
1152                 }
1153
1154                 bool const was_enabled = (cpi->protocol != 0);
1155                 bool const is_enabled = r[_model.enabled];
1156
1157
1158                 if (was_enabled != is_enabled) {
1159
1160                         if (!was_enabled) {
1161                                 ControlProtocolManager::instance().activate (*cpi);
1162                         } else {
1163                                 ControlProtocolManager::instance().deactivate (*cpi);
1164                         }
1165                 }
1166
1167                 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
1168                 bool const is_feedback = r[_model.feedback];
1169
1170                 if (was_feedback != is_feedback && cpi->protocol) {
1171                         cpi->protocol->set_feedback (is_feedback);
1172                 }
1173         }
1174
1175         void edit_clicked (GdkEventButton* ev)
1176         {
1177                 if (ev->type != GDK_2BUTTON_PRESS) {
1178                         return;
1179                 }
1180
1181                 std::string name;
1182                 ControlProtocolInfo* cpi;
1183                 TreeModel::Row row;
1184
1185                 row = *(_view.get_selection()->get_selected());
1186                 if (!row[_model.enabled]) {
1187                         return;
1188                 }
1189                 cpi = row[_model.protocol_info];
1190                 if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
1191                         return;
1192                 }
1193                 Box* box = (Box*) cpi->protocol->get_gui ();
1194                 if (!box) {
1195                         return;
1196                 }
1197                 if (box->get_parent()) {
1198                         static_cast<ArdourWindow*>(box->get_parent())->present();
1199                         return;
1200                 }
1201                 string title = row[_model.name];
1202                 /* once created, the window is managed by the surface itself (as ->get_parent())
1203                  * Surface's tear_down_gui() is called on session close, when de-activating
1204                  * or re-initializing a surface.
1205                  * tear_down_gui() hides an deletes the Window if it exists.
1206                  */
1207                 ArdourWindow* win = new ArdourWindow (_parent, title);
1208                 win->set_title ("Control Protocol Options");
1209                 win->add (*box);
1210                 box->show ();
1211                 win->present ();
1212         }
1213
1214         class ControlSurfacesModelColumns : public TreeModelColumnRecord
1215         {
1216         public:
1217
1218                 ControlSurfacesModelColumns ()
1219                 {
1220                         add (name);
1221                         add (enabled);
1222                         add (feedback);
1223                         add (protocol_info);
1224                 }
1225
1226                 TreeModelColumn<string> name;
1227                 TreeModelColumn<bool> enabled;
1228                 TreeModelColumn<bool> feedback;
1229                 TreeModelColumn<ControlProtocolInfo*> protocol_info;
1230         };
1231
1232         Glib::RefPtr<ListStore> _store;
1233         ControlSurfacesModelColumns _model;
1234         TreeView _view;
1235         Gtk::Window& _parent;
1236         PBD::ScopedConnection protocol_status_connection;
1237         uint32_t _ignore_view_change;
1238 };
1239
1240 class VideoTimelineOptions : public OptionEditorBox
1241 {
1242 public:
1243         VideoTimelineOptions (RCConfiguration* c)
1244                 : _rc_config (c)
1245                 , _show_video_export_info_button (_("Show Video Export Info before export"))
1246                 , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
1247                 , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
1248         {
1249                 Table* t = manage (new Table (2, 6));
1250                 t->set_spacings (4);
1251
1252                 t->attach (_video_advanced_setup_button, 0, 2, 0, 1);
1253                 _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
1254                 Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
1255                                             _("<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."));
1256
1257                 Label* l = manage (new Label (_("Video Server URL:")));
1258                 l->set_alignment (0, 0.5);
1259                 t->attach (*l, 0, 1, 1, 2, FILL);
1260                 t->attach (_video_server_url_entry, 1, 2, 1, 2, FILL);
1261                 Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
1262                                             _("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"));
1263
1264                 l = manage (new Label (_("Video Folder:")));
1265                 l->set_alignment (0, 0.5);
1266                 t->attach (*l, 0, 1, 2, 3, FILL);
1267                 t->attach (_video_server_docroot_entry, 1, 2, 2, 3);
1268                 Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
1269                                             _("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."));
1270
1271                 /* small vspace  y=3..4 */
1272
1273                 t->attach (_show_video_export_info_button, 0, 2, 4, 5);
1274                 _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
1275                 Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
1276                                             _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
1277
1278                 t->attach (_show_video_server_dialog_button, 0, 2, 5, 6);
1279                 _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
1280                 Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
1281                                             _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
1282
1283                 _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1284                 _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1285                 _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1286                 _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1287
1288                 _box->pack_start (*t,true,true);
1289         }
1290
1291         void server_url_changed ()
1292         {
1293                 _rc_config->set_video_server_url (_video_server_url_entry.get_text());
1294         }
1295
1296         void server_docroot_changed ()
1297         {
1298                 _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
1299         }
1300
1301         void show_video_export_info_toggled ()
1302         {
1303                 bool const x = _show_video_export_info_button.get_active ();
1304                 _rc_config->set_show_video_export_info (x);
1305         }
1306
1307         void show_video_server_dialog_toggled ()
1308         {
1309                 bool const x = _show_video_server_dialog_button.get_active ();
1310                 _rc_config->set_show_video_server_dialog (x);
1311         }
1312
1313         void video_advanced_setup_toggled ()
1314         {
1315                 bool const x = _video_advanced_setup_button.get_active ();
1316                 _rc_config->set_video_advanced_setup(x);
1317         }
1318
1319         void parameter_changed (string const & p)
1320         {
1321                 if (p == "video-server-url") {
1322                         _video_server_url_entry.set_text (_rc_config->get_video_server_url());
1323                 } else if (p == "video-server-docroot") {
1324                         _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
1325                 } else if (p == "show-video-export-info") {
1326                         bool const x = _rc_config->get_show_video_export_info();
1327                         _show_video_export_info_button.set_active (x);
1328                 } else if (p == "show-video-server-dialog") {
1329                         bool const x = _rc_config->get_show_video_server_dialog();
1330                         _show_video_server_dialog_button.set_active (x);
1331                 } else if (p == "video-advanced-setup") {
1332                         bool const x = _rc_config->get_video_advanced_setup();
1333                         _video_advanced_setup_button.set_active(x);
1334                         _video_server_docroot_entry.set_sensitive(x);
1335                         _video_server_url_entry.set_sensitive(x);
1336                 }
1337         }
1338
1339         void set_state_from_config ()
1340         {
1341                 parameter_changed ("video-server-url");
1342                 parameter_changed ("video-server-docroot");
1343                 parameter_changed ("video-monitor-setup-dialog");
1344                 parameter_changed ("show-video-export-info");
1345                 parameter_changed ("show-video-server-dialog");
1346                 parameter_changed ("video-advanced-setup");
1347         }
1348
1349 private:
1350         RCConfiguration* _rc_config;
1351         Entry _video_server_url_entry;
1352         Entry _video_server_docroot_entry;
1353         CheckButton _show_video_export_info_button;
1354         CheckButton _show_video_server_dialog_button;
1355         CheckButton _video_advanced_setup_button;
1356 };
1357
1358 class PluginOptions : public OptionEditorBox
1359 {
1360 public:
1361         PluginOptions (RCConfiguration* c, UIConfiguration* uic)
1362                 : _rc_config (c)
1363                 , _ui_config (uic)
1364                 , _display_plugin_scan_progress (_("Always Display Plugin Scan Progress"))
1365                 , _discover_vst_on_start (_("Scan for [new] VST Plugins on Application Start"))
1366                 , _discover_au_on_start (_("Scan for AudioUnit Plugins on Application Start"))
1367                 , _timeout_adjustment (0, 0, 3000, 50, 50)
1368                 , _timeout_slider (_timeout_adjustment)
1369         {
1370                 Label *l;
1371                 std::stringstream ss;
1372                 Table* t = manage (new Table (2, 6));
1373                 t->set_spacings (4);
1374                 Button* b;
1375                 int n = 0;
1376
1377                 ss << "<b>" << _("General") << "</b>";
1378                 l = manage (left_aligned_label (ss.str()));
1379                 l->set_use_markup (true);
1380                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1381                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1382
1383                 b = manage (new Button (_("Scan for Plugins")));
1384                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::refresh_clicked));
1385                 t->attach (*b, 0, 2, n, n+1, FILL); ++n;
1386
1387                 t->attach (_display_plugin_scan_progress, 0, 2, n, n+1); ++n;
1388                 _display_plugin_scan_progress.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::display_plugin_scan_progress_toggled));
1389                 Gtkmm2ext::UI::instance()->set_tip (_display_plugin_scan_progress,
1390                                             _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
1391
1392 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
1393                 _timeout_slider.set_digits (0);
1394                 _timeout_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &PluginOptions::timeout_changed));
1395
1396                 Gtkmm2ext::UI::instance()->set_tip(_timeout_slider,
1397                          _("Specify the default timeout for plugin instantiation in 1/10 seconds. Plugins that require more time to load will be blacklisted. A value of 0 disables the timeout."));
1398
1399                 l = manage (left_aligned_label (_("Scan Time Out [deciseconds]")));;
1400                 HBox* h = manage (new HBox);
1401                 h->set_spacing (4);
1402                 h->pack_start (*l, false, false);
1403                 h->pack_start (_timeout_slider, true, true);
1404                 t->attach (*h, 0, 2, n, n+1); ++n;
1405
1406                 ss.str("");
1407                 ss << "<b>" << _("VST") << "</b>";
1408                 l = manage (left_aligned_label (ss.str()));
1409                 l->set_use_markup (true);
1410                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1411                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1412
1413                 b = manage (new Button (_("Clear VST Cache")));
1414                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_cache_clicked));
1415                 t->attach (*b, 0, 1, n, n+1, FILL);
1416
1417                 b = manage (new Button (_("Clear VST Blacklist")));
1418                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_blacklist_clicked));
1419                 t->attach (*b, 1, 2, n, n+1, FILL);
1420                 ++n;
1421
1422                 t->attach (_discover_vst_on_start, 0, 2, n, n+1); ++n;
1423                 _discover_vst_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_vst_on_start_toggled));
1424                 Gtkmm2ext::UI::instance()->set_tip (_discover_vst_on_start,
1425                                             _("<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"));
1426
1427 #ifdef LXVST_SUPPORT
1428                 t->attach (*manage (left_aligned_label (_("Linux VST Path:"))), 0, 1, n, n+1);
1429                 b = manage (new Button (_("Edit")));
1430                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_lxvst_path_clicked));
1431                 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1432 #endif
1433
1434 #ifdef WINDOWS_VST_SUPPORT
1435                 t->attach (*manage (left_aligned_label (_("Windows VST Path:"))), 0, 1, n, n+1);
1436                 b = manage (new Button (_("Edit")));
1437                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_vst_path_clicked));
1438                 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1439 #endif
1440 #endif // any VST
1441
1442 #ifdef AUDIOUNIT_SUPPORT
1443                 ss.str("");
1444                 ss << "<b>" << _("Audio Unit") << "</b>";
1445                 l = manage (left_aligned_label (ss.str()));
1446                 l->set_use_markup (true);
1447                 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1448                 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1449
1450                 t->attach (_discover_au_on_start, 0, 2, n, n+1); ++n;
1451                 _discover_au_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_au_on_start_toggled));
1452                 Gtkmm2ext::UI::instance()->set_tip (_discover_au_on_start,
1453                                             _("<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."));
1454
1455                 ++n;
1456                 b = manage (new Button (_("Clear AU Cache")));
1457                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_cache_clicked));
1458                 t->attach (*b, 0, 1, n, n+1, FILL);
1459
1460                 b = manage (new Button (_("Clear AU Blacklist")));
1461                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_blacklist_clicked));
1462                 t->attach (*b, 1, 2, n, n+1, FILL);
1463                 ++n;
1464 #endif
1465
1466                 _box->pack_start (*t,true,true);
1467         }
1468
1469         void parameter_changed (string const & p) {
1470                 if (p == "show-plugin-scan-window") {
1471                         bool const x = _ui_config->get_show_plugin_scan_window();
1472                         _display_plugin_scan_progress.set_active (x);
1473                 }
1474                 else if (p == "discover-vst-on-start") {
1475                         bool const x = _rc_config->get_discover_vst_on_start();
1476                         _discover_vst_on_start.set_active (x);
1477                 }
1478                 else if (p == "vst-scan-timeout") {
1479                         int const x = _rc_config->get_vst_scan_timeout();
1480                         _timeout_adjustment.set_value (x);
1481                 }
1482                 else if (p == "discover-audio-units") {
1483                         bool const x = _rc_config->get_discover_audio_units();
1484                         _discover_au_on_start.set_active (x);
1485                 }
1486         }
1487
1488         void set_state_from_config () {
1489                 parameter_changed ("show-plugin-scan-window");
1490                 parameter_changed ("discover-vst-on-start");
1491                 parameter_changed ("vst-scan-timeout");
1492                 parameter_changed ("discover-audio-units");
1493         }
1494
1495 private:
1496         RCConfiguration* _rc_config;
1497         UIConfiguration* _ui_config;
1498         CheckButton _display_plugin_scan_progress;
1499         CheckButton _discover_vst_on_start;
1500         CheckButton _discover_au_on_start;
1501         Adjustment _timeout_adjustment;
1502         HScale _timeout_slider;
1503
1504         void display_plugin_scan_progress_toggled () {
1505                 bool const x = _display_plugin_scan_progress.get_active();
1506                 _ui_config->set_show_plugin_scan_window(x);
1507         }
1508
1509         void discover_vst_on_start_toggled () {
1510                 bool const x = _discover_vst_on_start.get_active();
1511                 _rc_config->set_discover_vst_on_start(x);
1512         }
1513
1514         void discover_au_on_start_toggled () {
1515                 bool const x = _discover_au_on_start.get_active();
1516                 _rc_config->set_discover_audio_units(x);
1517         }
1518
1519         void timeout_changed () {
1520                 int x = floor(_timeout_adjustment.get_value());
1521                 _rc_config->set_vst_scan_timeout(x);
1522         }
1523
1524         void clear_vst_cache_clicked () {
1525                 PluginManager::instance().clear_vst_cache();
1526         }
1527
1528         void clear_vst_blacklist_clicked () {
1529                 PluginManager::instance().clear_vst_blacklist();
1530         }
1531
1532         void clear_au_cache_clicked () {
1533                 PluginManager::instance().clear_au_cache();
1534         }
1535
1536         void clear_au_blacklist_clicked () {
1537                 PluginManager::instance().clear_au_blacklist();
1538         }
1539
1540
1541         void edit_vst_path_clicked () {
1542                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1543                                 _("Set Windows VST Search Path"),
1544                                 _rc_config->get_plugin_path_vst(),
1545                                 PluginManager::instance().get_default_windows_vst_path()
1546                         );
1547                 ResponseType r = (ResponseType) pd->run ();
1548                 pd->hide();
1549                 if (r == RESPONSE_ACCEPT) {
1550                         _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
1551                 }
1552                 delete pd;
1553         }
1554
1555         // todo consolidate with edit_vst_path_clicked..
1556         void edit_lxvst_path_clicked () {
1557                 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1558                                 _("Set Linux VST Search Path"),
1559                                 _rc_config->get_plugin_path_lxvst(),
1560                                 PluginManager::instance().get_default_lxvst_path()
1561                                 );
1562                 ResponseType r = (ResponseType) pd->run ();
1563                 pd->hide();
1564                 if (r == RESPONSE_ACCEPT) {
1565                         _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
1566                 }
1567                 delete pd;
1568         }
1569
1570         void refresh_clicked () {
1571                 PluginManager::instance().refresh();
1572         }
1573 };
1574
1575
1576 /** A class which allows control of visibility of some editor components usign
1577  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
1578  *  which has the correct members, but with null widget pointers.  This
1579  *  class allows the user to set visibility of the members, the details
1580  *  of which are stored in a configuration variable which can be watched
1581  *  by parts of the editor that actually contain the widgets whose visibility
1582  *  is being controlled.
1583  */
1584
1585 class VisibilityOption : public Option
1586 {
1587 public:
1588         /** @param name User-visible name for this group.
1589          *  @param g `Dummy' VisibilityGroup (as described above).
1590          *  @param get Method to get the value of the appropriate configuration variable.
1591          *  @param set Method to set the value of the appropriate configuration variable.
1592          */
1593         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1594                 : Option (g->get_state_name(), name)
1595                 , _heading (name)
1596                 , _visibility_group (g)
1597                 , _get (get)
1598                 , _set (set)
1599         {
1600                 /* Watch for changes made by the user to our members */
1601                 _visibility_group->VisibilityChanged.connect_same_thread (
1602                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1603                         );
1604         }
1605
1606         void set_state_from_config ()
1607         {
1608                 /* Set our state from the current configuration */
1609                 _visibility_group->set_state (_get ());
1610         }
1611
1612         void add_to_page (OptionEditorPage* p)
1613         {
1614                 _heading.add_to_page (p);
1615                 add_widget_to_page (p, _visibility_group->list_view ());
1616         }
1617
1618         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1619
1620 private:
1621         void changed ()
1622         {
1623                 /* The user has changed something, so reflect this change
1624                    in the RCConfiguration.
1625                 */
1626                 _set (_visibility_group->get_state_value ());
1627         }
1628         
1629         OptionEditorHeading _heading;
1630         VisibilityGroup* _visibility_group;
1631         sigc::slot<std::string> _get;
1632         sigc::slot<bool, std::string> _set;
1633         PBD::ScopedConnection _visibility_group_connection;
1634 };
1635
1636
1637
1638 RCOptionEditor::RCOptionEditor ()
1639         : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
1640         , _rc_config (Config)
1641         , _ui_config (ARDOUR_UI::config())
1642         , _mixer_strip_visibility ("mixer-element-visibility")
1643 {
1644         /* MISC */
1645
1646         uint32_t hwcpus = hardware_concurrency ();
1647         BoolOption* bo;
1648         BoolComboOption* bco;
1649
1650         if (hwcpus > 1) {
1651                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
1652
1653                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
1654                         "processor-usage",
1655                         _("Signal processing uses"),
1656                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
1657                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
1658                         );
1659
1660                 procs->add (-1, _("all but one processor"));
1661                 procs->add (0, _("all available processors"));
1662
1663                 for (uint32_t i = 1; i <= hwcpus; ++i) {
1664                         procs->add (i, string_compose (_("%1 processors"), i));
1665                 }
1666
1667                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
1668
1669                 add_option (_("Misc"), procs);
1670         }
1671
1672         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
1673
1674         add_option (_("Misc"), new UndoOptions (_rc_config));
1675
1676         add_option (_("Misc"),
1677              new BoolOption (
1678                      "verify-remove-last-capture",
1679                      _("Verify removal of last capture"),
1680                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
1681                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
1682                      ));
1683
1684         add_option (_("Misc"),
1685              new BoolOption (
1686                      "periodic-safety-backups",
1687                      _("Make periodic backups of the session file"),
1688                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1689                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1690                      ));
1691
1692         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
1693
1694         add_option (_("Misc"),
1695              new BoolOption (
1696                      "only-copy-imported-files",
1697                      _("Always copy imported files"),
1698                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_only_copy_imported_files),
1699                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_only_copy_imported_files)
1700                      ));
1701
1702         add_option (_("Misc"), new DirectoryOption (
1703                             X_("default-session-parent-dir"),
1704                             _("Default folder for new sessions:"),
1705                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
1706                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
1707                             ));
1708
1709         add_option (_("Misc"),
1710              new SpinOption<uint32_t> (
1711                      "max-recent-sessions",
1712                      _("Maximum number of recent sessions"),
1713                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
1714                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
1715                      0, 1000, 1, 20
1716                      ));
1717
1718         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
1719
1720         add_option (_("Misc"), new ClickOptions (_rc_config, this));
1721
1722         add_option (_("Misc"),
1723              new FaderOption (
1724                      "click-gain",
1725                      _("Click gain level"),
1726                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
1727                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
1728                      ));
1729
1730         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
1731
1732         add_option (_("Misc"),
1733              new SpinOption<double> (
1734                      "automation-thinning-factor",
1735                      _("Thinning factor (larger value => less data)"),
1736                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
1737                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
1738                      0, 1000, 1, 20
1739                      ));
1740
1741         add_option (_("Misc"),
1742              new SpinOption<double> (
1743                      "automation-interval-msecs",
1744                      _("Automation sampling interval (milliseconds)"),
1745                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
1746                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
1747                      1, 1000, 1, 20
1748                      ));
1749
1750         /* TRANSPORT */
1751
1752         BoolOption* tsf;
1753
1754         tsf = new BoolOption (
1755                      "latched-record-enable",
1756                      _("Keep record-enable engaged on stop"),
1757                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
1758                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
1759                      );
1760         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1761         add_option (_("Transport"), tsf);
1762
1763         tsf = new BoolOption (
1764                      "loop-is-mode",
1765                      _("Play loop is a transport mode"),
1766                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
1767                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
1768                      );
1769         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1770                                             (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
1771                                                "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
1772         add_option (_("Transport"), tsf);
1773         
1774         tsf = new BoolOption (
1775                      "stop-recording-on-xrun",
1776                      _("Stop recording when an xrun occurs"),
1777                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1778                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1779                      );
1780         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1781                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
1782                                                             PROGRAM_NAME));
1783         add_option (_("Transport"), tsf);
1784
1785         tsf = new BoolOption (
1786                      "create-xrun-marker",
1787                      _("Create markers where xruns occur"),
1788                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1789                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1790                      );
1791         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1792         add_option (_("Transport"), tsf);
1793
1794         tsf = new BoolOption (
1795                      "stop-at-session-end",
1796                      _("Stop at the end of the session"),
1797                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1798                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1799                      );
1800         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1801                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1802                                                               "when it reaches the current session end marker\n\n"
1803                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1804                                                             PROGRAM_NAME));
1805         add_option (_("Transport"), tsf);
1806
1807         tsf = new BoolOption (
1808                      "seamless-loop",
1809                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1810                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1811                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1812                      );
1813         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1814                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1815                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
1816                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
1817                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
1818         add_option (_("Transport"), tsf);
1819
1820         tsf = new BoolOption (
1821                      "disable-disarm-during-roll",
1822                      _("Disable per-track record disarm while rolling"),
1823                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1824                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1825                      );
1826         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"));
1827         add_option (_("Transport"), tsf);
1828
1829         tsf = new BoolOption (
1830                      "quieten_at_speed",
1831                      _("12dB gain reduction during fast-forward and fast-rewind"),
1832                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1833                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1834                      );
1835         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1836                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1837         add_option (_("Transport"), tsf);
1838
1839         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1840
1841         _sync_source = new ComboOption<SyncSource> (
1842                 "sync-source",
1843                 _("External timecode source"),
1844                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1845                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1846                 );
1847
1848         add_option (_("Transport"), _sync_source);
1849
1850         _sync_framerate = new BoolOption (
1851                      "timecode-sync-frame-rate",
1852                      _("Match session video frame rate to external timecode"),
1853                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1854                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1855                      );
1856         Gtkmm2ext::UI::instance()->set_tip 
1857                 (_sync_framerate->tip_widget(),
1858                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1859                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1860                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1861                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1862                                    "timecode standard and the session standard."), PROGRAM_NAME));
1863
1864         add_option (_("Transport"), _sync_framerate);
1865
1866         _sync_genlock = new BoolOption (
1867                 "timecode-source-is-synced",
1868                 _("Sync-lock timecode to clock (disable drift compensation)"),
1869                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1870                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1871                 );
1872         Gtkmm2ext::UI::instance()->set_tip 
1873                 (_sync_genlock->tip_widget(),
1874                  string_compose (_("<b>When enabled</b> %1 will never varispeed when slaved to external timecode. "
1875                                    "Sync Lock indicates that the selected external timecode source shares clock-sync "
1876                                    "(Black &amp; Burst, Wordclock, etc) with the audio interface. "
1877                                    "This option disables drift compensation. The transport speed is fixed at 1.0. "
1878                                    "Vari-speed LTC will be ignored and cause drift."
1879                                    "\n\n"
1880                                    "<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
1881                                    "timecode sources shares clock sync."
1882                                   ), PROGRAM_NAME));
1883
1884
1885         add_option (_("Transport"), _sync_genlock);
1886
1887         _sync_source_2997 = new BoolOption (
1888                 "timecode-source-2997",
1889                 _("Lock to 29.9700 fps instead of 30000/1001"),
1890                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1891                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1892                 );
1893         Gtkmm2ext::UI::instance()->set_tip
1894                 (_sync_source_2997->tip_widget(),
1895                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1896                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1897                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1898                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1899                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1900                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1901                          ));
1902
1903         add_option (_("Transport"), _sync_source_2997);
1904
1905         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1906
1907         _ltc_port = new ComboStringOption (
1908                 "ltc-source-port",
1909                 _("LTC incoming port"),
1910                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1911                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1912                 );
1913
1914         vector<string> physical_inputs;
1915         physical_inputs.push_back (_("None"));
1916         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1917         _ltc_port->set_popdown_strings (physical_inputs);
1918
1919         populate_sync_options ();
1920
1921         add_option (_("Transport"), _ltc_port);
1922
1923         // TODO; rather disable this button than not compile it..
1924         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1925
1926         add_option (_("Transport"),
1927                     new BoolOption (
1928                             "send-ltc",
1929                             _("Enable LTC generator"),
1930                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1931                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1932                             ));
1933
1934         _ltc_send_continuously = new BoolOption (
1935                             "ltc-send-continuously",
1936                             _("Send LTC while stopped"),
1937                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1938                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1939                             );
1940         Gtkmm2ext::UI::instance()->set_tip
1941                 (_ltc_send_continuously->tip_widget(),
1942                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
1943         add_option (_("Transport"), _ltc_send_continuously);
1944
1945         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1946         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1947         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1948         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1949
1950         Gtkmm2ext::UI::instance()->set_tip
1951                 (_ltc_volume_slider->tip_widget(),
1952                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1953
1954         add_option (_("Transport"), _ltc_volume_slider);
1955         parameter_changed ("send-ltc");
1956
1957         parameter_changed ("sync-source");
1958
1959         /* EDITOR */
1960
1961         add_option (S_("Editor"),
1962              new BoolOption (
1963                      "draggable-playhead",
1964                      _("Allow dragging of playhead"),
1965                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_draggable_playhead),
1966                      sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_draggable_playhead)
1967                      ));
1968
1969         add_option (_("Editor"),
1970              new BoolOption (
1971                      "automation-follows-regions",
1972                      _("Move relevant automation when audio regions are moved"),
1973                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1974                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1975                      ));
1976
1977         add_option (_("Editor"),
1978              new BoolOption (
1979                      "show-track-meters",
1980                      _("Show meters on tracks in the editor"),
1981                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_track_meters),
1982                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_track_meters)
1983                      ));
1984
1985         add_option (_("Editor"),
1986              new BoolOption (
1987                      "show-editor-meter",
1988                      _("Display master-meter in the toolbar"),
1989                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_editor_meter),
1990                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_editor_meter)
1991                      ));
1992
1993         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
1994                         "default-fade-shape",
1995                         _("Default fade shape"),
1996                         sigc::mem_fun (*_rc_config,
1997                                 &RCConfiguration::get_default_fade_shape),
1998                         sigc::mem_fun (*_rc_config,
1999                                 &RCConfiguration::set_default_fade_shape)
2000                         );
2001
2002         fadeshape->add (FadeLinear,
2003                         _("Linear (for highly correlated material)"));
2004         fadeshape->add (FadeConstantPower, _("Constant power"));
2005         fadeshape->add (FadeSymmetric, _("Symmetric"));
2006         fadeshape->add (FadeSlow, _("Slow"));
2007         fadeshape->add (FadeFast, _("Fast"));
2008
2009         add_option (_("Editor"), fadeshape);
2010
2011
2012         bco = new BoolComboOption (
2013                      "use-overlap-equivalency",
2014                      _("Regions in active edit groups are edited together"),
2015                      _("whenever they overlap in time"),
2016                      _("only if they have identical length, position and origin"),
2017                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
2018                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
2019                      );
2020
2021         add_option (_("Editor"), bco);
2022
2023         ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
2024                 "layer-model",
2025                 _("Layering model"),
2026                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
2027                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
2028                 );
2029
2030         lm->add (LaterHigher, _("later is higher"));
2031         lm->add (Manual, _("manual layering"));
2032         add_option (_("Editor"), lm);
2033
2034         add_option (_("Editor"),
2035              new BoolOption (
2036                      "rubberbanding-snaps-to-grid",
2037                      _("Make rubberband selection rectangle snap to the grid"),
2038                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_rubberbanding_snaps_to_grid),
2039                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_rubberbanding_snaps_to_grid)
2040                      ));
2041
2042         add_option (_("Editor"),
2043              new BoolOption (
2044                      "show-waveforms",
2045                      _("Show waveforms in regions"),
2046                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms),
2047                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms)
2048                      ));
2049
2050         add_option (_("Editor"),
2051              new BoolComboOption (
2052                      "show-region-gain-envelopes",
2053                      _("Show gain envelopes in audio regions"),
2054                      _("in all modes"),
2055                      _("only in region gain mode"),
2056                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_region_gain),
2057                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_region_gain)
2058                      ));
2059
2060         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
2061                 "waveform-scale",
2062                 _("Waveform scale"),
2063                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_scale),
2064                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_scale)
2065                 );
2066
2067         wfs->add (Linear, _("linear"));
2068         wfs->add (Logarithmic, _("logarithmic"));
2069
2070         add_option (_("Editor"), wfs);
2071
2072         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
2073                 "waveform-shape",
2074                 _("Waveform shape"),
2075                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_shape),
2076                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_shape)
2077                 );
2078
2079         wfsh->add (Traditional, _("traditional"));
2080         wfsh->add (Rectified, _("rectified"));
2081
2082         add_option (_("Editor"), wfsh);
2083
2084         add_option (_("Editor"), new ClipLevelOptions (_ui_config));
2085
2086         add_option (_("Editor"),
2087              new BoolOption (
2088                      "show-waveforms-while-recording",
2089                      _("Show waveforms for audio while it is being recorded"),
2090                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms_while_recording),
2091                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms_while_recording)
2092                      ));
2093
2094         add_option (_("Editor"),
2095                     new BoolOption (
2096                             "show-zoom-tools",
2097                             _("Show zoom toolbar"),
2098                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_zoom_tools),
2099                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_zoom_tools)
2100                             ));
2101
2102         add_option (_("Editor"),
2103                     new BoolOption (
2104                             "update-editor-during-summary-drag",
2105                             _("Update editor window during drags of the summary"),
2106                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_update_editor_during_summary_drag),
2107                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_update_editor_during_summary_drag)
2108                             ));
2109
2110         bo = new BoolOption (
2111                      "name-new-markers",
2112                      _("Name new markers"),
2113                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_name_new_markers),
2114                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_name_new_markers)
2115                 );
2116         
2117         add_option (_("Editor"), bo);
2118         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."
2119                                                                 "\n\nYou can always rename markers by right-clicking on them"));
2120
2121         add_option (_("Editor"),
2122             new BoolOption (
2123                     "autoscroll-editor",
2124                     _("Auto-scroll editor window when dragging near its edges"),
2125                     sigc::mem_fun (*_ui_config, &UIConfiguration::get_autoscroll_editor),
2126                     sigc::mem_fun (*_ui_config, &UIConfiguration::set_autoscroll_editor)
2127                     ));
2128
2129         ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
2130                     "region-selection-after-split",
2131                     _("After splitting selected regions, select"),
2132                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
2133                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
2134
2135         // TODO: decide which of these modes are really useful
2136         rsas->add(None, _("no regions"));
2137         // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
2138         // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
2139         rsas->add(NewlyCreatedBoth, _("newly-created regions"));
2140         // rsas->add(Existing, _("unmodified regions in the existing selection"));
2141         // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
2142         // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
2143         rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
2144
2145         add_option (_("Editor"), rsas);
2146
2147
2148         /* AUDIO */
2149
2150         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
2151
2152         add_option (_("Audio"), new BufferingOptions (_rc_config));
2153
2154         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
2155
2156         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
2157                 "monitoring-model",
2158                 _("Record monitoring handled by"),
2159                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
2160                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
2161                 );
2162
2163         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
2164                 mm->add (HardwareMonitoring, _("via Audio Driver"));
2165         }
2166
2167         string prog (PROGRAM_NAME);
2168         boost::algorithm::to_lower (prog);
2169         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
2170         mm->add (ExternalMonitoring, _("audio hardware"));
2171
2172         add_option (_("Audio"), mm);
2173
2174         add_option (_("Audio"),
2175              new BoolOption (
2176                      "tape-machine-mode",
2177                      _("Tape machine mode"),
2178                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
2179                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
2180                      ));
2181
2182         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
2183
2184         add_option (_("Audio"),
2185                     new BoolOption (
2186                             "auto-connect-standard-busses",
2187                             _("Auto-connect master/monitor busses"),
2188                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
2189                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
2190                             ));
2191
2192         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
2193                 "input-auto-connect",
2194                 _("Connect track inputs"),
2195                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
2196                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
2197                 );
2198
2199         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
2200         iac->add (ManualConnect, _("manually"));
2201
2202         add_option (_("Audio"), iac);
2203
2204         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
2205                 "output-auto-connect",
2206                 _("Connect track and bus outputs"),
2207                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
2208                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
2209                 );
2210
2211         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
2212         oac->add (AutoConnectMaster, _("automatically to master bus"));
2213         oac->add (ManualConnect, _("manually"));
2214
2215         add_option (_("Audio"), oac);
2216
2217         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
2218
2219         add_option (_("Audio"),
2220              new BoolOption (
2221                      "denormal-protection",
2222                      _("Use DC bias to protect against denormals"),
2223                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
2224                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
2225                      ));
2226
2227         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
2228                 "denormal-model",
2229                 _("Processor handling"),
2230                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
2231                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
2232                 );
2233
2234         int dmsize = 1;
2235         dm->add (DenormalNone, _("no processor handling"));
2236
2237         FPU fpu;
2238
2239         if (fpu.has_flush_to_zero()) {
2240                 ++dmsize;
2241                 dm->add (DenormalFTZ, _("use FlushToZero"));
2242         } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
2243                 _rc_config->set_denormal_model(DenormalNone);
2244         }
2245
2246         if (fpu.has_denormals_are_zero()) {
2247                 ++dmsize;
2248                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
2249         } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
2250                 _rc_config->set_denormal_model(DenormalNone);
2251         }
2252
2253         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
2254                 ++dmsize;
2255                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
2256         } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
2257                 _rc_config->set_denormal_model(DenormalNone);
2258         }
2259
2260         if (dmsize == 1) {
2261                 dm->set_sensitive(false);
2262         }
2263
2264         add_option (_("Audio"), dm);
2265
2266         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
2267
2268         add_option (_("Audio"),
2269              new BoolOption (
2270                      "plugins-stop-with-transport",
2271                      _("Silence plugins when the transport is stopped"),
2272                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
2273                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
2274                      ));
2275
2276         add_option (_("Audio"),
2277              new BoolOption (
2278                      "new-plugins-active",
2279                      _("Make new plugins active"),
2280                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
2281                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
2282                      ));
2283
2284         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
2285
2286         add_option (_("Audio"),
2287              new BoolOption (
2288                      "auto-analyse-audio",
2289                      _("Enable automatic analysis of audio"),
2290                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
2291                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
2292                      ));
2293
2294         add_option (_("Audio"),
2295              new BoolOption (
2296                      "replicate-missing-region-channels",
2297                      _("Replicate missing region channels"),
2298                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
2299                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
2300                      ));
2301
2302         /* SOLO AND MUTE */
2303
2304         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
2305
2306         add_option (_("Solo / mute"),
2307              new FaderOption (
2308                      "solo-mute-gain",
2309                      _("Solo-in-place mute cut (dB)"),
2310                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
2311                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
2312                      ));
2313
2314         _solo_control_is_listen_control = new BoolOption (
2315                 "solo-control-is-listen-control",
2316                 _("Solo controls are Listen controls"),
2317                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
2318                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
2319                 );
2320
2321         add_option (_("Solo / mute"), _solo_control_is_listen_control);
2322
2323         _listen_position = new ComboOption<ListenPosition> (
2324                 "listen-position",
2325                 _("Listen Position"),
2326                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
2327                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
2328                 );
2329
2330         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
2331         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
2332
2333         add_option (_("Solo / mute"), _listen_position);
2334
2335         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
2336                 "pfl-position",
2337                 _("PFL signals come from"),
2338                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
2339                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
2340                 );
2341
2342         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2343         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2344
2345         add_option (_("Solo / mute"), pp);
2346
2347         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2348                 "afl-position",
2349                 _("AFL signals come from"),
2350                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2351                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2352                 );
2353
2354         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2355         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2356
2357         add_option (_("Solo / mute"), pa);
2358
2359         parameter_changed ("use-monitor-bus");
2360
2361         add_option (_("Solo / mute"),
2362              new BoolOption (
2363                      "exclusive-solo",
2364                      _("Exclusive solo"),
2365                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2366                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2367                      ));
2368
2369         add_option (_("Solo / mute"),
2370              new BoolOption (
2371                      "show-solo-mutes",
2372                      _("Show solo muting"),
2373                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2374                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2375                      ));
2376
2377         add_option (_("Solo / mute"),
2378              new BoolOption (
2379                      "solo-mute-override",
2380                      _("Soloing overrides muting"),
2381                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2382                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2383                      ));
2384
2385         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
2386
2387         add_option (_("Solo / mute"),
2388              new BoolOption (
2389                      "mute-affects-pre-fader",
2390                      _("Mute affects pre-fader sends"),
2391                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2392                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2393                      ));
2394
2395         add_option (_("Solo / mute"),
2396              new BoolOption (
2397                      "mute-affects-post-fader",
2398                      _("Mute affects post-fader sends"),
2399                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2400                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2401                      ));
2402
2403         add_option (_("Solo / mute"),
2404              new BoolOption (
2405                      "mute-affects-control-outs",
2406                      _("Mute affects control outputs"),
2407                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2408                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2409                      ));
2410
2411         add_option (_("Solo / mute"),
2412              new BoolOption (
2413                      "mute-affects-main-outs",
2414                      _("Mute affects main outputs"),
2415                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2416                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2417                      ));
2418
2419         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
2420
2421         add_option (_("Solo / mute"),
2422              new BoolOption (
2423                      "link-send-and-route-panner",
2424                      _("Link panners of Aux and External Sends with main panner by default"),
2425                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2426                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2427                      ));
2428
2429         add_option (_("MIDI"),
2430                     new SpinOption<float> (
2431                             "midi-readahead",
2432                             _("MIDI read-ahead time (seconds)"),
2433                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2434                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2435                             0.1, 10, 0.1, 1,
2436                             "", 1.0, 1
2437                             ));
2438
2439         add_option (_("MIDI"),
2440                     new BoolOption (
2441                             "send-midi-clock",
2442                             _("Send MIDI Clock"),
2443                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2444                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2445                             ));
2446
2447         add_option (_("MIDI"),
2448                     new BoolOption (
2449                             "send-mtc",
2450                             _("Send MIDI Time Code"),
2451                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2452                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2453                             ));
2454
2455         add_option (_("MIDI"),
2456                     new SpinOption<int> (
2457                             "mtc-qf-speed-tolerance",
2458                             _("Percentage either side of normal transport speed to transmit MTC"),
2459                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2460                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2461                             0, 20, 1, 5
2462                             ));
2463
2464         add_option (_("MIDI"),
2465                     new BoolOption (
2466                             "mmc-control",
2467                             _("Obey MIDI Machine Control commands"),
2468                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2469                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2470                             ));
2471
2472         add_option (_("MIDI"),
2473                     new BoolOption (
2474                             "send-mmc",
2475                             _("Send MIDI Machine Control commands"),
2476                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2477                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2478                             ));
2479
2480         add_option (_("MIDI"),
2481                     new BoolOption (
2482                             "midi-feedback",
2483                             _("Send MIDI control feedback"),
2484                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2485                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2486                             ));
2487
2488         add_option (_("MIDI"),
2489              new SpinOption<uint8_t> (
2490                      "mmc-receive-device-id",
2491                      _("Inbound MMC device ID"),
2492                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2493                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2494                      0, 128, 1, 10
2495                      ));
2496
2497         add_option (_("MIDI"),
2498              new SpinOption<uint8_t> (
2499                      "mmc-send-device-id",
2500                      _("Outbound MMC device ID"),
2501                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2502                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2503                      0, 128, 1, 10
2504                      ));
2505
2506         add_option (_("MIDI"),
2507              new SpinOption<int32_t> (
2508                      "initial-program-change",
2509                      _("Initial program change"),
2510                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2511                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2512                      -1, 65536, 1, 10
2513                      ));
2514
2515         add_option (_("MIDI"),
2516                     new BoolOption (
2517                             "display-first-midi-bank-as-zero",
2518                             _("Display first MIDI bank/program as 0"),
2519                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2520                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2521                             ));
2522
2523         add_option (_("MIDI"),
2524              new BoolOption (
2525                      "never-display-periodic-midi",
2526                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2527                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_never_display_periodic_midi),
2528                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_never_display_periodic_midi)
2529                      ));
2530
2531         add_option (_("MIDI"),
2532              new BoolOption (
2533                      "sound-midi-notes",
2534                      _("Sound MIDI notes as they are selected"),
2535                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_sound_midi_notes),
2536                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_sound_midi_notes)
2537                      ));
2538
2539         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2540
2541         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2542                 "midi-audition-synth-uri",
2543                 _("Midi Audition Synth (LV2)"),
2544                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2545                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2546                 );
2547
2548         audition_synth->add(X_(""), _("None"));
2549         PluginInfoList all_plugs;
2550         PluginManager& manager (PluginManager::instance());
2551 #ifdef LV2_SUPPORT
2552         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2553
2554         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2555                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2556                 if (!(*i)->is_instrument()) continue;
2557                 if ((*i)->type != ARDOUR::LV2) continue;
2558                 audition_synth->add((*i)->unique_id, (*i)->name);
2559         }
2560 #endif
2561
2562         add_option (_("MIDI"), audition_synth);
2563
2564         /* USER INTERACTION */
2565
2566         if (
2567 #ifdef PLATFORM_WINDOWS
2568                         true
2569 #else
2570                         getenv ("ARDOUR_BUNDLED")
2571 #endif
2572            )
2573         {
2574                 add_option (_("User interaction"), 
2575                             new BoolOption (
2576                                     "enable-translation",
2577                                     string_compose (_("Use translations of %1 messages\n"
2578                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2579                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2580                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2581                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2582         }
2583
2584         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2585
2586         add_option (_("User interaction"), new KeyboardOptions);
2587
2588         /* Control Surfaces */
2589
2590         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2591
2592         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2593                 "remote-model",
2594                 _("Control surface remote ID"),
2595                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2596                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2597                 );
2598
2599         rm->add (UserOrdered, _("assigned by user"));
2600         rm->add (MixerOrdered, _("follows order of mixer"));
2601
2602         add_option (_("Control Surfaces"), rm);
2603
2604         /* VIDEO Timeline */
2605         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2606
2607 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2608         /* Plugin options (currrently VST only) */
2609         add_option (_("Plugins"), new PluginOptions (_rc_config, _ui_config));
2610 #endif
2611
2612         /* INTERFACE */
2613
2614         add_option (S_("Preferences|GUI"),
2615              new BoolOption (
2616                      "widget-prelight",
2617                      _("Graphically indicate mouse pointer hovering over various widgets"),
2618                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_widget_prelight),
2619                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_widget_prelight)
2620                      ));
2621
2622 #ifdef TOOLTIPS_GOT_FIXED
2623         add_option (S_("Preferences|GUI"),
2624              new BoolOption (
2625                      "use-tooltips",
2626                      _("Show tooltips if mouse hovers over a control"),
2627                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_use_tooltips),
2628                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_use_tooltips)
2629                      ));
2630 #endif
2631
2632         add_option (S_("Preferences|GUI"),
2633              new BoolOption (
2634                      "show-name-highlight",
2635                      _("Use name highlight bars in region displays (requires a restart)"),
2636                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_name_highlight),
2637                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_name_highlight)
2638                      ));
2639
2640 #ifndef GTKOSX
2641         /* font scaling does nothing with GDK/Quartz */
2642         add_option (S_("Preferences|GUI"), new FontScalingOptions (_ui_config));
2643 #endif
2644
2645         add_option (S_("GUI"),
2646                     new BoolOption (
2647                             "super-rapid-clock-update",
2648                             _("update transport clock display at FPS instead of every 100ms"),
2649                             sigc::mem_fun (*_ui_config, &UIConfiguration::get_super_rapid_clock_update),
2650                             sigc::mem_fun (*_ui_config, &UIConfiguration::set_super_rapid_clock_update)
2651                             ));
2652
2653         /* Lock GUI timeout */
2654
2655         Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2656         HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2657                                                 _("Lock timeout (seconds)"),
2658                                                 lts,
2659                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_lock_gui_after_seconds),
2660                                                 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_lock_gui_after_seconds)
2661                         );
2662         slts->scale().set_digits (0);
2663         Gtkmm2ext::UI::instance()->set_tip
2664                 (slts->tip_widget(),
2665                  _("Lock GUI after this many idle seconds (zero to never lock)"));
2666         add_option (S_("Preferences|GUI"), slts);
2667
2668         /* The names of these controls must be the same as those given in MixerStrip
2669            for the actual widgets being controlled.
2670         */
2671         _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2672         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2673         _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2674         _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2675         _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2676         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2677         
2678         add_option (
2679                 S_("Preferences|GUI"),
2680                 new VisibilityOption (
2681                         _("Mixer Strip"),
2682                         &_mixer_strip_visibility,
2683                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_mixer_strip_visibility),
2684                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_mixer_strip_visibility)
2685                         )
2686                 );
2687
2688         add_option (S_("Preferences|GUI"),
2689              new BoolOption (
2690                      "default-narrow_ms",
2691                      _("Use narrow strips in the mixer by default"),
2692                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_default_narrow_ms),
2693                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_default_narrow_ms)
2694                      ));
2695
2696         add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2697
2698         ComboOption<float>* mht = new ComboOption<float> (
2699                 "meter-hold",
2700                 _("Peak hold time"),
2701                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_hold),
2702                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_hold)
2703                 );
2704
2705         mht->add (MeterHoldOff, _("off"));
2706         mht->add (MeterHoldShort, _("short"));
2707         mht->add (MeterHoldMedium, _("medium"));
2708         mht->add (MeterHoldLong, _("long"));
2709
2710         add_option (S_("Preferences|Metering"), mht);
2711
2712         ComboOption<float>* mfo = new ComboOption<float> (
2713                 "meter-falloff",
2714                 _("DPM fall-off"),
2715                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2716                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2717                 );
2718
2719         mfo->add (METER_FALLOFF_OFF,      _("off"));
2720         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2721         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2722         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2723         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2724         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2725         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2726         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2727         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2728
2729         add_option (S_("Preferences|Metering"), mfo);
2730
2731         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2732                 "meter-line-up-level",
2733                 _("Meter line-up level; 0dBu"),
2734                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_level),
2735                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_level)
2736                 );
2737
2738         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2739         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2740         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2741         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2742
2743         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."));
2744
2745         add_option (S_("Preferences|Metering"), mlu);
2746
2747         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2748                 "meter-line-up-din",
2749                 _("IEC1/DIN Meter line-up level; 0dBu"),
2750                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_din),
2751                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_din)
2752                 );
2753
2754         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2755         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2756         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2757         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2758
2759         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2760
2761         add_option (S_("Preferences|Metering"), mld);
2762
2763         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2764                 "meter-vu-standard",
2765                 _("VU Meter standard"),
2766                 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_vu_standard),
2767                 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_vu_standard)
2768                 );
2769
2770         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2771         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2772         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2773         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2774
2775         add_option (S_("Preferences|Metering"), mvu);
2776
2777         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2778         HSliderOption *mpks = new HSliderOption("meter-peak",
2779                         _("Peak threshold [dBFS]"),
2780                         mpk,
2781                         sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_peak),
2782                         sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_peak)
2783                         );
2784
2785         Gtkmm2ext::UI::instance()->set_tip
2786                 (mpks->tip_widget(),
2787                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2788
2789         add_option (S_("Preferences|Metering"), mpks);
2790
2791         add_option (S_("Preferences|Metering"),
2792              new BoolOption (
2793                      "meter-style-led",
2794                      _("LED meter style"),
2795                      sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_style_led),
2796                      sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_style_led)
2797                      ));
2798
2799         /* and now the theme manager */
2800
2801         ThemeManager* tm = manage (new ThemeManager);
2802         add_page (_("Theme"), *tm);
2803 }
2804
2805 void
2806 RCOptionEditor::parameter_changed (string const & p)
2807 {
2808         OptionEditor::parameter_changed (p);
2809
2810         if (p == "use-monitor-bus") {
2811                 bool const s = Config->get_use_monitor_bus ();
2812                 if (!s) {
2813                         /* we can't use this if we don't have a monitor bus */
2814                         Config->set_solo_control_is_listen_control (false);
2815                 }
2816                 _solo_control_is_listen_control->set_sensitive (s);
2817                 _listen_position->set_sensitive (s);
2818         } else if (p == "sync-source") {
2819                 _sync_source->set_sensitive (true);
2820                 if (_session) {
2821                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2822                 }
2823                 switch(Config->get_sync_source()) {
2824                 case ARDOUR::MTC:
2825                 case ARDOUR::LTC:
2826                         _sync_genlock->set_sensitive (true);
2827                         _sync_framerate->set_sensitive (true);
2828                         _sync_source_2997->set_sensitive (true);
2829                         break;
2830                 default:
2831                         _sync_genlock->set_sensitive (false);
2832                         _sync_framerate->set_sensitive (false);
2833                         _sync_source_2997->set_sensitive (false);
2834                         break;
2835                 }
2836         } else if (p == "send-ltc") {
2837                 bool const s = Config->get_send_ltc ();
2838                 _ltc_send_continuously->set_sensitive (s);
2839                 _ltc_volume_slider->set_sensitive (s);
2840         }
2841 }
2842
2843 void RCOptionEditor::ltc_generator_volume_changed () {
2844         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2845 }
2846
2847 void
2848 RCOptionEditor::populate_sync_options ()
2849 {
2850         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2851
2852         _sync_source->clear ();
2853
2854         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2855                 _sync_source->add (*i, sync_source_to_string (*i));
2856         }
2857
2858         if (sync_opts.empty()) {
2859                 _sync_source->set_sensitive(false);
2860         } else {
2861                 if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
2862                         _rc_config->set_sync_source(sync_opts.front());
2863                 }
2864         }
2865 }