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