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