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