summaryrefslogtreecommitdiffstats
path: root/doc/c
diff options
context:
space:
mode:
Diffstat (limited to 'doc/c')
-rw-r--r--doc/c/Doxyfile26
-rw-r--r--doc/c/index.rst10
-rw-r--r--doc/c/overview.rst18
-rw-r--r--doc/c/plugins.rst90
-rw-r--r--doc/c/uis.rst21
-rw-r--r--doc/c/world.rst153
-rw-r--r--doc/c/wscript43
7 files changed, 361 insertions, 0 deletions
diff --git a/doc/c/Doxyfile b/doc/c/Doxyfile
new file mode 100644
index 0000000..ce10524
--- /dev/null
+++ b/doc/c/Doxyfile
@@ -0,0 +1,26 @@
+PROJECT_NAME = Lilv
+PROJECT_BRIEF = "A library for simple use of LV2 plugins"
+
+QUIET = YES
+WARN_AS_ERROR = NO
+WARN_IF_UNDOCUMENTED = NO
+WARN_NO_PARAMDOC = NO
+
+JAVADOC_AUTOBRIEF = YES
+
+CASE_SENSE_NAMES = YES
+HIDE_IN_BODY_DOCS = YES
+REFERENCES_LINK_SOURCE = NO
+
+GENERATE_HTML = NO
+GENERATE_LATEX = NO
+GENERATE_XML = YES
+XML_PROGRAMLISTING = NO
+SHOW_FILES = NO
+
+MACRO_EXPANSION = YES
+PREDEFINED = LILV_API LILV_DEPRECATED
+
+INPUT = ../../include/lilv/lilv.h
+
+OUTPUT_DIRECTORY = .
diff --git a/doc/c/index.rst b/doc/c/index.rst
new file mode 100644
index 0000000..6968981
--- /dev/null
+++ b/doc/c/index.rst
@@ -0,0 +1,10 @@
+####
+Lilv
+####
+
+.. include:: summary.rst
+
+.. toctree::
+
+ overview
+ api/lilv
diff --git a/doc/c/overview.rst b/doc/c/overview.rst
new file mode 100644
index 0000000..6abc123
--- /dev/null
+++ b/doc/c/overview.rst
@@ -0,0 +1,18 @@
+.. default-domain:: c
+.. highlight:: c
+
+########
+Overview
+########
+
+The complete API is declared in ``lilv.h``:
+
+.. code-block:: c
+
+ #include <lilv/lilv.h>
+
+.. toctree::
+
+ world
+ plugins
+ uis
diff --git a/doc/c/plugins.rst b/doc/c/plugins.rst
new file mode 100644
index 0000000..3551e08
--- /dev/null
+++ b/doc/c/plugins.rst
@@ -0,0 +1,90 @@
+.. default-domain:: c
+.. highlight:: c
+
+#######
+Plugins
+#######
+
+After bundles are loaded,
+all discovered plugins can be accessed via :func:`lilv_world_get_all_plugins`:
+
+.. code-block:: c
+
+ LilvPlugins* plugins = lilv_world_get_all_plugins(world);
+
+:struct:`LilvPlugins` is a collection of plugins that can be accessed by index or plugin URI.
+The convenicne macro :macro:`LILV_FOREACH` is provided to make iterating over collections simple.
+For example, to print the URI of every plugin:
+
+.. code-block:: c
+
+ LILV_FOREACH (plugins, i, list) {
+ const LilvPlugin* p = lilv_plugins_get(list, i);
+ printf("%s\n", lilv_node_as_uri(lilv_plugin_get_uri(p)));
+ }
+ }
+
+More typically,
+you want to load a specific plugin,
+which can be done with :func:`lilv_plugins_get_by_uri`:
+
+.. code-block:: c
+
+ LilvNode* plugin_uri = lilv_new_uri(world, "http://example.org/Osc");
+
+ const LilvPlugin* plugin = lilv_plugins_get_by_uri(list, plugin_uri);
+
+:struct:`LilvPlugin` has various accessors that can be used to get information about the plugin.
+See the :doc:`API reference <api/plugin>` for details.
+
+*********
+Instances
+*********
+
+:struct:`LilvPlugin` only represents the data of the plugin,
+it does not load or access the actual plugin code.
+To do that, you must instantiate a plugin to create :struct:`LilvInstance`:
+
+.. code-block:: c
+
+ LilvInstance* instance = lilv_plugin_instantiate(plugin, 48000.0, NULL);
+
+Connecting Ports
+================
+
+Before running a plugin instance, its ports must be connected to some data.
+This is done with :func:`lilv_instance_connect_port`.
+Assuming the plugins has two control input ports and one audio output port,
+in that order:
+
+.. code-block:: c
+
+ float control_in_1 = 0.0f;
+ float control_in_2 = 0.0f;
+
+ float audio_out[128];
+
+ lilv_instance_connect_port(instance, 0, &control_in_1);
+ lilv_instance_connect_port(instance, 1, &control_in_2);
+ lilv_instance_connect_port(instance, 2, &audio_out);
+
+Processing Data
+===============
+
+Once the ports are connected, the instance can be activated and run:
+
+.. code-block:: c
+
+ lilv_instance_activate(instance);
+
+ lilv_instance_run(instance, 128);
+ // Copy buffers around and probably run several times here...
+
+ lilv_instance_deactivate(instance);
+
+Once you are done with an instance,
+it can be destroyed with :func:`lilv_instance_free`:
+
+.. code-block:: c
+
+ lilv_instance_free(instance);
diff --git a/doc/c/uis.rst b/doc/c/uis.rst
new file mode 100644
index 0000000..cbca8f6
--- /dev/null
+++ b/doc/c/uis.rst
@@ -0,0 +1,21 @@
+.. default-domain:: c
+.. highlight:: c
+
+###############
+User Interfaces
+###############
+
+Plugins may have custom user interfaces, or `UIs`,
+which are installed in bundles just like plugins.
+
+The available UIs for a plugin can be accessed with :func:`lilv_plugin_get_uis`:
+
+.. code-block:: c
+
+ LilvUIs* uis = lilv_plugin_get_uis(plugin);
+
+:struct:`LilvUIs` is a collection much like `LilvPlugins`,
+except it is of course a set of :struct:`LilvUI` rather than a set of :struct:`LilvPlugin`.
+Also like plugins,
+the :struct:`LilvUI` class has various accessors that can be used to get information about the UI.
+See the :doc:`API reference <api/ui>` for details.
diff --git a/doc/c/world.rst b/doc/c/world.rst
new file mode 100644
index 0000000..4128f77
--- /dev/null
+++ b/doc/c/world.rst
@@ -0,0 +1,153 @@
+.. default-domain:: c
+.. highlight:: c
+
+#####
+World
+#####
+
+The world is the top-level object which represents an instance of Lilv.
+It is used to discover and load LV2 data,
+and stores an internal cache of loaded data for fast searching.
+
+An application typically has a single world,
+which is constructed once on startup and used throughout the application's lifetime.
+
+************
+Construction
+************
+
+A world must be created before anything else.
+A world is created with :func:`lilv_world_new`, for example:
+
+.. code-block:: c
+
+ LilvWorld* world = lilv_world_new();
+
+***************
+Setting Options
+***************
+
+Various options to control Lilv's behavior can be set with :func:`lilv_world_set_option`.
+The currently supported options are :c:macro:`LILV_OPTION_FILTER_LANG`,
+:c:macro:`LILV_OPTION_DYN_MANIFEST`, and :c:macro:`LILV_OPTION_LV2_PATH`.
+
+For example, to set the LV2 path to only load plugins bundled in the application:
+
+.. code-block:: c
+
+ LilvNode* lv2_path = lilv_new_file_uri(world, NULL, "/myapp/lv2");
+
+ lilv_world_set_option(world, LILV_OPTION_LV2_PATH, lv2_path);
+
+************
+Loading Data
+************
+
+Before using anything, data must be loaded from disk.
+All LV2 data (plugins, UIs, specifications, presets, and so on) is installed in `bundles`,
+a standard directory format
+
+Discovering and Loading Bundles
+===============================
+
+Typical hosts will simply load all bundles in the standard LV2 locations on the system:
+
+.. code-block:: c
+
+ lilv_world_load_all(world);
+
+This will discover all bundles on the system,
+as well as load the required data defined in any discovered specifications.
+
+It is also possible to load a specific bundle:
+
+.. code-block:: c
+
+ LilvNode* bundle_uri = lilv_new_file_uri(world, NULL, "/some/plugin.lv2");
+
+ lilv_world_load_bundle(world, bundle_uri);
+
+The LV2 specification itself is also installed in bundles,
+so if you are not using :func:`lilv_world_load_all`,
+it is necessary to manually load the discovered specification data:
+
+.. code-block:: c
+
+ lilv_world_load_specifications(world);
+ lilv_world_load_plugin_classes(world);
+
+*************
+Querying Data
+*************
+
+The world contains a model of all the loaded data in memory which can be queried.
+
+Data Model
+==========
+
+LV2 data is a set of "statements",
+where a statement is a bit like a simple machine-readable sentence.
+The "subject" and "object" are as in natural language,
+and the "predicate" is like the verb, but more general.
+
+For example, we could make a statement about a plugin in english:
+
+ MyOsc has the name "Super Oscillator"
+
+We can break this statement into 3 pieces like so:
+
+.. list-table::
+ :header-rows: 1
+
+ * - Subject
+ - Predicate
+ - Object
+ * - MyOsc
+ - has the name
+ - "My Super Oscillator"
+
+Statements use URIs to identify things.
+In this case, we assume that this plugin has the URI ``http://example.org/Osc``.
+The LV2 specification defines that ``http://usefulinc.com/ns/doap#name`` is the property used to describe a plugin's name.
+So, this statement is:
+
+.. list-table::
+ :header-rows: 1
+
+ * - Subject
+ - Predicate
+ - Object
+ * - ``http://example.org/Osc``
+ - ``http://usefulinc.com/ns/doap#name``
+ - "My Oscillator"
+
+Finding Values
+==============
+
+Based on this model, you can find all values that match a certain pattern.
+Patterns are just statements,
+but with ``NULL`` used as a wildcard that matches anything.
+So, for example, you can get the name of a plugin using :func:`lilv_world_find_nodes`:
+
+.. code-block:: c
+
+ LilvNode* plugin_uri = lilv_new_uri(world, "http://example.org/Osc");
+ LilvNode* doap_name = lilv_new_uri(world, "http://usefulinc.com/ns/doap#name");
+
+ LilvNodes* values = lilv_world_find_nodes(world, plugin_uri, doap_name, NULL);
+
+Note that a set of values is returned,
+because some properties may have several values.
+When you are only interested in one value,
+you can use the simpler :func:`lilv_world_get` instead:
+
+.. code-block:: c
+
+ LilvNode* value = lilv_world_get(world, plugin_uri, doap_name, NULL);
+
+If you are only interested if a value exists at all,
+use :func:`lilv_world_ask`:
+
+.. code-block:: c
+
+ bool has_name = lilv_world_ask(world, plugin_uri, doap_name, NULL);
diff --git a/doc/c/wscript b/doc/c/wscript
new file mode 100644
index 0000000..d515ddf
--- /dev/null
+++ b/doc/c/wscript
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+def build(bld):
+ dox_to_sphinx = bld.path.find_node("../../scripts/dox_to_sphinx.py")
+ index_xml = bld.path.get_bld().make_node("xml/index.xml")
+
+ files = [
+ ("../summary.rst", "sphinx/summary.rst"),
+ ("index.rst", "sphinx/index.rst"),
+ ("overview.rst", "sphinx/overview.rst"),
+ ("plugins.rst", "sphinx/plugins.rst"),
+ ("uis.rst", "sphinx/uis.rst"),
+ ("world.rst", "sphinx/world.rst"),
+ ]
+
+ # Run Doxygen to generate XML documentation
+ bld(features="doxygen", doxyfile="Doxyfile")
+
+ # Substitute variables to make Sphinx configuration file
+ bld(features="subst",
+ source="../conf.py.in",
+ target="sphinx/conf.py",
+ LILV_VERSION=bld.env.LILV_VERSION)
+
+ # Copy static documentation files to Sphinx build directory
+ for f in files:
+ bld(features="subst", is_copy=True, source=f[0], target=f[1])
+
+ # Generate Sphinx markup from Doxygen XML
+ bld.add_group()
+ bld(rule="${PYTHON} " + dox_to_sphinx.abspath() + " -f ${SRC} ${TGT}",
+ source=index_xml,
+ target="sphinx/api/")
+
+ doc_dir = bld.env.DOCDIR + "/lilv-%s/" % bld.env.LILV_MAJOR_VERSION
+
+ # Run Sphinx to generate HTML documentation
+ for builder in ["html", "singlehtml"]:
+ bld(features="sphinx",
+ sphinx_source=bld.path.get_bld().make_node("sphinx"),
+ sphinx_output_format=builder,
+ sphinx_options=["-E", "-q", "-t", builder],
+ install_path=doc_dir + "c/%s/" % builder)