tweak config param for automation sampling interval, set to 500msec by default, and...
[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 <gtkmm/liststore.h>
25 #include <gtkmm/stock.h>
26 #include <gtkmm/scale.h>
27 #include <gtkmm2ext/utils.h>
28 #include <gtkmm2ext/slider_controller.h>
29 #include <gtkmm2ext/gtk_ui.h>
30
31 #include "pbd/fpu.h"
32 #include "pbd/cpus.h"
33
34 #include "midi++/manager.h"
35
36 #include "ardour/audioengine.h"
37 #include "ardour/dB.h"
38 #include "ardour/rc_configuration.h"
39 #include "ardour/control_protocol_manager.h"
40 #include "control_protocol/control_protocol.h"
41
42 #include "ardour_window.h"
43 #include "ardour_dialog.h"
44 #include "gui_thread.h"
45 #include "midi_tracer.h"
46 #include "rc_option_editor.h"
47 #include "utils.h"
48 #include "midi_port_dialog.h"
49 #include "sfdb_ui.h"
50 #include "keyboard.h"
51 #include "i18n.h"
52
53 using namespace std;
54 using namespace Gtk;
55 using namespace Gtkmm2ext;
56 using namespace PBD;
57 using namespace ARDOUR;
58
59 class ClickOptions : public OptionEditorBox
60 {
61 public:
62         ClickOptions (RCConfiguration* c, Gtk::Window* p)
63                 : _rc_config (c),
64                   _parent (p)
65         {
66                 Table* t = manage (new Table (2, 3));
67                 t->set_spacings (4);
68
69                 Label* l = manage (left_aligned_label (_("Click audio file:")));
70                 t->attach (*l, 0, 1, 0, 1, FILL);
71                 t->attach (_click_path_entry, 1, 2, 0, 1, FILL);
72                 Button* b = manage (new Button (_("Browse...")));
73                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
74                 t->attach (*b, 2, 3, 0, 1, FILL);
75
76                 l = manage (left_aligned_label (_("Click emphasis audio file:")));
77                 t->attach (*l, 0, 1, 1, 2, FILL);
78                 t->attach (_click_emphasis_path_entry, 1, 2, 1, 2, FILL);
79                 b = manage (new Button (_("Browse...")));
80                 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
81                 t->attach (*b, 2, 3, 1, 2, FILL);
82                 
83                 _box->pack_start (*t, false, false);
84
85                 _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));      
86                 _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
87         }
88
89         void parameter_changed (string const & p)
90         {
91                 if (p == "click-sound") {
92                         _click_path_entry.set_text (_rc_config->get_click_sound());
93                 } else if (p == "click-emphasis-sound") {
94                         _click_emphasis_path_entry.set_text (_rc_config->get_click_emphasis_sound());
95                 }
96         }
97
98         void set_state_from_config ()
99         {
100                 parameter_changed ("click-sound");
101                 parameter_changed ("click-emphasis-sound");
102         }
103
104 private:
105
106         void click_browse_clicked ()
107         {
108                 SoundFileChooser sfdb (*_parent, _("Choose Click"));
109
110                 sfdb.show_all ();
111                 sfdb.present ();
112
113                 if (sfdb.run () == RESPONSE_OK) {
114                         click_chosen (sfdb.get_filename());
115                 }
116         }
117
118         void click_chosen (string const & path)
119         {
120                 _click_path_entry.set_text (path);
121                 _rc_config->set_click_sound (path);
122         }
123
124         void click_changed ()
125         {
126                 click_chosen (_click_path_entry.get_text ());
127         }
128         
129         void click_emphasis_browse_clicked ()
130         {
131                 SoundFileChooser sfdb (*_parent, _("Choose Click Emphasis"));
132
133                 sfdb.show_all ();
134                 sfdb.present ();
135
136                 if (sfdb.run () == RESPONSE_OK) {
137                         click_emphasis_chosen (sfdb.get_filename());
138                 }
139         }
140
141         void click_emphasis_chosen (string const & path)
142         {
143                 _click_emphasis_path_entry.set_text (path);
144                 _rc_config->set_click_emphasis_sound (path);
145         }
146
147         void click_emphasis_changed ()
148         {
149                 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
150         }
151
152         RCConfiguration* _rc_config;
153         Gtk::Window* _parent;
154         Entry _click_path_entry;
155         Entry _click_emphasis_path_entry;
156 };
157
158 class UndoOptions : public OptionEditorBox
159 {
160 public:
161         UndoOptions (RCConfiguration* c) :
162                 _rc_config (c),
163                 _limit_undo_button (_("Limit undo history to")),
164                 _save_undo_button (_("Save undo history of"))
165         {
166                 Table* t = new Table (2, 3);
167                 t->set_spacings (4);
168
169                 t->attach (_limit_undo_button, 0, 1, 0, 1, FILL);
170                 _limit_undo_spin.set_range (0, 512);
171                 _limit_undo_spin.set_increments (1, 10);
172                 t->attach (_limit_undo_spin, 1, 2, 0, 1, FILL | EXPAND);
173                 Label* l = manage (left_aligned_label (_("commands")));
174                 t->attach (*l, 2, 3, 0, 1);
175
176                 t->attach (_save_undo_button, 0, 1, 1, 2, FILL);
177                 _save_undo_spin.set_range (0, 512);
178                 _save_undo_spin.set_increments (1, 10);
179                 t->attach (_save_undo_spin, 1, 2, 1, 2, FILL | EXPAND);
180                 l = manage (left_aligned_label (_("commands")));
181                 t->attach (*l, 2, 3, 1, 2);
182
183                 _box->pack_start (*t);
184
185                 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
186                 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
187                 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
188                 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
189         }
190
191         void parameter_changed (string const & p)
192         {
193                 if (p == "history-depth") {
194                         int32_t const d = _rc_config->get_history_depth();
195                         _limit_undo_button.set_active (d != 0);
196                         _limit_undo_spin.set_sensitive (d != 0);
197                         _limit_undo_spin.set_value (d);
198                 } else if (p == "save-history") {
199                         bool const x = _rc_config->get_save_history ();
200                         _save_undo_button.set_active (x);
201                         _save_undo_spin.set_sensitive (x);
202                 } else if (p == "save-history-depth") {
203                         _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
204                 }
205         }
206
207         void set_state_from_config ()
208         {
209                 parameter_changed ("save-history");
210                 parameter_changed ("history-depth");
211                 parameter_changed ("save-history-depth");
212         }
213
214         void limit_undo_toggled ()
215         {
216                 bool const x = _limit_undo_button.get_active ();
217                 _limit_undo_spin.set_sensitive (x);
218                 int32_t const n = x ? 16 : 0;
219                 _limit_undo_spin.set_value (n);
220                 _rc_config->set_history_depth (n);
221         }
222
223         void limit_undo_changed ()
224         {
225                 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
226         }
227
228         void save_undo_toggled ()
229         {
230                 bool const x = _save_undo_button.get_active ();
231                 _rc_config->set_save_history (x);
232         }
233
234         void save_undo_changed ()
235         {
236                 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
237         }
238
239 private:
240         RCConfiguration* _rc_config;
241         CheckButton _limit_undo_button;
242         SpinButton _limit_undo_spin;
243         CheckButton _save_undo_button;
244         SpinButton _save_undo_spin;
245 };
246
247
248
249 static const struct {
250     const char *name;
251     guint modifier;
252 } modifiers[] = {
253
254         { "Unmodified", 0 },
255
256 #ifdef GTKOSX
257
258         /* Command = Meta
259            Option/Alt = Mod1
260         */
261         { "Key|Shift", GDK_SHIFT_MASK },
262         { "Command", GDK_META_MASK },
263         { "Control", GDK_CONTROL_MASK },
264         { "Option", GDK_MOD1_MASK },
265         { "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
266         { "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
267         { "Shift-Option", GDK_SHIFT_MASK|GDK_MOD1_MASK },
268         { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
269
270 #else
271         { "Key|Shift", GDK_SHIFT_MASK },
272         { "Control", GDK_CONTROL_MASK },
273         { "Alt (Mod1)", GDK_MOD1_MASK },
274         { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
275         { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
276         { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
277         { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
278         { "Mod2", GDK_MOD2_MASK },
279         { "Mod3", GDK_MOD3_MASK },
280         { "Mod4", GDK_MOD4_MASK },
281         { "Mod5", GDK_MOD5_MASK },
282 #endif
283         { 0, 0 }
284 };
285
286
287 class KeyboardOptions : public OptionEditorBox
288 {
289 public:
290         KeyboardOptions () :
291                   _delete_button_adjustment (3, 1, 12),
292                   _delete_button_spin (_delete_button_adjustment),
293                   _edit_button_adjustment (3, 1, 5),
294                   _edit_button_spin (_edit_button_adjustment),
295                   _insert_note_button_adjustment (3, 1, 5),
296                   _insert_note_button_spin (_insert_note_button_adjustment)
297         {
298                 /* internationalize and prepare for use with combos */
299
300                 vector<string> dumb;
301                 for (int i = 0; modifiers[i].name; ++i) {
302                         dumb.push_back (S_(modifiers[i].name));
303                 }
304
305                 set_popdown_strings (_edit_modifier_combo, dumb);
306                 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
307
308                 for (int x = 0; modifiers[x].name; ++x) {
309                         if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
310                                 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
311                                 break;
312                         }
313                 }
314
315                 Table* t = manage (new Table (4, 4));
316                 t->set_spacings (4);
317
318                 Label* l = manage (left_aligned_label (_("Edit using:")));
319                 l->set_name ("OptionsLabel");
320
321                 t->attach (*l, 0, 1, 0, 1, FILL | EXPAND, FILL);
322                 t->attach (_edit_modifier_combo, 1, 2, 0, 1, FILL | EXPAND, FILL);
323
324                 l = manage (new Label (_("+ button")));
325                 l->set_name ("OptionsLabel");
326
327                 t->attach (*l, 3, 4, 0, 1, FILL | EXPAND, FILL);
328                 t->attach (_edit_button_spin, 4, 5, 0, 1, FILL | EXPAND, FILL);
329
330                 _edit_button_spin.set_name ("OptionsEntry");
331                 _edit_button_adjustment.set_value (Keyboard::edit_button());
332                 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
333
334                 set_popdown_strings (_delete_modifier_combo, dumb);
335                 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
336
337                 for (int x = 0; modifiers[x].name; ++x) {
338                         if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
339                                 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
340                                 break;
341                         }
342                 }
343
344                 l = manage (left_aligned_label (_("Delete using:")));
345                 l->set_name ("OptionsLabel");
346
347                 t->attach (*l, 0, 1, 1, 2, FILL | EXPAND, FILL);
348                 t->attach (_delete_modifier_combo, 1, 2, 1, 2, FILL | EXPAND, FILL);
349
350                 l = manage (new Label (_("+ button")));
351                 l->set_name ("OptionsLabel");
352
353                 t->attach (*l, 3, 4, 1, 2, FILL | EXPAND, FILL);
354                 t->attach (_delete_button_spin, 4, 5, 1, 2, FILL | EXPAND, FILL);
355
356                 _delete_button_spin.set_name ("OptionsEntry");
357                 _delete_button_adjustment.set_value (Keyboard::delete_button());
358                 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
359
360
361                 set_popdown_strings (_insert_note_modifier_combo, dumb);
362                 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
363
364                 for (int x = 0; modifiers[x].name; ++x) {
365                         if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
366                                 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
367                                 break;
368                         }
369                 }
370
371                 l = manage (left_aligned_label (_("Insert note using:")));
372                 l->set_name ("OptionsLabel");
373
374                 t->attach (*l, 0, 1, 2, 3, FILL | EXPAND, FILL);
375                 t->attach (_insert_note_modifier_combo, 1, 2, 2, 3, FILL | EXPAND, FILL);
376
377                 l = manage (new Label (_("+ button")));
378                 l->set_name ("OptionsLabel");
379
380                 t->attach (*l, 3, 4, 2, 3, FILL | EXPAND, FILL);
381                 t->attach (_insert_note_button_spin, 4, 5, 2, 3, FILL | EXPAND, FILL);
382
383                 _insert_note_button_spin.set_name ("OptionsEntry");
384                 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
385                 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
386
387
388                 set_popdown_strings (_snap_modifier_combo, dumb);
389                 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
390
391                 for (int x = 0; modifiers[x].name; ++x) {
392                         if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
393                                 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
394                                 break;
395                         }
396                 }
397
398                 l = manage (left_aligned_label (_("Toggle snap using:")));
399                 l->set_name ("OptionsLabel");
400
401                 t->attach (*l, 0, 1, 3, 4, FILL | EXPAND, FILL);
402                 t->attach (_snap_modifier_combo, 1, 2, 3, 4, FILL | EXPAND, FILL);
403
404                 vector<string> strs;
405
406                 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
407                         strs.push_back (bf->first);
408                 }
409
410                 set_popdown_strings (_keyboard_layout_selector, strs);
411                 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
412                 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
413
414                 l = manage (left_aligned_label (_("Keyboard layout:")));
415                 l->set_name ("OptionsLabel");
416
417                 t->attach (*l, 0, 1, 4, 5, FILL | EXPAND, FILL);
418                 t->attach (_keyboard_layout_selector, 1, 2, 4, 5, FILL | EXPAND, FILL);
419
420                 _box->pack_start (*t, false, false);
421         }
422
423         void parameter_changed (string const &)
424         {
425                 /* XXX: these aren't really config options... */
426         }
427
428         void set_state_from_config ()
429         {
430                 /* XXX: these aren't really config options... */
431         }
432
433 private:
434
435         void bindings_changed ()
436         {
437                 string const txt = _keyboard_layout_selector.get_active_text();
438
439                 /* XXX: config...?  for all this keyboard stuff */
440
441                 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
442                         if (txt == i->first) {
443                                 if (Keyboard::load_keybindings (i->second)) {
444                                         Keyboard::save_keybindings ();
445                                 }
446                         }
447                 }
448         }
449
450         void edit_modifier_chosen ()
451         {
452                 string const txt = _edit_modifier_combo.get_active_text();
453
454                 for (int i = 0; modifiers[i].name; ++i) {
455                         if (txt == _(modifiers[i].name)) {
456                                 Keyboard::set_edit_modifier (modifiers[i].modifier);
457                                 break;
458                         }
459                 }
460         }
461
462         void delete_modifier_chosen ()
463         {
464                 string const txt = _delete_modifier_combo.get_active_text();
465
466                 for (int i = 0; modifiers[i].name; ++i) {
467                         if (txt == _(modifiers[i].name)) {
468                                 Keyboard::set_delete_modifier (modifiers[i].modifier);
469                                 break;
470                         }
471                 }
472         }
473
474         void insert_note_modifier_chosen ()
475         {
476                 string const txt = _insert_note_modifier_combo.get_active_text();
477
478                 for (int i = 0; modifiers[i].name; ++i) {
479                         if (txt == _(modifiers[i].name)) {
480                                 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
481                                 break;
482                         }
483                 }
484         }
485
486         void snap_modifier_chosen ()
487         {
488                 string const txt = _snap_modifier_combo.get_active_text();
489
490                 for (int i = 0; modifiers[i].name; ++i) {
491                         if (txt == _(modifiers[i].name)) {
492                                 Keyboard::set_snap_modifier (modifiers[i].modifier);
493                                 break;
494                         }
495                 }
496         }
497
498         void delete_button_changed ()
499         {
500                 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
501         }
502
503         void edit_button_changed ()
504         {
505                 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
506         }
507
508         void insert_note_button_changed ()
509         {
510                 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
511         }
512
513         ComboBoxText _keyboard_layout_selector;
514         ComboBoxText _edit_modifier_combo;
515         ComboBoxText _delete_modifier_combo;
516         ComboBoxText _insert_note_modifier_combo;
517         ComboBoxText _snap_modifier_combo;
518         Adjustment _delete_button_adjustment;
519         SpinButton _delete_button_spin;
520         Adjustment _edit_button_adjustment;
521         SpinButton _edit_button_spin;
522         Adjustment _insert_note_button_adjustment;
523         SpinButton _insert_note_button_spin;
524
525 };
526
527 class FontScalingOptions : public OptionEditorBox
528 {
529 public:
530         FontScalingOptions (RCConfiguration* c) :
531                 _rc_config (c),
532                 _dpi_adjustment (50, 50, 250, 1, 10),
533                 _dpi_slider (_dpi_adjustment)
534         {
535                 _dpi_adjustment.set_value (_rc_config->get_font_scale () / 1024);
536
537                 Label* l = manage (new Label (_("Font scaling:")));
538                 l->set_name ("OptionsLabel");
539
540                 _dpi_slider.set_update_policy (UPDATE_DISCONTINUOUS);
541                 HBox* h = manage (new HBox);
542                 h->set_spacing (4);
543                 h->pack_start (*l, false, false);
544                 h->pack_start (_dpi_slider, true, true);
545
546                 _box->pack_start (*h, false, false);
547
548                 _dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
549         }
550
551         void parameter_changed (string const & p)
552         {
553                 if (p == "font-scale") {
554                         _dpi_adjustment.set_value (_rc_config->get_font_scale() / 1024);
555                 }
556         }
557
558         void set_state_from_config ()
559         {
560                 parameter_changed ("font-scale");
561         }
562
563 private:
564
565         void dpi_changed ()
566         {
567                 _rc_config->set_font_scale ((long) floor (_dpi_adjustment.get_value() * 1024));
568                 /* XXX: should be triggered from the parameter changed signal */
569                 reset_dpi ();
570         }
571
572         RCConfiguration* _rc_config;
573         Adjustment _dpi_adjustment;
574         HScale _dpi_slider;
575 };
576
577 class BufferingOptions : public OptionEditorBox
578 {
579 public:
580         BufferingOptions (RCConfiguration* c)
581                 : _rc_config (c)
582                 , _playback_adjustment (5, 1, 60, 1, 4)
583                 , _capture_adjustment (5, 1, 60, 1, 4)
584                 , _playback_slider (_playback_adjustment)
585                 , _capture_slider (_capture_adjustment)
586         {
587                 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
588
589                 Label* l = manage (new Label (_("Playback (seconds of buffering):")));
590                 l->set_name ("OptionsLabel");
591
592                 _playback_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 (_playback_slider, true, true);
597
598                 _box->pack_start (*h, false, false);
599
600                 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
601
602                 l = manage (new Label (_("Recording (seconds of buffering):")));
603                 l->set_name ("OptionsLabel");
604
605                 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
606                 h = manage (new HBox);
607                 h->set_spacing (4);
608                 h->pack_start (*l, false, false);
609                 h->pack_start (_capture_slider, true, true);
610
611                 _box->pack_start (*h, false, false);
612
613                 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
614                 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
615         }
616
617         void parameter_changed (string const & p)
618         {
619                 if (p == "playback-buffer-seconds") {
620                         _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
621                 } else if (p == "capture-buffer-seconds") {
622                         _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
623                 }
624         }
625
626         void set_state_from_config ()
627         {
628                 parameter_changed ("playback-buffer-seconds");
629                 parameter_changed ("capture-buffer-seconds");
630         }
631
632 private:
633
634         void playback_changed ()
635         {
636                 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
637         }
638
639         void capture_changed ()
640         {
641                 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
642         }
643
644         RCConfiguration* _rc_config;
645         Adjustment _playback_adjustment;
646         Adjustment _capture_adjustment;
647         HScale _playback_slider;
648         HScale _capture_slider;
649 };
650
651 class ControlSurfacesOptions : public OptionEditorBox
652 {
653 public:
654         ControlSurfacesOptions (Gtk::Window& parent)
655                 : _parent (parent)
656         {
657                 _store = ListStore::create (_model);
658                 _view.set_model (_store);
659                 _view.append_column (_("Name"), _model.name);
660                 _view.get_column(0)->set_resizable (true);
661                 _view.get_column(0)->set_expand (true);
662                 _view.append_column_editable (_("Enabled"), _model.enabled);
663                 _view.append_column_editable (_("Feedback"), _model.feedback);
664
665                 _box->pack_start (_view, false, false);
666
667                 Label* label = manage (new Label);
668                 label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
669
670                 _box->pack_start (*label, false, false);
671                 label->show ();
672
673                 ControlProtocolManager& m = ControlProtocolManager::instance ();
674                 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
675                                                 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
676
677                 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
678                 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
679         }
680
681         void parameter_changed (std::string const &)
682         {
683
684         }
685
686         void set_state_from_config ()
687         {
688                 _store->clear ();
689
690                 ControlProtocolManager& m = ControlProtocolManager::instance ();
691                 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
692
693                         if (!(*i)->mandatory) {
694                                 TreeModel::Row r = *_store->append ();
695                                 r[_model.name] = (*i)->name;
696                                 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
697                                 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
698                                 r[_model.protocol_info] = *i;
699                         }
700                 }
701         }
702
703 private:
704
705         void protocol_status_changed (ControlProtocolInfo* cpi) {
706                 /* find the row */
707                 TreeModel::Children rows = _store->children();
708                 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
709                         if ((*x)[_model.protocol_info] == cpi) {
710                                 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
711                                 break;
712                         }
713                 }
714         }
715
716         void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
717         {
718                 TreeModel::Row r = *i;
719
720                 ControlProtocolInfo* cpi = r[_model.protocol_info];
721                 if (!cpi) {
722                         return;
723                 }
724
725                 bool const was_enabled = (cpi->protocol != 0);
726                 bool const is_enabled = r[_model.enabled];
727
728                 if (was_enabled != is_enabled) {
729                         if (!was_enabled) {
730                                 ControlProtocolManager::instance().instantiate (*cpi);
731                         } else {
732                                 Gtk::Window* win = r[_model.editor];
733                                 if (win) {
734                                         win->hide ();
735                                 }
736
737                                 ControlProtocolManager::instance().teardown (*cpi);
738                                         
739                                 if (win) {
740                                         delete win;
741                                 }
742                                 r[_model.editor] = 0;
743                                 cpi->requested = false;
744                         }
745                 }
746
747                 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
748                 bool const is_feedback = r[_model.feedback];
749
750                 if (was_feedback != is_feedback && cpi->protocol) {
751                         cpi->protocol->set_feedback (is_feedback);
752                 }
753         }
754
755         void edit_clicked (GdkEventButton* ev)
756         {
757                 if (ev->type != GDK_2BUTTON_PRESS) {
758                         return;
759                 }
760
761                 std::string name;
762                 ControlProtocolInfo* cpi;
763                 TreeModel::Row row;
764
765                 row = *(_view.get_selection()->get_selected());
766
767                 Window* win = row[_model.editor];
768                 if (win && !win->is_visible()) {
769                         win->present ();
770                 } else {
771                         cpi = row[_model.protocol_info];
772
773                         if (cpi && cpi->protocol && cpi->protocol->has_editor ()) {
774                                 Box* box = (Box*) cpi->protocol->get_gui ();
775                                 if (box) {
776                                         string title = row[_model.name];
777                                         ArdourWindow* win = new ArdourWindow (_parent, title);
778                                         win->set_title ("Control Protocol Options");
779                                         win->add (*box);
780                                         box->show ();
781                                         win->present ();
782                                         row[_model.editor] = win;
783                                 }
784                         }
785                 }
786         }
787
788         class ControlSurfacesModelColumns : public TreeModelColumnRecord
789         {
790         public:
791
792                 ControlSurfacesModelColumns ()
793                 {
794                         add (name);
795                         add (enabled);
796                         add (feedback);
797                         add (protocol_info);
798                         add (editor);
799                 }
800
801                 TreeModelColumn<string> name;
802                 TreeModelColumn<bool> enabled;
803                 TreeModelColumn<bool> feedback;
804                 TreeModelColumn<ControlProtocolInfo*> protocol_info;
805                 TreeModelColumn<Gtk::Window*> editor;
806         };
807
808         Glib::RefPtr<ListStore> _store;
809         ControlSurfacesModelColumns _model;
810         TreeView _view;
811         Gtk::Window& _parent;
812         PBD::ScopedConnection protocol_status_connection;
813 };
814
815 /** A class which allows control of visibility of some editor components usign
816  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
817  *  which has the correct members, but with null widget pointers.  This
818  *  class allows the user to set visibility of the members, the details
819  *  of which are stored in a configuration variable which can be watched
820  *  by parts of the editor that actually contain the widgets whose visibility
821  *  is being controlled.
822  */
823
824 class VisibilityOption : public Option
825 {
826 public:
827         /** @param name User-visible name for this group.
828          *  @param g `Dummy' VisibilityGroup (as described above).
829          *  @param get Method to get the value of the appropriate configuration variable.
830          *  @param set Method to set the value of the appropriate configuration variable.
831          */
832         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
833                 : Option (g->get_state_name(), name)
834                 , _heading (name)
835                 , _visibility_group (g)
836                 , _get (get)
837                 , _set (set)
838         {
839                 /* Watch for changes made by the user to our members */
840                 _visibility_group->VisibilityChanged.connect_same_thread (
841                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
842                         );
843         }
844
845         void set_state_from_config ()
846         {
847                 /* Set our state from the current configuration */
848                 _visibility_group->set_state (_get ());
849         }
850
851         void add_to_page (OptionEditorPage* p)
852         {
853                 _heading.add_to_page (p);
854                 add_widget_to_page (p, _visibility_group->list_view ());
855         }
856
857         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
858
859 private:
860         void changed ()
861         {
862                 /* The user has changed something, so reflect this change
863                    in the RCConfiguration.
864                 */
865                 _set (_visibility_group->get_state_value ());
866         }
867         
868         OptionEditorHeading _heading;
869         VisibilityGroup* _visibility_group;
870         sigc::slot<std::string> _get;
871         sigc::slot<bool, std::string> _set;
872         PBD::ScopedConnection _visibility_group_connection;
873 };
874
875
876 RCOptionEditor::RCOptionEditor ()
877         : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
878         , _rc_config (Config)
879         , _mixer_strip_visibility ("mixer-strip-visibility")
880 {
881         /* MISC */
882
883         uint32_t hwcpus = hardware_concurrency ();
884
885         if (hwcpus > 1) {
886                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
887
888                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
889                         "processor-usage",
890                         _("Signal processing uses"),
891                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
892                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
893                         );
894
895                 procs->add (-1, _("all but one processor"));
896                 procs->add (0, _("all available processors"));
897
898                 for (uint32_t i = 1; i <= hwcpus; ++i) {
899                         procs->add (i, string_compose (_("%1 processors"), i));
900                 }
901
902                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
903
904                 add_option (_("Misc"), procs);
905         }
906
907         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
908
909         add_option (_("Misc"), new UndoOptions (_rc_config));
910
911         add_option (_("Misc"),
912              new BoolOption (
913                      "verify-remove-last-capture",
914                      _("Verify removal of last capture"),
915                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
916                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
917                      ));
918
919         add_option (_("Misc"),
920              new BoolOption (
921                      "periodic-safety-backups",
922                      _("Make periodic backups of the session file"),
923                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
924                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
925                      ));
926
927         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
928
929         add_option (_("Misc"),
930              new BoolOption (
931                      "only-copy-imported-files",
932                      _("Always copy imported files"),
933                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_only_copy_imported_files),
934                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_only_copy_imported_files)
935                      ));
936
937         add_option (_("Misc"), new DirectoryOption (
938                             X_("default-session-parent-dir"),
939                             _("Default folder for new sessions:"),
940                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
941                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
942                             ));
943
944         add_option (_("Misc"),
945              new SpinOption<uint32_t> (
946                      "max-recent-sessions",
947                      _("Maximum number of recent sessions"),
948                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
949                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
950                      0, 1000, 1, 20
951                      ));
952
953         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
954
955         add_option (_("Misc"), new ClickOptions (_rc_config, this));
956
957         add_option (_("Misc"),
958              new FaderOption (
959                      "click-gain",
960                      _("Click gain level"),
961                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
962                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
963                      ));
964
965         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
966
967         add_option (_("Misc"),
968              new SpinOption<double> (
969                      "automation-thinning-factor",
970                      _("Thinning factor (larger value => less data)"),
971                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
972                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
973                      0, 1000, 1, 20
974                      ));
975
976         add_option (_("Misc"),
977              new SpinOption<double> (
978                      "automation-interval-msecs",
979                      _("Automation sampling interval (milliseconds)"),
980                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
981                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
982                      1, 1000, 1, 20
983                      ));
984
985         /* TRANSPORT */
986
987         BoolOption* tsf;
988
989         tsf = new BoolOption (
990                      "latched-record-enable",
991                      _("Keep record-enable engaged on stop"),
992                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
993                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
994                      );
995         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
996         add_option (_("Transport"), tsf);
997
998         tsf = new BoolOption (
999                      "stop-recording-on-xrun",
1000                      _("Stop recording when an xrun occurs"),
1001                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1002                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1003                      );
1004         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> Ardour will stop recording if an over- or underrun is detected by the audio engine"));
1005         add_option (_("Transport"), tsf);
1006
1007         tsf = new BoolOption (
1008                      "create-xrun-marker",
1009                      _("Create markers where xruns occur"),
1010                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1011                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1012                      );
1013         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1014         add_option (_("Transport"), tsf);
1015
1016         tsf = new BoolOption (
1017                      "stop-at-session-end",
1018                      _("Stop at the end of the session"),
1019                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1020                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1021                      );
1022         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> if Ardour is <b>not recording</b>, it will stop the transport "
1023                                                    "when it reaches the current session end marker\n\n"
1024                                                    "<b>When disabled</b> Ardour will continue to roll past the session end marker at all times"));
1025         add_option (_("Transport"), tsf);
1026
1027         tsf = new BoolOption (
1028                      "seamless-loop",
1029                      _("Do seamless looping (not possible when slaved to MTC, JACK etc)"),
1030                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1031                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1032                      );
1033         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1034                                                    "preventing any need to do a transport locate at the end of the loop\n\n"
1035                                                    "<b>When disabled</b> looping is done by locating back to the start of the loop when Ardour reaches the end "
1036                                                    "which will often cause a small click or delay"));
1037         add_option (_("Transport"), tsf);
1038
1039         tsf = new BoolOption (
1040                      "disable-disarm-during-roll",
1041                      _("Disable per-track record disarm while rolling"),
1042                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1043                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1044                      );
1045         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"));
1046         add_option (_("Transport"), tsf);
1047
1048         tsf = new BoolOption (
1049                      "quieten_at_speed",
1050                      _("12dB gain reduction during fast-forward and fast-rewind"),
1051                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1052                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1053                      );
1054         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1055                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1056         add_option (_("Transport"), tsf);
1057
1058         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1059
1060         _sync_source = new ComboOption<SyncSource> (
1061                 "sync-source",
1062                 _("External timecode source"),
1063                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1064                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1065                 );
1066
1067         populate_sync_options ();
1068         add_option (_("Transport"), _sync_source);
1069
1070         _sync_framerate = new BoolOption (
1071                      "timecode-sync-frame-rate",
1072                      _("Match session video frame rate to external timecode"),
1073                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1074                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1075                      );
1076         Gtkmm2ext::UI::instance()->set_tip 
1077                 (_sync_framerate->tip_widget(),
1078                  _("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1079                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1080                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1081                    "Instead the frame rate indication in the main clock will flash red and Ardour will convert between the external "
1082                    "timecode standard and the session standard."));
1083
1084         add_option (_("Transport"), _sync_framerate);
1085
1086         _sync_genlock = new BoolOption (
1087                 "timecode-source-is-synced",
1088                 _("External timecode is sync locked"),
1089                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1090                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1091                 );
1092         Gtkmm2ext::UI::instance()->set_tip 
1093                 (_sync_genlock->tip_widget(), 
1094                  _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface."));
1095
1096
1097         add_option (_("Transport"), _sync_genlock);
1098
1099         _sync_source_2997 = new BoolOption (
1100                 "timecode-source-2997",
1101                 _("Lock to 29.9700 fps instead of 30000/1001"),
1102                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1103                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1104                 );
1105         Gtkmm2ext::UI::instance()->set_tip
1106                 (_sync_source_2997->tip_widget(),
1107                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1108                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1109                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1110                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1111                          "That is not the actual rate, however some vendor use that rate - despite it being against the specs - "
1112                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1113                          ));
1114
1115         add_option (_("Transport"), _sync_source_2997);
1116
1117         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1118
1119         _ltc_port = new ComboStringOption (
1120                 "ltc-source-port",
1121                 _("LTC incoming port"),
1122                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1123                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1124                 );
1125
1126         vector<string> physical_inputs;
1127         physical_inputs.push_back (_("None"));
1128         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1129         _ltc_port->set_popdown_strings (physical_inputs);
1130
1131         add_option (_("Transport"), _ltc_port);
1132
1133 #ifdef HAVE_LTC
1134         // TODO; rather disable this button than not compile it..
1135         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1136
1137         add_option (_("Transport"),
1138                     new BoolOption (
1139                             "send-ltc",
1140                             _("Enable LTC generator"),
1141                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1142                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1143                             ));
1144
1145         _ltc_send_continuously = new BoolOption (
1146                             "ltc-send-continuously",
1147                             _("send LTC while stopped"),
1148                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1149                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1150                             );
1151         Gtkmm2ext::UI::instance()->set_tip
1152                 (_ltc_send_continuously->tip_widget(),
1153                  _("<b>When enabled</b> Ardour will continue to send LTC information even when the transport (playhead) is not moving"));
1154         add_option (_("Transport"), _ltc_send_continuously);
1155
1156   _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1157         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1158         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1159         _ltc_volume_slider = new HSliderOption("ltcvol", ("LTC generator level:"), *_ltc_volume_adjustment);
1160
1161         Gtkmm2ext::UI::instance()->set_tip
1162                 (_ltc_volume_slider->tip_widget(),
1163                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1164
1165         add_option (_("Transport"), _ltc_volume_slider);
1166         parameter_changed ("send-ltc");
1167 #endif
1168
1169         parameter_changed ("sync-source");
1170
1171         /* EDITOR */
1172
1173         add_option (_("Editor"),
1174              new BoolOption (
1175                      "link-region-and-track-selection",
1176                      _("Link selection of regions and tracks"),
1177                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1178                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1179                      ));
1180
1181         add_option (_("Editor"),
1182              new BoolOption (
1183                      "automation-follows-regions",
1184                      _("Move relevant automation when audio regions are moved"),
1185                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1186                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1187                      ));
1188
1189         add_option (_("Editor"),
1190              new BoolOption (
1191                      "show-track-meters",
1192                      _("Show meters on tracks in the editor"),
1193                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1194                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1195                      ));
1196
1197         add_option (_("Editor"),
1198              new BoolOption (
1199                      "use-overlap-equivalency",
1200                      _("Use overlap equivalency for regions"),
1201                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1202                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1203                      ));
1204
1205         add_option (_("Editor"),
1206              new BoolOption (
1207                      "rubberbanding-snaps-to-grid",
1208                      _("Make rubberband selection rectangle snap to the grid"),
1209                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1210                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1211                      ));
1212
1213         add_option (_("Editor"),
1214              new BoolOption (
1215                      "show-waveforms",
1216                      _("Show waveforms in regions"),
1217                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1218                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1219                      ));
1220
1221         add_option (_("Editor"),
1222              new BoolComboOption (
1223                      "show-region-gain-envelopes",
1224                      _("Show gain envelopes in audio regions"),
1225                      _("in all modes"),
1226                      _("only in region gain mode"),
1227                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1228                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1229                      ));
1230
1231         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1232                 "waveform-scale",
1233                 _("Waveform scale"),
1234                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1235                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1236                 );
1237
1238         wfs->add (Linear, _("linear"));
1239         wfs->add (Logarithmic, _("logarithmic"));
1240
1241         add_option (_("Editor"), wfs);
1242
1243         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1244                 "waveform-shape",
1245                 _("Waveform shape"),
1246                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1247                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1248                 );
1249
1250         wfsh->add (Traditional, _("traditional"));
1251         wfsh->add (Rectified, _("rectified"));
1252
1253         add_option (_("Editor"), wfsh);
1254
1255         add_option (_("Editor"),
1256              new BoolOption (
1257                      "show-waveforms-while-recording",
1258                      _("Show waveforms for audio while it is being recorded"),
1259                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1260                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1261                      ));
1262
1263         add_option (_("Editor"),
1264                     new BoolOption (
1265                             "show-zoom-tools",
1266                             _("Show zoom toolbar"),
1267                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1268                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1269                             ));
1270
1271         add_option (_("Editor"),
1272                     new BoolOption (
1273                             "color-regions-using-track-color",
1274                             _("Color regions using their track's color"),
1275                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_color_regions_using_track_color),
1276                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
1277                             ));
1278
1279         add_option (_("Editor"),
1280                     new BoolOption (
1281                             "update-editor-during-summary-drag",
1282                             _("Update editor window during drags of the summary"),
1283                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1284                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1285                             ));
1286
1287         add_option (_("Editor"),
1288              new BoolOption (
1289                      "sync-all-route-ordering",
1290                      _("Synchronise editor and mixer track order"),
1291                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
1292                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
1293                      ));
1294
1295         add_option (_("Editor"),
1296              new BoolOption (
1297                      "link-editor-and-mixer-selection",
1298                      _("Synchronise editor and mixer selection"),
1299                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1300                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1301                      ));
1302
1303         add_option (_("Editor"),
1304              new BoolOption (
1305                      "name-new-markers",
1306                      _("Name new markers"),
1307                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1308                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1309                      ));
1310
1311         add_option (_("Editor"),
1312             new BoolOption (
1313                     "autoscroll-editor",
1314                     _("Auto-scroll editor window when dragging near its edges"),
1315                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1316                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1317                     ));
1318
1319         /* AUDIO */
1320
1321         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1322
1323         add_option (_("Audio"), new BufferingOptions (_rc_config));
1324
1325         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1326
1327         add_option (_("Audio"),
1328              new BoolOption (
1329                      "use-monitor-bus",
1330                      _("Use a monitor bus (allows AFL/PFL and more control)"),
1331                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_monitor_bus),
1332                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_monitor_bus)
1333                      ));
1334
1335         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1336                 "monitoring-model",
1337                 _("Record monitoring handled by"),
1338                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1339                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1340                 );
1341
1342 #ifndef __APPLE__
1343         /* no JACK monitoring on CoreAudio */
1344         if (AudioEngine::instance()->can_request_hardware_monitoring()) {
1345                 mm->add (HardwareMonitoring, _("JACK"));
1346         }
1347 #endif
1348         mm->add (SoftwareMonitoring, _("ardour"));
1349         mm->add (ExternalMonitoring, _("audio hardware"));
1350
1351         add_option (_("Audio"), mm);
1352
1353         add_option (_("Audio"),
1354              new BoolOption (
1355                      "tape-machine-mode",
1356                      _("Tape machine mode"),
1357                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1358                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1359                      ));
1360
1361         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1362
1363         add_option (_("Audio"),
1364                     new BoolOption (
1365                             "auto-connect-standard-busses",
1366                             _("Auto-connect master/monitor busses"),
1367                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1368                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1369                             ));
1370
1371         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1372                 "input-auto-connect",
1373                 _("Connect track inputs"),
1374                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1375                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1376                 );
1377
1378         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1379         iac->add (ManualConnect, _("manually"));
1380
1381         add_option (_("Audio"), iac);
1382
1383         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1384                 "output-auto-connect",
1385                 _("Connect track and bus outputs"),
1386                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1387                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1388                 );
1389
1390         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1391         oac->add (AutoConnectMaster, _("automatically to master bus"));
1392         oac->add (ManualConnect, _("manually"));
1393
1394         add_option (_("Audio"), oac);
1395
1396         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1397
1398         add_option (_("Audio"),
1399              new BoolOption (
1400                      "denormal-protection",
1401                      _("Use DC bias to protect against denormals"),
1402                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1403                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1404                      ));
1405
1406         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1407                 "denormal-model",
1408                 _("Processor handling"),
1409                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1410                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1411                 );
1412
1413         dm->add (DenormalNone, _("no processor handling"));
1414
1415         FPU fpu;
1416
1417         if (fpu.has_flush_to_zero()) {
1418                 dm->add (DenormalFTZ, _("use FlushToZero"));
1419         }
1420
1421         if (fpu.has_denormals_are_zero()) {
1422                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1423         }
1424
1425         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1426                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1427         }
1428
1429         add_option (_("Audio"), dm);
1430
1431         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1432
1433         add_option (_("Audio"),
1434              new BoolOption (
1435                      "plugins-stop-with-transport",
1436                      _("Silence plugins when the transport is stopped"),
1437                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1438                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1439                      ));
1440
1441         add_option (_("Audio"),
1442              new BoolOption (
1443                      "do-not-record-plugins",
1444                      _("Disable plugins during recording"),
1445                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_do_not_record_plugins),
1446                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_do_not_record_plugins)
1447                      ));
1448
1449         add_option (_("Audio"),
1450              new BoolOption (
1451                      "new-plugins-active",
1452                      _("Make new plugins active"),
1453                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1454                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1455                      ));
1456
1457         add_option (_("Audio"),
1458              new BoolOption (
1459                      "auto-analyse-audio",
1460                      _("Enable automatic analysis of audio"),
1461                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1462                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1463                      ));
1464
1465         add_option (_("Audio"),
1466              new BoolOption (
1467                      "replicate-missing-region-channels",
1468                      _("Replicate missing region channels"),
1469                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1470                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1471                      ));
1472
1473         /* SOLO AND MUTE */
1474
1475         add_option (_("Solo / mute"),
1476              new FaderOption (
1477                      "solo-mute-gain",
1478                      _("Solo-in-place mute cut (dB)"),
1479                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1480                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1481                      ));
1482
1483         _solo_control_is_listen_control = new BoolOption (
1484                 "solo-control-is-listen-control",
1485                 _("Solo controls are Listen controls"),
1486                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1487                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1488                 );
1489
1490         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1491
1492         _listen_position = new ComboOption<ListenPosition> (
1493                 "listen-position",
1494                 _("Listen Position"),
1495                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1496                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1497                 );
1498
1499         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1500         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1501
1502         add_option (_("Solo / mute"), _listen_position);
1503
1504         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1505                 "pfl-position",
1506                 _("PFL signals come from"),
1507                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1508                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1509                 );
1510
1511         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1512         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1513
1514         add_option (_("Solo / mute"), pp);
1515
1516         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1517                 "afl-position",
1518                 _("AFL signals come from"),
1519                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1520                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1521                 );
1522
1523         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1524         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1525
1526         add_option (_("Solo / mute"), pa);
1527
1528         parameter_changed ("use-monitor-bus");
1529
1530         add_option (_("Solo / mute"),
1531              new BoolOption (
1532                      "exclusive-solo",
1533                      _("Exclusive solo"),
1534                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1535                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1536                      ));
1537
1538         add_option (_("Solo / mute"),
1539              new BoolOption (
1540                      "show-solo-mutes",
1541                      _("Show solo muting"),
1542                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1543                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1544                      ));
1545
1546         add_option (_("Solo / mute"),
1547              new BoolOption (
1548                      "solo-mute-override",
1549                      _("Soloing overrides muting"),
1550                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1551                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1552                      ));
1553
1554         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1555
1556         add_option (_("Solo / mute"),
1557              new BoolOption (
1558                      "mute-affects-pre-fader",
1559                      _("Mute affects pre-fader sends"),
1560                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1561                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1562                      ));
1563
1564         add_option (_("Solo / mute"),
1565              new BoolOption (
1566                      "mute-affects-post-fader",
1567                      _("Mute affects post-fader sends"),
1568                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1569                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1570                      ));
1571
1572         add_option (_("Solo / mute"),
1573              new BoolOption (
1574                      "mute-affects-control-outs",
1575                      _("Mute affects control outputs"),
1576                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1577                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1578                      ));
1579
1580         add_option (_("Solo / mute"),
1581              new BoolOption (
1582                      "mute-affects-main-outs",
1583                      _("Mute affects main outputs"),
1584                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1585                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1586                      ));
1587
1588         add_option (_("MIDI"),
1589                     new BoolOption (
1590                             "send-midi-clock",
1591                             _("Send MIDI Clock"),
1592                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1593                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1594                             ));
1595
1596         add_option (_("MIDI"),
1597                     new BoolOption (
1598                             "send-mtc",
1599                             _("Send MIDI Time Code"),
1600                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1601                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1602                             ));
1603
1604         add_option (_("MIDI"),
1605                     new SpinOption<int> (
1606                             "mtc-qf-speed-tolerance",
1607                             _("Percentage either side of normal transport speed to transmit MTC"),
1608                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1609                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1610                             0, 20, 1, 5
1611                             ));
1612
1613         add_option (_("MIDI"),
1614                     new BoolOption (
1615                             "mmc-control",
1616                             _("Obey MIDI Machine Control commands"),
1617                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1618                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1619                             ));
1620
1621         add_option (_("MIDI"),
1622                     new BoolOption (
1623                             "send-mmc",
1624                             _("Send MIDI Machine Control commands"),
1625                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1626                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1627                             ));
1628
1629         add_option (_("MIDI"),
1630                     new BoolOption (
1631                             "midi-feedback",
1632                             _("Send MIDI control feedback"),
1633                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1634                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1635                             ));
1636
1637         add_option (_("MIDI"),
1638              new SpinOption<uint8_t> (
1639                      "mmc-receive-device-id",
1640                      _("Inbound MMC device ID"),
1641                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1642                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1643                      0, 128, 1, 10
1644                      ));
1645
1646         add_option (_("MIDI"),
1647              new SpinOption<uint8_t> (
1648                      "mmc-send-device-id",
1649                      _("Outbound MMC device ID"),
1650                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1651                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1652                      0, 128, 1, 10
1653                      ));
1654
1655         add_option (_("MIDI"),
1656              new SpinOption<int32_t> (
1657                      "initial-program-change",
1658                      _("Initial program change"),
1659                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1660                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1661                      -1, 65536, 1, 10
1662                      ));
1663
1664         add_option (_("MIDI"),
1665                     new BoolOption (
1666                             "diplay-first-midi-bank-as-zero",
1667                             _("Display first MIDI bank/program as 0"),
1668                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1669                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1670                             ));
1671
1672         add_option (_("MIDI"),
1673              new BoolOption (
1674                      "never-display-periodic-midi",
1675                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1676                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1677                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1678                      ));
1679
1680         add_option (_("MIDI"),
1681              new BoolOption (
1682                      "sound-midi-notes",
1683                      _("Sound MIDI notes as they are selected"),
1684                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1685                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1686                      ));
1687
1688         /* USER INTERACTION */
1689
1690         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1691
1692         add_option (_("User interaction"), new KeyboardOptions);
1693
1694         add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
1695
1696         add_option (_("User interaction"), new ControlSurfacesOptions (*this));
1697
1698         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1699                 "remote-model",
1700                 _("Control surface remote ID"),
1701                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1702                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1703                 );
1704
1705         rm->add (UserOrdered, _("assigned by user"));
1706         rm->add (MixerOrdered, _("follows order of mixer"));
1707         rm->add (EditorOrdered, _("follows order of editor"));
1708
1709         add_option (_("User interaction"), rm);
1710
1711         /* INTERFACE */
1712
1713         add_option (S_("GUI"),
1714              new BoolOption (
1715                      "widget-prelight",
1716                      _("Graphically indicate mouse pointer hovering over various widgets"),
1717                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
1718                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
1719                      ));
1720
1721         add_option (S_("GUI"),
1722              new BoolOption (
1723                      "use-tooltips",
1724                      _("Show tooltips if mouse hovers over a control"),
1725                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
1726                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
1727                      ));
1728
1729 #ifndef GTKOSX
1730         /* font scaling does nothing with GDK/Quartz */
1731         add_option (S_("GUI"), new FontScalingOptions (_rc_config));
1732 #endif
1733         add_option (S_("GUI"),
1734                     new BoolOption (
1735                             "use-own-plugin-gui",
1736                             _("Use plugins' own interfaces instead of Ardour's"),
1737                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
1738                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
1739                             ));
1740
1741         /* The names of these controls must be the same as those given in MixerStrip
1742            for the actual widgets being controlled.
1743         */
1744         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
1745         _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
1746         _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
1747         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
1748         _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
1749         _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
1750         
1751         add_option (
1752                 S_("GUI"),
1753                 new VisibilityOption (
1754                         _("Mixer Strip"),
1755                         &_mixer_strip_visibility,
1756                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
1757                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
1758                         )
1759                 );
1760
1761         add_option (S_("GUI"),
1762              new BoolOption (
1763                      "default-narrow_ms",
1764                      _("Use narrow strips in the mixer by default"),
1765                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
1766                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
1767                      ));
1768
1769         add_option (S_("GUI"), new OptionEditorHeading (_("Metering")));
1770
1771         ComboOption<float>* mht = new ComboOption<float> (
1772                 "meter-hold",
1773                 _("Meter hold time"),
1774                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
1775                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
1776                 );
1777
1778         mht->add (MeterHoldOff, _("off"));
1779         mht->add (MeterHoldShort, _("short"));
1780         mht->add (MeterHoldMedium, _("medium"));
1781         mht->add (MeterHoldLong, _("long"));
1782
1783         add_option (S_("GUI"), mht);
1784
1785         ComboOption<float>* mfo = new ComboOption<float> (
1786                 "meter-falloff",
1787                 _("Meter fall-off"),
1788                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
1789                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
1790                 );
1791
1792         mfo->add (METER_FALLOFF_OFF, _("off"));
1793         mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
1794         mfo->add (METER_FALLOFF_SLOW, _("slow"));
1795         mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
1796         mfo->add (METER_FALLOFF_FAST, _("fast"));
1797         mfo->add (METER_FALLOFF_FASTER, _("faster"));
1798         mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
1799
1800         add_option (S_("GUI"), mfo);
1801 }
1802
1803 void
1804 RCOptionEditor::parameter_changed (string const & p)
1805 {
1806         OptionEditor::parameter_changed (p);
1807
1808         if (p == "use-monitor-bus") {
1809                 bool const s = Config->get_use_monitor_bus ();
1810                 if (!s) {
1811                         /* we can't use this if we don't have a monitor bus */
1812                         Config->set_solo_control_is_listen_control (false);
1813                 }
1814                 _solo_control_is_listen_control->set_sensitive (s);
1815                 _listen_position->set_sensitive (s);
1816         } else if (p == "sync-source") {
1817                 _sync_source->set_sensitive (true);
1818                 if (_session) {
1819                         _sync_source->set_sensitive (_session->config.get_external_sync());
1820                 }
1821                 switch(Config->get_sync_source()) {
1822                 case ARDOUR::MTC:
1823                 case ARDOUR::LTC:
1824                         _sync_genlock->set_sensitive (true);
1825                         _sync_framerate->set_sensitive (true);
1826                         _sync_source_2997->set_sensitive (true);
1827                         break;
1828                 default:
1829                         _sync_genlock->set_sensitive (false);
1830                         _sync_framerate->set_sensitive (false);
1831                         _sync_source_2997->set_sensitive (false);
1832                         break;
1833                 }
1834 #ifdef HAVE_LTC
1835         } else if (p == "send-ltc") {
1836                 bool const s = Config->get_send_ltc ();
1837                 _ltc_send_continuously->set_sensitive (s);
1838                 _ltc_volume_slider->set_sensitive (s);
1839 #endif /*HAVE_LTC*/
1840         }
1841 }
1842
1843 void RCOptionEditor::ltc_generator_volume_changed () {
1844         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
1845 }
1846
1847 void
1848 RCOptionEditor::populate_sync_options ()
1849 {
1850         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
1851
1852         _sync_source->clear ();
1853
1854         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
1855                 _sync_source->add (*i, sync_source_to_string (*i));
1856         }
1857 }