Clean up plugin preset handling a bit.

git-svn-id: svn://localhost/ardour2/branches/3.0@8301 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
Carl Hetherington 2010-12-19 23:11:01 +00:00
parent bb7dbe6d86
commit 5f4bdb233a
18 changed files with 391 additions and 231 deletions

View File

@ -92,7 +92,7 @@ GenericPluginUI::GenericPluginUI (boost::shared_ptr<PluginInsert> pi, bool scrol
set_latency_label ();
smaller_hbox->pack_start (latency_button, false, false, 10);
smaller_hbox->pack_start (preset_combo, false, false);
smaller_hbox->pack_start (_preset_box, false, false);
smaller_hbox->pack_start (add_button, false, false);
smaller_hbox->pack_start (save_button, false, false);
smaller_hbox->pack_start (delete_button, false, false);
@ -425,7 +425,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
//control_ui->combo->set_value_in_list(true, false);
set_popdown_strings (*control_ui->combo, setup_scale_values(port_index, control_ui));
control_ui->combo->signal_changed().connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::control_combo_changed), control_ui));
mcontrol->Changed.connect (control_connections, invalidator (*this), boost::bind (&GenericPluginUI::parameter_changed, this, control_ui), gui_context());
mcontrol->Changed.connect (control_connections, invalidator (*this), boost::bind (&GenericPluginUI::ui_parameter_changed, this, control_ui), gui_context());
control_ui->pack_start(control_ui->label, true, true);
control_ui->pack_start(*control_ui->combo, false, true);
@ -446,7 +446,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
//control_ui->combo->set_value_in_list(true, false);
set_popdown_strings (*control_ui->combo, setup_scale_values(port_index, control_ui));
control_ui->combo->signal_changed().connect (sigc::bind (sigc::mem_fun(*this, &GenericPluginUI::control_combo_changed), control_ui));
mcontrol->Changed.connect (control_connections, invalidator (*this), boost::bind (&GenericPluginUI::parameter_changed, this, control_ui), gui_context());
mcontrol->Changed.connect (control_connections, invalidator (*this), boost::bind (&GenericPluginUI::ui_parameter_changed, this, control_ui), gui_context());
control_ui->pack_start(control_ui->label, true, true);
control_ui->pack_start(*control_ui->combo, false, true);
@ -557,7 +557,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
automation_state_changed (control_ui);
mcontrol->Changed.connect (control_connections, invalidator (*this), boost::bind (&GenericPluginUI::parameter_changed, this, control_ui), gui_context());
mcontrol->Changed.connect (control_connections, invalidator (*this), boost::bind (&GenericPluginUI::ui_parameter_changed, this, control_ui), gui_context());
mcontrol->alist()->automation_state_changed.connect (control_connections, invalidator (*this), boost::bind (&GenericPluginUI::automation_state_changed, this, control_ui), gui_context());
input_controls.push_back (control_ui);
@ -609,7 +609,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, boost::shared_ptr<Automat
output_controls.push_back (control_ui);
}
mcontrol->Changed.connect (control_connections, invalidator (*this), boost::bind (&GenericPluginUI::parameter_changed, this, control_ui), gui_context());
mcontrol->Changed.connect (control_connections, invalidator (*this), boost::bind (&GenericPluginUI::ui_parameter_changed, this, control_ui), gui_context());
return control_ui;
}
@ -672,7 +672,7 @@ GenericPluginUI::toggle_parameter_changed (ControlUI* cui)
}
void
GenericPluginUI::parameter_changed (ControlUI* cui)
GenericPluginUI::ui_parameter_changed (ControlUI* cui)
{
if (!cui->update_pending) {
cui->update_pending = true;

View File

@ -55,7 +55,8 @@ void LV2PluginUI::on_external_ui_closed(LV2UI_Controller controller)
void
LV2PluginUI::parameter_changed (uint32_t port_index, float val)
{
//cout << "parameter_changed" << endl;
PlugUIBase::parameter_changed (port_index, val);
if (val != _values[port_index]) {
parameter_update(port_index, val);
}
@ -199,8 +200,6 @@ LV2PluginUI::lv2ui_instantiate(const std::string& title)
}
}
}
_lv2->ParameterChanged.connect (parameter_connection, invalidator (*this), ui_bind (&LV2PluginUI::parameter_changed, this, _1, _2), gui_context());
}
LV2PluginUI::~LV2PluginUI ()

View File

@ -59,6 +59,9 @@ class LV2PluginUI : public PlugUIBase, public Gtk::VBox
int package (Gtk::Window&);
private:
void parameter_changed (uint32_t, float);
boost::shared_ptr<ARDOUR::LV2Plugin> _lv2;
std::vector<int> _output_ports;
sigc::connection _screen_update_connection;
@ -83,7 +86,6 @@ class LV2PluginUI : public PlugUIBase, public Gtk::VBox
void lv2ui_instantiate(const std::string& title);
void parameter_changed(uint32_t, float);
void parameter_update(uint32_t, float);
bool configure_handler (GdkEventConfigure*);
void save_plugin_setting ();
@ -92,8 +94,6 @@ class LV2PluginUI : public PlugUIBase, public Gtk::VBox
virtual bool on_window_show(const std::string& title);
virtual void on_window_hide();
PBD::ScopedConnection parameter_connection;
};
#endif // HAVE_SLV2

View File

