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