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 (_("Choose Click"));
110 if (sfdb.run () == RESPONSE_OK) {
111 click_chosen (sfdb.get_filename());
115 void click_chosen (string const & path)
117 _click_path_entry.set_text (path);
118 _rc_config->set_click_sound (path);
121 void click_changed ()
123 click_chosen (_click_path_entry.get_text ());
126 void click_emphasis_browse_clicked ()
128 SoundFileChooser sfdb (_("Choose Click Emphasis"));
133 if (sfdb.run () == RESPONSE_OK) {
134 click_emphasis_chosen (sfdb.get_filename());
138 void click_emphasis_chosen (string const & path)
140 _click_emphasis_path_entry.set_text (path);
141 _rc_config->set_click_emphasis_sound (path);
144 void click_emphasis_changed ()
146 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
149 RCConfiguration* _rc_config;
150 Gtk::Window* _parent;
151 Entry _click_path_entry;
152 Entry _click_emphasis_path_entry;
155 class UndoOptions : public OptionEditorBox
158 UndoOptions (RCConfiguration* c) :
160 _limit_undo_button (_("Limit undo history to")),
161 _save_undo_button (_("Save undo history of"))
163 Table* t = new Table (2, 3);
166 t->attach (_limit_undo_button, 0, 1, 0, 1, FILL);
167 _limit_undo_spin.set_range (0, 512);
168 _limit_undo_spin.set_increments (1, 10);
169 t->attach (_limit_undo_spin, 1, 2, 0, 1, FILL | EXPAND);
170 Label* l = manage (left_aligned_label (_("commands")));
171 t->attach (*l, 2, 3, 0, 1);
173 t->attach (_save_undo_button, 0, 1, 1, 2, FILL);
174 _save_undo_spin.set_range (0, 512);
175 _save_undo_spin.set_increments (1, 10);
176 t->attach (_save_undo_spin, 1, 2, 1, 2, FILL | EXPAND);
177 l = manage (left_aligned_label (_("commands")));
178 t->attach (*l, 2, 3, 1, 2);
180 _box->pack_start (*t);
182 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
183 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
184 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
185 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
188 void parameter_changed (string const & p)
190 if (p == "history-depth") {
191 int32_t const d = _rc_config->get_history_depth();
192 _limit_undo_button.set_active (d != 0);
193 _limit_undo_spin.set_sensitive (d != 0);
194 _limit_undo_spin.set_value (d);
195 } else if (p == "save-history") {
196 bool const x = _rc_config->get_save_history ();
197 _save_undo_button.set_active (x);
198 _save_undo_spin.set_sensitive (x);
199 } else if (p == "save-history-depth") {
200 _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
204 void set_state_from_config ()
206 parameter_changed ("save-history");
207 parameter_changed ("history-depth");
208 parameter_changed ("save-history-depth");
211 void limit_undo_toggled ()
213 bool const x = _limit_undo_button.get_active ();
214 _limit_undo_spin.set_sensitive (x);
215 int32_t const n = x ? 16 : 0;
216 _limit_undo_spin.set_value (n);
217 _rc_config->set_history_depth (n);
220 void limit_undo_changed ()
222 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
225 void save_undo_toggled ()
227 bool const x = _save_undo_button.get_active ();
228 _rc_config->set_save_history (x);
231 void save_undo_changed ()
233 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
237 RCConfiguration* _rc_config;
238 CheckButton _limit_undo_button;
239 SpinButton _limit_undo_spin;
240 CheckButton _save_undo_button;
241 SpinButton _save_undo_spin;
246 static const struct {
258 { "Key|Shift", GDK_SHIFT_MASK },
259 { "Command", GDK_META_MASK },
260 { "Control", GDK_CONTROL_MASK },
261 { "Option", GDK_MOD1_MASK },
262 { "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
263 { "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
264 { "Shift-Option", GDK_SHIFT_MASK|GDK_MOD1_MASK },
265 { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
268 { "Key|Shift", GDK_SHIFT_MASK },
269 { "Control", GDK_CONTROL_MASK },
270 { "Alt (Mod1)", GDK_MOD1_MASK },
271 { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
272 { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
273 { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
274 { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
275 { "Mod2", GDK_MOD2_MASK },
276 { "Mod3", GDK_MOD3_MASK },
277 { "Mod4", GDK_MOD4_MASK },
278 { "Mod5", GDK_MOD5_MASK },
284 class KeyboardOptions : public OptionEditorBox
288 _delete_button_adjustment (3, 1, 12),
289 _delete_button_spin (_delete_button_adjustment),
290 _edit_button_adjustment (3, 1, 5),
291 _edit_button_spin (_edit_button_adjustment),
292 _insert_note_button_adjustment (3, 1, 5),
293 _insert_note_button_spin (_insert_note_button_adjustment)
295 /* internationalize and prepare for use with combos */
298 for (int i = 0; modifiers[i].name; ++i) {
299 dumb.push_back (S_(modifiers[i].name));
302 set_popdown_strings (_edit_modifier_combo, dumb);
303 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
305 for (int x = 0; modifiers[x].name; ++x) {
306 if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
307 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
312 Table* t = manage (new Table (4, 4));
315 Label* l = manage (left_aligned_label (_("Edit using:")));
316 l->set_name ("OptionsLabel");
318 t->attach (*l, 0, 1, 0, 1, FILL | EXPAND, FILL);
319 t->attach (_edit_modifier_combo, 1, 2, 0, 1, FILL | EXPAND, FILL);
321 l = manage (new Label (_("+ button")));
322 l->set_name ("OptionsLabel");
324 t->attach (*l, 3, 4, 0, 1, FILL | EXPAND, FILL);
325 t->attach (_edit_button_spin, 4, 5, 0, 1, FILL | EXPAND, FILL);
327 _edit_button_spin.set_name ("OptionsEntry");
328 _edit_button_adjustment.set_value (Keyboard::edit_button());
329 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
331 set_popdown_strings (_delete_modifier_combo, dumb);
332 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
334 for (int x = 0; modifiers[x].name; ++x) {
335 if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
336 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
341 l = manage (left_aligned_label (_("Delete using:")));
342 l->set_name ("OptionsLabel");
344 t->attach (*l, 0, 1, 1, 2, FILL | EXPAND, FILL);
345 t->attach (_delete_modifier_combo, 1, 2, 1, 2, FILL | EXPAND, FILL);
347 l = manage (new Label (_("+ button")));
348 l->set_name ("OptionsLabel");
350 t->attach (*l, 3, 4, 1, 2, FILL | EXPAND, FILL);
351 t->attach (_delete_button_spin, 4, 5, 1, 2, FILL | EXPAND, FILL);
353 _delete_button_spin.set_name ("OptionsEntry");
354 _delete_button_adjustment.set_value (Keyboard::delete_button());
355 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
358 set_popdown_strings (_insert_note_modifier_combo, dumb);
359 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
361 for (int x = 0; modifiers[x].name; ++x) {
362 if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
363 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
368 l = manage (left_aligned_label (_("Insert note using:")));
369 l->set_name ("OptionsLabel");
371 t->attach (*l, 0, 1, 2, 3, FILL | EXPAND, FILL);
372 t->attach (_insert_note_modifier_combo, 1, 2, 2, 3, FILL | EXPAND, FILL);
374 l = manage (new Label (_("+ button")));
375 l->set_name ("OptionsLabel");
377 t->attach (*l, 3, 4, 2, 3, FILL | EXPAND, FILL);
378 t->attach (_insert_note_button_spin, 4, 5, 2, 3, FILL | EXPAND, FILL);
380 _insert_note_button_spin.set_name ("OptionsEntry");
381 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
382 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
385 set_popdown_strings (_snap_modifier_combo, dumb);
386 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
388 for (int x = 0; modifiers[x].name; ++x) {
389 if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
390 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
395 l = manage (left_aligned_label (_("Ignore snap using:")));
396 l->set_name ("OptionsLabel");
398 t->attach (*l, 0, 1, 3, 4, FILL | EXPAND, FILL);
399 t->attach (_snap_modifier_combo, 1, 2, 3, 4, FILL | EXPAND, FILL);
403 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
404 strs.push_back (bf->first);
407 set_popdown_strings (_keyboard_layout_selector, strs);
408 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
409 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
411 l = manage (left_aligned_label (_("Keyboard layout:")));
412 l->set_name ("OptionsLabel");
414 t->attach (*l, 0, 1, 4, 5, FILL | EXPAND, FILL);
415 t->attach (_keyboard_layout_selector, 1, 2, 4, 5, FILL | EXPAND, FILL);
417 _box->pack_start (*t, false, false);
420 void parameter_changed (string const &)
422 /* XXX: these aren't really config options... */
425 void set_state_from_config ()
427 /* XXX: these aren't really config options... */
432 void bindings_changed ()
434 string const txt = _keyboard_layout_selector.get_active_text();
436 /* XXX: config...? for all this keyboard stuff */
438 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
439 if (txt == i->first) {
440 if (Keyboard::load_keybindings (i->second)) {
441 Keyboard::save_keybindings ();
447 void edit_modifier_chosen ()
449 string const txt = _edit_modifier_combo.get_active_text();
451 for (int i = 0; modifiers[i].name; ++i) {
452 if (txt == _(modifiers[i].name)) {
453 Keyboard::set_edit_modifier (modifiers[i].modifier);
459 void delete_modifier_chosen ()
461 string const txt = _delete_modifier_combo.get_active_text();
463 for (int i = 0; modifiers[i].name; ++i) {
464 if (txt == _(modifiers[i].name)) {
465 Keyboard::set_delete_modifier (modifiers[i].modifier);
471 void insert_note_modifier_chosen ()
473 string const txt = _insert_note_modifier_combo.get_active_text();
475 for (int i = 0; modifiers[i].name; ++i) {
476 if (txt == _(modifiers[i].name)) {
477 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
483 void snap_modifier_chosen ()
485 string const txt = _snap_modifier_combo.get_active_text();
487 for (int i = 0; modifiers[i].name; ++i) {
488 if (txt == _(modifiers[i].name)) {
489 Keyboard::set_snap_modifier (modifiers[i].modifier);
495 void delete_button_changed ()
497 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
500 void edit_button_changed ()
502 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
505 void insert_note_button_changed ()
507 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
510 ComboBoxText _keyboard_layout_selector;
511 ComboBoxText _edit_modifier_combo;
512 ComboBoxText _delete_modifier_combo;
513 ComboBoxText _insert_note_modifier_combo;
514 ComboBoxText _snap_modifier_combo;
515 Adjustment _delete_button_adjustment;
516 SpinButton _delete_button_spin;
517 Adjustment _edit_button_adjustment;
518 SpinButton _edit_button_spin;
519 Adjustment _insert_note_button_adjustment;
520 SpinButton _insert_note_button_spin;
524 class FontScalingOptions : public OptionEditorBox
527 FontScalingOptions (RCConfiguration* c) :
529 _dpi_adjustment (50, 50, 250, 1, 10),
530 _dpi_slider (_dpi_adjustment)
532 _dpi_adjustment.set_value (floor (_rc_config->get_font_scale () / 1024));
534 Label* l = manage (new Label (_("Font scaling:")));
535 l->set_name ("OptionsLabel");
537 _dpi_slider.set_update_policy (UPDATE_DISCONTINUOUS);
538 HBox* h = manage (new HBox);
540 h->pack_start (*l, false, false);
541 h->pack_start (_dpi_slider, true, true);
543 _box->pack_start (*h, false, false);
545 _dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
548 void parameter_changed (string const & p)
550 if (p == "font-scale") {
551 _dpi_adjustment.set_value (floor (_rc_config->get_font_scale() / 1024));
555 void set_state_from_config ()
557 parameter_changed ("font-scale");
564 _rc_config->set_font_scale ((long) floor (_dpi_adjustment.get_value() * 1024));
565 /* XXX: should be triggered from the parameter changed signal */
569 RCConfiguration* _rc_config;
570 Adjustment _dpi_adjustment;
574 class BufferingOptions : public OptionEditorBox
577 BufferingOptions (RCConfiguration* c)
579 , _playback_adjustment (5, 1, 60, 1, 4)
580 , _capture_adjustment (5, 1, 60, 1, 4)
581 , _playback_slider (_playback_adjustment)
582 , _capture_slider (_capture_adjustment)
584 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
586 Label* l = manage (new Label (_("Playback (seconds of buffering):")));
587 l->set_name ("OptionsLabel");
589 _playback_slider.set_update_policy (UPDATE_DISCONTINUOUS);
590 HBox* h = manage (new HBox);
592 h->pack_start (*l, false, false);
593 h->pack_start (_playback_slider, true, true);
595 _box->pack_start (*h, false, false);
597 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
599 l = manage (new Label (_("Recording (seconds of buffering):")));
600 l->set_name ("OptionsLabel");
602 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
603 h = manage (new HBox);
605 h->pack_start (*l, false, false);
606 h->pack_start (_capture_slider, true, true);
608 _box->pack_start (*h, false, false);
610 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
611 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
614 void parameter_changed (string const & p)
616 if (p == "playback-buffer-seconds") {
617 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
618 } else if (p == "capture-buffer-seconds") {
619 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
623 void set_state_from_config ()
625 parameter_changed ("playback-buffer-seconds");
626 parameter_changed ("capture-buffer-seconds");
631 void playback_changed ()
633 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
636 void capture_changed ()
638 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
641 RCConfiguration* _rc_config;
642 Adjustment _playback_adjustment;
643 Adjustment _capture_adjustment;
644 HScale _playback_slider;
645 HScale _capture_slider;
648 class ControlSurfacesOptions : public OptionEditorBox
651 ControlSurfacesOptions (Gtk::Window& parent)
654 _store = ListStore::create (_model);
655 _view.set_model (_store);
656 _view.append_column (_("Name"), _model.name);
657 _view.get_column(0)->set_resizable (true);
658 _view.get_column(0)->set_expand (true);
659 _view.append_column_editable (_("Enabled"), _model.enabled);
660 _view.append_column_editable (_("Feedback"), _model.feedback);
662 _box->pack_start (_view, false, false);
664 Label* label = manage (new Label);
665 label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
667 _box->pack_start (*label, false, false);
670 ControlProtocolManager& m = ControlProtocolManager::instance ();
671 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
672 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
674 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
675 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
678 void parameter_changed (std::string const &)
683 void set_state_from_config ()
687 ControlProtocolManager& m = ControlProtocolManager::instance ();
688 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
690 if (!(*i)->mandatory) {
691 TreeModel::Row r = *_store->append ();
692 r[_model.name] = (*i)->name;
693 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
694 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
695 r[_model.protocol_info] = *i;
702 void protocol_status_changed (ControlProtocolInfo* cpi) {
704 TreeModel::Children rows = _store->children();
705 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
706 if ((*x)[_model.protocol_info] == cpi) {
707 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
713 void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
715 TreeModel::Row r = *i;
717 ControlProtocolInfo* cpi = r[_model.protocol_info];
722 bool const was_enabled = (cpi->protocol != 0);
723 bool const is_enabled = r[_model.enabled];
725 if (was_enabled != is_enabled) {
727 ControlProtocolManager::instance().instantiate (*cpi);
729 Gtk::Window* win = r[_model.editor];
734 ControlProtocolManager::instance().teardown (*cpi);
739 r[_model.editor] = 0;
740 cpi->requested = false;
744 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
745 bool const is_feedback = r[_model.feedback];
747 if (was_feedback != is_feedback && cpi->protocol) {
748 cpi->protocol->set_feedback (is_feedback);
752 void edit_clicked (GdkEventButton* ev)
754 if (ev->type != GDK_2BUTTON_PRESS) {
759 ControlProtocolInfo* cpi;
762 row = *(_view.get_selection()->get_selected());
764 Window* win = row[_model.editor];
765 if (win && !win->is_visible()) {
768 cpi = row[_model.protocol_info];
770 if (cpi && cpi->protocol && cpi->protocol->has_editor ()) {
771 Box* box = (Box*) cpi->protocol->get_gui ();
773 string title = row[_model.name];
774 ArdourWindow* win = new ArdourWindow (_parent, title);
775 win->set_title ("Control Protocol Options");
779 row[_model.editor] = win;
785 class ControlSurfacesModelColumns : public TreeModelColumnRecord
789 ControlSurfacesModelColumns ()
798 TreeModelColumn<string> name;
799 TreeModelColumn<bool> enabled;
800 TreeModelColumn<bool> feedback;
801 TreeModelColumn<ControlProtocolInfo*> protocol_info;
802 TreeModelColumn<Gtk::Window*> editor;
805 Glib::RefPtr<ListStore> _store;
806 ControlSurfacesModelColumns _model;
808 Gtk::Window& _parent;
809 PBD::ScopedConnection protocol_status_connection;
812 /** A class which allows control of visibility of some editor components usign
813 * a VisibilityGroup. The caller should pass in a `dummy' VisibilityGroup
814 * which has the correct members, but with null widget pointers. This
815 * class allows the user to set visibility of the members, the details
816 * of which are stored in a configuration variable which can be watched
817 * by parts of the editor that actually contain the widgets whose visibility
818 * is being controlled.
821 class VisibilityOption : public Option
824 /** @param name User-visible name for this group.
825 * @param g `Dummy' VisibilityGroup (as described above).
826 * @param get Method to get the value of the appropriate configuration variable.
827 * @param set Method to set the value of the appropriate configuration variable.
829 VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
830 : Option (g->get_state_name(), name)
832 , _visibility_group (g)
836 /* Watch for changes made by the user to our members */
837 _visibility_group->VisibilityChanged.connect_same_thread (
838 _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
842 void set_state_from_config ()
844 /* Set our state from the current configuration */
845 _visibility_group->set_state (_get ());
848 void add_to_page (OptionEditorPage* p)
850 _heading.add_to_page (p);
851 add_widget_to_page (p, _visibility_group->list_view ());
854 Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
859 /* The user has changed something, so reflect this change
860 in the RCConfiguration.
862 _set (_visibility_group->get_state_value ());
865 OptionEditorHeading _heading;
866 VisibilityGroup* _visibility_group;
867 sigc::slot<std::string> _get;
868 sigc::slot<bool, std::string> _set;
869 PBD::ScopedConnection _visibility_group_connection;
873 RCOptionEditor::RCOptionEditor ()
874 : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
875 , _rc_config (Config)
876 , _mixer_strip_visibility ("mixer-strip-visibility")
880 uint32_t hwcpus = hardware_concurrency ();
884 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
886 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
888 _("Signal processing uses"),
889 sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
890 sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
893 procs->add (-1, _("all but one processor"));
894 procs->add (0, _("all available processors"));
896 for (uint32_t i = 1; i <= hwcpus; ++i) {
897 procs->add (i, string_compose (_("%1 processors"), i));
900 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
902 add_option (_("Misc"), procs);
905 add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
907 add_option (_("Misc"), new UndoOptions (_rc_config));
909 add_option (_("Misc"),
911 "verify-remove-last-capture",
912 _("Verify removal of last capture"),
913 sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
914 sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
917 add_option (_("Misc"),
919 "periodic-safety-backups",
920 _("Make periodic backups of the session file"),
921 sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
922 sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
925 add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
927 add_option (_("Misc"),
929 "only-copy-imported-files",
930 _("Always copy imported files"),
931 sigc::mem_fun (*_rc_config, &RCConfiguration::get_only_copy_imported_files),
932 sigc::mem_fun (*_rc_config, &RCConfiguration::set_only_copy_imported_files)
935 add_option (_("Misc"), new DirectoryOption (
936 X_("default-session-parent-dir"),
937 _("Default folder for new sessions:"),
938 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
939 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
942 add_option (_("Misc"),
943 new SpinOption<uint32_t> (
944 "max-recent-sessions",
945 _("Maximum number of recent sessions"),
946 sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
947 sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
951 add_option (_("Misc"), new OptionEditorHeading (_("Click")));
953 add_option (_("Misc"), new ClickOptions (_rc_config, this));
955 add_option (_("Misc"),
958 _("Click gain level"),
959 sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
960 sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
963 add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
965 add_option (_("Misc"),
966 new SpinOption<double> (
967 "automation-thinning-factor",
968 _("Thinning factor (larger value => less data)"),
969 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
970 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
974 add_option (_("Misc"),
975 new SpinOption<double> (
976 "automation-interval-msecs",
977 _("Automation sampling interval (milliseconds)"),
978 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
979 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
987 tsf = new BoolOption (
988 "latched-record-enable",
989 _("Keep record-enable engaged on stop"),
990 sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
991 sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
993 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
994 add_option (_("Transport"), tsf);
996 tsf = new BoolOption (
997 "stop-recording-on-xrun",
998 _("Stop recording when an xrun occurs"),
999 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1000 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1002 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"));
1003 add_option (_("Transport"), tsf);
1005 tsf = new BoolOption (
1006 "create-xrun-marker",
1007 _("Create markers where xruns occur"),
1008 sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1009 sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1011 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1012 add_option (_("Transport"), tsf);
1014 tsf = new BoolOption (
1015 "stop-at-session-end",
1016 _("Stop at the end of the session"),
1017 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1018 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1020 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("<b>When enabled</b> if Ardour is <b>not recording</b>, it will stop the transport "
1021 "when it reaches the current session end marker\n\n"
1022 "<b>When disabled</b> Ardour will continue to roll past the session end marker at all times"));
1023 add_option (_("Transport"), tsf);
1025 tsf = new BoolOption (
1027 _("Do seamless looping (not possible when slaved to MTC, JACK etc)"),
1028 sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1029 sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1031 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, "
1032 "preventing any need to do a transport locate at the end of the loop\n\n"
1033 "<b>When disabled</b> looping is done by locating back to the start of the loop when Ardour reaches the end "
1034 "which will often cause a small click or delay"));
1035 add_option (_("Transport"), tsf);
1037 tsf = new BoolOption (
1038 "disable-disarm-during-roll",
1039 _("Disable per-track record disarm while rolling"),
1040 sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
1041 sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
1043 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"));
1044 add_option (_("Transport"), tsf);
1046 tsf = new BoolOption (
1048 _("12dB gain reduction during fast-forward and fast-rewind"),
1049 sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
1050 sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
1052 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
1053 "that occurs when fast-forwarding or rewinding through some kinds of audio"));
1054 add_option (_("Transport"), tsf);
1056 add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
1058 _sync_source = new ComboOption<SyncSource> (
1060 _("External timecode source"),
1061 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
1062 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
1065 populate_sync_options ();
1066 add_option (_("Transport"), _sync_source);
1068 _sync_framerate = new BoolOption (
1069 "timecode-sync-frame-rate",
1070 _("Match session video frame rate to external timecode"),
1071 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
1072 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
1074 Gtkmm2ext::UI::instance()->set_tip
1075 (_sync_framerate->tip_widget(),
1076 _("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
1077 "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
1078 "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
1079 "Instead the frame rate indication in the main clock will flash red and Ardour will convert between the external "
1080 "timecode standard and the session standard."));
1082 add_option (_("Transport"), _sync_framerate);
1084 _sync_genlock = new BoolOption (
1085 "timecode-source-is-synced",
1086 _("External timecode is sync locked"),
1087 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
1088 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
1090 Gtkmm2ext::UI::instance()->set_tip
1091 (_sync_genlock->tip_widget(),
1092 _("<b>When enabled</b> indicates that the selected external timecode source shares sync (Black & Burst, Wordclock, etc) with the audio interface."));
1095 add_option (_("Transport"), _sync_genlock);
1097 _sync_source_2997 = new BoolOption (
1098 "timecode-source-2997",
1099 _("Lock to 29.9700 fps instead of 30000/1001"),
1100 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
1101 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
1103 Gtkmm2ext::UI::instance()->set_tip
1104 (_sync_source_2997->tip_widget(),
1105 _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
1106 "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
1107 "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
1108 "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
1109 "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
1110 "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
1113 add_option (_("Transport"), _sync_source_2997);
1115 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
1117 _ltc_port = new ComboStringOption (
1119 _("LTC incoming port"),
1120 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
1121 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
1124 vector<string> physical_inputs;
1125 physical_inputs.push_back (_("None"));
1126 AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
1127 _ltc_port->set_popdown_strings (physical_inputs);
1129 add_option (_("Transport"), _ltc_port);
1131 // TODO; rather disable this button than not compile it..
1132 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
1134 add_option (_("Transport"),
1137 _("Enable LTC generator"),
1138 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
1139 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
1142 _ltc_send_continuously = new BoolOption (
1143 "ltc-send-continuously",
1144 _("send LTC while stopped"),
1145 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
1146 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
1148 Gtkmm2ext::UI::instance()->set_tip
1149 (_ltc_send_continuously->tip_widget(),
1150 _("<b>When enabled</b> Ardour will continue to send LTC information even when the transport (playhead) is not moving"));
1151 add_option (_("Transport"), _ltc_send_continuously);
1153 _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
1154 _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
1155 _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
1156 _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
1158 Gtkmm2ext::UI::instance()->set_tip
1159 (_ltc_volume_slider->tip_widget(),
1160 _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is 0dBu ^= -18dbFS in an EBU calibrated system"));
1162 add_option (_("Transport"), _ltc_volume_slider);
1163 parameter_changed ("send-ltc");
1165 parameter_changed ("sync-source");
1169 add_option (_("Editor"),
1171 "link-region-and-track-selection",
1172 _("Link selection of regions and tracks"),
1173 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_region_and_track_selection),
1174 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_region_and_track_selection)
1177 add_option (_("Editor"),
1179 "automation-follows-regions",
1180 _("Move relevant automation when audio regions are moved"),
1181 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
1182 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
1185 add_option (_("Editor"),
1187 "show-track-meters",
1188 _("Show meters on tracks in the editor"),
1189 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_track_meters),
1190 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_track_meters)
1193 bo = new BoolOption (
1194 "use-overlap-equivalency",
1195 _("Use overlap equivalency for regions"),
1196 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
1197 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
1200 add_option (_("Editor"), bo);
1201 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
1202 string_compose (_("When extending region selection across a group, %1 must decide which regions are equivalent"
1203 "\n\nIf enabled, regions are considered \"equivalent\" if they overlap on the timeline."
1204 "\n\nIf disabled, regions are considered \"equivalent\" only if have the same start time, length and position"),
1207 add_option (_("Editor"),
1209 "rubberbanding-snaps-to-grid",
1210 _("Make rubberband selection rectangle snap to the grid"),
1211 sigc::mem_fun (*_rc_config, &RCConfiguration::get_rubberbanding_snaps_to_grid),
1212 sigc::mem_fun (*_rc_config, &RCConfiguration::set_rubberbanding_snaps_to_grid)
1215 add_option (_("Editor"),
1218 _("Show waveforms in regions"),
1219 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms),
1220 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms)
1223 add_option (_("Editor"),
1224 new BoolComboOption (
1225 "show-region-gain-envelopes",
1226 _("Show gain envelopes in audio regions"),
1228 _("only in region gain mode"),
1229 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_region_gain),
1230 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_region_gain)
1233 ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
1235 _("Waveform scale"),
1236 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_scale),
1237 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_scale)
1240 wfs->add (Linear, _("linear"));
1241 wfs->add (Logarithmic, _("logarithmic"));
1243 add_option (_("Editor"), wfs);
1245 ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
1247 _("Waveform shape"),
1248 sigc::mem_fun (*_rc_config, &RCConfiguration::get_waveform_shape),
1249 sigc::mem_fun (*_rc_config, &RCConfiguration::set_waveform_shape)
1252 wfsh->add (Traditional, _("traditional"));
1253 wfsh->add (Rectified, _("rectified"));
1255 add_option (_("Editor"), wfsh);
1257 add_option (_("Editor"),
1259 "show-waveforms-while-recording",
1260 _("Show waveforms for audio while it is being recorded"),
1261 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_waveforms_while_recording),
1262 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_waveforms_while_recording)
1265 add_option (_("Editor"),
1268 _("Show zoom toolbar"),
1269 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_zoom_tools),
1270 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_zoom_tools)
1273 add_option (_("Editor"),
1275 "color-regions-using-track-color",
1276 _("Color regions using their track's color"),
1277 sigc::mem_fun (*_rc_config, &RCConfiguration::get_color_regions_using_track_color),
1278 sigc::mem_fun (*_rc_config, &RCConfiguration::set_color_regions_using_track_color)
1281 add_option (_("Editor"),
1283 "update-editor-during-summary-drag",
1284 _("Update editor window during drags of the summary"),
1285 sigc::mem_fun (*_rc_config, &RCConfiguration::get_update_editor_during_summary_drag),
1286 sigc::mem_fun (*_rc_config, &RCConfiguration::set_update_editor_during_summary_drag)
1289 add_option (_("Editor"),
1291 "sync-all-route-ordering",
1292 _("Synchronise editor and mixer track order"),
1293 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_all_route_ordering),
1294 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_all_route_ordering)
1297 add_option (_("Editor"),
1299 "link-editor-and-mixer-selection",
1300 _("Synchronise editor and mixer selection"),
1301 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_editor_and_mixer_selection),
1302 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_editor_and_mixer_selection)
1305 bo = new BoolOption (
1307 _("Name new markers"),
1308 sigc::mem_fun (*_rc_config, &RCConfiguration::get_name_new_markers),
1309 sigc::mem_fun (*_rc_config, &RCConfiguration::set_name_new_markers)
1312 add_option (_("Editor"), bo);
1313 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("If enabled, popup a dialog when a new marker is created to allow its name to be set as it is created."
1314 "\n\nYou can always rename markers by right-clicking on them"));
1316 add_option (_("Editor"),
1318 "autoscroll-editor",
1319 _("Auto-scroll editor window when dragging near its edges"),
1320 sigc::mem_fun (*_rc_config, &RCConfiguration::get_autoscroll_editor),
1321 sigc::mem_fun (*_rc_config, &RCConfiguration::set_autoscroll_editor)
1326 add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
1328 add_option (_("Audio"), new BufferingOptions (_rc_config));
1330 add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
1332 add_option (_("Audio"),
1335 _("Use a monitor bus (allows AFL/PFL and more control)"),
1336 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_monitor_bus),
1337 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_monitor_bus)
1340 ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
1342 _("Record monitoring handled by"),
1343 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
1344 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
1348 /* no JACK monitoring on CoreAudio */
1349 if (AudioEngine::instance()->can_request_hardware_monitoring()) {
1350 mm->add (HardwareMonitoring, _("JACK"));
1353 mm->add (SoftwareMonitoring, _("ardour"));
1354 mm->add (ExternalMonitoring, _("audio hardware"));
1356 add_option (_("Audio"), mm);
1358 add_option (_("Audio"),
1360 "tape-machine-mode",
1361 _("Tape machine mode"),
1362 sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
1363 sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
1366 add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
1368 add_option (_("Audio"),
1370 "auto-connect-standard-busses",
1371 _("Auto-connect master/monitor busses"),
1372 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
1373 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
1376 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
1377 "input-auto-connect",
1378 _("Connect track inputs"),
1379 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
1380 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
1383 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
1384 iac->add (ManualConnect, _("manually"));
1386 add_option (_("Audio"), iac);
1388 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
1389 "output-auto-connect",
1390 _("Connect track and bus outputs"),
1391 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
1392 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
1395 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
1396 oac->add (AutoConnectMaster, _("automatically to master bus"));
1397 oac->add (ManualConnect, _("manually"));
1399 add_option (_("Audio"), oac);
1401 add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
1403 add_option (_("Audio"),
1405 "denormal-protection",
1406 _("Use DC bias to protect against denormals"),
1407 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
1408 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
1411 ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
1413 _("Processor handling"),
1414 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
1415 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
1418 dm->add (DenormalNone, _("no processor handling"));
1422 if (fpu.has_flush_to_zero()) {
1423 dm->add (DenormalFTZ, _("use FlushToZero"));
1426 if (fpu.has_denormals_are_zero()) {
1427 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
1430 if (fpu.has_flush_to_zero() && fpu.has_denormals_are_zero()) {
1431 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
1434 add_option (_("Audio"), dm);
1436 add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
1438 add_option (_("Audio"),
1440 "plugins-stop-with-transport",
1441 _("Silence plugins when the transport is stopped"),
1442 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
1443 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
1446 add_option (_("Audio"),
1448 "new-plugins-active",
1449 _("Make new plugins active"),
1450 sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
1451 sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
1454 add_option (_("Audio"),
1456 "auto-analyse-audio",
1457 _("Enable automatic analysis of audio"),
1458 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
1459 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
1462 add_option (_("Audio"),
1464 "replicate-missing-region-channels",
1465 _("Replicate missing region channels"),
1466 sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
1467 sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
1472 add_option (_("Solo / mute"),
1475 _("Solo-in-place mute cut (dB)"),
1476 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
1477 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
1480 _solo_control_is_listen_control = new BoolOption (
1481 "solo-control-is-listen-control",
1482 _("Solo controls are Listen controls"),
1483 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
1484 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
1487 add_option (_("Solo / mute"), _solo_control_is_listen_control);
1489 _listen_position = new ComboOption<ListenPosition> (
1491 _("Listen Position"),
1492 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
1493 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
1496 _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
1497 _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
1499 add_option (_("Solo / mute"), _listen_position);
1501 ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
1503 _("PFL signals come from"),
1504 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
1505 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
1508 pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
1509 pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
1511 add_option (_("Solo / mute"), pp);
1513 ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
1515 _("AFL signals come from"),
1516 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
1517 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
1520 pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
1521 pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
1523 add_option (_("Solo / mute"), pa);
1525 parameter_changed ("use-monitor-bus");
1527 add_option (_("Solo / mute"),
1530 _("Exclusive solo"),
1531 sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
1532 sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
1535 add_option (_("Solo / mute"),
1538 _("Show solo muting"),
1539 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
1540 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
1543 add_option (_("Solo / mute"),
1545 "solo-mute-override",
1546 _("Soloing overrides muting"),
1547 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
1548 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
1551 add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
1553 add_option (_("Solo / mute"),
1555 "mute-affects-pre-fader",
1556 _("Mute affects pre-fader sends"),
1557 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
1558 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
1561 add_option (_("Solo / mute"),
1563 "mute-affects-post-fader",
1564 _("Mute affects post-fader sends"),
1565 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
1566 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
1569 add_option (_("Solo / mute"),
1571 "mute-affects-control-outs",
1572 _("Mute affects control outputs"),
1573 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
1574 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
1577 add_option (_("Solo / mute"),
1579 "mute-affects-main-outs",
1580 _("Mute affects main outputs"),
1581 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
1582 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
1585 add_option (_("MIDI"),
1588 _("Send MIDI Clock"),
1589 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
1590 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
1593 add_option (_("MIDI"),
1596 _("Send MIDI Time Code"),
1597 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
1598 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
1601 add_option (_("MIDI"),
1602 new SpinOption<int> (
1603 "mtc-qf-speed-tolerance",
1604 _("Percentage either side of normal transport speed to transmit MTC"),
1605 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
1606 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
1610 add_option (_("MIDI"),
1613 _("Obey MIDI Machine Control commands"),
1614 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
1615 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
1618 add_option (_("MIDI"),
1621 _("Send MIDI Machine Control commands"),
1622 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
1623 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
1626 add_option (_("MIDI"),
1629 _("Send MIDI control feedback"),
1630 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
1631 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
1634 add_option (_("MIDI"),
1635 new SpinOption<uint8_t> (
1636 "mmc-receive-device-id",
1637 _("Inbound MMC device ID"),
1638 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
1639 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
1643 add_option (_("MIDI"),
1644 new SpinOption<uint8_t> (
1645 "mmc-send-device-id",
1646 _("Outbound MMC device ID"),
1647 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
1648 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
1652 add_option (_("MIDI"),
1653 new SpinOption<int32_t> (
1654 "initial-program-change",
1655 _("Initial program change"),
1656 sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
1657 sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
1661 add_option (_("MIDI"),
1663 "diplay-first-midi-bank-as-zero",
1664 _("Display first MIDI bank/program as 0"),
1665 sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
1666 sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
1669 add_option (_("MIDI"),
1671 "never-display-periodic-midi",
1672 _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
1673 sigc::mem_fun (*_rc_config, &RCConfiguration::get_never_display_periodic_midi),
1674 sigc::mem_fun (*_rc_config, &RCConfiguration::set_never_display_periodic_midi)
1677 add_option (_("MIDI"),
1680 _("Sound MIDI notes as they are selected"),
1681 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sound_midi_notes),
1682 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sound_midi_notes)
1685 /* USER INTERACTION */
1687 add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
1689 add_option (_("User interaction"), new KeyboardOptions);
1691 add_option (_("User interaction"), new OptionEditorHeading (_("Control surfaces")));
1693 add_option (_("User interaction"), new ControlSurfacesOptions (*this));
1695 ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
1697 _("Control surface remote ID"),
1698 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
1699 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
1702 rm->add (UserOrdered, _("assigned by user"));
1703 rm->add (MixerOrdered, _("follows order of mixer"));
1704 rm->add (EditorOrdered, _("follows order of editor"));
1706 add_option (_("User interaction"), rm);
1710 add_option (S_("GUI"),
1713 _("Graphically indicate mouse pointer hovering over various widgets"),
1714 sigc::mem_fun (*_rc_config, &RCConfiguration::get_widget_prelight),
1715 sigc::mem_fun (*_rc_config, &RCConfiguration::set_widget_prelight)
1718 add_option (S_("GUI"),
1721 _("Show tooltips if mouse hovers over a control"),
1722 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_tooltips),
1723 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_tooltips)
1727 /* font scaling does nothing with GDK/Quartz */
1728 add_option (S_("GUI"), new FontScalingOptions (_rc_config));
1730 add_option (S_("GUI"),
1732 "use-own-plugin-gui",
1733 _("Use plugins' own interfaces instead of Ardour's"),
1734 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_plugin_own_gui),
1735 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_plugin_own_gui)
1738 /* The names of these controls must be the same as those given in MixerStrip
1739 for the actual widgets being controlled.
1741 _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
1742 _mixer_strip_visibility.add (0, X_("SoloSafe"), _("Solo Safe"));
1743 _mixer_strip_visibility.add (0, X_("SoloIsolated"), _("Solo Isolated"));
1744 _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
1745 _mixer_strip_visibility.add (0, X_("MeterPoint"), _("Meter Point"));
1749 new VisibilityOption (
1751 &_mixer_strip_visibility,
1752 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mixer_strip_visibility),
1753 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mixer_strip_visibility)
1757 add_option (S_("GUI"),
1759 "default-narrow_ms",
1760 _("Use narrow strips in the mixer by default"),
1761 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_narrow_ms),
1762 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_narrow_ms)
1765 add_option (S_("GUI"), new OptionEditorHeading (_("Metering")));
1767 ComboOption<float>* mht = new ComboOption<float> (
1769 _("Meter hold time"),
1770 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_hold),
1771 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_hold)
1774 mht->add (MeterHoldOff, _("off"));
1775 mht->add (MeterHoldShort, _("short"));
1776 mht->add (MeterHoldMedium, _("medium"));
1777 mht->add (MeterHoldLong, _("long"));
1779 add_option (S_("GUI"), mht);
1781 ComboOption<float>* mfo = new ComboOption<float> (
1783 _("Meter fall-off"),
1784 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
1785 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
1788 mfo->add (METER_FALLOFF_OFF, _("off"));
1789 mfo->add (METER_FALLOFF_SLOWEST, _("slowest"));
1790 mfo->add (METER_FALLOFF_SLOW, _("slow"));
1791 mfo->add (METER_FALLOFF_MEDIUM, _("medium"));
1792 mfo->add (METER_FALLOFF_FAST, _("fast"));
1793 mfo->add (METER_FALLOFF_FASTER, _("faster"));
1794 mfo->add (METER_FALLOFF_FASTEST, _("fastest"));
1796 add_option (S_("GUI"), mfo);
1800 RCOptionEditor::parameter_changed (string const & p)
1802 OptionEditor::parameter_changed (p);
1804 if (p == "use-monitor-bus") {
1805 bool const s = Config->get_use_monitor_bus ();
1807 /* we can't use this if we don't have a monitor bus */
1808 Config->set_solo_control_is_listen_control (false);
1810 _solo_control_is_listen_control->set_sensitive (s);
1811 _listen_position->set_sensitive (s);
1812 } else if (p == "sync-source") {
1813 _sync_source->set_sensitive (true);
1815 _sync_source->set_sensitive (!_session->config.get_external_sync());
1817 switch(Config->get_sync_source()) {
1820 _sync_genlock->set_sensitive (true);
1821 _sync_framerate->set_sensitive (true);
1822 _sync_source_2997->set_sensitive (true);
1825 _sync_genlock->set_sensitive (false);
1826 _sync_framerate->set_sensitive (false);
1827 _sync_source_2997->set_sensitive (false);
1830 } else if (p == "send-ltc") {
1831 bool const s = Config->get_send_ltc ();
1832 _ltc_send_continuously->set_sensitive (s);
1833 _ltc_volume_slider->set_sensitive (s);
1837 void RCOptionEditor::ltc_generator_volume_changed () {
1838 _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
1842 RCOptionEditor::populate_sync_options ()
1844 vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
1846 _sync_source->clear ();
1848 for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
1849 _sync_source->add (*i, sync_source_to_string (*i));