summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
authorCarl Hetherington <carl@carlh.net>2010-12-19 23:11:01 +0000
committerCarl Hetherington <carl@carlh.net>2010-12-19 23:11:01 +0000
commit5f4bdb233a53932986e07fca1cd6c87d22c2886f (patch)
treec9c980115453452dc21931d4337ab1b592f80d95 /libs/ardour
parentbb7dbe6d86e08ea0fedf12ce50ca3d395aa212a5 (diff)
Clean up plugin preset handling a bit.
git-svn-id: svn://localhost/ardour2/branches/3.0@8301 d708f5d6-7413-0410-9779-e7cbd77b26cf
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/audio_unit.h5
-rw-r--r--libs/ardour/ardour/ladspa_plugin.h7
-rw-r--r--libs/ardour/ardour/lv2_plugin.h9
-rw-r--r--libs/ardour/ardour/plugin.h60
-rw-r--r--libs/ardour/ardour/vst_plugin.h10
-rw-r--r--libs/ardour/audio_unit.cc84
-rw-r--r--libs/ardour/ladspa_plugin.cc35
-rw-r--r--libs/ardour/lv2_plugin.cc31
-rw-r--r--libs/ardour/plugin.cc85
-rw-r--r--libs/ardour/session_vst.cc4
-rw-r--r--libs/ardour/vst_plugin.cc109
11 files changed, 289 insertions, 150 deletions
diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h
index b00c23b1dc..abbfdbea3d 100644
--- a/libs/ardour/ardour/audio_unit.h
+++ b/libs/ardour/ardour/audio_unit.h
@@ -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;
diff --git a/libs/ardour/ardour/ladspa_plugin.h b/libs/ardour/ardour/ladspa_plugin.h
index 7d561dd0a8..457921cf36 100644
--- a/libs/ardour/ardour/ladspa_plugin.h
+++ b/libs/ardour/ardour/ladspa_plugin.h
@@ -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 {
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h
index c2b9ebc7bb..0920a01e6d 100644
--- a/libs/ardour/ardour/lv2_plugin.h
+++ b/libs/ardour/ardour/lv2_plugin.h
@@ -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;
};
diff --git a/libs/ardour/ardour/plugin.h b/libs/ardour/ardour/plugin.h
index ad002a926d..00ed6bdc94 100644
--- a/libs/ardour/ardour/plugin.h
+++ b/libs/ardour/ardour/plugin.h
@@ -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;
+
+ virtual bool has_editor () const = 0;
- PBD::Signal2<void,uint32_t,float> ParameterChanged;
+ /** 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);
diff --git a/libs/ardour/ardour/vst_plugin.h b/libs/ardour/ardour/vst_plugin.h
index e9a2c4abdf..83bf58c4ac 100644
--- a/libs/ardour/ardour/vst_plugin.h
+++ b/libs/ardour/ardour/vst_plugin.h
@@ -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;
diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc
index 2e47a0bd48..54342c7f91 100644
--- a/libs/ardour/audio_unit.cc
+++ b/libs/ardour/audio_unit.cc
@@ -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
diff --git a/libs/ardour/ladspa_plugin.cc b/libs/ardour/ladspa_plugin.cc
index 43fa8e43ee..cab21f46f9 100644
--- a/libs/ardour/ladspa_plugin.cc
+++ b/libs/ardour/ladspa_plugin.cc
@@ -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;
}
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index d8daca9f64..dd36d134f5 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -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
diff --git a/libs/ardour/plugin.cc b/libs/ardour/plugin.cc
index 1a711b5250..3ba0f8ddec 100644
--- a/libs/ardour/plugin.cc
+++ b/libs/ardour/plugin.cc
@@ -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;
+}
diff --git a/libs/ardour/session_vst.cc b/libs/ardour/session_vst.cc
index 85b5f13c4c..2aa873c6e6 100644
--- a/libs/ardour/session_vst.cc
+++ b/libs/ardour/session_vst.cc
@@ -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;
diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc
index 1f3cc95c27..92aac83beb 100644
--- a/libs/ardour/vst_plugin.cc
+++ b/libs/ardour/vst_plugin.cc
@@ -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