@ -217,7 +217,8 @@ PluginUIWindow::on_show ()
set_role("plugin_ui");
if (_pluginui) {
_pluginui->update_presets ();
_pluginui->update_preset_list ();
_pluginui->update_preset ();
}
if (_pluginui) {
@ -427,15 +428,17 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
latency_gui (0),
plugin_analysis_expander (_("Plugin analysis"))
{
//preset_combo.set_use_arrows_always(true);
update_presets ();
update_sensitivity ();
preset_combo.set_size_request (100, -1);
preset_combo.set_active_text ("");
preset_combo.signal_changed().connect(sigc::mem_fun(*this, &PlugUIBase::setting_selected));
no_load_preset = false;
_preset_combo.set_size_request (100, -1);
_preset_modified.set_size_request (16, -1);
_preset_combo.signal_changed().connect(sigc::mem_fun(*this, &PlugUIBase::preset_selected));
_no_load_preset = 0;
_preset_box.pack_start (_preset_combo);
_preset_box.pack_start (_preset_modified);
update_preset_list ();
update_preset ();
add_button.set_name ("PluginAddButton");
add_button.signal_clicked().connect (sigc::mem_fun (*this, &PlugUIBase::add_plugin_setting));
@ -471,8 +474,10 @@ PlugUIBase::PlugUIBase (boost::shared_ptr<PluginInsert> pi)
insert->DropReferences.connect (death_connection, invalidator (*this), boost::bind (&PlugUIBase::plugin_going_away, this), gui_context());
plugin->PresetAdded.connect (preset_added_connection, invalidator (*this), boost::bind (&PlugUIBase::update_presets, this), gui_context ());
plugin->PresetRemoved.connect (preset_removed_connection, invalidator (*this), boost::bind (&PlugUIBase::update_presets, this), gui_context ());
plugin->PresetAdded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
plugin->PresetRemoved.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
plugin->PresetLoaded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::update_preset, this), gui_context ());
plugin->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::parameter_changed, this, _1, _2), gui_context ());
}
PlugUIBase::~PlugUIBase()
@ -529,20 +534,19 @@ PlugUIBase::processor_active_changed (boost::weak_ptr<Processor> weak_p)
}
void
PlugUIBase::setting_selected ()
PlugUIBase::preset_selected ()
{
if (no_load_preset) {
if (_no_load_preset) {
return;
}
if (preset_combo.get_active_text().length() > 0) {
const Plugin::PresetRecord* pr = plugin->preset_by_label(preset_combo.get_active_text());
if (_preset_combo.get_active_text().length() > 0) {
const Plugin::PresetRecord* pr = plugin->preset_by_label (_preset_combo.get_active_text());
if (pr) {
plugin->load_preset (pr->uri);
update_sensitivity ();
plugin->load_preset (*pr);
} else {
warning << string_compose(_("Plugin preset %1 not found"),
preset_combo.get_active_text()) << endmsg;
_preset_combo.get_active_text()) << endmsg;
}
}
}
@ -562,8 +566,9 @@ PlugUIBase::add_plugin_setting ()
plugin->remove_preset (d.name ());
}
if (plugin->save_preset (d.name())) {
preset_combo.set_active_text (d.name());
Plugin::PresetRecord const r = plugin->save_preset (d.name());
if (!r.uri.empty ()) {
plugin->load_preset (r);
}
break;
}
@ -572,23 +577,18 @@ PlugUIBase::add_plugin_setting ()
void
PlugUIBase::save_plugin_setting ()
{
string const name = preset_combo.get_active_text ();
string const name = _preset_combo.get_active_text ();
plugin->remove_preset (name);
plugin->save_preset (name);
preset_combo.set_active_text (name);
Plugin::PresetRecord const r = plugin->save_preset (name);
if (!r.uri.empty ()) {
plugin->load_preset (r);
}
}
void
PlugUIBase::delete_plugin_setting ()
{
plugin->remove_preset (preset_combo.get_active_text ());
vector<ARDOUR::Plugin::PresetRecord> presets = plugin->get_presets();
if (presets.empty ()) {
preset_combo.set_active_text ("");
} else {
preset_combo.set_active_text (presets.front().label);
}
plugin->remove_preset (_preset_combo.get_active_text ());
}
void
@ -667,30 +667,61 @@ PlugUIBase::toggle_plugin_analysis()
}
void
PlugUIBase::update_presets ()
PlugUIBase::update_preset_list ()
{
vector<string> preset_labels;
vector<ARDOUR::Plugin::PresetRecord> presets = plugin->get_presets();
no_load_preset = true;
++_no_load_preset;
for (vector<ARDOUR::Plugin::PresetRecord>::const_iterator i = presets.begin(); i != presets.end(); ++i) {
preset_labels.push_back(i->label);
preset_labels.push_back (i->label);
}
set_popdown_strings (preset_combo, preset_labels);
set_popdown_strings (_preset_combo, preset_labels);
no_load_preset = false;
update_sensitivity ();
--_no_load_preset;
}
void
PlugUIBase::update_sensitivity ()
PlugUIBase::update_preset ()
{
bool const have_user_preset =
!preset_combo.get_model()->children().empty() && preset_combo.get_active_row_number() >= plugin->first_user_preset_index();
save_button.set_sensitive (have_user_preset);
delete_button.set_sensitive (have_user_preset);
Plugin::PresetRecord p = plugin->last_preset();
++_no_load_preset;
_preset_combo.set_active_text (p.label);
--_no_load_preset;
save_button.set_sensitive (!p.uri.empty() && p.user);
delete_button.set_sensitive (!p.uri.empty() && p.user);
update_preset_modified ();
}
void
PlugUIBase::update_preset_modified ()
{
if (plugin->last_preset().uri.empty()) {
_preset_modified.set_text ("");
return;
}
bool const c = plugin->parameter_changed_since_last_preset ();
if (_preset_modified.get_text().empty() == c) {
_preset_modified.set_text (c ? "*" : "");
}
}
void
PlugUIBase::parameter_changed (uint32_t, float)
{
update_preset_modified ();
}
void
PlugUIBase::preset_added_or_removed ()
{
/* Update both the list and the currently-displayed preset */
update_preset_list ();
update_preset ();
}

View File

