diff options
author | Carl Hetherington <carl@carlh.net> | 2010-12-19 23:11:01 +0000 |
---|---|---|
committer | Carl Hetherington <carl@carlh.net> | 2010-12-19 23:11:01 +0000 |
commit | 5f4bdb233a53932986e07fca1cd6c87d22c2886f (patch) | |
tree | c9c980115453452dc21931d4337ab1b592f80d95 /libs/ardour | |
parent | bb7dbe6d86e08ea0fedf12ce50ca3d395aa212a5 (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.h | 5 | ||||
-rw-r--r-- | libs/ardour/ardour/ladspa_plugin.h | 7 | ||||
-rw-r--r-- | libs/ardour/ardour/lv2_plugin.h | 9 | ||||
-rw-r--r-- | libs/ardour/ardour/plugin.h | 60 | ||||
-rw-r--r-- | libs/ardour/ardour/vst_plugin.h | 10 | ||||
-rw-r--r-- | libs/ardour/audio_unit.cc | 84 | ||||
-rw-r--r-- | libs/ardour/ladspa_plugin.cc | 35 | ||||
-rw-r--r-- | libs/ardour/lv2_plugin.cc | 31 | ||||
-rw-r--r-- | libs/ardour/plugin.cc | 85 | ||||
-rw-r--r-- | libs/ardour/session_vst.cc | 4 | ||||
-rw-r--r-- | libs/ardour/vst_plugin.cc | 109 |
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 |