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 ();
887 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
889 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
891 _("Signal processing uses"),
892 sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
893 sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
896 procs->add (-1, _("all but one processor"));
897 procs->add (0, _("all available processors"));
899 for (uint32_t i = 1; i <= hwcpus; ++i) {
900 procs->add (i, string_compose (_("%1 processors"), i));
903 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
905 add_option (_("Misc"), procs);
908 add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
910 add_option (_("Misc"), new UndoOptions (_rc_config));
912 add_option (_("Misc"),
914 "verify-remove-last-capture",
915 _("Verify removal of last capture"),
916 sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
917 sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
920 add_option (_("Misc"),
922 "periodic-safety-backups",
923 _("Make periodic backups of the session file"),
924 sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
925 sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
928 add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
930 add_option (_("Misc"),
932 "only-copy-imported-files",
933 _("Always copy imported files"),
934 sigc::mem_fun (*_rc_config, &RCConfiguration::get_only_copy_imported_files),
935 sigc::mem_fun (*_rc_config, &RCConfiguration::set_only_copy_imported_files)
938 add_option (_("Misc"), new DirectoryOption (
939 X_("default-session-parent-dir"),
940 _("Default folder for new sessions:"),
941 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
942 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
945 add_option (_("Misc"),
946 new SpinOption<uint32_t> (
947 "max-recent-sessions",
948 _("Maximum number of recent sessions"),
949 sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
950 sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
954 add_option (_("Misc"), new OptionEditorHeading (_("Click")));
956 add_option (_("Misc"), new ClickOptions (_rc_config, this));
958 add_option (_("Misc"),
961 _("Click gain level"),
962 sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
963 sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
966 add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
968 add_option (_("Misc"),
969 new SpinOption<double> (
970 "automation-thinning-factor",
971 _("Thinning factor (larger value => less data)"),
972 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
973 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
977 add_option (_("Misc"),
978 new SpinOption<double> (
979 "automation-interval-msecs",
980 _("Automation sampling interval (milliseconds)"),
981 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
982 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
990 tsf = new BoolOption (
991 "latched-record-enable",
992 _("Keep record-enable engaged on stop"),
993 sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
994 sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
996 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
997 add_option (_("Transport"), tsf);
999 tsf = new BoolOption (
1000 "stop-recording-on-xrun",
1001 _("Stop recording when an xrun occurs"),
1002 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1003 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1005 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"));
1006 add_option (_("Transport"), tsf);
1008 tsf = new BoolOption (
1009 "create-xrun-marker",
1010 _("Create markers where xruns occur"),
1011 sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1012 sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1014 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1015 add_option (_("Transport"), tsf);
1017 tsf = new BoolOption (
1018 "stop-at-session-end",
1019 _("Stop at the end of the session"),
1020 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1021 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1023 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> if Ardour is <b>not recording</b>, it will stop the transport "
1024 "when it reaches the current session end marker\n\n"
1025 "<b>When disabled</b> Ardour will continue to roll past the session end marker at all times"));
1026 add_option (_("Transport"), tsf);
1028 tsf = new BoolOption (
1030 _("Do seamless looping (not possible when slaved to MTC, JACK etc)"),
1031 sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1032 sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1034 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, "
1035 "preventing any need to do a transport locate at the end of the loop\n\n"
1036 "<b>When disabled</b> looping is done by locating back to the start of the loop when Ardour reaches the end "
1037 "which will often cause a small click or delay"));
1038 add_option (_("Transport"), tsf);
1040 tsf = new BoolOption (
1041 "disable-disarm-during-roll",
1042 _("Disable per-track record disarm while rolling"),
1043 sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1044 sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1046 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"));
1047 add_option (_("Transport"), tsf);
1049 tsf = new BoolOption (
1051 _("12dB gain reduction during fast-forward and fast-rewind"),
1052 sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1053 sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1055 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1056 "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1057 add_option (_("Transport"), tsf);
1059 add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1061 _sync_source = new ComboOption<SyncSource> (
1063 _("External timecode source"),
1064 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1065 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1068 populate_sync_options ();
1069 add_option (_("Transport"), _sync_source);
1071 _sync_framerate = new BoolOption (
1072 "timecode-sync-frame-rate",
1073 _("Match session video frame rate to external timecode"),
1074 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1075 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1077 Gtkmm2ext::UI::instance()->set_tip
1078 (_sync_framerate->tip_widget(),
1079 _("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1080 "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1081 "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1082 "Instead the frame rate indication in the main clock will flash red and Ardour will convert between the external "
1083 "timecode standard and the session standard."));
1085 add_option (_("Transport"), _sync_framerate);
1087 _sync_genlock = new BoolOption (
1088 "timecode-source-is-synced",
1089 _("External timecode is sync locked"),
1090 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1091 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1093 Gtkmm2ext::UI::instance()->set_tip
1094 (_sync_genlock->tip_widget(),
1095 _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black & Burst, Wordclock, etc) with the audio interface."));
1098 add_option (_("Transport"), _sync_genlock);
1100 _sync_source_2997 = new BoolOption (
1101 "timecode-source-2997",
1102 _("Lock to 29.9700 fps instead of 30000/1001"),
1103 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1104 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1106 Gtkmm2ext::UI::instance()->set_tip
1107 (_sync_source_2997->tip_widget(),
1108 _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1109 "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1110 "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1111 "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1112 "That is not the actual rate, however some vendor use that rate - despite it being against the specs - "
1113 "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1116 add_option (_("Transport"), _sync_source_2997);
1118 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1120 _ltc_port = new ComboStringOption (
1122 _("LTC incoming port"),
1123 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1124 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1127 vector<string> physical_inputs;
1128 physical_inputs.push_back (_("None"));
1129 AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1130 _ltc_port->set_popdown_strings (physical_inputs);
1132 add_option (_("Transport"), _ltc_port);
1135 // TODO; rather disable this button than not compile it..
1136 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1138 add_option (_("Transport"),
1141 _("Enable LTC generator"),
1142 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1143 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1146 _ltc_send_continuously = new BoolOption (
1147 "ltc-send-continuously",
1148 _("send LTC while stopped"),
1149 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1150 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1152 Gtkmm2ext::UI::instance()->set_tip
1153 (_ltc_send_continuously->tip_widget(),
1154 _("<b>When enabled</b> Ardour will continue to send LTC information even when the transport (playhead) is not moving"));
1155 add_option (_("Transport"), _ltc_send_continuously);
1157 _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1158 _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1159 _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1160 _ltc_volume_slider = new HSliderOption("ltcvol", ("LTC generator level:"), *_ltc_volume_adjustment);
1162 Gtkmm2ext::UI::instance()->set_tip
1163 (_ltc_volume_slider->tip_widget(),
1164 _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is 0dBu ^= -18dbFS in an EBU calibrated system"));
1166 add_option (_("Transport"), _ltc_volume_slider);
1167 parameter_changed ("send-ltc");
1170 parameter_changed ("sync-source");
1174 add_option (_("Editor"),
1176 "link-region-and-track-selection",
1177 _("Link selection of regions and tracks"),
1178 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1179 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1182 add_option (_("Editor"),
1184 "automation-follows-regions",
1185 _("Move relevant automation when audio regions are moved"),
1186 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1187 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1190 add_option (_("Editor"),
1192 "show-track-meters",
1193 _("Show meters on tracks in the editor"),
1194 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1195 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1198 bo = new BoolOption (
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"), bo);
1206 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
1207 string_compose (_("When extending region selection across a group, %1 must decide which regions are equivalent"
1208 "\n\nIf enabled, regions are considered \"equivalent\" if they overlap on the timeline."
1209 "\n\nIf disabled, regions are considered \"equivalent\" only if have the same start time, length and position"),
1212 add_option (_("Editor"),
1214 "rubberbanding-snaps-to-grid",
1215 _("Make rubberband selection rectangle snap to the grid"),
1216 sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1217 sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1220 add_option (_("Editor"),
1223 _("Show waveforms in regions"),
1224 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1225 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1228 add_option (_("Editor"),
1229 new BoolComboOption (
1230 "show-region-gain-envelopes",
1231 _("Show gain envelopes in audio regions"),
1233 _("only in region gain mode"),
1234 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1235 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1238 ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1240 _("Waveform scale"),
1241 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1242 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1245 wfs->add (Linear, _("linear"));
1246 wfs->add (Logarithmic, _("logarithmic"));
1248 add_option (_("Editor"), wfs);
1250 ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1252 _("Waveform shape"),
1253 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1254 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1257 wfsh->add (Traditional, _("traditional"));
1258 wfsh->add (Rectified, _("rectified"));
1260 add_option (_("Editor"), wfsh);
1262 add_option (_("Editor"),
1264 "show-waveforms-while-recording",
1265 _("Show waveforms for audio while it is being recorded"),
1266 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1267 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1270 add_option (_("Editor"),
1273 _("Show zoom toolbar"),
1274 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1275 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1278 add_option (_("Editor"),
1280 "color-regions-using-track-color",
1281 _("Color regions using their track's color"),
1282 sigc::mem_fun (*_rc_config, &RCConfiguration::get_color_regions_using_track_color),
1283 sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
1286 add_option (_("Editor"),
1288 "update-editor-during-summary-drag",
1289 _("Update editor window during drags of the summary"),
1290 sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1291 sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1294 add_option (_("Editor"),
1296 "sync-all-route-ordering",
1297 _("Synchronise editor and mixer track order"),
1298 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
1299 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
1302 add_option (_("Editor"),
1304 "link-editor-and-mixer-selection",
1305 _("Synchronise editor and mixer selection"),
1306 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1307 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1310 bo = new BoolOption (
1312 _("Name new markers"),
1313 sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1314 sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1317 add_option (_("Editor"), bo);
1318 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."
1319 "\n\nYou can always rename markers by right-clicking on them"));
1321 add_option (_("Editor"),
1323 "autoscroll-editor",
1324 _("Auto-scroll editor window when dragging near its edges"),
1325 sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1326 sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1331 add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1333 add_option (_("Audio"), new BufferingOptions (_rc_config));
1335 add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1337 add_option (_("Audio"),
1340 _("Use a monitor bus (allows AFL/PFL and more control)"),
1341 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_monitor_bus),
1342 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_monitor_bus)
1345 ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1347 _("Record monitoring handled by"),
1348 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1349 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1353 /* no JACK monitoring on CoreAudio */
1354 if (AudioEngine::instance()->can_request_hardware_monitoring()) {
1355 mm->add (HardwareMonitoring, _("JACK"));
1358 mm->add (SoftwareMonitoring, _("ardour"));
1359 mm->add (ExternalMonitoring, _("audio hardware"));
1361 add_option (_("Audio"), mm);
1363 add_option (_("Audio"),
1365 "tape-machine-mode",
1366 _("Tape machine mode"),
1367 sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1368 sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1371 add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1373 add_option (_("Audio"),
1375 "auto-connect-standard-busses",
1376 _("Auto-connect master/monitor busses"),
1377 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1378 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1381 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1382 "input-auto-connect",
1383 _("Connect track inputs"),
1384 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1385 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1388 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1389 iac->add (ManualConnect, _("manually"));
1391 add_option (_("Audio"), iac);
1393 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1394 "output-auto-connect",
1395 _("Connect track and bus outputs"),
1396 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1397 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1400 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1401 oac->add (AutoConnectMaster, _("automatically to master bus"));
1402 oac->add (ManualConnect, _("manually"));
1404 add_option (_("Audio"), oac);
1406 add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1408 add_option (_("Audio"),
1410 "denormal-protection",
1411 _("Use DC bias to protect against denormals"),
1412 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1413 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1416 ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1418 _("Processor handling"),
1419 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1420 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1423 dm->add (DenormalNone, _("no processor handling"));
1427 if (fpu.has_flush_to_zero()) {
1428 dm->add (DenormalFTZ, _("use FlushToZero"));
1431 if (fpu.has_denormals_are_zero()) {
1432 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1435 if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1436 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1439 add_option (_("Audio"), dm);
1441 add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1443 add_option (_("Audio"),
1445 "plugins-stop-with-transport",
1446 _("Silence plugins when the transport is stopped"),
1447 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1448 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1451 add_option (_("Audio"),
1453 "do-not-record-plugins",
1454 _("Disable plugins during recording"),
1455 sigc::mem_fun (*_rc_config, &RCConfiguration::get_do_not_record_plugins),
1456 sigc::mem_fun (*_rc_config, &RCConfiguration::set_do_not_record_plugins)
1459 add_option (_("Audio"),
1461 "new-plugins-active",
1462 _("Make new plugins active"),
1463 sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1464 sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1467 add_option (_("Audio"),
1469 "auto-analyse-audio",
1470 _("Enable automatic analysis of audio"),
1471 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1472 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1475 add_option (_("Audio"),
1477 "replicate-missing-region-channels",
1478 _("Replicate missing region channels"),
1479 sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1480 sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1485 add_option (_("Solo / mute"),
1488 _("Solo-in-place mute cut (dB)"),
1489 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1490 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1493 _solo_control_is_listen_control = new BoolOption (
1494 "solo-control-is-listen-control",
1495 _("Solo controls are Listen controls"),
1496 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1497 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1500 add_option (_("Solo / mute"), _solo_control_is_listen_control);
1502 _listen_position = new ComboOption<ListenPosition> (
1504 _("Listen Position"),
1505 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1506 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1509 _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1510 _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1512 add_option (_("Solo / mute"), _listen_position);
1514 ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1516 _("PFL signals come from"),
1517 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1518 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1521 pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1522 pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1524 add_option (_("Solo / mute"), pp);
1526 ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1528 _("AFL signals come from"),
1529 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1530 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1533 pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1534 pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1536 add_option (_("Solo / mute"), pa);
1538 parameter_changed ("use-monitor-bus");
1540 add_option (_("Solo / mute"),
1543 _("Exclusive solo"),
1544 sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1545 sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1548 add_option (_("Solo / mute"),
1551 _("Show solo muting"),
1552 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1553 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1556 add_option (_("Solo / mute"),
1558 "solo-mute-override",
1559 _("Soloing overrides muting"),
1560 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1561 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1564 add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1566 add_option (_("Solo / mute"),
1568 "mute-affects-pre-fader",
1569 _("Mute affects pre-fader sends"),
1570 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1571 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1574 add_option (_("Solo / mute"),
1576 "mute-affects-post-fader",
1577 _("Mute affects post-fader sends"),
1578 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1579 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1582 add_option (_("Solo / mute"),
1584 "mute-affects-control-outs",
1585 _("Mute affects control outputs"),
1586 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1587 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1590 add_option (_("Solo / mute"),
1592 "mute-affects-main-outs",
1593 _("Mute affects main outputs"),
1594 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1595 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1598 add_option (_("MIDI"),
1601 _("Send MIDI Clock"),
1602 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1603 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1606 add_option (_("MIDI"),
1609 _("Send MIDI Time Code"),
1610 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1611 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1614 add_option (_("MIDI"),
1615 new SpinOption<int> (
1616 "mtc-qf-speed-tolerance",
1617 _("Percentage either side of normal transport speed to transmit MTC"),
1618 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1619 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1623 add_option (_("MIDI"),
1626 _("Obey MIDI Machine Control commands"),
1627 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1628 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1631 add_option (_("MIDI"),
1634 _("Send MIDI Machine Control commands"),
1635 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1636 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1639 add_option (_("MIDI"),
1642 _("Send MIDI control feedback"),
1643 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1644 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1647 add_option (_("MIDI"),
1648 new SpinOption<uint8_t> (
1649 "mmc-receive-device-id",
1650 _("Inbound MMC device ID"),
1651 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1652 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1656 add_option (_("MIDI"),
1657 new SpinOption<uint8_t> (
1658 "mmc-send-device-id",
1659 _("Outbound MMC device ID"),
1660 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1661 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1665 add_option (_("MIDI"),
1666 new SpinOption<int32_t> (
1667 "initial-program-change",
1668 _("Initial program change"),
1669 sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1670 sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1674 add_option (_("MIDI"),
1676 "diplay-first-midi-bank-as-zero",
1677 _("Display first MIDI bank/program as 0"),
1678 sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1679 sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1682 add_option (_("MIDI"),
1684 "never-display-periodic-midi",
1685 _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1686 sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1687 sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1690 add_option (_("MIDI"),
1693 _("Sound MIDI notes as they are selected"),
1694 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1695 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1698 /* USER INTERACTION */
1700 add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1702 add_option (_("User interaction"), new KeyboardOptions);
1704 add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
1706 add_option (_("User interaction"), new ControlSurfacesOptions (*this));
1708 ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1710 _("Control surface remote ID"),
1711 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1712 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1715 rm->add (UserOrdered, _("assigned by user"));
1716 rm->add (MixerOrdered, _("follows order of mixer"));
1717 rm->add (EditorOrdered, _("follows order of editor"));
1719 add_option (_("User interaction"), rm);
1723 add_option (S_("GUI"),
1726 _("Graphically indicate mouse pointer hovering over various widgets"),
1727 sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
1728 sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
1731 add_option (S_("GUI"),
1734 _("Show tooltips if mouse hovers over a control"),
1735 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
1736 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
1740 /* font scaling does nothing with GDK/Quartz */
1741 add_option (S_("GUI"), new FontScalingOptions (_rc_config));
1743 add_option (S_("GUI"),
1745 "use-own-plugin-gui",
1746 _("Use plugins' own interfaces instead of Ardour's"),
1747 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
1748 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
1751 /* The names of these controls must be the same as those given in MixerStrip
1752 for the actual widgets being controlled.
1754 _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
1755 _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
1756 _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
1757 _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
1758 _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
1759 _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
1763 new VisibilityOption (
1765 &_mixer_strip_visibility,
1766 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
1767 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
1771 add_option (S_("GUI"),
1773 "default-narrow_ms",
1774 _("Use narrow strips in the mixer by default"),
1775 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
1776 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
1779 add_option (S_("GUI"), new OptionEditorHeading (_("Metering")));
1781 ComboOption<float>* mht = new ComboOption<float> (
1783 _("Meter hold time"),
1784 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
1785 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
1788 mht->add (MeterHoldOff, _("off"));
1789 mht->add (MeterHoldShort, _("short"));
1790 mht->add (MeterHoldMedium, _("medium"));
1791 mht->add (MeterHoldLong, _("long"));
1793 add_option (S_("GUI"), mht);
1795 ComboOption<float>* mfo = new ComboOption<float> (
1797 _("Meter fall-off"),
1798 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
1799 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
1802 mfo->add (METER_FALLOFF_OFF, _("off"));
1803 mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
1804 mfo->add (METER_FALLOFF_SLOW, _("slow"));
1805 mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
1806 mfo->add (METER_FALLOFF_FAST, _("fast"));
1807 mfo->add (METER_FALLOFF_FASTER, _("faster"));
1808 mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
1810 add_option (S_("GUI"), mfo);
1814 RCOptionEditor::parameter_changed (string const & p)
1816 OptionEditor::parameter_changed (p);
1818 if (p == "use-monitor-bus") {
1819 bool const s = Config->get_use_monitor_bus ();
1821 /* we can't use this if we don't have a monitor bus */
1822 Config->set_solo_control_is_listen_control (false);
1824 _solo_control_is_listen_control->set_sensitive (s);
1825 _listen_position->set_sensitive (s);
1826 } else if (p == "sync-source") {
1827 _sync_source->set_sensitive (true);
1829 _sync_source->set_sensitive (_session->config.get_external_sync());
1831 switch(Config->get_sync_source()) {
1834 _sync_genlock->set_sensitive (true);
1835 _sync_framerate->set_sensitive (true);
1836 _sync_source_2997->set_sensitive (true);
1839 _sync_genlock->set_sensitive (false);
1840 _sync_framerate->set_sensitive (false);
1841 _sync_source_2997->set_sensitive (false);
1845 } else if (p == "send-ltc") {
1846 bool const s = Config->get_send_ltc ();
1847 _ltc_send_continuously->set_sensitive (s);
1848 _ltc_volume_slider->set_sensitive (s);
1853 void RCOptionEditor::ltc_generator_volume_changed () {
1854 _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
1858 RCOptionEditor::populate_sync_options ()
1860 vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
1862 _sync_source->clear ();
1864 for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
1865 _sync_source->add (*i, sync_source_to_string (*i));