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