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