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),
980 tsf = new BoolOption (
981 "latched-record-enable",
982 _("Keep record-enable engaged on stop"),
983 sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
984 sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
986 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
987 add_option (_("Transport"), tsf);
989 tsf = new BoolOption (
990 "stop-recording-on-xrun",
991 _("Stop recording when an xrun occurs"),
992 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
993 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
995 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"));
996 add_option (_("Transport"), tsf);
998 tsf = new BoolOption (
999 "create-xrun-marker",
1000 _("Create markers where xruns occur"),
1001 sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1002 sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1004 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1005 add_option (_("Transport"), tsf);
1007 tsf = new BoolOption (
1008 "stop-at-session-end",
1009 _("Stop at the end of the session"),
1010 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1011 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1013 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> if Ardour is <b>not recording</b>, it will stop the transport "
1014 "when it reaches the current session end marker\n\n"
1015 "<b>When disabled</b> Ardour will continue to roll past the session end marker at all times"));
1016 add_option (_("Transport"), tsf);
1018 tsf = new BoolOption (
1020 _("Do seamless looping (not possible when slaved to MTC, JACK etc)"),
1021 sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1022 sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1024 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, "
1025 "preventing any need to do a transport locate at the end of the loop\n\n"
1026 "<b>When disabled</b> looping is done by locating back to the start of the loop when Ardour reaches the end "
1027 "which will often cause a small click or delay"));
1028 add_option (_("Transport"), tsf);
1030 tsf = new BoolOption (
1031 "disable-disarm-during-roll",
1032 _("Disable per-track record disarm while rolling"),
1033 sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1034 sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1036 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"));
1037 add_option (_("Transport"), tsf);
1039 tsf = new BoolOption (
1041 _("12dB gain reduction during fast-forward and fast-rewind"),
1042 sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1043 sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1045 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1046 "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1047 add_option (_("Transport"), tsf);
1049 add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1051 _sync_source = new ComboOption<SyncSource> (
1053 _("External timecode source"),
1054 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1055 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1058 populate_sync_options ();
1059 add_option (_("Transport"), _sync_source);
1061 _sync_framerate = new BoolOption (
1062 "timecode-sync-frame-rate",
1063 _("Match session video frame rate to external timecode"),
1064 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1065 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1067 Gtkmm2ext::UI::instance()->set_tip
1068 (_sync_framerate->tip_widget(),
1069 _("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1070 "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1071 "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1072 "Instead the frame rate indication in the main clock will flash red and Ardour will convert between the external "
1073 "timecode standard and the session standard"));
1075 add_option (_("Transport"), _sync_framerate);
1077 _sync_genlock = new BoolOption (
1078 "timecode-source-is-synced",
1079 _("External timecode is sync locked"),
1080 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1081 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1083 Gtkmm2ext::UI::instance()->set_tip
1084 (_sync_genlock->tip_widget(),
1085 _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black & Burst, Wordclock, etc) with the audio interface"));
1088 add_option (_("Transport"), _sync_genlock);
1090 _ltc_port = new ComboStringOption (
1092 _("LTC incoming port"),
1093 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1094 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1097 vector<string> physical_inputs;
1098 physical_inputs.push_back (_("None"));
1099 AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1100 _ltc_port->set_popdown_strings (physical_inputs);
1102 add_option (_("Transport"), _ltc_port);
1105 // TODO; rather disable this button than not compile it..
1106 add_option (_("Transport"),
1109 _("Enable LTC generator"),
1110 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1111 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1114 _ltc_send_continuously = new BoolOption (
1115 "ltc-send-continuously",
1116 _("send LTC while stopped"),
1117 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1118 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1120 Gtkmm2ext::UI::instance()->set_tip
1121 (_ltc_send_continuously->tip_widget(),
1122 _("<b>When enabled</b> Ardour will continue to send LTC information even when the transport (playhead) is not moving"));
1123 add_option (_("Transport"), _ltc_send_continuously);
1125 _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1126 _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1127 _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1128 _ltc_volume_slider = new HSliderOption("ltcvol", ("LTC generator level:"), *_ltc_volume_adjustment);
1130 Gtkmm2ext::UI::instance()->set_tip
1131 (_ltc_volume_slider->tip_widget(),
1132 _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is 0dBu ^= -18dbFS in an EBU calibrated system"));
1134 add_option (_("Transport"), _ltc_volume_slider);
1137 parameter_changed ("sync-source");
1138 parameter_changed ("send-ltc");
1142 add_option (_("Editor"),
1144 "link-region-and-track-selection",
1145 _("Link selection of regions and tracks"),
1146 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1147 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1150 add_option (_("Editor"),
1152 "automation-follows-regions",
1153 _("Move relevant automation when audio regions are moved"),
1154 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1155 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1158 add_option (_("Editor"),
1160 "show-track-meters",
1161 _("Show meters on tracks in the editor"),
1162 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1163 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1166 add_option (_("Editor"),
1168 "use-overlap-equivalency",
1169 _("Use overlap equivalency for regions"),
1170 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1171 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1174 add_option (_("Editor"),
1176 "rubberbanding-snaps-to-grid",
1177 _("Make rubberband selection rectangle snap to the grid"),
1178 sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1179 sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1182 add_option (_("Editor"),
1185 _("Show waveforms in regions"),
1186 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1187 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1190 add_option (_("Editor"),
1191 new BoolComboOption (
1192 "show-region-gain-envelopes",
1193 _("Show gain envelopes in audio regions"),
1195 _("only in region gain mode"),
1196 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1197 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1200 ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1202 _("Waveform scale"),
1203 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1204 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1207 wfs->add (Linear, _("linear"));
1208 wfs->add (Logarithmic, _("logarithmic"));
1210 add_option (_("Editor"), wfs);
1212 ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1214 _("Waveform shape"),
1215 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1216 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1219 wfsh->add (Traditional, _("traditional"));
1220 wfsh->add (Rectified, _("rectified"));
1222 add_option (_("Editor"), wfsh);
1224 add_option (_("Editor"),
1226 "show-waveforms-while-recording",
1227 _("Show waveforms for audio while it is being recorded"),
1228 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1229 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1232 add_option (_("Editor"),
1235 _("Show zoom toolbar"),
1236 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1237 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1240 add_option (_("Editor"),
1242 "color-regions-using-track-color",
1243 _("Color regions using their track's color"),
1244 sigc::mem_fun (*_rc_config, &RCConfiguration::get_color_regions_using_track_color),
1245 sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
1248 add_option (_("Editor"),
1250 "update-editor-during-summary-drag",
1251 _("Update editor window during drags of the summary"),
1252 sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1253 sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1256 add_option (_("Editor"),
1258 "sync-all-route-ordering",
1259 _("Synchronise editor and mixer track order"),
1260 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
1261 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
1264 add_option (_("Editor"),
1266 "link-editor-and-mixer-selection",
1267 _("Synchronise editor and mixer selection"),
1268 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1269 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1272 add_option (_("Editor"),
1275 _("Name new markers"),
1276 sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1277 sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1280 add_option (_("Editor"),
1282 "autoscroll-editor",
1283 _("Auto-scroll editor window when dragging near its edges"),
1284 sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1285 sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1290 add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1292 add_option (_("Audio"), new BufferingOptions (_rc_config));
1294 add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1296 add_option (_("Audio"),
1299 _("Use a monitor bus (allows AFL/PFL and more control)"),
1300 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_monitor_bus),
1301 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_monitor_bus)
1304 ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1306 _("Record monitoring handled by"),
1307 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1308 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1312 /* no JACK monitoring on CoreAudio */
1313 if (AudioEngine::instance()->can_request_hardware_monitoring()) {
1314 mm->add (HardwareMonitoring, _("JACK"));
1317 mm->add (SoftwareMonitoring, _("ardour"));
1318 mm->add (ExternalMonitoring, _("audio hardware"));
1320 add_option (_("Audio"), mm);
1322 add_option (_("Audio"),
1324 "tape-machine-mode",
1325 _("Tape machine mode"),
1326 sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1327 sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1330 add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1332 add_option (_("Audio"),
1334 "auto-connect-standard-busses",
1335 _("Auto-connect master/monitor busses"),
1336 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1337 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1340 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1341 "input-auto-connect",
1342 _("Connect track inputs"),
1343 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1344 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1347 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1348 iac->add (ManualConnect, _("manually"));
1350 add_option (_("Audio"), iac);
1352 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1353 "output-auto-connect",
1354 _("Connect track and bus outputs"),
1355 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1356 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1359 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1360 oac->add (AutoConnectMaster, _("automatically to master bus"));
1361 oac->add (ManualConnect, _("manually"));
1363 add_option (_("Audio"), oac);
1365 add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1367 add_option (_("Audio"),
1369 "denormal-protection",
1370 _("Use DC bias to protect against denormals"),
1371 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1372 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1375 ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1377 _("Processor handling"),
1378 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1379 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1382 dm->add (DenormalNone, _("no processor handling"));
1386 if (fpu.has_flush_to_zero()) {
1387 dm->add (DenormalFTZ, _("use FlushToZero"));
1390 if (fpu.has_denormals_are_zero()) {
1391 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1394 if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1395 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1398 add_option (_("Audio"), dm);
1400 add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1402 add_option (_("Audio"),
1404 "plugins-stop-with-transport",
1405 _("Silence plugins when the transport is stopped"),
1406 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1407 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1410 add_option (_("Audio"),
1412 "do-not-record-plugins",
1413 _("Disable plugins during recording"),
1414 sigc::mem_fun (*_rc_config, &RCConfiguration::get_do_not_record_plugins),
1415 sigc::mem_fun (*_rc_config, &RCConfiguration::set_do_not_record_plugins)
1418 add_option (_("Audio"),
1420 "new-plugins-active",
1421 _("Make new plugins active"),
1422 sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1423 sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1426 add_option (_("Audio"),
1428 "auto-analyse-audio",
1429 _("Enable automatic analysis of audio"),
1430 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1431 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1434 add_option (_("Audio"),
1436 "replicate-missing-region-channels",
1437 _("Replicate missing region channels"),
1438 sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1439 sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1444 add_option (_("Solo / mute"),
1447 _("Solo-in-place mute cut (dB)"),
1448 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1449 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1452 _solo_control_is_listen_control = new BoolOption (
1453 "solo-control-is-listen-control",
1454 _("Solo controls are Listen controls"),
1455 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1456 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1459 add_option (_("Solo / mute"), _solo_control_is_listen_control);
1461 _listen_position = new ComboOption<ListenPosition> (
1463 _("Listen Position"),
1464 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1465 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1468 _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1469 _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1471 add_option (_("Solo / mute"), _listen_position);
1473 ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1475 _("PFL signals come from"),
1476 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1477 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1480 pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1481 pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1483 add_option (_("Solo / mute"), pp);
1485 ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1487 _("AFL signals come from"),
1488 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1489 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1492 pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1493 pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1495 add_option (_("Solo / mute"), pa);
1497 parameter_changed ("use-monitor-bus");
1499 add_option (_("Solo / mute"),
1502 _("Exclusive solo"),
1503 sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1504 sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1507 add_option (_("Solo / mute"),
1510 _("Show solo muting"),
1511 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1512 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1515 add_option (_("Solo / mute"),
1517 "solo-mute-override",
1518 _("Soloing overrides muting"),
1519 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1520 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1523 add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1525 add_option (_("Solo / mute"),
1527 "mute-affects-pre-fader",
1528 _("Mute affects pre-fader sends"),
1529 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1530 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1533 add_option (_("Solo / mute"),
1535 "mute-affects-post-fader",
1536 _("Mute affects post-fader sends"),
1537 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1538 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1541 add_option (_("Solo / mute"),
1543 "mute-affects-control-outs",
1544 _("Mute affects control outputs"),
1545 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1546 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1549 add_option (_("Solo / mute"),
1551 "mute-affects-main-outs",
1552 _("Mute affects main outputs"),
1553 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1554 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1557 add_option (_("MIDI"),
1560 _("Send MIDI Clock"),
1561 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1562 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1565 add_option (_("MIDI"),
1568 _("Send MIDI Time Code"),
1569 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1570 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1573 add_option (_("MIDI"),
1574 new SpinOption<int> (
1575 "mtc-qf-speed-tolerance",
1576 _("Percentage either side of normal transport speed to transmit MTC"),
1577 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1578 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1582 add_option (_("MIDI"),
1585 _("Obey MIDI Machine Control commands"),
1586 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1587 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1590 add_option (_("MIDI"),
1593 _("Send MIDI Machine Control commands"),
1594 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1595 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1598 add_option (_("MIDI"),
1601 _("Send MIDI control feedback"),
1602 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1603 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1606 add_option (_("MIDI"),
1607 new SpinOption<uint8_t> (
1608 "mmc-receive-device-id",
1609 _("Inbound MMC device ID"),
1610 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1611 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1615 add_option (_("MIDI"),
1616 new SpinOption<uint8_t> (
1617 "mmc-send-device-id",
1618 _("Outbound MMC device ID"),
1619 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1620 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1624 add_option (_("MIDI"),
1625 new SpinOption<int32_t> (
1626 "initial-program-change",
1627 _("Initial program change"),
1628 sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1629 sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1633 add_option (_("MIDI"),
1635 "diplay-first-midi-bank-as-zero",
1636 _("Display first MIDI bank/program as 0"),
1637 sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1638 sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1641 add_option (_("MIDI"),
1643 "never-display-periodic-midi",
1644 _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1645 sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1646 sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1649 add_option (_("MIDI"),
1652 _("Sound MIDI notes as they are selected"),
1653 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1654 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1657 /* USER INTERACTION */
1659 add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1661 add_option (_("User interaction"), new KeyboardOptions);
1663 add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
1665 add_option (_("User interaction"), new ControlSurfacesOptions (*this));
1667 ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1669 _("Control surface remote ID"),
1670 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1671 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1674 rm->add (UserOrdered, _("assigned by user"));
1675 rm->add (MixerOrdered, _("follows order of mixer"));
1676 rm->add (EditorOrdered, _("follows order of editor"));
1678 add_option (_("User interaction"), rm);
1682 add_option (S_("GUI"),
1685 _("Graphically indicate mouse pointer hovering over various widgets"),
1686 sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
1687 sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
1691 /* font scaling does nothing with GDK/Quartz */
1692 add_option (S_("GUI"), new FontScalingOptions (_rc_config));
1694 add_option (S_("GUI"),
1696 "use-own-plugin-gui",
1697 _("Use plugins' own interfaces instead of Ardour's"),
1698 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
1699 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
1702 /* The names of these controls must be the same as those given in MixerStrip
1703 for the actual widgets being controlled.
1705 _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
1706 _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
1707 _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
1708 _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
1709 _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
1710 _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
1714 new VisibilityOption (
1716 &_mixer_strip_visibility,
1717 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
1718 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
1722 add_option (S_("GUI"),
1724 "default-narrow_ms",
1725 _("Use narrow strips in the mixer by default"),
1726 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
1727 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
1730 add_option (S_("GUI"), new OptionEditorHeading (_("Metering")));
1732 ComboOption<float>* mht = new ComboOption<float> (
1734 _("Meter hold time"),
1735 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
1736 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
1739 mht->add (MeterHoldOff, _("off"));
1740 mht->add (MeterHoldShort, _("short"));
1741 mht->add (MeterHoldMedium, _("medium"));
1742 mht->add (MeterHoldLong, _("long"));
1744 add_option (S_("GUI"), mht);
1746 ComboOption<float>* mfo = new ComboOption<float> (
1748 _("Meter fall-off"),
1749 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
1750 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
1753 mfo->add (METER_FALLOFF_OFF, _("off"));
1754 mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
1755 mfo->add (METER_FALLOFF_SLOW, _("slow"));
1756 mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
1757 mfo->add (METER_FALLOFF_FAST, _("fast"));
1758 mfo->add (METER_FALLOFF_FASTER, _("faster"));
1759 mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
1761 add_option (S_("GUI"), mfo);
1765 RCOptionEditor::parameter_changed (string const & p)
1767 OptionEditor::parameter_changed (p);
1769 if (p == "use-monitor-bus") {
1770 bool const s = Config->get_use_monitor_bus ();
1772 /* we can't use this if we don't have a monitor bus */
1773 Config->set_solo_control_is_listen_control (false);
1775 _solo_control_is_listen_control->set_sensitive (s);
1776 _listen_position->set_sensitive (s);
1777 } else if (p == "sync-source") {
1778 switch(Config->get_sync_source()) {
1781 _sync_genlock->set_sensitive (true);
1782 _sync_framerate->set_sensitive (true);
1785 _sync_genlock->set_sensitive (false);
1786 _sync_framerate->set_sensitive (false);
1789 } else if (p == "send-ltc") {
1790 bool const s = Config->get_send_ltc ();
1791 _ltc_send_continuously->set_sensitive (s);
1792 _ltc_volume_slider->set_sensitive (s);
1796 void RCOptionEditor::ltc_generator_volume_changed () {
1797 _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
1801 RCOptionEditor::populate_sync_options ()
1803 vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
1805 _sync_source->clear ();
1807 for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
1808 _sync_source->add (*i, sync_source_to_string (*i));