Save references to external files in LV2 state as symbolic links.
With this commit it is possible to archive sessions that contain plugins with complex file-containing state (e.g. Linuxsampler with a sample bank loaded) with any archive tool, e.g.: tar -hjcf session.tar.bz2 session Which will give you a fully self-contained archive of everything used in the session, so you can e.g. send it to a collaborator who may not have the same sample banks in the same place as you and it will work. git-svn-id: svn://localhost/ardour2/branches/3.0@10817 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
5aec659c60
commit
0bd3105f50
@ -150,6 +150,8 @@ class LV2Plugin : public ARDOUR::Plugin
|
||||
static uint32_t _midi_event_type;
|
||||
static uint32_t _state_path_type;
|
||||
|
||||
const std::string state_dir () const;
|
||||
|
||||
static int
|
||||
lv2_state_store_callback (void* handle,
|
||||
uint32_t key,
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include <cstring>
|
||||
|
||||
#include <glibmm.h>
|
||||
#include <giomm/file.h>
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
|
||||
@ -454,6 +455,13 @@ LV2Plugin::c_ui_type ()
|
||||
return (void*)_impl->ui_type;
|
||||
}
|
||||
|
||||
const std::string
|
||||
LV2Plugin::state_dir() const
|
||||
{
|
||||
return Glib::build_filename(_session.plugins_dir(),
|
||||
_insert_id.to_s());
|
||||
}
|
||||
|
||||
int
|
||||
LV2Plugin::lv2_state_store_callback(LV2_State_Handle handle,
|
||||
uint32_t key,
|
||||
@ -527,13 +535,17 @@ LV2Plugin::lv2_state_abstract_path(LV2_State_Map_Path_Handle handle,
|
||||
return g_strdup(absolute_path);
|
||||
}
|
||||
|
||||
const std::string state_dir = Glib::build_filename(me->_session.plugins_dir(),
|
||||
me->_insert_id.to_s());
|
||||
const std::string state_dir = me->state_dir();
|
||||
|
||||
char* ret = NULL;
|
||||
if (strncmp(absolute_path, state_dir.c_str(), state_dir.length())) {
|
||||
ret = g_strdup(absolute_path);
|
||||
// Path outside state directory, make symbolic link
|
||||
const std::string name = Glib::path_get_basename(absolute_path);
|
||||
const std::string path = Glib::build_filename(state_dir, name);
|
||||
Gio::File::create_for_path(path)->make_symbolic_link(absolute_path);
|
||||
ret = g_strndup(path.c_str(), path.length());
|
||||
} else {
|
||||
// Path inside the state directory, return relative path
|
||||
const std::string path(absolute_path + state_dir.length() + 1);
|
||||
ret = g_strndup(path.c_str(), path.length());
|
||||
}
|
||||
@ -558,10 +570,7 @@ LV2Plugin::lv2_state_absolute_path(LV2_State_Map_Path_Handle handle,
|
||||
ret = g_strdup(abstract_path);
|
||||
} else {
|
||||
const std::string apath(abstract_path);
|
||||
const std::string state_dir = Glib::build_filename(me->_session.plugins_dir(),
|
||||
me->_insert_id.to_s());
|
||||
const std::string path = Glib::build_filename(state_dir,
|
||||
apath);
|
||||
const std::string path = Glib::build_filename(me->state_dir(), apath);
|
||||
ret = g_strndup(path.c_str(), path.length());
|
||||
}
|
||||
|
||||
@ -580,13 +589,9 @@ LV2Plugin::lv2_state_make_path(LV2_State_Make_Path_Handle handle,
|
||||
return g_strdup(path);
|
||||
}
|
||||
|
||||
const std::string abs_path = Glib::build_filename(
|
||||
Glib::build_filename(
|
||||
me->_session.plugins_dir(),
|
||||
me->_insert_id.to_s()),
|
||||
path);
|
||||
const std::string abs_path = Glib::build_filename(me->state_dir(), path);
|
||||
const std::string dirname = Glib::path_get_dirname(abs_path);
|
||||
|
||||
const std::string dirname = Glib::path_get_dirname(abs_path);
|
||||
g_mkdir_with_parents(dirname.c_str(), 0744);
|
||||
|
||||
DEBUG_TRACE(DEBUG::LV2, string_compose("new file path %1 => %2\n",
|
||||
@ -595,6 +600,26 @@ LV2Plugin::lv2_state_make_path(LV2_State_Make_Path_Handle handle,
|
||||
return g_strndup(abs_path.c_str(), abs_path.length());
|
||||
}
|
||||
|
||||
static void
|
||||
remove_directory(const std::string& path)
|
||||
{
|
||||
if (!Glib::file_test(path, Glib::FILE_TEST_IS_DIR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Glib::RefPtr<Gio::File> dir = Gio::File::create_for_path(path);
|
||||
Glib::RefPtr<Gio::FileEnumerator> e = dir->enumerate_children();
|
||||
Glib::RefPtr<Gio::FileInfo> fi;
|
||||
while ((fi = e->next_file())) {
|
||||
if (fi->get_type() == Gio::FILE_TYPE_DIRECTORY) {
|
||||
remove_directory(fi->get_name());
|
||||
} else {
|
||||
dir->get_child(fi->get_name())->remove();
|
||||
}
|
||||
}
|
||||
dir->remove();
|
||||
}
|
||||
|
||||
void
|
||||
LV2Plugin::add_state(XMLNode* root) const
|
||||
{
|
||||
@ -633,6 +658,9 @@ LV2Plugin::add_state(XMLNode* root) const
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove old state directory (FIXME: should this be preserved?)
|
||||
remove_directory(state_dir());
|
||||
|
||||
// Save plugin state to state object
|
||||
LV2State state(*this, _uri_map);
|
||||
state_iface->save(_impl->instance->lv2_handle,
|
||||
|
Loading…
Reference in New Issue
Block a user