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