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