13
0

Stub implementation of LV2 persist extension.

git-svn-id: svn://localhost/ardour2/branches/3.0@8087 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
David Robillard 2010-11-25 22:12:03 +00:00
parent 8b68ed57ec
commit 2a6dcddcc5
6 changed files with 140 additions and 77 deletions

View File

@ -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;

View File

@ -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);
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
*/
/* 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

View File

@ -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

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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>