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