On 05/04/11 10:36 AM, David Robillard wrote:
On 03/04/11 03:29 AM, Christian Schoenebeck wrote:
[snip]
These extensions are still provisional, feedback on them is welcome
(when they are implemented in at least one other plugin and host (I'll
probably do QTractor) and any issues people bring up have been
addressed, then they will become stable/released).
We just checked it. The extensions and your LinuxSampler patch look fine to us.
Good job! But we like to wait for applying your patch until QTractor also
supports those new LV2 extensions. Is that OK for you David?
Great.
Sure, that makes sense. AFAIK there are no other implementations yet, so
once qtractor is done everyone is on the same page.
Updated version of the LS patch attached (I split the "refer to files in
state" and "create new files" features in the files extension). Matches
latest Ardour3.
QSampler is close, working on polishing its implementation up...
Cheers,
-dr
Index: AUTHORS
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/AUTHORS,v
retrieving revision 1.8
diff -u -r1.8 AUTHORS
--- AUTHORS 31 Jul 2009 07:45:47 -0000 1.8
+++ AUTHORS 6 Apr 2011 00:14:17 -0000
@@ -46,3 +46,4 @@
Andrew Williams
Devin Anderson
Chris Cherrett
+ David Robillard
Index: src/drivers/Plugin.cpp
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/drivers/Plugin.cpp,v
retrieving revision 1.11
diff -u -r1.11 Plugin.cpp
--- src/drivers/Plugin.cpp 20 Feb 2011 14:20:21 -0000 1.11
+++ src/drivers/Plugin.cpp 6 Apr 2011 00:14:17 -0000
@@ -173,6 +173,20 @@
}
/*
+ These methods can be overloaded by different plugin types to map
+ file names to/from file names to be used in the state text, making
+ it possible for state to be self-contained and/or movable.
+ */
+
+ String Plugin::PathToState(const String& string) {
+ return string;
+ }
+
+ String Plugin::PathFromState(const String& string) {
+ return string;
+ }
+
+ /*
The sampler state is stored in a text base format, designed to
be easy to parse with the istream >> operator. Values are
separated by spaces or newlines. All string values that may
@@ -218,7 +232,7 @@
int(iter->first.midi_bank_lsb)) << ' ' <<
int(iter->first.midi_prog) << ' ' <<
iter->second.EngineName << ' ' <<
- iter->second.InstrumentFile << '\n' <<
+ PathToState(iter->second.InstrumentFile) << '\n' <<
MIDIMAPPING << ' ' <<
iter->second.InstrumentIndex << ' ' <<
iter->second.Volume << ' ' <<
@@ -240,7 +254,7 @@
String filename = engine_channel->InstrumentFileName();
s << channel->GetMidiInputChannel() << ' ' <<
engine_channel->Volume() << ' ' <<
- filename << '\n' <<
+ PathToState(filename) << '\n' <<
engine_channel->InstrumentIndex() << ' ' <<
engine_channel->GetSolo() << ' ' <<
(engine_channel->GetMute() == 1) << ' ' <<
@@ -336,7 +350,7 @@
}
if (!filename.empty() && index != -1) {
InstrumentManager::instrument_id_t id;
- id.FileName = filename;
+ id.FileName = PathFromState(filename);
id.Index = index;
InstrumentManager::LoadInstrumentInBackground(id, engine_channel);
}
Index: src/drivers/Plugin.h
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/drivers/Plugin.h,v
retrieving revision 1.4
diff -u -r1.4 Plugin.h
--- src/drivers/Plugin.h 28 Aug 2009 07:48:46 -0000 1.4
+++ src/drivers/Plugin.h 6 Apr 2011 00:14:17 -0000
@@ -69,6 +69,9 @@
void PreInit();
void Init(int SampleRate, int FragmentSize, int Channels = -1);
+ virtual String PathToState(const String& string);
+ virtual String PathFromState(const String& string);
+
void InitState();
String GetState();
bool SetState(String State);
Index: src/hostplugins/lv2/PluginLv2.cpp
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/hostplugins/lv2/PluginLv2.cpp,v
retrieving revision 1.1
diff -u -r1.1 PluginLv2.cpp
--- src/hostplugins/lv2/PluginLv2.cpp 15 Sep 2008 16:58:10 -0000 1.1
+++ src/hostplugins/lv2/PluginLv2.cpp 6 Apr 2011 00:14:17 -0000
@@ -19,6 +19,7 @@
***************************************************************************/
#include <algorithm>
+#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
@@ -34,8 +35,18 @@
const LV2_Feature* const* Features) {
Out[0] = 0;
Out[1] = 0;
+ UriMap = 0;
+ PathSupport = 0;
+ NewFileSupport = 0;
for (int i = 0 ; Features[i] ; i++) {
dmsg(2, ("linuxsampler: host feature: %s\n", Features[i]->URI));
+ if (!strcmp(Features[i]->URI, LV2_URI_MAP_URI)) {
+ UriMap = (LV2_URI_Map_Feature*)Features[i]->data;
+ } else if (!strcmp(Features[i]->URI, LV2_FILES_PATH_SUPPORT_URI)) {
+ PathSupport = (LV2_Files_Path_Support*)Features[i]->data;
+ } else if (!strcmp(Features[i]->URI, LV2_FILES_NEW_FILE_SUPPORT_URI)) {
+ NewFileSupport = (LV2_Files_New_File_Support*)Features[i]->data;
+ }
}
Init(SampleRate, 128);
@@ -86,44 +97,97 @@
dmsg(2, ("linuxsampler: Deactivate\n"));
}
- char* PluginLv2::Save(const char* Directory, LV2SR_File*** Files) {
- dmsg(2, ("linuxsampler: Save Directory=%s\n", Directory));
-
- String filename(Directory);
- filename += "/linuxsampler";
- dmsg(2, ("saving to %s\n", filename.c_str()));
- std::ofstream out(filename.c_str());
- out << GetState();
- out.close();
-
- LV2SR_File** filearr = static_cast<LV2SR_File**>(malloc(sizeof(LV2SR_File*) * 2));
-
- LV2SR_File* file = static_cast<LV2SR_File*>(malloc(sizeof(LV2SR_File)));
- file->name = strdup("linuxsampler");
- file->path = strdup(filename.c_str());
- file->must_copy = 0;
-
- filearr[0] = file;
- filearr[1] = 0;
+ String PluginLv2::PathToState(const String& path) {
+ if (PathSupport) {
+ char* cstr = PathSupport->abstract_path(PathSupport->host_data,
+ path.c_str());
+ const String abstract_path(cstr);
+ free(cstr);
+ return abstract_path;
+ }
+ return path;
+ }
- *Files = filearr;
+ String PluginLv2::PathFromState(const String& path) {
+ if (PathSupport) {
+ char* cstr = PathSupport->absolute_path(PathSupport->host_data,
+ path.c_str());
+ const String abstract_path(cstr);
+ free(cstr);
+ return abstract_path;
+ }
+ return path;
+ }
+ void PluginLv2::Save(LV2_Persist_Store_Function store, void* host_data) {
+ if (NewFileSupport) {
+ char* path = NewFileSupport->new_file_path(PathSupport->host_data,
+ "linuxsampler");
+ dmsg(2, ("saving to file %s\n", path));
+
+ std::ofstream out(path);
+ out << GetState();
+
+ const String abstract_path = PathToState(path);
+
+ store(host_data,
+ uri_to_id(NULL, "http://linuxsampler.org/ns/state-file"),
+ abstract_path.c_str(),
+ abstract_path.length() + 1,
+ uri_to_id(NULL, LV2_FILES_URI "#AbstractPath"),
+ LV2_PERSIST_IS_PORTABLE);
+ } else {
+ dmsg(2, ("saving to string\n"));
+
+ std::ostringstream out;
+ out << GetState();
+
+ store(host_data,
+ uri_to_id(NULL, "http://linuxsampler.org/ns/state-string"),
+ out.str().c_str(),
+ out.str().length() + 1,
+ uri_to_id(NULL, "http://www.w3.org/2001/XMLSchema#string"),
+ LV2_PERSIST_IS_POD | LV2_PERSIST_IS_PORTABLE);
+ }
dmsg(2, ("saving done\n"));
- return 0;
}
- char* PluginLv2::Restore(const LV2SR_File** Files) {
- dmsg(2, ("linuxsampler: restore\n"));
- for (int i = 0 ; Files[i] ; i++) {
- dmsg(2, (" name=%s path=%s\n", Files[i]->name, Files[i]->path));
- if (strcmp(Files[i]->name, "linuxsampler") == 0) {
- std::ifstream in(Files[0]->path);
- String state;
- std::getline(in, state, '\0');
- SetState(state);
- }
+ void PluginLv2::Restore(LV2_Persist_Retrieve_Function retrieve, void* data) {
+ size_t size;
+ uint32_t type;
+ uint32_t flags;
+
+ const void* value = retrieve(
+ data,
+ uri_to_id(NULL, "http://linuxsampler.org/ns/state-file"),
+ &size, &type, &flags);
+
+ if (value) {
+ assert(type == uri_to_id(NULL, LV2_FILES_URI "#AbstractPath"));
+ const String path = PathFromState((const char*)value);
+ dmsg(2, ("linuxsampler: restoring from file %s\n", path.c_str()));
+ std::ifstream in(path.c_str());
+ String state;
+ std::getline(in, state, '\0');
+ SetState(state);
+ return;
}
- return 0;
+
+ value = retrieve(
+ data,
+ uri_to_id(NULL, "http://linuxsampler.org/ns/state-string"),
+ &size, &type, &flags);
+ if (value) {
+ dmsg(2, ("linuxsampler: restoring from string\n"));
+ assert(type == uri_to_id(NULL, "http://www.w3.org/2001/XMLSchema#string"));
+ String state((const char*)value);
+ SetState(state);
+ return;
+ }
+
+ // No valid state found, reset to default state
+ dmsg(2, ("linuxsampler: restoring default state\n"));
+ SetState("");
}
LV2_Handle instantiate(const LV2_Descriptor* descriptor,
@@ -152,12 +216,12 @@
delete static_cast<PluginLv2*>(instance);
}
- char* save(LV2_Handle handle, const char* directory, LV2SR_File*** files) {
- return static_cast<PluginLv2*>(handle)->Save(directory, files);
+ void save(LV2_Handle handle, LV2_Persist_Store_Function store, void* callback_data) {
+ return static_cast<PluginLv2*>(handle)->Save(store, callback_data);
}
- char* restore(LV2_Handle handle, const LV2SR_File** files) {
- return static_cast<PluginLv2*>(handle)->Restore(files);
+ void restore(LV2_Handle handle, LV2_Persist_Retrieve_Function store, void* callback_data) {
+ return static_cast<PluginLv2*>(handle)->Restore(store, callback_data);
}
PluginInfo PluginInfo::Instance;
@@ -171,15 +235,15 @@
Lv2.instantiate = instantiate;
Lv2.run = run;
Lv2.extension_data = extension_data;
- Lv2sr.save = save;
- Lv2sr.restore = restore;
+ Persist.save = save;
+ Persist.restore = restore;
}
const void* extension_data(const char* uri) {
dmsg(2, ("linuxsampler: extension_data %s\n", uri));
- if (strcmp(uri, LV2_SAVERESTORE_URI) == 0) {
- return PluginInfo::Lv2srDescriptor();
+ if (strcmp(uri, LV2_PERSIST_URI) == 0) {
+ return PluginInfo::Lv2PersistDescriptor();
}
return 0;
}
Index: src/hostplugins/lv2/PluginLv2.h
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/hostplugins/lv2/PluginLv2.h,v
retrieving revision 1.1
diff -u -r1.1 PluginLv2.h
--- src/hostplugins/lv2/PluginLv2.h 15 Sep 2008 16:58:10 -0000 1.1
+++ src/hostplugins/lv2/PluginLv2.h 6 Apr 2011 00:14:18 -0000
@@ -23,7 +23,9 @@
#include <lv2.h>
#include "lv2_event.h"
-#include "lv2-saverestore.h"
+#include "lv2_persist.h"
+#include "lv2_uri_map.h"
+#include "lv2_files.h"
#include "../../drivers/Plugin.h"
namespace {
@@ -37,12 +39,23 @@
void Activate();
void Run(uint32_t SampleCount);
void Deactivate();
- char* Save(const char* Directory, LV2SR_File*** Files);
- char* Restore(const LV2SR_File** Files);
+ void Save(LV2_Persist_Store_Function store, void* data);
+ void Restore(LV2_Persist_Retrieve_Function retrieve, void* data);
+
+ protected:
+ virtual String PathToState(const String& string);
+ virtual String PathFromState(const String& string);
private:
+ uint32_t uri_to_id(const char* map, const char* uri) {
+ return UriMap->uri_to_id(UriMap->callback_data, map, uri);
+ }
+
float* Out[2];
LV2_Event_Buffer* MidiBuf;
+ LV2_URI_Map_Feature* UriMap;
+ LV2_Files_Path_Support* PathSupport;
+ LV2_Files_New_File_Support* NewFileSupport;
};
class PluginInfo {
@@ -50,12 +63,12 @@
static const LV2_Descriptor* Lv2Descriptor() {
return &Instance.Lv2;
}
- static const LV2SR_Descriptor* Lv2srDescriptor() {
- return &Instance.Lv2sr;
+ static const LV2_Persist* Lv2PersistDescriptor() {
+ return &Instance.Persist;
}
private:
LV2_Descriptor Lv2;
- LV2SR_Descriptor Lv2sr;
+ LV2_Persist Persist;
PluginInfo();
static PluginInfo Instance;
@@ -73,9 +86,13 @@
static void cleanup(LV2_Handle instance);
static const void* extension_data(const char* uri);
- static char* save(LV2_Handle handle, const char* directory,
- LV2SR_File*** files);
- static char* restore(LV2_Handle handle, const LV2SR_File** files);
+ static void save(LV2_Handle handle,
+ LV2_Persist_Store_Function store,
+ void* data);
+
+ static void restore(LV2_Handle handle,
+ LV2_Persist_Retrieve_Function retrieve,
+ void* data);
}
}
Index: src/hostplugins/lv2/linuxsampler.ttl
===================================================================
RCS file: /var/cvs/linuxsampler/linuxsampler/src/hostplugins/lv2/linuxsampler.ttl,v
retrieving revision 1.1
diff -u -r1.1 linuxsampler.ttl
--- src/hostplugins/lv2/linuxsampler.ttl 15 Sep 2008 16:58:10 -0000 1.1
+++ src/hostplugins/lv2/linuxsampler.ttl 6 Apr 2011 00:14:18 -0000
@@ -8,7 +8,10 @@
doap:name "LinuxSampler" ;
doap:license <http://linuxsampler.org/downloads.html#exception> ;
lv2:optionalFeature lv2:hardRtCapable ;
- lv2:optionalFeature <http://ll-plugins.nongnu.org/lv2/ext/saverestore> ;
+ lv2:optionalFeature <http://lv2plug.in/ns/ext/persist> ;
+ lv2:optionalFeature <http://lv2plug.in/ns/ext/files#pathSupport> ;
+ lv2:optionalFeature <http://lv2plug.in/ns/ext/files#newFileSupport> ;
+ lv2:optionalFeature <http://lv2plug.in/ns/ext/uri-map> ;
lv2:port [
a lv2:AudioPort , lv2:OutputPort ;
lv2:index 0 ;
------------------------------------------------------------------------------
Xperia(TM) PLAY
It's a major breakthrough. An authentic gaming
smartphone on the nation's most reliable network.
And it wants your games.
http://p.sf.net/sfu/verizon-sfdev
_______________________________________________
Linuxsampler-devel mailing list
Linuxsampler-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxsampler-devel