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