2256 lines
81 KiB
C++
2256 lines
81 KiB
C++
/*
|
|
* Copyright (C) 2009-2012 Carl Hetherington <carl@carlh.net>
|
|
* Copyright (C) 2009-2015 David Robillard <d@drobilla.net>
|
|
* Copyright (C) 2009-2019 Paul Davis <paul@linuxaudiosystems.com>
|
|
* Copyright (C) 2012-2019 Robin Gareus <robin@gareus.org>
|
|
* Copyright (C) 2013-2016 Nick Mainsbridge <mainsbridge@gmail.com>
|
|
* Copyright (C) 2013-2018 Colin Fletcher <colin.m.fletcher@googlemail.com>
|
|
* Copyright (C) 2013 John Emmas <john@creativepost.co.uk>
|
|
* Copyright (C) 2014-2016 Tim Mayberry <mojofunk@gmail.com>
|
|
* Copyright (C) 2014-2019 Ben Loftis <ben@harrisonconsoles.com>
|
|
* Copyright (C) 2018 Len Ovens <len@ovenwerks.net>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#ifdef WAF_BUILD
|
|
#include "gtk2ardour-config.h"
|
|
#endif
|
|
|
|
#include <cairo/cairo.h>
|
|
|
|
#include <boost/algorithm/string.hpp>
|
|
|
|
#include <gtkmm/liststore.h>
|
|
#include <gtkmm/stock.h>
|
|
#include <gtkmm/scale.h>
|
|
|
|
#include "gtkmm2ext/keyboard.h"
|
|
#include "gtkmm2ext/utils.h"
|
|
#include "gtkmm2ext/gtk_ui.h"
|
|
#include "gtkmm2ext/window_title.h"
|
|
|
|
#include "pbd/file_utils.h"
|
|
#include "pbd/fpu.h"
|
|
#include "pbd/cpus.h"
|
|
#include "pbd/unwind.h"
|
|
#include "pbd/i18n.h"
|
|
|
|
#include "ardour/audio_backend.h"
|
|
#include "ardour/audioengine.h"
|
|
#include "ardour/clip_library.h"
|
|
#include "ardour/control_protocol_manager.h"
|
|
#include "ardour/dB.h"
|
|
#include "ardour/parameter_descriptor.h"
|
|
#include "ardour/port_manager.h"
|
|
#include "ardour/plugin_manager.h"
|
|
#include "ardour/profile.h"
|
|
#include "ardour/rc_configuration.h"
|
|
#include "ardour/transport_master_manager.h"
|
|
|
|
#include "control_protocol/control_protocol.h"
|
|
|
|
#include "waveview/wave_view.h"
|
|
|
|
#include "widgets/paths_dialog.h"
|
|
#include "widgets/tooltips.h"
|
|
|
|
#include "actions.h"
|
|
#include "ardour_ui.h"
|
|
#include "ardour_dialog.h"
|
|
#include "ardour_ui.h"
|
|
#include "ardour_window.h"
|
|
#include "color_theme_manager.h"
|
|
#include "gui_thread.h"
|
|
#include "keyboard.h"
|
|
#include "meter_patterns.h"
|
|
#include "midi_tracer.h"
|
|
#include "plugin_scan_dialog.h"
|
|
#include "livetrax_rc_option_editor.h"
|
|
#include "sfdb_ui.h"
|
|
#include "transport_masters_dialog.h"
|
|
#include "ui_config.h"
|
|
#include "utils.h"
|
|
|
|
using namespace std;
|
|
using namespace Gtk;
|
|
using namespace Gtkmm2ext;
|
|
using namespace PBD;
|
|
using namespace ARDOUR;
|
|
using namespace ARDOUR_UI_UTILS;
|
|
using namespace ArdourWidgets;
|
|
|
|
class UndoOptions : public OptionEditorComponent
|
|
{
|
|
public:
|
|
UndoOptions (RCConfiguration* c) :
|
|
_rc_config (c),
|
|
_limit_undo_button (_("Limit undo history to")),
|
|
_save_undo_button (_("Save undo history of"))
|
|
{
|
|
// TODO get rid of GTK -> use OptionEditor SpinOption
|
|
_limit_undo_spin.set_range (0, 512);
|
|
_limit_undo_spin.set_increments (1, 10);
|
|
|
|
_save_undo_spin.set_range (0, 512);
|
|
_save_undo_spin.set_increments (1, 10);
|
|
|
|
_limit_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_toggled));
|
|
_limit_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::limit_undo_changed));
|
|
_save_undo_button.signal_toggled().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_toggled));
|
|
_save_undo_spin.signal_value_changed().connect (sigc::mem_fun (*this, &UndoOptions::save_undo_changed));
|
|
}
|
|
|
|
void parameter_changed (string const & p)
|
|
{
|
|
if (p == "history-depth") {
|
|
int32_t const d = _rc_config->get_history_depth();
|
|
_limit_undo_button.set_active (d != 0);
|
|
_limit_undo_spin.set_sensitive (d != 0);
|
|
_limit_undo_spin.set_value (d);
|
|
} else if (p == "save-history") {
|
|
bool const x = _rc_config->get_save_history ();
|
|
_save_undo_button.set_active (x);
|
|
_save_undo_spin.set_sensitive (x);
|
|
} else if (p == "save-history-depth") {
|
|
_save_undo_spin.set_value (_rc_config->get_saved_history_depth());
|
|
}
|
|
}
|
|
|
|
void set_state_from_config ()
|
|
{
|
|
parameter_changed ("save-history");
|
|
parameter_changed ("history-depth");
|
|
parameter_changed ("save-history-depth");
|
|
}
|
|
|
|
void limit_undo_toggled ()
|
|
{
|
|
bool const x = _limit_undo_button.get_active ();
|
|
_limit_undo_spin.set_sensitive (x);
|
|
int32_t const n = x ? 16 : 0;
|
|
_limit_undo_spin.set_value (n);
|
|
_rc_config->set_history_depth (n);
|
|
}
|
|
|
|
void limit_undo_changed ()
|
|
{
|
|
_rc_config->set_history_depth (_limit_undo_spin.get_value_as_int ());
|
|
}
|
|
|
|
void save_undo_toggled ()
|
|
{
|
|
bool const x = _save_undo_button.get_active ();
|
|
_rc_config->set_save_history (x);
|
|
}
|
|
|
|
void save_undo_changed ()
|
|
{
|
|
_rc_config->set_saved_history_depth (_save_undo_spin.get_value_as_int ());
|
|
}
|
|
|
|
void add_to_page (OptionEditorPage* p)
|
|
{
|
|
int const n = p->table.property_n_rows();
|
|
Table* t = & p->table;
|
|
|
|
t->resize (n + 2, 3);
|
|
|
|
Label* l = manage (left_aligned_label (_("commands")));
|
|
HBox* box = manage (new HBox());
|
|
box->set_spacing (4);
|
|
box->pack_start (_limit_undo_spin, false, false);
|
|
box->pack_start (*l, true, true);
|
|
t->attach (_limit_undo_button, 1, 2, n, n +1, FILL);
|
|
t->attach (*box, 2, 3, n, n + 1, FILL | EXPAND);
|
|
|
|
l = manage (left_aligned_label (_("commands")));
|
|
box = manage (new HBox());
|
|
box->set_spacing (4);
|
|
box->pack_start (_save_undo_spin, false, false);
|
|
box->pack_start (*l, true, true);
|
|
t->attach (_save_undo_button, 1, 2, n + 1, n + 2, FILL);
|
|
t->attach (*box, 2, 3, n + 1, n + 2, FILL | EXPAND);
|
|
}
|
|
|
|
Gtk::Widget& tip_widget() {
|
|
return _limit_undo_button; // unused
|
|
}
|
|
|
|
private:
|
|
RCConfiguration* _rc_config;
|
|
CheckButton _limit_undo_button;
|
|
SpinButton _limit_undo_spin;
|
|
CheckButton _save_undo_button;
|
|
SpinButton _save_undo_spin;
|
|
};
|
|
|
|
|
|
static const struct {
|
|
const char *name;
|
|
guint modifier;
|
|
} modifiers[] = {
|
|
|
|
{ "Unmodified", 0 },
|
|
|
|
#ifdef __APPLE__
|
|
|
|
/* Command = Meta
|
|
Option/Alt = Mod1
|
|
*/
|
|
{ "Key|Shift", GDK_SHIFT_MASK },
|
|
{ "Command", GDK_MOD2_MASK },
|
|
{ "Control", GDK_CONTROL_MASK },
|
|
{ "Option", GDK_MOD1_MASK },
|
|
{ "Command-Shift", GDK_MOD2_MASK|GDK_SHIFT_MASK },
|
|
{ "Command-Option", GDK_MOD2_MASK|GDK_MOD1_MASK },
|
|
{ "Command-Control", GDK_MOD2_MASK|GDK_CONTROL_MASK },
|
|
{ "Command-Option-Control", GDK_MOD2_MASK|GDK_MOD1_MASK|GDK_CONTROL_MASK },
|
|
{ "Option-Control", GDK_MOD1_MASK|GDK_CONTROL_MASK },
|
|
{ "Option-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
|
|
{ "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
|
|
{ "Shift-Command-Option", GDK_MOD5_MASK|GDK_SHIFT_MASK|GDK_MOD2_MASK },
|
|
|
|
#else
|
|
{ "Key|Shift", GDK_SHIFT_MASK },
|
|
{ "Control", GDK_CONTROL_MASK },
|
|
{ "Alt", GDK_MOD1_MASK },
|
|
{ "Control-Shift", GDK_CONTROL_MASK|GDK_SHIFT_MASK },
|
|
{ "Control-Alt", GDK_CONTROL_MASK|GDK_MOD1_MASK },
|
|
{ "Control-Windows", GDK_CONTROL_MASK|GDK_MOD4_MASK },
|
|
{ "Control-Shift-Alt", GDK_CONTROL_MASK|GDK_SHIFT_MASK|GDK_MOD1_MASK },
|
|
{ "Alt-Windows", GDK_MOD1_MASK|GDK_MOD4_MASK },
|
|
{ "Alt-Shift", GDK_MOD1_MASK|GDK_SHIFT_MASK },
|
|
{ "Alt-Shift-Windows", GDK_MOD1_MASK|GDK_SHIFT_MASK|GDK_MOD4_MASK },
|
|
{ "Mod2", GDK_MOD2_MASK },
|
|
{ "Mod3", GDK_MOD3_MASK },
|
|
{ "Windows", GDK_MOD4_MASK },
|
|
{ "Mod5", GDK_MOD5_MASK },
|
|
#endif
|
|
{ 0, 0 }
|
|
};
|
|
|
|
class FontScalingOptions : public HSliderOption
|
|
{
|
|
public:
|
|
FontScalingOptions ()
|
|
: HSliderOption ("font-scale", _("GUI and Font scaling"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_font_scale),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_font_scale),
|
|
50, 250, 1, 5,
|
|
1024, false)
|
|
{
|
|
const std::string dflt = _("100%");
|
|
const std::string dbl = _("200%");
|
|
const std::string empty = X_(""); // despite gtk-doc saying so, NULL does not work as reference
|
|
|
|
_hscale.set_name("FontScaleSlider");
|
|
_hscale.set_draw_value(false);
|
|
_hscale.add_mark(50, Gtk::POS_TOP, empty);
|
|
_hscale.add_mark(60, Gtk::POS_TOP, empty);
|
|
_hscale.add_mark(70, Gtk::POS_TOP, empty);
|
|
_hscale.add_mark(80, Gtk::POS_TOP, empty);
|
|
_hscale.add_mark(90, Gtk::POS_TOP, empty);
|
|
_hscale.add_mark(100, Gtk::POS_TOP, dflt);
|
|
_hscale.add_mark(125, Gtk::POS_TOP, empty);
|
|
_hscale.add_mark(150, Gtk::POS_TOP, empty);
|
|
_hscale.add_mark(175, Gtk::POS_TOP, empty);
|
|
_hscale.add_mark(200, Gtk::POS_TOP, dbl);
|
|
_hscale.add_mark(250, Gtk::POS_TOP, empty);
|
|
|
|
set_note (_("Adjusting the scale requires an application restart for fully accurate re-layout."));
|
|
}
|
|
|
|
void changed ()
|
|
{
|
|
HSliderOption::changed ();
|
|
/* XXX: should be triggered from the parameter changed signal */
|
|
UIConfiguration::instance().reset_dpi ();
|
|
}
|
|
};
|
|
|
|
class ClipLevelOptions : public HSliderOption
|
|
{
|
|
public:
|
|
ClipLevelOptions ()
|
|
: HSliderOption (X_("waveform-clip-level"),
|
|
_("Waveform Clip Level (dBFS)"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_clip_level),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_clip_level),
|
|
-50.0, -0.5, 0.1, 1.0, /* units of dB */
|
|
1.0,
|
|
false)
|
|
{
|
|
}
|
|
|
|
void parameter_changed (string const & p)
|
|
{
|
|
if (p == "waveform-clip-level") {
|
|
ArdourWaveView::WaveView::set_clip_level (UIConfiguration::instance().get_waveform_clip_level());
|
|
}
|
|
if (p == "show-waveform-clipping") {
|
|
_hscale.set_sensitive (UIConfiguration::instance().get_show_waveform_clipping ());
|
|
}
|
|
}
|
|
|
|
void set_state_from_config ()
|
|
{
|
|
parameter_changed ("waveform-clip-level");
|
|
parameter_changed ("show-waveform-clipping");
|
|
}
|
|
};
|
|
|
|
class BufferingOptions : public OptionEditorComponent
|
|
{
|
|
public:
|
|
BufferingOptions (RCConfiguration* c)
|
|
: _rc_config (c)
|
|
, _label (_("Preset:"))
|
|
, _playback ("playback-buffer-seconds", _("Playback (seconds of buffering)"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_audio_playback_buffer_seconds),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_audio_playback_buffer_seconds),
|
|
1, 60, 1, 4)
|
|
, _capture ("capture-buffer-seconds", _("Recording (seconds of buffering)"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_audio_capture_buffer_seconds),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_audio_capture_buffer_seconds),
|
|
1, 60, 1, 4)
|
|
{
|
|
// TODO use ComboOption
|
|
vector<string> presets;
|
|
|
|
/* these must match the order of the enums for BufferingPreset */
|
|
presets.push_back (_("Small sessions (4-16 tracks)"));
|
|
presets.push_back (_("Medium sessions (16-64 tracks)"));
|
|
presets.push_back (_("Large sessions (64+ tracks)"));
|
|
presets.push_back (_("Custom (set by sliders below)"));
|
|
|
|
set_popdown_strings (_buffering_presets_combo, presets);
|
|
_buffering_presets_combo.signal_changed().connect (sigc::mem_fun (*this, &BufferingOptions::preset_changed));
|
|
|
|
_label.set_name ("OptionsLabel");
|
|
_label.set_alignment (0, 0.5);
|
|
}
|
|
|
|
void
|
|
add_to_page (OptionEditorPage* p)
|
|
{
|
|
add_widgets_to_page (p, &_label, &_buffering_presets_combo);
|
|
_playback.add_to_page (p);
|
|
_capture.add_to_page (p);
|
|
}
|
|
|
|
void parameter_changed (string const & p)
|
|
{
|
|
if (p == "buffering-preset") {
|
|
switch (_rc_config->get_buffering_preset()) {
|
|
case Small:
|
|
_playback.set_sensitive (false);
|
|
_capture.set_sensitive (false);
|
|
_buffering_presets_combo.set_active (0);
|
|
break;
|
|
case Medium:
|
|
_playback.set_sensitive (false);
|
|
_capture.set_sensitive (false);
|
|
_buffering_presets_combo.set_active (1);
|
|
break;
|
|
case Large:
|
|
_playback.set_sensitive (false);
|
|
_capture.set_sensitive (false);
|
|
_buffering_presets_combo.set_active (2);
|
|
break;
|
|
case Custom:
|
|
_playback.set_sensitive (true);
|
|
_capture.set_sensitive (true);
|
|
_buffering_presets_combo.set_active (3);
|
|
break;
|
|
}
|
|
}
|
|
_playback.parameter_changed (p);
|
|
_capture.parameter_changed (p);
|
|
}
|
|
|
|
void set_state_from_config ()
|
|
{
|
|
parameter_changed ("buffering-preset");
|
|
_playback.set_state_from_config();
|
|
_capture.set_state_from_config();
|
|
}
|
|
|
|
Gtk::Widget& tip_widget() { return _buffering_presets_combo; }
|
|
|
|
private:
|
|
|
|
void preset_changed ()
|
|
{
|
|
int index = _buffering_presets_combo.get_active_row_number ();
|
|
if (index < 0) {
|
|
return;
|
|
}
|
|
switch (index) {
|
|
case 0:
|
|
_rc_config->set_buffering_preset (Small);
|
|
break;
|
|
case 1:
|
|
_rc_config->set_buffering_preset (Medium);
|
|
break;
|
|
case 2:
|
|
_rc_config->set_buffering_preset (Large);
|
|
break;
|
|
case 3:
|
|
_rc_config->set_buffering_preset (Custom);
|
|
break;
|
|
default:
|
|
error << string_compose (_("programming error: unknown buffering preset string, index = %1"), index) << endmsg;
|
|
break;
|
|
}
|
|
}
|
|
|
|
RCConfiguration* _rc_config;
|
|
Label _label;
|
|
HSliderOption _playback;
|
|
HSliderOption _capture;
|
|
ComboBoxText _buffering_presets_combo;
|
|
};
|
|
|
|
class PortSelectOption : public OptionEditorComponent, public sigc::trackable {
|
|
public:
|
|
PortSelectOption (RCConfiguration* c, SessionHandlePtr* shp, std::string const & tooltip, std::string const & parameter_name, std::string const & label, DataType dt, PortFlags pf)
|
|
: _rc_config (c)
|
|
, _shp (shp)
|
|
, _label (label)
|
|
, _ignore_change (false)
|
|
, data_type (dt)
|
|
, port_flags (pf)
|
|
{
|
|
_store = ListStore::create (_port_columns);
|
|
_combo.set_model (_store);
|
|
_combo.pack_start (_port_columns.short_name);
|
|
|
|
set_tooltip (_combo, tooltip);
|
|
|
|
_combo.signal_map ().connect (sigc::mem_fun (*this, &PortSelectOption::on_map));
|
|
_combo.signal_unmap ().connect (sigc::mem_fun (*this, &PortSelectOption::on_unmap));
|
|
_combo.signal_changed ().connect (sigc::mem_fun (*this, &PortSelectOption::port_changed));
|
|
}
|
|
|
|
void add_to_page (OptionEditorPage* p)
|
|
{
|
|
add_widgets_to_page (p, &_label, &_combo);
|
|
}
|
|
|
|
Gtk::Widget& tip_widget()
|
|
{
|
|
return _combo;
|
|
}
|
|
|
|
void parameter_changed (string const & p)
|
|
{
|
|
if (p == parameter_name) {
|
|
update_selection ();
|
|
}
|
|
}
|
|
|
|
void set_state_from_config ()
|
|
{
|
|
parameter_changed (parameter_name);
|
|
}
|
|
|
|
protected:
|
|
struct PortColumns : public Gtk::TreeModel::ColumnRecord {
|
|
PortColumns() {
|
|
add (short_name);
|
|
add (full_name);
|
|
}
|
|
Gtk::TreeModelColumn<std::string> short_name;
|
|
Gtk::TreeModelColumn<std::string> full_name;
|
|
};
|
|
|
|
RCConfiguration* _rc_config;
|
|
SessionHandlePtr* _shp;
|
|
Label _label;
|
|
Gtk::ComboBox _combo;
|
|
bool _ignore_change;
|
|
std::string parameter_name;
|
|
ARDOUR::DataType data_type;
|
|
ARDOUR::PortFlags port_flags;
|
|
PortColumns _port_columns;
|
|
|
|
Glib::RefPtr<Gtk::ListStore> _store;
|
|
PBD::ScopedConnectionList _engine_connection;
|
|
|
|
void on_map ()
|
|
{
|
|
AudioEngine::instance()->PortRegisteredOrUnregistered.connect (
|
|
_engine_connection,
|
|
invalidator (*this),
|
|
std::bind (&PortSelectOption::update_port_combo, this),
|
|
gui_context());
|
|
|
|
AudioEngine::instance()->PortPrettyNameChanged.connect (
|
|
_engine_connection,
|
|
invalidator (*this),
|
|
std::bind (&PortSelectOption::update_port_combo, this),
|
|
gui_context());
|
|
}
|
|
|
|
void on_unmap ()
|
|
{
|
|
_engine_connection.drop_connections ();
|
|
}
|
|
|
|
|
|
void update_port_combo ()
|
|
{
|
|
vector<string> ports;
|
|
ARDOUR::AudioEngine::instance()->get_ports ("", data_type, port_flags, ports);
|
|
|
|
PBD::Unwinder<bool> uw (_ignore_change, true);
|
|
_store->clear ();
|
|
|
|
TreeModel::Row row;
|
|
row = *_store->append ();
|
|
row[_port_columns.full_name] = string();
|
|
row[_port_columns.short_name] = _("Disconnected");
|
|
|
|
for (vector<string>::const_iterator p = ports.begin(); p != ports.end(); ++p) {
|
|
row = *_store->append ();
|
|
row[_port_columns.full_name] = *p;
|
|
std::string pn = ARDOUR::AudioEngine::instance()->get_pretty_name_by_name (*p);
|
|
if (pn.empty ()) {
|
|
pn = (*p).substr ((*p).find (':') + 1);
|
|
}
|
|
row[_port_columns.short_name] = pn;
|
|
}
|
|
|
|
update_selection ();
|
|
}
|
|
|
|
virtual void update_selection() = 0;
|
|
virtual void port_changed () = 0;
|
|
};
|
|
|
|
class LTCPortSelectOption : public PortSelectOption
|
|
{
|
|
public:
|
|
LTCPortSelectOption (RCConfiguration* c, SessionHandlePtr* shp)
|
|
: PortSelectOption (c, shp,
|
|
_("The LTC generator output will be auto-connected to this port when a session is loaded."),
|
|
X_("ltc-output-port"),
|
|
_("LTC Output Port:"),
|
|
ARDOUR::DataType::AUDIO,
|
|
ARDOUR::PortFlags (ARDOUR::IsInput|ARDOUR::IsTerminal)) {
|
|
/* cannot call from parent due to the method being pure virtual */
|
|
update_port_combo ();
|
|
}
|
|
|
|
void port_changed ()
|
|
{
|
|
if (_ignore_change) {
|
|
return;
|
|
}
|
|
TreeModel::iterator active = _combo.get_active ();
|
|
string new_port = (*active)[_port_columns.full_name];
|
|
_rc_config->set_ltc_output_port (new_port);
|
|
|
|
if (!_shp->session()) {
|
|
return;
|
|
}
|
|
std::shared_ptr<Port> ltc_port = _shp->session()->ltc_output_port ();
|
|
if (!ltc_port) {
|
|
return;
|
|
}
|
|
if (ltc_port->connected_to (new_port)) {
|
|
return;
|
|
}
|
|
|
|
ltc_port->disconnect_all ();
|
|
if (!new_port.empty()) {
|
|
ltc_port->connect (new_port);
|
|
}
|
|
}
|
|
|
|
void update_selection ()
|
|
{
|
|
int n;
|
|
Gtk::TreeModel::Children children = _store->children();
|
|
Gtk::TreeModel::Children::iterator i = children.begin();
|
|
++i; /* skip "Disconnected" */
|
|
|
|
std::string const& pn = _rc_config->get_ltc_output_port ();
|
|
std::shared_ptr<Port> ltc_port;
|
|
if (_shp->session()) {
|
|
ltc_port = _shp->session()->ltc_output_port ();
|
|
}
|
|
|
|
PBD::Unwinder<bool> uw (_ignore_change, true);
|
|
|
|
/* try match preference with available port-names */
|
|
for (n = 1; i != children.end(); ++i, ++n) {
|
|
string port_name = (*i)[_port_columns.full_name];
|
|
if (port_name == pn) {
|
|
_combo.set_active (n);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Set preference to current port connection
|
|
* (LTC is auto-connected at session load).
|
|
*/
|
|
if (ltc_port) {
|
|
i = children.begin();
|
|
++i; /* skip "Disconnected" */
|
|
for (n = 1; i != children.end(); ++i, ++n) {
|
|
string port_name = (*i)[_port_columns.full_name];
|
|
if (ltc_port->connected_to (port_name)) {
|
|
_combo.set_active (n);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pn.empty ()) {
|
|
_combo.set_active (0); /* disconnected */
|
|
} else {
|
|
/* The port is currently not available, retain preference */
|
|
TreeModel::Row row = *_store->append ();
|
|
row[_port_columns.full_name] = pn;
|
|
row[_port_columns.short_name] = (pn).substr ((pn).find (':') + 1);
|
|
_combo.set_active (n);
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
class ControlSurfacesOptions : public OptionEditorMiniPage
|
|
{
|
|
public:
|
|
ControlSurfacesOptions ()
|
|
: _ignore_view_change (0)
|
|
{
|
|
_store = ListStore::create (_model);
|
|
_view.set_model (_store);
|
|
_view.append_column_editable (_("Enable"), _model.enabled);
|
|
_view.append_column (_("Control Surface Protocol"), _model.name);
|
|
_view.get_column(1)->set_resizable (true);
|
|
_view.get_column(1)->set_expand (true);
|
|
|
|
Gtk::HBox* edit_box = manage (new Gtk::HBox);
|
|
edit_box->set_spacing(3);
|
|
edit_box->show ();
|
|
|
|
Label* label = manage (new Label);
|
|
label->set_text (_("Edit the settings for selected protocol (it must be ENABLED first):"));
|
|
edit_box->pack_start (*label, false, false);
|
|
label->show ();
|
|
|
|
edit_button = manage (new Button(_("Show Protocol Settings")));
|
|
edit_button->signal_clicked().connect (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_btn_clicked));
|
|
edit_box->pack_start (*edit_button, true, true);
|
|
edit_button->set_sensitive (false);
|
|
edit_button->show ();
|
|
|
|
int const n = table.property_n_rows();
|
|
table.resize (n + 2, 3);
|
|
table.attach (_view, 0, 3, n, n + 1);
|
|
table.attach (*edit_box, 0, 3, n + 1, n + 2);
|
|
|
|
ControlProtocolManager& m = ControlProtocolManager::instance ();
|
|
m.ProtocolStatusChange.connect (protocol_status_connection, MISSING_INVALIDATOR,
|
|
std::bind (&ControlSurfacesOptions::protocol_status_changed, this, _1), gui_context());
|
|
|
|
_store->signal_row_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::view_changed));
|
|
_view.signal_button_press_event().connect_notify (sigc::mem_fun(*this, &ControlSurfacesOptions::edit_clicked));
|
|
_view.get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ControlSurfacesOptions::selection_changed));
|
|
}
|
|
|
|
void parameter_changed (std::string const &)
|
|
{
|
|
|
|
}
|
|
|
|
void set_state_from_config ()
|
|
{
|
|
_store->clear ();
|
|
|
|
ControlProtocolManager& m = ControlProtocolManager::instance ();
|
|
for (auto const& i : m.control_protocol_info) {
|
|
TreeModel::Row r = *_store->append ();
|
|
r[_model.name] = i->name;
|
|
r[_model.enabled] = 0 != i->protocol;
|
|
r[_model.protocol_info] = i;
|
|
}
|
|
}
|
|
|
|
private:
|
|
|
|
void protocol_status_changed (ControlProtocolInfo* cpi) {
|
|
/* find the row */
|
|
TreeModel::Children rows = _store->children();
|
|
|
|
for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
|
|
string n = ((*x)[_model.name]);
|
|
|
|
if ((*x)[_model.protocol_info] == cpi) {
|
|
_ignore_view_change++;
|
|
(*x)[_model.enabled] = 0 != cpi->protocol;
|
|
_ignore_view_change--;
|
|
selection_changed (); // update sensitivity
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void selection_changed ()
|
|
{
|
|
//enable the Edit button when a row is selected for editing
|
|
TreeModel::Row row = *(_view.get_selection()->get_selected());
|
|
if (row && row[_model.enabled]) {
|
|
ControlProtocolInfo* cpi = row[_model.protocol_info];
|
|
edit_button->set_sensitive (cpi && cpi->protocol && cpi->protocol->has_editor ());
|
|
} else {
|
|
edit_button->set_sensitive (false);
|
|
}
|
|
}
|
|
|
|
void view_changed (TreeModel::Path const &, TreeModel::iterator const & i)
|
|
{
|
|
TreeModel::Row r = *i;
|
|
|
|
if (_ignore_view_change) {
|
|
return;
|
|
}
|
|
|
|
ControlProtocolInfo* cpi = r[_model.protocol_info];
|
|
if (!cpi) {
|
|
return;
|
|
}
|
|
|
|
bool const was_enabled = (cpi->protocol != 0);
|
|
bool const is_enabled = r[_model.enabled];
|
|
|
|
|
|
if (was_enabled != is_enabled) {
|
|
|
|
if (!was_enabled) {
|
|
ControlProtocolManager::instance().activate (*cpi);
|
|
} else {
|
|
ControlProtocolManager::instance().deactivate (*cpi);
|
|
}
|
|
}
|
|
|
|
selection_changed ();
|
|
}
|
|
|
|
void edit_btn_clicked ()
|
|
{
|
|
std::string name;
|
|
ControlProtocolInfo* cpi;
|
|
TreeModel::Row row;
|
|
|
|
row = *(_view.get_selection()->get_selected());
|
|
if (!row[_model.enabled]) {
|
|
return;
|
|
}
|
|
cpi = row[_model.protocol_info];
|
|
if (!cpi || !cpi->protocol || !cpi->protocol->has_editor ()) {
|
|
return;
|
|
}
|
|
Box* box = (Box*) cpi->protocol->get_gui ();
|
|
if (!box) {
|
|
return;
|
|
}
|
|
if (box->get_parent()) {
|
|
static_cast<ArdourWindow*>(box->get_parent())->present();
|
|
return;
|
|
}
|
|
WindowTitle title (Glib::get_application_name());
|
|
title += row[_model.name];
|
|
title += _("Configuration");
|
|
/* once created, the window is managed by the surface itself (as ->get_parent())
|
|
* Surface's tear_down_gui() is called on session close, when de-activating
|
|
* or re-initializing a surface.
|
|
* tear_down_gui() hides an deletes the Window if it exists.
|
|
*/
|
|
ArdourWindow* win = new ArdourWindow (*((Gtk::Window*) _view.get_toplevel()), title.get_string());
|
|
win->set_title (_("Control Protocol Settings"));
|
|
win->add (*box);
|
|
box->show ();
|
|
win->present ();
|
|
}
|
|
|
|
void edit_clicked (GdkEventButton* ev)
|
|
{
|
|
if (ev->type != GDK_2BUTTON_PRESS) {
|
|
return;
|
|
}
|
|
|
|
edit_btn_clicked();
|
|
}
|
|
|
|
class ControlSurfacesModelColumns : public TreeModelColumnRecord
|
|
{
|
|
public:
|
|
|
|
ControlSurfacesModelColumns ()
|
|
{
|
|
add (name);
|
|
add (enabled);
|
|
add (protocol_info);
|
|
}
|
|
|
|
TreeModelColumn<string> name;
|
|
TreeModelColumn<bool> enabled;
|
|
TreeModelColumn<ControlProtocolInfo*> protocol_info;
|
|
};
|
|
|
|
Glib::RefPtr<ListStore> _store;
|
|
ControlSurfacesModelColumns _model;
|
|
TreeView _view;
|
|
PBD::ScopedConnection protocol_status_connection;
|
|
uint32_t _ignore_view_change;
|
|
Gtk::Button* edit_button;
|
|
};
|
|
|
|
class ColumVisibilityOption : public Option
|
|
{
|
|
public:
|
|
ColumVisibilityOption (string id, string name, uint32_t n_col, sigc::slot<uint32_t> get, sigc::slot<bool, uint32_t> set)
|
|
: Option (id, name)
|
|
, _heading (name)
|
|
, _n_col (n_col)
|
|
, _get (get)
|
|
, _set (set)
|
|
{
|
|
cb = (CheckButton**) malloc (sizeof (CheckButton*) * n_col);
|
|
for (uint32_t i = 0; i < n_col; ++i) {
|
|
CheckButton* col = manage (new CheckButton (string_compose (_("Column %1 (Actions %2 + %3)"), i + 1, i * 2 + 1, i * 2 + 2)));
|
|
col->signal_toggled().connect (sigc::bind (sigc::mem_fun (*this, &ColumVisibilityOption::column_toggled), i));
|
|
_vbox.pack_start (*col);
|
|
cb[i] = col;
|
|
}
|
|
parameter_changed (id);
|
|
}
|
|
|
|
~ColumVisibilityOption () {
|
|
free (cb);
|
|
}
|
|
|
|
Gtk::Widget& tip_widget() { return _vbox; }
|
|
|
|
void set_state_from_config ()
|
|
{
|
|
uint32_t c = _get();
|
|
for (uint32_t i = 0; i < _n_col; ++i) {
|
|
bool en = (c & (1<<i)) ? true : false;
|
|
if (cb[i]->get_active () != en) {
|
|
cb[i]->set_active (en);
|
|
}
|
|
}
|
|
}
|
|
|
|
void add_to_page (OptionEditorPage* p)
|
|
{
|
|
_heading.add_to_page (p);
|
|
add_widget_to_page (p, &_vbox);
|
|
}
|
|
private:
|
|
|
|
void column_toggled (int b) {
|
|
uint32_t c = _get();
|
|
uint32_t cc = c;
|
|
if (cb[b]->get_active ()) {
|
|
c |= (1<<b);
|
|
} else {
|
|
c &= ~(1<<b);
|
|
}
|
|
if (cc != c) {
|
|
_set (c);
|
|
}
|
|
}
|
|
|
|
VBox _vbox;
|
|
OptionEditorHeading _heading;
|
|
|
|
CheckButton** cb;
|
|
uint32_t _n_col;
|
|
sigc::slot<uint32_t> _get;
|
|
sigc::slot<bool, uint32_t> _set;
|
|
};
|
|
|
|
RCOptionEditor::RCOptionEditor ()
|
|
: OptionEditorWindow (Config, _("Preferences"))
|
|
, _rc_config (Config)
|
|
, _mixer_strip_visibility ("mixer-element-visibility")
|
|
, _cairo_image_surface (0)
|
|
, audiomidi_tab_button (_("Audio\nSystem\nSettings"))
|
|
, midi_tab_button (_("MIDI\nSystem\nSettings"))
|
|
, session_tab_button (_("Session\nSettings"))
|
|
, preferences_tab_button (_("Preferences"))
|
|
, sync_tab_button (_("Sync"))
|
|
{
|
|
UIConfiguration::instance().ParameterChanged.connect (sigc::mem_fun (*this, &RCOptionEditor::parameter_changed));
|
|
BoolOption* bo;
|
|
|
|
button_box().pack_start (audiomidi_tab_button, true, true);
|
|
button_box().pack_start (midi_tab_button, true, true);
|
|
button_box().pack_start (session_tab_button, true, true);
|
|
button_box().pack_start (preferences_tab_button, true, true);
|
|
button_box().pack_start (sync_tab_button, true, true);
|
|
button_box().set_homogeneous (true);
|
|
button_box().show_all ();
|
|
|
|
/* These bindings all use the page title, which is the full first (string argument) to ::add_option() */
|
|
audiomidi_tab_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &OptionEditor::set_current_page), _("General")));
|
|
midi_tab_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &OptionEditor::set_current_page), _("MIDI")));
|
|
preferences_tab_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &OptionEditor::set_current_page), _("General")));
|
|
sync_tab_button.signal_clicked().connect (sigc::bind (sigc::mem_fun (*this, &OptionEditor::set_current_page), _("Transport")));
|
|
|
|
/* GENERAL *****************************************************************/
|
|
|
|
add_option (_("General"), new OptionEditorHeading (_("Audio/MIDI Setup")));
|
|
|
|
add_option (_("General"),
|
|
new RcActionButton (_("Show Audio/MIDI Setup Window"),
|
|
sigc::mem_fun (*this, &RCOptionEditor::show_audio_setup)));
|
|
|
|
bo = new BoolOption (
|
|
"try-autostart-engine",
|
|
_("Try to auto-launch audio/midi engine"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_try_autostart_engine),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_try_autostart_engine)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
|
|
_("When opening an existing session, if the most recent audio engine is available and can open the session's sample rate, the audio engine dialog may be skipped."));
|
|
add_option (_("General"), bo );
|
|
|
|
#if 0
|
|
/* "preferred-time-domain"
|
|
unlike other preferences, this variable would not actually 'change' anything; the session's domain is stored in session-config
|
|
so we don't show the rc-config value here. instead, it is invisibly stored in the rc-config, with the user's most recent selection */
|
|
#endif
|
|
|
|
add_option (_("General"), new OptionEditorHeading (S_("Options|Editor Undo")));
|
|
|
|
add_option (_("General"), new UndoOptions (_rc_config));
|
|
|
|
add_option (_("General"),
|
|
new BoolOption (
|
|
"verify-remove-last-capture",
|
|
_("Verify removal of last capture"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_verify_remove_last_capture),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_verify_remove_last_capture)
|
|
));
|
|
|
|
add_option (_("General"), new OptionEditorHeading (_("Session Management")));
|
|
|
|
add_option (_("General"),
|
|
new BoolOption (
|
|
"periodic-safety-backups",
|
|
_("Make periodic backups of the session file"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_periodic_safety_backups),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_periodic_safety_backups)
|
|
));
|
|
|
|
add_option (_("General"), new DirectoryOption (
|
|
X_("default-session-parent-dir"),
|
|
_("Default folder for new sessions:"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_default_session_parent_dir),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_default_session_parent_dir)
|
|
));
|
|
|
|
add_option (_("General"),
|
|
new SpinOption<uint32_t> (
|
|
"max-recent-sessions",
|
|
_("Maximum number of recent sessions"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_max_recent_sessions),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_max_recent_sessions),
|
|
0, 1000, 1, 20
|
|
));
|
|
|
|
add_option (_("General"), new OptionEditorHeading (_("Import")));
|
|
|
|
add_option (_("General"),
|
|
new BoolOption (
|
|
"only-copy-imported-files",
|
|
_("Drag and drop import always copies files to session"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_only_copy_imported_files),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_only_copy_imported_files)
|
|
));
|
|
|
|
|
|
add_option (_("General"),
|
|
new DirectoryOption (
|
|
X_("freesound-dir"),
|
|
_("Cache Folder for downloaded Freesound clips:"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_freesound_dir),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_freesound_dir)
|
|
));
|
|
|
|
add_option (_("General"), new OptionEditorHeading (_("Export")));
|
|
|
|
add_option (_("General"),
|
|
new BoolOption (
|
|
"save-export-analysis-image",
|
|
_("Save loudness analysis as image file after export"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_save_export_analysis_image),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_save_export_analysis_image)
|
|
));
|
|
|
|
#if defined PHONE_HOME && !defined MIXBUS
|
|
add_option (_("General"), new OptionEditorHeading (_("New Version Check")));
|
|
bo = new BoolOption (
|
|
"check-announcements",
|
|
_("Check for announcements at application start"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_check_announcements),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_check_announcements)
|
|
);
|
|
bo ->set_note (string_compose (_("An anonymous request is performed to query announcements by contacting\n%1"), Config->get_pingback_url ()));
|
|
add_option (_("General"), bo);
|
|
|
|
#endif
|
|
|
|
/* APPEARANCE ***************************************************************/
|
|
|
|
if (!ARDOUR::Profile->get_mixbus()) {
|
|
add_option (_("Appearance"), new OptionEditorHeading (_("GUI Lock")));
|
|
/* Lock GUI timeout */
|
|
|
|
HSliderOption *slts = new HSliderOption("lock-gui-after-seconds",
|
|
_("Lock timeout (seconds)"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_lock_gui_after_seconds),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_lock_gui_after_seconds),
|
|
0, 1000, 1, 10
|
|
);
|
|
slts->scale().set_digits (0);
|
|
Gtkmm2ext::UI::instance()->set_tip (
|
|
slts->tip_widget(),
|
|
_("Lock GUI after this many idle seconds (zero to never lock)"));
|
|
add_option (_("Appearance"), slts);
|
|
|
|
ComboOption<ScreenSaverMode>* scsvr = new ComboOption<ScreenSaverMode> (
|
|
"screen-saver-mode",
|
|
_("System Screensaver Mode"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_screen_saver_mode),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_screen_saver_mode)
|
|
);
|
|
|
|
scsvr->add (InhibitNever, _("Never Inhibit"));
|
|
scsvr->add (InhibitWhileRecording, _("Inhibit while Recording"));
|
|
scsvr->add (InhibitAlways, string_compose (_("Inhibit while %1 is running"), PROGRAM_NAME));
|
|
|
|
add_option (_("Appearance"), scsvr);
|
|
|
|
|
|
} // !mixbus
|
|
|
|
add_option (_("Appearance"), new OptionEditorHeading (_("Theme")));
|
|
|
|
add_option (_("Appearance"), new BoolOption (
|
|
"meter-style-led",
|
|
_("LED meter style"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_style_led),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_style_led)
|
|
));
|
|
|
|
add_option (_("Appearance"), new OptionEditorHeading (_("Graphical User Interface")));
|
|
|
|
add_option (_("Appearance"),
|
|
new BoolOption (
|
|
"widget-prelight",
|
|
_("Highlight widgets on mouseover"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_widget_prelight),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_widget_prelight)
|
|
));
|
|
|
|
add_option (_("Appearance"),
|
|
new BoolOption (
|
|
"use-tooltips",
|
|
_("Show tooltips if mouse hovers over a control"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_tooltips),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_tooltips)
|
|
));
|
|
|
|
bo = new BoolOption (
|
|
"super-rapid-clock-update",
|
|
_("Update clocks at TC Frame rate"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_super_rapid_clock_update),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_super_rapid_clock_update)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
|
|
_("<b>When enabled</b> clock displays are updated every Timecode Frame (fps).\n\n"
|
|
"<b>When disabled</b> clock displays are updated only every 100ms."
|
|
));
|
|
add_option (_("Appearance"), bo);
|
|
|
|
add_option (_("Appearance"),
|
|
new BoolOption (
|
|
"blink-rec-arm",
|
|
_("Blink Rec-Arm buttons"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_blink_rec_arm),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_blink_rec_arm)
|
|
));
|
|
|
|
add_option (_("Appearance"),
|
|
new BoolOption (
|
|
"blink-alert-indicators",
|
|
_("Blink Alert Indicators"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_blink_alert_indicators),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_blink_alert_indicators)
|
|
));
|
|
|
|
BoolOption* strobe = new BoolOption (
|
|
"no-strobe",
|
|
_("Avoid strobing/blinking/flashing elements"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_no_strobe),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_no_strobe)
|
|
);
|
|
|
|
Gtkmm2ext::UI::instance()->set_tip (strobe->tip_widget(), _("If enabled, disables meters in editor & mixer, running clock updates and most blinking."));
|
|
add_option (_("Appearance"), strobe);
|
|
|
|
add_option (_("Appearance/Recorder"), new OptionEditorHeading (_("Input Meter Layout")));
|
|
|
|
ComboOption<InputMeterLayout>* iml = new ComboOption<InputMeterLayout> (
|
|
"input-meter-layout",
|
|
_("Input Meter Layout"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_input_meter_layout),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_input_meter_layout)
|
|
);
|
|
|
|
iml->add (LayoutAutomatic, _("Automatic"));
|
|
iml->add (LayoutHorizontal, _("Horizontal"));
|
|
iml->add (LayoutVertical, _("Vertical"));
|
|
|
|
add_option (S_("Appearance/Recorder"), iml);
|
|
|
|
|
|
add_option (_("Appearance/Editor"), new OptionEditorHeading (_("General")));
|
|
|
|
add_option (_("Appearance/Editor"),
|
|
new BoolOption (
|
|
"color-regions-using-track-color",
|
|
_("Region color follows track color"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_color_regions_using_track_color),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_color_regions_using_track_color)
|
|
));
|
|
|
|
add_option (_("Appearance/Editor"),
|
|
new BoolOption (
|
|
"show-region-names",
|
|
_("Show Region Names"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_region_name),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_region_name)
|
|
));
|
|
|
|
ComboOption<int>* emode = new ComboOption<int> (
|
|
"time-axis-name-ellipsize-mode",
|
|
_("Track name ellipsize mode"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_time_axis_name_ellipsize_mode),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_time_axis_name_ellipsize_mode)
|
|
);
|
|
emode->add (-1, _("Ellipsize start of name"));
|
|
emode->add (0, _("Ellipsize middle of name"));
|
|
emode->add (1, _("Ellipsize end of name"));
|
|
|
|
Gtkmm2ext::UI::instance()->set_tip (emode->tip_widget(), _("Choose which part of long track names are hidden in the editor's track headers"));
|
|
add_option (_("Appearance/Editor"), emode);
|
|
|
|
add_option (_("Appearance/Editor"), new OptionEditorHeading (_("Editor Meters")));
|
|
|
|
add_option (_("Appearance/Editor"),
|
|
new BoolOption (
|
|
"show-track-meters",
|
|
_("Show meters in track headers"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_track_meters),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_track_meters)
|
|
));
|
|
|
|
add_option (_("Appearance/Editor"), new OptionEditorBlank ());
|
|
|
|
add_option (_("Appearance/Waveform"), new OptionEditorHeading (_("Editor Waveforms")));
|
|
|
|
if (!Profile->get_mixbus()) {
|
|
add_option (_("Appearance/Waveform"),
|
|
new BoolOption (
|
|
"show-waveforms",
|
|
_("Show waveforms in regions"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms)
|
|
));
|
|
} // !mixbus
|
|
|
|
add_option (_("Appearance/Waveform"),
|
|
new BoolOption (
|
|
"show-waveforms-while-recording",
|
|
_("Show waveforms while recording"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveforms_while_recording),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveforms_while_recording)
|
|
));
|
|
|
|
add_option (_("Appearance/Waveform"),
|
|
new BoolOption (
|
|
"show-waveform-clipping",
|
|
_("Show waveform clipping"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_show_waveform_clipping),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_show_waveform_clipping)
|
|
));
|
|
|
|
add_option (_("Appearance/Waveform"), new ClipLevelOptions ());
|
|
|
|
ComboOption<WaveformScale>* wfs = new ComboOption<WaveformScale> (
|
|
"waveform-scale",
|
|
_("Waveform scale"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_scale),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_scale)
|
|
);
|
|
|
|
wfs->add (Linear, _("linear"));
|
|
wfs->add (Logarithmic, _("logarithmic"));
|
|
|
|
add_option (_("Appearance/Waveform"), wfs);
|
|
|
|
ComboOption<WaveformShape>* wfsh = new ComboOption<WaveformShape> (
|
|
"waveform-shape",
|
|
_("Waveform shape"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_shape),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_shape)
|
|
);
|
|
|
|
wfsh->add (Traditional, _("traditional"));
|
|
wfsh->add (Rectified, _("rectified"));
|
|
|
|
add_option (_("Appearance/Waveform"), wfsh);
|
|
add_option (_("Appearance/Waveform"), new OptionEditorBlank ());
|
|
|
|
#ifndef MIXBUS
|
|
add_option (_("Appearance/Mixer"),
|
|
new BoolOption (
|
|
"default-narrow_ms",
|
|
_("Use narrow strips in the mixer for new strips by default"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_default_narrow_ms),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_default_narrow_ms)
|
|
));
|
|
#endif
|
|
|
|
add_option (_("Appearance/Mixer"), new OptionEditorBlank ());
|
|
|
|
add_option (_("Appearance/Toolbar"), new OptionEditorHeading (_("Main Transport Toolbar Items")));
|
|
|
|
add_option (_("Appearance/Toolbar"), new OptionEditorBlank ());
|
|
|
|
/* size and scale */
|
|
|
|
#if (!defined __APPLE__ || defined MIXBUS)
|
|
add_option (_("Appearance/Size and Scale"), new OptionEditorHeading (_("User Interface Size and Scale")));
|
|
#endif
|
|
|
|
#ifndef __APPLE__
|
|
/* font scaling does nothing with GDK/Quartz */
|
|
add_option (_("Appearance/Size and Scale"), new FontScalingOptions ());
|
|
#endif
|
|
|
|
add_option (_("Appearance/Colors"), new OptionEditorHeading (_("Colors")));
|
|
add_option (_("Appearance/Colors"), new ColorThemeManager);
|
|
add_option (_("Appearance/Colors"), new OptionEditorBlank ());
|
|
|
|
/* Quirks */
|
|
|
|
OptionEditorHeading* quirks_head = new OptionEditorHeading (_("Various Workarounds for Windowing Systems"));
|
|
|
|
quirks_head->set_note (string_compose (_("Rules for closing, minimizing, maximizing, and stay-on-top can vary \
|
|
with each version of your OS, and the preferences that you've set in your OS.\n\n\
|
|
You can adjust the options, below, to change how application windows and dialogs behave.\n\n\
|
|
These settings will only take effect after %1 is restarted.\n\
|
|
"), PROGRAM_NAME));
|
|
|
|
add_option (_("Appearance/Quirks"), quirks_head);
|
|
|
|
bo = new BoolOption (
|
|
"use-wm-visibility",
|
|
_("Use visibility information provided by your Window Manager/Desktop"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_wm_visibility),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_wm_visibility)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
|
|
_("If you have trouble toggling between hidden Editor and Mixer windows, try changing this setting."));
|
|
add_option (_("Appearance/Quirks"), bo);
|
|
|
|
#ifndef __APPLE__
|
|
|
|
#ifndef PLATFORM_WINDOWS
|
|
bo = new BoolOption (
|
|
"hide-splash-screen",
|
|
_("Show/Hide splash screen instead of setting z-axis stack order"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_hide_splash_screen),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_hide_splash_screen)
|
|
);
|
|
add_option (_("Appearance/Quirks"), bo);
|
|
#endif
|
|
|
|
bo = new BoolOption (
|
|
"all-floating-windows-are-dialogs",
|
|
_("All floating windows are dialogs"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_all_floating_windows_are_dialogs),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_all_floating_windows_are_dialogs)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
|
|
_("Mark all floating windows to be type \"Dialog\" rather than using \"Utility\" for some.\nThis may help with some window managers."));
|
|
add_option (_("Appearance/Quirks"), bo);
|
|
|
|
bo = new BoolOption (
|
|
"transients-follow-front",
|
|
_("Transient windows follow front window."),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_transients_follow_front),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_transients_follow_front)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
|
|
_("Make transient windows follow the front window when toggling between the editor and mixer."));
|
|
add_option (_("Appearance/Quirks"), bo);
|
|
#endif
|
|
|
|
#if !(defined PLATFORM_WINDOWS || defined __APPLE__)
|
|
bo = new BoolOption (
|
|
"allow-to-resize-engine-dialog",
|
|
_("Allow to resize Engine Dialog"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_allow_to_resize_engine_dialog),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_allow_to_resize_engine_dialog)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget (),
|
|
_("On some XWayland systems the engine-dialog is blank when shown a second time (from the main menu). Allowing to resize the window works around this oddity."));
|
|
add_option (_("Appearance/Quirks"), bo);
|
|
#endif
|
|
|
|
#ifdef __APPLE__
|
|
BoolOption* bco = new BoolOption (
|
|
"use-cocoa-invalidation",
|
|
_("Use macOS to determine GUI redraw areas"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_use_cocoa_invalidation),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_use_cocoa_invalidation)
|
|
);
|
|
|
|
Gtkmm2ext::UI::instance()->set_tip (bco->tip_widget(), string_compose (_("When enabled, macOS is in charge of what areas of the GUI are redrawn.\nWhen disabled, %1 manages this by itself"), PROGRAM_NAME));
|
|
add_option (_("Appearance/Quirks"), bco);
|
|
#endif
|
|
|
|
add_option (_("Appearance/Quirks"), new OptionEditorBlank ());
|
|
#if (!defined USE_CAIRO_IMAGE_SURFACE || defined CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE || defined __APPLE__)
|
|
add_option (_("Appearance"), new OptionEditorHeading (_("Graphics Acceleration")));
|
|
#endif
|
|
|
|
#ifdef __APPLE__
|
|
ComboOption<AppleNSGLViewMode>* glmode = new ComboOption<AppleNSGLViewMode> (
|
|
"nsgl-view-mode",
|
|
_("Render Canvas on openGL texture (requires restart)"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_nsgl_view_mode),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_nsgl_view_mode)
|
|
);
|
|
glmode->add (NSGLHiRes, _("Yes, with Retina scaling"));
|
|
glmode->add (NSGLLoRes, _("Yes, low resolution"));
|
|
glmode->add (NSGLDisable, _("No"));
|
|
|
|
Gtkmm2ext::UI::instance()->set_tip (glmode->tip_widget(), string_compose (
|
|
_("Render editor canvas, on a openGL texture which may improve graphics performance.\nThis requires restarting %1 before having an effect"), PROGRAM_NAME));
|
|
add_option (_("Appearance"), glmode);
|
|
#endif
|
|
|
|
#ifndef USE_CAIRO_IMAGE_SURFACE
|
|
_cairo_image_surface = new BoolOption (
|
|
"cairo-image-surface",
|
|
_("Use intermediate image-surface to render canvas (requires restart)"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_cairo_image_surface),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_cairo_image_surface)
|
|
);
|
|
|
|
Gtkmm2ext::UI::instance()->set_tip (_cairo_image_surface->tip_widget(), string_compose (
|
|
_("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));
|
|
add_option (_("Appearance"), _cairo_image_surface);
|
|
#endif
|
|
|
|
#ifdef CAIRO_SUPPORTS_FORCE_BUGGY_GRADIENTS_ENVIRONMENT_VARIABLE
|
|
BoolOption* bgo = new BoolOption (
|
|
"buggy-gradients",
|
|
_("Possibly improve slow graphical performance (requires restart)"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_buggy_gradients),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_buggy_gradients)
|
|
);
|
|
|
|
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));
|
|
add_option (_("Appearance"), bgo);
|
|
#endif
|
|
|
|
#if ENABLE_NLS
|
|
|
|
add_option (_("Appearance/Translation"), new OptionEditorHeading (_("Internationalization")));
|
|
|
|
bo = new BoolOption (
|
|
"enable-translation",
|
|
_("Use translations"),
|
|
sigc::ptr_fun (ARDOUR::translations_are_enabled),
|
|
sigc::ptr_fun (ARDOUR::set_translations_enabled)
|
|
);
|
|
|
|
bo->set_note (string_compose (_("These settings will only take effect after %1 is restarted (if available for your language preferences)."), PROGRAM_NAME));
|
|
|
|
add_option (_("Appearance/Translation"), bo);
|
|
|
|
parameter_changed ("enable-translation");
|
|
#endif // ENABLE_NLS
|
|
|
|
/* EDITOR *******************************************************************/
|
|
|
|
|
|
// XXX Long label, pushes other ComboBoxes to the right
|
|
ComboOption<float>* eet = new ComboOption<float> (
|
|
"extra-ui-extents-time",
|
|
_("Limit zoom & summary view beyond session extents to"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_extra_ui_extents_time),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_extra_ui_extents_time)
|
|
);
|
|
eet->add (1, _("1 minute"));
|
|
eet->add (2, _("2 minutes"));
|
|
eet->add (20, _("20 minutes"));
|
|
eet->add (60, _("1 hour"));
|
|
eet->add (60*2, _("2 hours"));
|
|
eet->add (60*24, _("24 hours"));
|
|
add_option (_("Editor"), eet);
|
|
|
|
add_option (_("Editor"), new OptionEditorHeading (_("Editor Behavior")));
|
|
|
|
add_option (_("Editor"), new OptionEditorHeading (_("Split/Separate")));
|
|
|
|
ComboOption<RangeSelectionAfterSplit> *rras = new ComboOption<RangeSelectionAfterSplit> (
|
|
"range-selection-after-separate",
|
|
_("After a Separate operation, in Range mode"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_range_selection_after_split),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_range_selection_after_split));
|
|
|
|
rras->add(ClearSel, _("Clear the Range Selection"));
|
|
rras->add(PreserveSel, _("Preserve the Range Selection"));
|
|
rras->add(ForceSel, _("Select the regions under the range."));
|
|
add_option (_("Editor"), rras);
|
|
|
|
#if 1 // XXX very wide ComboBox
|
|
ComboOption<RegionSelectionAfterSplit> *rsas = new ComboOption<RegionSelectionAfterSplit> (
|
|
"region-selection-after-split",
|
|
_("After a Split operation, in Object mode"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_region_selection_after_split),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_region_selection_after_split));
|
|
|
|
// TODO: decide which of these modes are really useful
|
|
rsas->add (None, _("Clear the Region Selection"));
|
|
rsas->add (NewlyCreatedLeft, _("Select the newly-created regions BEFORE the split point"));
|
|
rsas->add (NewlyCreatedRight, _("Select only the newly-created regions AFTER the split point"));
|
|
rsas->add (NewlyCreatedBoth, _("Select the newly-created regions"));
|
|
#if 0
|
|
rsas->add(Existing, _("unmodified regions in the existing selection"));
|
|
rsas->add(ExistingNewlyCreatedLeft, _("existing selection and newly-created regions before the split"));
|
|
rsas->add(ExistingNewlyCreatedRight, _("existing selection and newly-created regions after the split"));
|
|
#endif
|
|
rsas->add(ExistingNewlyCreatedBoth, _("Preserve existing selection, and select newly-created regions"));
|
|
|
|
add_option (_("Editor"), rsas);
|
|
#endif
|
|
|
|
/* TRANSPORT & SYNC *********************************************************/
|
|
|
|
add_option (_("Transport"), new OptionEditorHeading (_("General")));
|
|
|
|
bo = new BoolOption (
|
|
"name-new-markers",
|
|
_("Prompt for new marker names"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_name_new_markers),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_name_new_markers)
|
|
);
|
|
add_option (_("Transport"), bo);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(), _("<b>When enabled</b>, popup a dialog when a new marker is created to allow its name to be set as it is created."
|
|
"\n\nYou can always rename markers by right-clicking on them."));
|
|
|
|
bo = new BoolOption (
|
|
"stop-at-session-end",
|
|
_("Stop at the end of the session"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_at_session_end),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_at_session_end)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
|
|
string_compose (_("<b>When enabled</b> if %1 is <b>not recording</b>, and <b>all trigger-slots are unused</b> "
|
|
"the transport is stopped when it reaches the current session end marker\n\n"
|
|
"<b>When disabled</b> %1 will continue to roll past the session end marker at all times"),
|
|
PROGRAM_NAME));
|
|
add_option (_("Transport"), bo);
|
|
|
|
|
|
bo = new BoolOption (
|
|
"latched-record-enable",
|
|
_("Keep record-enable engaged on stop"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_latched_record_enable),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_latched_record_enable)
|
|
);
|
|
add_option (_("Transport"), bo);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
|
|
_("<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."));
|
|
|
|
bo = new BoolOption (
|
|
"disable-disarm-during-roll",
|
|
_("Disable per-track record disarm while rolling"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_disable_disarm_during_roll),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_disable_disarm_during_roll)
|
|
);
|
|
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."));
|
|
add_option (_("Transport"), bo);
|
|
|
|
bo = new BoolOption (
|
|
"mark-at-pgm-change",
|
|
_("Create a marker when a MIDI program change is received (and RECORDING)"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_mark_at_pgm_change),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_mark_at_pgm_change)
|
|
);
|
|
add_option (_("Transport"), bo);
|
|
|
|
bo = new BoolOption (
|
|
"locate-to-pgm-change",
|
|
_("Locate to the next matching scene marker when a MIDI program change is received (and NOT recording)"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_locate_to_pgm_change),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_locate_to_pgm_change)
|
|
);
|
|
add_option (_("Transport"), bo);
|
|
|
|
add_option (_("Transport"), new OptionEditorHeading (_("Looping")));
|
|
|
|
bo = new BoolOption (
|
|
"loop-is-mode",
|
|
_("Play loop is a transport mode"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_is_mode),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_is_mode)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
|
|
(_("<b>When enabled</b> the loop button does not start playback but forces playback to always play the loop\n\n"
|
|
"<b>When disabled</b> the loop button starts playing the loop, but stop then cancels loop playback")));
|
|
|
|
add_option (_("Transport"), bo);
|
|
|
|
ComboOption<LoopFadeChoice>* lca = new ComboOption<LoopFadeChoice> (
|
|
"loop-fade-choice",
|
|
_("Loop Fades"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_loop_fade_choice),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_loop_fade_choice)
|
|
);
|
|
lca->add (NoLoopFade, _("No fades at loop boundaries"));
|
|
lca->add (EndLoopFade, _("Fade out at loop end"));
|
|
lca->add (BothLoopFade, _("Fade in at loop start & Fade out at loop end"));
|
|
lca->add (XFadeLoop, _("Cross-fade loop end and start"));
|
|
add_option (_("Transport"), lca);
|
|
Gtkmm2ext::UI::instance()->set_tip (lca->tip_widget(), _("Options for fades/crossfades at loop boundaries"));
|
|
|
|
add_option (_("Transport"), new OptionEditorHeading (_("Dropout (xrun) Handling")));
|
|
bo = new BoolOption (
|
|
"stop-recording-on-xrun",
|
|
_("Stop recording when an xrun occurs"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_stop_recording_on_xrun),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_stop_recording_on_xrun)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
|
|
string_compose (_("<b>When enabled</b> %1 will stop recording if an over- or underrun is detected by the audio engine"),
|
|
PROGRAM_NAME));
|
|
add_option (_("Transport"), bo);
|
|
|
|
bo = new BoolOption (
|
|
"create-xrun-marker",
|
|
_("Create markers where xruns occur"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_create_xrun_marker),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_create_xrun_marker)
|
|
);
|
|
add_option (_("Transport"), bo);
|
|
|
|
bo = new BoolOption (
|
|
"recording-resets-xrun-count",
|
|
_("Reset xrun counter when starting to record"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_recording_resets_xrun_count),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_recording_resets_xrun_count)
|
|
);
|
|
add_option (_("Transport"), bo);
|
|
|
|
add_option (_("Transport/Chase"), new OptionEditorHeading (_("MIDI Machine Control (MMC)")));
|
|
|
|
add_option (_("Transport/Chase"),
|
|
new BoolOption (
|
|
"mmc-control",
|
|
_("Respond to MMC commands"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_control),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_control)
|
|
));
|
|
|
|
add_option (_("Transport/Chase"),
|
|
new SpinOption<uint8_t> (
|
|
"mmc-receive-device-id",
|
|
_("Inbound MMC device ID"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_receive_device_id),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_receive_device_id),
|
|
0, 127, 1, 10
|
|
));
|
|
|
|
add_option (_("Transport/Chase"), new OptionEditorHeading (_("Transport Masters")));
|
|
|
|
add_option (_("Transport/Chase"),
|
|
new RcActionButton (_("Show Transport Masters Window"),
|
|
sigc::mem_fun (*this, &RCOptionEditor::show_transport_masters)));
|
|
|
|
_sync_framerate = new BoolOption (
|
|
"timecode-sync-frame-rate",
|
|
_("Match session video frame rate to external timecode"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_timecode_sync_frame_rate),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_timecode_sync_frame_rate)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip
|
|
(_sync_framerate->tip_widget(),
|
|
string_compose (_("This option controls the value of the video frame rate <i>while chasing</i> an external timecode source.\n\n"
|
|
"<b>When enabled</b> the session video frame rate will be changed to match that of the selected external timecode source.\n\n"
|
|
"<b>When disabled</b> the session video frame rate will not be changed to match that of the selected external timecode source."
|
|
"Instead the frame rate indication in the main clock will flash red and %1 will convert between the external "
|
|
"timecode standard and the session standard."), PROGRAM_NAME));
|
|
add_option (_("Transport/Chase"), _sync_framerate);
|
|
|
|
auto mcr = new SpinOption<double> (
|
|
"midi-clock-resolution",
|
|
_("BPM Resolution for incoming MIDI Clock"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_midi_clock_resolution),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_midi_clock_resolution),
|
|
0., 1., 0.01, 0.1, _("quarters"), 1, 2
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip
|
|
(mcr->tip_widget(),
|
|
_("This option can be used to quantize incoming MIDI clock to whole (or fractions of a) quarter note.\n\n"
|
|
"Setting it to zero prevents any quantization, which can result in a rather jittery response to incoming MIDI Clock.\n\n"
|
|
"Setting it to 1.0 quantizes to whole (integer) BPM values, and is the default.\n\n"
|
|
"If you are using a MIDI clock source that quantizes to some fraction of a quarter note then adjust this setting to reflect that."));
|
|
|
|
add_option (_("Transport/Chase"), new OptionEditorHeading (_("MIDI Clock")));
|
|
add_option (_("Transport/Chase"), mcr);
|
|
|
|
add_option (_("Transport/Generate"), new OptionEditorHeading (_("Linear Timecode (LTC) Generator")));
|
|
|
|
add_option (_("Transport/Generate"),
|
|
new BoolOption (
|
|
"send-ltc",
|
|
_("Enable LTC generator"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_ltc),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_ltc)
|
|
));
|
|
|
|
_ltc_send_continuously = new BoolOption (
|
|
"ltc-send-continuously",
|
|
_("Send LTC while stopped"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_send_continuously),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_send_continuously)
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip
|
|
(_ltc_send_continuously->tip_widget(),
|
|
string_compose (_("<b>When enabled</b> %1 will continue to send LTC information even when the transport (playhead) is not moving"), PROGRAM_NAME));
|
|
add_option (_("Transport/Generate"), _ltc_send_continuously);
|
|
|
|
_ltc_volume_slider = new HSliderOption("ltcvol", _("LTC generator level [dBFS]"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_ltc_output_volume),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_ltc_output_volume),
|
|
-50, 0, .5, 5,
|
|
.05, true);
|
|
|
|
Gtkmm2ext::UI::instance()->set_tip
|
|
(_ltc_volume_slider->tip_widget(),
|
|
_("Specify the Peak Volume of the generated LTC signal in dBFS. A good value is 0dBu ^= -18dBFS in an EBU calibrated system"));
|
|
|
|
add_option (_("Transport/Generate"), _ltc_volume_slider);
|
|
|
|
add_option (_("Transport/Generate"), new LTCPortSelectOption (_rc_config, this));
|
|
|
|
add_option (_("Transport/Generate"), new OptionEditorHeading (_("MIDI Time Code (MTC) Generator")));
|
|
|
|
add_option (_("Transport/Generate"),
|
|
new BoolOption (
|
|
"send-mtc",
|
|
_("Enable MTC Generator"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mtc),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mtc)
|
|
));
|
|
|
|
|
|
SpinOption<int>* soi = new SpinOption<int> (
|
|
"mtc-qf-speed-tolerance",
|
|
_("Max MTC varispeed (%)"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_mtc_qf_speed_tolerance),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_mtc_qf_speed_tolerance),
|
|
0, 20, 1, 5
|
|
);
|
|
Gtkmm2ext::UI::instance()->set_tip (soi->tip_widget(), _("Percentage either side of normal transport speed to transmit MTC."));
|
|
add_option (_("Transport/Generate"), soi);
|
|
|
|
add_option (_("Transport/Generate"), new OptionEditorHeading (_("MIDI Machine Control (MMC)")));
|
|
|
|
add_option (_("Transport/Generate"),
|
|
new BoolOption (
|
|
"send-mmc",
|
|
_("Send MMC commands"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_mmc),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_mmc)
|
|
));
|
|
|
|
add_option (_("Transport/Generate"),
|
|
new SpinOption<uint8_t> (
|
|
"mmc-send-device-id",
|
|
_("Outbound MMC device ID"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_mmc_send_device_id),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_mmc_send_device_id),
|
|
0, 127, 1, 10
|
|
));
|
|
|
|
add_option (_("Transport/Generate"), new OptionEditorHeading (_("MIDI Beat Clock (Mclk) Generator")));
|
|
|
|
add_option (_("Transport/Generate"),
|
|
new BoolOption (
|
|
"send-midi-clock",
|
|
_("Enable Mclk generator"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_send_midi_clock),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_send_midi_clock)
|
|
));
|
|
|
|
add_option (_("Transport"), new OptionEditorHeading (_("Plugins")));
|
|
|
|
/* MONITORING, SOLO) ********************************************************/
|
|
|
|
add_option (_("Monitoring"), new OptionEditorHeading (_("Monitoring")));
|
|
|
|
ComboOption<MonitorModel>* mm = new ComboOption<MonitorModel> (
|
|
"monitoring-model",
|
|
_("Record monitoring handled by"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_monitoring_model),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_monitoring_model)
|
|
);
|
|
|
|
if (AudioEngine::instance()->port_engine().can_monitor_input()) {
|
|
mm->add (HardwareMonitoring, _("Audio Driver"));
|
|
}
|
|
|
|
string prog (PROGRAM_NAME);
|
|
boost::algorithm::to_lower (prog);
|
|
mm->add (SoftwareMonitoring, string_compose (_("%1"), prog));
|
|
mm->add (ExternalMonitoring, _("Audio Hardware"));
|
|
|
|
add_option (_("Monitoring"), mm);
|
|
|
|
bo = new BoolOption (
|
|
"auto-input-does-talkback",
|
|
_("Auto Input does 'talkback'"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_input_does_talkback),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_input_does_talkback)
|
|
);
|
|
add_option (_("Monitoring"), bo);
|
|
Gtkmm2ext::UI::instance()->set_tip (bo->tip_widget(),
|
|
string_compose (_("<b>When enabled</b>, and Transport -> Auto-Input is enabled, %1 will always monitor audio inputs when transport is stopped, even if tracks aren't armed."),
|
|
PROGRAM_NAME));
|
|
|
|
add_option (_("Monitoring"), new OptionEditorHeading (_("Solo")));
|
|
|
|
_solo_control_is_listen_control = new BoolOption (
|
|
"solo-control-is-listen-control",
|
|
_("Solo controls are Listen controls"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_control_is_listen_control),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_control_is_listen_control)
|
|
);
|
|
|
|
add_option (_("Monitoring"), _solo_control_is_listen_control);
|
|
|
|
add_option (_("Monitoring"),
|
|
new BoolOption (
|
|
"exclusive-solo",
|
|
_("Exclusive solo"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_exclusive_solo),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_exclusive_solo)
|
|
));
|
|
|
|
add_option (_("Monitoring"),
|
|
new BoolOption (
|
|
"show-solo-mutes",
|
|
_("Show solo muting"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_show_solo_mutes),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_show_solo_mutes)
|
|
));
|
|
|
|
add_option (_("Monitoring"),
|
|
new BoolOption (
|
|
"solo-mute-override",
|
|
_("Soloing overrides muting"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_override),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_override)
|
|
));
|
|
|
|
add_option (_("Monitoring"),
|
|
new FaderOption (
|
|
"solo-mute-gain",
|
|
_("Solo-in-place mute cut (dB)"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_solo_mute_gain),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_solo_mute_gain)
|
|
));
|
|
|
|
/* SIGNAL FLOW **************************************************************/
|
|
|
|
add_option (_("Signal Flow"), new OptionEditorHeading (_("Master")));
|
|
|
|
ComboOption<uint32_t>* zitaq = new ComboOption<uint32_t> (
|
|
"port-resampler-quality",
|
|
_("I/O Resampler (vari-speed) quality"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_port_resampler_quality),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_port_resampler_quality)
|
|
);
|
|
|
|
zitaq->add (0, _("Off (no vari-speed)"));
|
|
zitaq->add (9, _("Low (16 samples latency)"));
|
|
zitaq->add (17, _("Moderate (32 samples latency), default"));
|
|
zitaq->add (33, _("Medium (64 samples latency)"));
|
|
zitaq->add (49, _("High (96 samples latency)"));
|
|
zitaq->add (65, _("Very High (128 samples latency)"));
|
|
zitaq->add (93, _("Extreme (184 samples latency)"));
|
|
|
|
uint32_t prq_val = _rc_config->get_port_resampler_quality ();
|
|
if (!(prq_val == 0 || prq_val == 9 || prq_val == 17 || prq_val == 33 || prq_val == 65 || prq_val == 93)) {
|
|
if (prq_val < 8) {
|
|
_rc_config->set_port_resampler_quality (8);
|
|
prq_val = 8;
|
|
}
|
|
if (prq_val > 96) {
|
|
_rc_config->set_port_resampler_quality (96);
|
|
prq_val = 96;
|
|
}
|
|
zitaq->add (prq_val, string_compose (_("Custom (%1 samples latency)"), prq_val - 1));
|
|
}
|
|
|
|
zitaq->set_note (_("This setting will only take effect when the Audio Engine is restarted."));
|
|
set_tooltip (zitaq->tip_widget(), _("To facilitate vari-speed playback/recording, audio is resampled to change pitch and speed. This introduces latency depending on the quality. For consistency this latency is also present when not vari-speeding (even if no resampling happens).\n\nIt is possible to disable this feature, which will also disable vari-speed. - Except if the audio-engine runs at a different sample-rate than the session, the quality is set to be at least 'Very High' (128 samples round-trip latency)"));
|
|
|
|
add_option (_("Signal Flow"), zitaq);
|
|
|
|
add_option (_("Signal Flow"), new OptionEditorHeading (_("Default Track / Bus Muting Options")));
|
|
|
|
add_option (_("Signal Flow"), new OptionEditorHeading (_("Audio Regions")));
|
|
|
|
/* CONTROL SURFACES *********************************************************/
|
|
|
|
add_option (_("Control Surfaces"), new OptionEditorHeading (_("Control Surfaces")));
|
|
add_option (_("Control Surfaces"), new ControlSurfacesOptions ());
|
|
|
|
|
|
/* METERS *******************************************************************/
|
|
|
|
if (Profile->get_mixbus()) {
|
|
add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Meterbridge meters")));
|
|
} else {
|
|
add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Metering")));
|
|
}
|
|
|
|
ComboOption<float>* mht = new ComboOption<float> (
|
|
"meter-hold",
|
|
_("Peak hold time"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_hold),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_hold)
|
|
);
|
|
|
|
mht->add (MeterHoldOff, _("off"));
|
|
mht->add (MeterHoldShort, _("short"));
|
|
mht->add (MeterHoldMedium, _("medium"));
|
|
mht->add (MeterHoldLong, _("long"));
|
|
|
|
add_option (S_("Preferences|Metering"), mht);
|
|
|
|
ComboOption<float>* mfo = new ComboOption<float> (
|
|
"meter-falloff",
|
|
_("DPM fall-off"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_falloff),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_falloff)
|
|
);
|
|
|
|
mfo->add (METER_FALLOFF_OFF, _("off"));
|
|
mfo->add (METER_FALLOFF_SLOWEST, _("slowest [6.6dB/sec]"));
|
|
mfo->add (METER_FALLOFF_SLOW, _("slow [8.6dB/sec] (BBC PPM, EBU PPM)"));
|
|
mfo->add (METER_FALLOFF_SLOWISH, _("moderate [12.0dB/sec] (DIN)"));
|
|
mfo->add (METER_FALLOFF_MODERATE, _("medium [13.3dB/sec] (EBU Digi PPM, IRT Digi PPM)"));
|
|
mfo->add (METER_FALLOFF_MEDIUM, _("fast [20dB/sec]"));
|
|
mfo->add (METER_FALLOFF_FAST, _("very fast [32dB/sec]"));
|
|
|
|
add_option (S_("Preferences|Metering"), mfo);
|
|
|
|
ComboOption<MeterLineUp>* mlu = new ComboOption<MeterLineUp> (
|
|
"meter-line-up-level",
|
|
_("Meter line-up level; 0dBu"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_level),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_level)
|
|
);
|
|
|
|
mlu->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
|
|
mlu->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
|
|
mlu->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
|
|
mlu->add (MeteringLineUp15, _("-15dBFS (DIN)"));
|
|
|
|
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."));
|
|
|
|
add_option (S_("Preferences|Metering"), mlu);
|
|
|
|
ComboOption<MeterLineUp>* mld = new ComboOption<MeterLineUp> (
|
|
"meter-line-up-din",
|
|
_("IEC1/DIN Meter line-up level; 0dBu"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_line_up_din),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_line_up_din)
|
|
);
|
|
|
|
mld->add (MeteringLineUp24, _("-24dBFS (SMPTE US: 4dBu = -20dBFS)"));
|
|
mld->add (MeteringLineUp20, _("-20dBFS (SMPTE RP.0155)"));
|
|
mld->add (MeteringLineUp18, _("-18dBFS (EBU, BBC)"));
|
|
mld->add (MeteringLineUp15, _("-15dBFS (DIN)"));
|
|
|
|
Gtkmm2ext::UI::instance()->set_tip (mld->tip_widget(), _("Reference level for IEC1/DIN meter."));
|
|
|
|
add_option (S_("Preferences|Metering"), mld);
|
|
|
|
ComboOption<VUMeterStandard>* mvu = new ComboOption<VUMeterStandard> (
|
|
"meter-vu-standard",
|
|
_("VU Meter standard"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_vu_standard),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_vu_standard)
|
|
);
|
|
|
|
mvu->add (MeteringVUfrench, _("0VU = -2dBu (France)"));
|
|
mvu->add (MeteringVUamerican, _("0VU = 0dBu (North America, Australia)"));
|
|
mvu->add (MeteringVUstandard, _("0VU = +4dBu (standard)"));
|
|
mvu->add (MeteringVUeight, _("0VU = +8dBu"));
|
|
|
|
add_option (S_("Preferences|Metering"), mvu);
|
|
|
|
HSliderOption *mpks = new HSliderOption("meter-peak",
|
|
_("Peak indicator threshold [dBFS]"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_meter_peak),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_meter_peak),
|
|
-10, 0, .1, .1
|
|
);
|
|
|
|
Gtkmm2ext::UI::instance()->set_tip (
|
|
mpks->tip_widget(),
|
|
_("Specify the audio signal level in dBFS at and above which the meter-peak indicator will flash red."));
|
|
|
|
add_option (S_("Preferences|Metering"), mpks);
|
|
|
|
OptionEditorHeading* default_meter_head = new OptionEditorHeading (_("Default Meter Types"));
|
|
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."));
|
|
|
|
add_option (S_("Preferences|Metering"), default_meter_head);
|
|
|
|
ComboOption<MeterType>* mtm = new ComboOption<MeterType> (
|
|
"meter-type-master",
|
|
_("Default Meter Type for Master Bus"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_master),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_master)
|
|
);
|
|
mtm->add (MeterPeak, ArdourMeter::meter_type_string(MeterPeak));
|
|
mtm->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
|
|
mtm->add (MeterK20, ArdourMeter::meter_type_string(MeterK20));
|
|
mtm->add (MeterK14, ArdourMeter::meter_type_string(MeterK14));
|
|
mtm->add (MeterK12, ArdourMeter::meter_type_string(MeterK12));
|
|
mtm->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
|
|
mtm->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
|
|
mtm->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
|
|
mtm->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
|
|
|
|
add_option (S_("Preferences|Metering"), mtm);
|
|
|
|
ComboOption<MeterType>* mtb = new ComboOption<MeterType> (
|
|
"meter-type-bus",
|
|
_("Default meter type for busses"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_bus),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_bus)
|
|
);
|
|
mtb->add (MeterPeak, ArdourMeter::meter_type_string(MeterPeak));
|
|
mtb->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
|
|
mtb->add (MeterK20, ArdourMeter::meter_type_string(MeterK20));
|
|
mtb->add (MeterK14, ArdourMeter::meter_type_string(MeterK14));
|
|
mtb->add (MeterK12, ArdourMeter::meter_type_string(MeterK12));
|
|
mtb->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
|
|
mtb->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
|
|
mtb->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
|
|
mtb->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
|
|
|
|
add_option (S_("Preferences|Metering"), mtb);
|
|
|
|
ComboOption<MeterType>* mtt = new ComboOption<MeterType> (
|
|
"meter-type-track",
|
|
_("Default meter type for tracks"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_meter_type_track),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_meter_type_track)
|
|
);
|
|
mtt->add (MeterPeak, ArdourMeter::meter_type_string(MeterPeak));
|
|
mtt->add (MeterPeak0dB, ArdourMeter::meter_type_string(MeterPeak0dB));
|
|
mtt->add (MeterK20, ArdourMeter::meter_type_string(MeterK20));
|
|
mtt->add (MeterK14, ArdourMeter::meter_type_string(MeterK14));
|
|
mtt->add (MeterK12, ArdourMeter::meter_type_string(MeterK12));
|
|
mtt->add (MeterIEC1DIN, ArdourMeter::meter_type_string(MeterIEC1DIN));
|
|
mtt->add (MeterIEC1NOR, ArdourMeter::meter_type_string(MeterIEC1NOR));
|
|
mtt->add (MeterIEC2BBC, ArdourMeter::meter_type_string(MeterIEC2BBC));
|
|
mtt->add (MeterIEC2EBU, ArdourMeter::meter_type_string(MeterIEC2EBU));
|
|
|
|
add_option (S_("Preferences|Metering"), mtt);
|
|
|
|
add_option (S_("Preferences|Metering"), new OptionEditorHeading (_("Region Analysis"))); //needs translation
|
|
|
|
add_option (S_("Preferences|Metering"),
|
|
new BoolOption (
|
|
"auto-analyse-audio",
|
|
_("Enable automatic analysis of audio"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_auto_analyse_audio),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_auto_analyse_audio)
|
|
));
|
|
|
|
|
|
/* PERFORMANCE **************************************************************/
|
|
|
|
uint32_t hwcpus = hardware_concurrency ();
|
|
|
|
if (hwcpus > 1) {
|
|
add_option (_("Performance"), new OptionEditorHeading (_("DSP CPU Utilization")));
|
|
|
|
ComboOption<int32_t>* procs = new ComboOption<int32_t> (
|
|
"processor-usage",
|
|
_("Signal processing uses"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_processor_usage),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_processor_usage)
|
|
);
|
|
|
|
procs->add (-1, _("all but one processor"));
|
|
procs->add (0, _("all available processors"));
|
|
|
|
for (uint32_t i = 1; i <= hwcpus; ++i) {
|
|
procs->add (i, string_compose (P_("%1 processor", "%1 processors", i), i));
|
|
}
|
|
|
|
procs->set_note (string_compose (_("This setting will only take effect when %1 is restarted."), PROGRAM_NAME));
|
|
|
|
add_option (_("Performance"), procs);
|
|
}
|
|
|
|
#if !(defined PLATFORM_WINDOWS || defined __APPLE__)
|
|
if (Glib::file_test ("/dev/cpu_dma_latency", Glib::FILE_TEST_EXISTS)) {
|
|
|
|
ComboOption<int32_t>* cpudma = new ComboOption<int32_t> (
|
|
"cpu-dma-latency",
|
|
_("Power Management, CPU DMA latency"),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::get_cpu_dma_latency),
|
|
sigc::mem_fun (*_rc_config, &RCConfiguration::set_cpu_dma_latency)
|
|
);
|
|
|
|
set<int> lvalues;
|
|
vector<string> latency_files;
|
|
Searchpath sp ("/sys/devices/system/cpu/cpu0/cpuidle/");
|
|
find_files_matching_regex (latency_files, sp, "latency$", true);
|
|
for (vector<string>::const_iterator i = latency_files.begin(); i != latency_files.end (); ++i) {
|
|
try {
|
|
std::string l = Glib::file_get_contents (*i);
|
|
int lv = atoi (l.c_str());
|
|
if (lv > 0) {
|
|
lvalues.insert (lv);
|
|
}
|
|
} catch (...) { }
|
|
}
|
|
|
|
if (lvalues.empty ()) {
|
|
lvalues.insert (5);
|
|
lvalues.insert (55);
|
|
lvalues.insert (100);
|
|
}
|
|
|
|
int32_t cpudma_val = _rc_config->get_cpu_dma_latency ();
|
|
if (cpudma_val > 0) {
|
|
lvalues.insert (cpudma_val);
|
|
}
|
|
|
|
cpudma->add (-1, _("Unset"));
|
|
cpudma->add (0, _("Lowest (prevent CPU sleep states)"));
|
|
|
|
for (set<int>::const_iterator i = lvalues.begin(); i != lvalues.end (); ++i) {
|
|
cpudma->add (*i, string_compose (_("%1 usec"), *i));
|
|
}
|
|
|
|
set_tooltip (cpudma->tip_widget(), _("This setting sets the maximum tolerable CPU DMA latency. This prevents the CPU from entering power-save states which can be beneficial for reliable low latency."));
|
|
|
|
if (access ("/dev/cpu_dma_latency", W_OK)) {
|
|
cpudma->set_note (_("This setting requires write access to `/dev/cpu_dma_latency'."));
|
|
}
|
|
|
|
add_option (_("Performance"), cpudma);
|
|
}
|
|
|
|
#endif
|
|
|
|
add_option (_("Performance"), new OptionEditorHeading (_("Disk I/O Buffering"))); //ToDo: this changed, needs translation. disambiguated from soundcard i/o buffering
|
|
|
|
add_option (_("Performance"), new BufferingOptions (_rc_config));
|
|
|
|
/* Image cache size */
|
|
add_option (_("Performance"), new OptionEditorHeading (_("Memory Usage")));
|
|
|
|
HSliderOption *sics = new HSliderOption ("waveform-cache-size",
|
|
_("Waveform image cache size (megabytes)"),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::get_waveform_cache_size),
|
|
sigc::mem_fun (UIConfiguration::instance(), &UIConfiguration::set_waveform_cache_size),
|
|
1, 1024, 10 /* 1 MB to 1GB in steps of 10MB */
|
|
);
|
|
sics->scale().set_digits (0);
|
|
Gtkmm2ext::UI::instance()->set_tip (
|
|
sics->tip_widget(),
|
|
_("Increasing the cache size uses more memory to store waveform images, which can improve graphical performance."));
|
|
add_option (_("Performance"), sics);
|
|
|
|
add_option (_("Performance"), new OptionEditorHeading (_("Automation")));
|
|
|
|
/* END OF SECTIONS/OPTIONS etc */
|
|
|
|
Widget::show_all ();
|
|
|
|
//trigger some parameter-changed messages which affect widget-visibility or -sensitivity
|
|
parameter_changed ("send-ltc");
|
|
parameter_changed ("sync-source");
|
|
parameter_changed ("open-gui-after-adding-plugin");
|
|
|
|
#ifdef __APPLE__
|
|
parameter_changed ("use-opengl-view");
|
|
#endif
|
|
|
|
// XMLNode* node = ARDOUR_UI::instance()->preferences_settings();
|
|
set_current_page (_("General"));
|
|
|
|
/* Connect metadata */
|
|
|
|
for (auto p : pages()) {
|
|
for (auto oc : p.second->components) {
|
|
Option* o = dynamic_cast<Option*> (oc);
|
|
if (o) {
|
|
Configuration::Metadata const * m = Configuration::get_metadata (o->id());
|
|
if (m) {
|
|
oc->set_metadata (*m);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool
|
|
RCOptionEditor::on_key_release_event (GdkEventKey* event)
|
|
{
|
|
if (Keyboard::modifier_state_equals (event->state, Keyboard::close_window_modifier)) {
|
|
if (event->keyval == (guint) Keyboard::close_window_key) {
|
|
hide ();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void
|
|
RCOptionEditor::set_session (Session *s)
|
|
{
|
|
ArdourWindow::set_session (s);
|
|
_transport_masters_widget.set_session (s);
|
|
}
|
|
|
|
void
|
|
RCOptionEditor::parameter_changed (string const & p)
|
|
{
|
|
OptionEditor::parameter_changed (p);
|
|
|
|
if (p == "use-monitor-bus") {
|
|
bool const s = Config->get_use_monitor_bus ();
|
|
if (!s) {
|
|
/* we can't use this if we don't have a monitor bus */
|
|
Config->set_solo_control_is_listen_control (false); // XXX
|
|
}
|
|
_solo_control_is_listen_control->set_sensitive (s);
|
|
_listen_position->set_sensitive (s);
|
|
} else if (p == "sync-source") {
|
|
std::shared_ptr<TransportMaster> tm (TransportMasterManager::instance().current());
|
|
if (std::dynamic_pointer_cast<TimecodeTransportMaster> (tm)) {
|
|
_sync_framerate->set_sensitive (true);
|
|
} else {
|
|
_sync_framerate->set_sensitive (false);
|
|
}
|
|
} else if (p == "send-ltc") {
|
|
bool const s = Config->get_send_ltc ();
|
|
_ltc_send_continuously->set_sensitive (s);
|
|
_ltc_volume_slider->set_sensitive (s);
|
|
}
|
|
}
|
|
|
|
void RCOptionEditor::reset_clip_library_dir () {
|
|
_rc_config->set_clip_library_dir ("@default@");
|
|
clip_library_dir (false);
|
|
}
|
|
|
|
void RCOptionEditor::show_audio_setup () {
|
|
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action ("Window", "toggle-audio-midi-setup");
|
|
tact->set_active();
|
|
}
|
|
|
|
void RCOptionEditor::show_transport_masters () {
|
|
Glib::RefPtr<ToggleAction> tact = ActionManager::get_toggle_action ("Window", "toggle-transport-masters");
|
|
tact->set_active();
|
|
}
|
|
|
|
XMLNode&
|
|
RCOptionEditor::get_state () const
|
|
{
|
|
XMLNode* node = new XMLNode (X_("Preferences"));
|
|
return *node;
|
|
}
|
|
|
|
std::string
|
|
RCOptionEditor::get_default_lower_midi_note ()
|
|
{
|
|
return ParameterDescriptor::midi_note_name (UIConfiguration::instance().get_default_lower_midi_note());
|
|
}
|
|
|
|
bool
|
|
RCOptionEditor::set_default_lower_midi_note (std::string str)
|
|
{
|
|
int note = ParameterDescriptor::midi_note_num (str);
|
|
|
|
if (note < 0) {
|
|
mru_option->set_state_from_config ();
|
|
return false;
|
|
}
|
|
|
|
return UIConfiguration::instance().set_default_lower_midi_note (note);
|
|
}
|
|
|
|
std::string
|
|
RCOptionEditor::get_default_upper_midi_note ()
|
|
{
|
|
return ParameterDescriptor::midi_note_name (UIConfiguration::instance().get_default_upper_midi_note());
|
|
}
|
|
|
|
bool
|
|
RCOptionEditor::set_default_upper_midi_note (std::string str)
|
|
{
|
|
int note = ParameterDescriptor::midi_note_num (str);
|
|
|
|
if (note < 0) {
|
|
mru_option->set_state_from_config ();
|
|
return false;
|
|
}
|
|
|
|
return UIConfiguration::instance().set_default_upper_midi_note (note);
|
|
}
|