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