summaryrefslogtreecommitdiffstats
path: root/doc/c/overview.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/c/overview.rst')
-rw-r--r--doc/c/overview.rst263
1 files changed, 259 insertions, 4 deletions
diff --git a/doc/c/overview.rst b/doc/c/overview.rst
index b5d75c1..2ffcfd1 100644
--- a/doc/c/overview.rst
+++ b/doc/c/overview.rst
@@ -1,12 +1,267 @@
-########
-Overview
-########
+############
+Using Sratom
+############
.. default-domain:: c
.. highlight:: c
-The entire API is declared in ``sratom.h``:
+The sratom API is declared in ``sratom.h``:
.. code-block:: c
#include <sratom/sratom.h>
+
+Sratom supports two operations:
+writing atoms to a model or string, called "dumping",
+and reading atoms from a model or string, called "loading".
+Each is supported by a separate object.
+
+*************
+Dumping Atoms
+*************
+
+Dumping atoms is supported by :struct:`SratomDumper`.
+A new dumper can be allocated with :func:`sratom_dumper_new`.
+It requires a :struct:`SerdWorld`,
+and both a URID map (to map vocabulary during setup),
+and URID unmap (for expanding URIDs in the output).
+For example, assuming these are already set up appropriately in the application:
+
+.. code-block:: c
+
+ SerdWorld* world = my_world();
+ LV2_URID_Map* map = my_urid_map();
+ LV2_URID_Unmap* unmap = my_urid_map();
+ SratomDumper* dumper = sratom_dumper_new(world, map, unmap);
+
+Dumping Strings
+===============
+
+Once a dumper is allocated it can be used to write any number of atoms.
+The simplest function to use is :func:`sratom_to_string`,
+which takes an environment and an atom,
+and returns a newly allocated string representation of the atom.
+
+The environment can be used to set up the base URI and any namespace prefixes for the output.
+The base URI is used to convert relative paths to URIs,
+and prefixes will be used to abbreviate the output.
+Typically, the base URI is a file URI that points to a directory that file paths are relative to,
+and prefixes are set for commonly used vocabularies.
+For example:
+
+.. code-block:: c
+
+ SerdStringView base = SERD_STATIC_STRING("file:///tmp/state/");
+ SerdEnv* env = serd_env_new(base);
+
+ serd_env_set_prefix(
+ env,
+ SERD_STATIC_STRING("atom"),
+ SERD_STATIC_STRING("http://lv2plug.in/ns/ext/atom#"));
+
+With the environment configured,
+:func:`sratom_to_string` can be used to convert atoms to strings:
+
+.. code-block:: c
+
+ LV2_Atom* atom = my_atom();
+ char* string = sratom_to_string(dumper, env, atom, 0);
+
+ fprintf(stderr, "Atom: %s\n", string);
+
+ sratom_free(string);
+
+Dumping to a Statement Sink
+===========================
+
+More advanced use cases are supported by the more fundamental functions :func:`sratom_dump` and :func:`sratom_dump_atom`.
+These write a series of statements that describe the atom to a :struct:`SerdSink`,
+which can be configured to write anywhere, such as a file or model.
+A subject and predicate should be provided for the main resulting statement.
+For example, when writing a value for some control,
+the subject might identify the device,
+and the predicate the parameter:
+
+.. code-block:: c
+
+ SerdModel* model = my_model();
+ LV2_URID subject = urid_map("http://example.org/amp");
+ LV2_URID predicate = urid_map("http://example.org/gain");
+ const SerdSink* sink = serd_inserter_new(model, NULL);
+
+ const float value = 42.0f;
+
+ sratom_dump(dumper,
+ env,
+ sink,
+ subject,
+ predicate,
+ urid_map(LV2_ATOM__Float),
+ sizeof(float),
+ &value,
+ 0);
+
+Which would produce output like:
+
+.. code-block:: text
+
+ eg:amp eg:gain 42.0 .
+
+More complex atoms might produce several statements,
+for example an object may itself have several properties:
+
+.. code-block:: text
+
+ eg:mixer eg:pan [
+ eg:left 1.0 ;
+ eg:front 0.5 ;
+ ] .
+
+Representation
+==============
+
+If no subject and predicate are given,
+either explicitly with :func:`sratom_dump` or by using :func:`sratom_to_string`,
+then the atom will be written as the subject.
+Literals (which are not enough to form a statement) are written as the sole element of a list.
+This ensures that the representation can be transmitted, stored, or transformed without loss.
+For example, here is the terse string format (which is Turtle) of various atom types:
+
+.. code-block:: turtle
+
+ ( "hello" ) .
+
+ ( true ) .
+
+ ( 1 ) .
+
+ ( 3.0 ) .
+
+ ( <file:///absolute/path> ) .
+
+ ( <relative/path> ) .
+
+ ( eg:thing ) .
+
+ []
+ a atom:Tuple ;
+ rdf:value ( "foo" true ) .
+
+ []
+ a atom:Vector ;
+ atom:childType atom:Int ;
+ rdf:value ( 1 2 3 4 5 ) .
+
+ []
+ a atom:Sequence ;
+ rdf:value (
+ [
+ atom:frameTime 1 ;
+ rdf:value "901A01"^^midi:MidiEvent
+ ]
+ [
+ atom:frameTime 3 ;
+ rdf:value "902B02"^^midi:MidiEvent
+ ]
+ ) .
+
+Cleaning Up
+===========
+
+When finished, a dumper must be destroyed by :func:`sratom_dumper_free`:
+
+.. code-block:: c
+
+ sratom_dumper_free(dumper);
+
+Any newly-allocated strings returned by :func:`sratom_to_string` are independent,
+and may outlive the dumper that created them.
+These must be individually destroyed with :func:`sratom_free`.
+
+*************
+Loading Atoms
+*************
+
+:struct:`SratomLoader` can construct atoms from descriptions written by a dumper.
+This is typically used to load saved atoms from a file, socket, or data model.
+A new loader can be allocated with :func:`sratom_loader_new`:
+
+.. code-block:: c
+
+ SerdWorld* world = my_world();
+ LV2_URID_Map* map = my_urid_map();
+ SratomLoader* loader = sratom_loader_new(world, map);
+
+Once a loader is allocated it can be used to read any number of atoms.
+
+Loading Strings
+===============
+
+:func:`sratom_from_string` can be used to load atoms from strings created by :func:`sratom_to_string`:
+
+.. code-block:: c
+
+ const char* string = "( 42.0 ) .";
+
+ LV2_Atom* atom = sratom_from_string(loader, env, string);
+
+ do_something_with(atom);
+
+The environment should match the one used when dumping the string,
+so that namespace prefixes can be parsed correctly.
+The returned atom is newly allocated and owned by the caller,
+who must eventually destroy it with :func:`sratom_free`:
+
+.. code-block:: c
+
+ sratom_free(atom);
+
+Loading from a Model
+====================
+
+:func:`sratom_from_model` and the lower-level :func:`sratom_load` can be used to load atoms from a data model.
+A model contains statements,
+so this can be used to load atoms that were saved with :func:`sratom_dump`.
+The node that represents the atom must be given to specify where in the model to find the atom.
+Typically,
+this is the object of a statement with the subject and predicate passed to :func:`sratom_dump`.
+
+For example,
+given some model and node in an application,
+a new atom can be allocated from its representation in the model:
+
+.. code-block:: c
+
+ const SerdModel* model = my_model();
+ const SerdNode* value_node = get_value(model);
+
+ Atom* atom = sratom_from_model(loader,
+ base,
+ model,
+ value_node);
+
+The lower-level :func:`sratom_load` can be used with a :struct:`LV2_Atom_Forge` instead,
+which allows writing the atom directly to an existing buffer:
+
+.. code-block:: c
+
+ LV2_Atom_Forge* forge = my_buffer_writing_forge();
+
+ sratom_load(loader,
+ base,
+ forge,
+ model,
+ value_node);
+
+Cleaning Up
+===========
+
+When finished, a loader must be destroyed by :func:`sratom_loader_free`:
+
+.. code-block:: c
+
+ sratom_loader_free(loader);
+
+Any newly-allocated atoms returned by :func:`sratom_from_model` are independent,
+and may outlive the loader that created them.
+These must be individually destroyed with :func:`sratom_free`.