<b>This document is a draft</b>

This document describes how to write a decent LV2 extension."Extension" is a loosely defined term, any API and/or ontology description related to LV2 is an "LV2 Extension".

Developers should adhere to these conventions when creating an LV2 extension to ensures extensions work with existing LV2 implementations as smoothly as possible.

Motivation

The motivation here is to have a useful 'normal' way of authoring and distributing extensions so they are as convenient as possible. Some criteria:

  • Extensions should be simple and natural to host via HTTP or some other protocol (to allow for resolvable URIs)
  • Extensions should be simple to distribute in a single archive
  • Extension distributions should be LV2 bundles (for discovery by hosts)
  • Extensions should copy the LV2 specification in style and spirit as much as possible

Conventions

All extensions at http://lv2plug.in/ns conform to these recommendations. Modifying an existing extension at http://lv2plug.in/ns/ext is the simplest way to follow these guidelines and make a good extension.

Using a "Foo Bar" extension with conventional prefix "fb" as an example:

  • The extension's basename is "foo-bar" (lowercase hyphen-delimited words)
  • The extension is distributed in an LV2 bundle with the same basename, e.g. foo-bar.lv2"
    • See wiki:Bundle_Definition
    • The description of the extension is RDF data in Turtle format in a file named manifest.ttl
    • manifest.ttl mentions the lv2:Specification, e.g. <pre>&lt; http://example.org/foo-bar&gt; a lv2:Specification .</pre>
    • Other data in separate files should be referred to from manifest.ttl (using rdfs:seeAlso or other appropriate predicates)
    • Use a 'suggested' prefix for the extension in the extension definition itself (e.g. don't use the empty prefix)
    • Express as much information in machine readable form as possible (avoid defining things in comments when they could be defined in RDF)
    • <b>Note:</b> The document URI is not the same as the extension URI, use a prefix or full URI for the extension.
      • <b><> is NOT the extension URI</b> (older revisions of lv2.ttl made this error, please do not reproduce it)
    • Rationale:
      • Allows easy parsing and merging by simple programs, and preserves namespace prefixes
      • Ensures hosts can automatically discover extension data via the normal LV2 bundle discovery mechanism
  • A separate manifest.ttl and foo-bar.ttl will speed the discovery process, and is a good idea for larger extensions
  • Other files describing the extension should have the same basename as the extension, with the appropriate file extension
    • e.g. C header "foo-bar.h", HTML document "foo-bar.html"
    • Other files may have any name (data, auxilliary documentation, etc)
  • C/C++ code can use include directly from the bundle like so: <pre>#include "foo-bar.lv2/foo-bar.h"</pre>

Revisions

  • All "revisions" of an extension with a given URI are compatible by definition. If an extension is changed in an incompatible way the URI must be changed (and the revision reset to 1 for this new extension)
    • If the revision is 1 it may be ommitted, and conversely if there is no revision it is assumed to be 1.
    • Revision numbers are appended to the basename with a hyphen, e.g. a non-compatible successor to foo-bar would have basename "foo-bar-2.lv2"

Example

A "Foo Bar" extension with a separate ontology file, C header, and some HTML documentation would have a directory layout like the following: <pre> foo-bar.lv2/manifest.ttl foo-bar.lv2/foo-bar.ttl foo-bar.lv2/foo-bar.h foo-bar.lv2/foo-bar.html </pre>

Be careful not to mix up the namespace prefix and the extension URI (see above); the URI of the extension does not contain the fragment identifier "#". A correct manifest.ttl might contain: <pre> @prefix rdfs: < http://www.w3.org/2000/01/rdf-schema#> . @prefix fb: &lt;http://lv2plug.in/ns/ext/foo-bar#&gt; .

&lt;http://lv2plug.in/ns/ext/foo-bar&gt;

a lv2:Specification ; rdfs:seeAlso <foo-bar.ttl> .

fb:Something a rdfs:Class . </pre>

Hosting

If the Foo Bar extension was published at http://lv2plug.in/ns/ext, the following resources would be available: <table> <tr><td>http://lv2plug.in/ns/ext/foo-bar</td><td>(content negotiated)</td> <tr><td>http://lv2plug.in/ns/ext/foo-bar.ttl</td><td>(convenient alias for foo-bar.lv2/manifest.ttl)</td> <tr><td>http://lv2plug.in/ns/ext/foo-bar.html</td><td>(convenient alias for foo-bar.lv2/foo-bar.html)</td> <tr><td>http://lv2plug.in/ns/ext/foo-bar.lv2/</td><td>(directory listing)</td> <tr><td>http://lv2plug.in/ns/ext/foo-bar.lv2/*</td><td>(where * is any file, e.g. foo-bar.h)</td> </table>

<b>Note:</b> http://lv2plug.in/ns/ext/foo-bar.lv2/ is a valid LV2 bundle that can be directly used via the normal LV2 discovery process, or downloaded easily. In general, extensions hosted anywhere should provide access to the bundle like this.

"Standard" Extensions

Developers may use the http://lv2plug.in/ns/dev/ prefix freely for anything, but must not assume any URI with this prefix is stable or unique.

Developers without permanent web hosting for resolvable URIs are welcome use lv2plug.in to permanently host an extension if it meets certain guidelines. To be a "standard" extension hosted at http://lv2plug.in/ns, the above MUST be adhered to (where possible/applicable), in addition to the following:

  • The extension URI is e.g. http://lv2plug.in/ns/ext/foo-bar
  • The "usual prefix" for the extension ("fb" here) is unique among other extensions at http://lv2plug.in/ns/
  • The extension's manifest.ttl declares this prefix, e.g. @prefix fb: http://lv2plug.in/ns/ext/foo-bar#
  • The extension has been discussed on the lv2-dev mailing list (and general consensus is that the extension is fine to publish at the given URI)
  • At least 2 implementations of the extension exist (preferably more)
    • If the distinction makes sense, at least one 'host side' implementation and at least one 'plugin side' implementation should exist, that function correctly together