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