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