back off on a probably too-aggressive X11 version requirement
[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 (floor (_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 (floor (_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         BoolOption* bo;
885
886         if (hwcpus > 1) {
887                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
888
889                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
890                         "processor-usage",
891                         _("Signal processing uses"),
892                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
893                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
894                         );
895
896                 procs->add (-1, _("all but one processor"));
897                 procs->add (0, _("all available processors"));
898
899                 for (uint32_t i = 1; i <= hwcpus; ++i) {
900                         procs->add (i, string_compose (_("%1 processors"), i));
901                 }
902
903                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
904
905                 add_option (_("Misc"), procs);
906         }
907
908         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
909
910         add_option (_("Misc"), new UndoOptions (_rc_config));
911
912         add_option (_("Misc"),
913              new BoolOption (
914                      "verify-remove-last-capture",
915                      _("Verify removal of last capture"),
916                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
917                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
918                      ));
919
920         add_option (_("Misc"),
921              new BoolOption (
922                      "periodic-safety-backups",
923                      _("Make periodic backups of the session file"),
924                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
925                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
926                      ));
927
928         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
929
930         add_option (_("Misc"),
931              new BoolOption (
932                      "only-copy-imported-files",
933                      _("Always copy imported files"),
934                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_only_copy_imported_files),
935                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_only_copy_imported_files)
936                      ));
937
938         add_option (_("Misc"), new DirectoryOption (
939                             X_("default-session-parent-dir"),
940                             _("Default folder for new sessions:"),
941                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
942                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
943                             ));
944
945         add_option (_("Misc"),
946              new SpinOption<uint32_t> (
947                      "max-recent-sessions",
948                      _("Maximum number of recent sessions"),
949                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
950                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
951                      0, 1000, 1, 20
952                      ));
953
954         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
955
956         add_option (_("Misc"), new ClickOptions (_rc_config, this));
957
958         add_option (_("Misc"),
959              new FaderOption (
960                      "click-gain",
961                      _("Click gain level"),
962                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
963                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
964                      ));
965
966         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
967
968         add_option (_("Misc"),
969              new SpinOption<double> (
970                      "automation-thinning-factor",
971                      _("Thinning factor (larger value => less data)"),
972                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
973                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
974                      0, 1000, 1, 20
975                      ));
976
977         add_option (_("Misc"),
978              new SpinOption<double> (
979                      "automation-interval-msecs",
980                      _("Automation sampling interval (milliseconds)"),
981                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
982                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
983                      1, 1000, 1, 20
984                      ));
985
986         /* TRANSPORT */
987
988         BoolOption* tsf;
989
990         tsf = new BoolOption (
991                      "latched-record-enable",
992                      _("Keep record-enable engaged on stop"),
993                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
994                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
995                      );
996         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
997         add_option (_("Transport"), tsf);
998
999         tsf = new BoolOption (
1000                      "stop-recording-on-xrun",
1001                      _("Stop recording when an xrun occurs"),
1002                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1003                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1004                      );
1005         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"));
1006         add_option (_("Transport"), tsf);
1007
1008         tsf = new BoolOption (
1009                      "create-xrun-marker",
1010                      _("Create markers where xruns occur"),
1011                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1012                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1013                      );
1014         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1015         add_option (_("Transport"), tsf);
1016
1017         tsf = new BoolOption (
1018                      "stop-at-session-end",
1019                      _("Stop at the end of the session"),
1020                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1021                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1022                      );
1023         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> if Ardour is <b>not recording</b>, it will stop the transport "
1024                                                    "when it reaches the current session end marker\n\n"
1025                                                    "<b>When disabled</b> Ardour will continue to roll past the session end marker at all times"));
1026         add_option (_("Transport"), tsf);
1027
1028         tsf = new BoolOption (
1029                      "seamless-loop",
1030                      _("Do seamless looping (not possible when slaved to MTC, JACK etc)"),
1031                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1032                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1033                      );
1034         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, "
1035                                                    "preventing any need to do a transport locate at the end of the loop\n\n"
1036                                                    "<b>When disabled</b> looping is done by locating back to the start of the loop when Ardour reaches the end "
1037                                                    "which will often cause a small click or delay"));
1038         add_option (_("Transport"), tsf);
1039
1040         tsf = new BoolOption (
1041                      "disable-disarm-during-roll",
1042                      _("Disable per-track record disarm while rolling"),
1043                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1044                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1045                      );
1046         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"));
1047         add_option (_("Transport"), tsf);
1048
1049         tsf = new BoolOption (
1050                      "quieten_at_speed",
1051                      _("12dB gain reduction during fast-forward and fast-rewind"),
1052                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1053                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1054                      );
1055         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1056                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1057         add_option (_("Transport"), tsf);
1058
1059         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1060
1061         _sync_source = new ComboOption<SyncSource> (
1062                 "sync-source",
1063                 _("External timecode source"),
1064                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1065                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1066                 );
1067
1068         populate_sync_options ();
1069         add_option (_("Transport"), _sync_source);
1070
1071         _sync_framerate = new BoolOption (
1072                      "timecode-sync-frame-rate",
1073                      _("Match session video frame rate to external timecode"),
1074                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1075                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1076                      );
1077         Gtkmm2ext::UI::instance()->set_tip 
1078                 (_sync_framerate->tip_widget(),
1079                  _("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1080                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1081                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1082                    "Instead the frame rate indication in the main clock will flash red and Ardour will convert between the external "
1083                    "timecode standard and the session standard."));
1084
1085         add_option (_("Transport"), _sync_framerate);
1086
1087         _sync_genlock = new BoolOption (
1088                 "timecode-source-is-synced",
1089                 _("External timecode is sync locked"),
1090                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1091                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1092                 );
1093         Gtkmm2ext::UI::instance()->set_tip 
1094                 (_sync_genlock->tip_widget(), 
1095                  _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface."));
1096
1097
1098         add_option (_("Transport"), _sync_genlock);
1099
1100         _sync_source_2997 = new BoolOption (
1101                 "timecode-source-2997",
1102                 _("Lock to 29.9700 fps instead of 30000/1001"),
1103                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1104                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1105                 );
1106         Gtkmm2ext::UI::instance()->set_tip
1107                 (_sync_source_2997->tip_widget(),
1108                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1109                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1110                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1111                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1112                          "That is not the actual rate, however some vendor use that rate - despite it being against the specs - "
1113                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1114                          ));
1115
1116         add_option (_("Transport"), _sync_source_2997);
1117
1118         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1119
1120         _ltc_port = new ComboStringOption (
1121                 "ltc-source-port",
1122                 _("LTC incoming port"),
1123                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1124                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1125                 );
1126
1127         vector<string> physical_inputs;
1128         physical_inputs.push_back (_("None"));
1129         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1130         _ltc_port->set_popdown_strings (physical_inputs);
1131
1132         add_option (_("Transport"), _ltc_port);
1133
1134 #ifdef HAVE_LTC
1135         // TODO; rather disable this button than not compile it..
1136         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1137
1138         add_option (_("Transport"),
1139                     new BoolOption (
1140                             "send-ltc",
1141                             _("Enable LTC generator"),
1142                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1143                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1144                             ));
1145
1146         _ltc_send_continuously = new BoolOption (
1147                             "ltc-send-continuously",
1148                             _("send LTC while stopped"),
1149                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1150                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1151                             );
1152         Gtkmm2ext::UI::instance()->set_tip
1153                 (_ltc_send_continuously->tip_widget(),
1154                  _("<b>When enabled</b> Ardour will continue to send LTC information even when the transport (playhead) is not moving"));
1155         add_option (_("Transport"), _ltc_send_continuously);
1156
1157   _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1158         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1159         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1160         _ltc_volume_slider = new HSliderOption("ltcvol", ("LTC generator level:"), *_ltc_volume_adjustment);
1161
1162         Gtkmm2ext::UI::instance()->set_tip
1163                 (_ltc_volume_slider->tip_widget(),
1164                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1165
1166         add_option (_("Transport"), _ltc_volume_slider);
1167         parameter_changed ("send-ltc");
1168 #endif
1169
1170         parameter_changed ("sync-source");
1171
1172         /* EDITOR */
1173
1174         add_option (_("Editor"),
1175              new BoolOption (
1176                      "link-region-and-track-selection",
1177                      _("Link selection of regions and tracks"),
1178                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1179                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1180                      ));
1181
1182         add_option (_("Editor"),
1183              new BoolOption (
1184                      "automation-follows-regions",
1185                      _("Move relevant automation when audio regions are moved"),
1186                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1187                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1188                      ));
1189
1190         add_option (_("Editor"),
1191              new BoolOption (
1192                      "show-track-meters",
1193                      _("Show meters on tracks in the editor"),
1194                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1195                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1196                      ));
1197
1198         bo = 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"), bo);
1206         Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), 
1207                                             string_compose (_("When extending region selection across a group, %1 must decide which regions are equivalent"
1208                                                               "\n\nIf enabled, regions are considered \"equivalent\" if they overlap on the timeline."
1209                                                               "\n\nIf disabled, regions are considered \"equivalent\" only if have the same start time, length and position"),
1210                                                             PROGRAM_NAME));
1211
1212         add_option (_("Editor"),
1213              new BoolOption (
1214                      "rubberbanding-snaps-to-grid",
1215                      _("Make rubberband selection rectangle snap to the grid"),
1216                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1217                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1218                      ));
1219
1220         add_option (_("Editor"),
1221              new BoolOption (
1222                      "show-waveforms",
1223                      _("Show waveforms in regions"),
1224                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1225                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1226                      ));
1227
1228         add_option (_("Editor"),
1229              new BoolComboOption (
1230                      "show-region-gain-envelopes",
1231                      _("Show gain envelopes in audio regions"),
1232                      _("in all modes"),
1233                      _("only in region gain mode"),
1234                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1235                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1236                      ));
1237
1238         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1239                 "waveform-scale",
1240                 _("Waveform scale"),
1241                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1242                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1243                 );
1244
1245         wfs->add (Linear, _("linear"));
1246         wfs->add (Logarithmic, _("logarithmic"));
1247
1248         add_option (_("Editor"), wfs);
1249
1250         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1251                 "waveform-shape",
1252                 _("Waveform shape"),
1253                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1254                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1255                 );
1256
1257         wfsh->add (Traditional, _("traditional"));
1258         wfsh->add (Rectified, _("rectified"));
1259
1260         add_option (_("Editor"), wfsh);
1261
1262         add_option (_("Editor"),
1263              new BoolOption (
1264                      "show-waveforms-while-recording",
1265                      _("Show waveforms for audio while it is being recorded"),
1266                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1267                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1268                      ));
1269
1270         add_option (_("Editor"),
1271                     new BoolOption (
1272                             "show-zoom-tools",
1273                             _("Show zoom toolbar"),
1274                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1275                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1276                             ));
1277
1278         add_option (_("Editor"),
1279                     new BoolOption (
1280                             "color-regions-using-track-color",
1281                             _("Color regions using their track's color"),
1282                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_color_regions_using_track_color),
1283                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
1284                             ));
1285
1286         add_option (_("Editor"),
1287                     new BoolOption (
1288                             "update-editor-during-summary-drag",
1289                             _("Update editor window during drags of the summary"),
1290                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1291                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1292                             ));
1293
1294         add_option (_("Editor"),
1295              new BoolOption (
1296                      "sync-all-route-ordering",
1297                      _("Synchronise editor and mixer track order"),
1298                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
1299                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
1300                      ));
1301
1302         add_option (_("Editor"),
1303              new BoolOption (
1304                      "link-editor-and-mixer-selection",
1305                      _("Synchronise editor and mixer selection"),
1306                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1307                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1308                      ));
1309
1310         bo = new BoolOption (
1311                      "name-new-markers",
1312                      _("Name new markers"),
1313                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1314                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1315                 );
1316         
1317         add_option (_("Editor"), bo);
1318         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."
1319                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1320
1321         add_option (_("Editor"),
1322             new BoolOption (
1323                     "autoscroll-editor",
1324                     _("Auto-scroll editor window when dragging near its edges"),
1325                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1326                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1327                     ));
1328
1329         /* AUDIO */
1330
1331         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1332
1333         add_option (_("Audio"), new BufferingOptions (_rc_config));
1334
1335         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1336
1337         add_option (_("Audio"),
1338              new BoolOption (
1339                      "use-monitor-bus",
1340                      _("Use a monitor bus (allows AFL/PFL and more control)"),
1341                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_monitor_bus),
1342                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_monitor_bus)
1343                      ));
1344
1345         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1346                 "monitoring-model",
1347                 _("Record monitoring handled by"),
1348                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1349                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1350                 );
1351
1352 #ifndef __APPLE__
1353         /* no JACK monitoring on CoreAudio */
1354         if (AudioEngine::instance()->can_request_hardware_monitoring()) {
1355                 mm->add (HardwareMonitoring, _("JACK"));
1356         }
1357 #endif
1358         mm->add (SoftwareMonitoring, _("ardour"));
1359         mm->add (ExternalMonitoring, _("audio hardware"));
1360
1361         add_option (_("Audio"), mm);
1362
1363         add_option (_("Audio"),
1364              new BoolOption (
1365                      "tape-machine-mode",
1366                      _("Tape machine mode"),
1367                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1368                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1369                      ));
1370
1371         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1372
1373         add_option (_("Audio"),
1374                     new BoolOption (
1375                             "auto-connect-standard-busses",
1376                             _("Auto-connect master/monitor busses"),
1377                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1378                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1379                             ));
1380
1381         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1382                 "input-auto-connect",
1383                 _("Connect track inputs"),
1384                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1385                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1386                 );
1387
1388         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1389         iac->add (ManualConnect, _("manually"));
1390
1391         add_option (_("Audio"), iac);
1392
1393         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1394                 "output-auto-connect",
1395                 _("Connect track and bus outputs"),
1396                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1397                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1398                 );
1399
1400         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1401         oac->add (AutoConnectMaster, _("automatically to master bus"));
1402         oac->add (ManualConnect, _("manually"));
1403
1404         add_option (_("Audio"), oac);
1405
1406         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1407
1408         add_option (_("Audio"),
1409              new BoolOption (
1410                      "denormal-protection",
1411                      _("Use DC bias to protect against denormals"),
1412                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1413                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1414                      ));
1415
1416         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1417                 "denormal-model",
1418                 _("Processor handling"),
1419                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1420                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1421                 );
1422
1423         dm->add (DenormalNone, _("no processor handling"));
1424
1425         FPU fpu;
1426
1427         if (fpu.has_flush_to_zero()) {
1428                 dm->add (DenormalFTZ, _("use FlushToZero"));
1429         }
1430
1431         if (fpu.has_denormals_are_zero()) {
1432                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1433         }
1434
1435         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1436                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1437         }
1438
1439         add_option (_("Audio"), dm);
1440
1441         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1442
1443         add_option (_("Audio"),
1444              new BoolOption (
1445                      "plugins-stop-with-transport",
1446                      _("Silence plugins when the transport is stopped"),
1447                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1448                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1449                      ));
1450
1451         add_option (_("Audio"),
1452              new BoolOption (
1453                      "new-plugins-active",
1454                      _("Make new plugins active"),
1455                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1456                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1457                      ));
1458
1459         add_option (_("Audio"),
1460              new BoolOption (
1461                      "auto-analyse-audio",
1462                      _("Enable automatic analysis of audio"),
1463                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1464                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1465                      ));
1466
1467         add_option (_("Audio"),
1468              new BoolOption (
1469                      "replicate-missing-region-channels",
1470                      _("Replicate missing region channels"),
1471                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1472                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1473                      ));
1474
1475         /* SOLO AND MUTE */
1476
1477         add_option (_("Solo / mute"),
1478              new FaderOption (
1479                      "solo-mute-gain",
1480                      _("Solo-in-place mute cut (dB)"),
1481                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1482                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1483                      ));
1484
1485         _solo_control_is_listen_control = new BoolOption (
1486                 "solo-control-is-listen-control",
1487                 _("Solo controls are Listen controls"),
1488                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1489                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1490                 );
1491
1492         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1493
1494         _listen_position = new ComboOption<ListenPosition> (
1495                 "listen-position",
1496                 _("Listen Position"),
1497                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1498                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1499                 );
1500
1501         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1502         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1503
1504         add_option (_("Solo / mute"), _listen_position);
1505
1506         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1507                 "pfl-position",
1508                 _("PFL signals come from"),
1509                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1510                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1511                 );
1512
1513         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1514         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1515
1516         add_option (_("Solo / mute"), pp);
1517
1518         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1519                 "afl-position",
1520                 _("AFL signals come from"),
1521                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1522                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1523                 );
1524
1525         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1526         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1527
1528         add_option (_("Solo / mute"), pa);
1529
1530         parameter_changed ("use-monitor-bus");
1531
1532         add_option (_("Solo / mute"),
1533              new BoolOption (
1534                      "exclusive-solo",
1535                      _("Exclusive solo"),
1536                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1537                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1538                      ));
1539
1540         add_option (_("Solo / mute"),
1541              new BoolOption (
1542                      "show-solo-mutes",
1543                      _("Show solo muting"),
1544                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1545                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1546                      ));
1547
1548         add_option (_("Solo / mute"),
1549              new BoolOption (
1550                      "solo-mute-override",
1551                      _("Soloing overrides muting"),
1552                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1553                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1554                      ));
1555
1556         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1557
1558         add_option (_("Solo / mute"),
1559              new BoolOption (
1560                      "mute-affects-pre-fader",
1561                      _("Mute affects pre-fader sends"),
1562                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1563                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1564                      ));
1565
1566         add_option (_("Solo / mute"),
1567              new BoolOption (
1568                      "mute-affects-post-fader",
1569                      _("Mute affects post-fader sends"),
1570                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1571                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1572                      ));
1573
1574         add_option (_("Solo / mute"),
1575              new BoolOption (
1576                      "mute-affects-control-outs",
1577                      _("Mute affects control outputs"),
1578                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1579                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1580                      ));
1581
1582         add_option (_("Solo / mute"),
1583              new BoolOption (
1584                      "mute-affects-main-outs",
1585                      _("Mute affects main outputs"),
1586                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1587                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1588                      ));
1589
1590         add_option (_("MIDI"),
1591                     new BoolOption (
1592                             "send-midi-clock",
1593                             _("Send MIDI Clock"),
1594                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1595                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1596                             ));
1597
1598         add_option (_("MIDI"),
1599                     new BoolOption (
1600                             "send-mtc",
1601                             _("Send MIDI Time Code"),
1602                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1603                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1604                             ));
1605
1606         add_option (_("MIDI"),
1607                     new SpinOption<int> (
1608                             "mtc-qf-speed-tolerance",
1609                             _("Percentage either side of normal transport speed to transmit MTC"),
1610                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1611                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1612                             0, 20, 1, 5
1613                             ));
1614
1615         add_option (_("MIDI"),
1616                     new BoolOption (
1617                             "mmc-control",
1618                             _("Obey MIDI Machine Control commands"),
1619                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1620                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1621                             ));
1622
1623         add_option (_("MIDI"),
1624                     new BoolOption (
1625                             "send-mmc",
1626                             _("Send MIDI Machine Control commands"),
1627                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1628                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1629                             ));
1630
1631         add_option (_("MIDI"),
1632                     new BoolOption (
1633                             "midi-feedback",
1634                             _("Send MIDI control feedback"),
1635                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1636                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1637                             ));
1638
1639         add_option (_("MIDI"),
1640              new SpinOption<uint8_t> (
1641                      "mmc-receive-device-id",
1642                      _("Inbound MMC device ID"),
1643                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1644                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1645                      0, 128, 1, 10
1646                      ));
1647
1648         add_option (_("MIDI"),
1649              new SpinOption<uint8_t> (
1650                      "mmc-send-device-id",
1651                      _("Outbound MMC device ID"),
1652                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1653                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1654                      0, 128, 1, 10
1655                      ));
1656
1657         add_option (_("MIDI"),
1658              new SpinOption<int32_t> (
1659                      "initial-program-change",
1660                      _("Initial program change"),
1661                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1662                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1663                      -1, 65536, 1, 10
1664                      ));
1665
1666         add_option (_("MIDI"),
1667                     new BoolOption (
1668                             "diplay-first-midi-bank-as-zero",
1669                             _("Display first MIDI bank/program as 0"),
1670                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1671                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1672                             ));
1673
1674         add_option (_("MIDI"),
1675              new BoolOption (
1676                      "never-display-periodic-midi",
1677                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1678                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1679                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1680                      ));
1681
1682         add_option (_("MIDI"),
1683              new BoolOption (
1684                      "sound-midi-notes",
1685                      _("Sound MIDI notes as they are selected"),
1686                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1687                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1688                      ));
1689
1690         /* USER INTERACTION */
1691
1692         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1693
1694         add_option (_("User interaction"), new KeyboardOptions);
1695
1696         add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
1697
1698         add_option (_("User interaction"), new ControlSurfacesOptions (*this));
1699
1700         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1701                 "remote-model",
1702                 _("Control surface remote ID"),
1703                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1704                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1705                 );
1706
1707         rm->add (UserOrdered, _("assigned by user"));
1708         rm->add (MixerOrdered, _("follows order of mixer"));
1709         rm->add (EditorOrdered, _("follows order of editor"));
1710
1711         add_option (_("User interaction"), rm);
1712
1713         /* INTERFACE */
1714
1715         add_option (S_("GUI"),
1716              new BoolOption (
1717                      "widget-prelight",
1718                      _("Graphically indicate mouse pointer hovering over various widgets"),
1719                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
1720                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
1721                      ));
1722
1723         add_option (S_("GUI"),
1724              new BoolOption (
1725                      "use-tooltips",
1726                      _("Show tooltips if mouse hovers over a control"),
1727                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
1728                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
1729                      ));
1730
1731 #ifndef GTKOSX
1732         /* font scaling does nothing with GDK/Quartz */
1733         add_option (S_("GUI"), new FontScalingOptions (_rc_config));
1734 #endif
1735         add_option (S_("GUI"),
1736                     new BoolOption (
1737                             "use-own-plugin-gui",
1738                             _("Use plugins' own interfaces instead of Ardour's"),
1739                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
1740                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
1741                             ));
1742
1743         /* The names of these controls must be the same as those given in MixerStrip
1744            for the actual widgets being controlled.
1745         */
1746         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
1747         _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
1748         _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
1749         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
1750         _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
1751         
1752         add_option (
1753                 S_("GUI"),
1754                 new VisibilityOption (
1755                         _("Mixer Strip"),
1756                         &_mixer_strip_visibility,
1757                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
1758                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
1759                         )
1760                 );
1761
1762         add_option (S_("GUI"),
1763              new BoolOption (
1764                      "default-narrow_ms",
1765                      _("Use narrow strips in the mixer by default"),
1766                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
1767                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
1768                      ));
1769
1770         add_option (S_("GUI"), new OptionEditorHeading (_("Metering")));
1771
1772         ComboOption<float>* mht = new ComboOption<float> (
1773                 "meter-hold",
1774                 _("Meter hold time"),
1775                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
1776                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
1777                 );
1778
1779         mht->add (MeterHoldOff, _("off"));
1780         mht->add (MeterHoldShort, _("short"));
1781         mht->add (MeterHoldMedium, _("medium"));
1782         mht->add (MeterHoldLong, _("long"));
1783
1784         add_option (S_("GUI"), mht);
1785
1786         ComboOption<float>* mfo = new ComboOption<float> (
1787                 "meter-falloff",
1788                 _("Meter fall-off"),
1789                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
1790                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
1791                 );
1792
1793         mfo->add (METER_FALLOFF_OFF, _("off"));
1794         mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
1795         mfo->add (METER_FALLOFF_SLOW, _("slow"));
1796         mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
1797         mfo->add (METER_FALLOFF_FAST, _("fast"));
1798         mfo->add (METER_FALLOFF_FASTER, _("faster"));
1799         mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
1800
1801         add_option (S_("GUI"), mfo);
1802 }
1803
1804 void
1805 RCOptionEditor::parameter_changed (string const & p)
1806 {
1807         OptionEditor::parameter_changed (p);
1808
1809         if (p == "use-monitor-bus") {
1810                 bool const s = Config->get_use_monitor_bus ();
1811                 if (!s) {
1812                         /* we can't use this if we don't have a monitor bus */
1813                         Config->set_solo_control_is_listen_control (false);
1814                 }
1815                 _solo_control_is_listen_control->set_sensitive (s);
1816                 _listen_position->set_sensitive (s);
1817         } else if (p == "sync-source") {
1818                 _sync_source->set_sensitive (true);
1819                 if (_session) {
1820                         _sync_source->set_sensitive (_session->config.get_external_sync());
1821                 }
1822                 switch(Config->get_sync_source()) {
1823                 case ARDOUR::MTC:
1824                 case ARDOUR::LTC:
1825                         _sync_genlock->set_sensitive (true);
1826                         _sync_framerate->set_sensitive (true);
1827                         _sync_source_2997->set_sensitive (true);
1828                         break;
1829                 default:
1830                         _sync_genlock->set_sensitive (false);
1831                         _sync_framerate->set_sensitive (false);
1832                         _sync_source_2997->set_sensitive (false);
1833                         break;
1834                 }
1835 #ifdef HAVE_LTC
1836         } else if (p == "send-ltc") {
1837                 bool const s = Config->get_send_ltc ();
1838                 _ltc_send_continuously->set_sensitive (s);
1839                 _ltc_volume_slider->set_sensitive (s);
1840 #endif /*HAVE_LTC*/
1841         }
1842 }
1843
1844 void RCOptionEditor::ltc_generator_volume_changed () {
1845         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
1846 }
1847
1848 void
1849 RCOptionEditor::populate_sync_options ()
1850 {
1851         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
1852
1853         _sync_source->clear ();
1854
1855         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
1856                 _sync_source->add (*i, sync_source_to_string (*i));
1857         }
1858 }