2 Copyright (C) 2001-2011 Paul Davis
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.
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.
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.
21 #include "gtk2ardour-config.h"
24 #include <boost/algorithm/string.hpp>
26 #include <gtkmm/liststore.h>
27 #include <gtkmm/stock.h>
28 #include <gtkmm/scale.h>
30 #include <gtkmm2ext/utils.h>
31 #include <gtkmm2ext/slider_controller.h>
32 #include <gtkmm2ext/gtk_ui.h>
33 #include <gtkmm2ext/paths_dialog.h>
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"
45 #include "canvas/wave_view.h"
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"
54 #include "midi_port_dialog.h"
57 #include "theme_manager.h"
58 #include "ui_config.h"
63 using namespace Gtkmm2ext;
65 using namespace ARDOUR;
66 using namespace ARDOUR_UI_UTILS;
68 class ClickOptions : public OptionEditorBox
71 ClickOptions (RCConfiguration* c, Gtk::Window* p)
74 Table* t = manage (new Table (2, 3));
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);
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);
91 _box->pack_start (*t, false, false);
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));
97 void parameter_changed (string const & p)
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());
106 void set_state_from_config ()
108 parameter_changed ("click-sound");
109 parameter_changed ("click-emphasis-sound");
114 void click_browse_clicked ()
116 SoundFileChooser sfdb (_("Choose Click"));
121 if (sfdb.run () == RESPONSE_OK) {
122 click_chosen (sfdb.get_filename());
126 void click_chosen (string const & path)
128 _click_path_entry.set_text (path);
129 _rc_config->set_click_sound (path);
132 void click_changed ()
134 click_chosen (_click_path_entry.get_text ());
137 void click_emphasis_browse_clicked ()
139 SoundFileChooser sfdb (_("Choose Click Emphasis"));
144 if (sfdb.run () == RESPONSE_OK) {
145 click_emphasis_chosen (sfdb.get_filename());
149 void click_emphasis_chosen (string const & path)
151 _click_emphasis_path_entry.set_text (path);
152 _rc_config->set_click_emphasis_sound (path);
155 void click_emphasis_changed ()
157 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
160 RCConfiguration* _rc_config;
161 Entry _click_path_entry;
162 Entry _click_emphasis_path_entry;
165 class UndoOptions : public OptionEditorBox
168 UndoOptions (RCConfiguration* c) :
170 _limit_undo_button (_("Limit undo history to")),
171 _save_undo_button (_("Save undo history of"))
173 Table* t = new Table (2, 3);
176 t->attach (_limit_undo_button, 0, 1, 0, 1, FILL);
177 _limit_undo_spin.set_range (0, 512);
178 _limit_undo_spin.set_increments (1, 10);
179 t->attach (_limit_undo_spin, 1, 2, 0, 1, FILL | EXPAND);
180 Label* l = manage (left_aligned_label (_("commands")));
181 t->attach (*l, 2, 3, 0, 1);
183 t->attach (_save_undo_button, 0, 1, 1, 2, FILL);
184 _save_undo_spin.set_range (0, 512);
185 _save_undo_spin.set_increments (1, 10);
186 t->attach (_save_undo_spin, 1, 2, 1, 2, FILL | EXPAND);
187 l = manage (left_aligned_label (_("commands")));
188 t->attach (*l, 2, 3, 1, 2);
190 _box->pack_start (*t);
192 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
193 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
194 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
195 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
198 void parameter_changed (string const & p)
200 if (p == "history-depth") {
201 int32_t const d = _rc_config->get_history_depth();
202 _limit_undo_button.set_active (d != 0);
203 _limit_undo_spin.set_sensitive (d != 0);
204 _limit_undo_spin.set_value (d);
205 } else if (p == "save-history") {
206 bool const x = _rc_config->get_save_history ();
207 _save_undo_button.set_active (x);
208 _save_undo_spin.set_sensitive (x);
209 } else if (p == "save-history-depth") {
210 _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
214 void set_state_from_config ()
216 parameter_changed ("save-history");
217 parameter_changed ("history-depth");
218 parameter_changed ("save-history-depth");
221 void limit_undo_toggled ()
223 bool const x = _limit_undo_button.get_active ();
224 _limit_undo_spin.set_sensitive (x);
225 int32_t const n = x ? 16 : 0;
226 _limit_undo_spin.set_value (n);
227 _rc_config->set_history_depth (n);
230 void limit_undo_changed ()
232 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
235 void save_undo_toggled ()
237 bool const x = _save_undo_button.get_active ();
238 _rc_config->set_save_history (x);
241 void save_undo_changed ()
243 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
247 RCConfiguration* _rc_config;
248 CheckButton _limit_undo_button;
249 SpinButton _limit_undo_spin;
250 CheckButton _save_undo_button;
251 SpinButton _save_undo_spin;
256 static const struct {
268 { "Key|Shift", GDK_SHIFT_MASK },
269 { "Command", GDK_META_MASK },
270 { "Control", GDK_CONTROL_MASK },
271 { "Option", GDK_MOD1_MASK },
272 { "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
273 { "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
274 { "Shift-Option", GDK_SHIFT_MASK|GDK_MOD1_MASK },
275 { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
278 { "Key|Shift", GDK_SHIFT_MASK },
279 { "Control", GDK_CONTROL_MASK },
280 { "Alt (Mod1)", GDK_MOD1_MASK },
281 { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
282 { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
283 { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
284 { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
285 { "Mod2", GDK_MOD2_MASK },
286 { "Mod3", GDK_MOD3_MASK },
287 { "Mod4", GDK_MOD4_MASK },
288 { "Mod5", GDK_MOD5_MASK },
294 class KeyboardOptions : public OptionEditorBox
298 _delete_button_adjustment (3, 1, 12),
299 _delete_button_spin (_delete_button_adjustment),
300 _edit_button_adjustment (3, 1, 5),
301 _edit_button_spin (_edit_button_adjustment),
302 _insert_note_button_adjustment (3, 1, 5),
303 _insert_note_button_spin (_insert_note_button_adjustment)
305 /* internationalize and prepare for use with combos */
308 for (int i = 0; modifiers[i].name; ++i) {
309 dumb.push_back (S_(modifiers[i].name));
312 set_popdown_strings (_edit_modifier_combo, dumb);
313 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
315 for (int x = 0; modifiers[x].name; ++x) {
316 if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
317 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
322 Table* t = manage (new Table (4, 4));
325 Label* l = manage (left_aligned_label (_("Edit using:")));
326 l->set_name ("OptionsLabel");
328 t->attach (*l, 0, 1, 0, 1, FILL | EXPAND, FILL);
329 t->attach (_edit_modifier_combo, 1, 2, 0, 1, FILL | EXPAND, FILL);
331 l = manage (new Label (_("+ button")));
332 l->set_name ("OptionsLabel");
334 t->attach (*l, 3, 4, 0, 1, FILL | EXPAND, FILL);
335 t->attach (_edit_button_spin, 4, 5, 0, 1, FILL | EXPAND, FILL);
337 _edit_button_spin.set_name ("OptionsEntry");
338 _edit_button_adjustment.set_value (Keyboard::edit_button());
339 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
341 set_popdown_strings (_delete_modifier_combo, dumb);
342 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
344 for (int x = 0; modifiers[x].name; ++x) {
345 if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
346 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
351 l = manage (left_aligned_label (_("Delete using:")));
352 l->set_name ("OptionsLabel");
354 t->attach (*l, 0, 1, 1, 2, FILL | EXPAND, FILL);
355 t->attach (_delete_modifier_combo, 1, 2, 1, 2, FILL | EXPAND, FILL);
357 l = manage (new Label (_("+ button")));
358 l->set_name ("OptionsLabel");
360 t->attach (*l, 3, 4, 1, 2, FILL | EXPAND, FILL);
361 t->attach (_delete_button_spin, 4, 5, 1, 2, FILL | EXPAND, FILL);
363 _delete_button_spin.set_name ("OptionsEntry");
364 _delete_button_adjustment.set_value (Keyboard::delete_button());
365 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
368 set_popdown_strings (_insert_note_modifier_combo, dumb);
369 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
371 for (int x = 0; modifiers[x].name; ++x) {
372 if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
373 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
378 l = manage (left_aligned_label (_("Insert note using:")));
379 l->set_name ("OptionsLabel");
381 t->attach (*l, 0, 1, 2, 3, FILL | EXPAND, FILL);
382 t->attach (_insert_note_modifier_combo, 1, 2, 2, 3, FILL | EXPAND, FILL);
384 l = manage (new Label (_("+ button")));
385 l->set_name ("OptionsLabel");
387 t->attach (*l, 3, 4, 2, 3, FILL | EXPAND, FILL);
388 t->attach (_insert_note_button_spin, 4, 5, 2, 3, FILL | EXPAND, FILL);
390 _insert_note_button_spin.set_name ("OptionsEntry");
391 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
392 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
395 set_popdown_strings (_snap_modifier_combo, dumb);
396 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
398 for (int x = 0; modifiers[x].name; ++x) {
399 if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
400 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
405 l = manage (left_aligned_label (_("Ignore snap using:")));
406 l->set_name ("OptionsLabel");
408 t->attach (*l, 0, 1, 3, 4, FILL | EXPAND, FILL);
409 t->attach (_snap_modifier_combo, 1, 2, 3, 4, FILL | EXPAND, FILL);
413 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
414 strs.push_back (bf->first);
417 set_popdown_strings (_keyboard_layout_selector, strs);
418 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
419 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
421 l = manage (left_aligned_label (_("Keyboard layout:")));
422 l->set_name ("OptionsLabel");
424 t->attach (*l, 0, 1, 4, 5, FILL | EXPAND, FILL);
425 t->attach (_keyboard_layout_selector, 1, 2, 4, 5, FILL | EXPAND, FILL);
427 _box->pack_start (*t, false, false);
430 void parameter_changed (string const &)
432 /* XXX: these aren't really config options... */
435 void set_state_from_config ()
437 /* XXX: these aren't really config options... */
442 void bindings_changed ()
444 string const txt = _keyboard_layout_selector.get_active_text();
446 /* XXX: config...? for all this keyboard stuff */
448 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
449 if (txt == i->first) {
450 if (Keyboard::load_keybindings (i->second)) {
451 Keyboard::save_keybindings ();
457 void edit_modifier_chosen ()
459 string const txt = _edit_modifier_combo.get_active_text();
461 for (int i = 0; modifiers[i].name; ++i) {
462 if (txt == _(modifiers[i].name)) {
463 Keyboard::set_edit_modifier (modifiers[i].modifier);
469 void delete_modifier_chosen ()
471 string const txt = _delete_modifier_combo.get_active_text();
473 for (int i = 0; modifiers[i].name; ++i) {
474 if (txt == _(modifiers[i].name)) {
475 Keyboard::set_delete_modifier (modifiers[i].modifier);
481 void insert_note_modifier_chosen ()
483 string const txt = _insert_note_modifier_combo.get_active_text();
485 for (int i = 0; modifiers[i].name; ++i) {
486 if (txt == _(modifiers[i].name)) {
487 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
493 void snap_modifier_chosen ()
495 string const txt = _snap_modifier_combo.get_active_text();
497 for (int i = 0; modifiers[i].name; ++i) {
498 if (txt == _(modifiers[i].name)) {
499 Keyboard::set_snap_modifier (modifiers[i].modifier);
505 void delete_button_changed ()
507 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
510 void edit_button_changed ()
512 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
515 void insert_note_button_changed ()
517 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
520 ComboBoxText _keyboard_layout_selector;
521 ComboBoxText _edit_modifier_combo;
522 ComboBoxText _delete_modifier_combo;
523 ComboBoxText _insert_note_modifier_combo;
524 ComboBoxText _snap_modifier_combo;
525 Adjustment _delete_button_adjustment;
526 SpinButton _delete_button_spin;
527 Adjustment _edit_button_adjustment;
528 SpinButton _edit_button_spin;
529 Adjustment _insert_note_button_adjustment;
530 SpinButton _insert_note_button_spin;
534 class FontScalingOptions : public OptionEditorBox
537 FontScalingOptions (UIConfiguration* uic) :
539 _dpi_adjustment (100, 50, 250, 1, 5),
540 _dpi_slider (_dpi_adjustment)
542 _dpi_adjustment.set_value (_ui_config->get_font_scale() / 1024.);
544 Label* l = manage (new Label (_("Font scaling:")));
545 l->set_name ("OptionsLabel");
547 const Glib::ustring dflt = _("Default");
548 const Glib::ustring empty = X_(""); // despite gtk-doc saying so, NULL does not work as reference
550 _dpi_slider.set_name("FontScaleSlider");
551 _dpi_slider.set_update_policy (UPDATE_DISCONTINUOUS);
552 _dpi_slider.set_draw_value(false);
553 _dpi_slider.add_mark(50, Gtk::POS_TOP, empty);
554 _dpi_slider.add_mark(60, Gtk::POS_TOP, empty);
555 _dpi_slider.add_mark(70, Gtk::POS_TOP, empty);
556 _dpi_slider.add_mark(80, Gtk::POS_TOP, empty);
557 _dpi_slider.add_mark(90, Gtk::POS_TOP, empty);
558 _dpi_slider.add_mark(100, Gtk::POS_TOP, dflt);
559 _dpi_slider.add_mark(125, Gtk::POS_TOP, empty);
560 _dpi_slider.add_mark(150, Gtk::POS_TOP, empty);
561 _dpi_slider.add_mark(175, Gtk::POS_TOP, empty);
562 _dpi_slider.add_mark(200, Gtk::POS_TOP, empty);
563 _dpi_slider.add_mark(225, Gtk::POS_TOP, empty);
564 _dpi_slider.add_mark(250, Gtk::POS_TOP, empty);
566 HBox* h = manage (new HBox);
568 h->pack_start (*l, false, false);
569 h->pack_start (_dpi_slider, true, true);
571 _box->pack_start (*h, false, false);
573 set_note (_("Major font-scale changes require an application restart to re-layout."));
575 _dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
578 void parameter_changed (string const & p)
580 if (p == "font-scale") {
581 _dpi_adjustment.set_value (_ui_config->get_font_scale() / 1024.);
585 void set_state_from_config ()
587 parameter_changed ("font-scale");
594 _ui_config->set_font_scale ((long) floor (_dpi_adjustment.get_value() * 1024.));
595 /* XXX: should be triggered from the parameter changed signal */
599 UIConfiguration* _ui_config;
600 Adjustment _dpi_adjustment;
604 class ClipLevelOptions : public OptionEditorBox
607 ClipLevelOptions (UIConfiguration* c)
609 , _clip_level_adjustment (-.5, -50.0, 0.0, 0.1, 1.0) /* units of dB */
610 , _clip_level_slider (_clip_level_adjustment)
612 _clip_level_adjustment.set_value (_ui_config->get_waveform_clip_level ());
614 Label* l = manage (new Label (_("Waveform Clip Level (dBFS):")));
615 l->set_name ("OptionsLabel");
617 _clip_level_slider.set_update_policy (UPDATE_DISCONTINUOUS);
618 HBox* h = manage (new HBox);
620 h->pack_start (*l, false, false);
621 h->pack_start (_clip_level_slider, true, true);
623 _box->pack_start (*h, false, false);
625 _clip_level_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &ClipLevelOptions::clip_level_changed));
628 void parameter_changed (string const & p)
630 if (p == "waveform-clip-level") {
631 _clip_level_adjustment.set_value (_ui_config->get_waveform_clip_level());
635 void set_state_from_config ()
637 parameter_changed ("waveform-clip-level");
642 void clip_level_changed ()
644 _ui_config->set_waveform_clip_level (_clip_level_adjustment.get_value());
645 /* XXX: should be triggered from the parameter changed signal */
646 ArdourCanvas::WaveView::set_clip_level (_clip_level_adjustment.get_value());
649 UIConfiguration* _ui_config;
650 Adjustment _clip_level_adjustment;
651 HScale _clip_level_slider;
654 class BufferingOptions : public OptionEditorBox
657 BufferingOptions (RCConfiguration* c)
659 , _playback_adjustment (5, 1, 60, 1, 4)
660 , _capture_adjustment (5, 1, 60, 1, 4)
661 , _playback_slider (_playback_adjustment)
662 , _capture_slider (_capture_adjustment)
664 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
666 Label* l = manage (new Label (_("Playback (seconds of buffering):")));
667 l->set_name ("OptionsLabel");
669 _playback_slider.set_update_policy (UPDATE_DISCONTINUOUS);
670 HBox* h = manage (new HBox);
672 h->pack_start (*l, false, false);
673 h->pack_start (_playback_slider, true, true);
675 _box->pack_start (*h, false, false);
677 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
679 l = manage (new Label (_("Recording (seconds of buffering):")));
680 l->set_name ("OptionsLabel");
682 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
683 h = manage (new HBox);
685 h->pack_start (*l, false, false);
686 h->pack_start (_capture_slider, true, true);
688 _box->pack_start (*h, false, false);
690 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
691 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
694 void parameter_changed (string const & p)
696 if (p == "playback-buffer-seconds") {
697 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
698 } else if (p == "capture-buffer-seconds") {
699 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
703 void set_state_from_config ()
705 parameter_changed ("playback-buffer-seconds");
706 parameter_changed ("capture-buffer-seconds");
711 void playback_changed ()
713 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
716 void capture_changed ()
718 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
721 RCConfiguration* _rc_config;
722 Adjustment _playback_adjustment;
723 Adjustment _capture_adjustment;
724 HScale _playback_slider;
725 HScale _capture_slider;
728 class ControlSurfacesOptions : public OptionEditorBox
731 ControlSurfacesOptions (Gtk::Window& parent)
733 , _ignore_view_change (0)
735 _store = ListStore::create (_model);
736 _view.set_model (_store);
737 _view.append_column (_("Control Surface Protocol"), _model.name);
738 _view.get_column(0)->set_resizable (true);
739 _view.get_column(0)->set_expand (true);
740 _view.append_column_editable (_("Enabled"), _model.enabled);
741 _view.append_column_editable (_("Feedback"), _model.feedback);
743 _box->pack_start (_view, false, false);
745 Label* label = manage (new Label);
746 label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
748 _box->pack_start (*label, false, false);
751 ControlProtocolManager& m = ControlProtocolManager::instance ();
752 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
753 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
755 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
756 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
759 void parameter_changed (std::string const &)
764 void set_state_from_config ()
768 ControlProtocolManager& m = ControlProtocolManager::instance ();
769 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
771 if (!(*i)->mandatory) {
772 TreeModel::Row r = *_store->append ();
773 r[_model.name] = (*i)->name;
774 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
775 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
776 r[_model.protocol_info] = *i;
783 void protocol_status_changed (ControlProtocolInfo* cpi) {
785 TreeModel::Children rows = _store->children();
787 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
788 string n = ((*x)[_model.name]);
790 if ((*x)[_model.protocol_info] == cpi) {
791 _ignore_view_change++;
792 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
793 _ignore_view_change--;
799 void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
801 TreeModel::Row r = *i;
803 if (_ignore_view_change) {
807 ControlProtocolInfo* cpi = r[_model.protocol_info];
812 bool const was_enabled = (cpi->protocol != 0);
813 bool const is_enabled = r[_model.enabled];
816 if (was_enabled != is_enabled) {
819 ControlProtocolManager::instance().activate (*cpi);
821 ControlProtocolManager::instance().deactivate (*cpi);
825 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
826 bool const is_feedback = r[_model.feedback];
828 if (was_feedback != is_feedback && cpi->protocol) {
829 cpi->protocol->set_feedback (is_feedback);
833 void edit_clicked (GdkEventButton* ev)
835 if (ev->type != GDK_2BUTTON_PRESS) {
840 ControlProtocolInfo* cpi;
843 row = *(_view.get_selection()->get_selected());
844 if (!row[_model.enabled]) {
847 cpi = row[_model.protocol_info];
848 if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
851 Box* box = (Box*) cpi->protocol->get_gui ();
855 if (box->get_parent()) {
856 static_cast<ArdourWindow*>(box->get_parent())->present();
859 string title = row[_model.name];
860 /* once created, the window is managed by the surface itself (as ->get_parent())
861 * Surface's tear_down_gui() is called on session close, when de-activating
862 * or re-initializing a surface.
863 * tear_down_gui() hides an deletes the Window if it exists.
865 ArdourWindow* win = new ArdourWindow (_parent, title);
866 win->set_title ("Control Protocol Options");
872 class ControlSurfacesModelColumns : public TreeModelColumnRecord
876 ControlSurfacesModelColumns ()
884 TreeModelColumn<string> name;
885 TreeModelColumn<bool> enabled;
886 TreeModelColumn<bool> feedback;
887 TreeModelColumn<ControlProtocolInfo*> protocol_info;
890 Glib::RefPtr<ListStore> _store;
891 ControlSurfacesModelColumns _model;
893 Gtk::Window& _parent;
894 PBD::ScopedConnection protocol_status_connection;
895 uint32_t _ignore_view_change;
898 class VideoTimelineOptions : public OptionEditorBox
901 VideoTimelineOptions (RCConfiguration* c)
903 , _show_video_export_info_button (_("Show Video Export Info before export"))
904 , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
905 , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
907 Table* t = manage (new Table (2, 6));
910 t->attach (_video_advanced_setup_button, 0, 2, 0, 1);
911 _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
912 Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
913 _("<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."));
915 Label* l = manage (new Label (_("Video Server URL:")));
916 l->set_alignment (0, 0.5);
917 t->attach (*l, 0, 1, 1, 2, FILL);
918 t->attach (_video_server_url_entry, 1, 2, 1, 2, FILL);
919 Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
920 _("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"));
922 l = manage (new Label (_("Video Folder:")));
923 l->set_alignment (0, 0.5);
924 t->attach (*l, 0, 1, 2, 3, FILL);
925 t->attach (_video_server_docroot_entry, 1, 2, 2, 3);
926 Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
927 _("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."));
929 /* small vspace y=3..4 */
931 t->attach (_show_video_export_info_button, 0, 2, 4, 5);
932 _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
933 Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
934 _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
936 t->attach (_show_video_server_dialog_button, 0, 2, 5, 6);
937 _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
938 Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
939 _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
941 _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
942 _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
943 _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
944 _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
946 _box->pack_start (*t,true,true);
949 void server_url_changed ()
951 _rc_config->set_video_server_url (_video_server_url_entry.get_text());
954 void server_docroot_changed ()
956 _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
959 void show_video_export_info_toggled ()
961 bool const x = _show_video_export_info_button.get_active ();
962 _rc_config->set_show_video_export_info (x);
965 void show_video_server_dialog_toggled ()
967 bool const x = _show_video_server_dialog_button.get_active ();
968 _rc_config->set_show_video_server_dialog (x);
971 void video_advanced_setup_toggled ()
973 bool const x = _video_advanced_setup_button.get_active ();
974 _rc_config->set_video_advanced_setup(x);
977 void parameter_changed (string const & p)
979 if (p == "video-server-url") {
980 _video_server_url_entry.set_text (_rc_config->get_video_server_url());
981 } else if (p == "video-server-docroot") {
982 _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
983 } else if (p == "show-video-export-info") {
984 bool const x = _rc_config->get_show_video_export_info();
985 _show_video_export_info_button.set_active (x);
986 } else if (p == "show-video-server-dialog") {
987 bool const x = _rc_config->get_show_video_server_dialog();
988 _show_video_server_dialog_button.set_active (x);
989 } else if (p == "video-advanced-setup") {
990 bool const x = _rc_config->get_video_advanced_setup();
991 _video_advanced_setup_button.set_active(x);
992 _video_server_docroot_entry.set_sensitive(x);
993 _video_server_url_entry.set_sensitive(x);
997 void set_state_from_config ()
999 parameter_changed ("video-server-url");
1000 parameter_changed ("video-server-docroot");
1001 parameter_changed ("video-monitor-setup-dialog");
1002 parameter_changed ("show-video-export-info");
1003 parameter_changed ("show-video-server-dialog");
1004 parameter_changed ("video-advanced-setup");
1008 RCConfiguration* _rc_config;
1009 Entry _video_server_url_entry;
1010 Entry _video_server_docroot_entry;
1011 CheckButton _show_video_export_info_button;
1012 CheckButton _show_video_server_dialog_button;
1013 CheckButton _video_advanced_setup_button;
1016 class PluginOptions : public OptionEditorBox
1019 PluginOptions (RCConfiguration* c, UIConfiguration* uic)
1022 , _display_plugin_scan_progress (_("Always Display Plugin Scan Progress"))
1023 , _discover_vst_on_start (_("Scan for [new] VST Plugins on Application Start"))
1024 , _discover_au_on_start (_("Scan for AudioUnit Plugins on Application Start"))
1025 , _timeout_adjustment (0, 0, 3000, 50, 50)
1026 , _timeout_slider (_timeout_adjustment)
1029 std::stringstream ss;
1030 Table* t = manage (new Table (2, 6));
1031 t->set_spacings (4);
1035 ss << "<b>" << _("General") << "</b>";
1036 l = manage (left_aligned_label (ss.str()));
1037 l->set_use_markup (true);
1038 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1039 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1041 b = manage (new Button (_("Scan for Plugins")));
1042 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::refresh_clicked));
1043 t->attach (*b, 0, 2, n, n+1, FILL); ++n;
1045 t->attach (_display_plugin_scan_progress, 0, 2, n, n+1); ++n;
1046 _display_plugin_scan_progress.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::display_plugin_scan_progress_toggled));
1047 Gtkmm2ext::UI::instance()->set_tip (_display_plugin_scan_progress,
1048 _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
1050 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
1051 _timeout_slider.set_digits (0);
1052 _timeout_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &PluginOptions::timeout_changed));
1054 Gtkmm2ext::UI::instance()->set_tip(_timeout_slider,
1055 _("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."));
1057 l = manage (left_aligned_label (_("Scan Time Out [deciseconds]")));;
1058 HBox* h = manage (new HBox);
1060 h->pack_start (*l, false, false);
1061 h->pack_start (_timeout_slider, true, true);
1062 t->attach (*h, 0, 2, n, n+1); ++n;
1065 ss << "<b>" << _("VST") << "</b>";
1066 l = manage (left_aligned_label (ss.str()));
1067 l->set_use_markup (true);
1068 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1069 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1071 b = manage (new Button (_("Clear VST Cache")));
1072 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_cache_clicked));
1073 t->attach (*b, 0, 1, n, n+1, FILL);
1075 b = manage (new Button (_("Clear VST Blacklist")));
1076 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_blacklist_clicked));
1077 t->attach (*b, 1, 2, n, n+1, FILL);
1080 t->attach (_discover_vst_on_start, 0, 2, n, n+1); ++n;
1081 _discover_vst_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_vst_on_start_toggled));
1082 Gtkmm2ext::UI::instance()->set_tip (_discover_vst_on_start,
1083 _("<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"));
1085 #ifdef LXVST_SUPPORT
1086 t->attach (*manage (left_aligned_label (_("Linux VST Path:"))), 0, 1, n, n+1);
1087 b = manage (new Button (_("Edit")));
1088 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_lxvst_path_clicked));
1089 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1092 #ifdef WINDOWS_VST_SUPPORT
1093 t->attach (*manage (left_aligned_label (_("Windows VST Path:"))), 0, 1, n, n+1);
1094 b = manage (new Button (_("Edit")));
1095 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_vst_path_clicked));
1096 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1100 #ifdef AUDIOUNIT_SUPPORT
1102 ss << "<b>" << _("Audio Unit") << "</b>";
1103 l = manage (left_aligned_label (ss.str()));
1104 l->set_use_markup (true);
1105 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1106 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1108 t->attach (_discover_au_on_start, 0, 2, n, n+1); ++n;
1109 _discover_au_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_au_on_start_toggled));
1110 Gtkmm2ext::UI::instance()->set_tip (_discover_au_on_start,
1111 _("<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."));
1114 b = manage (new Button (_("Clear AU Cache")));
1115 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_cache_clicked));
1116 t->attach (*b, 0, 1, n, n+1, FILL);
1118 b = manage (new Button (_("Clear AU Blacklist")));
1119 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_blacklist_clicked));
1120 t->attach (*b, 1, 2, n, n+1, FILL);
1124 _box->pack_start (*t,true,true);
1127 void parameter_changed (string const & p) {
1128 if (p == "show-plugin-scan-window") {
1129 bool const x = _ui_config->get_show_plugin_scan_window();
1130 _display_plugin_scan_progress.set_active (x);
1132 else if (p == "discover-vst-on-start") {
1133 bool const x = _rc_config->get_discover_vst_on_start();
1134 _discover_vst_on_start.set_active (x);
1136 else if (p == "vst-scan-timeout") {
1137 int const x = _rc_config->get_vst_scan_timeout();
1138 _timeout_adjustment.set_value (x);
1140 else if (p == "discover-audio-units") {
1141 bool const x = _rc_config->get_discover_audio_units();
1142 _discover_au_on_start.set_active (x);
1146 void set_state_from_config () {
1147 parameter_changed ("show-plugin-scan-window");
1148 parameter_changed ("discover-vst-on-start");
1149 parameter_changed ("vst-scan-timeout");
1150 parameter_changed ("discover-audio-units");
1154 RCConfiguration* _rc_config;
1155 UIConfiguration* _ui_config;
1156 CheckButton _display_plugin_scan_progress;
1157 CheckButton _discover_vst_on_start;
1158 CheckButton _discover_au_on_start;
1159 Adjustment _timeout_adjustment;
1160 HScale _timeout_slider;
1162 void display_plugin_scan_progress_toggled () {
1163 bool const x = _display_plugin_scan_progress.get_active();
1164 _ui_config->set_show_plugin_scan_window(x);
1167 void discover_vst_on_start_toggled () {
1168 bool const x = _discover_vst_on_start.get_active();
1169 _rc_config->set_discover_vst_on_start(x);
1172 void discover_au_on_start_toggled () {
1173 bool const x = _discover_au_on_start.get_active();
1174 _rc_config->set_discover_audio_units(x);
1177 void timeout_changed () {
1178 int x = floor(_timeout_adjustment.get_value());
1179 _rc_config->set_vst_scan_timeout(x);
1182 void clear_vst_cache_clicked () {
1183 PluginManager::instance().clear_vst_cache();
1186 void clear_vst_blacklist_clicked () {
1187 PluginManager::instance().clear_vst_blacklist();
1190 void clear_au_cache_clicked () {
1191 PluginManager::instance().clear_au_cache();
1194 void clear_au_blacklist_clicked () {
1195 PluginManager::instance().clear_au_blacklist();
1199 void edit_vst_path_clicked () {
1200 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1201 _("Set Windows VST Search Path"),
1202 _rc_config->get_plugin_path_vst(),
1203 PluginManager::instance().get_default_windows_vst_path()
1205 ResponseType r = (ResponseType) pd->run ();
1207 if (r == RESPONSE_ACCEPT) {
1208 _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
1213 // todo consolidate with edit_vst_path_clicked..
1214 void edit_lxvst_path_clicked () {
1215 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1216 _("Set Linux VST Search Path"),
1217 _rc_config->get_plugin_path_lxvst(),
1218 PluginManager::instance().get_default_lxvst_path()
1220 ResponseType r = (ResponseType) pd->run ();
1222 if (r == RESPONSE_ACCEPT) {
1223 _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
1228 void refresh_clicked () {
1229 PluginManager::instance().refresh();
1234 /** A class which allows control of visibility of some editor components usign
1235 * a VisibilityGroup. The caller should pass in a `dummy' VisibilityGroup
1236 * which has the correct members, but with null widget pointers. This
1237 * class allows the user to set visibility of the members, the details
1238 * of which are stored in a configuration variable which can be watched
1239 * by parts of the editor that actually contain the widgets whose visibility
1240 * is being controlled.
1243 class VisibilityOption : public Option
1246 /** @param name User-visible name for this group.
1247 * @param g `Dummy' VisibilityGroup (as described above).
1248 * @param get Method to get the value of the appropriate configuration variable.
1249 * @param set Method to set the value of the appropriate configuration variable.
1251 VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1252 : Option (g->get_state_name(), name)
1254 , _visibility_group (g)
1258 /* Watch for changes made by the user to our members */
1259 _visibility_group->VisibilityChanged.connect_same_thread (
1260 _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1264 void set_state_from_config ()
1266 /* Set our state from the current configuration */
1267 _visibility_group->set_state (_get ());
1270 void add_to_page (OptionEditorPage* p)
1272 _heading.add_to_page (p);
1273 add_widget_to_page (p, _visibility_group->list_view ());
1276 Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1281 /* The user has changed something, so reflect this change
1282 in the RCConfiguration.
1284 _set (_visibility_group->get_state_value ());
1287 OptionEditorHeading _heading;
1288 VisibilityGroup* _visibility_group;
1289 sigc::slot<std::string> _get;
1290 sigc::slot<bool, std::string> _set;
1291 PBD::ScopedConnection _visibility_group_connection;
1296 RCOptionEditor::RCOptionEditor ()
1297 : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
1298 , _rc_config (Config)
1299 , _ui_config (ARDOUR_UI::config())
1300 , _mixer_strip_visibility ("mixer-element-visibility")
1304 uint32_t hwcpus = hardware_concurrency ();
1306 BoolComboOption* bco;
1309 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
1311 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
1313 _("Signal processing uses"),
1314 sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
1315 sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
1318 procs->add (-1, _("all but one processor"));
1319 procs->add (0, _("all available processors"));
1321 for (uint32_t i = 1; i <= hwcpus; ++i) {
1322 procs->add (i, string_compose (_("%1 processors"), i));
1325 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
1327 add_option (_("Misc"), procs);
1330 add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
1332 add_option (_("Misc"), new UndoOptions (_rc_config));
1334 add_option (_("Misc"),
1336 "verify-remove-last-capture",
1337 _("Verify removal of last capture"),
1338 sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
1339 sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
1342 add_option (_("Misc"),
1344 "periodic-safety-backups",
1345 _("Make periodic backups of the session file"),
1346 sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1347 sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1350 add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
1352 add_option (_("Misc"),
1354 "only-copy-imported-files",
1355 _("Always copy imported files"),
1356 sigc::mem_fun (*_ui_config, &UIConfiguration::get_only_copy_imported_files),
1357 sigc::mem_fun (*_ui_config, &UIConfiguration::set_only_copy_imported_files)
1360 add_option (_("Misc"), new DirectoryOption (
1361 X_("default-session-parent-dir"),
1362 _("Default folder for new sessions:"),
1363 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
1364 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
1367 add_option (_("Misc"),
1368 new SpinOption<uint32_t> (
1369 "max-recent-sessions",
1370 _("Maximum number of recent sessions"),
1371 sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
1372 sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
1376 add_option (_("Misc"), new OptionEditorHeading (_("Click")));
1378 add_option (_("Misc"), new ClickOptions (_rc_config, this));
1380 add_option (_("Misc"),
1383 _("Click gain level"),
1384 sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
1385 sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
1388 add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
1390 add_option (_("Misc"),
1391 new SpinOption<double> (
1392 "automation-thinning-factor",
1393 _("Thinning factor (larger value => less data)"),
1394 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
1395 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
1399 add_option (_("Misc"),
1400 new SpinOption<double> (
1401 "automation-interval-msecs",
1402 _("Automation sampling interval (milliseconds)"),
1403 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
1404 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
1412 tsf = new BoolOption (
1413 "latched-record-enable",
1414 _("Keep record-enable engaged on stop"),
1415 sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
1416 sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
1418 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1419 add_option (_("Transport"), tsf);
1421 tsf = new BoolOption (
1423 _("Play loop is a transport mode"),
1424 sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
1425 sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
1427 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1428 (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
1429 "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
1430 add_option (_("Transport"), tsf);
1432 tsf = new BoolOption (
1433 "stop-recording-on-xrun",
1434 _("Stop recording when an xrun occurs"),
1435 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1436 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1438 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1439 string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
1441 add_option (_("Transport"), tsf);
1443 tsf = new BoolOption (
1444 "create-xrun-marker",
1445 _("Create markers where xruns occur"),
1446 sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1447 sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1449 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1450 add_option (_("Transport"), tsf);
1452 tsf = new BoolOption (
1453 "stop-at-session-end",
1454 _("Stop at the end of the session"),
1455 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1456 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1458 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1459 string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1460 "when it reaches the current session end marker\n\n"
1461 "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1463 add_option (_("Transport"), tsf);
1465 tsf = new BoolOption (
1467 _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1468 sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1469 sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1471 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1472 string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1473 "preventing any need to do a transport locate at the end of the loop\n\n"
1474 "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
1475 "which will often cause a small click or delay"), PROGRAM_NAME));
1476 add_option (_("Transport"), tsf);
1478 tsf = new BoolOption (
1479 "disable-disarm-during-roll",
1480 _("Disable per-track record disarm while rolling"),
1481 sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1482 sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1484 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"));
1485 add_option (_("Transport"), tsf);
1487 tsf = new BoolOption (
1489 _("12dB gain reduction during fast-forward and fast-rewind"),
1490 sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1491 sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1493 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1494 "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1495 add_option (_("Transport"), tsf);
1497 add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1499 _sync_source = new ComboOption<SyncSource> (
1501 _("External timecode source"),
1502 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1503 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1506 add_option (_("Transport"), _sync_source);
1508 _sync_framerate = new BoolOption (
1509 "timecode-sync-frame-rate",
1510 _("Match session video frame rate to external timecode"),
1511 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1512 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1514 Gtkmm2ext::UI::instance()->set_tip
1515 (_sync_framerate->tip_widget(),
1516 string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1517 "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1518 "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1519 "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
1520 "timecode standard and the session standard."), PROGRAM_NAME));
1522 add_option (_("Transport"), _sync_framerate);
1524 _sync_genlock = new BoolOption (
1525 "timecode-source-is-synced",
1526 _("Sync lock timecode to clock - Disable drift compensation."),
1527 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1528 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1530 Gtkmm2ext::UI::instance()->set_tip
1531 (_sync_genlock->tip_widget(),
1532 string_compose (_("<b>When enabled</b> %1 will never varispeed when slaved to external timecode. "
1533 "Sync Lock indicates that the selected external timecode source shares clock-sync "
1534 "(Black & Burst, Wordclock, etc) with the audio interface. "
1535 "This option disables drift compensation. The transport speed is fixed at 1.0."
1536 "Varispeed LTC will be ignored and cause drift."
1538 "<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
1539 "timecode sources shares clock sync."
1543 add_option (_("Transport"), _sync_genlock);
1545 _sync_source_2997 = new BoolOption (
1546 "timecode-source-2997",
1547 _("Lock to 29.9700 fps instead of 30000/1001"),
1548 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1549 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1551 Gtkmm2ext::UI::instance()->set_tip
1552 (_sync_source_2997->tip_widget(),
1553 _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1554 "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1555 "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1556 "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1557 "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1558 "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1561 add_option (_("Transport"), _sync_source_2997);
1563 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1565 _ltc_port = new ComboStringOption (
1567 _("LTC incoming port"),
1568 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1569 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1572 vector<string> physical_inputs;
1573 physical_inputs.push_back (_("None"));
1574 AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1575 _ltc_port->set_popdown_strings (physical_inputs);
1577 populate_sync_options ();
1579 add_option (_("Transport"), _ltc_port);
1581 // TODO; rather disable this button than not compile it..
1582 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1584 add_option (_("Transport"),
1587 _("Enable LTC generator"),
1588 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1589 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1592 _ltc_send_continuously = new BoolOption (
1593 "ltc-send-continuously",
1594 _("Send LTC while stopped"),
1595 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1596 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1598 Gtkmm2ext::UI::instance()->set_tip
1599 (_ltc_send_continuously->tip_widget(),
1600 string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
1601 add_option (_("Transport"), _ltc_send_continuously);
1603 _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1604 _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1605 _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1606 _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1608 Gtkmm2ext::UI::instance()->set_tip
1609 (_ltc_volume_slider->tip_widget(),
1610 _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is 0dBu ^= -18dbFS in an EBU calibrated system"));
1612 add_option (_("Transport"), _ltc_volume_slider);
1613 parameter_changed ("send-ltc");
1615 parameter_changed ("sync-source");
1619 add_option (S_("Editor"),
1621 "draggable-playhead",
1622 _("Allow dragging of playhead"),
1623 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_draggable_playhead),
1624 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_draggable_playhead)
1627 add_option (_("Editor"),
1629 "automation-follows-regions",
1630 _("Move relevant automation when audio regions are moved"),
1631 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1632 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1635 add_option (_("Editor"),
1637 "show-track-meters",
1638 _("Show meters on tracks in the editor"),
1639 sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_track_meters),
1640 sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_track_meters)
1643 add_option (_("Editor"),
1645 "show-editor-meter",
1646 _("Display master-meter in the toolbar"),
1647 sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_editor_meter),
1648 sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_editor_meter)
1651 ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
1652 "default-fade-shape",
1653 _("Default fade shape"),
1654 sigc::mem_fun (*_rc_config,
1655 &RCConfiguration::get_default_fade_shape),
1656 sigc::mem_fun (*_rc_config,
1657 &RCConfiguration::set_default_fade_shape)
1660 fadeshape->add (FadeLinear,
1661 _("Linear (for highly correlated material)"));
1662 fadeshape->add (FadeConstantPower, _("Constant power"));
1663 fadeshape->add (FadeSymmetric, _("Symmetric"));
1664 fadeshape->add (FadeSlow, _("Slow"));
1665 fadeshape->add (FadeFast, _("Fast"));
1667 add_option (_("Editor"), fadeshape);
1670 bco = new BoolComboOption (
1671 "use-overlap-equivalency",
1672 _("Regions in active edit groups are edited together"),
1673 _("whenever they overlap in time"),
1674 _("only if they have identical length, position and origin"),
1675 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1676 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1679 add_option (_("Editor"), bco);
1681 add_option (_("Editor"),
1683 "rubberbanding-snaps-to-grid",
1684 _("Make rubberband selection rectangle snap to the grid"),
1685 sigc::mem_fun (*_ui_config, &UIConfiguration::get_rubberbanding_snaps_to_grid),
1686 sigc::mem_fun (*_ui_config, &UIConfiguration::set_rubberbanding_snaps_to_grid)
1689 add_option (_("Editor"),
1692 _("Show waveforms in regions"),
1693 sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms),
1694 sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms)
1697 add_option (_("Editor"),
1698 new BoolComboOption (
1699 "show-region-gain-envelopes",
1700 _("Show gain envelopes in audio regions"),
1702 _("only in region gain mode"),
1703 sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_region_gain),
1704 sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_region_gain)
1707 ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1709 _("Waveform scale"),
1710 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_scale),
1711 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_scale)
1714 wfs->add (Linear, _("linear"));
1715 wfs->add (Logarithmic, _("logarithmic"));
1717 add_option (_("Editor"), wfs);
1719 ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1721 _("Waveform shape"),
1722 sigc::mem_fun (*_ui_config, &UIConfiguration::get_waveform_shape),
1723 sigc::mem_fun (*_ui_config, &UIConfiguration::set_waveform_shape)
1726 wfsh->add (Traditional, _("traditional"));
1727 wfsh->add (Rectified, _("rectified"));
1729 add_option (_("Editor"), wfsh);
1731 add_option (_("Editor"), new ClipLevelOptions (_ui_config));
1733 add_option (_("Editor"),
1735 "show-waveforms-while-recording",
1736 _("Show waveforms for audio while it is being recorded"),
1737 sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_waveforms_while_recording),
1738 sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_waveforms_while_recording)
1741 add_option (_("Editor"),
1744 _("Show zoom toolbar"),
1745 sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_zoom_tools),
1746 sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_zoom_tools)
1749 add_option (_("Editor"),
1751 "update-editor-during-summary-drag",
1752 _("Update editor window during drags of the summary"),
1753 sigc::mem_fun (*_ui_config, &UIConfiguration::get_update_editor_during_summary_drag),
1754 sigc::mem_fun (*_ui_config, &UIConfiguration::set_update_editor_during_summary_drag)
1757 add_option (_("Editor"),
1759 "link-editor-and-mixer-selection",
1760 _("Synchronise editor and mixer selection"),
1761 sigc::mem_fun (*_ui_config, &UIConfiguration::get_link_editor_and_mixer_selection),
1762 sigc::mem_fun (*_ui_config, &UIConfiguration::set_link_editor_and_mixer_selection)
1765 bo = new BoolOption (
1767 _("Name new markers"),
1768 sigc::mem_fun (*_ui_config, &UIConfiguration::get_name_new_markers),
1769 sigc::mem_fun (*_ui_config, &UIConfiguration::set_name_new_markers)
1772 add_option (_("Editor"), bo);
1773 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."
1774 "\n\nYou can always rename markers by right-clicking on them"));
1776 add_option (_("Editor"),
1778 "autoscroll-editor",
1779 _("Auto-scroll editor window when dragging near its edges"),
1780 sigc::mem_fun (*_ui_config, &UIConfiguration::get_autoscroll_editor),
1781 sigc::mem_fun (*_ui_config, &UIConfiguration::set_autoscroll_editor)
1784 ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
1785 "region-selection-after-split",
1786 _("After splitting selected regions, select"),
1787 sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
1788 sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
1790 // TODO: decide which of these modes are really useful
1791 rsas->add(None, _("no regions"));
1792 // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
1793 // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
1794 rsas->add(NewlyCreatedBoth, _("newly-created regions"));
1795 // rsas->add(Existing, _("unmodified regions in the existing selection"));
1796 // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
1797 // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
1798 rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
1800 add_option (_("Editor"), rsas);
1805 add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1807 add_option (_("Audio"), new BufferingOptions (_rc_config));
1809 add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1811 ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1813 _("Record monitoring handled by"),
1814 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1815 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1818 if (AudioEngine::instance()->port_engine().can_monitor_input()) {
1819 mm->add (HardwareMonitoring, _("via Audio Driver"));
1822 string prog (PROGRAM_NAME);
1823 boost::algorithm::to_lower (prog);
1824 mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
1825 mm->add (ExternalMonitoring, _("audio hardware"));
1827 add_option (_("Audio"), mm);
1829 add_option (_("Audio"),
1831 "tape-machine-mode",
1832 _("Tape machine mode"),
1833 sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1834 sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1837 add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1839 add_option (_("Audio"),
1841 "auto-connect-standard-busses",
1842 _("Auto-connect master/monitor busses"),
1843 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1844 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1847 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1848 "input-auto-connect",
1849 _("Connect track inputs"),
1850 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1851 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1854 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1855 iac->add (ManualConnect, _("manually"));
1857 add_option (_("Audio"), iac);
1859 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1860 "output-auto-connect",
1861 _("Connect track and bus outputs"),
1862 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1863 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1866 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1867 oac->add (AutoConnectMaster, _("automatically to master bus"));
1868 oac->add (ManualConnect, _("manually"));
1870 add_option (_("Audio"), oac);
1872 add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1874 add_option (_("Audio"),
1876 "denormal-protection",
1877 _("Use DC bias to protect against denormals"),
1878 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1879 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1882 ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1884 _("Processor handling"),
1885 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1886 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1890 dm->add (DenormalNone, _("no processor handling"));
1894 if (fpu.has_flush_to_zero()) {
1896 dm->add (DenormalFTZ, _("use FlushToZero"));
1897 } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
1898 _rc_config->set_denormal_model(DenormalNone);
1901 if (fpu.has_denormals_are_zero()) {
1903 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1904 } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
1905 _rc_config->set_denormal_model(DenormalNone);
1908 if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1910 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1911 } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
1912 _rc_config->set_denormal_model(DenormalNone);
1916 dm->set_sensitive(false);
1919 add_option (_("Audio"), dm);
1921 add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1923 add_option (_("Audio"),
1925 "plugins-stop-with-transport",
1926 _("Silence plugins when the transport is stopped"),
1927 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1928 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1931 add_option (_("Audio"),
1933 "new-plugins-active",
1934 _("Make new plugins active"),
1935 sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1936 sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1939 add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
1941 add_option (_("Audio"),
1943 "auto-analyse-audio",
1944 _("Enable automatic analysis of audio"),
1945 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1946 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1949 add_option (_("Audio"),
1951 "replicate-missing-region-channels",
1952 _("Replicate missing region channels"),
1953 sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1954 sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1959 add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
1961 add_option (_("Solo / mute"),
1964 _("Solo-in-place mute cut (dB)"),
1965 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1966 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1969 _solo_control_is_listen_control = new BoolOption (
1970 "solo-control-is-listen-control",
1971 _("Solo controls are Listen controls"),
1972 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1973 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1976 add_option (_("Solo / mute"), _solo_control_is_listen_control);
1978 _listen_position = new ComboOption<ListenPosition> (
1980 _("Listen Position"),
1981 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1982 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1985 _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1986 _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1988 add_option (_("Solo / mute"), _listen_position);
1990 ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1992 _("PFL signals come from"),
1993 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1994 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1997 pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1998 pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2000 add_option (_("Solo / mute"), pp);
2002 ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2004 _("AFL signals come from"),
2005 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2006 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2009 pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2010 pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2012 add_option (_("Solo / mute"), pa);
2014 parameter_changed ("use-monitor-bus");
2016 add_option (_("Solo / mute"),
2019 _("Exclusive solo"),
2020 sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2021 sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2024 add_option (_("Solo / mute"),
2027 _("Show solo muting"),
2028 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2029 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2032 add_option (_("Solo / mute"),
2034 "solo-mute-override",
2035 _("Soloing overrides muting"),
2036 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2037 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2040 add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
2042 add_option (_("Solo / mute"),
2044 "mute-affects-pre-fader",
2045 _("Mute affects pre-fader sends"),
2046 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2047 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2050 add_option (_("Solo / mute"),
2052 "mute-affects-post-fader",
2053 _("Mute affects post-fader sends"),
2054 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2055 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2058 add_option (_("Solo / mute"),
2060 "mute-affects-control-outs",
2061 _("Mute affects control outputs"),
2062 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2063 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2066 add_option (_("Solo / mute"),
2068 "mute-affects-main-outs",
2069 _("Mute affects main outputs"),
2070 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2071 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2074 add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
2076 add_option (_("Solo / mute"),
2078 "link-send-and-route-panner",
2079 _("Link panners of Aux and External Sends with main panner by default"),
2080 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2081 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2084 add_option (_("MIDI"),
2085 new SpinOption<float> (
2087 _("MIDI read-ahead time (seconds)"),
2088 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2089 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2094 add_option (_("MIDI"),
2097 _("Send MIDI Clock"),
2098 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2099 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2102 add_option (_("MIDI"),
2105 _("Send MIDI Time Code"),
2106 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2107 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2110 add_option (_("MIDI"),
2111 new SpinOption<int> (
2112 "mtc-qf-speed-tolerance",
2113 _("Percentage either side of normal transport speed to transmit MTC"),
2114 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2115 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2119 add_option (_("MIDI"),
2122 _("Obey MIDI Machine Control commands"),
2123 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2124 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2127 add_option (_("MIDI"),
2130 _("Send MIDI Machine Control commands"),
2131 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2132 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2135 add_option (_("MIDI"),
2138 _("Send MIDI control feedback"),
2139 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2140 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2143 add_option (_("MIDI"),
2144 new SpinOption<uint8_t> (
2145 "mmc-receive-device-id",
2146 _("Inbound MMC device ID"),
2147 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2148 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2152 add_option (_("MIDI"),
2153 new SpinOption<uint8_t> (
2154 "mmc-send-device-id",
2155 _("Outbound MMC device ID"),
2156 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2157 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2161 add_option (_("MIDI"),
2162 new SpinOption<int32_t> (
2163 "initial-program-change",
2164 _("Initial program change"),
2165 sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2166 sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2170 add_option (_("MIDI"),
2172 "display-first-midi-bank-as-zero",
2173 _("Display first MIDI bank/program as 0"),
2174 sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2175 sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2178 add_option (_("MIDI"),
2180 "never-display-periodic-midi",
2181 _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2182 sigc::mem_fun (*_ui_config, &UIConfiguration::get_never_display_periodic_midi),
2183 sigc::mem_fun (*_ui_config, &UIConfiguration::set_never_display_periodic_midi)
2186 add_option (_("MIDI"),
2189 _("Sound MIDI notes as they are selected"),
2190 sigc::mem_fun (*_ui_config, &UIConfiguration::get_sound_midi_notes),
2191 sigc::mem_fun (*_ui_config, &UIConfiguration::set_sound_midi_notes)
2194 add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2196 ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2197 "midi-audition-synth-uri",
2198 _("Midi Audition Synth (LV2)"),
2199 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2200 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2203 audition_synth->add(X_(""), _("None"));
2204 PluginInfoList all_plugs;
2205 PluginManager& manager (PluginManager::instance());
2207 all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2209 for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2210 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2211 if (!(*i)->is_instrument()) continue;
2212 if ((*i)->type != ARDOUR::LV2) continue;
2213 audition_synth->add((*i)->unique_id, (*i)->name);
2217 add_option (_("MIDI"), audition_synth);
2219 /* USER INTERACTION */
2222 #ifdef PLATFORM_WINDOWS
2225 getenv ("ARDOUR_BUNDLED")
2229 add_option (_("User interaction"),
2231 "enable-translation",
2232 string_compose (_("Use translations of %1 messages\n"
2233 " <i>(requires a restart of %1 to take effect)</i>\n"
2234 " <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2235 sigc::ptr_fun (ARDOUR::translations_are_enabled),
2236 sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2239 add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2241 add_option (_("User interaction"), new KeyboardOptions);
2243 /* Control Surfaces */
2245 add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2247 ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2249 _("Control surface remote ID"),
2250 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2251 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2254 rm->add (UserOrdered, _("assigned by user"));
2255 rm->add (MixerOrdered, _("follows order of mixer"));
2257 add_option (_("Control Surfaces"), rm);
2259 /* VIDEO Timeline */
2260 add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2262 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2263 /* Plugin options (currrently VST only) */
2264 add_option (_("Plugins"), new PluginOptions (_rc_config, _ui_config));
2269 add_option (S_("Preferences|GUI"),
2272 _("Graphically indicate mouse pointer hovering over various widgets"),
2273 sigc::mem_fun (*_ui_config, &UIConfiguration::get_widget_prelight),
2274 sigc::mem_fun (*_ui_config, &UIConfiguration::set_widget_prelight)
2277 #ifdef TOOLTIPS_GOT_FIXED
2278 add_option (S_("Preferences|GUI"),
2281 _("Show tooltips if mouse hovers over a control"),
2282 sigc::mem_fun (*_ui_config, &UIConfiguration::get_use_tooltips),
2283 sigc::mem_fun (*_ui_config, &UIConfiguration::set_use_tooltips)
2287 add_option (S_("Preferences|GUI"),
2289 "show-name-highlight",
2290 _("Use name highlight bars in region displays (requires a restart)"),
2291 sigc::mem_fun (*_ui_config, &UIConfiguration::get_show_name_highlight),
2292 sigc::mem_fun (*_ui_config, &UIConfiguration::set_show_name_highlight)
2296 /* font scaling does nothing with GDK/Quartz */
2297 add_option (S_("Preferences|GUI"), new FontScalingOptions (_ui_config));
2300 add_option (S_("GUI"),
2302 "super-rapid-clock-update",
2303 _("update transport clock display at FPS instead of every 100ms"),
2304 sigc::mem_fun (*_ui_config, &UIConfiguration::get_super_rapid_clock_update),
2305 sigc::mem_fun (*_ui_config, &UIConfiguration::set_super_rapid_clock_update)
2308 /* Lock GUI timeout */
2310 Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2311 HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2312 _("Lock timeout (seconds)"),
2314 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::get_lock_gui_after_seconds),
2315 sigc::mem_fun (*ARDOUR_UI::config(), &UIConfiguration::set_lock_gui_after_seconds)
2317 slts->scale().set_digits (0);
2318 Gtkmm2ext::UI::instance()->set_tip
2319 (slts->tip_widget(),
2320 _("Lock GUI after this many idle seconds (zero to never lock)"));
2321 add_option (S_("Preferences|GUI"), slts);
2323 /* The names of these controls must be the same as those given in MixerStrip
2324 for the actual widgets being controlled.
2326 _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2327 _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2328 _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2329 _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2330 _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2331 _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2334 S_("Preferences|GUI"),
2335 new VisibilityOption (
2337 &_mixer_strip_visibility,
2338 sigc::mem_fun (*_ui_config, &UIConfiguration::get_mixer_strip_visibility),
2339 sigc::mem_fun (*_ui_config, &UIConfiguration::set_mixer_strip_visibility)
2343 add_option (S_("Preferences|GUI"),
2345 "default-narrow_ms",
2346 _("Use narrow strips in the mixer by default"),
2347 sigc::mem_fun (*_ui_config, &UIConfiguration::get_default_narrow_ms),
2348 sigc::mem_fun (*_ui_config, &UIConfiguration::set_default_narrow_ms)
2351 add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2353 ComboOption<float>* mht = new ComboOption<float> (
2355 _("Peak hold time"),
2356 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_hold),
2357 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_hold)
2360 mht->add (MeterHoldOff, _("off"));
2361 mht->add (MeterHoldShort, _("short"));
2362 mht->add (MeterHoldMedium, _("medium"));
2363 mht->add (MeterHoldLong, _("long"));
2365 add_option (S_("Preferences|Metering"), mht);
2367 ComboOption<float>* mfo = new ComboOption<float> (
2370 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2371 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2374 mfo->add (METER_FALLOFF_OFF, _("off"));
2375 mfo->add (METER_FALLOFF_SLOWEST, _("slowest [6.6dB/sec]"));
2376 mfo->add (METER_FALLOFF_SLOW, _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2377 mfo->add (METER_FALLOFF_SLOWISH, _("slowish [12.0dB/sec] (DIN)"));
2378 mfo->add (METER_FALLOFF_MODERATE, _("moderate [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2379 mfo->add (METER_FALLOFF_MEDIUM, _("medium [20dB/sec]"));
2380 mfo->add (METER_FALLOFF_FAST, _("fast [32dB/sec]"));
2381 mfo->add (METER_FALLOFF_FASTER, _("faster [46dB/sec]"));
2382 mfo->add (METER_FALLOFF_FASTEST, _("fastest [70dB/sec]"));
2384 add_option (S_("Preferences|Metering"), mfo);
2386 ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2387 "meter-line-up-level",
2388 _("Meter line-up level; 0dBu"),
2389 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_level),
2390 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_level)
2393 mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2394 mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2395 mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2396 mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2398 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."));
2400 add_option (S_("Preferences|Metering"), mlu);
2402 ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2403 "meter-line-up-din",
2404 _("IEC1/DIN Meter line-up level; 0dBu"),
2405 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_line_up_din),
2406 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_line_up_din)
2409 mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2410 mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2411 mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2412 mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2414 Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2416 add_option (S_("Preferences|Metering"), mld);
2418 ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2419 "meter-vu-standard",
2420 _("VU Meter standard"),
2421 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_vu_standard),
2422 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_vu_standard)
2425 mvu->add (MeteringVUfrench, _("0VU = -2dBu (France)"));
2426 mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2427 mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2428 mvu->add (MeteringVUeight, _("0VU = +8dBu"));
2430 add_option (S_("Preferences|Metering"), mvu);
2432 Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
2433 HSliderOption *mpks = new HSliderOption("meter-peak",
2434 _("Peak threshold [dBFS]"),
2436 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_peak),
2437 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_peak)
2440 Gtkmm2ext::UI::instance()->set_tip
2441 (mpks->tip_widget(),
2442 _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
2444 add_option (S_("Preferences|Metering"), mpks);
2446 add_option (S_("Preferences|Metering"),
2449 _("LED meter style"),
2450 sigc::mem_fun (*_ui_config, &UIConfiguration::get_meter_style_led),
2451 sigc::mem_fun (*_ui_config, &UIConfiguration::set_meter_style_led)
2454 /* and now the theme manager */
2456 ThemeManager* tm = manage (new ThemeManager);
2457 add_page (_("Theme"), *tm);
2461 RCOptionEditor::parameter_changed (string const & p)
2463 OptionEditor::parameter_changed (p);
2465 if (p == "use-monitor-bus") {
2466 bool const s = Config->get_use_monitor_bus ();
2468 /* we can't use this if we don't have a monitor bus */
2469 Config->set_solo_control_is_listen_control (false);
2471 _solo_control_is_listen_control->set_sensitive (s);
2472 _listen_position->set_sensitive (s);
2473 } else if (p == "sync-source") {
2474 _sync_source->set_sensitive (true);
2476 _sync_source->set_sensitive (!_session->config.get_external_sync());
2478 switch(Config->get_sync_source()) {
2481 _sync_genlock->set_sensitive (true);
2482 _sync_framerate->set_sensitive (true);
2483 _sync_source_2997->set_sensitive (true);
2486 _sync_genlock->set_sensitive (false);
2487 _sync_framerate->set_sensitive (false);
2488 _sync_source_2997->set_sensitive (false);
2491 } else if (p == "send-ltc") {
2492 bool const s = Config->get_send_ltc ();
2493 _ltc_send_continuously->set_sensitive (s);
2494 _ltc_volume_slider->set_sensitive (s);
2498 void RCOptionEditor::ltc_generator_volume_changed () {
2499 _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
2503 RCOptionEditor::populate_sync_options ()
2505 vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
2507 _sync_source->clear ();
2509 for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
2510 _sync_source->add (*i, sync_source_to_string (*i));
2513 if (sync_opts.empty()) {
2514 _sync_source->set_sensitive(false);
2516 if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
2517 _rc_config->set_sync_source(sync_opts.front());