summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2010-11-25 22:12:03 +0000
committerDavid Robillard <d@drobilla.net>2010-11-25 22:12:03 +0000
commit2a6dcddcc513fa3ebc1aad4b2e5fede62277aba5 (patch)
treee3fcc56e80126df2b03d5e55897aa50a8dc322be
parent8b68ed57ec5c075261639435be3290c3ba8177eb (diff)
Stub implementation of LV2 persist extension.
git-svn-id: svn://localhost/ardour2/branches/3.0@8087 d708f5d6-7413-0410-9779-e7cbd77b26cf
-rw-r--r--libs/ardour/ardour/lv2_plugin.h2
-rw-r--r--libs/ardour/ardour/session.h118
-rw-r--r--libs/ardour/ardour/uri_map.h2
-rw-r--r--libs/ardour/lv2_plugin.cc49
-rw-r--r--libs/ardour/session_state.cc13
-rw-r--r--libs/ardour/uri_map.cc35
6 files changed, 141 insertions, 78 deletions
diff --git a/libs/ardour/ardour/lv2_plugin.h b/libs/ardour/ardour/lv2_plugin.h
index 329af1151f..4335d65539 100644
--- a/libs/ardour/ardour/lv2_plugin.h
+++ b/libs/ardour/ardour/lv2_plugin.h
@@ -136,6 +136,7 @@ class LV2Plugin : public ARDOUR::Plugin
float* _defaults;
float* _latency_control_port;
bool _was_activated;
+ bool _supports_persist;
std::vector<bool> _port_is_input;
std::map<std::string,uint32_t> _port_indices;
@@ -143,6 +144,7 @@ class LV2Plugin : public ARDOUR::Plugin
LV2_DataAccess _data_access_extension_data;
LV2_Feature _data_access_feature;
LV2_Feature _instance_access_feature;
+ LV2_Feature _persist_feature;
static URIMap _uri_map;
static uint32_t _midi_event_type;
diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
index d6dab480a7..ff69a9ebdf 100644
--- a/libs/ardour/ardour/session.h
+++ b/libs/ardour/ardour/session.h
@@ -128,24 +128,24 @@ extern void setup_enum_writer ();
class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionList, public SessionEventManager
{
public:
- enum RecordState {
+ enum RecordState {
Disabled = 0,
Enabled = 1,
Recording = 2
};
- /* a new session might have non-empty mix_template, an existing session should always have an empty one.
- the bus profile can be null if no master out bus is required.
- */
+ /* a new session might have non-empty mix_template, an existing session should always have an empty one.
+ the bus profile can be null if no master out bus is required.
+ */
Session (AudioEngine&,
- const std::string& fullpath,
- const std::string& snapshot_name,
- BusProfile* bus_profile = 0,
- std::string mix_template = "");
+ const std::string& fullpath,
+ const std::string& snapshot_name,
+ BusProfile* bus_profile = 0,
+ std::string mix_template = "");
virtual ~Session ();
-
+
std::string path() const { return _path; }
std::string name() const { return _name; }
std::string snap_name() const { return _current_snapshot_name; }
@@ -175,10 +175,11 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
std::string dead_sound_dir () const;
std::string automation_dir () const;
std::string analysis_dir() const;
-
+ std::string plugins_dir() const;
+
int ensure_subdirs ();
- std::string peak_path (std::string) const;
+ std::string peak_path (std::string) const;
std::string change_source_path_by_name (std::string oldpath, std::string oldname, std::string newname, bool destructive);
@@ -233,7 +234,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
template<class T> void foreach_route (T *obj, void (T::*func)(boost::shared_ptr<Route>));
template<class T, class A> void foreach_route (T *obj, void (T::*func)(Route&, A), A arg);
- bool io_name_is_legal (const std::string&);
+ bool io_name_is_legal (const std::string&);
boost::shared_ptr<Route> route_by_name (std::string);
boost::shared_ptr<Route> route_by_id (PBD::ID);
boost::shared_ptr<Route> route_by_remote_id (uint32_t id);
@@ -282,8 +283,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
/** Emitted when anything about any of our route groups changes */
PBD::Signal0<void> RouteGroupChanged;
- /* Step Editing status changed */
- PBD::Signal1<void,bool> StepEditStatusChange;
+ /* Step Editing status changed */
+ PBD::Signal1<void,bool> StepEditStatusChange;
void queue_event (SessionEvent*);
@@ -395,7 +396,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void remove_route_group (RouteGroup&);
RouteGroup* route_group_by_name (std::string);
- RouteGroup& all_route_group() const;
+ RouteGroup& all_route_group() const;
PBD::Signal1<void,RouteGroup*> route_group_added;
PBD::Signal0<void> route_group_removed;
@@ -429,7 +430,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
/* Time */
- framepos_t transport_frame () const {return _transport_frame; }
+ framepos_t transport_frame () const {return _transport_frame; }
framepos_t audible_frame () const;
framepos_t requested_return_frame() const { return _requested_return_frame; }
@@ -468,9 +469,9 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
static PBD::Signal1<void, framepos_t> EndTimeChanged;
static PBD::Signal0<void> TimecodeOffsetChanged;
- std::vector<SyncSource> get_available_sync_options() const;
+ std::vector<SyncSource> get_available_sync_options() const;
void request_sync_source (Slave*);
- bool synced_to_jack() const { return config.get_external_sync() && config.get_sync_source() == JACK; }
+ bool synced_to_jack() const { return config.get_external_sync() && config.get_sync_source() == JACK; }
double transport_speed() const { return _transport_speed; }
bool transport_stopped() const { return _transport_speed == 0.0f; }
@@ -535,10 +536,11 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
*/
static PBD::Signal0<int> AskAboutPendingState;
- boost::shared_ptr<AudioFileSource> create_audio_source_for_session (size_t, std::string const &, uint32_t,
- bool destructive, bool as_stub = false);
-
- boost::shared_ptr<MidiSource> create_midi_source_for_session (Track*, std::string const &, bool as_stub = false);
+ boost::shared_ptr<AudioFileSource> create_audio_source_for_session (
+ size_t, std::string const &, uint32_t, bool destructive, bool as_stub = false);
+
+ boost::shared_ptr<MidiSource> create_midi_source_for_session (
+ Track*, std::string const &, bool as_stub = false);
boost::shared_ptr<Source> source_by_id (const PBD::ID&);
boost::shared_ptr<Source> source_by_path_and_channel (const std::string&, uint16_t);
@@ -586,7 +588,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
bool soloing() const { return _non_soloed_outs_muted; }
bool listening() const { return _listen_cnt > 0; }
- bool solo_isolated() const { return _solo_isolated_cnt > 0; }
+ bool solo_isolated() const { return _solo_isolated_cnt > 0; }
static const SessionEvent::RTeventCallback rt_cleanup;
@@ -595,11 +597,11 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void set_mute (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
void set_listen (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
void set_record_enabled (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
- void set_solo_isolated (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
+ void set_solo_isolated (boost::shared_ptr<RouteList>, bool, SessionEvent::RTeventCallback after = rt_cleanup, bool group_override = false);
PBD::Signal1<void,bool> SoloActive;
PBD::Signal0<void> SoloChanged;
- PBD::Signal0<void> IsolatedChanged;
+ PBD::Signal0<void> IsolatedChanged;
/* control/master out */
@@ -724,9 +726,9 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
static PBD::Signal0<void> SendFeedback;
- /* Speakers */
+ /* Speakers */
- VBAPSpeakers& get_speakers ();
+ VBAPSpeakers& get_speakers ();
/* Controllables */
@@ -785,24 +787,24 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
PBD::Signal0<void> RouteOrderKeyChanged;
- bool step_editing() const { return (_step_editors > 0); }
+ bool step_editing() const { return (_step_editors > 0); }
void request_suspend_timecode_transmission ();
void request_resume_timecode_transmission ();
bool timecode_transmission_suspended () const;
- std::string source_search_path(DataType) const;
- void ensure_search_path_includes (const std::string& path, DataType type);
-
- /* handlers can return an integer value:
- 0: config.set_audio_search_path() or config.set_midi_search_path() was used
- to modify the search path and we should try to find it again.
- 1: quit entire session load
- 2: as 0, but don't ask about other missing files
- 3: don't ask about other missing files, and just mark this one missing
- -1: just mark this one missing
- any other value: as -1
- */
+ std::string source_search_path(DataType) const;
+ void ensure_search_path_includes (const std::string& path, DataType type);
+
+ /* handlers can return an integer value:
+ 0: config.set_audio_search_path() or config.set_midi_search_path() was used
+ to modify the search path and we should try to find it again.
+ 1: quit entire session load
+ 2: as 0, but don't ask about other missing files
+ 3: don't ask about other missing files, and just mark this one missing
+ -1: just mark this one missing
+ any other value: as -1
+ */
static PBD::Signal3<int,Session*,std::string,DataType> MissingFile;
/** Emitted when the session wants Ardour to quit */
@@ -893,8 +895,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void unblock_processing() { g_atomic_int_set (&processing_prohibited, 0); }
bool processing_blocked() const { return g_atomic_int_get (&processing_prohibited); }
- Glib::Mutex process_thread_lock;
- std::list<ProcessThread*> process_threads;
+ Glib::Mutex process_thread_lock;
+ std::list<ProcessThread*> process_threads;
/* slave tracking */
@@ -914,11 +916,11 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void track_slave_state(float slave_speed, nframes_t slave_transport_frame, nframes_t this_delta);
void follow_slave_silently(nframes_t nframes, float slave_speed);
- void switch_to_sync_source (SyncSource); /* !RT context */
- void drop_sync_source (); /* !RT context */
- void use_sync_source (Slave*); /* RT context */
+ void switch_to_sync_source (SyncSource); /* !RT context */
+ void drop_sync_source (); /* !RT context */
+ void use_sync_source (Slave*); /* RT context */
- bool post_export_sync;
+ bool post_export_sync;
nframes_t post_export_position;
bool _exporting;
@@ -967,7 +969,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
std::string _path;
std::string _name;
- bool _is_new;
+ bool _is_new;
bool session_send_mtc;
bool session_midi_feedback;
bool play_loop;
@@ -1039,8 +1041,8 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void set_post_transport_work (PostTransportWork ptw) { g_atomic_int_set (&_post_transport_work, (gint) ptw); }
void add_post_transport_work (PostTransportWork ptw);
- void schedule_playback_buffering_adjustment ();
- void schedule_capture_buffering_adjustment ();
+ void schedule_playback_buffering_adjustment ();
+ void schedule_capture_buffering_adjustment ();
uint32_t cumulative_rf_motion;
uint32_t rf_scale;
@@ -1170,11 +1172,11 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void overwrite_some_buffers (Track *);
void flush_all_inserts ();
int micro_locate (nframes_t distance);
- void locate (framepos_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false, bool with_mmc=true);
- void start_locate (framepos_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false);
+ void locate (framepos_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false, bool with_mmc=true);
+ void start_locate (framepos_t, bool with_roll, bool with_flush, bool with_loop=false, bool force=false);
void force_locate (framepos_t frame, bool with_roll = false);
void set_track_speed (Track *, double speed);
- void set_transport_speed (double speed, bool abort = false, bool clear_state = false);
+ void set_transport_speed (double speed, bool abort = false, bool clear_state = false);
void stop_transport (bool abort = false, bool clear_state = false);
void start_transport ();
void realtime_stop (bool abort, bool clear_state);
@@ -1195,7 +1197,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
int load_route_groups (const XMLNode&, int);
std::list<RouteGroup *> _route_groups;
- RouteGroup* _all_route_group;
+ RouteGroup* _all_route_group;
/* routes stuff */
@@ -1330,7 +1332,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
uint32_t _total_free_4k_blocks;
Glib::Mutex space_lock;
- bool no_questions_about_missing_files;
+ bool no_questions_about_missing_files;
std::string get_best_session_directory_for_new_source ();
@@ -1453,12 +1455,12 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void add_session_range_location (nframes_t, nframes_t);
void setup_midi_machine_control ();
- void cleanup_stubfiles ();
+ void cleanup_stubfiles ();
void route_order_key_changed ();
- void step_edit_status_change (bool);
- uint32_t _step_editors;
+ void step_edit_status_change (bool);
+ uint32_t _step_editors;
/** true if timecode transmission by the transport is suspended, otherwise false */
mutable gint _suspend_timecode_transmission;
@@ -1468,7 +1470,7 @@ class Session : public PBD::StatefulDestructible, public PBD::ScopedConnectionLi
void start_time_changed (framepos_t);
void end_time_changed (framepos_t);
- VBAPSpeakers* _speakers;
+ VBAPSpeakers* _speakers;
};
} // namespace ARDOUR
diff --git a/libs/ardour/ardour/uri_map.h b/libs/ardour/ardour/uri_map.h
index c62ec6bfc4..59de9b3dfd 100644
--- a/libs/ardour/ardour/uri_map.h
+++ b/libs/ardour/ardour/uri_map.h
@@ -1,6 +1,6 @@
/*
Copyright (C) 2009 Paul Davis
- Author: Dave Robillard
+ Author: David Robillard
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index b6349d012f..0bee37d2be 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -25,6 +25,8 @@
#include <cmath>
#include <cstring>
+#include <glibmm.h>
+
#include "pbd/compose.h"
#include "pbd/error.h"
#include "pbd/pathscanner.h"
@@ -42,6 +44,8 @@
#include "i18n.h"
#include <locale.h>
+#include "lv2ext/lv2_persist.h"
+
using namespace std;
using namespace ARDOUR;
using namespace PBD;
@@ -83,14 +87,21 @@ LV2Plugin::init (LV2World& world, SLV2Plugin plugin, nframes_t rate)
_latency_control_port = 0;
_was_activated = false;
+ SLV2Value persist_uri = slv2_value_new_uri(_world.world, "http://lv2plug.in/ns/ext/persist");
+ _supports_persist = slv2_plugin_has_feature(plugin, persist_uri);
+ slv2_value_free(persist_uri);
+
_instance_access_feature.URI = "http://lv2plug.in/ns/ext/instance-access";
_data_access_feature.URI = "http://lv2plug.in/ns/ext/data-access";
+ _persist_feature.URI = "http://lv2plug.in/ns/ext/persist";
+ _persist_feature.data = NULL;
- _features = (LV2_Feature**)malloc(sizeof(LV2_Feature*) * 4);
+ _features = (LV2_Feature**)malloc(sizeof(LV2_Feature*) * 5);
_features[0] = &_instance_access_feature;
_features[1] = &_data_access_feature;
- _features[2] = _uri_map.feature();
- _features[3] = NULL;
+ _features[2] = &_persist_feature;
+ _features[3] = _uri_map.feature();
+ _features[4] = NULL;
_instance = slv2_plugin_instantiate(plugin, rate, _features);
_name = slv2_plugin_get_name(plugin);
@@ -271,6 +282,19 @@ LV2Plugin::nth_parameter (uint32_t n, bool& ok) const
return 0;
}
+struct LV2Value { void* value; uint32_t type; };
+typedef std::map< std::string, LV2Value > LV2State;
+
+static void
+lv2_persist_store_callback(void* callback_data,
+ const char* key,
+ const void* value,
+ size_t size,
+ uint32_t type)
+{
+ cout << "LV2 PERSIST STORE " << key << " = " << value << " :: " << type << endl;
+}
+
XMLNode&
LV2Plugin::get_state()
{
@@ -296,6 +320,25 @@ LV2Plugin::get_state()
}
}
+ if (_supports_persist) {
+ // Create state directory for this plugin instance
+ const std::string state_path = Glib::build_filename(_session.plugins_dir(), _id.to_s());
+ cout << "LV2 plugin state path " << state_path << endl;
+
+ // Get LV2 Persist extension data from plugin instance
+ LV2_Persist* persist = (LV2_Persist*)slv2_instance_get_extension_data(
+ _instance, "http://lv2plug.in/ns/ext/persist");
+ if (!persist) {
+ warning << string_compose(
+ _("Plugin \"%1\% failed to return LV2 persist data"),
+ unique_id());
+ return *root; // FIXME: Possibly inconsistent state
+ }
+
+ LV2State state;
+ persist->save(_instance, lv2_persist_store_callback, &state);
+ }
+
return *root;
}
diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
index cdb1af9596..6ceeeb599c 100644
--- a/libs/ardour/session_state.cc
+++ b/libs/ardour/session_state.cc
@@ -500,6 +500,13 @@ Session::ensure_subdirs ()
return -1;
}
+ dir = plugins_dir ();
+
+ if (g_mkdir_with_parents (dir.c_str(), 0755) < 0) {
+ error << string_compose(_("Session: cannot create session plugins folder \"%1\" (%2)"), dir, strerror (errno)) << endmsg;
+ return -1;
+ }
+
return 0;
}
@@ -2177,6 +2184,12 @@ Session::analysis_dir () const
return Glib::build_filename (_path, "analysis");
}
+string
+Session::plugins_dir () const
+{
+ return Glib::build_filename (_path, "plugins");
+}
+
int
Session::load_bundles (XMLNode const & node)
{
diff --git a/libs/ardour/uri_map.cc b/libs/ardour/uri_map.cc
index 2c2861e385..a551a5b5a4 100644
--- a/libs/ardour/uri_map.cc
+++ b/libs/ardour/uri_map.cc
@@ -1,19 +1,22 @@
-/* This file is part of Ingen.
- * Copyright (C) 2008 Dave Robillard <http://drobilla.net>
- *
- * Ingen is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option) any later
- * version.
- *
- * Ingen is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
- * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
+/*
+ Copyright (C) 2008-2010 Paul Davis
+ Author: David Robillard
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
#include <cassert>
#include <iostream>