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 _sync_source_2997 = new BoolOption (
1091 "timecode-source-2997",
1092 _("Lock to 29.9700 fps instead of 30000/1001"),
1093 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1094 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1096 Gtkmm2ext::UI::instance()->set_tip
1097 (_sync_source_2997->tip_widget(),
1098 _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1099 "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1100 "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1101 "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1102 "That is not the actual rate, however some vendor use that rate - despite it being against the specs - "
1103 "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1106 add_option (_("Transport"), _sync_source_2997);
1108 _ltc_port = new ComboStringOption (
1110 _("LTC incoming port"),
1111 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1112 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1115 vector<string> physical_inputs;
1116 physical_inputs.push_back (_("None"));
1117 AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1118 _ltc_port->set_popdown_strings (physical_inputs);
1120 add_option (_("Transport"), _ltc_port);
1123 // TODO; rather disable this button than not compile it..
1124 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1126 add_option (_("Transport"),
1129 _("Enable LTC generator"),
1130 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1131 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1134 _ltc_send_continuously = new BoolOption (
1135 "ltc-send-continuously",
1136 _("send LTC while stopped"),
1137 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1138 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1140 Gtkmm2ext::UI::instance()->set_tip
1141 (_ltc_send_continuously->tip_widget(),
1142 _("<b>When enabled</b> Ardour will continue to send LTC information even when the transport (playhead) is not moving"));
1143 add_option (_("Transport"), _ltc_send_continuously);
1145 _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1146 _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1147 _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1148 _ltc_volume_slider = new HSliderOption("ltcvol", ("LTC generator level:"), *_ltc_volume_adjustment);
1150 Gtkmm2ext::UI::instance()->set_tip
1151 (_ltc_volume_slider->tip_widget(),
1152 _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is 0dBu ^= -18dbFS in an EBU calibrated system"));
1154 add_option (_("Transport"), _ltc_volume_slider);
1155 parameter_changed ("send-ltc");
1158 parameter_changed ("sync-source");
1162 add_option (_("Editor"),
1164 "link-region-and-track-selection",
1165 _("Link selection of regions and tracks"),
1166 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1167 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1170 add_option (_("Editor"),
1172 "automation-follows-regions",
1173 _("Move relevant automation when audio regions are moved"),
1174 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1175 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1178 add_option (_("Editor"),
1180 "show-track-meters",
1181 _("Show meters on tracks in the editor"),
1182 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1183 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1186 add_option (_("Editor"),
1188 "use-overlap-equivalency",
1189 _("Use overlap equivalency for regions"),
1190 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1191 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1194 add_option (_("Editor"),
1196 "rubberbanding-snaps-to-grid",
1197 _("Make rubberband selection rectangle snap to the grid"),
1198 sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1199 sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1202 add_option (_("Editor"),
1205 _("Show waveforms in regions"),
1206 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1207 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1210 add_option (_("Editor"),
1211 new BoolComboOption (
1212 "show-region-gain-envelopes",
1213 _("Show gain envelopes in audio regions"),
1215 _("only in region gain mode"),
1216 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1217 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1220 ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1222 _("Waveform scale"),
1223 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1224 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1227 wfs->add (Linear, _("linear"));
1228 wfs->add (Logarithmic, _("logarithmic"));
1230 add_option (_("Editor"), wfs);
1232 ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1234 _("Waveform shape"),
1235 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1236 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1239 wfsh->add (Traditional, _("traditional"));
1240 wfsh->add (Rectified, _("rectified"));
1242 add_option (_("Editor"), wfsh);
1244 add_option (_("Editor"),
1246 "show-waveforms-while-recording",
1247 _("Show waveforms for audio while it is being recorded"),
1248 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1249 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1252 add_option (_("Editor"),
1255 _("Show zoom toolbar"),
1256 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1257 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1260 add_option (_("Editor"),
1262 "color-regions-using-track-color",
1263 _("Color regions using their track's color"),
1264 sigc::mem_fun (*_rc_config, &RCConfiguration::get_color_regions_using_track_color),
1265 sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
1268 add_option (_("Editor"),
1270 "update-editor-during-summary-drag",
1271 _("Update editor window during drags of the summary"),
1272 sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1273 sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1276 add_option (_("Editor"),
1278 "sync-all-route-ordering",
1279 _("Synchronise editor and mixer track order"),
1280 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
1281 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
1284 add_option (_("Editor"),
1286 "link-editor-and-mixer-selection",
1287 _("Synchronise editor and mixer selection"),
1288 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1289 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1292 add_option (_("Editor"),
1295 _("Name new markers"),
1296 sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1297 sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1300 add_option (_("Editor"),
1302 "autoscroll-editor",
1303 _("Auto-scroll editor window when dragging near its edges"),
1304 sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1305 sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1310 add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1312 add_option (_("Audio"), new BufferingOptions (_rc_config));
1314 add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1316 add_option (_("Audio"),
1319 _("Use a monitor bus (allows AFL/PFL and more control)"),
1320 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_monitor_bus),
1321 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_monitor_bus)
1324 ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1326 _("Record monitoring handled by"),
1327 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1328 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1332 /* no JACK monitoring on CoreAudio */
1333 if (AudioEngine::instance()->can_request_hardware_monitoring()) {
1334 mm->add (HardwareMonitoring, _("JACK"));
1337 mm->add (SoftwareMonitoring, _("ardour"));
1338 mm->add (ExternalMonitoring, _("audio hardware"));
1340 add_option (_("Audio"), mm);
1342 add_option (_("Audio"),
1344 "tape-machine-mode",
1345 _("Tape machine mode"),
1346 sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1347 sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1350 add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1352 add_option (_("Audio"),
1354 "auto-connect-standard-busses",
1355 _("Auto-connect master/monitor busses"),
1356 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1357 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1360 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1361 "input-auto-connect",
1362 _("Connect track inputs"),
1363 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1364 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1367 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1368 iac->add (ManualConnect, _("manually"));
1370 add_option (_("Audio"), iac);
1372 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1373 "output-auto-connect",
1374 _("Connect track and bus outputs"),
1375 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1376 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1379 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1380 oac->add (AutoConnectMaster, _("automatically to master bus"));
1381 oac->add (ManualConnect, _("manually"));
1383 add_option (_("Audio"), oac);
1385 add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1387 add_option (_("Audio"),
1389 "denormal-protection",
1390 _("Use DC bias to protect against denormals"),
1391 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1392 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1395 ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1397 _("Processor handling"),
1398 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1399 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1402 dm->add (DenormalNone, _("no processor handling"));
1406 if (fpu.has_flush_to_zero()) {
1407 dm->add (DenormalFTZ, _("use FlushToZero"));
1410 if (fpu.has_denormals_are_zero()) {
1411 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1414 if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1415 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1418 add_option (_("Audio"), dm);
1420 add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1422 add_option (_("Audio"),
1424 "plugins-stop-with-transport",
1425 _("Silence plugins when the transport is stopped"),
1426 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1427 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1430 add_option (_("Audio"),
1432 "do-not-record-plugins",
1433 _("Disable plugins during recording"),
1434 sigc::mem_fun (*_rc_config, &RCConfiguration::get_do_not_record_plugins),
1435 sigc::mem_fun (*_rc_config, &RCConfiguration::set_do_not_record_plugins)
1438 add_option (_("Audio"),
1440 "new-plugins-active",
1441 _("Make new plugins active"),
1442 sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1443 sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1446 add_option (_("Audio"),
1448 "auto-analyse-audio",
1449 _("Enable automatic analysis of audio"),
1450 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1451 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1454 add_option (_("Audio"),
1456 "replicate-missing-region-channels",
1457 _("Replicate missing region channels"),
1458 sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1459 sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1464 add_option (_("Solo / mute"),
1467 _("Solo-in-place mute cut (dB)"),
1468 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1469 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1472 _solo_control_is_listen_control = new BoolOption (
1473 "solo-control-is-listen-control",
1474 _("Solo controls are Listen controls"),
1475 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1476 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1479 add_option (_("Solo / mute"), _solo_control_is_listen_control);
1481 _listen_position = new ComboOption<ListenPosition> (
1483 _("Listen Position"),
1484 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1485 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1488 _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1489 _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1491 add_option (_("Solo / mute"), _listen_position);
1493 ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1495 _("PFL signals come from"),
1496 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1497 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1500 pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1501 pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1503 add_option (_("Solo / mute"), pp);
1505 ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1507 _("AFL signals come from"),
1508 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1509 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1512 pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1513 pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1515 add_option (_("Solo / mute"), pa);
1517 parameter_changed ("use-monitor-bus");
1519 add_option (_("Solo / mute"),
1522 _("Exclusive solo"),
1523 sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1524 sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1527 add_option (_("Solo / mute"),
1530 _("Show solo muting"),
1531 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1532 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1535 add_option (_("Solo / mute"),
1537 "solo-mute-override",
1538 _("Soloing overrides muting"),
1539 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1540 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1543 add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1545 add_option (_("Solo / mute"),
1547 "mute-affects-pre-fader",
1548 _("Mute affects pre-fader sends"),
1549 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1550 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1553 add_option (_("Solo / mute"),
1555 "mute-affects-post-fader",
1556 _("Mute affects post-fader sends"),
1557 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1558 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1561 add_option (_("Solo / mute"),
1563 "mute-affects-control-outs",
1564 _("Mute affects control outputs"),
1565 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1566 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1569 add_option (_("Solo / mute"),
1571 "mute-affects-main-outs",
1572 _("Mute affects main outputs"),
1573 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1574 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1577 add_option (_("MIDI"),
1580 _("Send MIDI Clock"),
1581 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1582 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1585 add_option (_("MIDI"),
1588 _("Send MIDI Time Code"),
1589 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1590 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1593 add_option (_("MIDI"),
1594 new SpinOption<int> (
1595 "mtc-qf-speed-tolerance",
1596 _("Percentage either side of normal transport speed to transmit MTC"),
1597 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1598 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1602 add_option (_("MIDI"),
1605 _("Obey MIDI Machine Control commands"),
1606 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1607 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1610 add_option (_("MIDI"),
1613 _("Send MIDI Machine Control commands"),
1614 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1615 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1618 add_option (_("MIDI"),
1621 _("Send MIDI control feedback"),
1622 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1623 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1626 add_option (_("MIDI"),
1627 new SpinOption<uint8_t> (
1628 "mmc-receive-device-id",
1629 _("Inbound MMC device ID"),
1630 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1631 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1635 add_option (_("MIDI"),
1636 new SpinOption<uint8_t> (
1637 "mmc-send-device-id",
1638 _("Outbound MMC device ID"),
1639 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1640 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1644 add_option (_("MIDI"),
1645 new SpinOption<int32_t> (
1646 "initial-program-change",
1647 _("Initial program change"),
1648 sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1649 sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1653 add_option (_("MIDI"),
1655 "diplay-first-midi-bank-as-zero",
1656 _("Display first MIDI bank/program as 0"),
1657 sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1658 sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1661 add_option (_("MIDI"),
1663 "never-display-periodic-midi",
1664 _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1665 sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1666 sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1669 add_option (_("MIDI"),
1672 _("Sound MIDI notes as they are selected"),
1673 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1674 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1677 /* USER INTERACTION */
1679 add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1681 add_option (_("User interaction"), new KeyboardOptions);
1683 add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
1685 add_option (_("User interaction"), new ControlSurfacesOptions (*this));
1687 ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1689 _("Control surface remote ID"),
1690 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1691 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1694 rm->add (UserOrdered, _("assigned by user"));
1695 rm->add (MixerOrdered, _("follows order of mixer"));
1696 rm->add (EditorOrdered, _("follows order of editor"));
1698 add_option (_("User interaction"), rm);
1702 add_option (S_("GUI"),
1705 _("Graphically indicate mouse pointer hovering over various widgets"),
1706 sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
1707 sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
1711 /* font scaling does nothing with GDK/Quartz */
1712 add_option (S_("GUI"), new FontScalingOptions (_rc_config));
1714 add_option (S_("GUI"),
1716 "use-own-plugin-gui",
1717 _("Use plugins' own interfaces instead of Ardour's"),
1718 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
1719 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
1722 /* The names of these controls must be the same as those given in MixerStrip
1723 for the actual widgets being controlled.
1725 _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
1726 _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
1727 _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
1728 _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
1729 _mixer_strip_visibility.add (0, X_("Group"), _("Group"));
1730 _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
1734 new VisibilityOption (
1736 &_mixer_strip_visibility,
1737 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
1738 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
1742 add_option (S_("GUI"),
1744 "default-narrow_ms",
1745 _("Use narrow strips in the mixer by default"),
1746 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
1747 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
1750 add_option (S_("GUI"), new OptionEditorHeading (_("Metering")));
1752 ComboOption<float>* mht = new ComboOption<float> (
1754 _("Meter hold time"),
1755 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
1756 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
1759 mht->add (MeterHoldOff, _("off"));
1760 mht->add (MeterHoldShort, _("short"));
1761 mht->add (MeterHoldMedium, _("medium"));
1762 mht->add (MeterHoldLong, _("long"));
1764 add_option (S_("GUI"), mht);
1766 ComboOption<float>* mfo = new ComboOption<float> (
1768 _("Meter fall-off"),
1769 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
1770 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
1773 mfo->add (METER_FALLOFF_OFF, _("off"));
1774 mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
1775 mfo->add (METER_FALLOFF_SLOW, _("slow"));
1776 mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
1777 mfo->add (METER_FALLOFF_FAST, _("fast"));
1778 mfo->add (METER_FALLOFF_FASTER, _("faster"));
1779 mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
1781 add_option (S_("GUI"), mfo);
1785 RCOptionEditor::parameter_changed (string const & p)
1787 OptionEditor::parameter_changed (p);
1789 if (p == "use-monitor-bus") {
1790 bool const s = Config->get_use_monitor_bus ();
1792 /* we can't use this if we don't have a monitor bus */
1793 Config->set_solo_control_is_listen_control (false);
1795 _solo_control_is_listen_control->set_sensitive (s);
1796 _listen_position->set_sensitive (s);
1797 } else if (p == "sync-source") {
1798 _sync_source->set_sensitive (true);
1800 _sync_source->set_sensitive (_session->config.get_external_sync());
1802 switch(Config->get_sync_source()) {
1805 _sync_genlock->set_sensitive (true);
1806 _sync_framerate->set_sensitive (true);
1807 _sync_source_2997->set_sensitive (true);
1810 _sync_genlock->set_sensitive (false);
1811 _sync_framerate->set_sensitive (false);
1812 _sync_source_2997->set_sensitive (false);
1816 } else if (p == "send-ltc") {
1817 bool const s = Config->get_send_ltc ();
1818 _ltc_send_continuously->set_sensitive (s);
1819 _ltc_volume_slider->set_sensitive (s);
1824 void RCOptionEditor::ltc_generator_volume_changed () {
1825 _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
1829 RCOptionEditor::populate_sync_options ()
1831 vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
1833 _sync_source->clear ();
1835 for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
1836 _sync_source->add (*i, sync_source_to_string (*i));