aboutsummaryrefslogtreecommitdiffstats
path: root/ext/persist.lv2
diff options
context:
space:
mode:
Diffstat (limited to 'ext/persist.lv2')
-rw-r--r--ext/persist.lv2/manifest.ttl7
-rw-r--r--ext/persist.lv2/persist.h177
-rw-r--r--ext/persist.lv2/persist.ttl116
3 files changed, 300 insertions, 0 deletions
diff --git a/ext/persist.lv2/manifest.ttl b/ext/persist.lv2/manifest.ttl
new file mode 100644
index 0000000..f1a7ecd
--- /dev/null
+++ b/ext/persist.lv2/manifest.ttl
@@ -0,0 +1,7 @@
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://lv2plug.in/ns/ext/persist>
+ a lv2:Specification ;
+ rdfs:seeAlso <persist.ttl> .
+
diff --git a/ext/persist.lv2/persist.h b/ext/persist.lv2/persist.h
new file mode 100644
index 0000000..928a297
--- /dev/null
+++ b/ext/persist.lv2/persist.h
@@ -0,0 +1,177 @@
+/* lv2_persist.h - C header file for the LV2 Persist extension.
+ * Copyright (C) 2010 Leonard Ritter <paniq@paniq.org>
+ *
+ * This header is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This header 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 Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this header; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA
+ */
+
+/** @file
+ * C header for the LV2 Persist extension <http://lv2plug.in/ns/ext/persist>.
+ */
+
+#ifndef LV2_PERSIST_H
+#define LV2_PERSIST_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LV2_PERSIST_URI "http://lv2plug.in/ns/ext/persist"
+
+/** Causes the host to store a value under a given key.
+ *
+ * This callback is passed by the host to LV2_Persist.save().
+ * @param callback_data Must be the callback_data passed to LV2_Persist.save().
+ * @param key The URI key (RDF predicate) under which the value is to be stored.
+ * @param value Pointer to the value (RDF object) to be stored.
+ * @param size The size of the data at @a value in bytes.
+ * @param type The type of @a value, as a URI mapped to an integer.
+ *
+ * Unless @a type is 0, @a value is guaranteed to be POD (i.e. a region
+ * of memory that does not contain pointers and can safely be copied
+ * and persisted indefinitely with a simple memcpy). If @a type is 0,
+ * then @a value is a reference, as defined by the LV2 Atom extension
+ * <http://lv2plug.in/ns/ext/atom/>. Hosts are not required to support
+ * references, a plugin MUST NOT expect a host to persist references unless
+ * the host supports the feature <http://lv2plug.in/ns/ext/atom#blobSupport>.
+ *
+ * Note that @a size MUST be > 0, and @a value MUST point to a valid region of
+ * memory @a size bytes long (this is required to make restore unambiguous).
+ * If only the key is of interest, store the empty string (which has size 1).
+ */
+typedef void (*LV2_Persist_Store_Function)(
+ void* callback_data,
+ const char* key,
+ const void* value,
+ size_t size,
+ uint32_t type);
+
+/** Causes the host to retrieve a value under a given key.
+ *
+ * This callback is passed by the host to LV2_Persist.restore().
+ * @param callback_data Must be the callback_data passed to LV2_Persist.restore().
+ * @param key The URI key (RDF predicate) under which a value has been stored.
+ * @param size (Output) If non-NULL, set to the size of the restored value.
+ * @param type (Output) If non-NULL, set to the type of the restored value.
+ * @return A pointer to the restored value (RDF object), or NULL if no value
+ * has been stored under @a key.
+ *
+ * The returned value MUST remain valid until LV2_Persist.restore() returns. The plugin
+ * MUST NOT attempt to access a returned pointer outside of the LV2_Persist.restore()
+ * context (it MUST make a copy in order to do so).
+ */
+typedef const void* (*LV2_Persist_Retrieve_Function)(
+ void* callback_data,
+ const char* key,
+ size_t* size,
+ uint32_t* type);
+
+/** When the plugin's extension_data is called with argument LV2_PERSIST_URI,
+ * the plugin MUST return an LV2_Persist structure, which remains valid for
+ * the lifetime of the plugin.
+ *
+ * The host can use the contained function pointers to save and restore the
+ * state of a plugin instance at any time (provided the threading restrictions
+ * for the given function are met).
+ *
+ * The typical use case is to save the plugin's state when a project is
+ * saved, and to restore the state when a project has been loaded. Other
+ * uses are possible (e.g. cloning plugin instances or taking a snapshot
+ * of plugin state).
+ *
+ * Stored data is only guaranteed to be compatible between instances of plugins
+ * with the same URI (i.e. if a change to a plugin would cause a fatal error
+ * when restoring state saved by a previous version of that plugin, the plugin
+ * URI must change just as it must when a plugin's ports change). Plugin
+ * authors should consider this possibility, and always store sensible data
+ * with meaningful types to avoid such compatibility issues in the future.
+ */
+typedef struct _LV2_Persist {
+ /** Causes the plugin to save state data using a host-provided
+ * @a store callback.
+ *
+ * @param instance The instance handle of the plugin.
+ * @param store The host-provided store callback.
+ * @param callback_data An opaque pointer to host data, e.g. the map or
+ * file where the values are to be stored. If @a store is called,
+ * this MUST be passed as its callback_data parameter.
+ *
+ * The plugin is expected to store everything necessary to completely
+ * restore its state later (possibly much later, in a different
+ * process, on a completely different machine, etc.)
+ *
+ * The @a callback_data pointer and @a store function MUST NOT be
+ * used beyond the scope of save().
+ *
+ * This function has its own special threading class: it may not be
+ * called concurrently with any "Instantiation" function, but it
+ * may be called concurrently with functions in any other class,
+ * unless the definition of that class prohibits it (e.g. it may
+ * not be called concurrently with a "Discovery" function, but it
+ * may be called concurrently with an "Audio" function. The plugin
+ * is responsible for any locking or lock-free techniques necessary
+ * to make this possible.
+ *
+ * Note that in the simple case where state is only modified by
+ * restore(), there are no synchronization issues since save() is
+ * never called concurrently with restore() (though run() may read
+ * it during a save).
+ *
+ * Plugins that dynamically modify state while running, however,
+ * must take care to do so in such a way that a concurrent call to
+ * save() will save a consistent representation of plugin state for a
+ * single point in time. The simplest way to do this is to modify a
+ * copy of the state map and atomically swap a pointer to the entire
+ * map once the changes are complete (for very large state maps,
+ * a purely functional map data structure would be more appropriate
+ * since a complete copy is not necessary).
+ */
+ void (*save)(LV2_Handle instance,
+ LV2_Persist_Store_Function store,
+ void* callback_data);
+
+ /** Causes the plugin to restore state data using a host-provided
+ * @a retrieve callback.
+ *
+ * @param instance The instance handle of the plugin.
+ * @param retrieve The host-provided retrieve callback.
+ * @param callback_data An opaque pointer to host data, e.g. the map or
+ * file from which the values are to be restored. If @a retrieve is
+ * called, this MUST be passed as its callback_data parameter.
+ *
+ * The plugin MAY assume a restored value was set by a previous call to
+ * LV2_Persist.save() by a plugin with the same URI.
+ *
+ * The plugin MUST gracefully fall back to a default value when a
+ * value can not be retrieved. This allows the host to reset the
+ * plugin state with an empty map.
+ *
+ * The @a callback_data pointer and @a store function MUST NOT be used
+ * beyond the scope of restore().
+ *
+ * This function is in the "Instantiation" threading class as defined
+ * by LV2. This means it MUST NOT be called concurrently with any other
+ * function on the same plugin instance.
+ */
+ void (*restore)(LV2_Handle instance,
+ LV2_Persist_Retrieve_Function retrieve,
+ void* callback_data);
+
+} LV2_Persist;
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* LV2_PERSIST_H */
diff --git a/ext/persist.lv2/persist.ttl b/ext/persist.lv2/persist.ttl
new file mode 100644
index 0000000..f1dd86f
--- /dev/null
+++ b/ext/persist.lv2/persist.ttl
@@ -0,0 +1,116 @@
+# LV2 Persist Extension
+# Copyright (C) 2010 Leonard Ritter <paniq@paniq.org>
+# Copyright (C) 2010 David Robillard <d@drobilla.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+
+@prefix persist: <http://lv2plug.in/ns/ext/persist#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema> .
+
+<http://lv2plug.in/ns/ext/persist>
+ a lv2:Specification ;
+ doap:name "LV2 Persist" ;
+ doap:maintainer [
+ a foaf:Person ;
+ foaf:name "David Robillard" ;
+ foaf:homepage <http://drobilla.net/> ;
+ rdfs:seeAlso <http://drobilla.net/drobilla.rdf>
+ ] ;
+ rdfs:comment """
+This extension provides a mechanism for plugins to save and restore state
+across instances, allowing hosts to save configuration/state/data with a
+project or fully clone a plugin instance (including internal state).
+
+The motivating idea behind this extension is that a plugin instance's state
+is entirely represented by port values and a single key/value dictionary.
+This makes state well-defined and easily manageable by hosts. Keys are URIs,
+avoiding conflicts and allowing the same dictionary to be used to store plugin
+state in any context. Values are typed tagged (by URI mapped integers),
+but otherwise are simple binary blobs.
+
+This extension defines plugin instance state and provides a mechanism
+for saving/restoring it, but otherwise makes no restrictions on how a
+plugin works with state. For example, other extensions may define dynamic
+ways to control plugin state at runtime. The idea is that <em>all</em>
+plugin state can be represented with a single (conceptual) dictionary.
+This state representation is tried-and-true, universal, and works well with
+many existing technologies. Accordingly, plugins/extensions that deal with
+instance state in any way SHOULD represent it in a way compatible with this
+extension, i.e. URI keys with URI-typed values. Similarly, plugins SHOULD NOT
+use any other mechanism to store/restore state; this <strong>will</strong>
+cause serious problems, don't do it! Note that you can store values of any
+format whatsoever, so if you have an existing state representation to use
+(e.g. XML), simply store it as a single value under some key.
+
+Files may be persisted using this extension in conjunction with the
+<a href="http://lv2plug.in/ns/ext/files">LV2 Files</a> extension.
+
+Instance state as defined by this extension is RDF compatible, allowing for
+simple and seamless integration with existing technology (LV2 or otherwise).
+An obvious benefit of this is that plugin state can be elegantly described
+in Turtle files; the persist:instanceState predicate is provided for this
+purpose. RDF compatibility is also convenient since LV2 hosts are likely
+to already have mechanisms for working with RDF-style data. Note, however,
+that hosts may store state in any way, and are not required to use any
+specific technology or file format to support this extension.
+""" .
+
+persist:InstanceState
+ a rdfs:Class ;
+ rdfs:label "Plugin Instance State" ;
+ rdfs:comment """
+This class is used to express a plugin instance's state in RDF. The key/value
+properties of the instance form the predicate/object (respectively) of triples
+with a persist:InstanceState as the subject (see persist:instanceState
+for an example). This may be used wherever it is useful to express a
+plugin instance's state in RDF (e.g. for serialisation, storing in a model, or
+transmitting over a network). Note that this class is provided because it
+may be useful for hosts, plugins, or extensions that work with instance state,
+but its use is not required to support the LV2 Persist extension.
+""" .
+
+
+persist:instanceState
+ a rdf:Property ;
+ rdfs:range persist:InstanceState ;
+ rdfs:comment """
+Predicate to relate a plugin instance to an InstanceState. This may be used
+wherever the state of a particular plugin instance needs to be represented.
+Note that the domain of this property is unspecified, since LV2 does not
+define any RDF class for plugin instance. This predicate may be used
+wherever it makes sense to do so, e.g.:
+<pre>
+@prefix eg: &lt;http://example.org/&gt .
+
+&lt;plugininstance&gt; persist:instanceState [
+ eg:somekey "some value" ;
+ eg:someotherkey "some other value" ;
+ eg:favouritenumber 2 .
+]
+</pre>
+Note that this property is provided because it may be useful for hosts,
+plugins, or extensions that work with instance state, but its use is not
+required to support the LV2 Persist extension.
+""" .
+ \ No newline at end of file