@ -72,7 +72,7 @@ namespace Gtkmm2ext {
class LatencyGUI;
class ArdourDialog;
class PlugUIBase : public virtual sigc::trackable
class PlugUIBase : public virtual sigc::trackable, public PBD::ScopedConnectionList
{
public:
PlugUIBase (boost::shared_ptr<ARDOUR::PluginInsert>);
@ -86,7 +86,8 @@ class PlugUIBase : public virtual sigc::trackable
virtual void activate () {}
virtual void deactivate () {}
virtual void update_presets ();
void update_preset_list ();
void update_preset ();
void latency_button_clicked ();
@ -101,7 +102,9 @@ class PlugUIBase : public virtual sigc::trackable
protected:
boost::shared_ptr<ARDOUR::PluginInsert> insert;
boost::shared_ptr<ARDOUR::Plugin> plugin;
Gtk::ComboBoxText preset_combo;
Gtk::HBox _preset_box;
Gtk::ComboBoxText _preset_combo;
Gtk::Label _preset_modified;
Gtk::Button add_button;
Gtk::Button save_button;
Gtk::Button delete_button;
@ -119,9 +122,9 @@ class PlugUIBase : public virtual sigc::trackable
Gtk::Image* focus_out_image;
Gtk::Image* focus_in_image;
bool no_load_preset;
int _no_load_preset;
virtual void setting_selected ();
virtual void preset_selected ();
void add_plugin_setting ();
void save_plugin_setting ();
void delete_plugin_setting ();
@ -130,7 +133,9 @@ class PlugUIBase : public virtual sigc::trackable
void toggle_plugin_analysis ();
void processor_active_changed (boost::weak_ptr<ARDOUR::Processor> p);
void plugin_going_away ();
void update_sensitivity ();
virtual void parameter_changed (uint32_t, float);
void preset_added_or_removed ();
void update_preset_modified ();
PBD::ScopedConnection death_connection;
PBD::ScopedConnection active_connection;
@ -234,7 +239,7 @@ class GenericPluginUI : public PlugUIBase, public Gtk::VBox
void build ();
ControlUI* build_control_ui (guint32 port_index, boost::shared_ptr<ARDOUR::AutomationControl>);
std::vector<std::string> setup_scale_values(guint32 port_index, ControlUI* cui);
void parameter_changed (ControlUI* cui);
void ui_parameter_changed (ControlUI* cui);
void toggle_parameter_changed (ControlUI* cui);
void update_control_display (ControlUI* cui);
void control_port_toggled (ControlUI* cui);

View File

@ -35,8 +35,6 @@ VSTPluginUI::VSTPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<
: PlugUIBase (pi),
vst (vp)
{
update_presets ();
fst_run_editor (vst->fst());
preset_box.set_spacing (6);
@ -45,7 +43,7 @@ VSTPluginUI::VSTPluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<
preset_box.pack_end (delete_button, false, false);
preset_box.pack_end (save_button, false, false);
preset_box.pack_end (add_button, false, false);
preset_box.pack_end (preset_combo, false, false);
preset_box.pack_end (_preset_box, false, false);
bypass_button.set_active (!insert->active());
@ -61,22 +59,10 @@ VSTPluginUI::~VSTPluginUI ()
}
void
VSTPluginUI::setting_selected ()
VSTPluginUI::preset_selected ()
{
int const r = preset_combo.get_active_row_number ();
if (r < vst->first_user_preset_index()) {
/* This is a plugin-provided preset.
We can't dispatch directly here; too many plugins expects only one GUI thread.
*/
vst->fst()->want_program = r;
} else {
/* This is a user preset. This method knows about the direct dispatch restriction, too */
plugin->load_preset (preset_combo.get_active_text());
}
socket.grab_focus ();
update_sensitivity ();
PlugUIBase::preset_selected ();
}
int

View File

@ -40,5 +40,5 @@ class VSTPluginUI : public PlugUIBase, public Gtk::VBox
bool configure_handler (GdkEventConfigure*, Gtk::Socket*);
void save_plugin_setting ();
void setting_selected ();
void preset_selected ();
};

View File

@ -95,12 +95,10 @@ class AUPlugin : public ARDOUR::Plugin
bool parameter_is_input (uint32_t) const;
bool parameter_is_output (uint32_t) const;
XMLNode& get_state();
int set_state(const XMLNode& node, int);
bool save_preset (std::string name);
bool load_preset (const std::string& preset_label);
std::vector<PresetRecord> get_presets ();
std::string current_preset() const;
bool has_editor () const;
@ -143,6 +141,8 @@ class AUPlugin : public ARDOUR::Plugin
static std::string maybe_fix_broken_au_id (const std::string&);
private:
void find_presets ();
boost::shared_ptr<CAComponent> comp;
boost::shared_ptr<CAAudioUnit> unit;
@ -178,6 +178,7 @@ class AUPlugin : public ARDOUR::Plugin
int set_input_format (AudioStreamBasicDescription&);
int set_stream_format (int scope, uint32_t cnt, AudioStreamBasicDescription&);
void discover_parameters ();
void add_state (XMLNode *) const;
std::vector<std::pair<uint32_t, uint32_t> > parameter_map;
uint32_t current_maxbuf;

View File

@ -97,11 +97,9 @@ class LadspaPlugin : public ARDOUR::Plugin
bool parameter_is_output(uint32_t) const;
bool parameter_is_toggled(uint32_t) const;
XMLNode& get_state();
int set_state (const XMLNode&, int version);
std::vector<PresetRecord> get_presets ();
bool load_preset (const std::string& uri);
bool load_preset (PresetRecord);
bool has_editor() const { return false; }
@ -131,6 +129,8 @@ class LadspaPlugin : public ARDOUR::Plugin
uint32_t _index;
bool _was_activated;
void find_presets ();
void init (void *mod, uint32_t index, framecnt_t rate);
void run_in_place (pframes_t nsamples);
void latency_compute_run ();
@ -140,6 +140,7 @@ class LadspaPlugin : public ARDOUR::Plugin
std::string preset_envvar () const;
std::string preset_source (std::string) const;
bool write_preset_file (std::string);
void add_state (XMLNode *) const;
};
class LadspaPluginInfo : public PluginInfo {

View File

@ -66,7 +66,7 @@ class LV2Plugin : public ARDOUR::Plugin
bool is_external_ui() const;
SLV2Port slv2_port(uint32_t i) { return slv2_plugin_get_port_by_index(_plugin, i); }
const char* port_symbol(uint32_t port);
const char* port_symbol (uint32_t port) const;
const LV2_Feature* const* features() { return _features; }
@ -112,12 +112,11 @@ class LV2Plugin : public ARDOUR::Plugin
static uint32_t midi_event_type() { return _midi_event_type; }
XMLNode& get_state();
int set_state(const XMLNode& node, int version);
bool save_preset (std::string uri);
void remove_preset (std::string uri);
bool load_preset (const std::string& uri);
virtual std::vector<Plugin::PresetRecord> get_presets();
bool load_preset (PresetRecord);
std::string current_preset () const;
bool has_editor() const;
@ -167,6 +166,8 @@ class LV2Plugin : public ARDOUR::Plugin
void latency_compute_run ();
std::string do_save_preset (std::string);
void do_remove_preset (std::string);
void find_presets ();
void add_state (XMLNode *) const;
};

