merge with master and fix 4 conflicts by hand
[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         ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
1573                         "default-fade-shape",
1574                         _("Default fade shape"),
1575                         sigc::mem_fun (*_rc_config,
1576                                 &RCConfiguration::get_default_fade_shape),
1577                         sigc::mem_fun (*_rc_config,
1578                                 &RCConfiguration::set_default_fade_shape)
1579                         );
1580
1581         fadeshape->add (FadeLinear,
1582                         _("Linear (for highly correlated material)"));
1583         fadeshape->add (FadeConstantPower, _("Constant power"));
1584         fadeshape->add (FadeSymmetric, _("Symmetric"));
1585         fadeshape->add (FadeSlow, _("Slow"));
1586         fadeshape->add (FadeFast, _("Fast"));
1587
1588         add_option (_("Editor"), fadeshape);
1589
1590
1591         bco = new BoolComboOption (
1592                      "use-overlap-equivalency",
1593                      _("Regions in active edit groups are edited together"),
1594                      _("whenever they overlap in time"),
1595                      _("only if they have identical length, position and origin"),
1596                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1597                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1598                      );
1599
1600         add_option (_("Editor"), bco);
1601
1602         add_option (_("Editor"),
1603              new BoolOption (
1604                      "rubberbanding-snaps-to-grid",
1605                      _("Make rubberband selection rectangle snap to the grid"),
1606                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1607                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1608                      ));
1609
1610         add_option (_("Editor"),
1611              new BoolOption (
1612                      "show-waveforms",
1613                      _("Show waveforms in regions"),
1614                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1615                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1616                      ));
1617
1618         add_option (_("Editor"),
1619              new BoolComboOption (
1620                      "show-region-gain-envelopes",
1621                      _("Show gain envelopes in audio regions"),
1622                      _("in all modes"),
1623                      _("only in region gain mode"),
1624                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1625                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1626                      ));
1627
1628         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1629                 "waveform-scale",
1630                 _("Waveform scale"),
1631                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1632                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1633                 );
1634
1635         wfs->add (Linear, _("linear"));
1636         wfs->add (Logarithmic, _("logarithmic"));
1637
1638         add_option (_("Editor"), wfs);
1639
1640         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1641                 "waveform-shape",
1642                 _("Waveform shape"),
1643                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1644                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1645                 );
1646
1647         wfsh->add (Traditional, _("traditional"));
1648         wfsh->add (Rectified, _("rectified"));
1649
1650         add_option (_("Editor"), wfsh);
1651
1652         add_option (_("Editor"), new ClipLevelOptions (_rc_config));
1653
1654         add_option (_("Editor"),
1655              new BoolOption (
1656                      "show-waveforms-while-recording",
1657                      _("Show waveforms for audio while it is being recorded"),
1658                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1659                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1660                      ));
1661
1662         add_option (_("Editor"),
1663                     new BoolOption (
1664                             "show-zoom-tools",
1665                             _("Show zoom toolbar"),
1666                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1667                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1668                             ));
1669
1670         add_option (_("Editor"),
1671                     new BoolOption (
1672                             "update-editor-during-summary-drag",
1673                             _("Update editor window during drags of the summary"),
1674                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1675                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1676                             ));
1677
1678         add_option (_("Editor"),
1679              new BoolOption (
1680                      "link-editor-and-mixer-selection",
1681                      _("Synchronise editor and mixer selection"),
1682                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1683                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1684                      ));
1685
1686         bo = new BoolOption (
1687                      "name-new-markers",
1688                      _("Name new markers"),
1689                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1690                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1691                 );
1692         
1693         add_option (_("Editor"), bo);
1694         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."
1695                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1696
1697         add_option (_("Editor"),
1698             new BoolOption (
1699                     "autoscroll-editor",
1700                     _("Auto-scroll editor window when dragging near its edges"),
1701                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1702                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1703                     ));
1704
1705         /* AUDIO */
1706
1707         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1708
1709         add_option (_("Audio"), new BufferingOptions (_rc_config));
1710
1711         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1712
1713         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1714                 "monitoring-model",
1715                 _("Record monitoring handled by"),
1716                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1717                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1718                 );
1719
1720         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
1721                 mm->add (HardwareMonitoring, _("via Audio Driver"));
1722         }
1723
1724         string prog (PROGRAM_NAME);
1725         boost::algorithm::to_lower (prog);
1726         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
1727         mm->add (ExternalMonitoring, _("audio hardware"));
1728
1729         add_option (_("Audio"), mm);
1730
1731         add_option (_("Audio"),
1732              new BoolOption (
1733                      "tape-machine-mode",
1734                      _("Tape machine mode"),
1735                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1736                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1737                      ));
1738
1739         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1740
1741         add_option (_("Audio"),
1742                     new BoolOption (
1743                             "auto-connect-standard-busses",
1744                             _("Auto-connect master/monitor busses"),
1745                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1746                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1747                             ));
1748
1749         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1750                 "input-auto-connect",
1751                 _("Connect track inputs"),
1752                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1753                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1754                 );
1755
1756         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1757         iac->add (ManualConnect, _("manually"));
1758
1759         add_option (_("Audio"), iac);
1760
1761         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1762                 "output-auto-connect",
1763                 _("Connect track and bus outputs"),
1764                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1765                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1766                 );
1767
1768         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1769         oac->add (AutoConnectMaster, _("automatically to master bus"));
1770         oac->add (ManualConnect, _("manually"));
1771
1772         add_option (_("Audio"), oac);
1773
1774         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1775
1776         add_option (_("Audio"),
1777              new BoolOption (
1778                      "denormal-protection",
1779                      _("Use DC bias to protect against denormals"),
1780                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1781                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1782                      ));
1783
1784         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1785                 "denormal-model",
1786                 _("Processor handling"),
1787                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1788                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1789                 );
1790
1791         dm->add (DenormalNone, _("no processor handling"));
1792
1793         FPU fpu;
1794
1795         if (fpu.has_flush_to_zero()) {
1796                 dm->add (DenormalFTZ, _("use FlushToZero"));
1797         }
1798
1799         if (fpu.has_denormals_are_zero()) {
1800                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1801         }
1802
1803         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1804                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1805         }
1806
1807         add_option (_("Audio"), dm);
1808
1809         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1810
1811         add_option (_("Audio"),
1812              new BoolOption (
1813                      "plugins-stop-with-transport",
1814                      _("Silence plugins when the transport is stopped"),
1815                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1816                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1817                      ));
1818
1819         add_option (_("Audio"),
1820              new BoolOption (
1821                      "new-plugins-active",
1822                      _("Make new plugins active"),
1823                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1824                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1825                      ));
1826
1827         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
1828
1829         add_option (_("Audio"),
1830              new BoolOption (
1831                      "auto-analyse-audio",
1832                      _("Enable automatic analysis of audio"),
1833                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1834                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1835                      ));
1836
1837         add_option (_("Audio"),
1838              new BoolOption (
1839                      "replicate-missing-region-channels",
1840                      _("Replicate missing region channels"),
1841                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1842                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1843                      ));
1844
1845         /* SOLO AND MUTE */
1846
1847         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
1848
1849         add_option (_("Solo / mute"),
1850              new FaderOption (
1851                      "solo-mute-gain",
1852                      _("Solo-in-place mute cut (dB)"),
1853                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1854                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1855                      ));
1856
1857         _solo_control_is_listen_control = new BoolOption (
1858                 "solo-control-is-listen-control",
1859                 _("Solo controls are Listen controls"),
1860                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1861                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1862                 );
1863
1864         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1865
1866         _listen_position = new ComboOption<ListenPosition> (
1867                 "listen-position",
1868                 _("Listen Position"),
1869                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1870                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1871                 );
1872
1873         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1874         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1875
1876         add_option (_("Solo / mute"), _listen_position);
1877
1878         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1879                 "pfl-position",
1880                 _("PFL signals come from"),
1881                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1882                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1883                 );
1884
1885         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1886         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1887
1888         add_option (_("Solo / mute"), pp);
1889
1890         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1891                 "afl-position",
1892                 _("AFL signals come from"),
1893                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1894                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1895                 );
1896
1897         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1898         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1899
1900         add_option (_("Solo / mute"), pa);
1901
1902         parameter_changed ("use-monitor-bus");
1903
1904         add_option (_("Solo / mute"),
1905              new BoolOption (
1906                      "exclusive-solo",
1907                      _("Exclusive solo"),
1908                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1909                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1910                      ));
1911
1912         add_option (_("Solo / mute"),
1913              new BoolOption (
1914                      "show-solo-mutes",
1915                      _("Show solo muting"),
1916                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1917                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1918                      ));
1919
1920         add_option (_("Solo / mute"),
1921              new BoolOption (
1922                      "solo-mute-override",
1923                      _("Soloing overrides muting"),
1924                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1925                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1926                      ));
1927
1928         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1929
1930         add_option (_("Solo / mute"),
1931              new BoolOption (
1932                      "mute-affects-pre-fader",
1933                      _("Mute affects pre-fader sends"),
1934                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1935                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1936                      ));
1937
1938         add_option (_("Solo / mute"),
1939              new BoolOption (
1940                      "mute-affects-post-fader",
1941                      _("Mute affects post-fader sends"),
1942                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1943                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1944                      ));
1945
1946         add_option (_("Solo / mute"),
1947              new BoolOption (
1948                      "mute-affects-control-outs",
1949                      _("Mute affects control outputs"),
1950                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1951                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1952                      ));
1953
1954         add_option (_("Solo / mute"),
1955              new BoolOption (
1956                      "mute-affects-main-outs",
1957                      _("Mute affects main outputs"),
1958                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1959                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1960                      ));
1961
1962         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
1963
1964         add_option (_("Solo / mute"),
1965              new BoolOption (
1966                      "link-send-and-route-panner",
1967                      _("Link panners of Aux and External Sends with main panner by default"),
1968                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
1969                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
1970                      ));
1971
1972         add_option (_("MIDI"),
1973                     new BoolOption (
1974                             "send-midi-clock",
1975                             _("Send MIDI Clock"),
1976                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1977                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1978                             ));
1979
1980         add_option (_("MIDI"),
1981                     new BoolOption (
1982                             "send-mtc",
1983                             _("Send MIDI Time Code"),
1984                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1985                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1986                             ));
1987
1988         add_option (_("MIDI"),
1989                     new SpinOption<int> (
1990                             "mtc-qf-speed-tolerance",
1991                             _("Percentage either side of normal transport speed to transmit MTC"),
1992                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1993                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1994                             0, 20, 1, 5
1995                             ));
1996
1997         add_option (_("MIDI"),
1998                     new BoolOption (
1999                             "mmc-control",
2000                             _("Obey MIDI Machine Control commands"),
2001                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2002                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2003                             ));
2004
2005         add_option (_("MIDI"),
2006                     new BoolOption (
2007                             "send-mmc",
2008                             _("Send MIDI Machine Control commands"),
2009                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2010                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2011                             ));
2012
2013         add_option (_("MIDI"),
2014                     new BoolOption (
2015                             "midi-feedback",
2016                             _("Send MIDI control feedback"),
2017                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2018                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2019                             ));
2020
2021         add_option (_("MIDI"),
2022              new SpinOption<uint8_t> (
2023                      "mmc-receive-device-id",
2024                      _("Inbound MMC device ID"),
2025                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2026                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2027                      0, 128, 1, 10
2028                      ));
2029
2030         add_option (_("MIDI"),
2031              new SpinOption<uint8_t> (
2032                      "mmc-send-device-id",
2033                      _("Outbound MMC device ID"),
2034                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2035                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2036                      0, 128, 1, 10
2037                      ));
2038
2039         add_option (_("MIDI"),
2040              new SpinOption<int32_t> (
2041                      "initial-program-change",
2042                      _("Initial program change"),
2043                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2044                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2045                      -1, 65536, 1, 10
2046                      ));
2047
2048         add_option (_("MIDI"),
2049                     new BoolOption (
2050                             "display-first-midi-bank-as-zero",
2051                             _("Display first MIDI bank/program as 0"),
2052                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2053                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2054                             ));
2055
2056         add_option (_("MIDI"),
2057              new BoolOption (
2058                      "never-display-periodic-midi",
2059                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2060                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
2061                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
2062                      ));
2063
2064         add_option (_("MIDI"),
2065              new BoolOption (
2066                      "sound-midi-notes",
2067                      _("Sound MIDI notes as they are selected"),
2068                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
2069                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
2070                      ));
2071
2072         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2073
2074         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2075                 "midi-audition-synth-uri",
2076                 _("Midi Audition Synth (LV2)"),
2077                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2078                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2079                 );
2080
2081         audition_synth->add(X_(""), _("None"));
2082         PluginInfoList all_plugs;
2083         PluginManager& manager (PluginManager::instance());
2084 #ifdef LV2_SUPPORT
2085         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2086
2087         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2088                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2089                 if (!(*i)->is_instrument()) continue;
2090                 if ((*i)->type != ARDOUR::LV2) continue;
2091                 audition_synth->add((*i)->unique_id, (*i)->name);
2092         }
2093 #endif
2094
2095         add_option (_("MIDI"), audition_synth);
2096
2097         /* USER INTERACTION */
2098
2099         if (getenv ("ARDOUR_BUNDLED")) {
2100                 add_option (_("User interaction"), 
2101                             new BoolOption (
2102                                     "enable-translation",
2103                                     string_compose (_("Use translations of %1 messages\n"
2104                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2105                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2106                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2107                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2108         }
2109
2110         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2111
2112         add_option (_("User interaction"), new KeyboardOptions);
2113
2114         /* Control Surfaces */
2115
2116         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2117
2118         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2119                 "remote-model",
2120                 _("Control surface remote ID"),
2121                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2122                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2123                 );
2124
2125         rm->add (UserOrdered, _("assigned by user"));
2126         rm->add (MixerOrdered, _("follows order of mixer"));
2127
2128         add_option (_("Control Surfaces"), rm);
2129
2130         /* VIDEO Timeline */
2131         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2132
2133 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
2134         /* Plugin options (currrently VST only) */
2135         add_option (_("Plugins"), new PluginOptions (_rc_config));
2136 #endif
2137
2138         /* INTERFACE */
2139
2140         add_option (S_("Preferences|GUI"),
2141              new BoolOption (
2142                      "widget-prelight",
2143                      _("Graphically indicate mouse pointer hovering over various widgets"),
2144                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
2145                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
2146                      ));
2147
2148         add_option (S_("Preferences|GUI"),
2149              new BoolOption (
2150                      "use-tooltips",
2151                      _("Show tooltips if mouse hovers over a control"),
2152                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
2153                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
2154                      ));
2155
2156         add_option (S_("Preferences|GUI"),
2157              new BoolOption (
2158                      "show-name-highlight",
2159                      _("Use name highlight bars in region displays"),
2160                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_name_highlight),
2161                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_name_highlight)
2162                      ));
2163
2164 #ifndef GTKOSX
2165         /* font scaling does nothing with GDK/Quartz */
2166         add_option (S_("Preferences|GUI"), new FontScalingOptions (_rc_config));
2167 #endif
2168
2169         add_option (S_("GUI"),
2170                     new BoolOption (
2171                             "super-rapid-clock-update",
2172                             _("update transport clock display every 40ms instead of every 100ms"),
2173                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_super_rapid_clock_update),
2174                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_super_rapid_clock_update)
2175                             ));
2176
2177         /* The names of these controls must be the same as those given in MixerStrip
2178            for the actual widgets being controlled.
2179         */
2180         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2181         _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
2182         _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
2183         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2184         _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
2185         _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
2186         
2187         add_option (
2188                 S_("Preferences|GUI"),
2189                 new VisibilityOption (
2190                         _("Mixer Strip"),
2191                         &_mixer_strip_visibility,
2192                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
2193                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
2194                         )
2195                 );
2196
2197         add_option (S_("Preferences|GUI"),
2198              new BoolOption (
2199                      "default-narrow_ms",
2200                      _("Use narrow strips in the mixer by default"),
2201                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
2202                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
2203                      ));
2204
2205         add_option (S_("Preferences|GUI"), new OptionEditorHeading (_("Metering")));
2206
2207         ComboOption<float>* mht = new ComboOption<float> (
2208                 "meter-hold",
2209                 _("Peak hold time"),
2210                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
2211                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
2212                 );
2213
2214         mht->add (MeterHoldOff, _("off"));
2215         mht->add (MeterHoldShort, _("short"));
2216         mht->add (MeterHoldMedium, _("medium"));
2217         mht->add (MeterHoldLong, _("long"));
2218
2219         add_option (S_("Preferences|GUI"), mht);
2220
2221         ComboOption<float>* mfo = new ComboOption<float> (
2222                 "meter-falloff",
2223                 _("DPM fall-off"),
2224                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2225                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2226                 );
2227
2228         mfo->add (METER_FALLOFF_OFF,      _("off"));
2229         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2230         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2231         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2232         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2233         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2234         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2235         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2236         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2237
2238         add_option (S_("Preferences|GUI"), mfo);
2239
2240         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2241                 "meter-line-up-level",
2242                 _("Meter line-up level; 0dBu"),
2243                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_level),
2244                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_level)
2245                 );
2246
2247         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2248         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2249         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2250         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2251
2252         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."));
2253
2254         add_option (S_("Preferences|GUI"), mlu);
2255
2256         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2257                 "meter-line-up-din",
2258                 _("IEC1/DIN Meter line-up level; 0dBu"),
2259                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_din),
2260                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_din)
2261                 );
2262
2263         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2264         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2265         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2266         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2267
2268         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2269
2270         add_option (S_("Preferences|GUI"), mld);
2271
2272         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2273                 "meter-vu-standard",
2274                 _("VU Meter standard"),
2275                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_vu_standard),
2276                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_vu_standard)
2277                 );
2278
2279         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2280         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2281         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2282         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2283
2284         add_option (S_("Preferences|GUI"), mvu);
2285
2286         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2287         HSliderOption *mpks = new HSliderOption("meter-peak",
2288                         _("Peak threshold [dBFS]"),
2289                         mpk,
2290                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_peak),
2291                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_peak)
2292                         );
2293
2294         Gtkmm2ext::UI::instance()->set_tip
2295                 (mpks->tip_widget(),
2296                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2297
2298         add_option (S_("Preferences|GUI"), mpks);
2299
2300         add_option (S_("Preferences|GUI"),
2301              new BoolOption (
2302                      "meter-style-led",
2303                      _("LED meter style"),
2304                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_style_led),
2305                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_style_led)
2306                      ));
2307
2308 }
2309
2310 void
2311 RCOptionEditor::parameter_changed (string const & p)
2312 {
2313         OptionEditor::parameter_changed (p);
2314
2315         if (p == "use-monitor-bus") {
2316                 bool const s = Config->get_use_monitor_bus ();
2317                 if (!s) {
2318                         /* we can't use this if we don't have a monitor bus */
2319                         Config->set_solo_control_is_listen_control (false);
2320                 }
2321                 _solo_control_is_listen_control->set_sensitive (s);
2322                 _listen_position->set_sensitive (s);
2323         } else if (p == "sync-source") {
2324                 _sync_source->set_sensitive (true);
2325                 if (_session) {
2326                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2327                 }
2328                 switch(Config->get_sync_source()) {
2329                 case ARDOUR::MTC:
2330                 case ARDOUR::LTC:
2331                         _sync_genlock->set_sensitive (true);
2332                         _sync_framerate->set_sensitive (true);
2333                         _sync_source_2997->set_sensitive (true);
2334                         break;
2335                 default:
2336                         _sync_genlock->set_sensitive (false);
2337                         _sync_framerate->set_sensitive (false);
2338                         _sync_source_2997->set_sensitive (false);
2339                         break;
2340                 }
2341         } else if (p == "send-ltc") {
2342                 bool const s = Config->get_send_ltc ();
2343                 _ltc_send_continuously->set_sensitive (s);
2344                 _ltc_volume_slider->set_sensitive (s);
2345         }
2346 }
2347
2348 void RCOptionEditor::ltc_generator_volume_changed () {
2349         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2350 }
2351
2352 void
2353 RCOptionEditor::populate_sync_options ()
2354 {
2355         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2356
2357         _sync_source->clear ();
2358
2359         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2360                 _sync_source->add (*i, sync_source_to_string (*i));
2361         }
2362 }