d4a5c57705a5200f633f6a5c11319bf095012016
[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 WINDOWS_VST_SUPPORT
1064                 t->attach (*manage (left_aligned_label (_("Windows VST Path:"))), 0, 1, n, n+1);
1065                 b = manage (new Button (_("Edit")));
1066                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_vst_path_clicked));
1067                 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1068 #endif
1069
1070 #ifdef LXVST_SUPPORT
1071                 t->attach (*manage (left_aligned_label (_("Linux VST:"))), 0, 1, n, n+1);
1072                 b = manage (new Button (_("Edit")));
1073                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_lxvst_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         add_option (_("Transport"), tsf);
1362
1363         tsf = new BoolOption (
1364                      "create-xrun-marker",
1365                      _("Create markers where xruns occur"),
1366                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1367                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1368                      );
1369         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1370         add_option (_("Transport"), tsf);
1371
1372         tsf = new BoolOption (
1373                      "stop-at-session-end",
1374                      _("Stop at the end of the session"),
1375                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1376                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1377                      );
1378         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1379                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1380                                                               "when it reaches the current session end marker\n\n"
1381                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1382                                                             PROGRAM_NAME));
1383         add_option (_("Transport"), tsf);
1384
1385         tsf = new BoolOption (
1386                      "seamless-loop",
1387                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1388                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1389                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1390                      );
1391         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1392                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1393                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
1394                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
1395                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
1396         add_option (_("Transport"), tsf);
1397
1398         tsf = new BoolOption (
1399                      "disable-disarm-during-roll",
1400                      _("Disable per-track record disarm while rolling"),
1401                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1402                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1403                      );
1404         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"));
1405         add_option (_("Transport"), tsf);
1406
1407         tsf = new BoolOption (
1408                      "quieten_at_speed",
1409                      _("12dB gain reduction during fast-forward and fast-rewind"),
1410                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1411                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1412                      );
1413         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1414                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1415         add_option (_("Transport"), tsf);
1416
1417         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1418
1419         _sync_source = new ComboOption<SyncSource> (
1420                 "sync-source",
1421                 _("External timecode source"),
1422                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1423                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1424                 );
1425
1426         populate_sync_options ();
1427         add_option (_("Transport"), _sync_source);
1428
1429         _sync_framerate = new BoolOption (
1430                      "timecode-sync-frame-rate",
1431                      _("Match session video frame rate to external timecode"),
1432                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1433                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1434                      );
1435         Gtkmm2ext::UI::instance()->set_tip 
1436                 (_sync_framerate->tip_widget(),
1437                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1438                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1439                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1440                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1441                                    "timecode standard and the session standard."), PROGRAM_NAME));
1442
1443         add_option (_("Transport"), _sync_framerate);
1444
1445         _sync_genlock = new BoolOption (
1446                 "timecode-source-is-synced",
1447                 _("External timecode is sync locked"),
1448                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1449                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1450                 );
1451         Gtkmm2ext::UI::instance()->set_tip 
1452                 (_sync_genlock->tip_widget(), 
1453                  _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface."));
1454
1455
1456         add_option (_("Transport"), _sync_genlock);
1457
1458         _sync_source_2997 = new BoolOption (
1459                 "timecode-source-2997",
1460                 _("Lock to 29.9700 fps instead of 30000/1001"),
1461                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1462                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1463                 );
1464         Gtkmm2ext::UI::instance()->set_tip
1465                 (_sync_source_2997->tip_widget(),
1466                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1467                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1468                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1469                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1470                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1471                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1472                          ));
1473
1474         add_option (_("Transport"), _sync_source_2997);
1475
1476         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1477
1478         _ltc_port = new ComboStringOption (
1479                 "ltc-source-port",
1480                 _("LTC incoming port"),
1481                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1482                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1483                 );
1484
1485         vector<string> physical_inputs;
1486         physical_inputs.push_back (_("None"));
1487         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1488         _ltc_port->set_popdown_strings (physical_inputs);
1489
1490         add_option (_("Transport"), _ltc_port);
1491
1492         // TODO; rather disable this button than not compile it..
1493         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1494
1495         add_option (_("Transport"),
1496                     new BoolOption (
1497                             "send-ltc",
1498                             _("Enable LTC generator"),
1499                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1500                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1501                             ));
1502
1503         _ltc_send_continuously = new BoolOption (
1504                             "ltc-send-continuously",
1505                             _("send LTC while stopped"),
1506                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1507                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1508                             );
1509         Gtkmm2ext::UI::instance()->set_tip
1510                 (_ltc_send_continuously->tip_widget(),
1511                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
1512         add_option (_("Transport"), _ltc_send_continuously);
1513
1514         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1515         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1516         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1517         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1518
1519         Gtkmm2ext::UI::instance()->set_tip
1520                 (_ltc_volume_slider->tip_widget(),
1521                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1522
1523         add_option (_("Transport"), _ltc_volume_slider);
1524         parameter_changed ("send-ltc");
1525
1526         parameter_changed ("sync-source");
1527
1528         /* EDITOR */
1529
1530         add_option (_("Editor"),
1531              new BoolOption (
1532                      "link-region-and-track-selection",
1533                      _("Link selection of regions and tracks"),
1534                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1535                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1536                      ));
1537
1538         add_option (_("Editor"),
1539              new BoolOption (
1540                      "automation-follows-regions",
1541                      _("Move relevant automation when audio regions are moved"),
1542                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1543                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1544                      ));
1545
1546         add_option (_("Editor"),
1547              new BoolOption (
1548                      "show-track-meters",
1549                      _("Show meters on tracks in the editor"),
1550                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1551                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1552                      ));
1553
1554         add_option (_("Editor"),
1555              new BoolOption (
1556                      "show-editor-meter",
1557                      _("Display master-meter in the toolbar"),
1558                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_editor_meter),
1559                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_editor_meter)
1560                      ));
1561
1562         bco = new BoolComboOption (
1563                      "use-overlap-equivalency",
1564                      _("Regions in active edit groups are edited together"),
1565                      _("whenever they overlap in time"),
1566                      _("only if they have identical length, position and origin"),
1567                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1568                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1569                      );
1570
1571         add_option (_("Editor"), bco);
1572
1573         add_option (_("Editor"),
1574              new BoolOption (
1575                      "rubberbanding-snaps-to-grid",
1576                      _("Make rubberband selection rectangle snap to the grid"),
1577                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1578                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1579                      ));
1580
1581         add_option (_("Editor"),
1582              new BoolOption (
1583                      "show-waveforms",
1584                      _("Show waveforms in regions"),
1585                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1586                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1587                      ));
1588
1589         add_option (_("Editor"),
1590              new BoolComboOption (
1591                      "show-region-gain-envelopes",
1592                      _("Show gain envelopes in audio regions"),
1593                      _("in all modes"),
1594                      _("only in region gain mode"),
1595                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1596                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1597                      ));
1598
1599         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1600                 "waveform-scale",
1601                 _("Waveform scale"),
1602                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1603                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1604                 );
1605
1606         wfs->add (Linear, _("linear"));
1607         wfs->add (Logarithmic, _("logarithmic"));
1608
1609         add_option (_("Editor"), wfs);
1610
1611         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1612                 "waveform-shape",
1613                 _("Waveform shape"),
1614                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1615                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1616                 );
1617
1618         wfsh->add (Traditional, _("traditional"));
1619         wfsh->add (Rectified, _("rectified"));
1620
1621         add_option (_("Editor"), wfsh);
1622
1623         add_option (_("Editor"), new ClipLevelOptions (_rc_config));
1624
1625         add_option (_("Editor"),
1626              new BoolOption (
1627                      "show-waveforms-while-recording",
1628                      _("Show waveforms for audio while it is being recorded"),
1629                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1630                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1631                      ));
1632
1633         add_option (_("Editor"),
1634                     new BoolOption (
1635                             "show-zoom-tools",
1636                             _("Show zoom toolbar"),
1637                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1638                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1639                             ));
1640
1641         add_option (_("Editor"),
1642                     new BoolOption (
1643                             "update-editor-during-summary-drag",
1644                             _("Update editor window during drags of the summary"),
1645                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1646                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1647                             ));
1648
1649         add_option (_("Editor"),
1650              new BoolOption (
1651                      "link-editor-and-mixer-selection",
1652                      _("Synchronise editor and mixer selection"),
1653                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1654                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1655                      ));
1656
1657         bo = new BoolOption (
1658                      "name-new-markers",
1659                      _("Name new markers"),
1660                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1661                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1662                 );
1663         
1664         add_option (_("Editor"), bo);
1665         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."
1666                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1667
1668         add_option (_("Editor"),
1669             new BoolOption (
1670                     "autoscroll-editor",
1671                     _("Auto-scroll editor window when dragging near its edges"),
1672                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1673                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1674                     ));
1675
1676         /* AUDIO */
1677
1678         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1679
1680         add_option (_("Audio"), new BufferingOptions (_rc_config));
1681
1682         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1683
1684         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1685                 "monitoring-model",
1686                 _("Record monitoring handled by"),
1687                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1688                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1689                 );
1690
1691         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
1692                 mm->add (HardwareMonitoring, _("via Audio Driver"));
1693         }
1694
1695         string prog (PROGRAM_NAME);
1696         boost::algorithm::to_lower (prog);
1697         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
1698         mm->add (ExternalMonitoring, _("audio hardware"));
1699
1700         add_option (_("Audio"), mm);
1701
1702         add_option (_("Audio"),
1703              new BoolOption (
1704                      "tape-machine-mode",
1705                      _("Tape machine mode"),
1706                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1707                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1708                      ));
1709
1710         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1711
1712         add_option (_("Audio"),
1713                     new BoolOption (
1714                             "auto-connect-standard-busses",
1715                             _("Auto-connect master/monitor busses"),
1716                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1717                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1718                             ));
1719
1720         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1721                 "input-auto-connect",
1722                 _("Connect track inputs"),
1723                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1724                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1725                 );
1726
1727         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1728         iac->add (ManualConnect, _("manually"));
1729
1730         add_option (_("Audio"), iac);
1731
1732         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1733                 "output-auto-connect",
1734                 _("Connect track and bus outputs"),
1735                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1736                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1737                 );
1738
1739         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1740         oac->add (AutoConnectMaster, _("automatically to master bus"));
1741         oac->add (ManualConnect, _("manually"));
1742
1743         add_option (_("Audio"), oac);
1744
1745         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1746
1747         add_option (_("Audio"),
1748              new BoolOption (
1749                      "denormal-protection",
1750                      _("Use DC bias to protect against denormals"),
1751                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1752                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1753                      ));
1754
1755         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1756                 "denormal-model",
1757                 _("Processor handling"),
1758                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1759                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1760                 );
1761
1762         dm->add (DenormalNone, _("no processor handling"));
1763
1764         FPU fpu;
1765
1766         if (fpu.has_flush_to_zero()) {
1767                 dm->add (DenormalFTZ, _("use FlushToZero"));
1768         }
1769
1770         if (fpu.has_denormals_are_zero()) {
1771                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1772         }
1773
1774         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1775                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1776         }
1777
1778         add_option (_("Audio"), dm);
1779
1780         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1781
1782         add_option (_("Audio"),
1783              new BoolOption (
1784                      "plugins-stop-with-transport",
1785                      _("Silence plugins when the transport is stopped"),
1786                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1787                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1788                      ));
1789
1790         add_option (_("Audio"),
1791              new BoolOption (
1792                      "new-plugins-active",
1793                      _("Make new plugins active"),
1794                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1795                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1796                      ));
1797
1798         add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
1799
1800         add_option (_("Audio"),
1801              new BoolOption (
1802                      "auto-analyse-audio",
1803                      _("Enable automatic analysis of audio"),
1804                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1805                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1806                      ));
1807
1808         add_option (_("Audio"),
1809              new BoolOption (
1810                      "replicate-missing-region-channels",
1811                      _("Replicate missing region channels"),
1812                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1813                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1814                      ));
1815
1816         /* SOLO AND MUTE */
1817
1818         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
1819
1820         add_option (_("Solo / mute"),
1821              new FaderOption (
1822                      "solo-mute-gain",
1823                      _("Solo-in-place mute cut (dB)"),
1824                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1825                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1826                      ));
1827
1828         _solo_control_is_listen_control = new BoolOption (
1829                 "solo-control-is-listen-control",
1830                 _("Solo controls are Listen controls"),
1831                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1832                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1833                 );
1834
1835         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1836
1837         _listen_position = new ComboOption<ListenPosition> (
1838                 "listen-position",
1839                 _("Listen Position"),
1840                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1841                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1842                 );
1843
1844         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1845         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1846
1847         add_option (_("Solo / mute"), _listen_position);
1848
1849         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1850                 "pfl-position",
1851                 _("PFL signals come from"),
1852                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1853                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1854                 );
1855
1856         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1857         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1858
1859         add_option (_("Solo / mute"), pp);
1860
1861         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1862                 "afl-position",
1863                 _("AFL signals come from"),
1864                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1865                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1866                 );
1867
1868         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1869         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1870
1871         add_option (_("Solo / mute"), pa);
1872
1873         parameter_changed ("use-monitor-bus");
1874
1875         add_option (_("Solo / mute"),
1876              new BoolOption (
1877                      "exclusive-solo",
1878                      _("Exclusive solo"),
1879                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1880                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1881                      ));
1882
1883         add_option (_("Solo / mute"),
1884              new BoolOption (
1885                      "show-solo-mutes",
1886                      _("Show solo muting"),
1887                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1888                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1889                      ));
1890
1891         add_option (_("Solo / mute"),
1892              new BoolOption (
1893                      "solo-mute-override",
1894                      _("Soloing overrides muting"),
1895                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1896                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1897                      ));
1898
1899         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1900
1901         add_option (_("Solo / mute"),
1902              new BoolOption (
1903                      "mute-affects-pre-fader",
1904                      _("Mute affects pre-fader sends"),
1905                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1906                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1907                      ));
1908
1909         add_option (_("Solo / mute"),
1910              new BoolOption (
1911                      "mute-affects-post-fader",
1912                      _("Mute affects post-fader sends"),
1913                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1914                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1915                      ));
1916
1917         add_option (_("Solo / mute"),
1918              new BoolOption (
1919                      "mute-affects-control-outs",
1920                      _("Mute affects control outputs"),
1921                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1922                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1923                      ));
1924
1925         add_option (_("Solo / mute"),
1926              new BoolOption (
1927                      "mute-affects-main-outs",
1928                      _("Mute affects main outputs"),
1929                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1930                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1931                      ));
1932
1933         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
1934
1935         add_option (_("Solo / mute"),
1936              new BoolOption (
1937                      "link-send-and-route-panner",
1938                      _("Link panners of Aux and External Sends with main panner by default"),
1939                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
1940                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
1941                      ));
1942
1943         add_option (_("MIDI"),
1944                     new BoolOption (
1945                             "send-midi-clock",
1946                             _("Send MIDI Clock"),
1947                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1948                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1949                             ));
1950
1951         add_option (_("MIDI"),
1952                     new BoolOption (
1953                             "send-mtc",
1954                             _("Send MIDI Time Code"),
1955                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1956                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1957                             ));
1958
1959         add_option (_("MIDI"),
1960                     new SpinOption<int> (
1961                             "mtc-qf-speed-tolerance",
1962                             _("Percentage either side of normal transport speed to transmit MTC"),
1963                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1964                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1965                             0, 20, 1, 5
1966                             ));
1967
1968         add_option (_("MIDI"),
1969                     new BoolOption (
1970                             "mmc-control",
1971                             _("Obey MIDI Machine Control commands"),
1972                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1973                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1974                             ));
1975
1976         add_option (_("MIDI"),
1977                     new BoolOption (
1978                             "send-mmc",
1979                             _("Send MIDI Machine Control commands"),
1980                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1981                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1982                             ));
1983
1984         add_option (_("MIDI"),
1985                     new BoolOption (
1986                             "midi-feedback",
1987                             _("Send MIDI control feedback"),
1988                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1989                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1990                             ));
1991
1992         add_option (_("MIDI"),
1993              new SpinOption<uint8_t> (
1994                      "mmc-receive-device-id",
1995                      _("Inbound MMC device ID"),
1996                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1997                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1998                      0, 128, 1, 10
1999                      ));
2000
2001         add_option (_("MIDI"),
2002              new SpinOption<uint8_t> (
2003                      "mmc-send-device-id",
2004                      _("Outbound MMC device ID"),
2005                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2006                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2007                      0, 128, 1, 10
2008                      ));
2009
2010         add_option (_("MIDI"),
2011              new SpinOption<int32_t> (
2012                      "initial-program-change",
2013                      _("Initial program change"),
2014                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2015                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2016                      -1, 65536, 1, 10
2017                      ));
2018
2019         add_option (_("MIDI"),
2020                     new BoolOption (
2021                             "display-first-midi-bank-as-zero",
2022                             _("Display first MIDI bank/program as 0"),
2023                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2024                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2025                             ));
2026
2027         add_option (_("MIDI"),
2028              new BoolOption (
2029                      "never-display-periodic-midi",
2030                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2031                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
2032                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
2033                      ));
2034
2035         add_option (_("MIDI"),
2036              new BoolOption (
2037                      "sound-midi-notes",
2038                      _("Sound MIDI notes as they are selected"),
2039                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
2040                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
2041                      ));
2042
2043         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2044
2045         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2046                 "midi-audition-synth-uri",
2047                 _("Midi Audition Synth (LV2)"),
2048                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2049                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2050                 );
2051
2052         audition_synth->add(X_(""), _("None"));
2053         PluginInfoList all_plugs;
2054         PluginManager& manager (PluginManager::instance());
2055 #ifdef LV2_SUPPORT
2056         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2057
2058         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2059                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2060                 if (!(*i)->is_instrument()) continue;
2061                 if ((*i)->type != ARDOUR::LV2) continue;
2062                 audition_synth->add((*i)->unique_id, (*i)->name);
2063         }
2064 #endif
2065
2066         add_option (_("MIDI"), audition_synth);
2067
2068         /* USER INTERACTION */
2069
2070         if (getenv ("ARDOUR_BUNDLED")) {
2071                 add_option (_("User interaction"), 
2072                             new BoolOption (
2073                                     "enable-translation",
2074                                     string_compose (_("Use translations of %1 messages\n"
2075                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
2076                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2077                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
2078                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2079         }
2080
2081         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2082
2083         add_option (_("User interaction"), new KeyboardOptions);
2084
2085         /* Control Surfaces */
2086
2087         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2088
2089         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2090                 "remote-model",
2091                 _("Control surface remote ID"),
2092                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2093                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2094                 );
2095
2096         rm->add (UserOrdered, _("assigned by user"));
2097         rm->add (MixerOrdered, _("follows order of mixer"));
2098
2099         add_option (_("Control Surfaces"), rm);
2100
2101         /* VIDEO Timeline */
2102         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2103
2104 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
2105         /* Plugin options (currrently VST only) */
2106         add_option (_("Plugins"), new PluginOptions (_rc_config));
2107 #endif
2108
2109         /* INTERFACE */
2110
2111         add_option (S_("Preferences|GUI"),
2112              new BoolOption (
2113                      "widget-prelight",
2114                      _("Graphically indicate mouse pointer hovering over various widgets"),
2115                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
2116                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
2117                      ));
2118
2119         add_option (S_("Preferences|GUI"),
2120              new BoolOption (
2121                      "use-tooltips",
2122                      _("Show tooltips if mouse hovers over a control"),
2123                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
2124                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
2125                      ));
2126
2127         add_option (S_("Preferences|GUI"),
2128              new BoolOption (
2129                      "show-name-highlight",
2130                      _("use name highlight bars in region displays"),
2131                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_name_highlight),
2132                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_name_highlight)
2133                      ));
2134
2135 #ifndef GTKOSX
2136         /* font scaling does nothing with GDK/Quartz */
2137         add_option (S_("Preferences|GUI"), new FontScalingOptions (_rc_config));
2138 #endif
2139
2140         add_option (S_("GUI"),
2141                     new BoolOption (
2142                             "super-rapid-clock-update",
2143                             _("update transport clock display every 40ms instead of every 100ms"),
2144                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_super_rapid_clock_update),
2145                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_super_rapid_clock_update)
2146                             ));
2147
2148         /* The names of these controls must be the same as those given in MixerStrip
2149            for the actual widgets being controlled.
2150         */
2151         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2152         _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
2153         _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
2154         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2155         _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
2156         _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
2157         
2158         add_option (
2159                 S_("Preferences|GUI"),
2160                 new VisibilityOption (
2161                         _("Mixer Strip"),
2162                         &_mixer_strip_visibility,
2163                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
2164                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
2165                         )
2166                 );
2167
2168         add_option (S_("Preferences|GUI"),
2169              new BoolOption (
2170                      "default-narrow_ms",
2171                      _("Use narrow strips in the mixer by default"),
2172                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
2173                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
2174                      ));
2175
2176         add_option (S_("Preferences|GUI"), new OptionEditorHeading (_("Metering")));
2177
2178         ComboOption<float>* mht = new ComboOption<float> (
2179                 "meter-hold",
2180                 _("Peak hold time"),
2181                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
2182                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
2183                 );
2184
2185         mht->add (MeterHoldOff, _("off"));
2186         mht->add (MeterHoldShort, _("short"));
2187         mht->add (MeterHoldMedium, _("medium"));
2188         mht->add (MeterHoldLong, _("long"));
2189
2190         add_option (S_("Preferences|GUI"), mht);
2191
2192         ComboOption<float>* mfo = new ComboOption<float> (
2193                 "meter-falloff",
2194                 _("DPM fall-off"),
2195                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2196                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2197                 );
2198
2199         mfo->add (METER_FALLOFF_OFF,      _("off"));
2200         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2201         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2202         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2203         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2204         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2205         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2206         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2207         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2208
2209         add_option (S_("Preferences|GUI"), mfo);
2210
2211         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2212                 "meter-line-up-level",
2213                 _("Meter line-up level; 0dBu"),
2214                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_level),
2215                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_level)
2216                 );
2217
2218         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2219         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2220         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2221         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2222
2223         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."));
2224
2225         add_option (S_("Preferences|GUI"), mlu);
2226
2227         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2228                 "meter-line-up-din",
2229                 _("IEC1/DIN Meter line-up level; 0dBu"),
2230                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_din),
2231                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_din)
2232                 );
2233
2234         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2235         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2236         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2237         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2238
2239         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2240
2241         add_option (S_("Preferences|GUI"), mld);
2242
2243         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2244                 "meter-vu-standard",
2245                 _("VU Meter standard"),
2246                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_vu_standard),
2247                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_vu_standard)
2248                 );
2249
2250         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2251         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2252         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2253         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2254
2255         add_option (S_("Preferences|GUI"), mvu);
2256
2257         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2258         HSliderOption *mpks = new HSliderOption("meter-peak",
2259                         _("Peak threshold [dBFS]"),
2260                         mpk,
2261                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_peak),
2262                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_peak)
2263                         );
2264
2265         Gtkmm2ext::UI::instance()->set_tip
2266                 (mpks->tip_widget(),
2267                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2268
2269         add_option (S_("Preferences|GUI"), mpks);
2270
2271         add_option (S_("Preferences|GUI"),
2272              new BoolOption (
2273                      "meter-style-led",
2274                      _("LED meter style"),
2275                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_style_led),
2276                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_style_led)
2277                      ));
2278
2279 }
2280
2281 void
2282 RCOptionEditor::parameter_changed (string const & p)
2283 {
2284         OptionEditor::parameter_changed (p);
2285
2286         if (p == "use-monitor-bus") {
2287                 bool const s = Config->get_use_monitor_bus ();
2288                 if (!s) {
2289                         /* we can't use this if we don't have a monitor bus */
2290                         Config->set_solo_control_is_listen_control (false);
2291                 }
2292                 _solo_control_is_listen_control->set_sensitive (s);
2293                 _listen_position->set_sensitive (s);
2294         } else if (p == "sync-source") {
2295                 _sync_source->set_sensitive (true);
2296                 if (_session) {
2297                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2298                 }
2299                 switch(Config->get_sync_source()) {
2300                 case ARDOUR::MTC:
2301                 case ARDOUR::LTC:
2302                         _sync_genlock->set_sensitive (true);
2303                         _sync_framerate->set_sensitive (true);
2304                         _sync_source_2997->set_sensitive (true);
2305                         break;
2306                 default:
2307                         _sync_genlock->set_sensitive (false);
2308                         _sync_framerate->set_sensitive (false);
2309                         _sync_source_2997->set_sensitive (false);
2310                         break;
2311                 }
2312         } else if (p == "send-ltc") {
2313                 bool const s = Config->get_send_ltc ();
2314                 _ltc_send_continuously->set_sensitive (s);
2315                 _ltc_volume_slider->set_sensitive (s);
2316         }
2317 }
2318
2319 void RCOptionEditor::ltc_generator_volume_changed () {
2320         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2321 }
2322
2323 void
2324 RCOptionEditor::populate_sync_options ()
2325 {
2326         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2327
2328         _sync_source->clear ();
2329
2330         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2331                 _sync_source->add (*i, sync_source_to_string (*i));
2332         }
2333 }