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