2 * Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
3 * Copyright (C) 2009-2015 David Robillard <d@drobilla.net>
4 * Copyright (C) 2009-2019 Paul Davis <paul@linuxaudiosystems.com>
5 * Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
6 * Copyright (C) 2013-2016 Nick Mainsbridge <mainsbridge@gmail.com>
7 * Copyright (C) 2013-2018 Colin Fletcher <colin.m.fletcher@googlemail.com>
8 * Copyright (C) 2013 John Emmas <john@creativepost.co.uk>
9 * Copyright (C) 2014-2016 Tim Mayberry <mojofunk@gmail.com>
10 * Copyright (C) 2014-2019 Ben Loftis <ben@harrisonconsoles.com>
11 * Copyright (C) 2018 Len Ovens <len@ovenwerks.net>
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 #include "gtk2ardour-config.h"
32 #if !defined USE_CAIRO_IMAGE_SURFACE && !defined NDEBUG
33 #define OPTIONAL_CAIRO_IMAGE_SURFACE
36 #include <cairo/cairo.h>
38 #include <boost/algorithm/string.hpp>
40 #include <gtkmm/liststore.h>
41 #include <gtkmm/stock.h>
42 #include <gtkmm/scale.h>
44 #include "gtkmm2ext/utils.h"
45 #include "gtkmm2ext/gtk_ui.h"
46 #include "gtkmm2ext/window_title.h"
52 #include "ardour/audio_backend.h"
53 #include "ardour/audioengine.h"
54 #include "ardour/control_protocol_manager.h"
55 #include "ardour/dB.h"
56 #include "ardour/port_manager.h"
57 #include "ardour/plugin_manager.h"
58 #include "ardour/profile.h"
59 #include "ardour/rc_configuration.h"
60 #include "ardour/transport_master_manager.h"
62 #include "control_protocol/control_protocol.h"
64 #include "waveview/wave_view.h"
66 #include "widgets/paths_dialog.h"
67 #include "widgets/tooltips.h"
69 #include "ardour_dialog.h"
70 #include "ardour_ui.h"
71 #include "ardour_window.h"
72 #include "color_theme_manager.h"
73 #include "gui_thread.h"
75 #include "meter_patterns.h"
76 #include "midi_tracer.h"
77 #include "plugin_scan_dialog.h"
78 #include "rc_option_editor.h"
80 #include "transport_masters_dialog.h"
81 #include "ui_config.h"
86 using namespace Gtkmm2ext;
88 using namespace ARDOUR;
89 using namespace ARDOUR_UI_UTILS;
90 using namespace ArdourWidgets;
92 class ClickOptions : public OptionEditorMiniPage
95 ClickOptions (RCConfiguration* c)
97 , _click_browse_button (_("Browse..."))
98 , _click_emphasis_browse_button (_("Browse..."))
100 // TODO get rid of GTK -> use OptionEditor Widgets
105 l = manage (left_aligned_label (_("Emphasis on first beat")));
106 _use_emphasis_on_click_check_button.add (*l);
107 t->attach (_use_emphasis_on_click_check_button, 1, 3, row, row + 1, FILL);
108 _use_emphasis_on_click_check_button.signal_toggled().connect (
109 sigc::mem_fun (*this, &ClickOptions::use_emphasis_on_click_toggled));
112 l = manage (left_aligned_label (_("Use built-in default sounds")));
113 _use_default_click_check_button.add (*l);
114 t->attach (_use_default_click_check_button, 1, 3, row, row + 1, FILL);
115 _use_default_click_check_button.signal_toggled().connect (
116 sigc::mem_fun (*this, &ClickOptions::use_default_click_toggled));
119 l = manage (left_aligned_label (_("Audio file:")));
120 t->attach (*l, 1, 2, row, row + 1, FILL);
121 t->attach (_click_path_entry, 2, 3, row, row + 1, FILL);
122 _click_browse_button.signal_clicked ().connect (
123 sigc::mem_fun (*this, &ClickOptions::click_browse_clicked));
124 t->attach (_click_browse_button, 3, 4, row, row + 1, FILL);
127 l = manage (left_aligned_label (_("Emphasis audio file:")));
128 t->attach (*l, 1, 2, row, row + 1, FILL);
129 t->attach (_click_emphasis_path_entry, 2, 3, row, row + 1, FILL);
130 _click_emphasis_browse_button.signal_clicked ().connect (
131 sigc::mem_fun (*this, &ClickOptions::click_emphasis_browse_clicked));
132 t->attach (_click_emphasis_browse_button, 3, 4, row, row + 1, FILL);
135 _click_fader = new FaderOption (
138 sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_gain),
139 sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_gain)
142 _click_fader->add_to_page (this);
143 _click_fader->set_state_from_config ();
145 _click_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_changed));
146 _click_emphasis_path_entry.signal_activate().connect (sigc::mem_fun (*this, &ClickOptions::click_emphasis_changed));
148 if (_rc_config->get_click_sound ().empty() &&
149 _rc_config->get_click_emphasis_sound().empty()) {
150 _use_default_click_check_button.set_active (true);
151 _use_emphasis_on_click_check_button.set_active (_rc_config->get_use_click_emphasis ());
154 _use_default_click_check_button.set_active (false);
155 _use_emphasis_on_click_check_button.set_active (false);
159 void parameter_changed (string const & p)
161 if (p == "click-sound") {
162 _click_path_entry.set_text (_rc_config->get_click_sound());
163 } else if (p == "click-emphasis-sound") {
164 _click_emphasis_path_entry.set_text (_rc_config->get_click_emphasis_sound());
165 } else if (p == "use-click-emphasis") {
166 bool x = _rc_config->get_use_click_emphasis ();
167 _use_emphasis_on_click_check_button.set_active (x);
168 } else if (p == "click-gain") {
169 _click_fader->set_state_from_config ();
173 void set_state_from_config ()
175 parameter_changed ("click-sound");
176 parameter_changed ("click-emphasis-sound");
177 parameter_changed ("use-click-emphasis");
182 void click_browse_clicked ()
184 SoundFileChooser sfdb (_("Choose Click"));
189 if (sfdb.run () == RESPONSE_OK) {
190 click_chosen (sfdb.get_filename());
194 void click_chosen (string const & path)
196 _click_path_entry.set_text (path);
197 _rc_config->set_click_sound (path);
200 void click_changed ()
202 click_chosen (_click_path_entry.get_text ());
205 void click_emphasis_browse_clicked ()
207 SoundFileChooser sfdb (_("Choose Click Emphasis"));
212 if (sfdb.run () == RESPONSE_OK) {
213 click_emphasis_chosen (sfdb.get_filename());
217 void click_emphasis_chosen (string const & path)
219 _click_emphasis_path_entry.set_text (path);
220 _rc_config->set_click_emphasis_sound (path);
223 void click_emphasis_changed ()
225 click_emphasis_chosen (_click_emphasis_path_entry.get_text ());
228 void use_default_click_toggled ()
230 if (_use_default_click_check_button.get_active ()) {
231 _rc_config->set_click_sound ("");
232 _rc_config->set_click_emphasis_sound ("");
233 _click_path_entry.set_sensitive (false);
234 _click_emphasis_path_entry.set_sensitive (false);
235 _click_browse_button.set_sensitive (false);
236 _click_emphasis_browse_button.set_sensitive (false);
238 _click_path_entry.set_sensitive (true);
239 _click_emphasis_path_entry.set_sensitive (true);
240 _click_browse_button.set_sensitive (true);
241 _click_emphasis_browse_button.set_sensitive (true);
245 void use_emphasis_on_click_toggled ()
247 if (_use_emphasis_on_click_check_button.get_active ()) {
248 _rc_config->set_use_click_emphasis(true);
250 _rc_config->set_use_click_emphasis(false);
254 RCConfiguration* _rc_config;
255 CheckButton _use_default_click_check_button;
256 CheckButton _use_emphasis_on_click_check_button;
257 Entry _click_path_entry;
258 Entry _click_emphasis_path_entry;
259 Button _click_browse_button;
260 Button _click_emphasis_browse_button;
261 FaderOption* _click_fader;
264 class UndoOptions : public OptionEditorComponent
267 UndoOptions (RCConfiguration* c) :
269 _limit_undo_button (_("Limit undo history to")),
270 _save_undo_button (_("Save undo history of"))
272 // TODO get rid of GTK -> use OptionEditor SpinOption
273 _limit_undo_spin.set_range (0, 512);
274 _limit_undo_spin.set_increments (1, 10);
276 _save_undo_spin.set_range (0, 512);
277 _save_undo_spin.set_increments (1, 10);
279 _limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
280 _limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
281 _save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
282 _save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
285 void parameter_changed (string const & p)
287 if (p == "history-depth") {
288 int32_t const d = _rc_config->get_history_depth();
289 _limit_undo_button.set_active (d != 0);
290 _limit_undo_spin.set_sensitive (d != 0);
291 _limit_undo_spin.set_value (d);
292 } else if (p == "save-history") {
293 bool const x = _rc_config->get_save_history ();
294 _save_undo_button.set_active (x);
295 _save_undo_spin.set_sensitive (x);
296 } else if (p == "save-history-depth") {
297 _save_undo_spin.set_value (_rc_config->get_saved_history_depth());
301 void set_state_from_config ()
303 parameter_changed ("save-history");
304 parameter_changed ("history-depth");
305 parameter_changed ("save-history-depth");
308 void limit_undo_toggled ()
310 bool const x = _limit_undo_button.get_active ();
311 _limit_undo_spin.set_sensitive (x);
312 int32_t const n = x ? 16 : 0;
313 _limit_undo_spin.set_value (n);
314 _rc_config->set_history_depth (n);
317 void limit_undo_changed ()
319 _rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
322 void save_undo_toggled ()
324 bool const x = _save_undo_button.get_active ();
325 _rc_config->set_save_history (x);
328 void save_undo_changed ()
330 _rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
333 void add_to_page (OptionEditorPage* p)
335 int const n = p->table.property_n_rows();
336 Table* t = & p->table;
338 t->resize (n + 2, 3);
340 Label* l = manage (left_aligned_label (_("commands")));
341 HBox* box = manage (new HBox());
342 box->set_spacing (4);
343 box->pack_start (_limit_undo_spin, false, false);
344 box->pack_start (*l, true, true);
345 t->attach (_limit_undo_button, 1, 2, n, n +1, FILL);
346 t->attach (*box, 2, 3, n, n + 1, FILL | EXPAND);
348 l = manage (left_aligned_label (_("commands")));
349 box = manage (new HBox());
350 box->set_spacing (4);
351 box->pack_start (_save_undo_spin, false, false);
352 box->pack_start (*l, true, true);
353 t->attach (_save_undo_button, 1, 2, n + 1, n + 2, FILL);
354 t->attach (*box, 2, 3, n + 1, n + 2, FILL | EXPAND);
357 Gtk::Widget& tip_widget() {
358 return _limit_undo_button; // unused
362 RCConfiguration* _rc_config;
363 CheckButton _limit_undo_button;
364 SpinButton _limit_undo_spin;
365 CheckButton _save_undo_button;
366 SpinButton _save_undo_spin;
370 static const struct {
382 { "Key|Shift", GDK_SHIFT_MASK },
383 { "Command", GDK_MOD2_MASK },
384 { "Control", GDK_CONTROL_MASK },
385 { "Option", GDK_MOD1_MASK },
386 { "Command-Shift", GDK_MOD2_MASK|GDK_SHIFT_MASK },
387 { "Command-Option", GDK_MOD2_MASK|GDK_MOD1_MASK },
388 { "Command-Control", GDK_MOD2_MASK|GDK_CONTROL_MASK },
389 { "Command-Option-Control", GDK_MOD2_MASK|GDK_MOD1_MASK|GDK_CONTROL_MASK },
390 { "Option-Control", GDK_MOD1_MASK|GDK_CONTROL_MASK },
391 { "Option-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
392 { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
393 { "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_MOD2_MASK },
396 { "Key|Shift", GDK_SHIFT_MASK },
397 { "Control", GDK_CONTROL_MASK },
398 { "Alt", GDK_MOD1_MASK },
399 { "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
400 { "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
401 { "Control-Windows", GDK_CONTROL_MASK|GDK_MOD4_MASK },
402 { "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
403 { "Alt-Windows", GDK_MOD1_MASK|GDK_MOD4_MASK },
404 { "Alt-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
405 { "Alt-Shift-Windows", GDK_MOD1_MASK|GDK_SHIFT_MASK|GDK_MOD4_MASK },
406 { "Mod2", GDK_MOD2_MASK },
407 { "Mod3", GDK_MOD3_MASK },
408 { "Windows", GDK_MOD4_MASK },
409 { "Mod5", GDK_MOD5_MASK },
415 class KeyboardOptions : public OptionEditorMiniPage
419 : _delete_button_adjustment (3, 1, 12)
420 , _delete_button_spin (_delete_button_adjustment)
421 , _edit_button_adjustment (3, 1, 5)
422 , _edit_button_spin (_edit_button_adjustment)
423 , _insert_note_button_adjustment (3, 1, 5)
424 , _insert_note_button_spin (_insert_note_button_adjustment)
426 // TODO get rid of GTK -> use OptionEditor Widgets
428 const std::string restart_msg = _("\nChanges to this setting will only persist after your project has been saved.");
429 /* internationalize and prepare for use with combos */
432 for (int i = 0; modifiers[i].name; ++i) {
433 dumb.push_back (S_(modifiers[i].name));
436 set_popdown_strings (_edit_modifier_combo, dumb);
437 _edit_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_modifier_chosen));
438 Gtkmm2ext::UI::instance()->set_tip (_edit_modifier_combo,
439 (string_compose (_("<b>Recommended Setting: %1 + button 3 (right mouse button)</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
446 Label* l = manage (left_aligned_label (_("Select Keyboard layout:")));
447 l->set_name ("OptionsLabel");
451 for (map<string,string>::iterator bf = Keyboard::binding_files.begin(); bf != Keyboard::binding_files.end(); ++bf) {
452 strs.push_back (bf->first);
455 set_popdown_strings (_keyboard_layout_selector, strs);
456 _keyboard_layout_selector.set_active_text (Keyboard::current_binding_name());
457 _keyboard_layout_selector.signal_changed().connect (sigc::mem_fun (*this, &KeyboardOptions::bindings_changed));
459 t->attach (*l, col + 1, col + 2, row, row + 1, FILL, FILL);
460 t->attach (_keyboard_layout_selector, col + 2, col + 3, row, row + 1, FILL | EXPAND, FILL);
465 l = manage (left_aligned_label (string_compose ("<b>%1</b>", _("When Clicking:"))));
466 l->set_name ("OptionEditorHeading");
467 l->set_use_markup (true);
468 t->attach (*l, col, col + 2, row, row + 1, FILL | EXPAND, FILL);
473 l = manage (left_aligned_label (_("Edit using:")));
474 l->set_name ("OptionsLabel");
476 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
477 t->attach (_edit_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
479 l = manage (new Label (_("+ button")));
480 l->set_name ("OptionsLabel");
482 t->attach (*l, col + 3, col + 4, row, row + 1, FILL, FILL);
483 t->attach (_edit_button_spin, col + 4, col + 5, row, row + 1, SHRINK , FILL);
485 _edit_button_spin.set_name ("OptionsEntry");
486 _edit_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::edit_button_changed));
491 set_popdown_strings (_delete_modifier_combo, dumb);
492 _delete_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_modifier_chosen));
493 Gtkmm2ext::UI::instance()->set_tip (_delete_modifier_combo,
494 (string_compose (_("<b>Recommended Setting: %1 + button 3 (right mouse button)</b>%2"), Keyboard::tertiary_modifier_name (), restart_msg)));
496 l = manage (left_aligned_label (_("Delete using:")));
497 l->set_name ("OptionsLabel");
499 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
500 t->attach (_delete_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
502 l = manage (new Label (_("+ button")));
503 l->set_name ("OptionsLabel");
505 t->attach (*l, col + 3, col + 4, row, row + 1, FILL, FILL);
506 t->attach (_delete_button_spin, col + 4, col + 5, row, row + 1, SHRINK, FILL);
508 _delete_button_spin.set_name ("OptionsEntry");
509 _delete_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::delete_button_changed));
514 set_popdown_strings (_insert_note_modifier_combo, dumb);
515 _insert_note_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_modifier_chosen));
516 Gtkmm2ext::UI::instance()->set_tip (_insert_note_modifier_combo,
517 (string_compose (_("<b>Recommended Setting: %1 + button 1 (left mouse button)</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
519 l = manage (left_aligned_label (_("Insert note using:")));
520 l->set_name ("OptionsLabel");
522 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
523 t->attach (_insert_note_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
525 l = manage (new Label (_("+ button")));
526 l->set_name ("OptionsLabel");
528 t->attach (*l, col + 3, col + 4, row, row + 1, FILL, FILL);
529 t->attach (_insert_note_button_spin, col + 4, col + 5, row, row + 1, SHRINK, FILL);
531 _insert_note_button_spin.set_name ("OptionsEntry");
532 _insert_note_button_adjustment.signal_value_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::insert_note_button_changed));
536 l = manage (left_aligned_label (string_compose ("<b>%1</b>", _("When Beginning a Drag:"))));
537 l->set_name ("OptionEditorHeading");
538 l->set_use_markup (true);
539 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
545 set_popdown_strings (_copy_modifier_combo, dumb);
546 _copy_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::copy_modifier_chosen));
547 Gtkmm2ext::UI::instance()->set_tip (_copy_modifier_combo,
548 (string_compose (_("<b>Recommended Setting: %1</b>%2"),
550 Keyboard::secondary_modifier_name (),
552 Keyboard::primary_modifier_name (),
556 l = manage (left_aligned_label (_("Copy items using:")));
557 l->set_name ("OptionsLabel");
559 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
560 t->attach (_copy_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
565 /* constraint modifier */
566 set_popdown_strings (_constraint_modifier_combo, dumb);
567 _constraint_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::constraint_modifier_chosen));
568 Gtkmm2ext::UI::instance()->set_tip (_constraint_modifier_combo,
569 (string_compose (_("<b>Recommended Setting: %1</b>%2"),
571 Keyboard::primary_modifier_name (),
573 Keyboard::tertiary_modifier_name (),
577 l = manage (left_aligned_label (_("Constrain drag using:")));
578 l->set_name ("OptionsLabel");
580 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
581 t->attach (_constraint_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
587 set_popdown_strings (_push_points_combo, dumb);
588 _push_points_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::push_points_modifier_chosen));
590 std::string mod_str = string_compose (X_("%1-%2"), Keyboard::primary_modifier_name (), Keyboard::level4_modifier_name ());
591 Gtkmm2ext::UI::instance()->set_tip (_push_points_combo,
592 (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
594 l = manage (left_aligned_label (_("Push points using:")));
595 l->set_name ("OptionsLabel");
597 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
598 t->attach (_push_points_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
602 l = manage (left_aligned_label (string_compose ("<b>%1</b>", _("When Beginning a Trim:"))));
603 l->set_name ("OptionEditorHeading");
604 l->set_use_markup (true);
605 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
611 set_popdown_strings (_trim_contents_combo, dumb);
612 _trim_contents_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_contents_modifier_chosen));
613 Gtkmm2ext::UI::instance()->set_tip (_trim_contents_combo,
614 (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::primary_modifier_name (), restart_msg)));
616 l = manage (left_aligned_label (_("Trim contents using:")));
617 l->set_name ("OptionsLabel");
619 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
620 t->attach (_trim_contents_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
626 set_popdown_strings (_trim_anchored_combo, dumb);
627 _trim_anchored_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_anchored_modifier_chosen));
629 mod_str = string_compose (X_("%1-%2"), Keyboard::primary_modifier_name (), Keyboard::tertiary_modifier_name ());
630 Gtkmm2ext::UI::instance()->set_tip (_trim_anchored_combo,
631 (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
633 l = manage (left_aligned_label (_("Anchored trim using:")));
634 l->set_name ("OptionsLabel");
636 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
638 t->attach (_trim_anchored_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
643 /* jump trim disabled for now
644 set_popdown_strings (_trim_jump_combo, dumb);
645 _trim_jump_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_jump_modifier_chosen));
647 l = manage (left_aligned_label (_("Jump after trim using:")));
648 l->set_name ("OptionsLabel");
650 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
652 t->attach (_trim_jump_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
658 /* note resize relative */
659 set_popdown_strings (_note_size_relative_combo, dumb);
660 _note_size_relative_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::note_size_relative_modifier_chosen));
661 Gtkmm2ext::UI::instance()->set_tip (_note_size_relative_combo,
662 (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::tertiary_modifier_name (), restart_msg))); // XXX 2ndary
664 l = manage (left_aligned_label (_("Resize notes relatively using:")));
665 l->set_name ("OptionsLabel");
667 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
669 t->attach (_note_size_relative_combo, col, col + 1, row, row + 1, FILL | EXPAND, FILL);
673 l = manage (left_aligned_label (string_compose ("<b>%1</b>", _("While Dragging:"))));
674 l->set_name ("OptionEditorHeading");
675 l->set_use_markup (true);
676 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
682 set_popdown_strings (_snap_modifier_combo, dumb);
683 _snap_modifier_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_modifier_chosen));
685 mod_str = string_compose (X_("%1-%2"), Keyboard::level4_modifier_name (), Keyboard::tertiary_modifier_name ());
687 mod_str = Keyboard::secondary_modifier_name();
689 Gtkmm2ext::UI::instance()->set_tip (_snap_modifier_combo,
690 (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
692 l = manage (left_aligned_label (_("Ignore snap using:")));
693 l->set_name ("OptionsLabel");
695 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
696 t->attach (_snap_modifier_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
702 set_popdown_strings (_snap_delta_combo, dumb);
703 _snap_delta_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::snap_delta_modifier_chosen));
705 mod_str = Keyboard::level4_modifier_name ();
707 mod_str = string_compose (X_("%1-%2"), Keyboard::secondary_modifier_name (), Keyboard::level4_modifier_name ());
709 Gtkmm2ext::UI::instance()->set_tip (_snap_delta_combo,
710 (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
712 l = manage (left_aligned_label (_("Snap relatively using:")));
713 l->set_name ("OptionsLabel");
715 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
716 t->attach (_snap_delta_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
720 l = manage (left_aligned_label (string_compose ("<b>%1</b>", _("While Trimming:"))));
721 l->set_name ("OptionEditorHeading");
722 l->set_use_markup (true);
723 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
729 set_popdown_strings (_trim_overlap_combo, dumb);
730 _trim_overlap_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::trim_overlap_modifier_chosen));
732 Gtkmm2ext::UI::instance()->set_tip (_trim_overlap_combo,
733 (string_compose (_("<b>Recommended Setting: %1</b>%2"), Keyboard::tertiary_modifier_name (), restart_msg)));
735 l = manage (left_aligned_label (_("Resize overlapped regions using:")));
736 l->set_name ("OptionsLabel");
738 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
739 t->attach (_trim_overlap_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
743 l = manage (left_aligned_label (string_compose ("<b>%1</b>", _("While Dragging Control Points:"))));
744 l->set_name ("OptionEditorHeading");
745 l->set_use_markup (true);
746 t->attach (*l, 0, 2, row, row + 1, FILL | EXPAND, FILL);
752 set_popdown_strings (_fine_adjust_combo, dumb);
753 _fine_adjust_combo.signal_changed().connect (sigc::mem_fun(*this, &KeyboardOptions::fine_adjust_modifier_chosen));
755 mod_str = string_compose (X_("%1-%2"), Keyboard::primary_modifier_name (), Keyboard::secondary_modifier_name ()); // XXX just 2ndary ?!
756 Gtkmm2ext::UI::instance()->set_tip (_fine_adjust_combo,
757 (string_compose (_("<b>Recommended Setting: %1</b>%2"), mod_str, restart_msg)));
759 l = manage (left_aligned_label (_("Fine adjust using:")));
760 l->set_name ("OptionsLabel");
762 t->attach (*l, col, col + 1, row, row + 1, FILL, FILL);
763 t->attach (_fine_adjust_combo, col + 1, col + 2, row, row + 1, FILL | EXPAND, FILL);
765 OptionEditorHeading* h = new OptionEditorHeading (_("Reset"));
766 h->add_to_page (this);
768 RcActionButton* rb = new RcActionButton (_("Reset to recommended defaults"),
769 sigc::mem_fun (*this, &KeyboardOptions::reset_to_defaults));
770 rb->add_to_page (this);
772 set_state_from_config ();
775 void parameter_changed (string const &)
777 /* XXX: these aren't really config options... */
780 void set_state_from_config ()
782 _delete_button_adjustment.set_value (Keyboard::delete_button());
783 _insert_note_button_adjustment.set_value (Keyboard::insert_note_button());
784 _edit_button_adjustment.set_value (Keyboard::edit_button());
786 for (int x = 0; modifiers[x].name; ++x) {
787 if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_overlap_modifier ()) {
788 _trim_overlap_combo.set_active_text (S_(modifiers[x].name));
790 if (modifiers[x].modifier == Keyboard::delete_modifier ()) {
791 _delete_modifier_combo.set_active_text (S_(modifiers[x].name));
793 if (modifiers[x].modifier == Keyboard::edit_modifier ()) {
794 _edit_modifier_combo.set_active_text (S_(modifiers[x].name));
796 if (modifiers[x].modifier == Keyboard::insert_note_modifier ()) {
797 _insert_note_modifier_combo.set_active_text (S_(modifiers[x].name));
799 if (modifiers[x].modifier == (guint) Keyboard::CopyModifier) {
800 _copy_modifier_combo.set_active_text (S_(modifiers[x].name));
802 if (modifiers[x].modifier == (guint) ArdourKeyboard::constraint_modifier ()) {
803 _constraint_modifier_combo.set_active_text (S_(modifiers[x].name));
805 if (modifiers[x].modifier == (guint) ArdourKeyboard::push_points_modifier ()) {
806 _push_points_combo.set_active_text (S_(modifiers[x].name));
808 if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_contents_modifier ()) {
809 _trim_contents_combo.set_active_text (S_(modifiers[x].name));
811 if (modifiers[x].modifier == (guint) ArdourKeyboard::trim_anchored_modifier ()) {
812 _trim_anchored_combo.set_active_text (S_(modifiers[x].name));
815 if (modifiers[x].modifier == (guint) Keyboard::trim_jump_modifier ()) {
816 _trim_jump_combo.set_active_text (S_(modifiers[x].name));
819 if (modifiers[x].modifier == (guint) ArdourKeyboard::note_size_relative_modifier ()) {
820 _note_size_relative_combo.set_active_text (S_(modifiers[x].name));
822 if (modifiers[x].modifier == (guint) Keyboard::snap_modifier ()) {
823 _snap_modifier_combo.set_active_text (S_(modifiers[x].name));
825 if (modifiers[x].modifier == (guint) Keyboard::snap_delta_modifier ()) {
826 _snap_delta_combo.set_active_text (S_(modifiers[x].name));
828 if (modifiers[x].modifier == (guint) ArdourKeyboard::fine_adjust_modifier ()) {
829 _fine_adjust_combo.set_active_text (S_(modifiers[x].name));
834 void add_to_page (OptionEditorPage* p)
836 int const n = p->table.property_n_rows();
837 p->table.resize (n + 1, 3);
838 p->table.attach (box, 1, 3, n, n + 1, FILL | EXPAND, SHRINK, 0, 0);
843 void bindings_changed ()
845 string const txt = _keyboard_layout_selector.get_active_text();
847 /* XXX: config...? for all this keyboard stuff */
849 for (map<string,string>::iterator i = Keyboard::binding_files.begin(); i != Keyboard::binding_files.end(); ++i) {
850 if (txt == i->first) {
851 if (Keyboard::load_keybindings (i->second)) {
852 Keyboard::save_keybindings ();
858 void edit_modifier_chosen ()
860 string const txt = _edit_modifier_combo.get_active_text();
862 for (int i = 0; modifiers[i].name; ++i) {
863 if (txt == S_(modifiers[i].name)) {
864 Keyboard::set_edit_modifier (modifiers[i].modifier);
870 void delete_modifier_chosen ()
872 string const txt = _delete_modifier_combo.get_active_text();
874 for (int i = 0; modifiers[i].name; ++i) {
875 if (txt == S_(modifiers[i].name)) {
876 Keyboard::set_delete_modifier (modifiers[i].modifier);
882 void copy_modifier_chosen ()
884 string const txt = _copy_modifier_combo.get_active_text();
886 for (int i = 0; modifiers[i].name; ++i) {
887 if (txt == S_(modifiers[i].name)) {
888 Keyboard::set_copy_modifier (modifiers[i].modifier);
894 void insert_note_modifier_chosen ()
896 string const txt = _insert_note_modifier_combo.get_active_text();
898 for (int i = 0; modifiers[i].name; ++i) {
899 if (txt == S_(modifiers[i].name)) {
900 Keyboard::set_insert_note_modifier (modifiers[i].modifier);
906 void snap_modifier_chosen ()
908 string const txt = _snap_modifier_combo.get_active_text();
910 for (int i = 0; modifiers[i].name; ++i) {
911 if (txt == S_(modifiers[i].name)) {
912 Keyboard::set_snap_modifier (modifiers[i].modifier);
918 void snap_delta_modifier_chosen ()
920 string const txt = _snap_delta_combo.get_active_text();
922 for (int i = 0; modifiers[i].name; ++i) {
923 if (txt == S_(modifiers[i].name)) {
924 Keyboard::set_snap_delta_modifier (modifiers[i].modifier);
930 void constraint_modifier_chosen ()
932 string const txt = _constraint_modifier_combo.get_active_text();
934 for (int i = 0; modifiers[i].name; ++i) {
935 if (txt == S_(modifiers[i].name)) {
936 ArdourKeyboard::set_constraint_modifier (modifiers[i].modifier);
942 void trim_contents_modifier_chosen ()
944 string const txt = _trim_contents_combo.get_active_text();
946 for (int i = 0; modifiers[i].name; ++i) {
947 if (txt == S_(modifiers[i].name)) {
948 ArdourKeyboard::set_trim_contents_modifier (modifiers[i].modifier);
954 void trim_overlap_modifier_chosen ()
956 string const txt = _trim_overlap_combo.get_active_text();
958 for (int i = 0; modifiers[i].name; ++i) {
959 if (txt == S_(modifiers[i].name)) {
960 ArdourKeyboard::set_trim_overlap_modifier (modifiers[i].modifier);
966 void trim_anchored_modifier_chosen ()
968 string const txt = _trim_anchored_combo.get_active_text();
970 for (int i = 0; modifiers[i].name; ++i) {
971 if (txt == S_(modifiers[i].name)) {
972 ArdourKeyboard::set_trim_anchored_modifier (modifiers[i].modifier);
978 void fine_adjust_modifier_chosen ()
980 string const txt = _fine_adjust_combo.get_active_text();
982 for (int i = 0; modifiers[i].name; ++i) {
983 if (txt == S_(modifiers[i].name)) {
984 ArdourKeyboard::set_fine_adjust_modifier (modifiers[i].modifier);
990 void push_points_modifier_chosen ()
992 string const txt = _push_points_combo.get_active_text();
994 for (int i = 0; modifiers[i].name; ++i) {
995 if (txt == S_(modifiers[i].name)) {
996 ArdourKeyboard::set_push_points_modifier (modifiers[i].modifier);
1002 void note_size_relative_modifier_chosen ()
1004 string const txt = _note_size_relative_combo.get_active_text();
1006 for (int i = 0; modifiers[i].name; ++i) {
1007 if (txt == S_(modifiers[i].name)) {
1008 ArdourKeyboard::set_note_size_relative_modifier (modifiers[i].modifier);
1014 void delete_button_changed ()
1016 Keyboard::set_delete_button (_delete_button_spin.get_value_as_int());
1019 void edit_button_changed ()
1021 Keyboard::set_edit_button (_edit_button_spin.get_value_as_int());
1024 void insert_note_button_changed ()
1026 Keyboard::set_insert_note_button (_insert_note_button_spin.get_value_as_int());
1029 void reset_to_defaults ()
1032 Keyboard::set_edit_modifier (Keyboard::PrimaryModifier);
1033 Keyboard::set_edit_button (3);
1034 Keyboard::set_delete_modifier (Keyboard::TertiaryModifier);
1035 Keyboard::set_delete_button (3);
1036 Keyboard::set_insert_note_modifier (Keyboard::PrimaryModifier);
1037 Keyboard::set_insert_note_button (1);
1039 /* when beginning a drag */
1041 Keyboard::set_copy_modifier (Keyboard::SecondaryModifier);
1043 Keyboard::set_copy_modifier (Keyboard::PrimaryModifier);
1047 ArdourKeyboard::set_constraint_modifier (Keyboard::PrimaryModifier);
1049 ArdourKeyboard::set_constraint_modifier (Keyboard::TertiaryModifier);
1051 ArdourKeyboard::set_push_points_modifier (Keyboard::PrimaryModifier | Keyboard::Level4Modifier);
1053 /* when beginning a trim */
1054 ArdourKeyboard::set_trim_contents_modifier (Keyboard::PrimaryModifier);
1055 ArdourKeyboard::set_trim_anchored_modifier (Keyboard::PrimaryModifier | Keyboard::TertiaryModifier);
1056 ArdourKeyboard::set_note_size_relative_modifier (Keyboard::TertiaryModifier); // XXX better: 2ndary
1058 /* while dragging */
1060 Keyboard::set_snap_modifier (Keyboard::TertiaryModifier);
1062 Keyboard::set_snap_modifier (Keyboard::SecondaryModifier);
1065 Keyboard::set_snap_delta_modifier (Keyboard::Level4Modifier);
1067 Keyboard::set_snap_delta_modifier (Keyboard::SecondaryModifier | Keyboard::Level4Modifier);
1070 /* while trimming */
1071 ArdourKeyboard::set_trim_overlap_modifier (Keyboard::TertiaryModifier);
1073 /* while dragging ctrl points */
1074 ArdourKeyboard::set_fine_adjust_modifier (/*Keyboard::PrimaryModifier | */Keyboard::SecondaryModifier); // XXX
1076 set_state_from_config ();
1079 ComboBoxText _keyboard_layout_selector;
1080 ComboBoxText _edit_modifier_combo;
1081 ComboBoxText _delete_modifier_combo;
1082 ComboBoxText _copy_modifier_combo;
1083 ComboBoxText _insert_note_modifier_combo;
1084 ComboBoxText _snap_modifier_combo;
1085 ComboBoxText _snap_delta_combo;
1086 ComboBoxText _constraint_modifier_combo;
1087 ComboBoxText _trim_contents_combo;
1088 ComboBoxText _trim_overlap_combo;
1089 ComboBoxText _trim_anchored_combo;
1090 ComboBoxText _trim_jump_combo;
1091 ComboBoxText _fine_adjust_combo;
1092 ComboBoxText _push_points_combo;
1093 ComboBoxText _note_size_relative_combo;
1094 Adjustment _delete_button_adjustment;
1095 SpinButton _delete_button_spin;
1096 Adjustment _edit_button_adjustment;
1097 SpinButton _edit_button_spin;
1098 Adjustment _insert_note_button_adjustment;
1099 SpinButton _insert_note_button_spin;
1103 class FontScalingOptions : public HSliderOption
1106 FontScalingOptions ()
1107 : HSliderOption ("font-scale", _("GUI and Font scaling"),
1108 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_font_scale),
1109 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_font_scale),
1113 const std::string dflt = _("100%");
1114 const std::string empty = X_(""); // despite gtk-doc saying so, NULL does not work as reference
1116 _hscale.set_name("FontScaleSlider");
1117 _hscale.set_draw_value(false);
1118 _hscale.add_mark(50, Gtk::POS_TOP, empty);
1119 _hscale.add_mark(60, Gtk::POS_TOP, empty);
1120 _hscale.add_mark(70, Gtk::POS_TOP, empty);
1121 _hscale.add_mark(80, Gtk::POS_TOP, empty);
1122 _hscale.add_mark(90, Gtk::POS_TOP, empty);
1123 _hscale.add_mark(100, Gtk::POS_TOP, dflt);
1124 _hscale.add_mark(125, Gtk::POS_TOP, empty);
1125 _hscale.add_mark(150, Gtk::POS_TOP, empty);
1126 _hscale.add_mark(175, Gtk::POS_TOP, empty);
1127 _hscale.add_mark(200, Gtk::POS_TOP, empty);
1128 _hscale.add_mark(250, Gtk::POS_TOP, empty);
1130 set_note (_("Adjusting the scale requires an application restart to re-layout."));
1135 HSliderOption::changed ();
1136 /* XXX: should be triggered from the parameter changed signal */
1137 UIConfiguration::instance().reset_dpi ();
1141 class VstTimeOutSliderOption : public HSliderOption
1144 VstTimeOutSliderOption (RCConfiguration* c)
1145 : HSliderOption ("vst-scan-timeout", _("Scan Time Out"),
1146 sigc::mem_fun (*c, &RCConfiguration::get_vst_scan_timeout),
1147 sigc::mem_fun (*c, &RCConfiguration::set_vst_scan_timeout),
1150 _label.set_alignment (1.0, 0.5); // match buttons below
1151 _hscale.set_digits (0);
1152 _hscale.set_draw_value(false);
1153 _hscale.add_mark( 0, Gtk::POS_TOP, _("\u221e")); // infinity
1154 _hscale.add_mark( 300, Gtk::POS_TOP, _("30 sec"));
1155 _hscale.add_mark( 600, Gtk::POS_TOP, _("1 min"));
1156 _hscale.add_mark(1200, Gtk::POS_TOP, _("2 mins"));
1157 _hscale.add_mark(1800, Gtk::POS_TOP, _("3 mins"));
1158 _hscale.add_mark(2400, Gtk::POS_TOP, _("4 mins"));
1159 _hscale.add_mark(3000, Gtk::POS_TOP, _("5 mins"));
1161 Gtkmm2ext::UI::instance()->set_tip(_hscale,
1162 _("Specify the default timeout for plugin instantiation. Plugins that require more time to load will be blacklisted. A value of 0 disables the timeout."));
1166 class ClipLevelOptions : public HSliderOption
1170 : HSliderOption (X_("waveform-clip-level"),
1171 _("Waveform Clip Level (dBFS):"),
1172 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_clip_level),
1173 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_clip_level),
1174 -50.0, -0.5, 0.1, 1.0, /* units of dB */
1180 void parameter_changed (string const & p)
1182 if (p == "waveform-clip-level") {
1183 ArdourWaveView::WaveView::set_clip_level (UIConfiguration::instance().get_waveform_clip_level());
1185 if (p == "show-waveform-clipping") {
1186 _hscale.set_sensitive (UIConfiguration::instance().get_show_waveform_clipping ());
1190 void set_state_from_config ()
1192 parameter_changed ("waveform-clip-level");
1193 parameter_changed ("show-waveform-clipping");
1197 class BufferingOptions : public OptionEditorComponent
1200 BufferingOptions (RCConfiguration* c)
1202 , _label (_("Preset:"))
1203 , _playback ("playback-buffer-seconds", _("Playback (seconds of buffering)"),
1204 sigc::mem_fun (*_rc_config, &RCConfiguration::get_audio_playback_buffer_seconds),
1205 sigc::mem_fun (*_rc_config, &RCConfiguration::set_audio_playback_buffer_seconds),
1207 , _capture ("capture-buffer-seconds", _("Recording (seconds of buffering)"),
1208 sigc::mem_fun (*_rc_config, &RCConfiguration::get_audio_capture_buffer_seconds),
1209 sigc::mem_fun (*_rc_config, &RCConfiguration::set_audio_capture_buffer_seconds),
1212 // TODO use ComboOption
1213 vector<string> presets;
1215 /* these must match the order of the enums for BufferingPreset */
1216 presets.push_back (_("Small sessions (4-16 tracks)"));
1217 presets.push_back (_("Medium sessions (16-64 tracks)"));
1218 presets.push_back (_("Large sessions (64+ tracks)"));
1219 presets.push_back (_("Custom (set by sliders below)"));
1221 set_popdown_strings (_buffering_presets_combo, presets);
1222 _buffering_presets_combo.signal_changed().connect (sigc::mem_fun (*this, &BufferingOptions::preset_changed));
1224 _label.set_name ("OptionsLabel");
1225 _label.set_alignment (0, 0.5);
1229 add_to_page (OptionEditorPage* p)
1231 add_widgets_to_page (p, &_label, &_buffering_presets_combo);
1232 _playback.add_to_page (p);
1233 _capture.add_to_page (p);
1236 void parameter_changed (string const & p)
1238 if (p == "buffering-preset") {
1239 switch (_rc_config->get_buffering_preset()) {
1241 _playback.set_sensitive (false);
1242 _capture.set_sensitive (false);
1243 _buffering_presets_combo.set_active (0);
1246 _playback.set_sensitive (false);
1247 _capture.set_sensitive (false);
1248 _buffering_presets_combo.set_active (1);
1251 _playback.set_sensitive (false);
1252 _capture.set_sensitive (false);
1253 _buffering_presets_combo.set_active (2);
1256 _playback.set_sensitive (true);
1257 _capture.set_sensitive (true);
1258 _buffering_presets_combo.set_active (3);
1262 _playback.parameter_changed (p);
1263 _capture.parameter_changed (p);
1266 void set_state_from_config ()
1268 parameter_changed ("buffering-preset");
1269 _playback.set_state_from_config();
1270 _capture.set_state_from_config();
1273 Gtk::Widget& tip_widget() { return _buffering_presets_combo; }
1277 void preset_changed ()
1279 int index = _buffering_presets_combo.get_active_row_number ();
1285 _rc_config->set_buffering_preset (Small);
1288 _rc_config->set_buffering_preset (Medium);
1291 _rc_config->set_buffering_preset (Large);
1294 _rc_config->set_buffering_preset (Custom);
1297 error << string_compose (_("programming error: unknown buffering preset string, index = %1"), index) << endmsg;
1302 RCConfiguration* _rc_config;
1304 HSliderOption _playback;
1305 HSliderOption _capture;
1306 ComboBoxText _buffering_presets_combo;
1309 class ControlSurfacesOptions : public OptionEditorMiniPage
1312 ControlSurfacesOptions ()
1313 : _ignore_view_change (0)
1315 _store = ListStore::create (_model);
1316 _view.set_model (_store);
1317 _view.append_column_editable (_("Enable"), _model.enabled);
1318 _view.append_column (_("Control Surface Protocol"), _model.name);
1319 _view.get_column(1)->set_resizable (true);
1320 _view.get_column(1)->set_expand (true);
1322 Gtk::HBox* edit_box = manage (new Gtk::HBox);
1323 edit_box->set_spacing(3);
1326 Label* label = manage (new Label);
1327 label->set_text (_("Edit the settings for selected protocol (it must be ENABLED first):"));
1328 edit_box->pack_start (*label, false, false);
1331 edit_button = manage (new Button(_("Show Protocol Settings")));
1332 edit_button->signal_clicked().connect (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_btn_clicked));
1333 edit_box->pack_start (*edit_button, true, true);
1334 edit_button->set_sensitive (false);
1335 edit_button->show ();
1337 int const n = table.property_n_rows();
1338 table.resize (n + 2, 3);
1339 table.attach (_view, 0, 3, n, n + 1);
1340 table.attach (*edit_box, 0, 3, n + 1, n + 2);
1342 ControlProtocolManager& m = ControlProtocolManager::instance ();
1343 m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
1344 boost::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
1346 _store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
1347 _view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
1348 _view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::selection_changed));
1351 void parameter_changed (std::string const &)
1356 void set_state_from_config ()
1360 ControlProtocolManager& m = ControlProtocolManager::instance ();
1361 for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
1363 if (!(*i)->mandatory) {
1364 TreeModel::Row r = *_store->append ();
1365 r[_model.name] = (*i)->name;
1366 r[_model.enabled] = 0 != (*i)->protocol;
1367 r[_model.protocol_info] = *i;
1374 void protocol_status_changed (ControlProtocolInfo* cpi) {
1376 TreeModel::Children rows = _store->children();
1378 for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
1379 string n = ((*x)[_model.name]);
1381 if ((*x)[_model.protocol_info] == cpi) {
1382 _ignore_view_change++;
1383 (*x)[_model.enabled] = 0 != cpi->protocol;
1384 _ignore_view_change--;
1385 selection_changed (); // update sensitivity
1391 void selection_changed ()
1393 //enable the Edit button when a row is selected for editing
1394 TreeModel::Row row = *(_view.get_selection()->get_selected());
1395 if (row && row[_model.enabled]) {
1396 ControlProtocolInfo* cpi = row[_model.protocol_info];
1397 edit_button->set_sensitive (cpi && cpi->protocol && cpi->protocol->has_editor ());
1399 edit_button->set_sensitive (false);
1403 void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
1405 TreeModel::Row r = *i;
1407 if (_ignore_view_change) {
1411 ControlProtocolInfo* cpi = r[_model.protocol_info];
1416 bool const was_enabled = (cpi->protocol != 0);
1417 bool const is_enabled = r[_model.enabled];
1420 if (was_enabled != is_enabled) {
1423 ControlProtocolManager::instance().activate (*cpi);
1425 ControlProtocolManager::instance().deactivate (*cpi);
1429 selection_changed ();
1432 void edit_btn_clicked ()
1435 ControlProtocolInfo* cpi;
1438 row = *(_view.get_selection()->get_selected());
1439 if (!row[_model.enabled]) {
1442 cpi = row[_model.protocol_info];
1443 if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
1446 Box* box = (Box*) cpi->protocol->get_gui ();
1450 if (box->get_parent()) {
1451 static_cast<ArdourWindow*>(box->get_parent())->present();
1454 WindowTitle title (Glib::get_application_name());
1455 title += row[_model.name];
1456 title += _("Configuration");
1457 /* once created, the window is managed by the surface itself (as ->get_parent())
1458 * Surface's tear_down_gui() is called on session close, when de-activating
1459 * or re-initializing a surface.
1460 * tear_down_gui() hides an deletes the Window if it exists.
1462 ArdourWindow* win = new ArdourWindow (*((Gtk::Window*) _view.get_toplevel()), title.get_string());
1463 win->set_title (_("Control Protocol Settings"));
1469 void edit_clicked (GdkEventButton* ev)
1471 if (ev->type != GDK_2BUTTON_PRESS) {
1478 class ControlSurfacesModelColumns : public TreeModelColumnRecord
1482 ControlSurfacesModelColumns ()
1486 add (protocol_info);
1489 TreeModelColumn<string> name;
1490 TreeModelColumn<bool> enabled;
1491 TreeModelColumn<ControlProtocolInfo*> protocol_info;
1494 Glib::RefPtr<ListStore> _store;
1495 ControlSurfacesModelColumns _model;
1497 PBD::ScopedConnection protocol_status_connection;
1498 uint32_t _ignore_view_change;
1499 Gtk::Button* edit_button;
1502 class VideoTimelineOptions : public OptionEditorMiniPage
1505 VideoTimelineOptions (RCConfiguration* c)
1507 , _show_video_export_info_button (_("Show Video Export Info before export"))
1508 , _show_video_server_dialog_button (_("Show Video Server Startup Dialog"))
1509 , _video_advanced_setup_button (_("Advanced Setup (remote video server)"))
1510 , _xjadeo_browse_button (_("Browse..."))
1513 int n = table.property_n_rows();
1515 t->attach (_show_video_export_info_button, 1, 4, n, n + 1);
1516 _show_video_export_info_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_export_info_toggled));
1517 Gtkmm2ext::UI::instance()->set_tip (_show_video_export_info_button,
1518 _("<b>When enabled</b> an information window with details is displayed before the video-export dialog."));
1521 t->attach (_show_video_server_dialog_button, 1, 4, n, n + 1);
1522 _show_video_server_dialog_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::show_video_server_dialog_toggled));
1523 Gtkmm2ext::UI::instance()->set_tip (_show_video_server_dialog_button,
1524 _("<b>When enabled</b> the video server is never launched automatically without confirmation"));
1527 t->attach (_video_advanced_setup_button, 1, 4, n, n + 1, FILL);
1528 _video_advanced_setup_button.signal_toggled().connect (sigc::mem_fun (*this, &VideoTimelineOptions::video_advanced_setup_toggled));
1529 Gtkmm2ext::UI::instance()->set_tip (_video_advanced_setup_button,
1530 _("<b>When enabled</b> you can specify a custom video-server URL and docroot. - Do not enable this option unless you know what you are doing."));
1533 Label* l = manage (new Label (_("Video Server URL:")));
1534 l->set_alignment (0, 0.5);
1535 t->attach (*l, 1, 2, n, n + 1, FILL);
1536 t->attach (_video_server_url_entry, 2, 4, n, n + 1, FILL);
1537 Gtkmm2ext::UI::instance()->set_tip (_video_server_url_entry,
1538 _("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"));
1541 l = manage (new Label (_("Video Folder:")));
1542 l->set_alignment (0, 0.5);
1543 t->attach (*l, 1, 2, n, n + 1, FILL);
1544 t->attach (_video_server_docroot_entry, 2, 4, n, n + 1);
1545 Gtkmm2ext::UI::instance()->set_tip (_video_server_docroot_entry,
1546 _("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 unavailable. It is used for the local video-monitor and file-browsing when opening/adding a video file."));
1549 l = manage (new Label (""));
1550 t->attach (*l, 0, 4, n, n + 1, EXPAND | FILL);
1553 l = manage (new Label (string_compose ("<b>%1</b>", _("Video Monitor"))));
1554 l->set_use_markup (true);
1555 l->set_alignment (0, 0.5);
1556 t->attach (*l, 0, 4, n, n + 1, EXPAND | FILL);
1559 l = manage (new Label (string_compose (_("Custom Path to Video Monitor (%1) - leave empty for default:"),
1562 #elif defined PLATFORM_WINDOWS
1568 l->set_alignment (0, 0.5);
1569 t->attach (*l, 1, 4, n, n + 1, FILL);
1572 t->attach (_custom_xjadeo_path, 2, 3, n, n + 1, EXPAND|FILL);
1573 Gtkmm2ext::UI::instance()->set_tip (_custom_xjadeo_path, _("Set a custom path to the Video Monitor Executable, changing this requires a restart."));
1574 t->attach (_xjadeo_browse_button, 3, 4, n, n + 1, FILL);
1576 _video_server_url_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1577 _video_server_url_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_url_changed));
1578 _video_server_docroot_entry.signal_changed().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1579 _video_server_docroot_entry.signal_activate().connect (sigc::mem_fun(*this, &VideoTimelineOptions::server_docroot_changed));
1580 _custom_xjadeo_path.signal_changed().connect (sigc::mem_fun (*this, &VideoTimelineOptions::custom_xjadeo_path_changed));
1581 _xjadeo_browse_button.signal_clicked ().connect (sigc::mem_fun (*this, &VideoTimelineOptions::xjadeo_browse_clicked));
1584 void server_url_changed ()
1586 _rc_config->set_video_server_url (_video_server_url_entry.get_text());
1589 void server_docroot_changed ()
1591 _rc_config->set_video_server_docroot (_video_server_docroot_entry.get_text());
1594 void show_video_export_info_toggled ()
1596 bool const x = _show_video_export_info_button.get_active ();
1597 _rc_config->set_show_video_export_info (x);
1600 void show_video_server_dialog_toggled ()
1602 bool const x = _show_video_server_dialog_button.get_active ();
1603 _rc_config->set_show_video_server_dialog (x);
1606 void video_advanced_setup_toggled ()
1608 bool const x = _video_advanced_setup_button.get_active ();
1609 _rc_config->set_video_advanced_setup(x);
1612 void custom_xjadeo_path_changed ()
1614 _rc_config->set_xjadeo_binary (_custom_xjadeo_path.get_text());
1617 void xjadeo_browse_clicked ()
1619 Gtk::FileChooserDialog dialog(_("Set Video Monitor Executable"), Gtk::FILE_CHOOSER_ACTION_OPEN);
1620 dialog.set_filename (_rc_config->get_xjadeo_binary());
1621 dialog.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL);
1622 dialog.add_button(Gtk::Stock::OK, Gtk::RESPONSE_OK);
1623 if (dialog.run () == Gtk::RESPONSE_OK) {
1624 const std::string& filename = dialog.get_filename();
1625 if (!filename.empty() && (
1627 Glib::file_test (filename + "/Contents/MacOS/xjadeo", Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE) ||
1629 Glib::file_test (filename, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_EXECUTABLE)
1631 _rc_config->set_xjadeo_binary (filename);
1636 void parameter_changed (string const & p)
1638 if (p == "video-server-url") {
1639 _video_server_url_entry.set_text (_rc_config->get_video_server_url());
1640 } else if (p == "video-server-docroot") {
1641 _video_server_docroot_entry.set_text (_rc_config->get_video_server_docroot());
1642 } else if (p == "show-video-export-info") {
1643 bool const x = _rc_config->get_show_video_export_info();
1644 _show_video_export_info_button.set_active (x);
1645 } else if (p == "show-video-server-dialog") {
1646 bool const x = _rc_config->get_show_video_server_dialog();
1647 _show_video_server_dialog_button.set_active (x);
1648 } else if (p == "video-advanced-setup") {
1649 bool const x = _rc_config->get_video_advanced_setup();
1650 _video_advanced_setup_button.set_active(x);
1651 _video_server_docroot_entry.set_sensitive(x);
1652 _video_server_url_entry.set_sensitive(x);
1653 } else if (p == "xjadeo-binary") {
1654 _custom_xjadeo_path.set_text (_rc_config->get_xjadeo_binary());
1658 void set_state_from_config ()
1660 parameter_changed ("video-server-url");
1661 parameter_changed ("video-server-docroot");
1662 parameter_changed ("video-monitor-setup-dialog");
1663 parameter_changed ("show-video-export-info");
1664 parameter_changed ("show-video-server-dialog");
1665 parameter_changed ("video-advanced-setup");
1666 parameter_changed ("xjadeo-binary");
1670 RCConfiguration* _rc_config;
1671 Entry _video_server_url_entry;
1672 Entry _video_server_docroot_entry;
1673 Entry _custom_xjadeo_path;
1674 CheckButton _show_video_export_info_button;
1675 CheckButton _show_video_server_dialog_button;
1676 CheckButton _video_advanced_setup_button;
1677 Button _xjadeo_browse_button;
1680 class ColumVisibilityOption : public Option
1683 ColumVisibilityOption (string id, string name, uint32_t n_col, sigc::slot<uint32_t> get, sigc::slot<bool, uint32_t> set)
1690 cb = (CheckButton**) malloc (sizeof (CheckButton*) * n_col);
1691 for (uint32_t i = 0; i < n_col; ++i) {
1692 CheckButton* col = manage (new CheckButton (string_compose (_("Column %1 (Actions %2 + %3)"), i + 1, i * 2 + 1, i * 2 + 2)));
1693 col->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &ColumVisibilityOption::column_toggled), i));
1694 _vbox.pack_start (*col);
1697 parameter_changed (id);
1700 ~ColumVisibilityOption () {
1704 Gtk::Widget& tip_widget() { return _vbox; }
1706 void set_state_from_config ()
1708 uint32_t c = _get();
1709 for (uint32_t i = 0; i < _n_col; ++i) {
1710 bool en = (c & (1<<i)) ? true : false;
1711 if (cb[i]->get_active () != en) {
1712 cb[i]->set_active (en);
1717 void add_to_page (OptionEditorPage* p)
1719 _heading.add_to_page (p);
1720 add_widget_to_page (p, &_vbox);
1724 void column_toggled (int b) {
1725 uint32_t c = _get();
1727 if (cb[b]->get_active ()) {
1738 OptionEditorHeading _heading;
1742 sigc::slot<uint32_t> _get;
1743 sigc::slot<bool, uint32_t> _set;
1747 /** A class which allows control of visibility of some editor components usign
1748 * a VisibilityGroup. The caller should pass in a `dummy' VisibilityGroup
1749 * which has the correct members, but with null widget pointers. This
1750 * class allows the user to set visibility of the members, the details
1751 * of which are stored in a configuration variable which can be watched
1752 * by parts of the editor that actually contain the widgets whose visibility
1753 * is being controlled.
1756 class VisibilityOption : public Option
1759 /** @param name User-visible name for this group.
1760 * @param g `Dummy' VisibilityGroup (as described above).
1761 * @param get Method to get the value of the appropriate configuration variable.
1762 * @param set Method to set the value of the appropriate configuration variable.
1764 VisibilityOption (string name, VisibilityGroup* g, sigc::slot<string> get, sigc::slot<bool, string> set)
1765 : Option (g->get_state_name(), name)
1767 , _visibility_group (g)
1771 /* Watch for changes made by the user to our members */
1772 _visibility_group->VisibilityChanged.connect_same_thread (
1773 _visibility_group_connection, sigc::bind (&VisibilityOption::changed, this)
1777 void set_state_from_config ()
1779 /* Set our state from the current configuration */
1780 _visibility_group->set_state (_get ());
1783 void add_to_page (OptionEditorPage* p)
1785 _heading.add_to_page (p);
1786 add_widget_to_page (p, _visibility_group->list_view ());
1789 Gtk::Widget& tip_widget() { return *_visibility_group->list_view (); }
1794 /* The user has changed something, so reflect this change
1795 in the RCConfiguration.
1797 _set (_visibility_group->get_state_value ());
1800 OptionEditorHeading _heading;
1801 VisibilityGroup* _visibility_group;
1802 sigc::slot<std::string> _get;
1803 sigc::slot<bool, std::string> _set;
1804 PBD::ScopedConnection _visibility_group_connection;
1808 class MidiPortOptions : public OptionEditorMiniPage, public sigc::trackable
1811 MidiPortOptions() : refill_id (-1) {
1813 setup_midi_port_view (midi_output_view, false);
1814 setup_midi_port_view (midi_input_view, true);
1816 OptionEditorHeading* h = new OptionEditorHeading (_("MIDI Inputs"));
1817 h->add_to_page (this);
1819 Gtk::ScrolledWindow* scroller = manage (new Gtk::ScrolledWindow);
1820 scroller->add (midi_input_view);
1821 scroller->set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
1822 scroller->set_size_request (-1, 180);
1824 int n = table.property_n_rows();
1825 table.attach (*scroller, 0, 3, n, n + 1, FILL | EXPAND);
1827 h = new OptionEditorHeading (_("MIDI Outputs"));
1828 h->add_to_page (this);
1830 scroller = manage (new Gtk::ScrolledWindow);
1831 scroller->add (midi_output_view);
1832 scroller->set_policy (POLICY_NEVER, POLICY_AUTOMATIC);
1833 scroller->set_size_request (-1, 180);
1835 n = table.property_n_rows();
1836 table.attach (*scroller, 0, 3, n, n + 1, FILL | EXPAND);
1838 midi_output_view.show ();
1839 midi_input_view.show ();
1841 table.signal_map().connect (sigc::mem_fun (*this, &MidiPortOptions::on_map));
1842 table.signal_unmap().connect (sigc::mem_fun (*this, &MidiPortOptions::on_unmap));
1845 void parameter_changed (string const&) {}
1846 void set_state_from_config() {}
1852 AudioEngine::instance()->PortRegisteredOrUnregistered.connect (connections,
1853 invalidator (*this),
1854 boost::bind (&MidiPortOptions::refill, this),
1856 AudioEngine::instance()->MidiPortInfoChanged.connect (connections,
1857 invalidator (*this),
1858 boost::bind (&MidiPortOptions::refill, this),
1860 AudioEngine::instance()->MidiSelectionPortsChanged.connect (connections,
1861 invalidator (*this),
1862 boost::bind (&MidiPortOptions::refill, this),
1867 connections.drop_connections ();
1872 if (refill_midi_ports (true, midi_input_view)) {
1873 input_label.show ();
1875 input_label.hide ();
1877 if (refill_midi_ports (false, midi_output_view)) {
1878 output_label.show ();
1880 output_label.hide ();
1887 PBD::ScopedConnectionList connections;
1889 /* MIDI port management */
1890 struct MidiPortColumns : public Gtk::TreeModel::ColumnRecord {
1892 MidiPortColumns () {
1902 Gtk::TreeModelColumn<std::string> pretty_name;
1903 Gtk::TreeModelColumn<bool> music_data;
1904 Gtk::TreeModelColumn<bool> control_data;
1905 Gtk::TreeModelColumn<bool> selection;
1906 Gtk::TreeModelColumn<std::string> fullname;
1907 Gtk::TreeModelColumn<std::string> shortname;
1908 Gtk::TreeModelColumn<std::string> filler;
1911 MidiPortColumns midi_port_columns;
1912 Gtk::TreeView midi_input_view;
1913 Gtk::TreeView midi_output_view;
1914 Gtk::Label input_label;
1915 Gtk::Label output_label;
1918 void setup_midi_port_view (Gtk::TreeView&, bool with_selection);
1919 bool refill_midi_ports (bool for_input, Gtk::TreeView&);
1920 void pretty_name_edit (std::string const & path, std::string const & new_text, Gtk::TreeView*);
1921 void midi_music_column_toggled (std::string const & path, Gtk::TreeView*);
1922 void midi_control_column_toggled (std::string const & path, Gtk::TreeView*);
1923 void midi_selection_column_toggled (std::string const & path, Gtk::TreeView*);
1927 MidiPortOptions::setup_midi_port_view (Gtk::TreeView& view, bool with_selection)
1929 int pretty_name_column;
1932 int selection_column;
1933 TreeViewColumn* col;
1936 pretty_name_column = view.append_column_editable (_("Name (click twice to edit)"), midi_port_columns.pretty_name) - 1;
1938 col = manage (new TreeViewColumn ("", midi_port_columns.music_data));
1939 col->set_alignment (ALIGN_CENTER);
1940 l = manage (new Label (_("Music Data")));
1941 set_tooltip (*l, string_compose (_("If ticked, %1 will consider this port to be a source of music performance data."), PROGRAM_NAME));
1942 col->set_widget (*l);
1944 music_column = view.append_column (*col) - 1;
1946 col = manage (new TreeViewColumn ("", midi_port_columns.control_data));
1947 col->set_alignment (ALIGN_CENTER);
1948 l = manage (new Label (_("Control Data")));
1949 set_tooltip (*l, string_compose (_("If ticked, %1 will consider this port to be a source of control data."), PROGRAM_NAME));
1950 col->set_widget (*l);
1952 control_column = view.append_column (*col) - 1;
1954 if (with_selection) {
1955 col = manage (new TreeViewColumn (_("Follow Selection"), midi_port_columns.selection));
1956 selection_column = view.append_column (*col) - 1;
1957 l = manage (new Label (_("Follow Selection")));
1958 set_tooltip (*l, string_compose (_("If ticked, and \"MIDI input follows selection\" is enabled,\n%1 will automatically connect the first selected MIDI track to this port.\n"), PROGRAM_NAME));
1959 col->set_widget (*l);
1963 /* filler column so that the last real column doesn't expand */
1964 view.append_column ("", midi_port_columns.filler);
1966 CellRendererText* pretty_name_cell = dynamic_cast<CellRendererText*> (view.get_column_cell_renderer (pretty_name_column));
1967 pretty_name_cell->property_editable() = true;
1968 pretty_name_cell->signal_edited().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::pretty_name_edit), &view));
1970 CellRendererToggle* toggle_cell;
1972 toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (music_column));
1973 toggle_cell->property_activatable() = true;
1974 toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_music_column_toggled), &view));
1976 toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (control_column));
1977 toggle_cell->property_activatable() = true;
1978 toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_control_column_toggled), &view));
1980 if (with_selection) {
1981 toggle_cell = dynamic_cast<CellRendererToggle*> (view.get_column_cell_renderer (selection_column));
1982 toggle_cell->property_activatable() = true;
1983 toggle_cell->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &MidiPortOptions::midi_selection_column_toggled), &view));
1986 view.get_selection()->set_mode (SELECTION_SINGLE);
1987 view.set_tooltip_column (5); /* port short name */
1988 view.get_column(0)->set_resizable (true);
1989 view.get_column(0)->set_expand (true);
1993 MidiPortOptions::refill_midi_ports (bool for_input, Gtk::TreeView& view)
1995 using namespace ARDOUR;
1997 std::vector<string> ports;
1999 AudioEngine::instance()->get_known_midi_ports (ports);
2001 if (ports.empty()) {
2006 Glib::RefPtr<ListStore> model = Gtk::ListStore::create (midi_port_columns);
2008 for (vector<string>::const_iterator s = ports.begin(); s != ports.end(); ++s) {
2010 PortManager::MidiPortInformation mpi (AudioEngine::instance()->midi_port_information (*s));
2016 if (for_input != mpi.input) {
2020 TreeModel::Row row = *(model->append());
2022 row[midi_port_columns.pretty_name] = mpi.pretty_name;
2023 row[midi_port_columns.music_data] = mpi.properties & MidiPortMusic;
2024 row[midi_port_columns.control_data] = mpi.properties & MidiPortControl;
2025 row[midi_port_columns.selection] = mpi.properties & MidiPortSelection;
2026 row[midi_port_columns.fullname] = *s;
2027 row[midi_port_columns.shortname] = AudioEngine::instance()->short_port_name_from_port_name (*s);
2030 view.set_model (model);
2036 MidiPortOptions::midi_music_column_toggled (string const & path, TreeView* view)
2038 TreeIter iter = view->get_model()->get_iter (path);
2044 bool new_value = ! bool ((*iter)[midi_port_columns.music_data]);
2046 /* don't reset model - wait for MidiPortInfoChanged signal */
2049 ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.fullname], MidiPortMusic);
2051 ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.fullname], MidiPortMusic);
2056 MidiPortOptions::midi_control_column_toggled (string const & path, TreeView* view)
2058 TreeIter iter = view->get_model()->get_iter (path);
2064 bool new_value = ! bool ((*iter)[midi_port_columns.control_data]);
2066 /* don't reset model - wait for MidiPortInfoChanged signal */
2069 ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.fullname], MidiPortControl);
2071 ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.fullname], MidiPortControl);
2076 MidiPortOptions::midi_selection_column_toggled (string const & path, TreeView* view)
2078 TreeIter iter = view->get_model()->get_iter (path);
2084 bool new_value = ! bool ((*iter)[midi_port_columns.selection]);
2086 /* don't reset model - wait for MidiSelectionPortsChanged signal */
2089 ARDOUR::AudioEngine::instance()->add_midi_port_flags ((*iter)[midi_port_columns.fullname], MidiPortSelection);
2091 ARDOUR::AudioEngine::instance()->remove_midi_port_flags ((*iter)[midi_port_columns.fullname], MidiPortSelection);
2096 MidiPortOptions::pretty_name_edit (std::string const & path, string const & new_text, Gtk::TreeView* view)
2098 TreeIter iter = view->get_model()->get_iter (path);
2104 AudioEngine::instance()->set_port_pretty_name ((*iter)[midi_port_columns.fullname], new_text);
2109 RCOptionEditor::RCOptionEditor ()
2110 : OptionEditorContainer (Config, string_compose (_("%1 Preferences"), PROGRAM_NAME))
2111 /* pack self-as-vbox into tabbable */
2112 , Tabbable (*this, _("Preferences"), /* detached by default */ false)
2113 , _rc_config (Config)
2114 , _mixer_strip_visibility ("mixer-element-visibility")
2116 UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &RCOptionEditor::parameter_changed));
2120 uint32_t hwcpus = hardware_concurrency ();
2124 add_option (_("General"), new OptionEditorHeading (_("DSP CPU Utilization")));
2126 ComboOption<int32_t>* procs = new ComboOption<int32_t> (
2128 _("Signal processing uses"),
2129 sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
2130 sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
2133 procs->add (-1, _("all but one processor"));
2134 procs->add (0, _("all available processors"));
2136 for (uint32_t i = 1; i <= hwcpus; ++i) {
2137 procs->add (i, string_compose (P_("%1 processor", "%1 processors", i), i));
2140 procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
2142 add_option (_("General"), procs);
2145 /* Image cache size */
2146 add_option (_("General"), new OptionEditorHeading (_("Memory Usage")));
2148 HSliderOption *sics = new HSliderOption ("waveform-cache-size",
2149 _("Waveform image cache size (megabytes)"),
2150 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_cache_size),
2151 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_cache_size),
2152 1, 1024, 10 /* 1 MB to 1GB in steps of 10MB */
2154 sics->scale().set_digits (0);
2155 Gtkmm2ext::UI::instance()->set_tip (
2157 _("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
2158 add_option (_("General"), sics);
2160 add_option (_("General"), new OptionEditorHeading (_("Engine")));
2162 add_option (_("General"),
2164 "try-autostart-engine",
2165 _("Try to auto-launch audio/midi engine"),
2166 sigc::mem_fun (*_rc_config, &RCConfiguration::get_try_autostart_engine),
2167 sigc::mem_fun (*_rc_config, &RCConfiguration::set_try_autostart_engine)
2170 add_option (_("General"), new OptionEditorHeading (_("Automation")));
2172 add_option (_("General"),
2173 new SpinOption<double> (
2174 "automation-thinning-factor",
2175 _("Thinning factor (larger value => less data)"),
2176 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_thinning_factor),
2177 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_thinning_factor),
2181 add_option (_("General"),
2182 new SpinOption<double> (
2183 "automation-interval-msecs",
2184 _("Automation sampling interval (milliseconds)"),
2185 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_interval_msecs),
2186 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_interval_msecs),
2190 add_option (_("General"), new OptionEditorHeading (_("Tempo")));
2192 bo = new BoolOption (
2193 "allow-non-quarter-pulse",
2194 _("Allow non quarter-note pulse"),
2195 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_allow_non_quarter_pulse),
2196 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_allow_non_quarter_pulse)
2198 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2199 string_compose (_("<b>When enabled</b> %1 will allow tempo to be expressed in divisions per minute\n"
2200 "<b>When disabled</b> %1 will only allow tempo to be expressed in quarter notes per minute"),
2202 add_option (_("General"), bo);
2204 if (!ARDOUR::Profile->get_mixbus()) {
2205 add_option (_("General"), new OptionEditorHeading (_("GUI Lock")));
2206 /* Lock GUI timeout */
2208 HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
2209 _("Lock timeout (seconds)"),
2210 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_lock_gui_after_seconds),
2211 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_lock_gui_after_seconds),
2214 slts->scale().set_digits (0);
2215 Gtkmm2ext::UI::instance()->set_tip (
2217 _("Lock GUI after this many idle seconds (zero to never lock)"));
2218 add_option (_("General"), slts);
2220 ComboOption<ScreenSaverMode>* scsvr = new ComboOption<ScreenSaverMode> (
2221 "screen-saver-mode",
2222 _("System Screensaver Mode"),
2223 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_screen_saver_mode),
2224 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_screen_saver_mode)
2227 scsvr->add (InhibitNever, _("Never Inhibit"));
2228 scsvr->add (InhibitWhileRecording, _("Inhibit while Recording"));
2229 scsvr->add (InhibitAlways, string_compose (_("Inhibit while %1 is running"), PROGRAM_NAME));
2231 add_option (_("General"), scsvr);
2236 add_option (_("General/Session"), new OptionEditorHeading (S_("Options|Undo")));
2238 add_option (_("General/Session"), new UndoOptions (_rc_config));
2240 add_option (_("General/Session"),
2242 "verify-remove-last-capture",
2243 _("Verify removal of last capture"),
2244 sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
2245 sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
2248 add_option (_("General/Session"), new OptionEditorHeading (_("Session Management")));
2250 add_option (_("General/Session"),
2252 "periodic-safety-backups",
2253 _("Make periodic backups of the session file"),
2254 sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
2255 sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
2258 add_option (_("General/Session"),
2260 "only-copy-imported-files",
2261 _("Always copy imported files"),
2262 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_only_copy_imported_files),
2263 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_only_copy_imported_files)
2266 add_option (_("General/Session"), new DirectoryOption (
2267 X_("default-session-parent-dir"),
2268 _("Default folder for new sessions:"),
2269 sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
2270 sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
2273 add_option (_("General/Session"),
2274 new SpinOption<uint32_t> (
2275 "max-recent-sessions",
2276 _("Maximum number of recent sessions"),
2277 sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
2278 sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
2285 add_option (_("General/Translation"), new OptionEditorHeading (_("Internationalization")));
2287 bo = new BoolOption (
2288 "enable-translation",
2289 _("Use translations"),
2290 sigc::ptr_fun (ARDOUR::translations_are_enabled),
2291 sigc::ptr_fun (ARDOUR::set_translations_enabled)
2294 bo->set_note (string_compose (_("These settings will only take effect after %1 is restarted (if available for your language preferences)."), PROGRAM_NAME));
2296 add_option (_("General/Translation"), bo);
2298 parameter_changed ("enable-translation");
2299 #endif // ENABLE_NLS
2304 add_option (_("Editor"), new OptionEditorHeading (_("General")));
2306 bo = new BoolOption (
2308 _("Prompt for new marker names"),
2309 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
2310 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
2312 add_option (_("Editor"), bo);
2313 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."
2314 "\n\nYou can always rename markers by right-clicking on them"));
2316 add_option (_("Editor"),
2318 "draggable-playhead",
2319 _("Allow dragging of playhead"),
2320 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead),
2321 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead)
2324 ComboOption<float>* dps = new ComboOption<float> (
2325 "draggable-playhead-speed",
2326 _("Playhead dragging speed (%)"),
2327 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_draggable_playhead_speed),
2328 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_draggable_playhead_speed)
2330 dps->add (0.05, _("5%"));
2331 dps->add (0.1, _("10%"));
2332 dps->add (0.25, _("25%"));
2333 dps->add (0.5, _("50%"));
2334 dps->add (1.0, _("100%"));
2335 add_option (_("Editor"), dps);
2337 ComboOption<float>* eet = new ComboOption<float> (
2338 "extra-ui-extents-time",
2339 _("Limit zooming & summary view to X minutes beyond session extents"),
2340 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_extra_ui_extents_time),
2341 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_extra_ui_extents_time)
2343 eet->add (1, _("1 minute"));
2344 eet->add (2, _("2 minutes"));
2345 eet->add (20, _("20 minutes"));
2346 eet->add (60, _("1 hour"));
2347 eet->add (60*2, _("2 hours"));
2348 eet->add (60*24, _("24 hours"));
2349 add_option (_("Editor"), eet);
2351 if (!Profile->get_mixbus()) {
2353 add_option (_("Editor"),
2355 "use-mouse-position-as-zoom-focus-on-scroll",
2356 _("Zoom to mouse position when zooming with scroll wheel"),
2357 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_mouse_position_as_zoom_focus_on_scroll),
2358 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_mouse_position_as_zoom_focus_on_scroll)
2362 add_option (_("Editor"),
2364 "use-time-rulers-to-zoom-with-vertical-drag",
2365 _("Zoom with vertical drag in rulers"),
2366 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_time_rulers_to_zoom_with_vertical_drag),
2367 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_time_rulers_to_zoom_with_vertical_drag)
2370 add_option (_("Editor"),
2372 "use-double-click-to-zoom-to-selection",
2373 _("Double click zooms to selection"),
2374 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_double_click_to_zoom_to_selection),
2375 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_double_click_to_zoom_to_selection)
2378 add_option (_("Editor"),
2380 "update-editor-during-summary-drag",
2381 _("Update editor window during drags of the summary"),
2382 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_update_editor_during_summary_drag),
2383 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_update_editor_during_summary_drag)
2386 add_option (_("Editor"),
2388 "autoscroll-editor",
2389 _("Auto-scroll editor window when dragging near its edges"),
2390 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_autoscroll_editor),
2391 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_autoscroll_editor)
2394 add_option (_("Editor"),
2395 new BoolComboOption (
2396 "show-region-gain-envelopes",
2397 _("Show gain envelopes in audio regions"),
2399 _("only in Draw and Internal Edit modes"),
2400 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_gain),
2401 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_gain)
2404 add_option (_("Editor"), new OptionEditorHeading (_("Editor Behavior")));
2406 add_option (_("Editor"),
2408 "automation-follows-regions",
2409 _("Move relevant automation when audio regions are moved"),
2410 sigc::mem_fun (*_rc_config, &RCConfiguration::get_automation_follows_regions),
2411 sigc::mem_fun (*_rc_config, &RCConfiguration::set_automation_follows_regions)
2414 bo = new BoolOption (
2415 "new-automation-points-on-lane",
2416 _("Ignore Y-axis click position when adding new automation-points"),
2417 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_new_automation_points_on_lane),
2418 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_new_automation_points_on_lane)
2420 add_option (_("Editor"), bo);
2421 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2422 _("<b>When enabled</b> The new points drawn in any automation lane will be placed on the existing line, regardless of mouse y-axis position."));
2424 ComboOption<FadeShape>* fadeshape = new ComboOption<FadeShape> (
2425 "default-fade-shape",
2426 _("Default fade shape"),
2427 sigc::mem_fun (*_rc_config,
2428 &RCConfiguration::get_default_fade_shape),
2429 sigc::mem_fun (*_rc_config,
2430 &RCConfiguration::set_default_fade_shape)
2433 fadeshape->add (FadeLinear,
2434 _("Linear (for highly correlated material)"));
2435 fadeshape->add (FadeConstantPower, _("Constant power"));
2436 fadeshape->add (FadeSymmetric, _("Symmetric"));
2437 fadeshape->add (FadeSlow, _("Slow"));
2438 fadeshape->add (FadeFast, _("Fast"));
2440 add_option (_("Editor"), fadeshape);
2442 ComboOption<RegionEquivalence> *eqv = new ComboOption<RegionEquivalence> (
2443 "region-equivalency",
2444 _("Regions in active edit groups are edited together"),
2445 sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_equivalence),
2446 sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_equivalence)
2449 eqv->add (Overlap, _("whenever they overlap in time"));
2450 eqv->add (Enclosed, _("if either encloses the other"));
2451 eqv->add (Exact, _("only if they have identical length, position and origin"));
2452 eqv->add (LayerTime, _("only if they have identical length, position and layer"));
2454 add_option (_("Editor"), eqv);
2456 ComboOption<LayerModel>* lm = new ComboOption<LayerModel> (
2458 _("Layering model"),
2459 sigc::mem_fun (*_rc_config, &RCConfiguration::get_layer_model),
2460 sigc::mem_fun (*_rc_config, &RCConfiguration::set_layer_model)
2463 lm->add (LaterHigher, _("later is higher"));
2464 lm->add (Manual, _("manual layering"));
2465 add_option (_("Editor"), lm);
2467 add_option (_("Editor"), new OptionEditorHeading (_("Split/Separate")));
2469 ComboOption<RangeSelectionAfterSplit> *rras = new ComboOption<RangeSelectionAfterSplit> (
2470 "range-selection-after-separate",
2471 _("After a Separate operation, in Range mode"),
2472 sigc::mem_fun (*_rc_config, &RCConfiguration::get_range_selection_after_split),
2473 sigc::mem_fun (*_rc_config, &RCConfiguration::set_range_selection_after_split));
2475 rras->add(ClearSel, _("Clear the Range Selection"));
2476 rras->add(PreserveSel, _("Preserve the Range Selection"));
2477 rras->add(ForceSel, _("Force-Select the regions under the range. (this might cause a tool change)"));
2478 add_option (_("Editor"), rras);
2480 ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
2481 "region-selection-after-split",
2482 _("After a Split operation, in Object mode"),
2483 sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
2484 sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
2486 // TODO: decide which of these modes are really useful
2487 rsas->add(None, _("Clear the Selected Regions"));
2488 rsas->add(NewlyCreatedLeft, _("Select only the newly-created regions BEFORE the split point"));
2489 rsas->add(NewlyCreatedRight, _("Select only the newly-created regions AFTER the split point"));
2490 rsas->add(NewlyCreatedBoth, _("Select the newly-created regions"));
2491 // rsas->add(Existing, _("unmodified regions in the existing selection"));
2492 // rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
2493 // rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
2494 rsas->add(ExistingNewlyCreatedBoth, _("Preserve the existing selection, AND select all newly-created regions"));
2496 add_option (_("Editor"), rsas);
2498 add_option (_("Editor/Snap"), new OptionEditorHeading (_("General Snap options:")));
2500 add_option (_("Editor/Snap"),
2501 new SpinOption<uint32_t> (
2503 _("Snap Threshold (pixels)"),
2504 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_threshold),
2505 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_threshold),
2510 add_option (_("Editor/Snap"),
2512 "show-snapped-cursor",
2513 _("Show \"snapped cursor\""),
2514 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_snapped_cursor),
2515 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_snapped_cursor)
2518 add_option (_("Editor/Snap"),
2520 "rubberbanding-snaps-to-grid",
2521 _("Snap rubberband selection to grid"),
2522 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rubberbanding_snaps_to_grid),
2523 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rubberbanding_snaps_to_grid)
2526 add_option (_("Editor/Snap"),
2528 "grid-follows-internal",
2529 _("Grid switches to alternate selection for Internal Edit tools"),
2530 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_grid_follows_internal),
2531 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_grid_follows_internal)
2534 add_option (_("Editor/Snap"),
2536 "rulers-follow-grid",
2537 _("Rulers automatically change to follow the Grid mode selection"),
2538 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_rulers_follow_grid),
2539 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_rulers_follow_grid)
2542 add_option (_("Editor/Snap"), new OptionEditorHeading (_("When \"Snap\" is enabled, snap to:")));
2545 add_option (_("Editor/Snap"),
2549 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_marks),
2550 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_marks)
2553 add_option (_("Editor/Snap"),
2555 "snap-to-region-sync",
2556 _("Region Sync Points"),
2557 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_sync),
2558 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_sync)
2561 add_option (_("Editor/Snap"),
2563 "snap-to-region-start",
2565 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_start),
2566 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_start)
2569 add_option (_("Editor/Snap"),
2571 "snap-to-region-end",
2573 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_region_end),
2574 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_region_end)
2577 add_option (_("Editor/Snap"),
2581 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_snap_to_grid),
2582 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_snap_to_grid)
2585 add_option (_("Editor/Modifiers"), new OptionEditorHeading (_("Keyboard Modifiers")));
2586 add_option (_("Editor/Modifiers"), new KeyboardOptions);
2587 add_option (_("Editor/Modifiers"), new OptionEditorBlank ());
2589 /* MIXER -- SOLO AND MUTE */
2591 add_option (_("Mixer"), new OptionEditorHeading (_("Solo")));
2593 _solo_control_is_listen_control = new BoolOption (
2594 "solo-control-is-listen-control",
2595 _("Solo controls are Listen controls"),
2596 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
2597 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
2600 add_option (_("Mixer"), _solo_control_is_listen_control);
2602 add_option (_("Mixer"),
2605 _("Exclusive solo"),
2606 sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
2607 sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
2610 add_option (_("Mixer"),
2613 _("Show solo muting"),
2614 sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
2615 sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
2618 add_option (_("Mixer"),
2620 "solo-mute-override",
2621 _("Soloing overrides muting"),
2622 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
2623 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
2626 add_option (_("Mixer"),
2629 _("Solo-in-place mute cut (dB)"),
2630 sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
2631 sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
2634 _listen_position = new ComboOption<ListenPosition> (
2636 _("Listen Position"),
2637 sigc::mem_fun (*_rc_config, &RCConfiguration::get_listen_position),
2638 sigc::mem_fun (*_rc_config, &RCConfiguration::set_listen_position)
2641 _listen_position->add (AfterFaderListen, _("after-fader (AFL)"));
2642 _listen_position->add (PreFaderListen, _("pre-fader (PFL)"));
2644 add_option (_("Mixer"), _listen_position);
2646 ComboOption<PFLPosition>* pp = new ComboOption<PFLPosition> (
2648 _("PFL signals come from"),
2649 sigc::mem_fun (*_rc_config, &RCConfiguration::get_pfl_position),
2650 sigc::mem_fun (*_rc_config, &RCConfiguration::set_pfl_position)
2653 pp->add (PFLFromBeforeProcessors, _("before pre-fader processors"));
2654 pp->add (PFLFromAfterProcessors, _("pre-fader but after pre-fader processors"));
2656 add_option (_("Mixer"), pp);
2658 ComboOption<AFLPosition>* pa = new ComboOption<AFLPosition> (
2660 _("AFL signals come from"),
2661 sigc::mem_fun (*_rc_config, &RCConfiguration::get_afl_position),
2662 sigc::mem_fun (*_rc_config, &RCConfiguration::set_afl_position)
2665 pa->add (AFLFromBeforeProcessors, _("immediately post-fader"));
2666 pa->add (AFLFromAfterProcessors, _("after post-fader processors (before pan)"));
2668 add_option (_("Mixer"), pa);
2670 add_option (_("Mixer"), new OptionEditorHeading (_("Default Track / Bus Muting Options")));
2672 add_option (_("Mixer"),
2674 "mute-affects-pre-fader",
2675 _("Mute affects pre-fader sends"),
2676 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_pre_fader),
2677 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_pre_fader)
2680 add_option (_("Mixer"),
2682 "mute-affects-post-fader",
2683 _("Mute affects post-fader sends"),
2684 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_post_fader),
2685 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_post_fader)
2688 add_option (_("Mixer"),
2690 "mute-affects-control-outs",
2691 _("Mute affects control outputs"),
2692 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_control_outs),
2693 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_control_outs)
2696 add_option (_("Mixer"),
2698 "mute-affects-main-outs",
2699 _("Mute affects main outputs"),
2700 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mute_affects_main_outs),
2701 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mute_affects_main_outs)
2705 if (!ARDOUR::Profile->get_mixbus()) {
2706 add_option (_("Mixer"), new OptionEditorHeading (_("Send Routing")));
2707 add_option (_("Mixer"),
2709 "link-send-and-route-panner",
2710 _("Link panners of Aux and External Sends with main panner by default"),
2711 sigc::mem_fun (*_rc_config, &RCConfiguration::get_link_send_and_route_panner),
2712 sigc::mem_fun (*_rc_config, &RCConfiguration::set_link_send_and_route_panner)
2718 add_option (_("Signal Flow"), new OptionEditorHeading (_("Monitoring")));
2720 ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
2722 _("Record monitoring handled by"),
2723 sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
2724 sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
2727 if (AudioEngine::instance()->port_engine().can_monitor_input()) {
2728 mm->add (HardwareMonitoring, _("via Audio Driver"));
2731 string prog (PROGRAM_NAME);
2732 boost::algorithm::to_lower (prog);
2733 mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
2734 mm->add (ExternalMonitoring, _("audio hardware"));
2736 add_option (_("Signal Flow"), mm);
2738 bo = new BoolOption (
2739 "tape-machine-mode",
2740 _("Tape machine mode"),
2741 sigc::mem_fun (*_rc_config, &RCConfiguration::get_tape_machine_mode),
2742 sigc::mem_fun (*_rc_config, &RCConfiguration::set_tape_machine_mode)
2744 add_option (_("Signal Flow"), bo);
2745 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2746 string_compose (_("<b>When enabled</b> %1 will not monitor a track's input if the transport is stopped."),
2749 if (!Profile->get_mixbus()) {
2751 add_option (_("Signal Flow"), new OptionEditorHeading (_("Track and Bus Connections")));
2753 bo = new BoolOption (
2754 "auto-connect-standard-busses",
2755 _("Auto-connect main output (master or monitor) bus to physical ports"),
2756 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_connect_standard_busses),
2757 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_connect_standard_busses)
2759 add_option (_("Signal Flow"), bo);
2760 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2761 _("<b>When enabled</b> the main output bus is auto-connected to the first N physical ports. "
2762 "If the session has a monitor-section, the monitor-bus output is conneced the the hardware playback ports, "
2763 "otherwise the master-bus output is directly used for playback."));
2765 ComboOption<AutoConnectOption>* iac = new ComboOption<AutoConnectOption> (
2766 "input-auto-connect",
2767 _("Connect track inputs"),
2768 sigc::mem_fun (*_rc_config, &RCConfiguration::get_input_auto_connect),
2769 sigc::mem_fun (*_rc_config, &RCConfiguration::set_input_auto_connect)
2772 iac->add (AutoConnectPhysical, _("automatically to physical inputs"));
2773 iac->add (ManualConnect, _("manually"));
2775 add_option (_("Signal Flow"), iac);
2777 ComboOption<AutoConnectOption>* oac = new ComboOption<AutoConnectOption> (
2778 "output-auto-connect",
2779 _("Connect track and bus outputs"),
2780 sigc::mem_fun (*_rc_config, &RCConfiguration::get_output_auto_connect),
2781 sigc::mem_fun (*_rc_config, &RCConfiguration::set_output_auto_connect)
2784 oac->add (AutoConnectPhysical, _("automatically to physical outputs"));
2785 oac->add (AutoConnectMaster, _("automatically to master bus"));
2786 oac->add (ManualConnect, _("manually"));
2788 add_option (_("Signal Flow"), oac);
2790 bo = new BoolOption (
2792 _("Use 'Strict-I/O' for new tracks or busses"),
2793 sigc::mem_fun (*_rc_config, &RCConfiguration::get_strict_io),
2794 sigc::mem_fun (*_rc_config, &RCConfiguration::set_strict_io)
2797 add_option (_("Signal Flow"), bo);
2798 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2799 _("With strict-i/o enabled, Effect Processors will not modify the number of channels on a track. The number of output channels will always match the number of input channels."));
2806 add_option (_("Audio"), new OptionEditorHeading (_("Buffering")));
2808 add_option (_("Audio"), new BufferingOptions (_rc_config));
2810 add_option (_("Audio"), new OptionEditorHeading (_("Denormals")));
2812 add_option (_("Audio"),
2814 "denormal-protection",
2815 _("Use DC bias to protect against denormals"),
2816 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_protection),
2817 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_protection)
2820 ComboOption<DenormalModel>* dm = new ComboOption<DenormalModel> (
2822 _("Processor handling"),
2823 sigc::mem_fun (*_rc_config, &RCConfiguration::get_denormal_model),
2824 sigc::mem_fun (*_rc_config, &RCConfiguration::set_denormal_model)
2828 dm->add (DenormalNone, _("no processor handling"));
2830 FPU* fpu = FPU::instance();
2832 if (fpu->has_flush_to_zero()) {
2834 dm->add (DenormalFTZ, _("use FlushToZero"));
2835 } else if (_rc_config->get_denormal_model() == DenormalFTZ) {
2836 _rc_config->set_denormal_model(DenormalNone);
2839 if (fpu->has_denormals_are_zero()) {
2841 dm->add (DenormalDAZ, _("use DenormalsAreZero"));
2842 } else if (_rc_config->get_denormal_model() == DenormalDAZ) {
2843 _rc_config->set_denormal_model(DenormalNone);
2846 if (fpu->has_flush_to_zero() && fpu->has_denormals_are_zero()) {
2848 dm->add (DenormalFTZDAZ, _("use FlushToZero and DenormalsAreZero"));
2849 } else if (_rc_config->get_denormal_model() == DenormalFTZDAZ) {
2850 _rc_config->set_denormal_model(DenormalNone);
2854 dm->set_sensitive(false);
2857 dm->set_note (_("Changes may not be effective until audio-engine restart."));
2859 add_option (_("Audio"), dm);
2861 add_option (_("Audio"), new OptionEditorHeading (_("Regions")));
2863 add_option (_("Audio"),
2865 "auto-analyse-audio",
2866 _("Enable automatic analysis of audio"),
2867 sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
2868 sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
2871 add_option (_("Audio"),
2873 "replicate-missing-region-channels",
2874 _("Replicate missing region channels"),
2875 sigc::mem_fun (*_rc_config, &RCConfiguration::get_replicate_missing_region_channels),
2876 sigc::mem_fun (*_rc_config, &RCConfiguration::set_replicate_missing_region_channels)
2881 add_option (_("MIDI"), new OptionEditorHeading (_("Buffering")));
2883 add_option (_("MIDI"), new OptionEditorHeading (_("Session")));
2885 add_option (_("MIDI"),
2886 new SpinOption<int32_t> (
2887 "initial-program-change",
2888 _("Initial program change"),
2889 sigc::mem_fun (*_rc_config, &RCConfiguration::get_initial_program_change),
2890 sigc::mem_fun (*_rc_config, &RCConfiguration::set_initial_program_change),
2894 add_option (_("MIDI"), new OptionEditorHeading (_("Audition")));
2896 add_option (_("MIDI"),
2899 _("Sound MIDI notes as they are selected in the editor"),
2900 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_sound_midi_notes),
2901 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_sound_midi_notes)
2906 add_option (_("Metronome"), new OptionEditorHeading (_("Metronome")));
2907 add_option (_("Metronome"), new ClickOptions (_rc_config));
2908 add_option (_("Metronome"), new OptionEditorHeading (_("Options")));
2910 bo = new BoolOption (
2911 "click-record-only",
2912 _("Enable metronome only while recording"),
2913 sigc::mem_fun (*_rc_config, &RCConfiguration::get_click_record_only),
2914 sigc::mem_fun (*_rc_config, &RCConfiguration::set_click_record_only)
2917 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
2918 string_compose (_("<b>When enabled</b> the metronome will remain silent if %1 is <b>not recording</b>."), PROGRAM_NAME));
2919 add_option (_("Metronome"), bo);
2920 add_option (_("Metronome"), new OptionEditorBlank ());
2925 add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
2927 ComboOption<float>* mht = new ComboOption<float> (
2929 _("Peak hold time"),
2930 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_hold),
2931 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_hold)
2934 mht->add (MeterHoldOff, _("off"));
2935 mht->add (MeterHoldShort, _("short"));
2936 mht->add (MeterHoldMedium, _("medium"));
2937 mht->add (MeterHoldLong, _("long"));
2939 add_option (S_("Preferences|Metering"), mht);
2941 ComboOption<float>* mfo = new ComboOption<float> (
2944 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
2945 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
2948 mfo->add (METER_FALLOFF_OFF, _("off"));
2949 mfo->add (METER_FALLOFF_SLOWEST, _("slowest [6.6dB/sec]"));
2950 mfo->add (METER_FALLOFF_SLOW, _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
2951 mfo->add (METER_FALLOFF_SLOWISH, _("moderate [12.0dB/sec] (DIN)"));
2952 mfo->add (METER_FALLOFF_MODERATE, _("medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
2953 mfo->add (METER_FALLOFF_MEDIUM, _("fast [20dB/sec]"));
2954 mfo->add (METER_FALLOFF_FAST, _("very fast [32dB/sec]"));
2956 add_option (S_("Preferences|Metering"), mfo);
2958 ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
2959 "meter-line-up-level",
2960 _("Meter line-up level; 0dBu"),
2961 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_level),
2962 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_level)
2965 mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2966 mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2967 mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2968 mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2970 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."));
2972 add_option (S_("Preferences|Metering"), mlu);
2974 ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
2975 "meter-line-up-din",
2976 _("IEC1/DIN Meter line-up level; 0dBu"),
2977 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_din),
2978 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_din)
2981 mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
2982 mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
2983 mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
2984 mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
2986 Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
2988 add_option (S_("Preferences|Metering"), mld);
2990 ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
2991 "meter-vu-standard",
2992 _("VU Meter standard"),
2993 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_vu_standard),
2994 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_vu_standard)
2997 mvu->add (MeteringVUfrench, _("0VU = -2dBu (France)"));
2998 mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
2999 mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
3000 mvu->add (MeteringVUeight, _("0VU = +8dBu"));
3002 add_option (S_("Preferences|Metering"), mvu);
3004 HSliderOption *mpks = new HSliderOption("meter-peak",
3005 _("Peak indicator threshold [dBFS]"),
3006 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_peak),
3007 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_peak),
3011 Gtkmm2ext::UI::instance()->set_tip (
3013 _("Specify the audio signal level in dBFS at and above which the meter-peak indicator will flash red."));
3015 add_option (S_("Preferences|Metering"), mpks);
3017 OptionEditorHeading* default_meter_head = new OptionEditorHeading (_("Default Meter Types"));
3018 default_meter_head->set_note (_("These settings apply to newly created tracks and busses. For the Master bus, this will be when a new session is created."));
3020 add_option (S_("Preferences|Metering"), default_meter_head);
3022 ComboOption<MeterType>* mtm = new ComboOption<MeterType> (
3023 "meter-type-master",
3024 _("Default Meter Type for Master Bus"),
3025 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_master),
3026 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_master)
3028 mtm->add (MeterPeak, ArdourMeter::meter_type_string(MeterPeak));
3029 mtm->add (MeterK20, ArdourMeter::meter_type_string(MeterK20));
3030 mtm->add (MeterK14, ArdourMeter::meter_type_string(MeterK14));
3031 mtm->add (MeterK12, ArdourMeter::meter_type_string(MeterK12));
3032 mtm->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3033 mtm->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3034 mtm->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3035 mtm->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3037 add_option (S_("Preferences|Metering"), mtm);
3040 ComboOption<MeterType>* mtb = new ComboOption<MeterType> (
3042 _("Default meter type for busses"),
3043 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_bus),
3044 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_bus)
3046 mtb->add (MeterPeak, ArdourMeter::meter_type_string(MeterPeak));
3047 mtb->add (MeterK20, ArdourMeter::meter_type_string(MeterK20));
3048 mtb->add (MeterK14, ArdourMeter::meter_type_string(MeterK14));
3049 mtb->add (MeterK12, ArdourMeter::meter_type_string(MeterK12));
3050 mtb->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
3051 mtb->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
3052 mtb->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
3053 mtb->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
3055 add_option (S_("Preferences|Metering"), mtb);
3057 ComboOption<MeterType>* mtt = new ComboOption<MeterType> (
3059 _("Default meter type for tracks"),
3060 sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_track),
3061 sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_track)
3063 mtt->add (MeterPeak, ArdourMeter::meter_type_string(MeterPeak));
3064 mtt->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
3066 add_option (S_("Preferences|Metering"), mtt);
3068 add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Post Export Analysis")));
3070 add_option (S_("Preferences|Metering"),
3072 "save-export-analysis-image",
3073 _("Save loudness analysis as image file after export"),
3074 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_save_export_analysis_image),
3075 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_save_export_analysis_image)
3078 add_option (S_("Preferences|Metering"),
3080 "save-export-mixer-screenshot",
3081 _("Save Mixer screenshot after export"),
3082 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_save_export_mixer_screenshot),
3083 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_save_export_mixer_screenshot)
3086 /* TRANSPORT & Sync */
3088 add_option (_("Transport"), new OptionEditorHeading (_("General")));
3090 bo = new BoolOption (
3091 "stop-at-session-end",
3092 _("Stop at the end of the session"),
3093 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
3094 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
3096 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3097 string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, it will stop the transport "
3098 "when it reaches the current session end marker\n\n"
3099 "<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
3101 add_option (_("Transport"), bo);
3103 bo = new BoolOption (
3104 "latched-record-enable",
3105 _("Keep record-enable engaged on stop"),
3106 sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
3107 sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
3109 add_option (_("Transport"), bo);
3110 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3111 _("<b>When enabled</b> master record will remain engaged when the transport transitions to stop.\n<b>When disabled</b> master record will be disabled when the transport transitions to stop."));
3113 bo = new BoolOption (
3114 "disable-disarm-during-roll",
3115 _("Disable per-track record disarm while rolling"),
3116 sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
3117 sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
3119 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("<b>When enabled</b> this will prevent you from accidentally stopping specific tracks recording during a take."));
3120 add_option (_("Transport"), bo);
3122 bo = new BoolOption (
3124 _("12dB gain reduction during fast-forward and fast-rewind"),
3125 sigc::mem_fun (*_rc_config, &RCConfiguration::get_quieten_at_speed),
3126 sigc::mem_fun (*_rc_config, &RCConfiguration::set_quieten_at_speed)
3128 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3129 _("<b>When enabled</b> this will reduce the unpleasant increase in perceived volume "
3130 "that occurs when fast-forwarding or rewinding through some kinds of audio"));
3131 add_option (_("Transport"), bo);
3133 ComboOption<float>* psc = new ComboOption<float> (
3136 sigc::mem_fun (*_rc_config, &RCConfiguration::get_preroll_seconds),
3137 sigc::mem_fun (*_rc_config, &RCConfiguration::set_preroll_seconds)
3139 Gtkmm2ext::UI::instance()->set_tip (psc->tip_widget(),
3140 (_("The amount of preroll to apply when <b>Play with Preroll</b> or <b>Record with Preroll</b>is initiated.\n\n"
3141 "If <b>Follow Edits</b> is enabled, the preroll is applied to the playhead position when a region is selected or trimmed.")));
3142 psc->add (-4.0, _("4 Bars"));
3143 psc->add (-2.0, _("2 Bars"));
3144 psc->add (-1.0, _("1 Bar"));
3145 psc->add (0.0, _("0 (no pre-roll)"));
3146 psc->add (0.1, _("0.1 second"));
3147 psc->add (0.25, _("0.25 second"));
3148 psc->add (0.5, _("0.5 second"));
3149 psc->add (1.0, _("1.0 second"));
3150 psc->add (2.0, _("2.0 seconds"));
3151 add_option (_("Transport"), psc);
3154 add_option (_("Transport"), new OptionEditorHeading (_("Looping")));
3156 bo = new BoolOption (
3158 _("Play loop is a transport mode"),
3159 sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
3160 sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
3162 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3163 (_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
3164 "<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
3167 add_option (_("Transport"), bo);
3170 ComboOption<LoopFadeChoice>* lca = new ComboOption<LoopFadeChoice> (
3173 sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_fade_choice),
3174 sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_fade_choice)
3176 lca->add (NoLoopFade, _("No fades at loop boundaries"));
3177 lca->add (EndLoopFade, _("Fade out at loop end"));
3178 lca->add (BothLoopFade, _("Fade in at loop start & Fade out at loop end"));
3179 lca->add (XFadeLoop, _("Cross-fade loop end and start"));
3180 add_option (_("Transport"), lca);
3181 Gtkmm2ext::UI::instance()->set_tip (lca->tip_widget(), _("Options for fades/crossfades at loop boundaries"));
3183 add_option (_("Transport"), new OptionEditorHeading (_("Dropout (xrun) Handling")));
3184 bo = new BoolOption (
3185 "stop-recording-on-xrun",
3186 _("Stop recording when an xrun occurs"),
3187 sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
3188 sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
3190 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3191 string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
3193 add_option (_("Transport"), bo);
3195 bo = new BoolOption (
3196 "create-xrun-marker",
3197 _("Create markers where xruns occur"),
3198 sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
3199 sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
3201 add_option (_("Transport"), bo);
3206 add_option (_("Sync"), new OptionEditorHeading (_("Transport Masters")));
3208 add_option (_("Sync"), new WidgetOption (X_("foo"), X_("Transport Masters"), _transport_masters_widget));
3210 _sync_framerate = new BoolOption (
3211 "timecode-sync-frame-rate",
3212 _("Match session video frame rate to external timecode"),
3213 sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
3214 sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
3216 Gtkmm2ext::UI::instance()->set_tip
3217 (_sync_framerate->tip_widget(),
3218 string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
3219 "<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
3220 "<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
3221 "Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
3222 "timecode standard and the session standard."), PROGRAM_NAME));
3224 add_option (_("Sync"), _sync_framerate);
3226 add_option (_("Sync/LTC"), new OptionEditorHeading (_("Linear Timecode (LTC) Generator")));
3228 add_option (_("Sync/LTC"),
3231 _("Enable LTC generator"),
3232 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
3233 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
3236 _ltc_send_continuously = new BoolOption (
3237 "ltc-send-continuously",
3238 _("Send LTC while stopped"),
3239 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
3240 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
3242 Gtkmm2ext::UI::instance()->set_tip
3243 (_ltc_send_continuously->tip_widget(),
3244 string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
3245 add_option (_("Sync/LTC"), _ltc_send_continuously);
3247 _ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level [dBFS]"),
3248 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_output_volume),
3249 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_output_volume),
3253 Gtkmm2ext::UI::instance()->set_tip
3254 (_ltc_volume_slider->tip_widget(),
3255 _("Specify the Peak Volume of the generated LTC signal in dBFS. A good value is 0dBu ^= -18dBFS in an EBU calibrated system"));
3257 add_option (_("Sync/LTC"), _ltc_volume_slider);
3259 add_option (_("Sync/MIDI"), new OptionEditorHeading (_("MIDI Beat Clock (Mclk) Generator")));
3261 add_option (_("Sync/MIDI"),
3264 _("Enable Mclk generator"),
3265 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
3266 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
3269 add_option (_("Sync/MIDI"), new OptionEditorHeading (_("MIDI Time Code (MTC) Generator")));
3271 add_option (_("Sync/MIDI"),
3274 _("Enable MTC Generator"),
3275 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
3276 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
3279 add_option (_("Sync/MIDI"),
3280 new SpinOption<int> (
3281 "mtc-qf-speed-tolerance",
3282 _("Percentage either side of normal transport speed to transmit MTC"),
3283 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
3284 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
3288 add_option (_("Sync/MIDI"), new OptionEditorHeading (_("MIDI Machine Control (MMC)")));
3290 add_option (_("Sync/MIDI"),
3293 _("Respond to MMC commands"),
3294 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
3295 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
3298 add_option (_("Sync/MIDI"),
3301 _("Send MMC commands"),
3302 sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
3303 sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
3306 add_option (_("Sync/MIDI"),
3307 new SpinOption<uint8_t> (
3308 "mmc-receive-device-id",
3309 _("Inbound MMC device ID"),
3310 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
3311 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
3315 add_option (_("Sync/MIDI"),
3316 new SpinOption<uint8_t> (
3317 "mmc-send-device-id",
3318 _("Outbound MMC device ID"),
3319 sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
3320 sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
3325 /* Control Surfaces */
3327 add_option (_("Control Surfaces"), new OptionEditorHeading (_("Control Surfaces")));
3328 add_option (_("Control Surfaces"), new ControlSurfacesOptions ());
3331 add_option (_("MIDI Ports"), new OptionEditorHeading (_("MIDI Port Options")));
3333 add_option (_("MIDI Ports"),
3335 "midi-input-follows-selection",
3336 _("MIDI input follows MIDI track selection"),
3337 sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_input_follows_selection),
3338 sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_input_follows_selection)
3341 add_option (_("MIDI Ports"), new MidiPortOptions ());
3342 add_option (_("MIDI Ports"), new OptionEditorBlank ());
3346 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
3347 add_option (_("Plugins"), new OptionEditorHeading (_("Scan/Discover")));
3348 add_option (_("Plugins"),
3349 new RcActionButton (_("Scan for Plugins"),
3350 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3354 add_option (_("Plugins"), new OptionEditorHeading (_("General")));
3356 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT)
3357 bo = new BoolOption (
3358 "show-plugin-scan-window",
3359 _("Always Display Plugin Scan Progress"),
3360 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_plugin_scan_window),
3361 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_plugin_scan_window)
3363 add_option (_("Plugins"), bo);
3364 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3365 _("<b>When enabled</b> a popup window showing plugin scan progress is displayed for indexing (cache load) and discovery (detect new plugins)"));
3368 bo = new BoolOption (
3369 "plugins-stop-with-transport",
3370 _("Silence plugins when the transport is stopped"),
3371 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugins_stop_with_transport),
3372 sigc::mem_fun (*_rc_config, &RCConfiguration::set_plugins_stop_with_transport)
3374 add_option (_("Plugins"), bo);
3375 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3376 _("<b>When enabled</b> plugins will be reset at transport stop. When disabled plugins will be left unchanged at transport stop.\n\nThis mostly affects plugins with a \"tail\" like Reverbs."));
3378 bo = new BoolOption (
3379 "new-plugins-active",
3380 _("Make new plugins active"),
3381 sigc::mem_fun (*_rc_config, &RCConfiguration::get_new_plugins_active),
3382 sigc::mem_fun (*_rc_config, &RCConfiguration::set_new_plugins_active)
3384 add_option (_("Plugins"), bo);
3385 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3386 _("<b>When enabled</b> plugins will be activated when they are added to tracks/busses. When disabled plugins will be left inactive when they are added to tracks/busses"));
3388 ComboOption<uint32_t>* lna = new ComboOption<uint32_t> (
3389 "limit-n-automatables",
3390 _("Limit automatable parameters per plugin"),
3391 sigc::mem_fun (*_rc_config, &RCConfiguration::get_limit_n_automatables),
3392 sigc::mem_fun (*_rc_config, &RCConfiguration::set_limit_n_automatables)
3394 lna->add (0, _("Unlimited"));
3395 lna->add (64, _("64 parameters"));
3396 lna->add (128, _("128 parameters"));
3397 lna->add (256, _("256 parameters"));
3398 lna->add (512, _("512 parameters"));
3399 lna->add (999, _("999 parameters"));
3400 add_option (_("Plugins"), lna);
3401 Gtkmm2ext::UI::instance()->set_tip (lna->tip_widget(),
3402 _("Some Plugins expose an unreasonable amount of control-inputs. This option limits the number of parameters that can are listed as automatable without restricting the number of total controls.\n\nThis reduces lag in the GUI and shortens excessively long drop-down lists for plugins with a large number of control ports.\n\nNote: This only affects newly added plugins and is applied to plugin on session-reload. Already automated parameters are retained."));
3405 #if (defined WINDOWS_VST_SUPPORT || defined MACVST_SUPPORT || defined LXVST_SUPPORT)
3406 add_option (_("Plugins/VST"), new OptionEditorHeading (_("VST")));
3408 add_option (_("Plugins/VST"),
3409 new RcActionButton (_("Scan for Plugins"),
3410 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3413 #if (defined AUDIOUNIT_SUPPORT && defined MACVST_SUPPORT)
3414 bo = new BoolOption (
3416 _("Enable Mac VST support (requires restart or re-scan)"),
3417 sigc::mem_fun (*_rc_config, &RCConfiguration::get_use_macvst),
3418 sigc::mem_fun (*_rc_config, &RCConfiguration::set_use_macvst)
3420 add_option (_("Plugins/VST"), bo);
3423 bo = new BoolOption (
3424 "discover-vst-on-start",
3425 _("Scan for [new] VST Plugins on Application Start"),
3426 sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_vst_on_start),
3427 sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_vst_on_start)
3429 add_option (_("Plugins/VST"), bo);
3430 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3431 _("<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"));
3433 #ifdef WINDOWS_VST_SUPPORT
3434 // currently verbose logging is only implemented for Windows VST.
3435 bo = new BoolOption (
3436 "verbose-plugin-scan",
3437 _("Verbose Plugin Scan"),
3438 sigc::mem_fun (*_rc_config, &RCConfiguration::get_verbose_plugin_scan),
3439 sigc::mem_fun (*_rc_config, &RCConfiguration::set_verbose_plugin_scan)
3441 add_option (_("Plugins/VST"), bo);
3442 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3443 _("<b>When enabled</b> additional information for every plugin is added to the Log Window."));
3446 add_option (_("Plugins/VST"), new VstTimeOutSliderOption (_rc_config));
3448 add_option (_("Plugins/VST"),
3449 new RcActionButton (_("Clear"),
3450 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_cache),
3453 add_option (_("Plugins/VST"),
3454 new RcActionButton (_("Clear"),
3455 sigc::mem_fun (*this, &RCOptionEditor::clear_vst_blacklist),
3456 _("VST Blacklist:")));
3459 #ifdef LXVST_SUPPORT
3460 add_option (_("Plugins/VST"),
3461 new RcActionButton (_("Edit"),
3462 sigc::mem_fun (*this, &RCOptionEditor::edit_lxvst_path),
3463 _("Linux VST Path:")));
3465 add_option (_("Plugins/VST"),
3466 new RcConfigDisplay (
3467 "plugin-path-lxvst",
3469 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_lxvst),
3473 #ifdef WINDOWS_VST_SUPPORT
3474 add_option (_("Plugins/VST"),
3475 new RcActionButton (_("Edit"),
3476 sigc::mem_fun (*this, &RCOptionEditor::edit_vst_path),
3477 _("Windows VST Path:")));
3478 add_option (_("Plugins/VST"),
3479 new RcConfigDisplay (
3482 sigc::mem_fun (*_rc_config, &RCConfiguration::get_plugin_path_vst),
3486 #ifdef AUDIOUNIT_SUPPORT
3488 add_option (_("Plugins/Audio Unit"), new OptionEditorHeading (_("Audio Unit")));
3490 add_option (_("Plugins/Audio Unit"),
3491 new RcActionButton (_("Scan for Plugins"),
3492 sigc::mem_fun (*this, &RCOptionEditor::plugin_scan_refresh)));
3495 bo = new BoolOption (
3496 "discover-audio-units",
3497 _("Scan for [new] AudioUnit Plugins on Application Start"),
3498 sigc::mem_fun (*_rc_config, &RCConfiguration::get_discover_audio_units),
3499 sigc::mem_fun (*_rc_config, &RCConfiguration::set_discover_audio_units)
3501 add_option (_("Plugins/Audio Unit"), bo);
3502 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3503 _("<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."));
3505 add_option (_("Plugins/Audio Unit"),
3506 new RcActionButton (_("Clear"),
3507 sigc::mem_fun (*this, &RCOptionEditor::clear_au_cache),
3510 add_option (_("Plugins/Audio Unit"),
3511 new RcActionButton (_("Clear"),
3512 sigc::mem_fun (*this, &RCOptionEditor::clear_au_blacklist),
3513 _("AU Blacklist:")));
3517 add_option (_("Plugins"), new OptionEditorHeading (_("LV1/LV2")));
3518 add_option (_("Plugins"),
3520 "conceal-lv1-if-lv2-exists",
3521 _("Conceal LADSPA (LV1) Plugins if matching LV2 exists"),
3522 sigc::mem_fun (*_rc_config, &RCConfiguration::get_conceal_lv1_if_lv2_exists),
3523 sigc::mem_fun (*_rc_config, &RCConfiguration::set_conceal_lv1_if_lv2_exists)
3527 #if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT || defined AUDIOUNIT_SUPPORT || defined HAVE_LV2)
3528 add_option (_("Plugins"), new OptionEditorHeading (_("Plugin GUI")));
3529 add_option (_("Plugins"),
3531 "open-gui-after-adding-plugin",
3532 _("Automatically open the plugin GUI when adding a new plugin"),
3533 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_open_gui_after_adding_plugin),
3534 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_open_gui_after_adding_plugin)
3537 #if (defined LV2_SUPPORT && defined LV2_EXTENDED)
3538 add_option (_("Plugins"),
3540 "show-inline-display-by-default",
3541 _("Show Plugin Inline Display on Mixerstrip by default"),
3542 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_inline_display_by_default),
3543 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_inline_display_by_default)
3546 _plugin_prefer_inline = new BoolOption (
3547 "prefer-inline-over-gui",
3548 _("Don't automatically open the plugin GUI when the plugin has an inline display mode"),
3549 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_prefer_inline_over_gui),
3550 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_prefer_inline_over_gui)
3552 add_option (_("Plugins"), _plugin_prefer_inline);
3555 add_option (_("Plugins"), new OptionEditorHeading (_("Instrument")));
3557 bo = new BoolOption (
3558 "ask-replace-instrument",
3559 _("Ask to replace existing instrument plugin"),
3560 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ask_replace_instrument),
3561 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ask_replace_instrument)
3563 add_option (_("Plugins"), bo);
3565 bo = new BoolOption (
3566 "ask-setup_instrument",
3567 _("Interactively configure instrument plugins on insert"),
3568 sigc::mem_fun (*_rc_config, &RCConfiguration::get_ask_setup_instrument),
3569 sigc::mem_fun (*_rc_config, &RCConfiguration::set_ask_setup_instrument)
3571 add_option (_("Plugins"), bo);
3572 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3573 _("<b>When enabled</b> show a dialog to select instrument channel configuration before adding a multichannel plugin."));
3576 add_option (_("Plugins"), new OptionEditorBlank ());
3579 #if (defined OPTIONAL_CAIRO_IMAGE_SURFACE || defined CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE)
3580 add_option (_("Appearance"), new OptionEditorHeading (_("Graphics Acceleration")));
3583 #ifdef OPTIONAL_CAIRO_IMAGE_SURFACE
3584 BoolOption* bgc = new BoolOption (
3585 "cairo-image-surface",
3586 _("Disable Graphics Hardware Acceleration (requires restart)"),
3587 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_cairo_image_surface),
3588 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_cairo_image_surface)
3591 Gtkmm2ext::UI::instance()->set_tip (bgc->tip_widget(), string_compose (
3592 _("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));
3593 add_option (_("Appearance"), bgc);
3596 #ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
3597 BoolOption* bgo = new BoolOption (
3599 _("Possibly improve slow graphical performance (requires restart)"),
3600 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_buggy_gradients),
3601 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_buggy_gradients)
3604 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));
3605 add_option (_("Appearance"), bgo);
3607 add_option (_("Appearance"), new OptionEditorHeading (_("Graphical User Interface")));
3609 add_option (_("Appearance"),
3612 _("Highlight widgets on mouseover"),
3613 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_widget_prelight),
3614 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_widget_prelight)
3617 add_option (_("Appearance"),
3620 _("Show tooltips if mouse hovers over a control"),
3621 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_tooltips),
3622 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_tooltips)
3625 bo = new BoolOption (
3626 "super-rapid-clock-update",
3627 _("Update clocks at TC Frame rate"),
3628 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
3629 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
3631 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
3632 _("<b>When enabled</b> clock displays are updated every Timecode Frame (fps).\n\n"
3633 "<b>When disabled</b> clock displays are updated only every 100ms."
3635 add_option (_("Appearance"), bo);
3637 add_option (_("Appearance"),
3640 _("Blink Rec-Arm buttons"),
3641 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_blink_rec_arm),
3642 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_blink_rec_arm)
3645 add_option (_("Appearance"),
3647 "blink-alert-indicators",
3648 _("Blink Alert Indicators"),
3649 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_blink_alert_indicators),
3650 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_blink_alert_indicators)
3655 /* font scaling does nothing with GDK/Quartz */
3656 add_option (_("Appearance"), new FontScalingOptions ());
3658 add_option (_("Appearance/Editor"), new OptionEditorHeading (_("General")));
3659 add_option (_("Appearance/Editor"),
3661 "show-name-highlight",
3662 _("Use name highlight bars in region displays (requires a restart)"),
3663 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_name_highlight),
3664 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_name_highlight)
3667 add_option (_("Appearance/Editor"),
3669 "color-regions-using-track-color",
3670 _("Region color follows track color"),
3671 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_color_regions_using_track_color),
3672 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_color_regions_using_track_color)
3675 add_option (_("Appearance/Editor"),
3677 "show-region-names",
3678 _("Show Region Names"),
3679 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_name),
3680 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_name)
3683 #ifndef MIXBUS // hide this setting in Mixbus. Always on, 4px
3684 ComboOption<uint32_t>* gap = new ComboOption<uint32_t> (
3685 "vertical-region-gap",
3686 _("Add a visual gap below Audio Regions"),
3687 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_vertical_region_gap),
3688 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_vertical_region_gap)
3690 gap->add (0, _("None"));
3691 gap->add (2, _("Small"));
3692 gap->add (4, _("Large"));
3693 add_option (_("Appearance/Editor"), gap);
3696 add_option (_("Appearance/Editor"), new OptionEditorHeading (_("Waveforms")));
3698 if (!Profile->get_mixbus()) {
3699 add_option (_("Appearance/Editor"),
3702 _("Show waveforms in regions"),
3703 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
3704 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
3708 add_option (_("Appearance/Editor"),
3710 "show-waveforms-while-recording",
3711 _("Show waveforms while recording"),
3712 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
3713 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
3716 add_option (_("Appearance/Editor"),
3718 "show-waveform-clipping",
3719 _("Show waveform clipping"),
3720 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveform_clipping),
3721 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveform_clipping)
3724 add_option (_("Appearance/Editor"), new ClipLevelOptions ());
3726 ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
3728 _("Waveform scale"),
3729 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_scale),
3730 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_scale)
3733 wfs->add (Linear, _("linear"));
3734 wfs->add (Logarithmic, _("logarithmic"));
3736 add_option (_("Appearance/Editor"), wfs);
3738 ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
3740 _("Waveform shape"),
3741 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_shape),
3742 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_shape)
3745 wfsh->add (Traditional, _("traditional"));
3746 wfsh->add (Rectified, _("rectified"));
3748 add_option (_("Appearance/Editor"), wfsh);
3750 add_option (_("Appearance/Editor"), new OptionEditorHeading (_("Editor Meters")));
3752 add_option (_("Appearance/Editor"),
3754 "show-track-meters",
3755 _("Show meters in track headers"),
3756 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
3757 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_track_meters)
3760 add_option (_("Appearance/Editor"),
3762 "editor-stereo-only-meters",
3763 _("Limit track header meters to stereo"),
3764 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_editor_stereo_only_meters),
3765 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_editor_stereo_only_meters)
3768 add_option (_("Appearance/Editor"), new OptionEditorHeading (_("MIDI Regions")));
3770 add_option (_("Appearance/Editor"),
3772 "display-first-midi-bank-as-zero",
3773 _("Display first MIDI bank/program as 0"),
3774 sigc::mem_fun (*_rc_config, &RCConfiguration::get_first_midi_bank_is_zero),
3775 sigc::mem_fun (*_rc_config, &RCConfiguration::set_first_midi_bank_is_zero)
3778 add_option (_("Appearance/Editor"),
3780 "never-display-periodic-midi",
3781 _("Don't display periodic (MTC, MMC) SysEx messages in MIDI Regions"),
3782 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_never_display_periodic_midi),
3783 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_never_display_periodic_midi)
3787 add_option (_("Appearance/Editor"),
3789 "use-note-bars-for-velocity",
3790 _("Show velocity horizontally inside notes"),
3791 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_note_bars_for_velocity),
3792 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_note_bars_for_velocity)
3795 add_option (_("Appearance/Editor"),
3797 "use-note-color-for-velocity",
3798 _("Use colors to show note velocity"),
3799 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_note_color_for_velocity),
3800 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_note_color_for_velocity)
3803 add_option (_("Appearance/Editor"), new OptionEditorBlank ());
3805 /* The names of these controls must be the same as those given in MixerStrip
3806 for the actual widgets being controlled.
3808 _mixer_strip_visibility.add (0, X_("Input"), _("Input"));
3809 _mixer_strip_visibility.add (0, X_("PhaseInvert"), _("Phase Invert"));
3810 _mixer_strip_visibility.add (0, X_("RecMon"), _("Record & Monitor"));
3811 _mixer_strip_visibility.add (0, X_("SoloIsoLock"), _("Solo Iso / Lock"));
3812 _mixer_strip_visibility.add (0, X_("Output"), _("Output"));
3813 _mixer_strip_visibility.add (0, X_("Comments"), _("Comments"));
3814 _mixer_strip_visibility.add (0, X_("VCA"), _("VCA Assigns"));
3816 add_option (_("Appearance/Mixer"),
3817 new VisibilityOption (
3819 &_mixer_strip_visibility,
3820 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_mixer_strip_visibility),
3821 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_mixer_strip_visibility)
3825 add_option (_("Appearance/Mixer"),
3827 "default-narrow_ms",
3828 _("Use narrow strips in the mixer for new strips by default"),
3829 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_default_narrow_ms),
3830 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
3833 ComboOption<uint32_t>* mic = new ComboOption<uint32_t> (
3834 "max-inline-controls",
3835 _("Limit inline-mixer-strip controls per plugin"),
3836 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_max_inline_controls),
3837 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_max_inline_controls)
3839 mic->add (0, _("Unlimited"));
3840 mic->add (16, _("16 parameters"));
3841 mic->add (32, _("32 parameters"));
3842 mic->add (64, _("64 parameters"));
3843 mic->add (128, _("128 parameters"));
3844 add_option (_("Appearance/Mixer"), mic);
3846 add_option (_("Appearance/Mixer"), new OptionEditorBlank ());
3848 add_option (_("Appearance/Toolbar"), new OptionEditorHeading (_("Main Transport Toolbar Items")));
3850 add_option (_("Appearance/Toolbar"),
3852 "show-toolbar-recpunch",
3853 _("Display Record/Punch Options"),
3854 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_recpunch),
3855 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_recpunch)
3858 add_option (_("Appearance/Toolbar"),
3860 "show-toolbar-monitoring",
3861 _("Display Monitor Options"),
3862 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_monitoring),
3863 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_monitoring)
3866 add_option (_("Appearance/Toolbar"),
3868 "show-toolbar-latency",
3869 _("Display Latency Compensation Info"),
3870 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_latency),
3871 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_latency)
3874 add_option (_("Appearance/Toolbar"),
3876 "show-toolbar-selclock",
3877 _("Display Selection Clock"),
3878 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_toolbar_selclock),
3879 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_toolbar_selclock)
3882 if (!ARDOUR::Profile->get_small_screen()) {
3883 add_option (_("Appearance/Toolbar"),
3885 "show-secondary-clock",
3886 _("Display Secondary Clock"),
3887 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_secondary_clock),
3888 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_secondary_clock)
3892 add_option (_("Appearance/Toolbar"),
3894 "show-mini-timeline",
3895 _("Display Navigation Timeline"),
3896 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_mini_timeline),
3897 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_mini_timeline)
3900 add_option (_("Appearance/Toolbar"),
3902 "show-editor-meter",
3903 _("Display Master Level Meter"),
3904 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_editor_meter),
3905 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_editor_meter)
3908 add_option (_("Appearance/Toolbar"),
3909 new ColumVisibilityOption (
3910 "action-table-columns", _("Display Action-Buttons"), MAX_LUA_ACTION_BUTTONS / 2,
3911 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_action_table_columns),
3912 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_action_table_columns)
3915 add_option (_("Appearance/Toolbar"), new OptionEditorBlank ());
3918 /* and now the theme manager */
3920 add_option (_("Appearance/Theme"), new OptionEditorHeading (_("Theme")));
3922 add_option (_("Appearance/Theme"), new BoolOption (
3924 _("Draw \"flat\" buttons"),
3925 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_flat_buttons),
3926 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_flat_buttons)
3929 add_option (_("Appearance/Theme"), new BoolOption (
3931 _("Draw \"boxy\" buttons"),
3932 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_boxy_buttons),
3933 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_boxy_buttons)
3936 add_option (_("Appearance/Theme"), new BoolOption (
3938 _("LED meter style"),
3939 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_style_led),
3940 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_style_led)
3944 HSliderOption *gui_hs = new HSliderOption(
3945 "timeline-item-gradient-depth",
3946 _("Waveforms color gradient depth"),
3947 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_gradient_depth),
3948 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_gradient_depth),
3951 gui_hs->scale().set_update_policy (Gtk::UPDATE_DELAYED);
3952 add_option (_("Appearance/Theme"), gui_hs);
3954 gui_hs = new HSliderOption(
3955 "timeline-item-gradient-depth",
3956 _("Timeline item gradient depth"),
3957 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_timeline_item_gradient_depth),
3958 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_timeline_item_gradient_depth),
3961 gui_hs->scale().set_update_policy (Gtk::UPDATE_DELAYED);
3962 add_option (_("Appearance/Theme"), gui_hs);
3964 vector<string> icon_sets = ::get_icon_sets ();
3965 if (icon_sets.size() > 1) {
3966 ComboOption<std::string>* io = new ComboOption<std::string> (
3967 "icon-set", _("Icon Set"),
3968 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_icon_set),
3969 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_icon_set)
3971 for (vector<string>::const_iterator i = icon_sets.begin (); i != icon_sets.end (); ++i) {
3974 add_option (_("Appearance/Theme"), io);
3977 add_option (_("Appearance/Colors"), new OptionEditorHeading (_("Colors")));
3978 add_option (_("Appearance/Colors"), new ColorThemeManager);
3979 add_option (_("Appearance/Colors"), new OptionEditorBlank ());
3983 OptionEditorHeading* quirks_head = new OptionEditorHeading (_("Various Workarounds for Windowing Systems"));
3985 quirks_head->set_note (string_compose (_("Rules for closing, minimizing, maximizing, and stay-on-top can vary \
3986 with each version of your OS, and the preferences that you've set in your OS.\n\n\
3987 You can adjust the options, below, to change how %1's windows and dialogs behave.\n\n\
3988 These settings will only take effect after %1 is restarted.\n\
3991 add_option (_("Appearance/Quirks"), quirks_head);
3993 bo = new BoolOption (
3994 "use-wm-visibility",
3995 _("Use visibility information provided by your Window Manager/Desktop"),
3996 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_wm_visibility),
3997 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_wm_visibility)
3999 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4000 _("If you have trouble toggling between hidden Editor and Mixer windows, try changing this setting."));
4001 add_option (_("Appearance/Quirks"), bo);
4004 bo = new BoolOption (
4005 "all-floating-windows-are-dialogs",
4006 _("All floating windows are dialogs"),
4007 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_all_floating_windows_are_dialogs),
4008 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_all_floating_windows_are_dialogs)
4010 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4011 _("Mark all floating windows to be type \"Dialog\" rather than using \"Utility\" for some.\nThis may help with some window managers."));
4012 add_option (_("Appearance/Quirks"), bo);
4014 bo = new BoolOption (
4015 "transients-follow-front",
4016 _("Transient windows follow front window."),
4017 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_transients_follow_front),
4018 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_transients_follow_front)
4020 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4021 _("Make transient windows follow the front window when toggling between the editor and mixer."));
4022 add_option (_("Appearance/Quirks"), bo);
4025 if (!Profile->get_mixbus()) {
4026 bo = new BoolOption (
4027 "floating-monitor-section",
4028 _("Float detached monitor-section window"),
4029 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_floating_monitor_section),
4030 sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_floating_monitor_section)
4032 Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
4033 _("When detaching the monitoring section, mark it as \"Utility\" window to stay in front."));
4034 add_option (_("Appearance/Quirks"), bo);
4037 add_option (_("Appearance/Quirks"), new OptionEditorBlank ());
4039 /* VIDEO Timeline */
4040 add_option (_("Video"), new OptionEditorHeading (_("Video Server")));
4041 add_option (_("Video"), new VideoTimelineOptions (_rc_config));
4043 Widget::show_all ();
4045 //trigger some parameter-changed messages which affect widget-visibility or -sensitivity
4046 parameter_changed ("send-ltc");
4047 parameter_changed ("sync-source");
4048 parameter_changed ("open-gui-after-adding-plugin");
4050 XMLNode* node = ARDOUR_UI::instance()->preferences_settings();
4052 /* gcc4 complains about ambiguity with Gtk::Widget::set_state
4053 (Gtk::StateType) here !!!
4055 Tabbable::set_state (*node, Stateful::loading_state_version);
4058 set_current_page (_("General"));
4062 RCOptionEditor::set_session (Session *s)
4064 SessionHandlePtr::set_session (s);
4065 _transport_masters_widget.set_session (s);
4069 RCOptionEditor::parameter_changed (string const & p)
4071 OptionEditor::parameter_changed (p);
4073 if (p == "use-monitor-bus") {
4074 bool const s = Config->get_use_monitor_bus ();
4076 /* we can't use this if we don't have a monitor bus */
4077 Config->set_solo_control_is_listen_control (false); // XXX
4079 _solo_control_is_listen_control->set_sensitive (s);
4080 _listen_position->set_sensitive (s);
4081 } else if (p == "sync-source") {
4082 boost::shared_ptr<TransportMaster> tm (TransportMasterManager::instance().current());
4083 if (boost::dynamic_pointer_cast<TimecodeTransportMaster> (tm)) {
4084 _sync_framerate->set_sensitive (true);
4086 _sync_framerate->set_sensitive (false);
4088 } else if (p == "send-ltc") {
4089 bool const s = Config->get_send_ltc ();
4090 _ltc_send_continuously->set_sensitive (s);
4091 _ltc_volume_slider->set_sensitive (s);
4092 } else if (p == "open-gui-after-adding-plugin" || p == "show-inline-display-by-default") {
4093 #if (defined LV2_SUPPORT && defined LV2_EXTENDED)
4094 _plugin_prefer_inline->set_sensitive (UIConfiguration::instance().get_open_gui_after_adding_plugin() && UIConfiguration::instance().get_show_inline_display_by_default());
4096 } else if (p == "conceal-lv1-if-lv2-exists") {
4097 plugin_scan_refresh ();
4101 void RCOptionEditor::plugin_scan_refresh () {
4102 /* first argument says discover new plugins, second means be verbose */
4103 PluginScanDialog psd (false, true);
4107 void RCOptionEditor::clear_vst_cache () {
4108 PluginManager::instance().clear_vst_cache();
4111 void RCOptionEditor::clear_vst_blacklist () {
4112 PluginManager::instance().clear_vst_blacklist();
4115 void RCOptionEditor::clear_au_cache () {
4116 PluginManager::instance().clear_au_cache();
4119 void RCOptionEditor::clear_au_blacklist () {
4120 PluginManager::instance().clear_au_blacklist();
4123 void RCOptionEditor::edit_lxvst_path () {
4124 Glib::RefPtr<Gdk::Window> win = get_parent_window ();
4125 PathsDialog *pd = new PathsDialog (
4126 *current_toplevel(), _("Set Linux VST Search Path"),
4127 _rc_config->get_plugin_path_lxvst(),
4128 PluginManager::instance().get_default_lxvst_path()
4130 ResponseType r = (ResponseType) pd->run ();
4132 if (r == RESPONSE_ACCEPT) {
4133 _rc_config->set_plugin_path_lxvst(pd->get_serialized_paths());
4135 MessageDialog msg (_("Re-scan Plugins now?"),
4136 false /*no markup*/, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true /*modal*/);
4137 msg.set_default_response (Gtk::RESPONSE_YES);
4138 if (msg.run() == Gtk::RESPONSE_YES) {
4140 plugin_scan_refresh ();
4146 void RCOptionEditor::edit_vst_path () {
4147 PathsDialog *pd = new PathsDialog (
4148 *current_toplevel(), _("Set Windows VST Search Path"),
4149 _rc_config->get_plugin_path_vst(),
4150 PluginManager::instance().get_default_windows_vst_path()
4152 ResponseType r = (ResponseType) pd->run ();
4154 if (r == RESPONSE_ACCEPT) {
4155 _rc_config->set_plugin_path_vst(pd->get_serialized_paths());
4156 MessageDialog msg (_("Re-scan Plugins now?"),
4157 false /*no markup*/, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO, true /*modal*/);
4158 msg.set_default_response (Gtk::RESPONSE_YES);
4159 if (msg.run() == Gtk::RESPONSE_YES) {
4161 plugin_scan_refresh ();
4168 RCOptionEditor::use_own_window (bool and_fill_it)
4170 bool new_window = !own_window ();
4172 Gtk::Window* win = Tabbable::use_own_window (and_fill_it);
4174 if (win && new_window) {
4175 win->set_name ("PreferencesWindow");
4176 ARDOUR_UI::instance()->setup_toplevel_window (*win, _("Preferences"), this);
4178 win->set_resizable (false);
4185 RCOptionEditor::get_state ()
4187 XMLNode* node = new XMLNode (X_("Preferences"));
4188 node->add_child_nocopy (Tabbable::get_state());