View File

@ -99,6 +99,9 @@ class Plugin : public PBD::StatefulDestructible, public Latent
bool max_unbound;
};
XMLNode& get_state ();
virtual int set_state (const XMLNode &, int version);
virtual std::string unique_id() const = 0;
virtual const char * label() const = 0;
virtual const char * name() const = 0;
@ -131,23 +134,40 @@ class Plugin : public PBD::StatefulDestructible, public Latent
void realtime_handle_transport_stopped ();
bool save_preset (std::string);
void remove_preset (std::string);
virtual bool load_preset (const std::string& uri) = 0;
struct PresetRecord {
PresetRecord (const std::string& u, const std::string& l) : uri(u), label(l) {}
PresetRecord () : user (true) {}
PresetRecord (const std::string& u, const std::string& l, bool s = true) : uri (u), label (l), user (s) {}
bool operator!= (PresetRecord const & a) const {
return uri != a.uri || label != a.label;
}
std::string uri;
std::string label;
bool user;
};
PresetRecord save_preset (std::string);
void remove_preset (std::string);
virtual bool load_preset (PresetRecord);
const PresetRecord * preset_by_label (const std::string &);
const PresetRecord * preset_by_uri (const std::string &);
/** Return this plugin's presets; should add them to _presets */
virtual std::vector<PresetRecord> get_presets () = 0;
virtual std::string current_preset () const { return std::string(); }
std::vector<PresetRecord> get_presets ();
/** @return Last preset to be requested; the settings may have
* been changed since; find out with parameter_changed_since_last_preset.
*/
PresetRecord last_preset () const {
return _last_preset;
}
bool parameter_changed_since_last_preset () const {
return _parameter_changed_since_last_preset;
}
virtual int first_user_preset_index () const {
return 0;
}
@ -155,13 +175,14 @@ class Plugin : public PBD::StatefulDestructible, public Latent
/** Emitted when a preset is added or removed, respectively */
PBD::Signal0<void> PresetAdded;
PBD::Signal0<void> PresetRemoved;
/* XXX: no-one listens to this */
static PBD::Signal0<bool> PresetFileExists;
virtual bool has_editor() const = 0;
/** Emitted when a preset has been loaded */
PBD::Signal0<void> PresetLoaded;
PBD::Signal2<void,uint32_t,float> ParameterChanged;
virtual bool has_editor () const = 0;
/** Emitted when any parameter changes */
PBD::Signal2<void, uint32_t, float> ParameterChanged;
/* NOTE: this block of virtual methods looks like the interface
to a Processor, but Plugin does not inherit from Processor.
@ -199,7 +220,7 @@ protected:
friend class PluginInsert;
friend struct PluginInsert::PluginControl;
virtual void set_parameter (uint32_t which, float val) = 0;
virtual void set_parameter (uint32_t which, float val);
/** Do the actual saving of the current plugin settings to a preset of the provided name.
* Should return a URI on success, or an empty string on failure.
@ -215,10 +236,19 @@ protected:
std::map<std::string, PresetRecord> _presets;
private:
/** Fill _presets with our presets */
virtual void find_presets () = 0;
/** Add state to an existing XMLNode */
virtual void add_state (XMLNode *) const = 0;
bool _have_presets;
MidiStateTracker _tracker;
BufferSet _pending_stop_events;
bool _have_pending_stop_events;
PresetRecord _last_preset;
bool _parameter_changed_since_last_preset;
};
PluginPtr find_plugin(ARDOUR::Session&, std::string unique_id, ARDOUR::PluginType);

View File

@ -78,13 +78,11 @@ class VSTPlugin : public ARDOUR::Plugin
bool parameter_is_input(uint32_t i) const { return true; }
bool parameter_is_output(uint32_t i) const { return false; }
bool load_preset (const std::string& preset_label);
virtual std::vector<PresetRecord> get_presets ();
bool load_preset (PresetRecord);
int first_user_preset_index () const;
bool has_editor () const;
XMLNode& get_state();
int set_state (XMLNode const &, int);
AEffect * plugin () const { return _plugin; }
@ -94,10 +92,14 @@ private:
void do_remove_preset (std::string name);
std::string do_save_preset (std::string name);
gchar* get_chunk (bool);
gchar* get_chunk (bool) const;
int set_chunk (gchar const *, bool);
XMLTree * presets_tree () const;
std::string presets_file () const;
void find_presets ();
bool load_user_preset (PresetRecord);
bool load_plugin_preset (PresetRecord);
void add_state (XMLNode *) const;
FSTHandle* handle;
FST* _fst;

