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