plugin scan progress-display & preferences
[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 class PluginOptions : public OptionEditorBox
997 {
998 public:
999         PluginOptions (RCConfiguration* c)
1000                 : _rc_config (c)
1001                 , _display_plugin_scan_progress (_("Display Plugin Scan Progress"))
1002         {
1003                 Table* t = manage (new Table (2, 6));
1004                 t->set_spacings (4);
1005                 Button* b;
1006
1007                 b = manage (new Button (_("Clear VST Cache")));
1008                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_cache_clicked));
1009                 t->attach (*b, 0, 2, 0, 1, FILL);
1010
1011                 b = manage (new Button (_("Clear VST Blacklist")));
1012                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_blacklist_clicked));
1013                 t->attach (*b, 0, 2, 1, 2, FILL);
1014
1015                 b = manage (new Button (_("Refresh Plugin List")));
1016                 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::refresh_clicked));
1017                 t->attach (*b, 0, 2, 2, 3, FILL);
1018
1019                 t->attach (_display_plugin_scan_progress, 0, 2, 3, 4);
1020                 _display_plugin_scan_progress.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::display_plugin_scan_progress_toggled));
1021                 Gtkmm2ext::UI::instance()->set_tip (_display_plugin_scan_progress,
1022                                             _("<b>When enabled</b> a popup window details plugin-scan."));
1023
1024                 _box->pack_start (*t,true,true);
1025         }
1026
1027         void parameter_changed (string const & p) {
1028                 if (p == "show-plugin-scan-window") {
1029                         bool const x = _rc_config->get_show_plugin_scan_window();
1030                         _display_plugin_scan_progress.set_active (x);
1031                 }
1032         }
1033         void set_state_from_config () {
1034                 parameter_changed ("show-plugin-scan-window");
1035         }
1036
1037 private:
1038         RCConfiguration* _rc_config;
1039         CheckButton _display_plugin_scan_progress;
1040
1041         void display_plugin_scan_progress_toggled () {
1042                 bool const x = _display_plugin_scan_progress.get_active ();
1043                 _rc_config->set_show_plugin_scan_window (x);
1044         }
1045         void clear_vst_cache_clicked () {
1046                 PluginManager::instance().clear_vst_cache();
1047         }
1048
1049         void clear_vst_blacklist_clicked () {
1050                 PluginManager::instance().clear_vst_blacklist();
1051         }
1052
1053         void refresh_clicked () {
1054                 PluginManager::instance().refresh();
1055         }
1056 };
1057
1058
1059 /** A class which allows control of visibility of some editor components usign
1060  *  a VisibilityGroup.  The caller should pass in a `dummy' VisibilityGroup
1061  *  which has the correct members, but with null widget pointers.  This
1062  *  class allows the user to set visibility of the members, the details
1063  *  of which are stored in a configuration variable which can be watched
1064  *  by parts of the editor that actually contain the widgets whose visibility
1065  *  is being controlled.
1066  */
1067
1068 class VisibilityOption : public Option
1069 {
1070 public:
1071         /** @param name User-visible name for this group.
1072          *  @param g `Dummy' VisibilityGroup (as described above).
1073          *  @param get Method to get the value of the appropriate configuration variable.
1074          *  @param set Method to set the value of the appropriate configuration variable.
1075          */
1076         VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1077                 : Option (g->get_state_name(), name)
1078                 , _heading (name)
1079                 , _visibility_group (g)
1080                 , _get (get)
1081                 , _set (set)
1082         {
1083                 /* Watch for changes made by the user to our members */
1084                 _visibility_group->VisibilityChanged.connect_same_thread (
1085                         _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1086                         );
1087         }
1088
1089         void set_state_from_config ()
1090         {
1091                 /* Set our state from the current configuration */
1092                 _visibility_group->set_state (_get ());
1093         }
1094
1095         void add_to_page (OptionEditorPage* p)
1096         {
1097                 _heading.add_to_page (p);
1098                 add_widget_to_page (p, _visibility_group->list_view ());
1099         }
1100
1101         Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1102
1103 private:
1104         void changed ()
1105         {
1106                 /* The user has changed something, so reflect this change
1107                    in the RCConfiguration.
1108                 */
1109                 _set (_visibility_group->get_state_value ());
1110         }
1111         
1112         OptionEditorHeading _heading;
1113         VisibilityGroup* _visibility_group;
1114         sigc::slot<std::string> _get;
1115         sigc::slot<bool, std::string> _set;
1116         PBD::ScopedConnection _visibility_group_connection;
1117 };
1118
1119
1120
1121 RCOptionEditor::RCOptionEditor ()
1122         : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
1123         , _rc_config (Config)
1124         , _mixer_strip_visibility ("mixer-strip-visibility")
1125 {
1126         /* MISC */
1127
1128         uint32_t hwcpus = hardware_concurrency ();
1129         BoolOption* bo;
1130         BoolComboOption* bco;
1131
1132         if (hwcpus > 1) {
1133                 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
1134
1135                 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
1136                         "processor-usage",
1137                         _("Signal processing uses"),
1138                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
1139                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
1140                         );
1141
1142                 procs->add (-1, _("all but one processor"));
1143                 procs->add (0, _("all available processors"));
1144
1145                 for (uint32_t i = 1; i <= hwcpus; ++i) {
1146                         procs->add (i, string_compose (_("%1 processors"), i));
1147                 }
1148
1149                 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
1150
1151                 add_option (_("Misc"), procs);
1152         }
1153
1154         add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
1155
1156         add_option (_("Misc"), new UndoOptions (_rc_config));
1157
1158         add_option (_("Misc"),
1159              new BoolOption (
1160                      "verify-remove-last-capture",
1161                      _("Verify removal of last capture"),
1162                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
1163                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
1164                      ));
1165
1166         add_option (_("Misc"),
1167              new BoolOption (
1168                      "periodic-safety-backups",
1169                      _("Make periodic backups of the session file"),
1170                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1171                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1172                      ));
1173
1174         add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
1175
1176         add_option (_("Misc"),
1177              new BoolOption (
1178                      "only-copy-imported-files",
1179                      _("Always copy imported files"),
1180                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_only_copy_imported_files),
1181                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_only_copy_imported_files)
1182                      ));
1183
1184         add_option (_("Misc"), new DirectoryOption (
1185                             X_("default-session-parent-dir"),
1186                             _("Default folder for new sessions:"),
1187                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
1188                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
1189                             ));
1190
1191         add_option (_("Misc"),
1192              new SpinOption<uint32_t> (
1193                      "max-recent-sessions",
1194                      _("Maximum number of recent sessions"),
1195                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
1196                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
1197                      0, 1000, 1, 20
1198                      ));
1199
1200         add_option (_("Misc"), new OptionEditorHeading (_("Click")));
1201
1202         add_option (_("Misc"), new ClickOptions (_rc_config, this));
1203
1204         add_option (_("Misc"),
1205              new FaderOption (
1206                      "click-gain",
1207                      _("Click gain level"),
1208                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
1209                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
1210                      ));
1211
1212         add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
1213
1214         add_option (_("Misc"),
1215              new SpinOption<double> (
1216                      "automation-thinning-factor",
1217                      _("Thinning factor (larger value => less data)"),
1218                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
1219                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
1220                      0, 1000, 1, 20
1221                      ));
1222
1223         add_option (_("Misc"),
1224              new SpinOption<double> (
1225                      "automation-interval-msecs",
1226                      _("Automation sampling interval (milliseconds)"),
1227                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
1228                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
1229                      1, 1000, 1, 20
1230                      ));
1231
1232         /* TRANSPORT */
1233
1234         BoolOption* tsf;
1235
1236         tsf = new BoolOption (
1237                      "latched-record-enable",
1238                      _("Keep record-enable engaged on stop"),
1239                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
1240                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
1241                      );
1242         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1243         add_option (_("Transport"), tsf);
1244
1245         tsf = new BoolOption (
1246                      "stop-recording-on-xrun",
1247                      _("Stop recording when an xrun occurs"),
1248                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1249                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1250                      );
1251         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1252                                             string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
1253                                                             PROGRAM_NAME));
1254         add_option (_("Transport"), tsf);
1255
1256         tsf = new BoolOption (
1257                      "create-xrun-marker",
1258                      _("Create markers where xruns occur"),
1259                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1260                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1261                      );
1262         // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1263         add_option (_("Transport"), tsf);
1264
1265         tsf = new BoolOption (
1266                      "stop-at-session-end",
1267                      _("Stop at the end of the session"),
1268                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1269                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1270                      );
1271         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1272                                             string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1273                                                               "when it reaches the current session end marker\n\n"
1274                                                               "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1275                                                             PROGRAM_NAME));
1276         add_option (_("Transport"), tsf);
1277
1278         tsf = new BoolOption (
1279                      "seamless-loop",
1280                      _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1281                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1282                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1283                      );
1284         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), 
1285                                             string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1286                                                               "preventing any need to do a transport locate at the end of the loop\n\n"
1287                                                               "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
1288                                                               "which will often cause a small click or delay"), PROGRAM_NAME));
1289         add_option (_("Transport"), tsf);
1290
1291         tsf = new BoolOption (
1292                      "disable-disarm-during-roll",
1293                      _("Disable per-track record disarm while rolling"),
1294                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1295                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1296                      );
1297         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"));
1298         add_option (_("Transport"), tsf);
1299
1300         tsf = new BoolOption (
1301                      "quieten_at_speed",
1302                      _("12dB gain reduction during fast-forward and fast-rewind"),
1303                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1304                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1305                      );
1306         Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1307                                                    "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1308         add_option (_("Transport"), tsf);
1309
1310         add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1311
1312         _sync_source = new ComboOption<SyncSource> (
1313                 "sync-source",
1314                 _("External timecode source"),
1315                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1316                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1317                 );
1318
1319         populate_sync_options ();
1320         add_option (_("Transport"), _sync_source);
1321
1322         _sync_framerate = new BoolOption (
1323                      "timecode-sync-frame-rate",
1324                      _("Match session video frame rate to external timecode"),
1325                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1326                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1327                      );
1328         Gtkmm2ext::UI::instance()->set_tip 
1329                 (_sync_framerate->tip_widget(),
1330                  string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1331                                    "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1332                                    "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1333                                    "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1334                                    "timecode standard and the session standard."), PROGRAM_NAME));
1335
1336         add_option (_("Transport"), _sync_framerate);
1337
1338         _sync_genlock = new BoolOption (
1339                 "timecode-source-is-synced",
1340                 _("External timecode is sync locked"),
1341                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1342                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1343                 );
1344         Gtkmm2ext::UI::instance()->set_tip 
1345                 (_sync_genlock->tip_widget(), 
1346                  _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black &amp; Burst, Wordclock, etc) with the audio interface."));
1347
1348
1349         add_option (_("Transport"), _sync_genlock);
1350
1351         _sync_source_2997 = new BoolOption (
1352                 "timecode-source-2997",
1353                 _("Lock to 29.9700 fps instead of 30000/1001"),
1354                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1355                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1356                 );
1357         Gtkmm2ext::UI::instance()->set_tip
1358                 (_sync_source_2997->tip_widget(),
1359                  _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1360                          "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1361                          "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1362                          "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1363                          "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1364                          "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1365                          ));
1366
1367         add_option (_("Transport"), _sync_source_2997);
1368
1369         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1370
1371         _ltc_port = new ComboStringOption (
1372                 "ltc-source-port",
1373                 _("LTC incoming port"),
1374                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1375                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1376                 );
1377
1378         vector<string> physical_inputs;
1379         physical_inputs.push_back (_("None"));
1380         AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1381         _ltc_port->set_popdown_strings (physical_inputs);
1382
1383         add_option (_("Transport"), _ltc_port);
1384
1385         // TODO; rather disable this button than not compile it..
1386         add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1387
1388         add_option (_("Transport"),
1389                     new BoolOption (
1390                             "send-ltc",
1391                             _("Enable LTC generator"),
1392                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1393                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1394                             ));
1395
1396         _ltc_send_continuously = new BoolOption (
1397                             "ltc-send-continuously",
1398                             _("send LTC while stopped"),
1399                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1400                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1401                             );
1402         Gtkmm2ext::UI::instance()->set_tip
1403                 (_ltc_send_continuously->tip_widget(),
1404                  string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
1405         add_option (_("Transport"), _ltc_send_continuously);
1406
1407         _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1408         _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1409         _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1410         _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1411
1412         Gtkmm2ext::UI::instance()->set_tip
1413                 (_ltc_volume_slider->tip_widget(),
1414                  _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is  0dBu ^= -18dbFS in an EBU calibrated system"));
1415
1416         add_option (_("Transport"), _ltc_volume_slider);
1417         parameter_changed ("send-ltc");
1418
1419         parameter_changed ("sync-source");
1420
1421         /* EDITOR */
1422
1423         add_option (_("Editor"),
1424              new BoolOption (
1425                      "link-region-and-track-selection",
1426                      _("Link selection of regions and tracks"),
1427                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1428                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1429                      ));
1430
1431         add_option (_("Editor"),
1432              new BoolOption (
1433                      "automation-follows-regions",
1434                      _("Move relevant automation when audio regions are moved"),
1435                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1436                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1437                      ));
1438
1439         add_option (_("Editor"),
1440              new BoolOption (
1441                      "show-track-meters",
1442                      _("Show meters on tracks in the editor"),
1443                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1444                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1445                      ));
1446
1447         add_option (_("Editor"),
1448              new BoolOption (
1449                      "show-editor-meter",
1450                      _("Display master-meter in the toolbar"),
1451                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_editor_meter),
1452                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_editor_meter)
1453                      ));
1454
1455         bco = new BoolComboOption (
1456                      "use-overlap-equivalency",
1457                      _("Regions in active edit groups are edited together"),
1458                      _("whenever they overlap in time"),
1459                      _("only if they have identical length, position and origin"),
1460                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1461                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1462                      );
1463
1464         add_option (_("Editor"), bco);
1465
1466         add_option (_("Editor"),
1467              new BoolOption (
1468                      "rubberbanding-snaps-to-grid",
1469                      _("Make rubberband selection rectangle snap to the grid"),
1470                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1471                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1472                      ));
1473
1474         add_option (_("Editor"),
1475              new BoolOption (
1476                      "show-waveforms",
1477                      _("Show waveforms in regions"),
1478                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1479                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1480                      ));
1481
1482         add_option (_("Editor"),
1483              new BoolComboOption (
1484                      "show-region-gain-envelopes",
1485                      _("Show gain envelopes in audio regions"),
1486                      _("in all modes"),
1487                      _("only in region gain mode"),
1488                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1489                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1490                      ));
1491
1492         ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1493                 "waveform-scale",
1494                 _("Waveform scale"),
1495                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1496                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1497                 );
1498
1499         wfs->add (Linear, _("linear"));
1500         wfs->add (Logarithmic, _("logarithmic"));
1501
1502         add_option (_("Editor"), wfs);
1503
1504         ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1505                 "waveform-shape",
1506                 _("Waveform shape"),
1507                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1508                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1509                 );
1510
1511         wfsh->add (Traditional, _("traditional"));
1512         wfsh->add (Rectified, _("rectified"));
1513
1514         add_option (_("Editor"), wfsh);
1515
1516         add_option (_("Editor"), new ClipLevelOptions (_rc_config));
1517
1518         add_option (_("Editor"),
1519              new BoolOption (
1520                      "show-waveforms-while-recording",
1521                      _("Show waveforms for audio while it is being recorded"),
1522                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1523                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1524                      ));
1525
1526         add_option (_("Editor"),
1527                     new BoolOption (
1528                             "show-zoom-tools",
1529                             _("Show zoom toolbar"),
1530                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1531                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1532                             ));
1533
1534         add_option (_("Editor"),
1535                     new BoolOption (
1536                             "update-editor-during-summary-drag",
1537                             _("Update editor window during drags of the summary"),
1538                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1539                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1540                             ));
1541
1542         add_option (_("Editor"),
1543              new BoolOption (
1544                      "link-editor-and-mixer-selection",
1545                      _("Synchronise editor and mixer selection"),
1546                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1547                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1548                      ));
1549
1550         bo = new BoolOption (
1551                      "name-new-markers",
1552                      _("Name new markers"),
1553                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1554                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1555                 );
1556         
1557         add_option (_("Editor"), bo);
1558         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."
1559                                                                 "\n\nYou can always rename markers by right-clicking on them"));
1560
1561         add_option (_("Editor"),
1562             new BoolOption (
1563                     "autoscroll-editor",
1564                     _("Auto-scroll editor window when dragging near its edges"),
1565                     sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1566                     sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1567                     ));
1568
1569         /* AUDIO */
1570
1571         add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1572
1573         add_option (_("Audio"), new BufferingOptions (_rc_config));
1574
1575         add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1576
1577         ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1578                 "monitoring-model",
1579                 _("Record monitoring handled by"),
1580                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1581                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1582                 );
1583
1584         if (AudioEngine::instance()->port_engine().can_monitor_input()) {
1585                 mm->add (HardwareMonitoring, _("via Audio Driver"));
1586         }
1587
1588         string prog (PROGRAM_NAME);
1589         boost::algorithm::to_lower (prog);
1590         mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
1591         mm->add (ExternalMonitoring, _("audio hardware"));
1592
1593         add_option (_("Audio"), mm);
1594
1595         add_option (_("Audio"),
1596              new BoolOption (
1597                      "tape-machine-mode",
1598                      _("Tape machine mode"),
1599                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1600                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1601                      ));
1602
1603         add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1604
1605         add_option (_("Audio"),
1606                     new BoolOption (
1607                             "auto-connect-standard-busses",
1608                             _("Auto-connect master/monitor busses"),
1609                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1610                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1611                             ));
1612
1613         ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1614                 "input-auto-connect",
1615                 _("Connect track inputs"),
1616                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1617                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1618                 );
1619
1620         iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1621         iac->add (ManualConnect, _("manually"));
1622
1623         add_option (_("Audio"), iac);
1624
1625         ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1626                 "output-auto-connect",
1627                 _("Connect track and bus outputs"),
1628                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1629                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1630                 );
1631
1632         oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1633         oac->add (AutoConnectMaster, _("automatically to master bus"));
1634         oac->add (ManualConnect, _("manually"));
1635
1636         add_option (_("Audio"), oac);
1637
1638         add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1639
1640         add_option (_("Audio"),
1641              new BoolOption (
1642                      "denormal-protection",
1643                      _("Use DC bias to protect against denormals"),
1644                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1645                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1646                      ));
1647
1648         ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1649                 "denormal-model",
1650                 _("Processor handling"),
1651                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1652                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1653                 );
1654
1655         dm->add (DenormalNone, _("no processor handling"));
1656
1657         FPU fpu;
1658
1659         if (fpu.has_flush_to_zero()) {
1660                 dm->add (DenormalFTZ, _("use FlushToZero"));
1661         }
1662
1663         if (fpu.has_denormals_are_zero()) {
1664                 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1665         }
1666
1667         if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1668                 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1669         }
1670
1671         add_option (_("Audio"), dm);
1672
1673         add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1674
1675         add_option (_("Audio"),
1676              new BoolOption (
1677                      "plugins-stop-with-transport",
1678                      _("Silence plugins when the transport is stopped"),
1679                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1680                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1681                      ));
1682
1683         add_option (_("Audio"),
1684              new BoolOption (
1685                      "new-plugins-active",
1686                      _("Make new plugins active"),
1687                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1688                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1689                      ));
1690
1691         add_option (_("Audio"),
1692              new BoolOption (
1693                      "auto-analyse-audio",
1694                      _("Enable automatic analysis of audio"),
1695                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1696                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1697                      ));
1698
1699         add_option (_("Audio"),
1700              new BoolOption (
1701                      "replicate-missing-region-channels",
1702                      _("Replicate missing region channels"),
1703                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1704                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1705                      ));
1706
1707         /* SOLO AND MUTE */
1708
1709         add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
1710
1711         add_option (_("Solo / mute"),
1712              new FaderOption (
1713                      "solo-mute-gain",
1714                      _("Solo-in-place mute cut (dB)"),
1715                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1716                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1717                      ));
1718
1719         _solo_control_is_listen_control = new BoolOption (
1720                 "solo-control-is-listen-control",
1721                 _("Solo controls are Listen controls"),
1722                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1723                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1724                 );
1725
1726         add_option (_("Solo / mute"), _solo_control_is_listen_control);
1727
1728         _listen_position = new ComboOption<ListenPosition> (
1729                 "listen-position",
1730                 _("Listen Position"),
1731                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1732                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1733                 );
1734
1735         _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1736         _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1737
1738         add_option (_("Solo / mute"), _listen_position);
1739
1740         ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1741                 "pfl-position",
1742                 _("PFL signals come from"),
1743                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1744                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1745                 );
1746
1747         pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1748         pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1749
1750         add_option (_("Solo / mute"), pp);
1751
1752         ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1753                 "afl-position",
1754                 _("AFL signals come from"),
1755                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1756                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1757                 );
1758
1759         pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1760         pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1761
1762         add_option (_("Solo / mute"), pa);
1763
1764         parameter_changed ("use-monitor-bus");
1765
1766         add_option (_("Solo / mute"),
1767              new BoolOption (
1768                      "exclusive-solo",
1769                      _("Exclusive solo"),
1770                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1771                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1772                      ));
1773
1774         add_option (_("Solo / mute"),
1775              new BoolOption (
1776                      "show-solo-mutes",
1777                      _("Show solo muting"),
1778                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1779                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1780                      ));
1781
1782         add_option (_("Solo / mute"),
1783              new BoolOption (
1784                      "solo-mute-override",
1785                      _("Soloing overrides muting"),
1786                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1787                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1788                      ));
1789
1790         add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1791
1792         add_option (_("Solo / mute"),
1793              new BoolOption (
1794                      "mute-affects-pre-fader",
1795                      _("Mute affects pre-fader sends"),
1796                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1797                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1798                      ));
1799
1800         add_option (_("Solo / mute"),
1801              new BoolOption (
1802                      "mute-affects-post-fader",
1803                      _("Mute affects post-fader sends"),
1804                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1805                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1806                      ));
1807
1808         add_option (_("Solo / mute"),
1809              new BoolOption (
1810                      "mute-affects-control-outs",
1811                      _("Mute affects control outputs"),
1812                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1813                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1814                      ));
1815
1816         add_option (_("Solo / mute"),
1817              new BoolOption (
1818                      "mute-affects-main-outs",
1819                      _("Mute affects main outputs"),
1820                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1821                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1822                      ));
1823
1824         add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
1825
1826         add_option (_("Solo / mute"),
1827              new BoolOption (
1828                      "link-send-and-route-panner",
1829                      _("Link panners of Aux and External Sends with main panner by default"),
1830                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
1831                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
1832                      ));
1833
1834         add_option (_("MIDI"),
1835                     new BoolOption (
1836                             "send-midi-clock",
1837                             _("Send MIDI Clock"),
1838                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1839                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1840                             ));
1841
1842         add_option (_("MIDI"),
1843                     new BoolOption (
1844                             "send-mtc",
1845                             _("Send MIDI Time Code"),
1846                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1847                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1848                             ));
1849
1850         add_option (_("MIDI"),
1851                     new SpinOption<int> (
1852                             "mtc-qf-speed-tolerance",
1853                             _("Percentage either side of normal transport speed to transmit MTC"),
1854                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1855                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1856                             0, 20, 1, 5
1857                             ));
1858
1859         add_option (_("MIDI"),
1860                     new BoolOption (
1861                             "mmc-control",
1862                             _("Obey MIDI Machine Control commands"),
1863                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1864                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1865                             ));
1866
1867         add_option (_("MIDI"),
1868                     new BoolOption (
1869                             "send-mmc",
1870                             _("Send MIDI Machine Control commands"),
1871                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1872                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1873                             ));
1874
1875         add_option (_("MIDI"),
1876                     new BoolOption (
1877                             "midi-feedback",
1878                             _("Send MIDI control feedback"),
1879                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1880                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1881                             ));
1882
1883         add_option (_("MIDI"),
1884              new SpinOption<uint8_t> (
1885                      "mmc-receive-device-id",
1886                      _("Inbound MMC device ID"),
1887                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1888                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1889                      0, 128, 1, 10
1890                      ));
1891
1892         add_option (_("MIDI"),
1893              new SpinOption<uint8_t> (
1894                      "mmc-send-device-id",
1895                      _("Outbound MMC device ID"),
1896                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1897                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1898                      0, 128, 1, 10
1899                      ));
1900
1901         add_option (_("MIDI"),
1902              new SpinOption<int32_t> (
1903                      "initial-program-change",
1904                      _("Initial program change"),
1905                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1906                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1907                      -1, 65536, 1, 10
1908                      ));
1909
1910         add_option (_("MIDI"),
1911                     new BoolOption (
1912                             "diplay-first-midi-bank-as-zero",
1913                             _("Display first MIDI bank/program as 0"),
1914                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1915                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1916                             ));
1917
1918         add_option (_("MIDI"),
1919              new BoolOption (
1920                      "never-display-periodic-midi",
1921                      _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1922                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1923                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1924                      ));
1925
1926         add_option (_("MIDI"),
1927              new BoolOption (
1928                      "sound-midi-notes",
1929                      _("Sound MIDI notes as they are selected"),
1930                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1931                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1932                      ));
1933
1934         add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
1935
1936         ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
1937                 "midi-audition-synth-uri",
1938                 _("Midi Audition Synth (LV2)"),
1939                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
1940                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
1941                 );
1942
1943         audition_synth->add(X_(""), _("None"));
1944         PluginInfoList all_plugs;
1945         PluginManager& manager (PluginManager::instance());
1946 #ifdef LV2_SUPPORT
1947         all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
1948
1949         for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
1950                 if (manager.get_status (*i) == PluginManager::Hidden) continue;
1951                 if (!(*i)->is_instrument()) continue;
1952                 if ((*i)->type != ARDOUR::LV2) continue;
1953                 audition_synth->add((*i)->unique_id, (*i)->name);
1954         }
1955 #endif
1956
1957         add_option (_("MIDI"), audition_synth);
1958
1959         /* USER INTERACTION */
1960
1961         if (getenv ("ARDOUR_BUNDLED")) {
1962                 add_option (_("User interaction"), 
1963                             new BoolOption (
1964                                     "enable-translation",
1965                                     string_compose (_("Use translations of %1 messages\n"
1966                                                       "   <i>(requires a restart of %1 to take effect)</i>\n"
1967                                                       "   <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
1968                                     sigc::ptr_fun (ARDOUR::translations_are_enabled),
1969                                     sigc::ptr_fun (ARDOUR::set_translations_enabled)));
1970         }
1971
1972         add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1973
1974         add_option (_("User interaction"), new KeyboardOptions);
1975
1976         /* Control Surfaces */
1977
1978         add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
1979
1980         ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1981                 "remote-model",
1982                 _("Control surface remote ID"),
1983                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1984                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1985                 );
1986
1987         rm->add (UserOrdered, _("assigned by user"));
1988         rm->add (MixerOrdered, _("follows order of mixer"));
1989
1990         add_option (_("Control Surfaces"), rm);
1991
1992         /* VIDEO Timeline */
1993         add_option (_("Video"), new VideoTimelineOptions (_rc_config));
1994
1995 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
1996         /* Plugin options (currrently VST only) */
1997         add_option (_("Plugin"), new PluginOptions (_rc_config));
1998 #endif
1999
2000         /* INTERFACE */
2001
2002         add_option (S_("Preferences|GUI"),
2003              new BoolOption (
2004                      "widget-prelight",
2005                      _("Graphically indicate mouse pointer hovering over various widgets"),
2006                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
2007                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
2008                      ));
2009
2010         add_option (S_("Preferences|GUI"),
2011              new BoolOption (
2012                      "use-tooltips",
2013                      _("Show tooltips if mouse hovers over a control"),
2014                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
2015                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
2016                      ));
2017
2018 #ifndef GTKOSX
2019         /* font scaling does nothing with GDK/Quartz */
2020         add_option (S_("Preferences|GUI"), new FontScalingOptions (_rc_config));
2021 #endif
2022
2023         add_option (S_("GUI"),
2024                     new BoolOption (
2025                             "super-rapid-clock-update",
2026                             _("update transport clock display every 40ms instead of every 100ms"),
2027                             sigc::mem_fun (*_rc_config, &RCConfiguration::get_super_rapid_clock_update),
2028                             sigc::mem_fun (*_rc_config, &RCConfiguration::set_super_rapid_clock_update)
2029                             ));
2030
2031         /* The names of these controls must be the same as those given in MixerStrip
2032            for the actual widgets being controlled.
2033         */
2034         _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2035         _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
2036         _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
2037         _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2038         _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
2039         
2040         add_option (
2041                 S_("Preferences|GUI"),
2042                 new VisibilityOption (
2043                         _("Mixer Strip"),
2044                         &_mixer_strip_visibility,
2045                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
2046                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
2047                         )
2048                 );
2049
2050         add_option (S_("Preferences|GUI"),
2051              new BoolOption (
2052                      "default-narrow_ms",
2053                      _("Use narrow strips in the mixer by default"),
2054                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
2055                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
2056                      ));
2057
2058         add_option (S_("Preferences|GUI"), new OptionEditorHeading (_("Metering")));
2059
2060         ComboOption<float>* mht = new ComboOption<float> (
2061                 "meter-hold",
2062                 _("Peak hold time"),
2063                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
2064                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
2065                 );
2066
2067         mht->add (MeterHoldOff, _("off"));
2068         mht->add (MeterHoldShort, _("short"));
2069         mht->add (MeterHoldMedium, _("medium"));
2070         mht->add (MeterHoldLong, _("long"));
2071
2072         add_option (S_("Preferences|GUI"), mht);
2073
2074         ComboOption<float>* mfo = new ComboOption<float> (
2075                 "meter-falloff",
2076                 _("DPM fall-off"),
2077                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2078                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2079                 );
2080
2081         mfo->add (METER_FALLOFF_OFF,      _("off"));
2082         mfo->add (METER_FALLOFF_SLOWEST,  _("slowest [6.6dB/sec]"));
2083         mfo->add (METER_FALLOFF_SLOW,     _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2084         mfo->add (METER_FALLOFF_SLOWISH,  _("slowish [12.0dB/sec] (DIN)"));
2085         mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2086         mfo->add (METER_FALLOFF_MEDIUM,   _("medium [20dB/sec]"));
2087         mfo->add (METER_FALLOFF_FAST,     _("fast [32dB/sec]"));
2088         mfo->add (METER_FALLOFF_FASTER,   _("faster [46dB/sec]"));
2089         mfo->add (METER_FALLOFF_FASTEST,  _("fastest [70dB/sec]"));
2090
2091         add_option (S_("Preferences|GUI"), mfo);
2092
2093         ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2094                 "meter-line-up-level",
2095                 _("Meter line-up level; 0dBu"),
2096                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_level),
2097                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_level)
2098                 );
2099
2100         mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2101         mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2102         mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2103         mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2104
2105         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."));
2106
2107         add_option (S_("Preferences|GUI"), mlu);
2108
2109         ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2110                 "meter-line-up-din",
2111                 _("IEC1/DIN Meter line-up level; 0dBu"),
2112                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_line_up_din),
2113                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_line_up_din)
2114                 );
2115
2116         mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2117         mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2118         mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2119         mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2120
2121         Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2122
2123         add_option (S_("Preferences|GUI"), mld);
2124
2125         ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2126                 "meter-vu-standard",
2127                 _("VU Meter standard"),
2128                 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_vu_standard),
2129                 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_vu_standard)
2130                 );
2131
2132         mvu->add (MeteringVUfrench,   _("0VU = -2dBu (France)"));
2133         mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2134         mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2135         mvu->add (MeteringVUeight,    _("0VU = +8dBu"));
2136
2137         add_option (S_("Preferences|GUI"), mvu);
2138
2139         Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2140         HSliderOption *mpks = new HSliderOption("meter-peak",
2141                         _("Peak threshold [dBFS]"),
2142                         mpk,
2143                         sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_peak),
2144                         sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_peak)
2145                         );
2146
2147         Gtkmm2ext::UI::instance()->set_tip
2148                 (mpks->tip_widget(),
2149                  _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2150
2151         add_option (S_("Preferences|GUI"), mpks);
2152
2153         add_option (S_("Preferences|GUI"),
2154              new BoolOption (
2155                      "meter-style-led",
2156                      _("LED meter style"),
2157                      sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_style_led),
2158                      sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_style_led)
2159                      ));
2160
2161 }
2162
2163 void
2164 RCOptionEditor::parameter_changed (string const & p)
2165 {
2166         OptionEditor::parameter_changed (p);
2167
2168         if (p == "use-monitor-bus") {
2169                 bool const s = Config->get_use_monitor_bus ();
2170                 if (!s) {
2171                         /* we can't use this if we don't have a monitor bus */
2172                         Config->set_solo_control_is_listen_control (false);
2173                 }
2174                 _solo_control_is_listen_control->set_sensitive (s);
2175                 _listen_position->set_sensitive (s);
2176         } else if (p == "sync-source") {
2177                 _sync_source->set_sensitive (true);
2178                 if (_session) {
2179                         _sync_source->set_sensitive (!_session->config.get_external_sync());
2180                 }
2181                 switch(Config->get_sync_source()) {
2182                 case ARDOUR::MTC:
2183                 case ARDOUR::LTC:
2184                         _sync_genlock->set_sensitive (true);
2185                         _sync_framerate->set_sensitive (true);
2186                         _sync_source_2997->set_sensitive (true);
2187                         break;
2188                 default:
2189                         _sync_genlock->set_sensitive (false);
2190                         _sync_framerate->set_sensitive (false);
2191                         _sync_source_2997->set_sensitive (false);
2192                         break;
2193                 }
2194         } else if (p == "send-ltc") {
2195                 bool const s = Config->get_send_ltc ();
2196                 _ltc_send_continuously->set_sensitive (s);
2197                 _ltc_volume_slider->set_sensitive (s);
2198         }
2199 }
2200
2201 void RCOptionEditor::ltc_generator_volume_changed () {
2202         _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2203 }
2204
2205 void
2206 RCOptionEditor::populate_sync_options ()
2207 {
2208         vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2209
2210         _sync_source->clear ();
2211
2212         for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2213                 _sync_source->add (*i, sync_source_to_string (*i));
2214         }
2215 }