View File

@ -162,16 +162,10 @@ save_property_list (CFPropertyListRef propertyList, Glib::ustring path)
fd = open (path.c_str(), O_WRONLY|O_CREAT|O_EXCL, 0664);
while (fd < 0) {
if (errno == EEXIST) {
/* tell any UI's that this file already exists and ask them what to do */
bool overwrite = Plugin::PresetFileExists(); // EMIT SIGNAL
if (overwrite) {
fd = open (path.c_str(), O_WRONLY, 0664);
continue;
} else {
return 0;
}
error << string_compose (_("Preset file %1 exists; not overwriting"), path);
} else {
error << string_compose (_("Cannot open preset file %1 (%2)"), path, strerror (errno)) << endmsg;
}
error << string_compose (_("Cannot open preset file %1 (%2)"), path, strerror (errno)) << endmsg;
CFRelease (xmlData);
return -1;
}
@ -767,24 +761,28 @@ AUPlugin::signal_latency () const
void
AUPlugin::set_parameter (uint32_t which, float val)
{
if (which < descriptors.size()) {
const AUParameterDescriptor& d (descriptors[which]);
TRACE_API ("set parameter %d in scope %d element %d to %f\n", d.id, d.scope, d.element, val);
unit->SetParameter (d.id, d.scope, d.element, val);
/* tell the world what we did */
AudioUnitEvent theEvent;
theEvent.mEventType = kAudioUnitEvent_ParameterValueChange;
theEvent.mArgument.mParameter.mAudioUnit = unit->AU();
theEvent.mArgument.mParameter.mParameterID = d.id;
theEvent.mArgument.mParameter.mScope = d.scope;
theEvent.mArgument.mParameter.mElement = d.element;
TRACE_API ("notify about parameter change\n");
AUEventListenerNotify (NULL, NULL, &theEvent);
if (which >= descriptors.size()) {
return;
}
const AUParameterDescriptor& d (descriptors[which]);
TRACE_API ("set parameter %d in scope %d element %d to %f\n", d.id, d.scope, d.element, val);
unit->SetParameter (d.id, d.scope, d.element, val);
/* tell the world what we did */
AudioUnitEvent theEvent;
theEvent.mEventType = kAudioUnitEvent_ParameterValueChange;
theEvent.mArgument.mParameter.mAudioUnit = unit->AU();
theEvent.mArgument.mParameter.mParameterID = d.id;
theEvent.mArgument.mParameter.mScope = d.scope;
theEvent.mArgument.mParameter.mElement = d.element;
TRACE_API ("notify about parameter change\n");
AUEventListenerNotify (NULL, NULL, &theEvent);
Plugin::set_parameter (which, val);
}
float
@ -1551,11 +1549,10 @@ AUPlugin::parameter_is_output (uint32_t) const
return false;
}
XMLNode&
AUPlugin::get_state()
void
AUPlugin::add_state (XMLNode* root)
{
LocaleGuard lg (X_("POSIX"));
XMLNode *root = new XMLNode (state_node_name());
#ifdef AU_STATE_SUPPORT
CFDataRef xmlData;
@ -1563,7 +1560,7 @@ AUPlugin::get_state()
TRACE_API ("get preset state\n");
if (unit->GetAUPreset (propertyList) != noErr) {
return *root;
return;
}
// Convert the property list into XML data.
@ -1597,12 +1594,10 @@ AUPlugin::get_state()
seen_get_state_message = true;
}
#endif
return *root;
}
int
AUPlugin::set_state(const XMLNode& node, int /* version*/)
AUPlugin::set_state(const XMLNode& node, int version)
{
#ifdef AU_STATE_SUPPORT
int ret = -1;
@ -1650,6 +1645,7 @@ AUPlugin::set_state(const XMLNode& node, int /* version*/)
CFRelease (propertyList);
}
Plugin::set_state (node, version);
return ret;
#else
if (!seen_set_state_message) {
@ -1657,13 +1653,15 @@ AUPlugin::set_state(const XMLNode& node, int /* version*/)
PROGRAM_NAME)
<< endmsg;
}
return 0;
return Plugin::set_state (node, version);
#endif
}
bool
AUPlugin::load_preset (const string& preset_label)
AUPlugin::load_preset (PluginRecord r)
{
Plugin::load_preset (r);
#ifdef AU_STATE_SUPPORT
bool ret = false;
CFPropertyListRef propertyList;
@ -1962,11 +1960,9 @@ AUPlugin::current_preset() const
return preset_name;
}
vector<Plugin::PresetRecord>
AUPlugin::get_presets ()
void
AUPlugin::find_presets ()
{
vector<Plugin::PresetRecord> presets;
#ifdef AU_STATE_SUPPORT
vector<string*>* preset_files;
PathScanner scanner;
@ -1976,7 +1972,7 @@ AUPlugin::get_presets ()
preset_files = scanner (preset_search_path, au_preset_filter, this, true, true, -1, true);
if (!preset_files) {
return presets;
return;
}
for (vector<string*>::iterator x = preset_files->begin(); x != preset_files->end(); ++x) {
@ -2006,18 +2002,18 @@ AUPlugin::get_presets ()
/* now fill the vector<string> with the names we have */
for (UserPresetMap::iterator i = user_preset_map.begin(); i != user_preset_map.end(); ++i) {
presets.push_back (Plugin::PresetRecord (i->second, i->first));
_presets.insert (i->second, Plugin::PresetRecord (i->second, i->first));
}
/* add factory presets */
for (FactoryPresetMap::iterator i = factory_preset_map.begin(); i != factory_preset_map.end(); ++i) {
presets.push_back (Plugin::PresetRecord ("", i->first));
/* XXX: dubious */
string const uri = string_compose ("%1", _presets.size ());
_presets.push_back (uri, Plugin::PresetRecord (uri, i->first));
}
#endif
return presets;
}
bool

View File

@ -297,9 +297,8 @@ LadspaPlugin::set_parameter (uint32_t which, float val)
{
if (which < _descriptor->PortCount) {
_shadow_data[which] = (LADSPA_Data) val;
#if 0
ParameterChanged (Parameter(PluginAutomation, 0, which), val); /* EMIT SIGNAL */
#if 0
if (which < parameter_count() && controls[which]) {
controls[which]->Changed ();
}
@ -311,6 +310,8 @@ LadspaPlugin::set_parameter (uint32_t which, float val)
"invalid"), name())
<< endmsg;
}
Plugin::set_parameter (which, val);
}
float
@ -341,10 +342,9 @@ LadspaPlugin::nth_parameter (uint32_t n, bool& ok) const
return 0;
}
XMLNode&
LadspaPlugin::get_state()
void
LadspaPlugin::add_state (XMLNode* root) const
{
XMLNode *root = new XMLNode(state_node_name());
XMLNode *child;
char buf[16];
LocaleGuard lg (X_("POSIX"));
@ -362,8 +362,6 @@ LadspaPlugin::get_state()
root->add_child_nocopy (*child);
}
}
return *root;
}
int
@ -372,7 +370,7 @@ LadspaPlugin::set_state (const XMLNode& node, int version)
if (version < 3000) {
return set_state_2X (node, version);
}
XMLNodeList nodes;
XMLProperty *prop;
XMLNodeConstIterator iter;
@ -389,7 +387,7 @@ LadspaPlugin::set_state (const XMLNode& node, int version)
nodes = node.children ("Port");
for(iter = nodes.begin(); iter != nodes.end(); ++iter){
for (iter = nodes.begin(); iter != nodes.end(); ++iter) {
child = *iter;
@ -412,7 +410,7 @@ LadspaPlugin::set_state (const XMLNode& node, int version)
latency_compute_run ();
return 0;
return Plugin::set_state (node, version);
}
int
@ -709,15 +707,14 @@ LadspaPluginInfo::LadspaPluginInfo()
}
vector<Plugin::PresetRecord>
LadspaPlugin::get_presets ()
void
LadspaPlugin::find_presets ()
{
vector<PresetRecord> result;
uint32_t id;
std::string unique (unique_id());
if (!isdigit (unique[0])) {
return result;
return;
}
id = atol (unique.c_str());
@ -727,22 +724,19 @@ LadspaPlugin::get_presets ()
if (set_uris) {
for (uint32_t i = 0; i < (uint32_t) set_uris->count; ++i) {
if (char* label = lrdf_get_label(set_uris->items[i])) {
PresetRecord rec(set_uris->items[i], label);
result.push_back(rec);
PresetRecord rec (set_uris->items[i], label);
_presets.insert (make_pair (set_uris->items[i], rec));
}
}
lrdf_free_uris(set_uris);
}
return result;
}
bool
LadspaPlugin::load_preset (const string& preset_uri)
LadspaPlugin::load_preset (PresetRecord r)
{
lrdf_defaults* defs = lrdf_get_setting_values(preset_uri.c_str());
lrdf_defaults* defs = lrdf_get_setting_values (r.uri.c_str());
if (defs) {
for (uint32_t i = 0; i < (uint32_t) defs->count; ++i) {
@ -755,6 +749,7 @@ LadspaPlugin::load_preset (const string& preset_uri)
lrdf_free_setting_values(defs);
}
Plugin::load_preset (r);
return true;
}

View File

@ -219,7 +219,7 @@ LV2Plugin::default_value (uint32_t port)
}
const char*
LV2Plugin::port_symbol (uint32_t index)
LV2Plugin::port_symbol (uint32_t index) const
{
SLV2Port port = slv2_plugin_get_port_by_index(_plugin, index);
if (!port) {
@ -236,7 +236,6 @@ LV2Plugin::set_parameter (uint32_t which, float val)
{
if (which < slv2_plugin_get_num_ports(_plugin)) {
_shadow_data[which] = val;
ParameterChanged (which, val); /* EMIT SIGNAL */
#if 0
if (which < parameter_count() && controls[which]) {
@ -249,6 +248,8 @@ LV2Plugin::set_parameter (uint32_t which, float val)
"This is a bug in either %2 or the LV2 plugin (%3)"),
name(), PROGRAM_NAME, unique_id()) << endmsg;
}
Plugin::set_parameter (which, val);
}
float
@ -307,10 +308,9 @@ LV2Plugin::lv2_persist_retrieve_callback(void* callback_data,
return NULL;
}
XMLNode&
LV2Plugin::get_state()
void
LV2Plugin::add_state (XMLNode* root) const
{
XMLNode *root = new XMLNode(state_node_name());
XMLNode *child;
char buf[16];
LocaleGuard lg (X_("POSIX"));
@ -347,7 +347,7 @@ LV2Plugin::get_state()
warning << string_compose(
_("Plugin \"%1\% failed to return LV2 persist data"),
unique_id());
return *root; // FIXME: Possibly inconsistent state
return;
}
LV2PFile file = lv2_pfile_open(state_path.c_str(), true);
@ -356,36 +356,35 @@ LV2Plugin::get_state()
root->add_property("state-file", state_filename);
}
return *root;
}
vector<Plugin::PresetRecord>
LV2Plugin::get_presets()
void
LV2Plugin::find_presets ()
{
vector<PresetRecord> result;
SLV2Results presets = slv2_plugin_query_sparql(_plugin,
"PREFIX lv2p: <http://lv2plug.in/ns/dev/presets#>\n"
"PREFIX dc: <http://dublincore.org/documents/dcmi-namespace/>\n"
"SELECT ?p ?name WHERE { <> lv2p:hasPreset ?p . ?p dc:title ?name }\n");
for (; !slv2_results_finished(presets); slv2_results_next(presets)) {
SLV2Value uri = slv2_results_get_binding_value(presets, 0);
SLV2Value name = slv2_results_get_binding_value(presets, 1);
PresetRecord rec(slv2_value_as_string(uri), slv2_value_as_string(name));
result.push_back(rec);
_presets.insert(std::make_pair(slv2_value_as_string(uri), rec));
}
slv2_results_free(presets);
return result;
}
bool
LV2Plugin::load_preset(const string& uri)
LV2Plugin::load_preset (PresetRecord r)
{
Plugin::load_preset (r);
const string query = string(
"PREFIX lv2p: <http://lv2plug.in/ns/dev/presets#>\n"
"PREFIX dc: <http://dublincore.org/documents/dcmi-namespace/>\n"
"SELECT ?sym ?val WHERE { <") + uri + "> lv2:port ?port . "
"SELECT ?sym ?val WHERE { <") + r.uri + "> lv2:port ?port . "
" ?port lv2:symbol ?sym ; lv2p:value ?val . }";
SLV2Results values = slv2_plugin_query_sparql(_plugin, query.c_str());
for (; !slv2_results_finished(values); slv2_results_next(values)) {
@ -491,7 +490,7 @@ LV2Plugin::set_state(const XMLNode& node, int version)
latency_compute_run ();
return 0;
return Plugin::set_state (node, version);
}
int

