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