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 #if !defined USE_CAIRO_IMAGE_SURFACE && !defined NDEBUG
25 #define OPTIONAL_CAIRO_IMAGE_SURFACE
28 #include <cairo/cairo.h>
30 #include <boost/algorithm/string.hpp>
32 #include <gtkmm/liststore.h>
33 #include <gtkmm/stock.h>
34 #include <gtkmm/scale.h>
36 #include <gtkmm2ext/utils.h>
37 #include <gtkmm2ext/slider_controller.h>
38 #include <gtkmm2ext/gtk_ui.h>
39 #include <gtkmm2ext/paths_dialog.h>
44 #include "ardour/audioengine.h"
45 #include "ardour/dB.h"
46 #include "ardour/rc_configuration.h"
47 #include "ardour/control_protocol_manager.h"
48 #include "ardour/plugin_manager.h"
49 #include "control_protocol/control_protocol.h"
51 #include "canvas/wave_view.h"
53 #include "ardour_window.h"
54 #include "ardour_dialog.h"
55 #include "gui_thread.h"
56 #include "meter_patterns.h"
57 #include "midi_tracer.h"
58 #include "rc_option_editor.h"
60 #include "midi_port_dialog.h"
63 #include "theme_manager.h"
64 #include "ui_config.h"
69 using namespace Gtkmm2ext;
71 using namespace ARDOUR;
72 using namespace ARDOUR_UI_UTILS;
74 class ClickOptions : public OptionEditorBox
77 ClickOptions (RCConfiguration* c, Gtk::Window* p)
79 , _click_browse_button (_("Browse..."))
80 , _click_emphasis_browse_button (_("Browse..."))
82 Table* t = manage (new Table (4, 3));
85 Label* l = manage (left_aligned_label (_("Use default Click:")));
86 t->attach (*l, 0, 1, 0, 1, FILL);
87 t->attach (_use_default_click_check_button, 1, 2, 0, 1, FILL);
88 _use_default_click_check_button.signal_toggled().connect (
89 sigc::mem_fun (*this, &ClickOptions::use_default_click_toggled));
91 l = manage (left_aligned_label (_("Emphasis on first beat:")));
92 t->attach (*l, 0, 1, 1, 2, FILL);
93 t->attach (_use_emphasis_on_click_check_button, 1, 2, 1, 2, FILL);
94 _use_emphasis_on_click_check_button.signal_toggled().connect (
95 sigc::mem_fun (*this, &ClickOptions::use_emphasis_on_click_toggled));
97 l = manage (left_aligned_label (_("Click audio file:")));
98 t->attach (*l, 0, 1, 2, 3, FILL);
99 t->attach (_click_path_entry, 1, 2, 2, 3, FILL);
100 _click_browse_button.signal_clicked ().connect (
101 sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
102 t->attach (_click_browse_button, 2, 3, 2, 3, FILL);
104 l = manage (left_aligned_label (_("Click emphasis audio file:")));
105 t->attach (*l, 0, 1, 3, 4, FILL);
106 t->attach (_click_emphasis_path_entry, 1, 2, 3, 4, FILL);
107 _click_emphasis_browse_button.signal_clicked ().connect (
108 sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
109 t->attach (_click_emphasis_browse_button, 2, 3, 3, 4, FILL);
111 _box->pack_start (*t, false, false);
113 _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));
114 _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
116 if (_rc_config->get_click_sound ().empty() &&
117 _rc_config->get_click_emphasis_sound().empty()) {
118 _use_default_click_check_button.set_active (true);
119 _use_emphasis_on_click_check_button.set_active (true);
122 _use_default_click_check_button.set_active (false);
123 _use_emphasis_on_click_check_button.set_active (false);
127 void parameter_changed (string const & p)
129 if (p == "click-sound") {
130 _click_path_entry.set_text (_rc_config->get_click_sound());
131 } else if (p == "click-emphasis-sound") {
132 _click_emphasis_path_entry.set_text (_rc_config->get_click_emphasis_sound());
133 } else if (p == "use-click-emphasis") {
134 bool x = _rc_config->get_use_click_emphasis ();
135 _use_emphasis_on_click_check_button.set_active (x);
139 void set_state_from_config ()
141 parameter_changed ("click-sound");
142 parameter_changed ("click-emphasis-sound");
143 parameter_changed ("use-click-emphasis");
148 void click_browse_clicked ()
150 SoundFileChooser sfdb (_("Choose Click"));
155 if (sfdb.run () == RESPONSE_OK) {
156 click_chosen (sfdb.get_filename());
160 void click_chosen (string const & path)
162 _click_path_entry.set_text (path);
163 _rc_config->set_click_sound (path);
166 void click_changed ()
168 click_chosen (_click_path_entry.get_text ());
171 void click_emphasis_browse_clicked ()
173 SoundFileChooser sfdb (_("Choose Click Emphasis"));
178 if (sfdb.run () == RESPONSE_OK) {
179 click_emphasis_chosen (sfdb.get_filename());
183 void click_emphasis_chosen (string const & path)
185 _click_emphasis_path_entry.set_text (path);
186 _rc_config->set_click_emphasis_sound (path);
189 void click_emphasis_changed ()
191 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
194 void use_default_click_toggled ()
196 if (_use_default_click_check_button.get_active ()) {
197 _rc_config->set_click_sound ("");
198 _rc_config->set_click_emphasis_sound ("");
199 _click_path_entry.set_sensitive (false);
200 _click_emphasis_path_entry.set_sensitive (false);
201 _click_browse_button.set_sensitive (false);
202 _click_emphasis_browse_button.set_sensitive (false);
204 _click_path_entry.set_sensitive (true);
205 _click_emphasis_path_entry.set_sensitive (true);
206 _click_browse_button.set_sensitive (true);
207 _click_emphasis_browse_button.set_sensitive (true);
211 void use_emphasis_on_click_toggled ()
213 if (_use_emphasis_on_click_check_button.get_active ()) {
214 _rc_config->set_use_click_emphasis(true);
216 _rc_config->set_use_click_emphasis(false);
220 RCConfiguration* _rc_config;
221 CheckButton _use_default_click_check_button;
222 CheckButton _use_emphasis_on_click_check_button;
223 Entry _click_path_entry;
224 Entry _click_emphasis_path_entry;
225 Button _click_browse_button;
226 Button _click_emphasis_browse_button;
229 class UndoOptions : public OptionEditorBox
232 UndoOptions (RCConfiguration* c) :
234 _limit_undo_button (_("Limit undo history to")),
235 _save_undo_button (_("Save undo history of"))
237 Table* t = new Table (2, 3);
240 t->attach (_limit_undo_button, 0, 1, 0, 1, FILL);
241 _limit_undo_spin.set_range (0, 512);
242 _limit_undo_spin.set_increments (1, 10);
243 t->attach (_limit_undo_spin, 1, 2, 0, 1, FILL | EXPAND);
244 Label* l = manage (left_aligned_label (_("commands")));
245 t->attach (*l, 2, 3, 0, 1);
247 t->attach (_save_undo_button, 0, 1, 1, 2, FILL);
248 _save_undo_spin.set_range (0, 512);
249 _save_undo_spin.set_increments (1, 10);
250 t->attach (_save_undo_spin, 1, 2, 1, 2, FILL | EXPAND);
251 l = manage (left_aligned_label (_("commands")));
252 t->attach (*l, 2, 3, 1, 2);
254 _box->pack_start (*t);
256 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
257 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
258 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
259 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
262 void parameter_changed (string const & p)
264 if (p == "history-depth") {
265 int32_t const d = _rc_config->get_history_depth();
266 _limit_undo_button.set_active (d != 0);
267 _limit_undo_spin.set_sensitive (d != 0);
268 _limit_undo_spin.set_value (d);
269 } else if (p == "save-history") {
270 bool const x = _rc_config->get_save_history ();
271 _save_undo_button.set_active (x);
272 _save_undo_spin.set_sensitive (x);
273 } else if (p == "save-history-depth") {
274 _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
278 void set_state_from_config ()
280 parameter_changed ("save-history");
281 parameter_changed ("history-depth");
282 parameter_changed ("save-history-depth");
285 void limit_undo_toggled ()
287 bool const x = _limit_undo_button.get_active ();
288 _limit_undo_spin.set_sensitive (x);
289 int32_t const n = x ? 16 : 0;
290 _limit_undo_spin.set_value (n);
291 _rc_config->set_history_depth (n);
294 void limit_undo_changed ()
296 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
299 void save_undo_toggled ()
301 bool const x = _save_undo_button.get_active ();
302 _rc_config->set_save_history (x);
305 void save_undo_changed ()
307 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
311 RCConfiguration* _rc_config;
312 CheckButton _limit_undo_button;
313 SpinButton _limit_undo_spin;
314 CheckButton _save_undo_button;
315 SpinButton _save_undo_spin;
320 static const struct {
332 { "Key|Shift", GDK_SHIFT_MASK },
333 { "Command", GDK_META_MASK },
334 { "Control", GDK_CONTROL_MASK },
335 { "Option", GDK_MOD1_MASK },
336 { "Command-Shift", GDK_META_MASK|GDK_SHIFT_MASK },
337 { "Command-Option", GDK_MOD1_MASK|GDK_META_MASK },
338 { "Option-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
339 { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
340 { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_META_MASK },
343 { "Key|Shift", GDK_SHIFT_MASK },
344 { "Control", GDK_CONTROL_MASK },
345 { "Alt", GDK_MOD1_MASK },
346 { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
347 { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
348 { "Shift-Alt", GDK_SHIFT_MASK|GDK_MOD1_MASK },
349 { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
350 { "Alt-Windows", GDK_MOD1_MASK|GDK_MOD4_MASK },
351 { "Alt-Shift-Windows", GDK_MOD1_MASK|GDK_SHIFT_MASK|GDK_MOD4_MASK },
352 { "Mod2", GDK_MOD2_MASK },
353 { "Mod3", GDK_MOD3_MASK },
354 { "Windows", GDK_MOD4_MASK },
355 { "Mod5", GDK_MOD5_MASK },
361 class KeyboardOptions : public OptionEditorBox
365 _delete_button_adjustment (3, 1, 12),
366 _delete_button_spin (_delete_button_adjustment),
367 _edit_button_adjustment (3, 1, 5),
368 _edit_button_spin (_edit_button_adjustment),
369 _insert_note_button_adjustment (3, 1, 5),
370 _insert_note_button_spin (_insert_note_button_adjustment)
372 /* internationalize and prepare for use with combos */
375 for (int i = 0; modifiers[i].name; ++i) {
376 dumb.push_back (S_(modifiers[i].name));
379 set_popdown_strings (_edit_modifier_combo, dumb);
380 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
382 for (int x = 0; modifiers[x].name; ++x) {
383 if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
384 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
389 Table* t = manage (new Table (5, 11));
395 Label* l = manage (left_aligned_label (_("Select Keyboard layout:")));
396 l->set_name ("OptionsLabel");
400 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
401 strs.push_back (bf->first);
404 set_popdown_strings (_keyboard_layout_selector, strs);
405 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
406 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
408 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
409 t->attach (_keyboard_layout_selector, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
414 l = manage (left_aligned_label (_("When Clicking:")));
415 l->set_name ("OptionEditorHeading");
416 t->attach (*l, col, col + 2, row, row + 1, FILL | EXPAND, FILL);
421 l = manage (left_aligned_label (_("Edit using:")));
422 l->set_name ("OptionsLabel");
424 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
425 t->attach (_edit_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
427 l = manage (new Label (_("+ button")));
428 l->set_name ("OptionsLabel");
430 t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
431 t->attach (_edit_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
433 _edit_button_spin.set_name ("OptionsEntry");
434 _edit_button_adjustment.set_value (Keyboard::edit_button());
435 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
440 set_popdown_strings (_delete_modifier_combo, dumb);
441 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
443 for (int x = 0; modifiers[x].name; ++x) {
444 if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
445 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
450 l = manage (left_aligned_label (_("Delete using:")));
451 l->set_name ("OptionsLabel");
453 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
454 t->attach (_delete_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
456 l = manage (new Label (_("+ button")));
457 l->set_name ("OptionsLabel");
459 t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
460 t->attach (_delete_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
462 _delete_button_spin.set_name ("OptionsEntry");
463 _delete_button_adjustment.set_value (Keyboard::delete_button());
464 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
469 set_popdown_strings (_insert_note_modifier_combo, dumb);
470 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
472 for (int x = 0; modifiers[x].name; ++x) {
473 if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
474 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
479 l = manage (left_aligned_label (_("Insert note using:")));
480 l->set_name ("OptionsLabel");
482 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
483 t->attach (_insert_note_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
485 l = manage (new Label (_("+ button")));
486 l->set_name ("OptionsLabel");
488 t->attach (*l, col + 3, col + 4, row, row + 1, FILL | EXPAND, FILL);
489 t->attach (_insert_note_button_spin, col + 4, col + 5, row, row + 1, FILL | EXPAND, FILL);
491 _insert_note_button_spin.set_name ("OptionsEntry");
492 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
493 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
497 l = manage (left_aligned_label (_("When Beginning a Drag:")));
498 l->set_name ("OptionEditorHeading");
499 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
505 set_popdown_strings (_copy_modifier_combo, dumb);
506 _copy_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::copy_modifier_chosen));
508 for (int x = 0; modifiers[x].name; ++x) {
509 if (modifiers[x].modifier == (guint) Keyboard::CopyModifier) {
510 _copy_modifier_combo.set_active_text (S_(modifiers[x].name));
515 l = manage (left_aligned_label (_("Copy items using:")));
516 l->set_name ("OptionsLabel");
518 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
519 t->attach (_copy_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
524 /* constraint modifier */
525 set_popdown_strings (_constraint_modifier_combo, dumb);
526 _constraint_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::constraint_modifier_chosen));
528 for (int x = 0; modifiers[x].name; ++x) {
529 if (modifiers[x].modifier == (guint) ArdourKeyboard::constraint_modifier ()) {
530 _constraint_modifier_combo.set_active_text (S_(modifiers[x].name));
535 l = manage (left_aligned_label (_("Constrain drag using:")));
536 l->set_name ("OptionsLabel");
538 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
539 t->attach (_constraint_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
543 l = manage (left_aligned_label (_("When Beginning a Trim:")));
544 l->set_name ("OptionEditorHeading");
545 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
551 set_popdown_strings (_trim_contents_combo, dumb);
552 _trim_contents_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_contents_modifier_chosen));
554 for (int x = 0; modifiers[x].name; ++x) {
555 if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_contents_modifier ()) {
556 _trim_contents_combo.set_active_text (S_(modifiers[x].name));
561 l = manage (left_aligned_label (_("Trim contents using:")));
562 l->set_name ("OptionsLabel");
564 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
565 t->attach (_trim_contents_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
571 set_popdown_strings (_trim_anchored_combo, dumb);
572 _trim_anchored_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_anchored_modifier_chosen));
574 for (int x = 0; modifiers[x].name; ++x) {
575 if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_anchored_modifier ()) {
576 _trim_anchored_combo.set_active_text (S_(modifiers[x].name));
581 l = manage (left_aligned_label (_("Anchored trim using:")));
582 l->set_name ("OptionsLabel");
584 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
586 t->attach (_trim_anchored_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
591 /* jump trim disabled for now
592 set_popdown_strings (_trim_jump_combo, dumb);
593 _trim_jump_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_jump_modifier_chosen));
595 for (int x = 0; modifiers[x].name; ++x) {
596 if (modifiers[x].modifier == (guint) Keyboard::trim_jump_modifier ()) {
597 _trim_jump_combo.set_active_text (S_(modifiers[x].name));
602 l = manage (left_aligned_label (_("Jump after trim using:")));
603 l->set_name ("OptionsLabel");
605 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
607 t->attach (_trim_jump_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
613 /* note resize relative */
614 set_popdown_strings (_note_size_relative_combo, dumb);
615 _note_size_relative_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::note_size_relative_modifier_chosen));
617 for (int x = 0; modifiers[x].name; ++x) {
618 if (modifiers[x].modifier == (guint) ArdourKeyboard::note_size_relative_modifier ()) {
619 _note_size_relative_combo.set_active_text (S_(modifiers[x].name));
624 l = manage (left_aligned_label (_("Resize notes relatively using:")));
625 l->set_name ("OptionsLabel");
627 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
629 t->attach (_note_size_relative_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
633 l = manage (left_aligned_label (_("While Dragging:")));
634 l->set_name ("OptionEditorHeading");
635 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
641 set_popdown_strings (_snap_modifier_combo, dumb);
642 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
644 for (int x = 0; modifiers[x].name; ++x) {
645 if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
646 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
651 l = manage (left_aligned_label (_("Ignore snap using:")));
652 l->set_name ("OptionsLabel");
654 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
655 t->attach (_snap_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
661 set_popdown_strings (_snap_delta_combo, dumb);
662 _snap_delta_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_delta_modifier_chosen));
664 for (int x = 0; modifiers[x].name; ++x) {
665 if (modifiers[x].modifier == (guint) Keyboard::snap_delta_modifier ()) {
666 _snap_delta_combo.set_active_text (S_(modifiers[x].name));
671 l = manage (left_aligned_label (_("Snap relatively using:")));
672 l->set_name ("OptionsLabel");
674 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
675 t->attach (_snap_delta_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
679 l = manage (left_aligned_label (_("While Trimming:")));
680 l->set_name ("OptionEditorHeading");
681 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
687 set_popdown_strings (_trim_overlap_combo, dumb);
688 _trim_overlap_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_overlap_modifier_chosen));
690 for (int x = 0; modifiers[x].name; ++x) {
691 if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_overlap_modifier ()) {
692 _trim_overlap_combo.set_active_text (S_(modifiers[x].name));
697 l = manage (left_aligned_label (_("Resize overlapped regions using:")));
698 l->set_name ("OptionsLabel");
700 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
701 t->attach (_trim_overlap_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
705 l = manage (left_aligned_label (_("While Dragging Control Points:")));
706 l->set_name ("OptionEditorHeading");
707 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
713 set_popdown_strings (_fine_adjust_combo, dumb);
714 _fine_adjust_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::fine_adjust_modifier_chosen));
716 for (int x = 0; modifiers[x].name; ++x) {
717 if (modifiers[x].modifier == (guint) ArdourKeyboard::fine_adjust_modifier ()) {
718 _fine_adjust_combo.set_active_text (S_(modifiers[x].name));
723 l = manage (left_aligned_label (_("Fine adjust using:")));
724 l->set_name ("OptionsLabel");
726 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
727 t->attach (_fine_adjust_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
733 set_popdown_strings (_push_points_combo, dumb);
734 _push_points_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::push_points_modifier_chosen));
736 for (int x = 0; modifiers[x].name; ++x) {
737 if (modifiers[x].modifier == (guint) ArdourKeyboard::push_points_modifier ()) {
738 _push_points_combo.set_active_text (S_(modifiers[x].name));
743 l = manage (left_aligned_label (_("Push points using:")));
744 l->set_name ("OptionsLabel");
746 t->attach (*l, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
747 t->attach (_push_points_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
749 _box->pack_start (*t, false, false);
752 void parameter_changed (string const &)
754 /* XXX: these aren't really config options... */
757 void set_state_from_config ()
759 /* XXX: these aren't really config options... */
764 void bindings_changed ()
766 string const txt = _keyboard_layout_selector.get_active_text();
768 /* XXX: config...? for all this keyboard stuff */
770 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
771 if (txt == i->first) {
772 if (Keyboard::load_keybindings (i->second)) {
773 Keyboard::save_keybindings ();
779 void edit_modifier_chosen ()
781 string const txt = _edit_modifier_combo.get_active_text();
783 for (int i = 0; modifiers[i].name; ++i) {
784 if (txt == _(modifiers[i].name)) {
785 Keyboard::set_edit_modifier (modifiers[i].modifier);
791 void delete_modifier_chosen ()
793 string const txt = _delete_modifier_combo.get_active_text();
795 for (int i = 0; modifiers[i].name; ++i) {
796 if (txt == _(modifiers[i].name)) {
797 Keyboard::set_delete_modifier (modifiers[i].modifier);
803 void copy_modifier_chosen ()
805 string const txt = _copy_modifier_combo.get_active_text();
807 for (int i = 0; modifiers[i].name; ++i) {
808 if (txt == _(modifiers[i].name)) {
809 Keyboard::set_copy_modifier (modifiers[i].modifier);
815 void insert_note_modifier_chosen ()
817 string const txt = _insert_note_modifier_combo.get_active_text();
819 for (int i = 0; modifiers[i].name; ++i) {
820 if (txt == _(modifiers[i].name)) {
821 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
827 void snap_modifier_chosen ()
829 string const txt = _snap_modifier_combo.get_active_text();
831 for (int i = 0; modifiers[i].name; ++i) {
832 if (txt == _(modifiers[i].name)) {
833 Keyboard::set_snap_modifier (modifiers[i].modifier);
839 void snap_delta_modifier_chosen ()
841 string const txt = _snap_delta_combo.get_active_text();
843 for (int i = 0; modifiers[i].name; ++i) {
844 if (txt == _(modifiers[i].name)) {
845 Keyboard::set_snap_delta_modifier (modifiers[i].modifier);
851 void constraint_modifier_chosen ()
853 string const txt = _constraint_modifier_combo.get_active_text();
855 for (int i = 0; modifiers[i].name; ++i) {
856 if (txt == _(modifiers[i].name)) {
857 ArdourKeyboard::set_constraint_modifier (modifiers[i].modifier);
863 void trim_contents_modifier_chosen ()
865 string const txt = _trim_contents_combo.get_active_text();
867 for (int i = 0; modifiers[i].name; ++i) {
868 if (txt == _(modifiers[i].name)) {
869 ArdourKeyboard::set_trim_contents_modifier (modifiers[i].modifier);
875 void trim_overlap_modifier_chosen ()
877 string const txt = _trim_overlap_combo.get_active_text();
879 for (int i = 0; modifiers[i].name; ++i) {
880 if (txt == _(modifiers[i].name)) {
881 ArdourKeyboard::set_trim_overlap_modifier (modifiers[i].modifier);
887 void trim_anchored_modifier_chosen ()
889 string const txt = _trim_anchored_combo.get_active_text();
891 for (int i = 0; modifiers[i].name; ++i) {
892 if (txt == _(modifiers[i].name)) {
893 ArdourKeyboard::set_trim_anchored_modifier (modifiers[i].modifier);
899 void fine_adjust_modifier_chosen ()
901 string const txt = _fine_adjust_combo.get_active_text();
903 for (int i = 0; modifiers[i].name; ++i) {
904 if (txt == _(modifiers[i].name)) {
905 ArdourKeyboard::set_fine_adjust_modifier (modifiers[i].modifier);
911 void push_points_modifier_chosen ()
913 string const txt = _push_points_combo.get_active_text();
915 for (int i = 0; modifiers[i].name; ++i) {
916 if (txt == _(modifiers[i].name)) {
917 ArdourKeyboard::set_push_points_modifier (modifiers[i].modifier);
923 void note_size_relative_modifier_chosen ()
925 string const txt = _note_size_relative_combo.get_active_text();
927 for (int i = 0; modifiers[i].name; ++i) {
928 if (txt == _(modifiers[i].name)) {
929 ArdourKeyboard::set_note_size_relative_modifier (modifiers[i].modifier);
935 void delete_button_changed ()
937 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
940 void edit_button_changed ()
942 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
945 void insert_note_button_changed ()
947 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
950 ComboBoxText _keyboard_layout_selector;
951 ComboBoxText _edit_modifier_combo;
952 ComboBoxText _delete_modifier_combo;
953 ComboBoxText _copy_modifier_combo;
954 ComboBoxText _insert_note_modifier_combo;
955 ComboBoxText _snap_modifier_combo;
956 ComboBoxText _snap_delta_combo;
957 ComboBoxText _constraint_modifier_combo;
958 ComboBoxText _trim_contents_combo;
959 ComboBoxText _trim_overlap_combo;
960 ComboBoxText _trim_anchored_combo;
961 ComboBoxText _trim_jump_combo;
962 ComboBoxText _fine_adjust_combo;
963 ComboBoxText _push_points_combo;
964 ComboBoxText _note_size_relative_combo;
965 Adjustment _delete_button_adjustment;
966 SpinButton _delete_button_spin;
967 Adjustment _edit_button_adjustment;
968 SpinButton _edit_button_spin;
969 Adjustment _insert_note_button_adjustment;
970 SpinButton _insert_note_button_spin;
974 class FontScalingOptions : public OptionEditorBox
977 FontScalingOptions () :
978 _dpi_adjustment (100, 50, 250, 1, 5),
979 _dpi_slider (_dpi_adjustment)
981 _dpi_adjustment.set_value (UIConfiguration::instance().get_font_scale() / 1024.);
983 Label* l = manage (new Label (_("GUI and Font scaling:")));
984 l->set_name ("OptionsLabel");
986 const Glib::ustring dflt = _("Default");
987 const Glib::ustring empty = X_(""); // despite gtk-doc saying so, NULL does not work as reference
989 _dpi_slider.set_name("FontScaleSlider");
990 _dpi_slider.set_update_policy (UPDATE_DISCONTINUOUS);
991 _dpi_slider.set_draw_value(false);
992 _dpi_slider.add_mark(50, Gtk::POS_TOP, empty);
993 _dpi_slider.add_mark(60, Gtk::POS_TOP, empty);
994 _dpi_slider.add_mark(70, Gtk::POS_TOP, empty);
995 _dpi_slider.add_mark(80, Gtk::POS_TOP, empty);
996 _dpi_slider.add_mark(90, Gtk::POS_TOP, empty);
997 _dpi_slider.add_mark(100, Gtk::POS_TOP, dflt);
998 _dpi_slider.add_mark(125, Gtk::POS_TOP, empty);
999 _dpi_slider.add_mark(150, Gtk::POS_TOP, empty);
1000 _dpi_slider.add_mark(175, Gtk::POS_TOP, empty);
1001 _dpi_slider.add_mark(200, Gtk::POS_TOP, empty);
1002 _dpi_slider.add_mark(225, Gtk::POS_TOP, empty);
1003 _dpi_slider.add_mark(250, Gtk::POS_TOP, empty);
1005 HBox* h = manage (new HBox);
1007 h->pack_start (*l, false, false);
1008 h->pack_start (_dpi_slider, true, true);
1010 _box->pack_start (*h, false, false);
1012 set_note (_("Adjusting the scale require an application restart to re-layout."));
1014 _dpi_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &FontScalingOptions::dpi_changed));
1017 void parameter_changed (string const & p)
1019 if (p == "font-scale") {
1020 _dpi_adjustment.set_value (UIConfiguration::instance().get_font_scale() / 1024.);
1024 void set_state_from_config ()
1026 parameter_changed ("font-scale");
1033 UIConfiguration::instance().set_font_scale ((long) floor (_dpi_adjustment.get_value() * 1024.));
1034 /* XXX: should be triggered from the parameter changed signal */
1035 UIConfiguration::instance().reset_dpi ();
1038 Adjustment _dpi_adjustment;
1042 class ClipLevelOptions : public OptionEditorBox
1046 : _clip_level_adjustment (-.5, -50.0, 0.0, 0.1, 1.0) /* units of dB */
1047 , _clip_level_slider (_clip_level_adjustment)
1049 _clip_level_adjustment.set_value (UIConfiguration::instance().get_waveform_clip_level ());
1051 Label* l = manage (new Label (_("Waveform Clip Level (dBFS):")));
1052 l->set_name ("OptionsLabel");
1054 _clip_level_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1055 HBox* h = manage (new HBox);
1057 h->pack_start (*l, false, false);
1058 h->pack_start (_clip_level_slider, true, true);
1060 _box->pack_start (*h, false, false);
1062 _clip_level_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &ClipLevelOptions::clip_level_changed));
1065 void parameter_changed (string const & p)
1067 if (p == "waveform-clip-level") {
1068 _clip_level_adjustment.set_value (UIConfiguration::instance().get_waveform_clip_level());
1072 void set_state_from_config ()
1074 parameter_changed ("waveform-clip-level");
1079 void clip_level_changed ()
1081 UIConfiguration::instance().set_waveform_clip_level (_clip_level_adjustment.get_value());
1082 /* XXX: should be triggered from the parameter changed signal */
1083 ArdourCanvas::WaveView::set_clip_level (_clip_level_adjustment.get_value());
1086 Adjustment _clip_level_adjustment;
1087 HScale _clip_level_slider;
1090 class BufferingOptions : public OptionEditorBox
1093 BufferingOptions (RCConfiguration* c)
1095 , _playback_adjustment (5, 1, 60, 1, 4)
1096 , _capture_adjustment (5, 1, 60, 1, 4)
1097 , _playback_slider (_playback_adjustment)
1098 , _capture_slider (_capture_adjustment)
1100 vector<string> presets;
1102 /* these must match the order of the enums for BufferingPreset */
1104 presets.push_back (_("Small sessions (4-16 tracks)"));
1105 presets.push_back (_("Medium sessions (16-64 tracks)"));
1106 presets.push_back (_("Large sessions (64+ tracks)"));
1107 presets.push_back (_("Custom (set by sliders below)"));
1109 set_popdown_strings (_buffering_presets_combo, presets);
1111 Label* l = manage (new Label (_("Preset:")));
1112 l->set_name ("OptionsLabel");
1113 HBox* h = manage (new HBox);
1114 h->set_spacing (12);
1115 h->pack_start (*l, false, false);
1116 h->pack_start (_buffering_presets_combo, true, true);
1117 _box->pack_start (*h, false, false);
1119 _buffering_presets_combo.signal_changed().connect (sigc::mem_fun (*this, &BufferingOptions::preset_changed));
1121 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
1123 l = manage (new Label (_("Playback (seconds of buffering):")));
1124 l->set_name ("OptionsLabel");
1126 _playback_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1127 h = manage (new HBox);
1129 h->pack_start (*l, false, false);
1130 h->pack_start (_playback_slider, true, true);
1132 _box->pack_start (*h, false, false);
1134 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
1136 l = manage (new Label (_("Recording (seconds of buffering):")));
1137 l->set_name ("OptionsLabel");
1139 _capture_slider.set_update_policy (UPDATE_DISCONTINUOUS);
1140 h = manage (new HBox);
1142 h->pack_start (*l, false, false);
1143 h->pack_start (_capture_slider, true, true);
1145 _box->pack_start (*h, false, false);
1147 _capture_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::capture_changed));
1148 _playback_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &BufferingOptions::playback_changed));
1151 void parameter_changed (string const & p)
1153 if (p == "buffering-preset") {
1154 switch (_rc_config->get_buffering_preset()) {
1156 _playback_slider.set_sensitive (false);
1157 _capture_slider.set_sensitive (false);
1158 _buffering_presets_combo.set_active (0);
1161 _playback_slider.set_sensitive (false);
1162 _capture_slider.set_sensitive (false);
1163 _buffering_presets_combo.set_active (1);
1166 _playback_slider.set_sensitive (false);
1167 _capture_slider.set_sensitive (false);
1168 _buffering_presets_combo.set_active (2);
1171 _playback_slider.set_sensitive (true);
1172 _capture_slider.set_sensitive (true);
1173 _buffering_presets_combo.set_active (3);
1178 if (p == "playback-buffer-seconds") {
1179 _playback_adjustment.set_value (_rc_config->get_audio_playback_buffer_seconds());
1180 } else if (p == "capture-buffer-seconds") {
1181 _capture_adjustment.set_value (_rc_config->get_audio_capture_buffer_seconds());
1185 void set_state_from_config ()
1187 parameter_changed ("buffering-preset");
1188 parameter_changed ("playback-buffer-seconds");
1189 parameter_changed ("capture-buffer-seconds");
1194 void preset_changed ()
1196 int index = _buffering_presets_combo.get_active_row_number ();
1202 _rc_config->set_buffering_preset (Small);
1205 _rc_config->set_buffering_preset (Medium);
1208 _rc_config->set_buffering_preset (Large);
1211 _rc_config->set_buffering_preset (Custom);
1214 error << string_compose (_("programming error: unknown buffering preset string, index = %1"), index) << endmsg;
1219 void playback_changed ()
1221 _rc_config->set_audio_playback_buffer_seconds ((long) _playback_adjustment.get_value());
1224 void capture_changed ()
1226 _rc_config->set_audio_capture_buffer_seconds ((long) _capture_adjustment.get_value());
1229 RCConfiguration* _rc_config;
1230 Adjustment _playback_adjustment;
1231 Adjustment _capture_adjustment;
1232 HScale _playback_slider;
1233 HScale _capture_slider;
1234 ComboBoxText _buffering_presets_combo;
1237 class ControlSurfacesOptions : public OptionEditorBox
1240 ControlSurfacesOptions (Gtk::Window& parent)
1242 , _ignore_view_change (0)
1244 _store = ListStore::create (_model);
1245 _view.set_model (_store);
1246 _view.append_column (_("Control Surface Protocol"), _model.name);
1247 _view.get_column(0)->set_resizable (true);
1248 _view.get_column(0)->set_expand (true);
1249 _view.append_column_editable (_("Enabled"), _model.enabled);
1250 _view.append_column_editable (_("Feedback"), _model.feedback);
1252 _box->pack_start (_view, false, false);
1254 Label* label = manage (new Label);
1255 label->set_markup (string_compose (X_("<i>%1</i>"), _("Double-click on a name to edit settings for an enabled protocol")));
1257 _box->pack_start (*label, false, false);
1260 ControlProtocolManager& m = ControlProtocolManager::instance ();
1261 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
1262 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
1264 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
1265 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
1268 void parameter_changed (std::string const &)
1273 void set_state_from_config ()
1277 ControlProtocolManager& m = ControlProtocolManager::instance ();
1278 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
1280 if (!(*i)->mandatory) {
1281 TreeModel::Row r = *_store->append ();
1282 r[_model.name] = (*i)->name;
1283 r[_model.enabled] = ((*i)->protocol || (*i)->requested);
1284 r[_model.feedback] = ((*i)->protocol && (*i)->protocol->get_feedback ());
1285 r[_model.protocol_info] = *i;
1292 void protocol_status_changed (ControlProtocolInfo* cpi) {
1294 TreeModel::Children rows = _store->children();
1296 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
1297 string n = ((*x)[_model.name]);
1299 if ((*x)[_model.protocol_info] == cpi) {
1300 _ignore_view_change++;
1301 (*x)[_model.enabled] = (cpi->protocol || cpi->requested);
1302 _ignore_view_change--;
1308 void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
1310 TreeModel::Row r = *i;
1312 if (_ignore_view_change) {
1316 ControlProtocolInfo* cpi = r[_model.protocol_info];
1321 bool const was_enabled = (cpi->protocol != 0);
1322 bool const is_enabled = r[_model.enabled];
1325 if (was_enabled != is_enabled) {
1328 ControlProtocolManager::instance().activate (*cpi);
1330 ControlProtocolManager::instance().deactivate (*cpi);
1334 bool const was_feedback = (cpi->protocol && cpi->protocol->get_feedback ());
1335 bool const is_feedback = r[_model.feedback];
1337 if (was_feedback != is_feedback && cpi->protocol) {
1338 cpi->protocol->set_feedback (is_feedback);
1342 void edit_clicked (GdkEventButton* ev)
1344 if (ev->type != GDK_2BUTTON_PRESS) {
1349 ControlProtocolInfo* cpi;
1352 row = *(_view.get_selection()->get_selected());
1353 if (!row[_model.enabled]) {
1356 cpi = row[_model.protocol_info];
1357 if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
1360 Box* box = (Box*) cpi->protocol->get_gui ();
1364 if (box->get_parent()) {
1365 static_cast<ArdourWindow*>(box->get_parent())->present();
1368 string title = row[_model.name];
1369 /* once created, the window is managed by the surface itself (as ->get_parent())
1370 * Surface's tear_down_gui() is called on session close, when de-activating
1371 * or re-initializing a surface.
1372 * tear_down_gui() hides an deletes the Window if it exists.
1374 ArdourWindow* win = new ArdourWindow (_parent, title);
1375 win->set_title ("Control Protocol Options");
1381 class ControlSurfacesModelColumns : public TreeModelColumnRecord
1385 ControlSurfacesModelColumns ()
1390 add (protocol_info);
1393 TreeModelColumn<string> name;
1394 TreeModelColumn<bool> enabled;
1395 TreeModelColumn<bool> feedback;
1396 TreeModelColumn<ControlProtocolInfo*> protocol_info;
1399 Glib::RefPtr<ListStore> _store;
1400 ControlSurfacesModelColumns _model;
1402 Gtk::Window& _parent;
1403 PBD::ScopedConnection protocol_status_connection;
1404 uint32_t _ignore_view_change;
1407 class VideoTimelineOptions : public OptionEditorBox
1410 VideoTimelineOptions (RCConfiguration* c)
1412 , _show_video_export_info_button (_("Show Video Export Info before export"))
1413 , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
1414 , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
1416 Table* t = manage (new Table (2, 6));
1417 t->set_spacings (4);
1419 t->attach (_video_advanced_setup_button, 0, 2, 0, 1);
1420 _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
1421 Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
1422 _("<b>When enabled</b> you can speficify a custom video-server URL and docroot. - Do not enable this option unless you know what you are doing."));
1424 Label* l = manage (new Label (_("Video Server URL:")));
1425 l->set_alignment (0, 0.5);
1426 t->attach (*l, 0, 1, 1, 2, FILL);
1427 t->attach (_video_server_url_entry, 1, 2, 1, 2, FILL);
1428 Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
1429 _("Base URL of the video-server including http prefix. This is usually 'http://hostname.example.org:1554/' and defaults to 'http://localhost:1554/' when the video-server is running locally"));
1431 l = manage (new Label (_("Video Folder:")));
1432 l->set_alignment (0, 0.5);
1433 t->attach (*l, 0, 1, 2, 3, FILL);
1434 t->attach (_video_server_docroot_entry, 1, 2, 2, 3);
1435 Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
1436 _("Local path to the video-server document-root. Only files below this directory will be accessible by the video-server. If the server run on a remote host, it should point to a network mounted folder of the server's docroot or be left empty if it is unvailable. It is used for the local video-monitor and file-browsing when opening/adding a video file."));
1438 /* small vspace y=3..4 */
1440 t->attach (_show_video_export_info_button, 0, 2, 4, 5);
1441 _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
1442 Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
1443 _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
1445 t->attach (_show_video_server_dialog_button, 0, 2, 5, 6);
1446 _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
1447 Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
1448 _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
1450 _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1451 _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1452 _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1453 _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1455 _box->pack_start (*t,true,true);
1458 void server_url_changed ()
1460 _rc_config->set_video_server_url (_video_server_url_entry.get_text());
1463 void server_docroot_changed ()
1465 _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
1468 void show_video_export_info_toggled ()
1470 bool const x = _show_video_export_info_button.get_active ();
1471 _rc_config->set_show_video_export_info (x);
1474 void show_video_server_dialog_toggled ()
1476 bool const x = _show_video_server_dialog_button.get_active ();
1477 _rc_config->set_show_video_server_dialog (x);
1480 void video_advanced_setup_toggled ()
1482 bool const x = _video_advanced_setup_button.get_active ();
1483 _rc_config->set_video_advanced_setup(x);
1486 void parameter_changed (string const & p)
1488 if (p == "video-server-url") {
1489 _video_server_url_entry.set_text (_rc_config->get_video_server_url());
1490 } else if (p == "video-server-docroot") {
1491 _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
1492 } else if (p == "show-video-export-info") {
1493 bool const x = _rc_config->get_show_video_export_info();
1494 _show_video_export_info_button.set_active (x);
1495 } else if (p == "show-video-server-dialog") {
1496 bool const x = _rc_config->get_show_video_server_dialog();
1497 _show_video_server_dialog_button.set_active (x);
1498 } else if (p == "video-advanced-setup") {
1499 bool const x = _rc_config->get_video_advanced_setup();
1500 _video_advanced_setup_button.set_active(x);
1501 _video_server_docroot_entry.set_sensitive(x);
1502 _video_server_url_entry.set_sensitive(x);
1506 void set_state_from_config ()
1508 parameter_changed ("video-server-url");
1509 parameter_changed ("video-server-docroot");
1510 parameter_changed ("video-monitor-setup-dialog");
1511 parameter_changed ("show-video-export-info");
1512 parameter_changed ("show-video-server-dialog");
1513 parameter_changed ("video-advanced-setup");
1517 RCConfiguration* _rc_config;
1518 Entry _video_server_url_entry;
1519 Entry _video_server_docroot_entry;
1520 CheckButton _show_video_export_info_button;
1521 CheckButton _show_video_server_dialog_button;
1522 CheckButton _video_advanced_setup_button;
1525 class PluginOptions : public OptionEditorBox
1528 PluginOptions (RCConfiguration* c)
1530 , _display_plugin_scan_progress (_("Always Display Plugin Scan Progress"))
1531 , _discover_vst_on_start (_("Scan for [new] VST Plugins on Application Start"))
1532 , _discover_au_on_start (_("Scan for AudioUnit Plugins on Application Start"))
1533 , _verbose_plugin_scan (_("Verbose Plugin Scan"))
1534 , _timeout_adjustment (0, 0, 3000, 50, 50)
1535 , _timeout_slider (_timeout_adjustment)
1538 std::stringstream ss;
1539 Table* t = manage (new Table (2, 6));
1540 t->set_spacings (4);
1544 ss << "<b>" << _("General") << "</b>";
1545 l = manage (left_aligned_label (ss.str()));
1546 l->set_use_markup (true);
1547 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1548 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1550 b = manage (new Button (_("Scan for Plugins")));
1551 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::refresh_clicked));
1552 t->attach (*b, 0, 2, n, n+1, FILL); ++n;
1554 t->attach (_display_plugin_scan_progress, 0, 2, n, n+1); ++n;
1555 _display_plugin_scan_progress.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::display_plugin_scan_progress_toggled));
1556 Gtkmm2ext::UI::instance()->set_tip (_display_plugin_scan_progress,
1557 _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
1559 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT)
1560 _timeout_slider.set_digits (0);
1561 _timeout_adjustment.signal_value_changed().connect (sigc::mem_fun (*this, &PluginOptions::timeout_changed));
1563 Gtkmm2ext::UI::instance()->set_tip(_timeout_slider,
1564 _("Specify the default timeout for plugin instantiation in 1/10 seconds. Plugins that require more time to load will be blacklisted. A value of 0 disables the timeout."));
1566 l = manage (left_aligned_label (_("Scan Time Out [deciseconds]")));;
1567 HBox* h = manage (new HBox);
1569 h->pack_start (*l, false, false);
1570 h->pack_start (_timeout_slider, true, true);
1571 t->attach (*h, 0, 2, n, n+1); ++n;
1574 ss << "<b>" << _("VST") << "</b>";
1575 l = manage (left_aligned_label (ss.str()));
1576 l->set_use_markup (true);
1577 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1578 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1580 b = manage (new Button (_("Clear VST Cache")));
1581 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_cache_clicked));
1582 t->attach (*b, 0, 1, n, n+1, FILL);
1584 b = manage (new Button (_("Clear VST Blacklist")));
1585 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_vst_blacklist_clicked));
1586 t->attach (*b, 1, 2, n, n+1, FILL);
1589 t->attach (_discover_vst_on_start, 0, 2, n, n+1); ++n;
1590 _discover_vst_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_vst_on_start_toggled));
1591 Gtkmm2ext::UI::instance()->set_tip (_discover_vst_on_start,
1592 _("<b>When enabled</b> new VST plugins are searched, tested and added to the cache index on application start. When disabled new plugins will only be available after triggering a 'Scan' manually"));
1594 #ifdef LXVST_SUPPORT
1595 t->attach (*manage (right_aligned_label (_("Linux VST Path:"))), 0, 1, n, n+1);
1596 b = manage (new Button (_("Edit")));
1597 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_lxvst_path_clicked));
1598 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1601 #ifdef WINDOWS_VST_SUPPORT
1602 t->attach (*manage (right_aligned_label (_("Windows VST Path:"))), 0, 1, n, n+1);
1603 b = manage (new Button (_("Edit")));
1604 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::edit_vst_path_clicked));
1605 t->attach (*b, 1, 2, n, n+1, FILL); ++n;
1607 // currently verbose logging is only implemented for Windows VST.
1608 t->attach (_verbose_plugin_scan, 0, 2, n, n+1); ++n;
1609 _verbose_plugin_scan.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::verbose_plugin_scan_toggled));
1610 Gtkmm2ext::UI::instance()->set_tip (_verbose_plugin_scan,
1611 _("<b>When enabled</b> additional information for every plugin is added to the Log Window."));
1615 #ifdef AUDIOUNIT_SUPPORT
1617 ss << "<b>" << _("Audio Unit") << "</b>";
1618 l = manage (left_aligned_label (ss.str()));
1619 l->set_use_markup (true);
1620 t->attach (*manage (new Label ("")), 0, 3, n, n+1, FILL | EXPAND); ++n;
1621 t->attach (*l, 0, 2, n, n+1, FILL | EXPAND); ++n;
1623 t->attach (_discover_au_on_start, 0, 2, n, n+1); ++n;
1624 _discover_au_on_start.signal_toggled().connect (sigc::mem_fun (*this, &PluginOptions::discover_au_on_start_toggled));
1625 Gtkmm2ext::UI::instance()->set_tip (_discover_au_on_start,
1626 _("<b>When enabled</b> Audio Unit Plugins are discovered on application start. When disabled AU plugins will only be available after triggering a 'Scan' manually. The first successful scan will enable AU auto-scan, Any crash during plugin discovery will disable it."));
1629 b = manage (new Button (_("Clear AU Cache")));
1630 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_cache_clicked));
1631 t->attach (*b, 0, 1, n, n+1, FILL);
1633 b = manage (new Button (_("Clear AU Blacklist")));
1634 b->signal_clicked().connect (sigc::mem_fun (*this, &PluginOptions::clear_au_blacklist_clicked));
1635 t->attach (*b, 1, 2, n, n+1, FILL);
1639 _box->pack_start (*t,true,true);
1642 void parameter_changed (string const & p) {
1643 if (p == "show-plugin-scan-window") {
1644 bool const x = UIConfiguration::instance().get_show_plugin_scan_window();
1645 _display_plugin_scan_progress.set_active (x);
1647 else if (p == "discover-vst-on-start") {
1648 bool const x = _rc_config->get_discover_vst_on_start();
1649 _discover_vst_on_start.set_active (x);
1651 else if (p == "vst-scan-timeout") {
1652 int const x = _rc_config->get_vst_scan_timeout();
1653 _timeout_adjustment.set_value (x);
1655 else if (p == "discover-audio-units") {
1656 bool const x = _rc_config->get_discover_audio_units();
1657 _discover_au_on_start.set_active (x);
1659 else if (p == "verbose-plugin-scan") {
1660 bool const x = _rc_config->get_verbose_plugin_scan();
1661 _verbose_plugin_scan.set_active (x);
1665 void set_state_from_config () {
1666 parameter_changed ("show-plugin-scan-window");
1667 parameter_changed ("discover-vst-on-start");
1668 parameter_changed ("vst-scan-timeout");
1669 parameter_changed ("discover-audio-units");
1670 parameter_changed ("verbose-plugin-scan");
1674 RCConfiguration* _rc_config;
1675 CheckButton _display_plugin_scan_progress;
1676 CheckButton _discover_vst_on_start;
1677 CheckButton _discover_au_on_start;
1678 CheckButton _verbose_plugin_scan;
1679 Adjustment _timeout_adjustment;
1680 HScale _timeout_slider;
1682 void display_plugin_scan_progress_toggled () {
1683 bool const x = _display_plugin_scan_progress.get_active();
1684 UIConfiguration::instance().set_show_plugin_scan_window(x);
1687 void discover_vst_on_start_toggled () {
1688 bool const x = _discover_vst_on_start.get_active();
1689 _rc_config->set_discover_vst_on_start(x);
1692 void discover_au_on_start_toggled () {
1693 bool const x = _discover_au_on_start.get_active();
1694 _rc_config->set_discover_audio_units(x);
1697 void verbose_plugin_scan_toggled () {
1698 bool const x = _verbose_plugin_scan.get_active();
1699 _rc_config->set_verbose_plugin_scan(x);
1702 void timeout_changed () {
1703 int x = floor(_timeout_adjustment.get_value());
1704 _rc_config->set_vst_scan_timeout(x);
1707 void clear_vst_cache_clicked () {
1708 PluginManager::instance().clear_vst_cache();
1711 void clear_vst_blacklist_clicked () {
1712 PluginManager::instance().clear_vst_blacklist();
1715 void clear_au_cache_clicked () {
1716 PluginManager::instance().clear_au_cache();
1719 void clear_au_blacklist_clicked () {
1720 PluginManager::instance().clear_au_blacklist();
1724 void edit_vst_path_clicked () {
1725 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1726 _("Set Windows VST Search Path"),
1727 _rc_config->get_plugin_path_vst(),
1728 PluginManager::instance().get_default_windows_vst_path()
1730 ResponseType r = (ResponseType) pd->run ();
1732 if (r == RESPONSE_ACCEPT) {
1733 _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
1738 // todo consolidate with edit_vst_path_clicked..
1739 void edit_lxvst_path_clicked () {
1740 Gtkmm2ext::PathsDialog *pd = new Gtkmm2ext::PathsDialog (
1741 _("Set Linux VST Search Path"),
1742 _rc_config->get_plugin_path_lxvst(),
1743 PluginManager::instance().get_default_lxvst_path()
1745 ResponseType r = (ResponseType) pd->run ();
1747 if (r == RESPONSE_ACCEPT) {
1748 _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
1753 void refresh_clicked () {
1754 PluginManager::instance().refresh();
1759 /** A class which allows control of visibility of some editor components usign
1760 * a VisibilityGroup. The caller should pass in a `dummy' VisibilityGroup
1761 * which has the correct members, but with null widget pointers. This
1762 * class allows the user to set visibility of the members, the details
1763 * of which are stored in a configuration variable which can be watched
1764 * by parts of the editor that actually contain the widgets whose visibility
1765 * is being controlled.
1768 class VisibilityOption : public Option
1771 /** @param name User-visible name for this group.
1772 * @param g `Dummy' VisibilityGroup (as described above).
1773 * @param get Method to get the value of the appropriate configuration variable.
1774 * @param set Method to set the value of the appropriate configuration variable.
1776 VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1777 : Option (g->get_state_name(), name)
1779 , _visibility_group (g)
1783 /* Watch for changes made by the user to our members */
1784 _visibility_group->VisibilityChanged.connect_same_thread (
1785 _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1789 void set_state_from_config ()
1791 /* Set our state from the current configuration */
1792 _visibility_group->set_state (_get ());
1795 void add_to_page (OptionEditorPage* p)
1797 _heading.add_to_page (p);
1798 add_widget_to_page (p, _visibility_group->list_view ());
1801 Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1806 /* The user has changed something, so reflect this change
1807 in the RCConfiguration.
1809 _set (_visibility_group->get_state_value ());
1812 OptionEditorHeading _heading;
1813 VisibilityGroup* _visibility_group;
1814 sigc::slot<std::string> _get;
1815 sigc::slot<bool, std::string> _set;
1816 PBD::ScopedConnection _visibility_group_connection;
1821 RCOptionEditor::RCOptionEditor ()
1822 : OptionEditor (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
1823 , _rc_config (Config)
1824 , _mixer_strip_visibility ("mixer-element-visibility")
1828 uint32_t hwcpus = hardware_concurrency ();
1830 BoolComboOption* bco;
1833 add_option (_("Misc"), new OptionEditorHeading (_("DSP CPU Utilization")));
1835 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
1837 _("Signal processing uses"),
1838 sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
1839 sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
1842 procs->add (-1, _("all but one processor"));
1843 procs->add (0, _("all available processors"));
1845 for (uint32_t i = 1; i <= hwcpus; ++i) {
1846 procs->add (i, string_compose (_("%1 processors"), i));
1849 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
1851 add_option (_("Misc"), procs);
1854 add_option (_("Misc"), new OptionEditorHeading (S_("Options|Undo")));
1856 add_option (_("Misc"), new UndoOptions (_rc_config));
1858 add_option (_("Misc"),
1860 "verify-remove-last-capture",
1861 _("Verify removal of last capture"),
1862 sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
1863 sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
1866 add_option (_("Misc"),
1868 "periodic-safety-backups",
1869 _("Make periodic backups of the session file"),
1870 sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
1871 sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
1874 add_option (_("Misc"), new OptionEditorHeading (_("Session Management")));
1876 add_option (_("Misc"),
1878 "only-copy-imported-files",
1879 _("Always copy imported files"),
1880 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_only_copy_imported_files),
1881 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_only_copy_imported_files)
1884 add_option (_("Misc"), new DirectoryOption (
1885 X_("default-session-parent-dir"),
1886 _("Default folder for new sessions:"),
1887 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
1888 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
1891 add_option (_("Misc"),
1892 new SpinOption<uint32_t> (
1893 "max-recent-sessions",
1894 _("Maximum number of recent sessions"),
1895 sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
1896 sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
1900 add_option (_("Misc"), new OptionEditorHeading (_("Click")));
1902 add_option (_("Misc"), new ClickOptions (_rc_config, this));
1904 add_option (_("Misc"),
1907 _("Click gain level"),
1908 sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
1909 sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
1912 add_option (_("Misc"), new OptionEditorHeading (_("Automation")));
1914 add_option (_("Misc"),
1915 new SpinOption<double> (
1916 "automation-thinning-factor",
1917 _("Thinning factor (larger value => less data)"),
1918 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
1919 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
1923 add_option (_("Misc"),
1924 new SpinOption<double> (
1925 "automation-interval-msecs",
1926 _("Automation sampling interval (milliseconds)"),
1927 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
1928 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
1934 add_option (_("Transport"), new OptionEditorHeading (S_("Transport Options")));
1938 tsf = new BoolOption (
1939 "latched-record-enable",
1940 _("Keep record-enable engaged on stop"),
1941 sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
1942 sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
1944 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1945 add_option (_("Transport"), tsf);
1947 tsf = new BoolOption (
1949 _("Play loop is a transport mode"),
1950 sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
1951 sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
1953 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1954 (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
1955 "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
1956 add_option (_("Transport"), tsf);
1958 tsf = new BoolOption (
1959 "stop-recording-on-xrun",
1960 _("Stop recording when an xrun occurs"),
1961 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
1962 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
1964 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1965 string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
1967 add_option (_("Transport"), tsf);
1969 tsf = new BoolOption (
1970 "create-xrun-marker",
1971 _("Create markers where xruns occur"),
1972 sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
1973 sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
1975 // Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _(""));
1976 add_option (_("Transport"), tsf);
1978 tsf = new BoolOption (
1979 "stop-at-session-end",
1980 _("Stop at the end of the session"),
1981 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
1982 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
1984 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1985 string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
1986 "when it reaches the current session end marker\n\n"
1987 "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
1989 add_option (_("Transport"), tsf);
1991 tsf = new BoolOption (
1993 _("Do seamless looping (not possible when slaved to MTC, LTC etc)"),
1994 sigc::mem_fun (*_rc_config, &RCConfiguration::get_seamless_loop),
1995 sigc::mem_fun (*_rc_config, &RCConfiguration::set_seamless_loop)
1997 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(),
1998 string_compose (_("<b>When enabled</b> this will loop by reading ahead and wrapping around at the loop point, "
1999 "preventing any need to do a transport locate at the end of the loop\n\n"
2000 "<b>When disabled</b> looping is done by locating back to the start of the loop when %1 reaches the end "
2001 "which will often cause a small click or delay"), PROGRAM_NAME));
2002 add_option (_("Transport"), tsf);
2004 tsf = new BoolOption (
2005 "disable-disarm-during-roll",
2006 _("Disable per-track record disarm while rolling"),
2007 sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
2008 sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
2010 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"));
2011 add_option (_("Transport"), tsf);
2013 tsf = new BoolOption (
2015 _("12dB gain reduction during fast-forward and fast-rewind"),
2016 sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
2017 sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
2019 Gtkmm2ext::UI::instance()->set_tip (tsf->tip_widget(), _("This will reduce the unpleasant increase in perceived volume "
2020 "that occurs when fast-forwarding or rewinding through some kinds of audio"));
2021 add_option (_("Transport"), tsf);
2023 add_option (_("Transport"), new OptionEditorHeading (S_("Sync/Slave")));
2025 _sync_source = new ComboOption<SyncSource> (
2027 _("External timecode source"),
2028 sigc::mem_fun (*_rc_config, &RCConfiguration::get_sync_source),
2029 sigc::mem_fun (*_rc_config, &RCConfiguration::set_sync_source)
2032 add_option (_("Transport"), _sync_source);
2034 _sync_framerate = new BoolOption (
2035 "timecode-sync-frame-rate",
2036 _("Match session video frame rate to external timecode"),
2037 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
2038 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
2040 Gtkmm2ext::UI::instance()->set_tip
2041 (_sync_framerate->tip_widget(),
2042 string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
2043 "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
2044 "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
2045 "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
2046 "timecode standard and the session standard."), PROGRAM_NAME));
2048 add_option (_("Transport"), _sync_framerate);
2050 _sync_genlock = new BoolOption (
2051 "timecode-source-is-synced",
2052 _("Sync-lock timecode to clock (disable drift compensation)"),
2053 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_is_synced),
2054 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_is_synced)
2056 Gtkmm2ext::UI::instance()->set_tip
2057 (_sync_genlock->tip_widget(),
2058 string_compose (_("<b>When enabled</b> %1 will never varispeed when slaved to external timecode. "
2059 "Sync Lock indicates that the selected external timecode source shares clock-sync "
2060 "(Black & Burst, Wordclock, etc) with the audio interface. "
2061 "This option disables drift compensation. The transport speed is fixed at 1.0. "
2062 "Vari-speed LTC will be ignored and cause drift."
2064 "<b>When disabled</b> %1 will compensate for potential drift, regardless if the "
2065 "timecode sources shares clock sync."
2069 add_option (_("Transport"), _sync_genlock);
2071 _sync_source_2997 = new BoolOption (
2072 "timecode-source-2997",
2073 _("Lock to 29.9700 fps instead of 30000/1001"),
2074 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_source_2997),
2075 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_source_2997)
2077 Gtkmm2ext::UI::instance()->set_tip
2078 (_sync_source_2997->tip_widget(),
2079 _("<b>When enabled</b> the external timecode source is assumed to use 29.97 fps instead of 30000/1001.\n"
2080 "SMPTE 12M-1999 specifies 29.97df as 30000/1001. The spec further mentions that "
2081 "drop-frame timecode has an accumulated error of -86ms over a 24-hour period.\n"
2082 "Drop-frame timecode would compensate exactly for a NTSC color frame rate of 30 * 0.9990 (ie 29.970000). "
2083 "That is not the actual rate. However, some vendors use that rate - despite it being against the specs - "
2084 "because the variant of using exactly 29.97 fps has zero timecode drift.\n"
2087 add_option (_("Transport"), _sync_source_2997);
2089 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Reader")));
2091 _ltc_port = new ComboStringOption (
2093 _("LTC incoming port"),
2094 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_source_port),
2095 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_source_port)
2098 vector<string> physical_inputs;
2099 physical_inputs.push_back (_("None"));
2100 AudioEngine::instance()->get_physical_inputs (DataType::AUDIO, physical_inputs);
2101 _ltc_port->set_popdown_strings (physical_inputs);
2103 populate_sync_options ();
2105 add_option (_("Transport"), _ltc_port);
2107 // TODO; rather disable this button than not compile it..
2108 add_option (_("Transport"), new OptionEditorHeading (S_("LTC Generator")));
2110 add_option (_("Transport"),
2113 _("Enable LTC generator"),
2114 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
2115 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
2118 _ltc_send_continuously = new BoolOption (
2119 "ltc-send-continuously",
2120 _("Send LTC while stopped"),
2121 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
2122 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
2124 Gtkmm2ext::UI::instance()->set_tip
2125 (_ltc_send_continuously->tip_widget(),
2126 string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
2127 add_option (_("Transport"), _ltc_send_continuously);
2129 _ltc_volume_adjustment = new Gtk::Adjustment(-18, -50, 0, .5, 5);
2130 _ltc_volume_adjustment->set_value (20 * log10(_rc_config->get_ltc_output_volume()));
2131 _ltc_volume_adjustment->signal_value_changed().connect (sigc::mem_fun (*this, &RCOptionEditor::ltc_generator_volume_changed));
2132 _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level"), *_ltc_volume_adjustment);
2134 Gtkmm2ext::UI::instance()->set_tip
2135 (_ltc_volume_slider->tip_widget(),
2136 _("Specify the Peak Volume of the generated LTC signal in dbFS. A good value is 0dBu ^= -18dbFS in an EBU calibrated system"));
2138 add_option (_("Transport"), _ltc_volume_slider);
2139 parameter_changed ("send-ltc");
2141 parameter_changed ("sync-source");
2145 add_option (S_("Editor"),
2147 "draggable-playhead",
2148 _("Allow dragging of playhead"),
2149 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead),
2150 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead)
2153 add_option (_("Editor"),
2155 "automation-follows-regions",
2156 _("Move relevant automation when audio regions are moved"),
2157 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
2158 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
2161 add_option (_("Editor"),
2163 "show-track-meters",
2164 _("Show meters on tracks in the editor"),
2165 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
2166 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_track_meters)
2169 add_option (_("Editor"),
2171 "show-editor-meter",
2172 _("Display master-meter in the toolbar"),
2173 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
2174 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
2177 ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
2178 "default-fade-shape",
2179 _("Default fade shape"),
2180 sigc::mem_fun (*_rc_config,
2181 &RCConfiguration::get_default_fade_shape),
2182 sigc::mem_fun (*_rc_config,
2183 &RCConfiguration::set_default_fade_shape)
2186 fadeshape->add (FadeLinear,
2187 _("Linear (for highly correlated material)"));
2188 fadeshape->add (FadeConstantPower, _("Constant power"));
2189 fadeshape->add (FadeSymmetric, _("Symmetric"));
2190 fadeshape->add (FadeSlow, _("Slow"));
2191 fadeshape->add (FadeFast, _("Fast"));
2193 add_option (_("Editor"), fadeshape);
2196 bco = new BoolComboOption (
2197 "use-overlap-equivalency",
2198 _("Regions in active edit groups are edited together"),
2199 _("whenever they overlap in time"),
2200 _("only if they have identical length, position and origin"),
2201 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_overlap_equivalency),
2202 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_overlap_equivalency)
2205 add_option (_("Editor"), bco);
2207 ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
2209 _("Layering model"),
2210 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
2211 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
2214 lm->add (LaterHigher, _("later is higher"));
2215 lm->add (Manual, _("manual layering"));
2216 add_option (_("Editor"), lm);
2218 add_option (_("Editor"),
2220 "rubberbanding-snaps-to-grid",
2221 _("Make rubberband selection rectangle snap to the grid"),
2222 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
2223 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
2226 add_option (_("Editor"),
2229 _("Show waveforms in regions"),
2230 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
2231 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
2234 add_option (_("Editor"),
2235 new BoolComboOption (
2236 "show-region-gain-envelopes",
2237 _("Show gain envelopes in audio regions"),
2239 _("only in Draw and Internal Edit modes"),
2240 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
2241 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
2244 ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
2246 _("Waveform scale"),
2247 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_scale),
2248 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_scale)
2251 wfs->add (Linear, _("linear"));
2252 wfs->add (Logarithmic, _("logarithmic"));
2254 add_option (_("Editor"), wfs);
2256 ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
2258 _("Waveform shape"),
2259 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_shape),
2260 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_shape)
2263 wfsh->add (Traditional, _("traditional"));
2264 wfsh->add (Rectified, _("rectified"));
2266 add_option (_("Editor"), wfsh);
2268 add_option (_("Editor"), new ClipLevelOptions ());
2270 add_option (_("Editor"),
2272 "show-waveforms-while-recording",
2273 _("Show waveforms for audio while it is being recorded"),
2274 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
2275 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
2278 add_option (_("Editor"),
2281 _("Show zoom toolbar"),
2282 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_zoom_tools),
2283 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_zoom_tools)
2286 add_option (_("Editor"),
2288 "update-editor-during-summary-drag",
2289 _("Update editor window during drags of the summary"),
2290 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
2291 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
2294 bo = new BoolOption (
2296 _("Name new markers"),
2297 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
2298 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
2301 add_option (_("Editor"), bo);
2302 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."
2303 "\n\nYou can always rename markers by right-clicking on them"));
2305 add_option (_("Editor"),
2307 "autoscroll-editor",
2308 _("Auto-scroll editor window when dragging near its edges"),
2309 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
2310 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
2313 ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
2314 "region-selection-after-split",
2315 _("After splitting selected regions, select"),
2316 sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
2317 sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
2319 // TODO: decide which of these modes are really useful
2320 rsas->add(None, _("no regions"));
2321 // rsas->add(NewlyCreatedLeft, _("newly-created regions before the split"));
2322 // rsas->add(NewlyCreatedRight, _("newly-created regions after the split"));
2323 rsas->add(NewlyCreatedBoth, _("newly-created regions"));
2324 // rsas->add(Existing, _("unmodified regions in the existing selection"));
2325 // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
2326 // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
2327 rsas->add(ExistingNewlyCreatedBoth, _("existing selection and newly-created regions"));
2329 add_option (_("Editor"), rsas);
2334 add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
2336 add_option (_("Audio"), new BufferingOptions (_rc_config));
2338 add_option (_("Audio"), new OptionEditorHeading (_("Monitoring")));
2340 ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
2342 _("Record monitoring handled by"),
2343 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
2344 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
2347 if (AudioEngine::instance()->port_engine().can_monitor_input()) {
2348 mm->add (HardwareMonitoring, _("via Audio Driver"));
2351 string prog (PROGRAM_NAME);
2352 boost::algorithm::to_lower (prog);
2353 mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
2354 mm->add (ExternalMonitoring, _("audio hardware"));
2356 add_option (_("Audio"), mm);
2358 add_option (_("Audio"),
2360 "tape-machine-mode",
2361 _("Tape machine mode"),
2362 sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
2363 sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
2366 add_option (_("Audio"), new OptionEditorHeading (_("Connection of tracks and busses")));
2368 add_option (_("Audio"),
2370 "auto-connect-standard-busses",
2371 _("Auto-connect master/monitor busses"),
2372 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
2373 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
2376 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
2377 "input-auto-connect",
2378 _("Connect track inputs"),
2379 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
2380 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
2383 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
2384 iac->add (ManualConnect, _("manually"));
2386 add_option (_("Audio"), iac);
2388 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
2389 "output-auto-connect",
2390 _("Connect track and bus outputs"),
2391 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
2392 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
2395 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
2396 oac->add (AutoConnectMaster, _("automatically to master bus"));
2397 oac->add (ManualConnect, _("manually"));
2399 add_option (_("Audio"), oac);
2401 add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
2403 add_option (_("Audio"),
2405 "denormal-protection",
2406 _("Use DC bias to protect against denormals"),
2407 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
2408 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
2411 ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
2413 _("Processor handling"),
2414 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
2415 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
2419 dm->add (DenormalNone, _("no processor handling"));
2421 FPU* fpu = FPU::instance();
2423 if (fpu->has_flush_to_zero()) {
2425 dm->add (DenormalFTZ, _("use FlushToZero"));
2426 } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
2427 _rc_config->set_denormal_model(DenormalNone);
2430 if (fpu->has_denormals_are_zero()) {
2432 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
2433 } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
2434 _rc_config->set_denormal_model(DenormalNone);
2437 if (fpu->has_flush_to_zero() && fpu->has_denormals_are_zero()) {
2439 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
2440 } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
2441 _rc_config->set_denormal_model(DenormalNone);
2445 dm->set_sensitive(false);
2448 add_option (_("Audio"), dm);
2450 add_option (_("Audio"), new OptionEditorHeading (_("Plugins")));
2452 add_option (_("Audio"),
2454 "plugins-stop-with-transport",
2455 _("Silence plugins when the transport is stopped"),
2456 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
2457 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
2460 add_option (_("Audio"),
2462 "new-plugins-active",
2463 _("Make new plugins active"),
2464 sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
2465 sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
2468 add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
2470 add_option (_("Audio"),
2472 "auto-analyse-audio",
2473 _("Enable automatic analysis of audio"),
2474 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
2475 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
2478 add_option (_("Audio"),
2480 "replicate-missing-region-channels",
2481 _("Replicate missing region channels"),
2482 sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
2483 sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
2488 add_option (_("Solo / mute"), new OptionEditorHeading (_("Solo")));
2490 add_option (_("Solo / mute"),
2493 _("Solo-in-place mute cut (dB)"),
2494 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
2495 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
2498 _solo_control_is_listen_control = new BoolOption (
2499 "solo-control-is-listen-control",
2500 _("Solo controls are Listen controls"),
2501 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
2502 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
2505 add_option (_("Solo / mute"), _solo_control_is_listen_control);
2507 _listen_position = new ComboOption<ListenPosition> (
2509 _("Listen Position"),
2510 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
2511 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
2514 _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
2515 _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
2517 add_option (_("Solo / mute"), _listen_position);
2519 ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
2521 _("PFL signals come from"),
2522 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
2523 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
2526 pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2527 pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2529 add_option (_("Solo / mute"), pp);
2531 ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2533 _("AFL signals come from"),
2534 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2535 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2538 pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2539 pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2541 add_option (_("Solo / mute"), pa);
2543 parameter_changed ("use-monitor-bus");
2545 add_option (_("Solo / mute"),
2548 _("Exclusive solo"),
2549 sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2550 sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2553 add_option (_("Solo / mute"),
2556 _("Show solo muting"),
2557 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2558 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2561 add_option (_("Solo / mute"),
2563 "solo-mute-override",
2564 _("Soloing overrides muting"),
2565 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2566 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2569 add_option (_("Solo / mute"), new OptionEditorHeading (_("Default track / bus muting options")));
2571 add_option (_("Solo / mute"),
2573 "mute-affects-pre-fader",
2574 _("Mute affects pre-fader sends"),
2575 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2576 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2579 add_option (_("Solo / mute"),
2581 "mute-affects-post-fader",
2582 _("Mute affects post-fader sends"),
2583 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2584 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2587 add_option (_("Solo / mute"),
2589 "mute-affects-control-outs",
2590 _("Mute affects control outputs"),
2591 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2592 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2595 add_option (_("Solo / mute"),
2597 "mute-affects-main-outs",
2598 _("Mute affects main outputs"),
2599 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2600 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2603 add_option (_("Solo / mute"), new OptionEditorHeading (_("Send Routing")));
2605 add_option (_("Solo / mute"),
2607 "link-send-and-route-panner",
2608 _("Link panners of Aux and External Sends with main panner by default"),
2609 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2610 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2613 add_option (_("MIDI"),
2614 new SpinOption<float> (
2616 _("MIDI read-ahead time (seconds)"),
2617 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_readahead),
2618 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_readahead),
2623 add_option (_("MIDI"),
2626 _("Send MIDI Clock"),
2627 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
2628 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
2631 add_option (_("MIDI"),
2634 _("Send MIDI Time Code"),
2635 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
2636 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
2639 add_option (_("MIDI"),
2640 new SpinOption<int> (
2641 "mtc-qf-speed-tolerance",
2642 _("Percentage either side of normal transport speed to transmit MTC"),
2643 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
2644 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
2648 add_option (_("MIDI"),
2651 _("Obey MIDI Machine Control commands"),
2652 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
2653 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
2656 add_option (_("MIDI"),
2659 _("Send MIDI Machine Control commands"),
2660 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
2661 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
2664 add_option (_("MIDI"),
2667 _("Send MIDI control feedback"),
2668 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_feedback),
2669 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_feedback)
2672 add_option (_("MIDI"),
2673 new SpinOption<uint8_t> (
2674 "mmc-receive-device-id",
2675 _("Inbound MMC device ID"),
2676 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
2677 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
2681 add_option (_("MIDI"),
2682 new SpinOption<uint8_t> (
2683 "mmc-send-device-id",
2684 _("Outbound MMC device ID"),
2685 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
2686 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
2690 add_option (_("MIDI"),
2691 new SpinOption<int32_t> (
2692 "initial-program-change",
2693 _("Initial program change"),
2694 sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2695 sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2699 add_option (_("MIDI"),
2701 "display-first-midi-bank-as-zero",
2702 _("Display first MIDI bank/program as 0"),
2703 sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
2704 sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
2707 add_option (_("MIDI"),
2709 "never-display-periodic-midi",
2710 _("Never display periodic MIDI messages (MTC, MIDI Clock)"),
2711 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
2712 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
2715 add_option (_("MIDI"),
2718 _("Sound MIDI notes as they are selected"),
2719 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
2720 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
2723 add_option (_("MIDI"), new OptionEditorHeading (_("Midi Audition")));
2725 ComboOption<std::string>* audition_synth = new ComboOption<std::string> (
2726 "midi-audition-synth-uri",
2727 _("Midi Audition Synth (LV2)"),
2728 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_audition_synth_uri),
2729 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_audition_synth_uri)
2732 audition_synth->add(X_(""), _("None"));
2733 PluginInfoList all_plugs;
2734 PluginManager& manager (PluginManager::instance());
2736 all_plugs.insert (all_plugs.end(), manager.lv2_plugin_info().begin(), manager.lv2_plugin_info().end());
2738 for (PluginInfoList::const_iterator i = all_plugs.begin(); i != all_plugs.end(); ++i) {
2739 if (manager.get_status (*i) == PluginManager::Hidden) continue;
2740 if (!(*i)->is_instrument()) continue;
2741 if ((*i)->type != ARDOUR::LV2) continue;
2742 audition_synth->add((*i)->unique_id, (*i)->name);
2746 add_option (_("MIDI"), audition_synth);
2748 /* USER INTERACTION */
2751 #ifdef PLATFORM_WINDOWS
2754 getenv ("ARDOUR_BUNDLED")
2758 add_option (_("User interaction"),
2760 "enable-translation",
2761 string_compose (_("Use translations of %1 messages\n"
2762 " <i>(requires a restart of %1 to take effect)</i>\n"
2763 " <i>(if available for your language preferences)</i>"), PROGRAM_NAME),
2764 sigc::ptr_fun (ARDOUR::translations_are_enabled),
2765 sigc::ptr_fun (ARDOUR::set_translations_enabled)));
2768 add_option (_("User interaction"), new OptionEditorHeading (_("Keyboard")));
2770 add_option (_("User interaction"), new KeyboardOptions);
2772 /* Control Surfaces */
2774 add_option (_("Control Surfaces"), new ControlSurfacesOptions (*this));
2776 ComboOption<RemoteModel>* rm = new ComboOption<RemoteModel> (
2778 _("Control surface remote ID"),
2779 sigc::mem_fun (*_rc_config, &RCConfiguration::get_remote_model),
2780 sigc::mem_fun (*_rc_config, &RCConfiguration::set_remote_model)
2783 rm->add (UserOrdered, _("assigned by user"));
2784 rm->add (MixerOrdered, _("follows order of mixer"));
2786 add_option (_("Control Surfaces"), rm);
2788 /* VIDEO Timeline */
2789 add_option (_("Video"), new VideoTimelineOptions (_rc_config));
2791 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
2792 /* Plugin options (currrently VST only) */
2793 add_option (_("Plugins"), new PluginOptions (_rc_config));
2798 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
2799 BoolOption* bgc = new BoolOption (
2800 "cairo-image-surface",
2801 _("Disable Graphics Hardware Acceleration (requires restart)"),
2802 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_cairo_image_surface),
2803 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_cairo_image_surface)
2806 Gtkmm2ext::UI::instance()->set_tip (bgc->tip_widget(), string_compose (
2807 _("Render large parts of the application user-interface in software, instead of using 2D-graphics acceleration.\nThis requires restarting %1 before having an effect"), PROGRAM_NAME));
2808 add_option (S_("Preferences|GUI"), bgc);
2811 #ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
2812 BoolOption* bgo = new BoolOption (
2814 _("Possibly improve slow graphical performance (requires restart)"),
2815 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_buggy_gradients),
2816 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_buggy_gradients)
2819 Gtkmm2ext::UI::instance()->set_tip (bgo->tip_widget(), string_compose (_("Disables hardware gradient rendering on buggy video drivers (\"buggy gradients patch\").\nThis requires restarting %1 before having an effect"), PROGRAM_NAME));
2820 add_option (S_("Preferences|GUI"), bgo);
2823 add_option (S_("Preferences|GUI"),
2826 _("Graphically indicate mouse pointer hovering over various widgets"),
2827 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_widget_prelight),
2828 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_widget_prelight)
2831 #ifdef TOOLTIPS_GOT_FIXED
2832 add_option (S_("Preferences|GUI"),
2835 _("Show tooltips if mouse hovers over a control"),
2836 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_tooltips),
2837 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_tooltips)
2841 add_option (S_("Preferences|GUI"),
2843 "show-name-highlight",
2844 _("Use name highlight bars in region displays (requires a restart)"),
2845 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_name_highlight),
2846 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_name_highlight)
2850 /* font scaling does nothing with GDK/Quartz */
2851 add_option (S_("Preferences|GUI"), new FontScalingOptions ());
2854 add_option (S_("GUI"),
2856 "super-rapid-clock-update",
2857 _("update transport clock display at FPS instead of every 100ms"),
2858 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
2859 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
2863 /* Image cache size */
2865 Gtk::Adjustment *ics = manage (new Gtk::Adjustment(0, 1, 1024, 10)); /* 1 MB to 1GB in steps of 10MB */
2866 HSliderOption *sics = new HSliderOption("waveform-cache-size",
2867 _("Waveform image cache size (megabytes)"),
2869 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_cache_size),
2870 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_cache_size)
2872 sics->scale().set_digits (0);
2873 Gtkmm2ext::UI::instance()->set_tip
2874 (sics->tip_widget(),
2875 _("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
2876 add_option (S_("Preferences|GUI"), sics);
2878 /* Lock GUI timeout */
2880 Gtk::Adjustment *lts = manage (new Gtk::Adjustment(0, 0, 1000, 1, 10));
2881 HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2882 _("Lock timeout (seconds)"),
2884 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_lock_gui_after_seconds),
2885 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_lock_gui_after_seconds)
2887 slts->scale().set_digits (0);
2888 Gtkmm2ext::UI::instance()->set_tip
2889 (slts->tip_widget(),
2890 _("Lock GUI after this many idle seconds (zero to never lock)"));
2891 add_option (S_("Preferences|GUI"), slts);
2893 /* The names of these controls must be the same as those given in MixerStrip
2894 for the actual widgets being controlled.
2896 _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
2897 _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
2898 _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
2899 _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
2900 _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
2901 _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
2904 S_("Preferences|GUI"),
2905 new VisibilityOption (
2907 &_mixer_strip_visibility,
2908 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_mixer_strip_visibility),
2909 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_mixer_strip_visibility)
2913 add_option (S_("Preferences|GUI"),
2915 "default-narrow_ms",
2916 _("Use narrow strips in the mixer by default"),
2917 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_default_narrow_ms),
2918 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
2921 add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2923 ComboOption<float>* mht = new ComboOption<float> (
2925 _("Peak hold time"),
2926 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_hold),
2927 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_hold)
2930 mht->add (MeterHoldOff, _("off"));
2931 mht->add (MeterHoldShort, _("short"));
2932 mht->add (MeterHoldMedium, _("medium"));
2933 mht->add (MeterHoldLong, _("long"));
2935 add_option (S_("Preferences|Metering"), mht);
2937 ComboOption<float>* mfo = new ComboOption<float> (
2940 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2941 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2944 mfo->add (METER_FALLOFF_OFF, _("off"));
2945 mfo->add (METER_FALLOFF_SLOWEST, _("slowest [6.6dB/sec]"));
2946 mfo->add (METER_FALLOFF_SLOW, _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2947 mfo->add (METER_FALLOFF_SLOWISH, _("moderate [12.0dB/sec] (DIN)"));
2948 mfo->add (METER_FALLOFF_MODERATE, _("medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2949 mfo->add (METER_FALLOFF_MEDIUM, _("fast [20dB/sec]"));
2950 mfo->add (METER_FALLOFF_FAST, _("very fast [32dB/sec]"));
2952 add_option (S_("Preferences|Metering"), mfo);
2954 ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2955 "meter-line-up-level",
2956 _("Meter line-up level; 0dBu"),
2957 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_level),
2958 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_level)
2961 mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2962 mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2963 mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2964 mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2966 Gtkmm2ext::UI::instance()->set_tip (mlu->tip_widget(), _("Configure meter-marks and color-knee point for dBFS scale DPM, set reference level for IEC1/Nordic, IEC2 PPM and VU meter."));
2968 add_option (S_("Preferences|Metering"), mlu);
2970 ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2971 "meter-line-up-din",
2972 _("IEC1/DIN Meter line-up level; 0dBu"),
2973 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_din),
2974 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_din)
2977 mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2978 mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2979 mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2980 mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2982 Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2984 add_option (S_("Preferences|Metering"), mld);
2986 ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2987 "meter-vu-standard",
2988 _("VU Meter standard"),
2989 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_vu_standard),
2990 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_vu_standard)
2993 mvu->add (MeteringVUfrench, _("0VU = -2dBu (France)"));
2994 mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2995 mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
2996 mvu->add (MeteringVUeight, _("0VU = +8dBu"));
2998 add_option (S_("Preferences|Metering"), mvu);
3000 Gtk::Adjustment *mpk = manage (new Gtk::Adjustment(0, -10, 0, .1, .1));
3001 HSliderOption *mpks = new HSliderOption("meter-peak",
3002 _("Peak threshold [dBFS]"),
3004 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_peak),
3005 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_peak)
3009 ComboOption<MeterType>* mtm = new ComboOption<MeterType> (
3010 "meter-type-master",
3011 _("Default Meter Type for Master Bus"),
3012 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_master),
3013 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_master)
3015 mtm->add (MeterPeak, ArdourMeter::meter_type_string(MeterPeak));
3016 mtm->add (MeterK20, ArdourMeter::meter_type_string(MeterK20));
3017 mtm->add (MeterK14, ArdourMeter::meter_type_string(MeterK14));
3018 mtm->add (MeterK12, ArdourMeter::meter_type_string(MeterK12));
3019 mtm->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3020 mtm->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3021 mtm->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3022 mtm->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3024 add_option (S_("Preferences|Metering"), mtm);
3027 ComboOption<MeterType>* mtb = new ComboOption<MeterType> (
3029 _("Default Meter Type for Busses"),
3030 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_bus),
3031 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_bus)
3033 mtb->add (MeterPeak, ArdourMeter::meter_type_string(MeterPeak));
3034 mtb->add (MeterK20, ArdourMeter::meter_type_string(MeterK20));
3035 mtb->add (MeterK14, ArdourMeter::meter_type_string(MeterK14));
3036 mtb->add (MeterK12, ArdourMeter::meter_type_string(MeterK12));
3037 mtb->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3038 mtb->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3039 mtb->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3040 mtb->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3042 add_option (S_("Preferences|Metering"), mtb);
3044 ComboOption<MeterType>* mtt = new ComboOption<MeterType> (
3046 _("Default Meter Type for Tracks"),
3047 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_track),
3048 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_track)
3050 mtt->add (MeterPeak, ArdourMeter::meter_type_string(MeterPeak));
3051 mtt->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
3053 add_option (S_("Preferences|Metering"), mtt);
3056 Gtkmm2ext::UI::instance()->set_tip
3057 (mpks->tip_widget(),
3058 _("Specify the audio signal level in dbFS at and above which the meter-peak indicator will flash red."));
3060 add_option (S_("Preferences|Metering"), mpks);
3062 add_option (S_("Preferences|Metering"),
3065 _("LED meter style"),
3066 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_style_led),
3067 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_style_led)
3070 /* and now the theme manager */
3072 ThemeManager* tm = manage (new ThemeManager);
3073 add_page (_("Theme"), *tm);
3077 RCOptionEditor::parameter_changed (string const & p)
3079 OptionEditor::parameter_changed (p);
3081 if (p == "use-monitor-bus") {
3082 bool const s = Config->get_use_monitor_bus ();
3084 /* we can't use this if we don't have a monitor bus */
3085 Config->set_solo_control_is_listen_control (false);
3087 _solo_control_is_listen_control->set_sensitive (s);
3088 _listen_position->set_sensitive (s);
3089 } else if (p == "sync-source") {
3090 _sync_source->set_sensitive (true);
3092 _sync_source->set_sensitive (!_session->config.get_external_sync());
3094 switch(Config->get_sync_source()) {
3097 _sync_genlock->set_sensitive (true);
3098 _sync_framerate->set_sensitive (true);
3099 _sync_source_2997->set_sensitive (true);
3102 _sync_genlock->set_sensitive (false);
3103 _sync_framerate->set_sensitive (false);
3104 _sync_source_2997->set_sensitive (false);
3107 } else if (p == "send-ltc") {
3108 bool const s = Config->get_send_ltc ();
3109 _ltc_send_continuously->set_sensitive (s);
3110 _ltc_volume_slider->set_sensitive (s);
3114 void RCOptionEditor::ltc_generator_volume_changed () {
3115 _rc_config->set_ltc_output_volume (pow(10, _ltc_volume_adjustment->get_value() / 20));
3119 RCOptionEditor::populate_sync_options ()
3121 vector<SyncSource> sync_opts = ARDOUR::get_available_sync_options ();
3123 _sync_source->clear ();
3125 for (vector<SyncSource>::iterator i = sync_opts.begin(); i != sync_opts.end(); ++i) {
3126 _sync_source->add (*i, sync_source_to_string (*i));
3129 if (sync_opts.empty()) {
3130 _sync_source->set_sensitive(false);
3132 if (std::find(sync_opts.begin(), sync_opts.end(), _rc_config->get_sync_source()) == sync_opts.end()) {
3133 _rc_config->set_sync_source(sync_opts.front());