View File

@ -62,13 +62,13 @@ using namespace std;
using namespace ARDOUR;
using namespace PBD;
PBD::Signal0<bool> Plugin::PresetFileExists;
Plugin::Plugin (AudioEngine& e, Session& s)
: _engine (e)
, _session (s)
, _cycles (0)
, _have_presets (false)
, _have_pending_stop_events (false)
, _parameter_changed_since_last_preset (false)
{
}
@ -79,7 +79,9 @@ Plugin::Plugin (const Plugin& other)
, _session (other._session)
, _info (other._info)
, _cycles (0)
, _have_presets (false)
, _have_pending_stop_events (false)
, _parameter_changed_since_last_preset (false)
{
}
@ -94,10 +96,14 @@ Plugin::remove_preset (string name)
{
do_remove_preset (name);
_presets.erase (preset_by_label (name)->uri);
_last_preset.uri = "";
_parameter_changed_since_last_preset = false;
PresetRemoved (); /* EMIT SIGNAL */
}
bool
/** @return PresetRecord with empty URI on failure */
Plugin::PresetRecord
Plugin::save_preset (string name)
{
string const uri = do_save_preset (name);
@ -106,8 +112,8 @@ Plugin::save_preset (string name)
_presets.insert (make_pair (uri, PresetRecord (uri, name)));
PresetAdded (); /* EMIT SIGNAL */
}
return !uri.empty ();
return PresetRecord (uri, name);
}
PluginPtr
@ -243,3 +249,72 @@ Plugin::realtime_handle_transport_stopped ()
_tracker.resolve_notes (_pending_stop_events.get_midi (0), 0);
_have_pending_stop_events = true;
}
vector<Plugin::PresetRecord>
Plugin::get_presets ()
{
if (!_have_presets) {
find_presets ();
_have_presets = true;
}
vector<PresetRecord> p;
for (map<string, PresetRecord>::const_iterator i = _presets.begin(); i != _presets.end(); ++i) {
p.push_back (i->second);
}
return p;
}
/** Set parameters using a preset */
bool
Plugin::load_preset (PresetRecord r)
{
_last_preset = r;
_parameter_changed_since_last_preset = false;
PresetLoaded (); /* EMIT SIGNAL */
return true;
}
void
Plugin::set_parameter (uint32_t which, float val)
{
_parameter_changed_since_last_preset = true;
ParameterChanged (Evoral::Parameter (PluginAutomation, 0, which), val); /* EMIT SIGNAL */
}
int
Plugin::set_state (const XMLNode& node, int version)
{
XMLProperty const * p = node.property (X_("last-preset-uri"));
if (p) {
_last_preset.uri = p->value ();
}
p = node.property (X_("last-preset-label"));
if (p) {
_last_preset.label = p->value ();
}
p = node.property (X_("parameter-changed-since-last-preset"));
if (p) {
_parameter_changed_since_last_preset = string_is_affirmative (p->value ());
}
return 0;
}
XMLNode &
Plugin::get_state ()
{
XMLNode* root = new XMLNode (state_node_name ());
LocaleGuard lg (X_("POSIX"));
root->add_property (X_("last-preset-uri"), _last_preset.uri);
root->add_property (X_("last-preset-label"), _last_preset.label);
root->add_property (X_("parameter-changed-since-last-preset"), _parameter_changed_since_last_preset ? X_("yes") : X_("no"));
add_state (root);
return *root;
}

