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 <gtkmm/liststore.h>
25 #include <gtkmm/stock.h>
26 #include <gtkmm/scale.h>
27 #include <gtkmm2ext/utils.h>
28 #include <gtkmm2ext/slider_controller.h>
29 #include <gtkmm2ext/gtk_ui.h>
34 #include "midi++/manager.h"
36 #include "ardour/audioengine.h"
37 #include "ardour/dB.h"
38 #include "ardour/rc_configuration.h"
39 #include "ardour/control_protocol_manager.h"
40 #include "control_protocol/control_protocol.h"
42 #include "ardour_window.h"
43 #include "ardour_dialog.h"
44 #include "gui_thread.h"
45 #include "midi_tracer.h"
46 #include "rc_option_editor.h"
48 #include "midi_port_dialog.h"
55 using namespace Gtkmm2ext;
57 using namespace ARDOUR;
59 class ClickOptions : public OptionEditorBox
62 ClickOptions (RCConfiguration* c, Gtk::Window* p)
66 Table* t = manage (new Table (2, 3));
69 Label* l = manage (left_aligned_label (_("Click audio file:")));
70 t->attach (*l, 0, 1, 0, 1, FILL);
71 t->attach (_click_path_entry, 1, 2, 0, 1, FILL);
72 Button* b = manage (new Button (_("Browse...")));
73 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
74 t->attach (*b, 2, 3, 0, 1, FILL);
76 l = manage (left_aligned_label (_("Click emphasis audio file:")));
77 t->attach (*l, 0, 1, 1, 2, FILL);
78 t->attach (_click_emphasis_path_entry, 1, 2, 1, 2, FILL);
79 b = manage (new Button (_("Browse...")));
80 b->signal_clicked().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
81 t->attach (*b, 2, 3, 1, 2, FILL);
83 _box->pack_start (*t, false, false);
85 _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));
86 _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
89 void parameter_changed (string const & p)
91 if (p == "click-sound") {
92 _click_path_entry.set_text (_rc_config->get_click_sound());
93 } else if (p == "click-emphasis-sound") {
94 _click_emphasis_path_entry.set_text (_rc_config->get_click_emphasis_sound());
98 void set_state_from_config ()
100 parameter_changed ("click-sound");
101 parameter_changed ("click-emphasis-sound");
106 void click_browse_clicked ()
108 SoundFileChooser sfdb (*_parent, _("Choose Click"));
113 if (sfdb.run () == RESPONSE_OK) {
114 click_chosen (sfdb.get_filename());
118 void click_chosen (string const & path)
120 _click_path_entry.set_text (path);
121 _rc_config->set_click_sound (path);
124 void click_changed ()
126 click_chosen (_click_path_entry.get_text ());
129 void click_emphasis_browse_clicked ()
131 SoundFileChooser sfdb (*_parent, _("Choose Click Emphasis"));
136 if (sfdb.run () == RESPONSE_OK) {
137 click_emphasis_chosen (sfdb.get_filename());
141 void click_emphasis_chosen (string const & path)
143 _click_emphasis_path_entry.set_text (path);
144 _rc_config->set_click_emphasis_sound (path);
147 void click_emphasis_changed ()
149 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
152 RCConfiguration* _rc_config;
153 Gtk::Window* _parent;
154 Entry _click_path_entry;
155 Entry _click_emphasis_path_entry;
158 class UndoOptions : public OptionEditorBox
161 UndoOptions (RCConfiguration* c) :
163 _limit_undo_button (_("Limit undo history to")),
164 _save_undo_button (_("Save undo history of"))
166 Table* t = new Table (2, 3);
169 t->attach (_limit_undo_button, 0, 1, 0, 1, FILL);
170 _limit_undo_spin.set_range (0, 512);
171 _limit_undo_spin.set_increments (1, 10);
172 t->attach (_limit_undo_spin, 1, 2, 0, 1, FILL | EXPAND);
173 Label* l = manage (left_aligned_label (_("commands")));
174 t->attach (*l, 2, 3, 0, 1);
176 t->attach (_save_undo_button, 0, 1, 1, 2, FILL);
177 _save_undo_spin.set_range (0, 512);
178 _save_undo_spin.set_increments (1, 10);
179 t->attach (_save_undo_spin, 1, 2, 1, 2, FILL | EXPAND);
180 l = manage (left_aligned_label (_("commands")));
181 t->attach (*l, 2, 3, 1, 2);
183 _box->pack_start (*t);
185 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
186 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
187 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
188 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
191 void parameter_changed (string const & p)
193 if (p == "history-depth") {
194 int32_t const d = _rc_config->get_history_depth();
195 _limit_undo_button.set_active (d != 0);
196 _limit_undo_spin.set_sensitive (d != 0);
197 _limit_undo_spin.set_value (d);
198 } else if (p == "save-history") {
199 bool const x = _rc_config->get_save_history ();
200 _save_undo_button.set_active (x);
201 _save_undo_spin.set_sensitive (x);
202 } else if (p == "save-history-depth") {
203 _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
207 void set_state_from_config ()
209 parameter_changed ("save-history");
210 parameter_changed ("history-depth");
211 parameter_changed ("save-history-depth");
214 void limit_undo_toggled ()
216 bool const x = _limit_undo_button.get_active ();
217 _limit_undo_spin.set_sensitive (x);
218 int32_t const n = x ? 16 : 0;
219 _limit_undo_spin.set_value (n);
220 _rc_config->set_history_depth (n);
223 void limit_undo_changed ()
225 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
228 void save_undo_toggled ()
230 bool const x = _save_undo_button.get_active ();
231 _rc_config->set_save_history (x);
234 void save_undo_changed ()
236 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
240 RCConfiguration* _rc_config;
241 CheckButton _limit_undo_button;
242 SpinButton _limit_undo_spin;
243 CheckButton _save_undo_button;
244 SpinButton _save_undo_spin;
249 static const struct {
261 { "Key|Shift", GDK_SHIFT_MASK },
262 { "Command", GDK_META_MASK },
263 { "Control", GDK_CONTROL_MASK },
264 { "Option", GDK_MOD1_MASK },
265 { "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
266 { "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
267 { "Shift-Option", GDK_SHIFT_MASK|GDK_MOD1_MASK },
268 { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
271 { "Key|Shift", GDK_SHIFT_MASK },
272 { "Control", GDK_CONTROL_MASK },
273 { "Alt (Mod1)", GDK_MOD1_MASK },
274 { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
275 { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
276 { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
277 { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
278 { "Mod2", GDK_MOD2_MASK },
279 { "Mod3", GDK_MOD3_MASK },
280 { "Mod4", GDK_MOD4_MASK },
281 { "Mod5", GDK_MOD5_MASK },
287 class KeyboardOptions : public OptionEditorBox
291 _delete_button_adjustment (3, 1, 12),
292 _delete_button_spin (_delete_button_adjustment),
293 _edit_button_adjustment (3, 1, 5),
294 _edit_button_spin (_edit_button_adjustment),
295 _insert_note_button_adjustment (3, 1, 5),
296 _insert_note_button_spin (_insert_note_button_adjustment)
298 /* internationalize and prepare for use with combos */
301 for (int i = 0; modifiers[i].name; ++i) {
302 dumb.push_back (S_(modifiers[i].name));
305 set_popdown_strings (_edit_modifier_combo, dumb);
306 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
308 for (int x = 0; modifiers[x].name; ++x) {
309 if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
310 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
315 Table* t = manage (new Table (4, 4));
318 Label* l = manage (left_aligned_label (_("Edit using:")));
319 l->set_name ("OptionsLabel");
321 t->attach (*l, 0, 1, 0, 1, FILL | EXPAND, FILL);
322 t->attach (_edit_modifier_combo, 1, 2, 0, 1, FILL | EXPAND, FILL);
324 l = manage (new Label (_("+ button")));
325 l->set_name ("OptionsLabel");
327 t->attach (*l, 3, 4, 0, 1, FILL | EXPAND, FILL);
328 t->attach (_edit_button_spin, 4, 5, 0, 1, FILL | EXPAND, FILL);
330 _edit_button_spin.set_name ("OptionsEntry");
331 _edit_button_adjustment.set_value (Keyboard::edit_button());
332 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
334 set_popdown_strings (_delete_modifier_combo, dumb);
335 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
337 for (int x = 0; modifiers[x].name; ++x) {
338 if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
339 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
344 l = manage (left_aligned_label (_("Delete using:")));
345 l->set_name ("OptionsLabel");
347 t->attach (*l, 0, 1, 1, 2, FILL | EXPAND, FILL);
348 t->attach (_delete_modifier_combo, 1, 2, 1, 2, FILL | EXPAND, FILL);
350 l = manage (new Label (_("+ button")));
351 l->set_name ("OptionsLabel");
353 t->attach (*l, 3, 4, 1, 2, FILL | EXPAND, FILL);
354 t->attach (_delete_button_spin, 4, 5, 1, 2, FILL | EXPAND, FILL);
356 _delete_button_spin.set_name ("OptionsEntry");
357 _delete_button_adjustment.set_value (Keyboard::delete_button());
358 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
361 set_popdown_strings (_insert_note_modifier_combo, dumb);
362 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
364 for (int x = 0; modifiers[x].name; ++x) {
365 if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
366 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
371 l = manage (left_aligned_label (_("Insert note using:")));
372 l->set_name ("OptionsLabel");
374 t->attach (*l, 0, 1, 2, 3, FILL | EXPAND, FILL);
375 t->attach (_insert_note_modifier_combo, 1, 2, 2, 3, FILL | EXPAND, FILL);
377 l = manage (new Label (_("+ button")));
378 l->set_name ("OptionsLabel");
380 t->attach (*l, 3, 4, 2, 3, FILL | EXPAND, FILL);
381 t->attach (_insert_note_button_spin, 4, 5, 2, 3, FILL | EXPAND, FILL);
383 _insert_note_button_spin.set_name ("OptionsEntry");
384 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
385 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
388 set_popdown_strings (_snap_modifier_combo, dumb);
389 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
391 for (int x = 0; modifiers[x].name; ++x) {
392 if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
393 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
398 l = manage (left_aligned_label (_("Toggle snap using:")));
399 l->set_name ("OptionsLabel");
401 t->attach (*l, 0, 1, 3, 4, FILL | EXPAND, FILL);
402 t->attach (_snap_modifier_combo, 1, 2, 3, 4, FILL | EXPAND, FILL);
406 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
407 strs.push_back (bf->first);
410 set_popdown_strings (_keyboard_layout_selector, strs);
411 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
412 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
414 l = manage (left_aligned_label (_("Keyboard layout:")));
415 l->set_name ("OptionsLabel");
417 t->attach (*l, 0, 1, 4, 5, FILL | EXPAND, FILL);
418 t->attach (_keyboard_layout_selector, 1, 2, 4, 5, FILL | EXPAND, FILL);
420 _box->pack_start (*t, false, false);
423 void parameter_changed (string const &)
425 /* XXX: these aren't really config options... */
428 void set_state_from_config ()
430 /* XXX: these aren't really config options... */
435 void bindings_changed ()
437 string const txt = _keyboard_layout_selector.get_active_text();
439 /* XXX: config...? for all this keyboard stuff */
441 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
442 if (txt == i->first) {
443 if (Keyboard::load_keybindings (i->second)) {
444 Keyboard::save_keybindings ();
450 void edit_modifier_chosen ()
452 string const txt = _edit_modifier_combo.get_active_text();
454 for (int i = 0; modifiers[i].name; ++i) {
455 if (txt == _(modifiers[i].name)) {
456 Keyboard::set_edit_modifier (modifiers[i].modifier);
462 void delete_modifier_chosen ()
464 string const txt = _delete_modifier_combo.get_active_text();
466 for (int i = 0; modifiers[i].name; ++i) {
467 if (txt == _(modifiers[i].name)) {
468 Keyboard::set_delete_modifier (modifiers[i].modifier);
474 void insert_note_modifier_chosen ()
476 string const txt = _insert_note_modifier_combo.get_active_text();
478 for (int i = 0; modifiers[i].name; ++i) {
479 if (txt == _(modifiers[i].name)) {
480 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
486 void snap_modifier_chosen ()
488 string const txt = _snap_modifier_combo.get_active_text();
490 for (int i = 0; modifiers[i].name; ++i) {
491 if (txt == _(modifiers[i].name)) {
492 Keyboard::set_snap_modifier (modifiers[i].modifier);
498 void delete_button_changed ()
500 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
503 void edit_button_changed ()
505 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
508 void insert_note_button_changed ()
510 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
513 ComboBoxText _keyboard_layout_selector;
514 ComboBoxText _edit_modifier_combo;
515 ComboBoxText _delete_modifier_combo;
516 ComboBoxText _insert_note_modifier_combo;
517 ComboBoxText _snap_modifier_combo;
518 Adjustment _delete_button_adjustment;
519 SpinButton _delete_button_spin;
520 Adjustment _edit_button_adjustment;
521 SpinButton _edit_button_spin;
522 Adjustment _insert_note_button_adjustment;
523 SpinButton _insert_note_button_spin;
527 class FontScalingOptions : public OptionEditorBox
530 FontScalingOptions (RCConfiguration* c) :
532 _dpi_adjustment (50, 50, 250, 1, 10),
533 _dpi_slider (_dpi_adjustment)
535 _dpi_adjustment.set_value (_rc_config->get_font_scale () / 1024);
537 Label* l = manage (new Label (_("Font scaling:")));
538 l->set_name ("OptionsLabel");
540 _dpi_slider.set_update_policy (UPDATE_DISCONTINUOUS);
541 HBox* h = manage (new HBox);
543 h->pack_start (*l, false, false);
544 h->pack_start (_dpi_slider, true, true);
546 _box->pack_start (*h, false, false);
548 _dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
551 void parameter_changed (string const & p)
553 if (p == "font-scale") {
554 _dpi_adjustment.set_value (_rc_config->get_font_scale() / 1024);
558 void set_state_from_config ()
560 parameter_changed ("font-scale");
567 _rc_config->set_font_scale ((long) floor (_dpi_adjustment.get_value() * 1024));
568 /* XXX: should be triggered from the parameter changed signal */
572 RCConfiguration* _rc_config;
573 Adjustment _dpi_adjustment;
577 class BufferingOptions : public OptionEditorBox
580 BufferingOptions (RCConfiguration* c)
582 , _playback_adjustment (5, 1, 60, 1, 4)
583 , _capture_adjustment (5, 1, 60, 1, 4)
584 , _playback_slider (_playback_adjustment)
585 , _capture_slider (_capture_adjustment)
587 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
589 Label* l = manage (new Label (_("Playback (seconds of buffering):")));
590 l->set_name ("OptionsLabel");
592 _playback_slider.set_update_policy (UPDATE_DISCONTINUOUS);
593 HBox* h = manage (new HBox);
595 h->pack_start (*l, false, false);
596 h->pack_start (_playback_slider, true, true);
598 _box->pack_start (*h, false, false);
600 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
602 l = manage (new Label (_("Recording (seconds of buffering):")));
603 l->set_name ("OptionsLabel");
605 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
606 h = manage (new HBox);
608 h->pack_start (*l, false, false);
609 h->pack_start (_capture_slider, true, true);
611 _box->pack_start (*h, false, false);
613 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
614 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
617 void parameter_changed (string const & p)
619 if (p == "playback-buffer-seconds") {
620 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
621 } else if (p == "capture-buffer-seconds") {
622 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
626 void set_state_from_config ()
628 parameter_changed ("playback-buffer-seconds");
629 parameter_changed ("capture-buffer-seconds");
634 void playback_changed ()
636 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
639 void capture_changed ()
641 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
644 RCConfiguration* _rc_config;
645 Adjustment _playback_adjustment;
646 Adjustment _capture_adjustment;
647 HScale _playback_slider;
648 HScale _capture_slider;
651 class ControlSurfacesOptions : public OptionEditorBox
654 ControlSurfacesOptions (Gtk::Window& parent)
657 _store = ListStore::create (_model);
658 _view.set_model (_store);
659 _view.append_column (_("Name"), _model.name);
660 _view.get_column(0)->set_resizable (true);
661 _view.get_column(0)->set_expand (true);
662 _view.append_column_editable (_("Enabled"), _model.enabled);
663 _view.append_column_editable (_("Feedback"), _model.feedback);
665 _box->pack_start (_view, false, false);
667 Label* label = manage (new Label);
668 label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
670 _box->pack_start (*label, false, false);
673 ControlProtocolManager& m = ControlProtocolManager::instance ();
674 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
675 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
677 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
678 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
681 void parameter_changed (std::string const &)
686 void set_state_from_config ()
690 ControlProtocolManager& m = ControlProtocolManager::instance ();
691 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
693 if (!(*i)->mandatory) {
694 TreeModel::Row r = *_store->append ();
695 r[_model.name] = (*i)->name;
696 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
697 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
698 r[_model.protocol_info] = *i;
705 void protocol_status_changed (ControlProtocolInfo* cpi) {
707 TreeModel::Children rows = _store->children();
708 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
709 if ((*x)[_model.protocol_info] == cpi) {
710 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
716 void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
718 TreeModel::Row r = *i;
720 ControlProtocolInfo* cpi = r[_model.protocol_info];
725 bool const was_enabled = (cpi->protocol != 0);
726 bool const is_enabled = r[_model.enabled];
728 if (was_enabled != is_enabled) {
730 ControlProtocolManager::instance().instantiate (*cpi);
732 Gtk::Window* win = r[_model.editor];
737 ControlProtocolManager::instance().teardown (*cpi);
742 r[_model.editor] = 0;
743 cpi->requested = false;
747 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
748 bool const is_feedback = r[_model.feedback];
750 if (was_feedback != is_feedback && cpi->protocol) {
751 cpi->protocol->set_feedback (is_feedback);
755 void edit_clicked (GdkEventButton* ev)
757 if (ev->type != GDK_2BUTTON_PRESS) {
762 ControlProtocolInfo* cpi;
765 row = *(_view.get_selection()->get_selected());
767 Window* win = row[_model.editor];
768 if (win && !win->is_visible()) {
771 cpi = row[_model.protocol_info];
773 if (cpi && cpi->protocol && cpi->protocol->has_editor ()) {
774 Box* box = (Box*) cpi->protocol->get_gui ();
776 string title = row[_model.name];
777 ArdourWindow* win = new ArdourWindow (_parent, title);
778 win->set_title ("Control Protocol Options");
782 row[_model.editor] = win;
788 class ControlSurfacesModelColumns : public TreeModelColumnRecord
792 ControlSurfacesModelColumns ()
801 TreeModelColumn<string> name;
802 TreeModelColumn<bool> enabled;
803 TreeModelColumn<bool> feedback;
804 TreeModelColumn<ControlProtocolInfo*> protocol_info;
805 TreeModelColumn<Gtk::Window*> editor;
808 Glib::RefPtr<ListStore> _store;
809 ControlSurfacesModelColumns _model;
811 Gtk::Window& _parent;
812 PBD::ScopedConnection protocol_status_connection;
815 /** A class which allows control of visibility of some editor components usign
816 * a VisibilityGroup. The caller should pass in a `dummy' VisibilityGroup
817 * which has the correct members, but with null widget pointers. This
818 * class allows the user to set visibility of the members, the details
819 * of which are stored in a configuration variable which can be watched
820 * by parts of the editor that actually contain the widgets whose visibility
821 * is being controlled.
824 class VisibilityOption : public Option
827 /** @param name User-visible name for this group.
828 * @param g `Dummy' VisibilityGroup (as described above).
829 * @param get Method to get the value of the appropriate configuration variable.
830 * @param set Method to set the value of the appropriate configuration variable.
832 VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
833 : Option (g->get_state_name(), name)
835 , _visibility_group (g)
839 /* Watch for changes made by the user to our members */
840 _visibility_group->VisibilityChanged.connect_same_thread (
841 _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
845 void set_state_from_config ()
847 /* Set our state from the current configuration */
848 _visibility_group->set_state (_get ());
851 void add_to_page (OptionEditorPage* p)
853 _heading.add_to_page (p);
854 add_widget_to_page (p, _visibility_group->list_view ());
857 Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
862 /* The user has changed something, so reflect this change
863 in the RCConfiguration.
865 _set (_visibility_group->get_state_value ());
868 OptionEditorHeading _heading;
869 VisibilityGroup* _visibility_group;
870 sigc::slot<std::string> _get;
871 sigc::slot<bool, std::string> _set;
872 PBD::ScopedConnection _visibility_group_connection;
876 RCOptionEditor::RCOptionEditor ()
877 : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
878 , _rc_config (Config)
879 , _mixer_strip_visibility ("mixer-strip-visibility")
883 uint32_t hwcpus = hardware_concurrency ();
886 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
888 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
890 _("Signal processing uses"),
891 sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
892 sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
895 procs->add (-1, _("all but one processor"));
896 procs->add (0, _("all available processors"));
898 for (uint32_t i = 1; i <= hwcpus; ++i) {
899 procs->add (i, string_compose (_("%1 processors"), i));
902 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
904 add_option (_("Misc"), procs);
907 add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
909 add_option (_("Misc"), new UndoOptions (_rc_config));
911 add_option (_("Misc"),
913 "verify-remove-last-capture",
914 _("Verify removal of last capture"),
915 sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
916 sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
919 add_option (_("Misc"),
921 "periodic-safety-backups",
922 _("Make periodic backups of the session file"),
923 sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
924 sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
927 add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
929 add_option (_("Misc"),
931 "only-copy-imported-files",
932 _("Always copy imported files"),
933 sigc::mem_fun (*_rc_config, &RCConfiguration::get_only_copy_imported_files),
934 sigc::mem_fun (*_rc_config, &RCConfiguration::set_only_copy_imported_files)
937 add_option (_("Misc"), new DirectoryOption (
938 X_("default-session-parent-dir"),
939 _("Default folder for new sessions:"),
940 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
941 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
944 add_option (_("Misc"),
945 new SpinOption<uint32_t> (
946 "max-recent-sessions",
947 _("Maximum number of recent sessions"),
948 sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
949 sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
953 add_option (_("Misc"), new OptionEditorHeading (_("Click")));
955 add_option (_("Misc"), new ClickOptions (_rc_config, this));
957 add_option (_("Misc"),
960 _("Click gain level"),
961 sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
962 sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
965 add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
967 add_option (_("Misc"),
968 new SpinOption<double> (
969 "automation-thinning-factor",
970 _("Thinning factor (larger value => less data)"),
971 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
972 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
976 add_option (_("Misc"),
977 new SpinOption<double> (
978 "automation-interval-msecs",
979 _("Automation sampling interval (milliseconds)"),
980 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
981 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
989 tsf = new BoolOption (
990 "latched-record-enable",
991 _("Keep record-enable engaged on stop"),
992 sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
993 sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
995 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
996 add_option (_("Transport"), tsf);
998 tsf = new BoolOption (
999 "stop-recording-on-xrun",
1000 _("Stop recording when an xrun occurs"),
1001 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1002 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1004 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> Ardour will stop recording if an over- or underrun is detected by the audio engine"));
1005 add_option (_("Transport"), tsf);
1007 tsf = new BoolOption (
1008 "create-xrun-marker",
1009 _("Create markers where xruns occur"),
1010 sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1011 sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1013 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1014 add_option (_("Transport"), tsf);
1016 tsf = new BoolOption (
1017 "stop-at-session-end",
1018 _("Stop at the end of the session"),
1019 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1020 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1022 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> if Ardour is <b>not recording</b>, it will stop the transport "
1023 "when it reaches the current session end marker\n\n"
1024 "<b>When disabled</b> Ardour will continue to roll past the session end marker at all times"));
1025 add_option (_("Transport"), tsf);
1027 tsf = new BoolOption (
1029 _("Do seamless looping (not possible when slaved to MTC, JACK etc)"),
1030 sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1031 sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1033 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1034 "preventing any need to do a transport locate at the end of the loop\n\n"
1035 "<b>When disabled</b> looping is done by locating back to the start of the loop when Ardour reaches the end "
1036 "which will often cause a small click or delay"));
1037 add_option (_("Transport"), tsf);
1039 tsf = new BoolOption (
1040 "disable-disarm-during-roll",
1041 _("Disable per-track record disarm while rolling"),
1042 sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1043 sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1045 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"));
1046 add_option (_("Transport"), tsf);
1048 tsf = new BoolOption (
1050 _("12dB gain reduction during fast-forward and fast-rewind"),
1051 sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1052 sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1054 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1055 "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1056 add_option (_("Transport"), tsf);
1058 add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1060 _sync_source = new ComboOption<SyncSource> (
1062 _("External timecode source"),
1063 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1064 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1067 populate_sync_options ();
1068 add_option (_("Transport"), _sync_source);
1070 _sync_framerate = new BoolOption (
1071 "timecode-sync-frame-rate",
1072 _("Match session video frame rate to external timecode"),
1073 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1074 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1076 Gtkmm2ext::UI::instance()->set_tip
1077 (_sync_framerate->tip_widget(),
1078 _("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1079 "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1080 "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1081 "Instead the frame rate indication in the main clock will flash red and Ardour will convert between the external "
1082 "timecode standard and the session standard."));
1084 add_option (_("Transport"), _sync_framerate);
1086 _sync_genlock = new BoolOption (
1087 "timecode-source-is-synced",
1088 _("External timecode is sync locked"),
1089 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1090 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1092 Gtkmm2ext::UI::instance()->set_tip
1093 (_sync_genlock->tip_widget(),
1094 _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black & Burst, Wordclock, etc) with the audio interface."));
1097 add_option (_("Transport"), _sync_genlock);
1099 _sync_source_2997 = new BoolOption (
1100 "timecode-source-2997",
1101 _("Lock to 29.9700 fps instead of 30000/1001"),
1102 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1103 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1105 Gtkmm2ext::UI::instance()->set_tip
1106 (_sync_source_2997->tip_widget(),
1107 _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1108 "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1109 "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1110 "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1111 "That is not the actual rate, however some vendor use that rate - despite it being against the specs - "
1112 "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1115 add_option (_("Transport"), _sync_source_2997);
1117 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1119 _ltc_port = new ComboStringOption (
1121 _("LTC incoming port"),
1122 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1123 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1126 vector<string> physical_inputs;
1127 physical_inputs.push_back (_("None"));
1128 AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1129 _ltc_port->set_popdown_strings (physical_inputs);
1131 add_option (_("Transport"), _ltc_port);
1134 // TODO; rather disable this button than not compile it..
1135 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1137 add_option (_("Transport"),
1140 _("Enable LTC generator"),
1141 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1142 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1145 _ltc_send_continuously = new BoolOption (
1146 "ltc-send-continuously",
1147 _("send LTC while stopped"),
1148 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1149 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1151 Gtkmm2ext::UI::instance()->set_tip
1152 (_ltc_send_continuously->tip_widget(),
1153 _("<b>When enabled</b> Ardour will continue to send LTC information even when the transport (playhead) is not moving"));
1154 add_option (_("Transport"), _ltc_send_continuously);
1156 _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1157 _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1158 _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1159 _ltc_volume_slider = new HSliderOption("ltcvol", ("LTC generator level:"), *_ltc_volume_adjustment);
1161 Gtkmm2ext::UI::instance()->set_tip
1162 (_ltc_volume_slider->tip_widget(),
1163 _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is 0dBu ^= -18dbFS in an EBU calibrated system"));
1165 add_option (_("Transport"), _ltc_volume_slider);
1166 parameter_changed ("send-ltc");
1169 parameter_changed ("sync-source");
1173 add_option (_("Editor"),
1175 "link-region-and-track-selection",
1176 _("Link selection of regions and tracks"),
1177 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1178 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1181 add_option (_("Editor"),
1183 "automation-follows-regions",
1184 _("Move relevant automation when audio regions are moved"),
1185 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1186 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1189 add_option (_("Editor"),
1191 "show-track-meters",
1192 _("Show meters on tracks in the editor"),
1193 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1194 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1197 add_option (_("Editor"),
1199 "use-overlap-equivalency",
1200 _("Use overlap equivalency for regions"),
1201 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1202 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1205 add_option (_("Editor"),
1207 "rubberbanding-snaps-to-grid",
1208 _("Make rubberband selection rectangle snap to the grid"),
1209 sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1210 sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1213 add_option (_("Editor"),
1216 _("Show waveforms in regions"),
1217 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1218 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1221 add_option (_("Editor"),
1222 new BoolComboOption (
1223 "show-region-gain-envelopes",
1224 _("Show gain envelopes in audio regions"),
1226 _("only in region gain mode"),
1227 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1228 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1231 ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1233 _("Waveform scale"),
1234 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1235 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1238 wfs->add (Linear, _("linear"));
1239 wfs->add (Logarithmic, _("logarithmic"));
1241 add_option (_("Editor"), wfs);
1243 ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1245 _("Waveform shape"),
1246 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1247 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1250 wfsh->add (Traditional, _("traditional"));
1251 wfsh->add (Rectified, _("rectified"));
1253 add_option (_("Editor"), wfsh);
1255 add_option (_("Editor"),
1257 "show-waveforms-while-recording",
1258 _("Show waveforms for audio while it is being recorded"),
1259 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1260 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1263 add_option (_("Editor"),
1266 _("Show zoom toolbar"),
1267 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1268 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1271 add_option (_("Editor"),
1273 "color-regions-using-track-color",
1274 _("Color regions using their track's color"),
1275 sigc::mem_fun (*_rc_config, &RCConfiguration::get_color_regions_using_track_color),
1276 sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
1279 add_option (_("Editor"),
1281 "update-editor-during-summary-drag",
1282 _("Update editor window during drags of the summary"),
1283 sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1284 sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1287 add_option (_("Editor"),
1289 "sync-all-route-ordering",
1290 _("Synchronise editor and mixer track order"),
1291 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
1292 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
1295 add_option (_("Editor"),
1297 "link-editor-and-mixer-selection",
1298 _("Synchronise editor and mixer selection"),
1299 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1300 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1303 add_option (_("Editor"),
1306 _("Name new markers"),
1307 sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1308 sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1311 add_option (_("Editor"),
1313 "autoscroll-editor",
1314 _("Auto-scroll editor window when dragging near its edges"),
1315 sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1316 sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1321 add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1323 add_option (_("Audio"), new BufferingOptions (_rc_config));
1325 add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1327 add_option (_("Audio"),
1330 _("Use a monitor bus (allows AFL/PFL and more control)"),
1331 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_monitor_bus),
1332 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_monitor_bus)
1335 ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1337 _("Record monitoring handled by"),
1338 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1339 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1343 /* no JACK monitoring on CoreAudio */
1344 if (AudioEngine::instance()->can_request_hardware_monitoring()) {
1345 mm->add (HardwareMonitoring, _("JACK"));
1348 mm->add (SoftwareMonitoring, _("ardour"));
1349 mm->add (ExternalMonitoring, _("audio hardware"));
1351 add_option (_("Audio"), mm);
1353 add_option (_("Audio"),
1355 "tape-machine-mode",
1356 _("Tape machine mode"),
1357 sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1358 sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1361 add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1363 add_option (_("Audio"),
1365 "auto-connect-standard-busses",
1366 _("Auto-connect master/monitor busses"),
1367 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1368 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1371 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1372 "input-auto-connect",
1373 _("Connect track inputs"),
1374 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1375 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1378 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1379 iac->add (ManualConnect, _("manually"));
1381 add_option (_("Audio"), iac);
1383 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1384 "output-auto-connect",
1385 _("Connect track and bus outputs"),
1386 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1387 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1390 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1391 oac->add (AutoConnectMaster, _("automatically to master bus"));
1392 oac->add (ManualConnect, _("manually"));
1394 add_option (_("Audio"), oac);
1396 add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1398 add_option (_("Audio"),
1400 "denormal-protection",
1401 _("Use DC bias to protect against denormals"),
1402 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1403 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1406 ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1408 _("Processor handling"),
1409 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1410 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1413 dm->add (DenormalNone, _("no processor handling"));
1417 if (fpu.has_flush_to_zero()) {
1418 dm->add (DenormalFTZ, _("use FlushToZero"));
1421 if (fpu.has_denormals_are_zero()) {
1422 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1425 if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1426 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1429 add_option (_("Audio"), dm);
1431 add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1433 add_option (_("Audio"),
1435 "plugins-stop-with-transport",
1436 _("Silence plugins when the transport is stopped"),
1437 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1438 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1441 add_option (_("Audio"),
1443 "do-not-record-plugins",
1444 _("Disable plugins during recording"),
1445 sigc::mem_fun (*_rc_config, &RCConfiguration::get_do_not_record_plugins),
1446 sigc::mem_fun (*_rc_config, &RCConfiguration::set_do_not_record_plugins)
1449 add_option (_("Audio"),
1451 "new-plugins-active",
1452 _("Make new plugins active"),
1453 sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1454 sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1457 add_option (_("Audio"),
1459 "auto-analyse-audio",
1460 _("Enable automatic analysis of audio"),
1461 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1462 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1465 add_option (_("Audio"),
1467 "replicate-missing-region-channels",
1468 _("Replicate missing region channels"),
1469 sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1470 sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1475 add_option (_("Solo / mute"),
1478 _("Solo-in-place mute cut (dB)"),
1479 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1480 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1483 _solo_control_is_listen_control = new BoolOption (
1484 "solo-control-is-listen-control",
1485 _("Solo controls are Listen controls"),
1486 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1487 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1490 add_option (_("Solo / mute"), _solo_control_is_listen_control);
1492 _listen_position = new ComboOption<ListenPosition> (
1494 _("Listen Position"),
1495 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1496 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1499 _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1500 _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1502 add_option (_("Solo / mute"), _listen_position);
1504 ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1506 _("PFL signals come from"),
1507 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1508 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1511 pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1512 pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1514 add_option (_("Solo / mute"), pp);
1516 ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1518 _("AFL signals come from"),
1519 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1520 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1523 pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1524 pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1526 add_option (_("Solo / mute"), pa);
1528 parameter_changed ("use-monitor-bus");
1530 add_option (_("Solo / mute"),
1533 _("Exclusive solo"),
1534 sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1535 sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1538 add_option (_("Solo / mute"),
1541 _("Show solo muting"),
1542 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1543 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1546 add_option (_("Solo / mute"),
1548 "solo-mute-override",
1549 _("Soloing overrides muting"),
1550 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1551 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1554 add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1556 add_option (_("Solo / mute"),
1558 "mute-affects-pre-fader",
1559 _("Mute affects pre-fader sends"),
1560 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1561 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1564 add_option (_("Solo / mute"),
1566 "mute-affects-post-fader",
1567 _("Mute affects post-fader sends"),
1568 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1569 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1572 add_option (_("Solo / mute"),
1574 "mute-affects-control-outs",
1575 _("Mute affects control outputs"),
1576 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1577 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1580 add_option (_("Solo / mute"),
1582 "mute-affects-main-outs",
1583 _("Mute affects main outputs"),
1584 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1585 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1588 add_option (_("MIDI"),
1591 _("Send MIDI Clock"),
1592 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1593 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1596 add_option (_("MIDI"),
1599 _("Send MIDI Time Code"),
1600 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1601 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1604 add_option (_("MIDI"),
1605 new SpinOption<int> (
1606 "mtc-qf-speed-tolerance",
1607 _("Percentage either side of normal transport speed to transmit MTC"),
1608 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1609 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1613 add_option (_("MIDI"),
1616 _("Obey MIDI Machine Control commands"),
1617 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1618 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1621 add_option (_("MIDI"),
1624 _("Send MIDI Machine Control commands"),
1625 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1626 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1629 add_option (_("MIDI"),
1632 _("Send MIDI control feedback"),
1633 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1634 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1637 add_option (_("MIDI"),
1638 new SpinOption<uint8_t> (
1639 "mmc-receive-device-id",
1640 _("Inbound MMC device ID"),
1641 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1642 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1646 add_option (_("MIDI"),
1647 new SpinOption<uint8_t> (
1648 "mmc-send-device-id",
1649 _("Outbound MMC device ID"),
1650 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1651 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1655 add_option (_("MIDI"),
1656 new SpinOption<int32_t> (
1657 "initial-program-change",
1658 _("Initial program change"),
1659 sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1660 sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1664 add_option (_("MIDI"),
1666 "diplay-first-midi-bank-as-zero",
1667 _("Display first MIDI bank/program as 0"),
1668 sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1669 sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1672 add_option (_("MIDI"),
1674 "never-display-periodic-midi",
1675 _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1676 sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1677 sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1680 add_option (_("MIDI"),
1683 _("Sound MIDI notes as they are selected"),
1684 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1685 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1688 /* USER INTERACTION */
1690 add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1692 add_option (_("User interaction"), new KeyboardOptions);
1694 add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
1696 add_option (_("User interaction"), new ControlSurfacesOptions (*this));
1698 ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1700 _("Control surface remote ID"),
1701 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1702 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1705 rm->add (UserOrdered, _("assigned by user"));
1706 rm->add (MixerOrdered, _("follows order of mixer"));
1707 rm->add (EditorOrdered, _("follows order of editor"));
1709 add_option (_("User interaction"), rm);
1713 add_option (S_("GUI"),
1716 _("Graphically indicate mouse pointer hovering over various widgets"),
1717 sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
1718 sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
1721 add_option (S_("GUI"),
1724 _("Show tooltips if mouse hovers over a control"),
1725 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
1726 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
1730 /* font scaling does nothing with GDK/Quartz */
1731 add_option (S_("GUI"), new FontScalingOptions (_rc_config));
1733 add_option (S_("GUI"),
1735 "use-own-plugin-gui",
1736 _("Use plugins' own interfaces instead of Ardour's"),
1737 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
1738 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
1741 /* The names of these controls must be the same as those given in MixerStrip
1742 for the actual widgets being controlled.
1744 _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
1745 _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
1746 _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
1747 _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
1748 _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
1749 _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
1753 new VisibilityOption (
1755 &_mixer_strip_visibility,
1756 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
1757 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
1761 add_option (S_("GUI"),
1763 "default-narrow_ms",
1764 _("Use narrow strips in the mixer by default"),
1765 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
1766 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
1769 add_option (S_("GUI"), new OptionEditorHeading (_("Metering")));
1771 ComboOption<float>* mht = new ComboOption<float> (
1773 _("Meter hold time"),
1774 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
1775 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
1778 mht->add (MeterHoldOff, _("off"));
1779 mht->add (MeterHoldShort, _("short"));
1780 mht->add (MeterHoldMedium, _("medium"));
1781 mht->add (MeterHoldLong, _("long"));
1783 add_option (S_("GUI"), mht);
1785 ComboOption<float>* mfo = new ComboOption<float> (
1787 _("Meter fall-off"),
1788 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
1789 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
1792 mfo->add (METER_FALLOFF_OFF, _("off"));
1793 mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
1794 mfo->add (METER_FALLOFF_SLOW, _("slow"));
1795 mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
1796 mfo->add (METER_FALLOFF_FAST, _("fast"));
1797 mfo->add (METER_FALLOFF_FASTER, _("faster"));
1798 mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
1800 add_option (S_("GUI"), mfo);
1804 RCOptionEditor::parameter_changed (string const & p)
1806 OptionEditor::parameter_changed (p);
1808 if (p == "use-monitor-bus") {
1809 bool const s = Config->get_use_monitor_bus ();
1811 /* we can't use this if we don't have a monitor bus */
1812 Config->set_solo_control_is_listen_control (false);
1814 _solo_control_is_listen_control->set_sensitive (s);
1815 _listen_position->set_sensitive (s);
1816 } else if (p == "sync-source") {
1817 _sync_source->set_sensitive (true);
1819 _sync_source->set_sensitive (_session->config.get_external_sync());
1821 switch(Config->get_sync_source()) {
1824 _sync_genlock->set_sensitive (true);
1825 _sync_framerate->set_sensitive (true);
1826 _sync_source_2997->set_sensitive (true);
1829 _sync_genlock->set_sensitive (false);
1830 _sync_framerate->set_sensitive (false);
1831 _sync_source_2997->set_sensitive (false);
1835 } else if (p == "send-ltc") {
1836 bool const s = Config->get_send_ltc ();
1837 _ltc_send_continuously->set_sensitive (s);
1838 _ltc_volume_slider->set_sensitive (s);
1843 void RCOptionEditor::ltc_generator_volume_changed () {
1844 _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
1848 RCOptionEditor::populate_sync_options ()
1850 vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
1852 _sync_source->clear ();
1854 for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
1855 _sync_source->add (*i, sync_source_to_string (*i));