View File

@ -70,8 +70,8 @@ long Session::vst_callback (AEffect* effect,
case audioMasterAutomate:
SHOW_CALLBACK ("amc: audioMasterAutomate\n");
// index, value, returns 0
if (effect) {
effect->setParameter (effect, index, opt);
if (plug) {
plug->set_parameter (index, opt);
}
return 0;

View File

@ -125,7 +125,15 @@ void
VSTPlugin::set_parameter (uint32_t which, float val)
{
_plugin->setParameter (_plugin, which, val);
//ParameterChanged (which, val); /* EMIT SIGNAL */
if (_fst->want_program == -1 && _fst->want_chunk == 0) {
/* Heinous hack: Plugin::set_parameter below updates the `modified' status of the
current preset, but if _fst->want_program is not -1 then there is a preset
setup pending or in progress, which we don't want any `modified' updates
to happen for. So we only do this if _fst->want_program is -1.
*/
Plugin::set_parameter (which, val);
}
}
float
@ -147,7 +155,7 @@ VSTPlugin::nth_parameter (uint32_t n, bool& ok) const
* @return 0-terminated base64-encoded data; must be passed to g_free () by caller.
*/
gchar *
VSTPlugin::get_chunk (bool single)
VSTPlugin::get_chunk (bool single) const
{
guchar* data;
int32_t data_size = _plugin->dispatcher (_plugin, 23 /* effGetChunk */, single ? 1 : 0, 0, &data, 0);
@ -173,10 +181,9 @@ VSTPlugin::set_chunk (gchar const * data, bool single)
return r;
}
XMLNode&
VSTPlugin::get_state()
void
VSTPlugin::add_state (XMLNode* root) const
{
XMLNode *root = new XMLNode (state_node_name());
LocaleGuard lg (X_("POSIX"));
if (_fst->current_program != -1) {
@ -189,7 +196,7 @@ VSTPlugin::get_state()
gchar* data = get_chunk (false);
if (data == 0) {
return *root;
return;
}
/* store information */
@ -215,12 +222,10 @@ VSTPlugin::get_state()
root->add_child_nocopy (*parameters);
}
return *root;
}
int
VSTPlugin::set_state(const XMLNode& node, int)
VSTPlugin::set_state (const XMLNode& node, int version)
{
LocaleGuard lg (X_("POSIX"));
@ -275,6 +280,7 @@ VSTPlugin::set_state(const XMLNode& node, int)
}
Plugin::set_state (node, version);
return ret;
}
@ -353,15 +359,54 @@ VSTPlugin::get_parameter_descriptor (uint32_t which, ParameterDescriptor& desc)
}
bool
VSTPlugin::load_preset (const string& name)
VSTPlugin::load_preset (PresetRecord r)
{
bool s;
if (r.user) {
s = load_user_preset (r);
} else {
s = load_plugin_preset (r);
}
if (s) {
Plugin::load_preset (r);
}
return s;
}
bool
VSTPlugin::load_plugin_preset (PresetRecord r)
{
/* This is a plugin-provided preset.
We can't dispatch directly here; too many plugins expects only one GUI thread.
*/
/* Extract the index of this preset from the URI */
int id;
int index;
int const p = sscanf (r.uri.c_str(), "VST:%d:%d", &id, &index);
assert (p == 2);
_fst->want_program = index;
return true;
}
bool
VSTPlugin::load_user_preset (PresetRecord r)
{
/* This is a user preset; we load it, and this code also knows about the
non-direct-dispatch thing.
*/
boost::shared_ptr<XMLTree> t (presets_tree ());
if (t == 0) {
return false;
}
XMLNode* root = t->root ();
for (XMLNodeList::const_iterator i = root->children().begin(); i != root->children().end(); ++i) {
XMLProperty* uri = (*i)->property (X_("uri"));
@ -369,11 +414,11 @@ VSTPlugin::load_preset (const string& name)
assert (uri);
assert (label);
if (label->value() != name) {
if (label->value() != r.label) {
continue;
}
if (_plugin->flags & 32 /* effFlagsProgramsChunks */) {
/* Load a user preset chunk from our XML file and send it via a circuitous route to the plugin */
@ -395,26 +440,26 @@ VSTPlugin::load_preset (const string& name)
}
return false;
} else {
for (XMLNodeList::const_iterator j = (*i)->children().begin(); j != (*i)->children().end(); ++j) {
if ((*j)->name() == X_("Parameter")) {
XMLProperty* index = (*j)->property (X_("index"));
XMLProperty* value = (*j)->property (X_("value"));
assert (index);
assert (value);
set_parameter (atoi (index->value().c_str()), atof (value->value().c_str ()));
XMLProperty* index = (*j)->property (X_("index"));
XMLProperty* value = (*j)->property (X_("value"));
assert (index);
assert (value);
set_parameter (atoi (index->value().c_str()), atof (value->value().c_str ()));
}
}
return true;
}
}
return false;
}
@ -556,7 +601,6 @@ VSTPlugin::connect_and_run (BufferSet& bufs,
}
/* we already know it can support processReplacing */
_plugin->processReplacing (_plugin, ins, outs, nframes);
return 0;
@ -670,16 +714,14 @@ VSTPluginInfo::load (Session& session)
}
}
vector<Plugin::PresetRecord>
VSTPlugin::get_presets ()
void
VSTPlugin::find_presets ()
{
vector<PresetRecord> p;
/* Built-in presets */
int const vst_version = _plugin->dispatcher (_plugin, effGetVstVersion, 0, 0, NULL, 0);
for (int i = 0; i < _plugin->numPrograms; ++i) {
PresetRecord r (string_compose (X_("VST:%1:%2"), unique_id (), i), "");
PresetRecord r (string_compose (X_("VST:%1:%2"), unique_id (), i), "", false);
if (vst_version >= 2) {
char buf[256];
@ -692,7 +734,6 @@ VSTPlugin::get_presets ()
r.label = string_compose (_("Preset %1"), i);
}
p.push_back (r);
_presets.insert (make_pair (r.uri, r));
}
@ -710,13 +751,11 @@ VSTPlugin::get_presets ()
assert (uri);
assert (label);
PresetRecord r (uri->value(), label->value());
p.push_back (r);
PresetRecord r (uri->value(), label->value(), true);
_presets.insert (make_pair (r.uri, r));
}
}
return p;
}
/** @return XMLTree with our user presets; could be a new one if no existing