From 725d4a404b838da6b67d9da66228a1125bddef57 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sun, 20 Nov 2011 23:08:57 +0000 Subject: Lay out repository structure to match include and URI structure. Treat lv2core like all the other specifications in gendoc.py. --- ns/ext/atom/atom-buffer.h | 163 +++++++++ ns/ext/atom/atom-helpers.h | 174 ++++++++++ ns/ext/atom/atom.h | 248 ++++++++++++++ ns/ext/atom/atom.ttl | 436 +++++++++++++++++++++++++ ns/ext/atom/ext.pc.in | 1 + ns/ext/atom/forge.h | 75 +++++ ns/ext/atom/manifest.ttl | 9 + ns/ext/atom/waf | 1 + ns/ext/atom/wscript | 1 + ns/ext/contexts/contexts.h | 82 +++++ ns/ext/contexts/contexts.ttl | 134 ++++++++ ns/ext/contexts/ext.pc.in | 1 + ns/ext/contexts/manifest.ttl | 9 + ns/ext/contexts/test.c | 67 ++++ ns/ext/contexts/waf | 1 + ns/ext/contexts/wscript | 1 + ns/ext/cv-port/cv-port.ttl | 77 +++++ ns/ext/cv-port/ext.pc.in | 1 + ns/ext/cv-port/manifest.ttl | 9 + ns/ext/cv-port/waf | 1 + ns/ext/cv-port/wscript | 1 + ns/ext/data-access/data-access.h | 56 ++++ ns/ext/data-access/data-access.ttl | 82 +++++ ns/ext/data-access/ext.pc.in | 1 + ns/ext/data-access/manifest.ttl | 9 + ns/ext/data-access/waf | 1 + ns/ext/data-access/wscript | 1 + ns/ext/dynmanifest/dynmanifest.h | 144 ++++++++ ns/ext/dynmanifest/dynmanifest.ttl | 122 +++++++ ns/ext/dynmanifest/ext.pc.in | 1 + ns/ext/dynmanifest/lv2-dynmanifest.doap.ttl | 43 +++ ns/ext/dynmanifest/manifest.ttl | 9 + ns/ext/dynmanifest/waf | 1 + ns/ext/dynmanifest/wscript | 1 + ns/ext/event/event-helpers.h | 246 ++++++++++++++ ns/ext/event/event.h | 281 ++++++++++++++++ ns/ext/event/event.ttl | 194 +++++++++++ ns/ext/event/ext.pc.in | 1 + ns/ext/event/manifest.ttl | 9 + ns/ext/event/waf | 1 + ns/ext/event/wscript | 1 + ns/ext/files/ext.pc.in | 1 + ns/ext/files/files.h | 134 ++++++++ ns/ext/files/files.ttl | 115 +++++++ ns/ext/files/manifest.ttl | 9 + ns/ext/files/waf | 1 + ns/ext/files/wscript | 1 + ns/ext/host-info/ext.pc.in | 1 + ns/ext/host-info/host-info.ttl | 118 +++++++ ns/ext/host-info/manifest.ttl | 9 + ns/ext/host-info/waf | 1 + ns/ext/host-info/wscript | 1 + ns/ext/instance-access/ext.pc.in | 1 + ns/ext/instance-access/instance-access.h | 38 +++ ns/ext/instance-access/instance-access.ttl | 80 +++++ ns/ext/instance-access/manifest.ttl | 9 + ns/ext/instance-access/waf | 1 + ns/ext/instance-access/wscript | 1 + ns/ext/midi/ext.pc.in | 1 + ns/ext/midi/manifest.ttl | 9 + ns/ext/midi/midi.ttl | 115 +++++++ ns/ext/midi/waf | 1 + ns/ext/midi/wscript | 1 + ns/ext/osc/ext.pc.in | 1 + ns/ext/osc/lv2_osc.c | 238 ++++++++++++++ ns/ext/osc/lv2_osc_print.c | 66 ++++ ns/ext/osc/lv2_osc_test.c | 55 ++++ ns/ext/osc/manifest.ttl | 9 + ns/ext/osc/osc-print.h | 42 +++ ns/ext/osc/osc.h | 119 +++++++ ns/ext/osc/osc.ttl | 39 +++ ns/ext/osc/waf | 1 + ns/ext/osc/wscript | 1 + ns/ext/parameter/ext.pc.in | 1 + ns/ext/parameter/manifest.ttl | 9 + ns/ext/parameter/parameter.ttl | 111 +++++++ ns/ext/parameter/waf | 1 + ns/ext/parameter/wscript | 1 + ns/ext/port-groups/ext.pc.in | 1 + ns/ext/port-groups/manifest.ttl | 9 + ns/ext/port-groups/port-groups.ttl | 490 ++++++++++++++++++++++++++++ ns/ext/port-groups/waf | 1 + ns/ext/port-groups/wscript | 1 + ns/ext/port-props/ext.pc.in | 1 + ns/ext/port-props/manifest.ttl | 8 + ns/ext/port-props/port-props.ttl | 217 ++++++++++++ ns/ext/port-props/waf | 1 + ns/ext/port-props/wscript | 1 + ns/ext/presets/ext.pc.in | 1 + ns/ext/presets/manifest.ttl | 9 + ns/ext/presets/presets.ttl | 113 +++++++ ns/ext/presets/waf | 1 + ns/ext/presets/wscript | 1 + ns/ext/pui/ext.pc.in | 1 + ns/ext/pui/manifest.ttl | 8 + ns/ext/pui/pui.h | 374 +++++++++++++++++++++ ns/ext/pui/pui.ttl | 282 ++++++++++++++++ ns/ext/pui/waf | 1 + ns/ext/pui/wscript | 1 + ns/ext/reference/ext.pc.in | 1 + ns/ext/reference/manifest.ttl | 9 + ns/ext/reference/reference.h | 161 +++++++++ ns/ext/reference/reference.ttl | 82 +++++ ns/ext/reference/waf | 1 + ns/ext/reference/wscript | 1 + ns/ext/resize-port/ext.pc.in | 1 + ns/ext/resize-port/manifest.ttl | 9 + ns/ext/resize-port/resize-port.h | 57 ++++ ns/ext/resize-port/resize-port.ttl | 80 +++++ ns/ext/resize-port/waf | 1 + ns/ext/resize-port/wscript | 1 + ns/ext/state/ext.pc.in | 1 + ns/ext/state/manifest.ttl | 9 + ns/ext/state/state.h | 258 +++++++++++++++ ns/ext/state/state.ttl | 231 +++++++++++++ ns/ext/state/waf | 1 + ns/ext/state/wscript | 1 + ns/ext/string-port/ext.pc.in | 1 + ns/ext/string-port/manifest.ttl | 8 + ns/ext/string-port/string-port.h | 58 ++++ ns/ext/string-port/string-port.ttl | 105 ++++++ ns/ext/string-port/waf | 1 + ns/ext/string-port/wscript | 1 + ns/ext/time/ext.pc.in | 1 + ns/ext/time/manifest.ttl | 9 + ns/ext/time/time.h | 131 ++++++++ ns/ext/time/time.ttl | 57 ++++ ns/ext/time/waf | 1 + ns/ext/time/wscript | 1 + ns/ext/ui-resize/ext.pc.in | 1 + ns/ext/ui-resize/manifest.ttl | 9 + ns/ext/ui-resize/ui-resize.h | 58 ++++ ns/ext/ui-resize/ui-resize.ttl | 43 +++ ns/ext/ui-resize/waf | 1 + ns/ext/ui-resize/wscript | 1 + ns/ext/uri-map/ext.pc.in | 1 + ns/ext/uri-map/manifest.ttl | 8 + ns/ext/uri-map/uri-map.h | 92 ++++++ ns/ext/uri-map/uri-map.ttl | 57 ++++ ns/ext/uri-map/waf | 1 + ns/ext/uri-map/wscript | 1 + ns/ext/uri-unmap/ext.pc.in | 1 + ns/ext/uri-unmap/manifest.ttl | 8 + ns/ext/uri-unmap/uri-unmap.h | 81 +++++ ns/ext/uri-unmap/uri-unmap.ttl | 46 +++ ns/ext/uri-unmap/waf | 1 + ns/ext/uri-unmap/wscript | 1 + ns/ext/urid/ext.pc.in | 1 + ns/ext/urid/manifest.ttl | 9 + ns/ext/urid/urid.h | 113 +++++++ ns/ext/urid/urid.ttl | 67 ++++ ns/ext/urid/waf | 1 + ns/ext/urid/wscript | 1 + 153 files changed, 7442 insertions(+) create mode 100644 ns/ext/atom/atom-buffer.h create mode 100644 ns/ext/atom/atom-helpers.h create mode 100644 ns/ext/atom/atom.h create mode 100644 ns/ext/atom/atom.ttl create mode 120000 ns/ext/atom/ext.pc.in create mode 100644 ns/ext/atom/forge.h create mode 100644 ns/ext/atom/manifest.ttl create mode 120000 ns/ext/atom/waf create mode 120000 ns/ext/atom/wscript create mode 100644 ns/ext/contexts/contexts.h create mode 100644 ns/ext/contexts/contexts.ttl create mode 120000 ns/ext/contexts/ext.pc.in create mode 100644 ns/ext/contexts/manifest.ttl create mode 100644 ns/ext/contexts/test.c create mode 120000 ns/ext/contexts/waf create mode 120000 ns/ext/contexts/wscript create mode 100644 ns/ext/cv-port/cv-port.ttl create mode 120000 ns/ext/cv-port/ext.pc.in create mode 100644 ns/ext/cv-port/manifest.ttl create mode 120000 ns/ext/cv-port/waf create mode 120000 ns/ext/cv-port/wscript create mode 100644 ns/ext/data-access/data-access.h create mode 100644 ns/ext/data-access/data-access.ttl create mode 120000 ns/ext/data-access/ext.pc.in create mode 100644 ns/ext/data-access/manifest.ttl create mode 120000 ns/ext/data-access/waf create mode 120000 ns/ext/data-access/wscript create mode 100644 ns/ext/dynmanifest/dynmanifest.h create mode 100644 ns/ext/dynmanifest/dynmanifest.ttl create mode 120000 ns/ext/dynmanifest/ext.pc.in create mode 100644 ns/ext/dynmanifest/lv2-dynmanifest.doap.ttl create mode 100644 ns/ext/dynmanifest/manifest.ttl create mode 120000 ns/ext/dynmanifest/waf create mode 120000 ns/ext/dynmanifest/wscript create mode 100644 ns/ext/event/event-helpers.h create mode 100644 ns/ext/event/event.h create mode 100644 ns/ext/event/event.ttl create mode 120000 ns/ext/event/ext.pc.in create mode 100644 ns/ext/event/manifest.ttl create mode 120000 ns/ext/event/waf create mode 120000 ns/ext/event/wscript create mode 120000 ns/ext/files/ext.pc.in create mode 100644 ns/ext/files/files.h create mode 100644 ns/ext/files/files.ttl create mode 100644 ns/ext/files/manifest.ttl create mode 120000 ns/ext/files/waf create mode 120000 ns/ext/files/wscript create mode 120000 ns/ext/host-info/ext.pc.in create mode 100644 ns/ext/host-info/host-info.ttl create mode 100644 ns/ext/host-info/manifest.ttl create mode 120000 ns/ext/host-info/waf create mode 120000 ns/ext/host-info/wscript create mode 120000 ns/ext/instance-access/ext.pc.in create mode 100644 ns/ext/instance-access/instance-access.h create mode 100644 ns/ext/instance-access/instance-access.ttl create mode 100644 ns/ext/instance-access/manifest.ttl create mode 120000 ns/ext/instance-access/waf create mode 120000 ns/ext/instance-access/wscript create mode 120000 ns/ext/midi/ext.pc.in create mode 100644 ns/ext/midi/manifest.ttl create mode 100644 ns/ext/midi/midi.ttl create mode 120000 ns/ext/midi/waf create mode 120000 ns/ext/midi/wscript create mode 120000 ns/ext/osc/ext.pc.in create mode 100644 ns/ext/osc/lv2_osc.c create mode 100644 ns/ext/osc/lv2_osc_print.c create mode 100644 ns/ext/osc/lv2_osc_test.c create mode 100644 ns/ext/osc/manifest.ttl create mode 100644 ns/ext/osc/osc-print.h create mode 100644 ns/ext/osc/osc.h create mode 100644 ns/ext/osc/osc.ttl create mode 120000 ns/ext/osc/waf create mode 120000 ns/ext/osc/wscript create mode 120000 ns/ext/parameter/ext.pc.in create mode 100644 ns/ext/parameter/manifest.ttl create mode 100644 ns/ext/parameter/parameter.ttl create mode 120000 ns/ext/parameter/waf create mode 120000 ns/ext/parameter/wscript create mode 120000 ns/ext/port-groups/ext.pc.in create mode 100644 ns/ext/port-groups/manifest.ttl create mode 100644 ns/ext/port-groups/port-groups.ttl create mode 120000 ns/ext/port-groups/waf create mode 120000 ns/ext/port-groups/wscript create mode 120000 ns/ext/port-props/ext.pc.in create mode 100644 ns/ext/port-props/manifest.ttl create mode 100644 ns/ext/port-props/port-props.ttl create mode 120000 ns/ext/port-props/waf create mode 120000 ns/ext/port-props/wscript create mode 120000 ns/ext/presets/ext.pc.in create mode 100644 ns/ext/presets/manifest.ttl create mode 100644 ns/ext/presets/presets.ttl create mode 120000 ns/ext/presets/waf create mode 120000 ns/ext/presets/wscript create mode 120000 ns/ext/pui/ext.pc.in create mode 100644 ns/ext/pui/manifest.ttl create mode 100644 ns/ext/pui/pui.h create mode 100644 ns/ext/pui/pui.ttl create mode 120000 ns/ext/pui/waf create mode 120000 ns/ext/pui/wscript create mode 120000 ns/ext/reference/ext.pc.in create mode 100644 ns/ext/reference/manifest.ttl create mode 100644 ns/ext/reference/reference.h create mode 100644 ns/ext/reference/reference.ttl create mode 120000 ns/ext/reference/waf create mode 120000 ns/ext/reference/wscript create mode 120000 ns/ext/resize-port/ext.pc.in create mode 100644 ns/ext/resize-port/manifest.ttl create mode 100644 ns/ext/resize-port/resize-port.h create mode 100644 ns/ext/resize-port/resize-port.ttl create mode 120000 ns/ext/resize-port/waf create mode 120000 ns/ext/resize-port/wscript create mode 120000 ns/ext/state/ext.pc.in create mode 100644 ns/ext/state/manifest.ttl create mode 100644 ns/ext/state/state.h create mode 100644 ns/ext/state/state.ttl create mode 120000 ns/ext/state/waf create mode 120000 ns/ext/state/wscript create mode 120000 ns/ext/string-port/ext.pc.in create mode 100644 ns/ext/string-port/manifest.ttl create mode 100644 ns/ext/string-port/string-port.h create mode 100644 ns/ext/string-port/string-port.ttl create mode 120000 ns/ext/string-port/waf create mode 120000 ns/ext/string-port/wscript create mode 120000 ns/ext/time/ext.pc.in create mode 100644 ns/ext/time/manifest.ttl create mode 100644 ns/ext/time/time.h create mode 100644 ns/ext/time/time.ttl create mode 120000 ns/ext/time/waf create mode 120000 ns/ext/time/wscript create mode 120000 ns/ext/ui-resize/ext.pc.in create mode 100644 ns/ext/ui-resize/manifest.ttl create mode 100644 ns/ext/ui-resize/ui-resize.h create mode 100644 ns/ext/ui-resize/ui-resize.ttl create mode 120000 ns/ext/ui-resize/waf create mode 120000 ns/ext/ui-resize/wscript create mode 120000 ns/ext/uri-map/ext.pc.in create mode 100644 ns/ext/uri-map/manifest.ttl create mode 100644 ns/ext/uri-map/uri-map.h create mode 100644 ns/ext/uri-map/uri-map.ttl create mode 120000 ns/ext/uri-map/waf create mode 120000 ns/ext/uri-map/wscript create mode 120000 ns/ext/uri-unmap/ext.pc.in create mode 100644 ns/ext/uri-unmap/manifest.ttl create mode 100644 ns/ext/uri-unmap/uri-unmap.h create mode 100644 ns/ext/uri-unmap/uri-unmap.ttl create mode 120000 ns/ext/uri-unmap/waf create mode 120000 ns/ext/uri-unmap/wscript create mode 120000 ns/ext/urid/ext.pc.in create mode 100644 ns/ext/urid/manifest.ttl create mode 100644 ns/ext/urid/urid.h create mode 100644 ns/ext/urid/urid.ttl create mode 120000 ns/ext/urid/waf create mode 120000 ns/ext/urid/wscript (limited to 'ns/ext') diff --git a/ns/ext/atom/atom-buffer.h b/ns/ext/atom/atom-buffer.h new file mode 100644 index 0000000..f4b90dd --- /dev/null +++ b/ns/ext/atom/atom-buffer.h @@ -0,0 +1,163 @@ +/* + Copyright 2008-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file atom-event-buffer.h Helper functions for atom:EventBuffer. + + Note that these functions are all static inline which basically means: + do not take the address of these functions. +*/ + +#ifndef LV2_ATOM_EVENT_BUFFER_H +#define LV2_ATOM_EVENT_BUFFER_H + +#include +#include +#include +#include + +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" + +/** + Initialize an existing atom buffer. + All fields of @c buf are reset, except capacity which is unmodified. +*/ +static inline void +lv2_atom_buffer_reset(LV2_Atom_Buffer* buf) +{ + buf->event_count = 0; + buf->size = 0; +} + +/** + Allocate a new, empty atom buffer. +*/ +static inline LV2_Atom_Buffer* +lv2_atom_buffer_new(uint32_t capacity) +{ + const uint32_t size = sizeof(LV2_Atom_Buffer) + capacity; + LV2_Atom_Buffer* buf = (LV2_Atom_Buffer*)malloc(size); + if (buf) { + buf->data = (uint8_t*)(buf + 1); + buf->capacity = capacity; + lv2_atom_buffer_reset(buf); + } + return buf; +} + +/** + Free an atom buffer allocated with lv2_atom_buffer_new(). +*/ +static inline void +lv2_atom_buffer_free(LV2_Atom_Buffer* buf) +{ + free(buf); +} + +/** + An iterator over an LV2_Atom_Buffer. +*/ +typedef struct { + LV2_Atom_Buffer* buf; + uint32_t offset; +} LV2_Atom_Buffer_Iterator; + +/** + Return an iterator to the beginning of @c buf. +*/ +static inline LV2_Atom_Buffer_Iterator +lv2_atom_buffer_begin(LV2_Atom_Buffer* buf) +{ + const LV2_Atom_Buffer_Iterator i = { buf, 0 }; + return i; +} + +/** + Return true iff @c i points to a valid atom. +*/ +static inline bool +lv2_atom_buffer_is_valid(LV2_Atom_Buffer_Iterator i) +{ + return i.offset < i.buf->size; +} + +/** + Return the iterator to the next element after @c i. + @param i A valid iterator to an atom in a buffer. +*/ +static inline LV2_Atom_Buffer_Iterator +lv2_atom_buffer_next(LV2_Atom_Buffer_Iterator i) +{ + if (!lv2_atom_buffer_is_valid(i)) { + return i; + } + const LV2_Atom_Event* const ev = (LV2_Atom_Event*)(i.buf->data + i.offset); + i.offset += lv2_atom_pad_size(sizeof(LV2_Atom_Event) + ev->body.size); + return i; +} + +/** + Return a pointer to the atom currently pointed to by @c i. +*/ +static inline LV2_Atom_Event* +lv2_atom_buffer_get(LV2_Atom_Buffer_Iterator i) +{ + if (!lv2_atom_buffer_is_valid(i)) { + return NULL; + } + return (LV2_Atom_Event*)(i.buf->data + i.offset); +} + +/** + Write an atom to a buffer. + + The atom will be written at the location pointed to by @c i, which will be + incremented to point to the location where the next atom should be written + (which is likely now garbage). Thus, this function can be called repeatedly + with a single @c i to write a sequence of atoms to the buffer. + + @return True if atom was written, otherwise false (buffer is full). +*/ +static inline bool +lv2_atom_buffer_write(LV2_Atom_Buffer_Iterator* i, + uint32_t frames, + uint32_t subframes, + uint32_t type, + uint32_t size, + const uint8_t* data) +{ + const uint32_t free_space = i->buf->capacity - i->buf->size; + if (free_space < sizeof(LV2_Atom_Event) + size) { + return false; + } + + LV2_Atom_Event* const ev = (LV2_Atom_Event*)(i->buf->data + i->offset); + + ev->frames = frames; + ev->subframes = subframes; + ev->body.type = type; + ev->body.size = size; + memcpy((uint8_t*)ev + sizeof(LV2_Atom_Event), data, size); + ++i->buf->event_count; + + size = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + size); + i->buf->size += size; + i->offset += size; + + return true; +} + +#endif /* LV2_ATOM_EVENT_BUFFER_H */ diff --git a/ns/ext/atom/atom-helpers.h b/ns/ext/atom/atom-helpers.h new file mode 100644 index 0000000..4e51c89 --- /dev/null +++ b/ns/ext/atom/atom-helpers.h @@ -0,0 +1,174 @@ +/* + Copyright 2008-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file atom-helpers.h Helper functions for the LV2 Atom extension. + + These functions are provided for convenience only, use of them is not + required for supporting atoms. + + Note that these functions are all static inline which basically means: + do not take the address of these functions. +*/ + +#ifndef LV2_ATOM_HELPERS_H +#define LV2_ATOM_HELPERS_H + +#include +#include +#include +#include + +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" + +typedef LV2_Atom_Property* LV2_Thing_Iter; + +/** Get an iterator pointing to @c prop in some LV2_Thing */ +static inline LV2_Thing_Iter +lv2_thing_begin(const LV2_Thing* obj) +{ + return (LV2_Thing_Iter)(obj->properties); +} + +/** Return true iff @c iter has reached the end of @c thing */ +static inline bool +lv2_thing_iter_is_end(const LV2_Thing* obj, LV2_Thing_Iter iter) +{ + return (uint8_t*)iter >= ((uint8_t*)obj + sizeof(LV2_Atom) + obj->size); +} + +/** Return true iff @c l points to the same property as @c r */ +static inline bool +lv2_thing_iter_equals(const LV2_Thing_Iter l, const LV2_Thing_Iter r) +{ + return l == r; +} + +/** Return an iterator to the property following @c iter */ +static inline LV2_Thing_Iter +lv2_thing_iter_next(const LV2_Thing_Iter iter) +{ + return (LV2_Thing_Iter)((uint8_t*)iter + + sizeof(LV2_Atom_Property) + + lv2_atom_pad_size(iter->value.size)); +} + +/** Return the property pointed to by @c iter */ +static inline LV2_Atom_Property* +lv2_thing_iter_get(LV2_Thing_Iter iter) +{ + return (LV2_Atom_Property*)iter; +} + +/** + A macro for iterating over all properties of an Thing. + @param thing The thing to iterate over + @param iter The name of the iterator + + This macro is used similarly to a for loop (which it expands to), e.g.: +
+   LV2_THING_FOREACH(thing, i) {
+   LV2_Atom_Property* prop = lv2_thing_iter_get(i);
+   // Do things with prop here...
+   }
+   
+*/ +#define LV2_THING_FOREACH(thing, iter) \ + for (LV2_Thing_Iter (iter) = lv2_thing_begin(thing); \ + !lv2_thing_iter_is_end(thing, (iter)); \ + (iter) = lv2_thing_iter_next(iter)) + +/** + Append a Property body to an Atom that contains properties (e.g. atom:Thing). + @param thing Pointer to the atom that contains the property to add. thing.size + must be valid, but thing.type is ignored. + @param key The key of the new property + @param value_type The type of the new value + @param value_size The size of the new value + @param value_body Pointer to the new value's data + @return a pointer to the new LV2_Atom_Property in @c body. + + This function will write the property body (not including an LV2_Thing + header) at lv2_atom_pad_size(body + size). Thus, it can be used with any + Atom type that contains headerless 32-bit aligned properties. +*/ +static inline LV2_Atom_Property* +lv2_thing_append(LV2_Thing* thing, + uint32_t key, + uint32_t value_type, + uint32_t value_size, + const void* value_body) +{ + thing->size = lv2_atom_pad_size(thing->size); + LV2_Atom_Property* prop = (LV2_Atom_Property*)( + (uint8_t*)thing + sizeof(LV2_Atom) + thing->size); + prop->key = key; + prop->value.type = value_type; + prop->value.size = value_size; + memcpy(prop->value.body, value_body, value_size); + thing->size += sizeof(LV2_Atom_Property) + value_size; + return prop; +} + +/** Return true iff @c atom is NULL */ +static inline bool +lv2_atom_is_null(LV2_Atom* atom) +{ + return !atom || (atom->type == 0 && atom->size == 0); +} + +/** A single entry in an Thing query. */ +typedef struct { + uint32_t key; /**< Key to query (input set by user) */ + const LV2_Atom** value; /**< Found value (output set by query function) */ +} LV2_Thing_Query; + +static const LV2_Thing_Query LV2_THING_QUERY_END = { 0, NULL }; + +/** + "Query" an thing, getting a pointer to the values for various keys. + + The value pointer of each item in @c query will be set to the location of + the corresponding value in @c thing. Every value pointer in @c query MUST + be initialised to NULL. This function reads @c thing in a single linear + sweep. By allocating @c query on the stack, things can be "queried" + quickly without allocating any memory. This function is realtime safe. +*/ +static inline int +lv2_thing_query(const LV2_Thing* thing, LV2_Thing_Query* query) +{ + int matches = 0; + int n_queries = 0; + + /* Count number of query keys so we can short-circuit when done */ + for (LV2_Thing_Query* q = query; q->key; ++q) + ++n_queries; + + LV2_THING_FOREACH(thing, o) { + const LV2_Atom_Property* prop = lv2_thing_iter_get(o); + for (LV2_Thing_Query* q = query; q->key; ++q) { + if (q->key == prop->key && !*q->value) { + *q->value = &prop->value; + if (++matches == n_queries) + return matches; + break; + } + } + } + return matches; +} + +#endif /* LV2_ATOM_HELPERS_H */ diff --git a/ns/ext/atom/atom.h b/ns/ext/atom/atom.h new file mode 100644 index 0000000..39d721c --- /dev/null +++ b/ns/ext/atom/atom.h @@ -0,0 +1,248 @@ +/* + Copyright 2008-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file atom.h C header for the LV2 Atom extension + . + + This header describes the binary layout of various types defined in the + atom extension. +*/ + +#ifndef LV2_ATOM_H +#define LV2_ATOM_H + +#define LV2_ATOM_URI "http://lv2plug.in/ns/ext/atom" + +#define LV2_ATOM_REFERENCE_TYPE 0 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + An LV2 Atom. + + An "Atom" is a generic chunk of memory with a given type and size. + The type field defines how to interpret an atom. + + All atoms are by definition Plain Old Data (POD) and may be safely copied + (e.g. with memcpy) using the size field, except atoms with type 0. An atom + with type 0 is a reference, and may only be used via the functions provided + in LV2_Blob_Support (e.g. it MUST NOT be manually copied). +*/ +typedef struct { + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint8_t body[]; /**< Body of length @ref size bytes. */ +} LV2_Atom; + +/** + An atom:String. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint8_t str[]; /**< Null-terminated string data in UTF-8 encoding. */ +} LV2_Atom_String; + +/** + An atom:Literal. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t datatype; /**< The ID of the datatype of this literal. */ + uint32_t lang; /**< The ID of the language of this literal. */ + uint8_t str[]; /**< Null-terminated string data in UTF-8 encoding. */ +} LV2_Atom_Literal; + +/** + An atom:URID or atom:BlankID. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t id; /**< URID (integer mapped URI) or blank node ID. */ +} LV2_Atom_ID; + +/** + An atom:Vector. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t elem_count; /**< The number of elements in the vector */ + uint32_t elem_type; /**< The type of each element in the vector */ + uint8_t elems[]; /**< Sequence of element bodies */ +} LV2_Atom_Vector; + +/** + The body of an atom:Property. + Note this type is not an LV2_Atom. +*/ +typedef struct _LV2_Atom_Property { + uint32_t key; /**< Key (predicate) (mapped URI). */ + LV2_Atom value; /**< Value (object) */ +} LV2_Atom_Property; + +/** + An atom:Thing (Resource, Blank, or Message). + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; /**< Type of this atom (mapped URI). */ + uint32_t size; /**< Size in bytes, not including type and size. */ + uint32_t context; /**< ID of context graph, or 0 for default */ + uint32_t id; /**< URID (for Resource) or blank ID (for Blank) */ + uint8_t properties[]; /**< Sequence of LV2_Atom_Property */ +} LV2_Thing; + +/** + An atom:Event, a timestamped Atom. + Note this type is not an LV2_Atom, but contains an Atom as payload. +*/ +typedef struct { + uint32_t frames; /**< Time in frames relative to this block. */ + uint32_t subframes; /**< Fractional time in 1/(2^32)ths of a frame. */ + LV2_Atom body; /**< Event body. */ +} LV2_Atom_Event; + +/** + An atom:Int32, a signed 32-bit integer. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; + uint32_t size; + int32_t value; +} LV2_Atom_Int32; + +/** + An atom:Int64, a signed 64-bit integer. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; + uint32_t size; + int64_t value; +} LV2_Atom_Int64; + +/** + An atom:Float, a 32-bit IEEE-754 floating point number. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; + uint32_t size; + float value; +} LV2_Atom_Float; + +/** + An atom:Double, a 64-bit IEEE-754 floating point number. + This type may safely be cast to LV2_Atom. +*/ +typedef struct { + uint32_t type; + uint32_t size; + double value; +} LV2_Atom_Double; + +/** + A buffer of events (the contents of an atom:EventPort). + + The host MAY elect to allocate buffers as a single chunk of POD by using + this struct as a header much like LV2_Atom, or it may choose to point to + a fragment of a buffer elsewhere. In either case, @ref data points to the + start of the data contained in this buffer. + + The buffer at @ref data contains a sequence of LV2_Atom_Event padded such + that the start of each event is aligned to 64 bits, e.g.: +
+   | Event 1 (size 6)                              | Event 2
+   |       |       |       |       |       |       |       |       |
+   | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
+   |FRAMES |SUBFRMS|TYPE   |SIZE   |DATADATADATAPAD|FRAMES |SUBFRMS|...
+   
+*/ +typedef struct { + + /** + The contents of the event buffer. This may or may not reside in the + same block of memory as this header, plugins must not assume either. + The host guarantees this points to at least capacity bytes of allocated + memory (though only size bytes of that are valid events). + */ + uint8_t* data; + + /** + The number of events in this buffer. + + INPUTS: The host must set this field to the number of events contained + in the data buffer before calling run(). The plugin must not change + this field. + + OUTPUTS: The plugin must set this field to the number of events it has + written to the buffer before returning from run(). Any initial value + should be ignored by the plugin. + */ + uint32_t event_count; + + /** + The capacity of the data buffer in bytes. + This is set by the host and must not be changed by the plugin. + The host is allowed to change this between run() calls. + */ + uint32_t capacity; + + /** + The size of the initial portion of the data buffer containing data. + + INPUTS: The host must set this field to the number of bytes used + by all events it has written to the buffer (including headers) + before calling the plugin's run(). + The plugin must not change this field. + + OUTPUTS: The plugin must set this field to the number of bytes + used by all events it has written to the buffer (including headers) + before returning from run(). + Any initial value should be ignored by the plugin. + */ + uint32_t size; + +} LV2_Atom_Buffer; + +/** + Pad a size to 64 bits. +*/ +static inline uint32_t +lv2_atom_pad_size(uint32_t size) +{ + return (size + 7) & (~7); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_ATOM_H */ diff --git a/ns/ext/atom/atom.ttl b/ns/ext/atom/atom.ttl new file mode 100644 index 0000000..0ef3b34 --- /dev/null +++ b/ns/ext/atom/atom.ttl @@ -0,0 +1,436 @@ +# LV2 Atom Extension +# Copyright 2007-2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix atom: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix owl: . + + + a lv2:Specification ; + doap:name "LV2 Atom" ; + doap:shortdesc "A generic value container and several data types." ; + doap:license ; + rdfs:seeAlso ; + doap:release [ + doap:revision "0.2" ; + doap:created "2011-11-05" + ] ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + lv2:documentation """ +

This extension defines a generic format for a typed piece of data, called an +lv2:Atom (e.g. integers, strings, buffers, data structures, +etc). Atoms allow LV2 plugins and hosts to communicate, process, serialise, +and store values of any type via a generic mechanism (e.g. LV2 ports, events, +disk, shared memory, network). Atoms are, with one exception, Plain +Old Data (POD) and may be safely copied (e.g. with a simple call to +memcpy).

+ +

Since Atom communication can be implemented generically, plugins that +understand some type can be used together in a host that does not understand +that type, and plugins (e.g. routers, delays) can process atoms of unknown +type.

+ +

An Atom can be trivially constructed in-place from an +Event as defined by the +LV2 Event extension. In other +words, an Event is simply an Atom with a time stamp header. Atoms SHOULD +be used anywhere a "value" needs to be stored or communicated, to allow +implementations to be polymorphic and extensible.

+ +

Atoms (the start of the LV2_Atom header) MUST be 32-bit aligned.

+ +

Atoms can be communicated in many ways. Since an Atom is the payload of an +Event, an EventPort can +be used for communicating Atoms in realtime with sub-sample time stamp +accuracy. This extension also defines two port types for connecting directly +to a single Atom: atom:ValuePort and atom:MessagePort, which both have the same +buffer format but different semantics (with respect to how the run() callback +interprets the Atom).

+ +

Implementing this extension requires a facility for mapping URIs to +integers, such as the LV2 URID +extension.

+""" . + +atom:Atom + a rdfs:Class ; + rdfs:label "Atom" ; + atom:cType "LV2_Atom" ; + lv2:documentation """ +

Abstract base class for all atoms. An LV2_Atom has a 32-bit +type and size followed by a body of +size bytes.

+ +

All concrete Atom types (subclasses of this class) MUST define a precise +binary layout for body.

+ +

The type field is the URI of a subclass of Atom mapped to an +integer using the URI Map +extension's LV2_URI_Map_Feature::uri_to_id() with +map = "http://lv2plug.in/ns/ext/event". If a plugin or host +does not understand type, that atom SHOULD be gracefully ignored +(or copied if it does not have type 0).

+ +

All atoms are POD by definition except references, which as a special case +have type = 0. An Atom MUST NOT contain a Reference. It is safe +to copy any non-reference Atom with a simple memcpy, even if the +implementation does not understand type. Though this extension reserves +the type 0 for references, actual specification of how references are used is left +to another extension.

+""" . + +atom:String + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "String" ; + atom:cType "LV2_Atom_String" ; + lv2:documentation """ +

A UTF-8 encoded string.

+ +

The body of an LV2_Atom_String is a C string in UTF-8 encoding, i.e. an +array of bytes (uint8_t) terminated with a NULL byte +('\\0').

+ +

This type can be used for free-form strings, but in most cases it is better to +use atom:Literal since this supports a language tag or datatype. Implementations +SHOULD NOT use atom:String unless translating the string does not make sense and +the string has no meaningful datatype.

+""" . + +atom:Literal + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "String Literal" ; + atom:cType "LV2_Atom_Literal" ; + lv2:documentation """ +

A UTF-8 encoded string literal, with an optional datatype or language.

+ +

This type is compatible with rdf:Literal and is capable of expressing a +string in any language, or a value of any type. A Literal has a +datatype and lang followed by string data in UTF-8 +encoding. The length of the string data in bytes is size - +sizeof(LV2_Atom_Literal), including the terminating NULL character. The +lang field SHOULD be a URI of the form +<http://lexvo.org/id/term/LANG> where LANG is an ISO 693-2 or ISO 693-3 language code.

+ +

For compatibility, a Literal MUST have either a datatype +or a lang, but never both.

+ +

For example, a Literal can be "Hello" in English:

+
+void set_to_hello_in_english(LV2_Atom_Literal* lit) {
+     lit->type     = map(expand("atom:Literal"));
+     lit->size     = 14;
+     lit->datatype = 0;
+     lit->lang     = map("http://lexvo.org/id/term/en");
+     memcpy(lit->str, "Hello", sizeof("Hello"));  // Assumes enough space
+}
+
+ +

or a Turtle string:

+
+void set_to_turtle_string(LV2_Atom_Literal* lit, const char* ttl) {
+     lit->type     = map(expand("atom:Literal"));
+     lit->size     = 64;
+     lit->datatype = map("http://www.w3.org/2008/turtle#turtle");
+     lit->lang     = 0;
+     memcpy(lit->str, ttl, strlen(ttl) + 1);  // Assumes enough space
+}
+
+""" . + +atom:URID + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Integer ID mapped from a URI" ; + atom:cType "LV2_Atom_ID" ; + lv2:documentation """ +

An unsigned 32-bit integer mapped from a URI using the URI Map extension's +LV2_URI_Map_Feature::uri_to_id() with map = NULL.

+""" . + +atom:BlankID + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Integer ID for a blank node" ; + atom:cType "LV2_Atom_ID" ; + lv2:documentation """ +

An unsigned 32-bit integer identifier for a blank node. A BlankID is only +meaningful within a limited scope (e.g. the Atom in which it appears), and +MUST NOT be used as a global identifier. In particular, a BlankID is NOT a +URID, and can not be mapped to/from a URI.

+""" . + +atom:Vector + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Vector" ; + atom:cType "LV2_Atom_Vector" ; + lv2:documentation """ +

A homogeneous sequence of atoms with equivalent type and size.

+ +

An LV2_Atom_Vector is a 32-bit elem_count and +elem_type followed by elem_count atom bodies of type +elem_type. The element type must be a fixed size atom:Atom type, +i.e. the size of each element is the vector's size / +elem_count.

+ +

For example, an atom:Vector containing 42 elements of type atom:Float:

+
+struct VectorOf42Floats {
+    uint32_t type;        // map(expand("atom:Vector"))
+    uint32_t size;        // sizeof(LV2_Atom_Vector) + (42 * sizeof(float);
+    uint32_t elem_count;  // 42
+    uint32_t elem_type;   // map(expand("atom:Float"))
+    float    elems[32];
+};
+
+ +

Note that it is possible to construct a valid Atom for each element +of the vector, even by an implementation which does not understand +elem_type.

+""" . + +atom:Tuple + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Tuple" ; + lv2:documentation """ +

A sequence of lv2:Atom with varying type +and size.

+ +

The body of a Tuple is simply a sequence of complete atoms, each aligned to +32 bits.

+""" . + +atom:Thing + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Thing" ; + atom:cType "LV2_Thing" ; + lv2:documentation """ +

Abstract base class for a "Thing", i.e. an atom:Atom with a +number of properties. An LV2_Object is an unsigned +32-bit integer context and id followed by a sequence +of LV2_Atom_Property .

+ +

The context is mapped using the URI Map extension's +LV2_URI_Map_Feature::uri_to_id() with map = NULL, and may be 0 +(the default context).

+ +

Note this is an abstract class, i.e. no Atom can exist with type = +uri_to_id(atom:Thing). An Object is either an atom:Resource or an +atom:Blank, but the body always has the same binary format, +LV2_Object. Thus, both named and anonymous objects can be handled with common +code using only a 64-bit header for both.

+""" . + +atom:Resource + a rdfs:Class ; + rdfs:subClassOf atom:Thing ; + atom:cType "LV2_Thing" ; + lv2:documentation """ +

An atom:Thing where id is the URI of the resource mapped to an +atom:URID.

+""" . + +atom:Blank + a rdfs:Class ; + rdfs:subClassOf atom:Thing ; + atom:cType "LV2_Thing" ; + lv2:documentation """ +

An atom:Thing where id is the blank node ID of the object, +which is only meaningful within a certain limited scope (e.g. the container of +the Blank) and MUST NOT be used as a global ID. In particular, id +is NOT an ID.

+""" . + +atom:Message + a rdfs:Class ; + rdfs:subClassOf atom:Thing ; + atom:cType "LV2_Thing" ; + lv2:documentation """ +

A atom:Thing where id is a message type ID. Conceptually, a +Message is identical to a Blank, but is a distinct type with a single type +field to allow simple and fast dispatch by handling code.

+ +

A Message may be serialised as a Blank by adding an rdf:type property with +the value id unmapped to a URI.

+""" . + +atom:Event + a rdfs:Class ; + rdfs:label "Event" ; + atom:cType "LV2_Atom_Event" ; + lv2:documentation """ +

An atom with a time stamp header prepended, typically for sample accurate +transmission via LV2 ports. See struct LV2_Atom_Event.

+""" . + +atom:Bang + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Bang (activity) (size = 0)" . + +atom:Number + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Number (abstract class)." . + +atom:Int32 + a rdfs:Class ; + rdfs:subClassOf atom:Number ; + rdfs:label "Signed 32-bit integer" ; + atom:cType "LV2_Atom_Int32" . + +atom:Int64 + a rdfs:Class ; + rdfs:subClassOf atom:Number ; + rdfs:label "Signed 64-bit integer" ; + atom:cType "LV2_Atom_Int64" . + +atom:Bool + a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "An atom:Int32 where 0 is false and all other values true" ; + atom:cType "LV2_Atom_Int32" . + +atom:Float + a rdfs:Class ; + rdfs:subClassOf atom:Number ; + rdfs:label "32-bit IEEE-754 floating point number" ; + atom:cType "LV2_Atom_Float" . + +atom:Double + a rdfs:Class ; + rdfs:subClassOf atom:Number ; + rdfs:label "64-bit IEEE-754 floating point number" ; + atom:cType "LV2_Atom_Double" . + +atom:blobSupport + a lv2:Feature ; + rdfs:label "Blob support" ; + lv2:documentation """ +

Support for dynamically allocated blobs. If a host supports this feature, +it MUST pass a LV2_Feature with URI +http://lv2plug.in/ns/ext/atom#blobSupport and data pointing to a +LV2_Blob_Support.

+""" . + +atom:AtomPort + a rdfs:Class ; + rdfs:subClassOf lv2:Port ; + rdfs:label "Atom Port" ; + lv2:documentation """ +

A port which contains an lv2:Atom. Ports of this type will +be connected to a 32-bit aligned LV2_Atom immediately followed by +size bytes of data.

+ +

This is an abstract port type, i.e. a port MUST NOT only be an AtomPort, +but must be a more descriptive type that is a subclass of AtomPort which +defines the port's semantics (typically atom:ValuePort or atom:MessagePort). +

+ +

Before calling a method on the plugin that writes to an AtomPort output, +the host MUST set the size of the Atom in that output to the amount of +available memory immediately following the Atom header. The plugin MUST +write a valid Atom to that port (leaving it untouched is illegal). If there +is no reasonable value to write to the port, the plugin MUST write NULL +(the Atom with both type = 0 and size = 0).

+""" . + +atom:ValuePort + a rdfs:Class ; + rdfs:subClassOf atom:AtomPort ; + rdfs:label "Value Port" ; + lv2:documentation """ +

An AtomPort that interprets its data as a persistent and time-independent +"value".

+
    +
  • If a plugin has fixed input values for all ports, all ValuePort outputs +are also fixed regardless of the number of times the plugin is run.
  • +
  • If a plugin has fixed input values for all ports except a ValuePort, +each value V of that ValuePort corresponds to a single set of outputs +for all ports.
  • +
  • If a ValuePort contains a reference then the blob it refers to is +constant; plugin MUST NOT modify the blob in any way.
  • +
+

Value ports can be thought of as purely functional ports: if a plugin +callback has only value ports, then the plugin callback is a pure function.

+""" . + +atom:MessagePort + a rdfs:Class ; + rdfs:subClassOf atom:AtomPort ; + rdfs:label "Message Port" ; + rdfs:comment """ +An AtomPort that "receives", "consumes", "executes", or "sends" its value. +The Atom contained in a MessagePort is considered transient and/or +time-dependent, and is only valid for a single run invocation. Unlike a +ValuePort, a MessagePort may be used to manipulate internal plugin state. + +Intuitively, a MessagePort contains a "message" or "command" or "event" +which is reacted to, NOT a "value" or "signal" (which is computed with). +""" . + +atom:cType + a rdf:Property , + owl:DatatypeProperty ; + rdfs:label "C type" ; + rdfs:domain rdfs:Class ; + rdfs:range xsd:string ; + rdfs:comment """ +The identifier for a C type describing the in-memory representation of +an instance of this class. +""" . + +atom:EventPort + a rdfs:Class ; + rdfs:label "Event port" ; + rdfs:subClassOf lv2:Port ; + lv2:documentation """ +

A port used for communicating time-stamped atoms in the audio context. +Ports of this type are connected to an LV2_Atom_Buffer, which contains a flat +time-stamped sequence of atom:Event.

+ +

This port type is intended as a simpler and atom compatible successor to ev:EventPort.

+""" . + +atom:supports + a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range atom:Atom ; + rdfs:label "supports" ; + lv2:documentation """ +

Indicates that a Port supports a certain atom:Atom type. This is distinct from +the port type - e.g. the port type ValuePort can hold atoms with many different +types. This property is used to describe which Atom types a Port expects to +receive or send.

+""" . diff --git a/ns/ext/atom/ext.pc.in b/ns/ext/atom/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/atom/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/atom/forge.h b/ns/ext/atom/forge.h new file mode 100644 index 0000000..e8f5d40 --- /dev/null +++ b/ns/ext/atom/forge.h @@ -0,0 +1,75 @@ +/* + Copyright 2008-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file forge.h Helper constructor functions for LV2 atoms. +*/ + +#ifndef LV2_ATOM_FORGE_H +#define LV2_ATOM_FORGE_H + +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" +#include "lv2/lv2plug.in/ns/ext/urid/urid.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint32_t ID; + uint32_t Message; + uint32_t Property; +} LV2_Atom_Forge; + +static inline LV2_Atom_Forge* +lv2_atom_forge_new(LV2_URID_Map* map) +{ + LV2_Atom_Forge* forge = (LV2_Atom_Forge*)malloc(sizeof(LV2_Atom_Forge)); + forge->ID = map->map(map->handle, LV2_ATOM_URI "#ID"); + forge->Message = map->map(map->handle, LV2_ATOM_URI "#Message"); + forge->Property = map->map(map->handle, LV2_ATOM_URI "#Property"); + return forge; +} + +static inline void +lv2_atom_forge_free(LV2_Atom_Forge* forge) +{ + free(forge); +} + +static inline LV2_Atom_ID +lv2_atom_forge_make_id(LV2_Atom_Forge* forge, uint32_t id) +{ + const LV2_Atom_ID atom = { forge->ID, sizeof(uint32_t), id }; + return atom; +} + +static inline void +lv2_atom_forge_set_message(LV2_Atom_Forge* forge, + LV2_Thing* msg, + uint32_t id) +{ + msg->type = forge->Message; + msg->size = sizeof(LV2_Thing) - sizeof(LV2_Atom); + msg->context = 0; + msg->id = id; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_ATOM_FORGE_H */ diff --git a/ns/ext/atom/manifest.ttl b/ns/ext/atom/manifest.ttl new file mode 100644 index 0000000..adb10e5 --- /dev/null +++ b/ns/ext/atom/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 2 ; + rdfs:seeAlso . + diff --git a/ns/ext/atom/waf b/ns/ext/atom/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/atom/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/atom/wscript b/ns/ext/atom/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/atom/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/contexts/contexts.h b/ns/ext/contexts/contexts.h new file mode 100644 index 0000000..f49b474 --- /dev/null +++ b/ns/ext/contexts/contexts.h @@ -0,0 +1,82 @@ +/* LV2 Contexts Extension + * Copyright (C) 2007-2009 David Robillard + * + * This header is free software; you can redistribute it and/or modify it + * under the terms of the GNU 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +/** @file + * C header for the LV2 Contexts extension + * . + */ + +#ifndef LV2_CONTEXTS_H +#define LV2_CONTEXTS_H + +#include + +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" + +#define LV2_CONTEXTS_URI "http://lv2plug.in/ns/ext/contexts" + +static inline void +lv2_contexts_set_port_valid(void* flags, uint32_t index) { + ((uint8_t*)flags)[index / 8] |= 1 << (index % 8); +} + +static inline void +lv2_contexts_unset_port_valid(void* flags, uint32_t index) { + ((uint8_t*)flags)[index / 8] &= ~(1 << (index % 8)); +} + +static inline int +lv2_contexts_port_is_valid(const void* flags, uint32_t index) { + return (((uint8_t*)flags)[index / 8] & (1 << (index % 8))) != 0; +} + +typedef struct { + + /** The message run function. This is called once to process a set of + * inputs and produce a set of outputs. + * + * Before calling the host MUST set valid_inputs such that the bit + * corresponding to each input port is 1 iff data is present. The plugin + * MUST only inspect bits corresponding to ports in the message thread. + * + * Similarly, before returning the plugin MUST set valid_outputs such that + * the bit corresponding to each output port of the message context is 1 + * iff the value at that port has changed. + * The plugin must return 1 if outputs have been written, 0 otherwise. + */ + uint32_t (*run)(LV2_Handle instance, + const void* valid_inputs, + void* valid_outputs); + +} LV2_Contexts_MessageContext; + +typedef void* LV2_Contexts_Request_Run_Data; + +typedef struct { + + /** Pointer to opaque host data (to be passed to request_run) */ + LV2_Contexts_Request_Run_Data data; + + /** Request the host execute the context with the given URI */ + void (*request_run)(LV2_Contexts_Request_Run_Data host_handle, + uint32_t context_uri); + +} LV2_Contexts_Request_Run_Feature; + +#endif /* LV2_CONTEXTS_H */ + diff --git a/ns/ext/contexts/contexts.ttl b/ns/ext/contexts/contexts.ttl new file mode 100644 index 0000000..c56c649 --- /dev/null +++ b/ns/ext/contexts/contexts.ttl @@ -0,0 +1,134 @@ +# LV2 Contexts Extension +# +# Allows for an LV2 plugin to have several independent contexts, each with its +# own run callback and associated ports. +# +# Copyright (C) 2007-2010 David Robillard +# +# 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 ctx: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + + a lv2:Specification , lv2:Feature ; + doap:name "LV2 Contexts" ; + doap:shortdesc "Support for plugins with several execution contexts." ; + lv2:documentation """ +

An extension for LV2 plugins which have several execution contexts.

+ +

Contexts allow plugins to run tasks and/or process input/output in +multiple threads. Contexts can be used to add non-realtime functionality +to a plugin while still keeping the audio run() method realtime safe.

+ +

A context is an LV2 feature, so the usual LV2 feature mechanism is used +to determine whether a plugin has a given context, and whether or not it is +mandatory.

+ +

Unless otherwise stated, each context (defined by some URI) adds a new +threading class similar to the Audio class defined by LV2. Each context has a +run callback and a connect_port callback both in the same class (i.e. can't be +called concurrently), but may be called concurrently with functions for other +contexts (excluding the Instantiation class). Context properties such as +ctx:hardRTCapable apply to both functions. +The host MUST only call the correct connect_port function associated with the +context for that port, i.e. it is an error to use the main LV2 connect_port +function on a port with a context other than the main LV2 run function.

+""" . + + +########################## +## Context Base Classes ## +########################## + +ctx:Context a rdfs:Class ; + rdfs:label "LV2 Context" ; + lv2:documentation """ +

A potentially concurrent context (callback) on a plugin.

+ +

Ports are always associated with a context. If a port has no explicit context +property, then its context is ctx:audioContext (the default LV2 run() context).

+ +

A plugin indicates support for a context by supporting an LV2 Feature with +that context's URI. If a plugin optionally supports a context (e.g. +<plugin> lv2:optionalFeature ctx:idleContext .), then +all ports associated with that context MUST be lv2:connectionOptional. Thus, +hosts that do not support contexts will connect such ports to NULL and the +plugin can run with only a standard LV2 run() context.

+ +

Any plugin that supports any context (optionally or mandatorily) MUST adhere +to the following additional threading rules for LV2_Descriptor.connect_port:

+
    +
  • connect_port MUST only be called for a given port from the context +associated with that port
  • +
  • connect_port MAY be called concurrently for ports with different +contexts (but MUST NOT be called concurrently for multiple ports in the +same context)
  • +
+

Note this implies that any shared data access in connect_port may be +accessed concurrently. The plugin is responsible for any synchronisation +or locking necessary to make this possible.

+""" . + +ctx:audioContext a ctx:Context , lv2:Feature ; + rdfs:comment """The context of LV2_Descriptor.run().""" . + +ctx:messageContext a ctx:Context , lv2:Feature ; + lv2:documentation """ +

A non-realtime context for plugin control via message passing. This context +has a run method which takes a bitset of flags for parameters specifying which +input and output ports are valid before and after the run method has executed, +respectively (see LV2_Contexts_MessageContext).

+""" . + +ctx:idleContext a ctx:Context , lv2:Feature ; + rdfs:comment """ +A non-realtime idle context, periodically run by the host roughly every second. +This context never has any ports. +""" . + +ctx:requestRunFeature a lv2:Feature ; + lv2:documentation """ +

A feature allowing the plugin to request the execution of a particular +context at an arbitrary time. To support this feature, the host MUST pass an +LV2_Feature to instantiate with data pointing to a +LV2_Contexts_Request_Run_Feature.

+ +

The plugin MAY call request_run with the given +data from any non-realtime context to demand soon-as-possible execution +of the specified context.

+""" . + +ctx:context a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range ctx:Context ; + rdfs:label "is used in context" ; + rdfs:comment """ +The context a particular port is associated with; the port will only be +connected/read/written by that context. + +If no context is specified, the port is considered part of the default LV2 +audio context.""" . + + diff --git a/ns/ext/contexts/ext.pc.in b/ns/ext/contexts/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/contexts/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/contexts/manifest.ttl b/ns/ext/contexts/manifest.ttl new file mode 100644 index 0000000..d2cc036 --- /dev/null +++ b/ns/ext/contexts/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/contexts/test.c b/ns/ext/contexts/test.c new file mode 100644 index 0000000..ca41a10 --- /dev/null +++ b/ns/ext/contexts/test.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include +#include +#include "contexts.h" + +#define TEST_ASSERT(check) do {\ + if (!(check)) {\ + fprintf(stderr, "Failure at line %d: %s\n", __LINE__, #check);\ + assert(false);\ + _exit(1);\ + }\ +} while (0) + +#define NUM_PORTS 64 + +void +print_flags(void* flags) +{ + for (int i = NUM_PORTS; i >= 0; --i) + printf((lv2_contexts_port_is_valid(flags, i)) ? "1" : "0"); + printf("\n"); +} + + +int +main() +{ + uint64_t flags = 0; + print_flags(&flags); + + lv2_contexts_set_port_valid(&flags, 16); + print_flags(&flags); + for (int i = 0; i < NUM_PORTS; ++i) { + if (i == 16) { + TEST_ASSERT(lv2_contexts_port_is_valid(&flags, i)); + } else { + TEST_ASSERT(!lv2_contexts_port_is_valid(&flags, i)); + } + } + + lv2_contexts_set_port_valid(&flags, 46); + lv2_contexts_set_port_valid(&flags, 0); + print_flags(&flags); + for (int i = 0; i < NUM_PORTS; ++i) { + if (i == 0 || i == 16 || i == 46) { + TEST_ASSERT(lv2_contexts_port_is_valid(&flags, i)); + } else { + TEST_ASSERT(!lv2_contexts_port_is_valid(&flags, i)); + } + } + + lv2_contexts_unset_port_valid(&flags, 16); + print_flags(&flags); + for (int i = 0; i < NUM_PORTS; ++i) { + if (i == 0 || i == 46) { + TEST_ASSERT(lv2_contexts_port_is_valid(&flags, i)); + } else { + TEST_ASSERT(!lv2_contexts_port_is_valid(&flags, i)); + } + } + + return 0; +} + diff --git a/ns/ext/contexts/waf b/ns/ext/contexts/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/contexts/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/contexts/wscript b/ns/ext/contexts/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/contexts/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/cv-port/cv-port.ttl b/ns/ext/cv-port/cv-port.ttl new file mode 100644 index 0000000..f49024b --- /dev/null +++ b/ns/ext/cv-port/cv-port.ttl @@ -0,0 +1,77 @@ +# LV2 CV Port Extension +# Copyright 2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix cv: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . + + + a lv2:Specification ; + doap:license ; + doap:name "LV2 CV Port" ; + doap:shortdesc "Control Voltage ports for LV2 plugins." ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + lv2:documentation """ +

This extension defines Control Voltage (CV) ports, which are audio-rate +control ports like those used on classical voltage-controlled synthesizers. +These ports serve as control ports like lv2:ControlPort but can +also be used for audio-rate modulation of control signals. This enables many +types of processing and synthesis which are not possible with a lower control +rate.

+""" . + +cv:CVPort + a rdfs:Class ; + rdfs:label "CV Port" ; + rdfs:subClassOf lv2:Port ; + lv2:documentation """ + +

Ports of this type have identical semantics to lv2:AudioPort in terms of +buffer format and connection/input/output logistics. However, rather than the +buffer representing audio, the buffer represents audio-rate control data. A +CVPort SHOULD have the same properties a lv2:ControlPort typically +has to describe appropriate control values (e.g. lv2:minimum, lv2:maximum, lv2:default)

+ +

Hosts SHOULD take care to prevent data from a CVPort port from being used as +audio except in cases where this is known to be safe.

+ +

Example:

+
+<http://example.org/some-plugin>
+    lv2:port [
+        a cv:CVPort, lv2:InputPort ;
+        lv2:index 0 ;
+        lv2:minimum -1.0 ;
+        lv2:maximum 1.0 ;
+        lv2:default 0.0 ;
+        lv2:symbol "modulation" ;
+        lv2:name "Modulation" ;
+    ] .
+
+""" . diff --git a/ns/ext/cv-port/ext.pc.in b/ns/ext/cv-port/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/cv-port/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/cv-port/manifest.ttl b/ns/ext/cv-port/manifest.ttl new file mode 100644 index 0000000..e5fa145 --- /dev/null +++ b/ns/ext/cv-port/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/cv-port/waf b/ns/ext/cv-port/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/cv-port/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/cv-port/wscript b/ns/ext/cv-port/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/cv-port/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/data-access/data-access.h b/ns/ext/data-access/data-access.h new file mode 100644 index 0000000..fac6974 --- /dev/null +++ b/ns/ext/data-access/data-access.h @@ -0,0 +1,56 @@ +/* + LV2 Data Access Extension + Copyright 2008-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file data-access.h + C header for the LV2 Extension Data extension + . + + This extension defines a method for (e.g.) plugin UIs to have (possibly + marshalled) access to the extension_data function on a plugin instance. +*/ + +#ifndef LV2_DATA_ACCESS_H +#define LV2_DATA_ACCESS_H + +#define LV2_DATA_ACCESS_URI "http://lv2plug.in/ns/ext/data-access" + +/** + The data field of the LV2_Feature for this extension. + + To support this feature the host must pass an LV2_Feature struct to the + instantiate method with URI "http://lv2plug.in/ns/ext/data-access" + and data pointed to an instance of this struct. +*/ +typedef struct { + /** + A pointer to a method the UI can call to get data (of a type specified + by some other extension) from the plugin. + + This call never is never guaranteed to return anything, UIs should + degrade gracefully if direct access to the plugin data is not possible + (in which case this function will return NULL). + + This is for access to large data that can only possibly work if the UI + and plugin are running in the same process. For all other things, use + the normal LV2 UI communication system. + */ + const void* (*data_access)(const char* uri); + +} LV2_Extension_Data_Feature; + +#endif /* LV2_DATA_ACCESS_H */ diff --git a/ns/ext/data-access/data-access.ttl b/ns/ext/data-access/data-access.ttl new file mode 100644 index 0000000..1f2ec04 --- /dev/null +++ b/ns/ext/data-access/data-access.ttl @@ -0,0 +1,82 @@ +# LV2 Data Access Extension +# Copyright 2008-2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix da: . +@prefix dcs: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix lv2ev: . +@prefix rdf: . +@prefix rdfs: . + + + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + foaf:mbox ; + rdfs:seeAlso . + + + a lv2:Specification , + doap:Project ; + doap:license ; + doap:name "LV2 Data Access" ; + doap:shortdesc "Provides access to LV2_Descriptor::extension_data()." ; + doap:developer ; + doap:release [ + doap:revision "1.4" ; + doap:created "2011-11-14" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Update packaging." + ] , [ + rdfs:label "Improve documentation." + ] + ] + ] , [ + doap:revision "1.2" ; + doap:created "2011-05-26" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Add build system for installation." + ] , [ + rdfs:label "Switch to ISC license." + ] + ] + ] , [ + doap:revision "1.0" ; + doap:created "2010-10-04" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Initial release." + ] + ] + ] ; + lv2:documentation """ +

This extension defines a feature, LV2_Extension_Data_Feature, which provides +access to LV2_Descriptor::extension_data() for plugin UIs or other potentially +remote users of a plugin.

+ +

To support this feature the host must pass an LV2_Feature struct to the +instantiate method with URI "http://lv2plug.in/ns/ext/data-access" and data +pointed to an instance of LV2_Extension_Data_Feature.

+""" . \ No newline at end of file diff --git a/ns/ext/data-access/ext.pc.in b/ns/ext/data-access/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/data-access/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/data-access/manifest.ttl b/ns/ext/data-access/manifest.ttl new file mode 100644 index 0000000..f7ccd9d --- /dev/null +++ b/ns/ext/data-access/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 1 ; + lv2:microVersion 4 ; + rdfs:seeAlso . + diff --git a/ns/ext/data-access/waf b/ns/ext/data-access/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/data-access/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/data-access/wscript b/ns/ext/data-access/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/data-access/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/dynmanifest/dynmanifest.h b/ns/ext/dynmanifest/dynmanifest.h new file mode 100644 index 0000000..56d829e --- /dev/null +++ b/ns/ext/dynmanifest/dynmanifest.h @@ -0,0 +1,144 @@ +/* + Dynamic manifest specification for LV2 + Copyright 2008-2011 Stefano D'Angelo + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file dynmanifest.h + C header for the LV2 Dynamic Manifest extension + . + Revision: 1.1 +*/ + +#ifndef LV2_DYN_MANIFEST_H_INCLUDED +#define LV2_DYN_MANIFEST_H_INCLUDED + +#include + +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" + +#define LV2_DYN_MANIFEST_URI "http://lv2plug.in/ns/ext/dynmanifest" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Dynamic manifest generator handle. + + This handle indicates a particular status of a dynamic manifest generator. + The host MUST NOT attempt to interpret it and, unlikely LV2_Handle, it is + NOT even valid to compare this to NULL. The dynamic manifest generator MAY + use it to reference internal data. +*/ +typedef void * LV2_Dyn_Manifest_Handle; + +/** + Generate the dynamic manifest. + + @param handle Pointer to an uninitialized dynamic manifest generator handle. + + @param features NULL terminated array of LV2_Feature structs which represent + the features the host supports. The dynamic manifest generator may refuse to + (re)generate the dynamic manifest if required features are not found here + (however hosts SHOULD NOT use this as a discovery mechanism, instead of + reading the static manifest file). This array must always exist; if a host + has no features, it MUST pass a single element array containing NULL. + + @return 0 on success, otherwise a non-zero error code. The host SHOULD + evaluate the result of the operation by examining the returned value and + MUST NOT try to interpret the value of handle. +*/ +int lv2_dyn_manifest_open(LV2_Dyn_Manifest_Handle * handle, + const LV2_Feature *const * features); + +/** + Fetch a "list" of subject URIs described in the dynamic manifest. + + The dynamic manifest generator has to fill the resource only with the needed + triples to make the host aware of the "objects" it wants to expose. For + example, if the plugin library exposes a regular LV2 plugin, it should + output only a triple like the following: + + a lv2:Plugin . + + The objects that are elegible for exposure are those that would need to be + represented by a subject node in a static manifest. + + @param handle Dynamic manifest generator handle. + + @param fp FILE * identifying the resource the host has to set up for the + dynamic manifest generator. The host MUST pass a writable, empty resource to + this function, and the dynamic manifest generator MUST ONLY perform write + operations on it at the end of the stream (e.g., using only fprintf(), + fwrite() and similar). + + @return 0 on success, otherwise a non-zero error code. +*/ +int lv2_dyn_manifest_get_subjects(LV2_Dyn_Manifest_Handle handle, + FILE * fp); + +/** + Function that fetches data related to a specific URI. + + The dynamic manifest generator has to fill the resource with data related to + object represented by the given URI. For example, if the library exposes a + regular LV2 plugin whose URI, as retrieved by the host using + lv2_dyn_manifest_get_subjects() is http://www.example.com/plugin/uri, it + should output something like: + +
+   
+       a lv2:Plugin ;
+       doap:name "My Plugin" ;
+       lv2:binary  ;
+       etc:etc "..." .
+   
+ + @param handle Dynamic manifest generator handle. + + @param fp FILE * identifying the resource the host has to set up for the + dynamic manifest generator. The host MUST pass a writable resource to this + function, and the dynamic manifest generator MUST ONLY perform write + operations on it at the current position of the stream (e.g. using only + fprintf(), fwrite() and similar). + + @param uri URI to get data about (in the "plain" form, i.e., absolute URI + without Turtle prefixes). + + @return 0 on success, otherwise a non-zero error code. +*/ +int lv2_dyn_manifest_get_data(LV2_Dyn_Manifest_Handle handle, + FILE * fp, + const char * uri); + +/** + Function that ends the operations on the dynamic manifest generator. + + This function SHOULD be used by the dynamic manifest generator to perform + cleanup operations, etc. + + Once this function is called, referring to handle will cause undefined + behavior. + + @param handle Dynamic manifest generator handle. +*/ +void lv2_dyn_manifest_close(LV2_Dyn_Manifest_Handle handle); + +#ifdef __cplusplus +} +#endif + +#endif /* LV2_DYN_MANIFEST_H_INCLUDED */ diff --git a/ns/ext/dynmanifest/dynmanifest.ttl b/ns/ext/dynmanifest/dynmanifest.ttl new file mode 100644 index 0000000..591cb11 --- /dev/null +++ b/ns/ext/dynmanifest/dynmanifest.ttl @@ -0,0 +1,122 @@ +# LV2 Dynamic Manifest Extension +# Copyright 2008-2011 Stefano D'Angelo +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix dman: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a doap:Project , + lv2:Specification ; + doap:license ; + doap:name "LV2 Dynamic Manifest" ; + doap:homepage ; + doap:created "2009-06-13" ; + doap:shortdesc "An LV2-based specification for dynamic data generation." ; + doap:programming-language "C" ; + doap:release [ + doap:revision "1.1" ; + doap:created "2011-11-17" + ] ; + doap:maintainer [ + a foaf:Person ; + foaf:name "Stefano D'Angelo" + ] ; + lv2:documentation """ +

The LV2 API, on its own, cannot be used to write plugin libraries where data +is dynamically generated at runtime (e.g. API wrappers), since LV2 requires +needed information to be provided in one or more static data (RDF) files. This +API addresses this limitation by extending the LV2 API.

+ +

To detect that a plugin library implements a dynamic manifest generator, +the host checks its static manifest for a description like:

+ +
+<http://example.org/my-dynamic-manifest>
+    a dman:DynManifest ;
+    lv2:binary <mydynmanifest.so> .
+
+ +

To load the data, the host loads the library +(e.g. mydynmanifest.so) as usual and fetches the dynamic Turtle +data from it using this API.

+ +

The host is allowed to request regeneration of the dynamic manifest multiple +times, and the plugin library is expected to provide updated data if/when +possible. All data and references provided via this API before the last +regeneration of the dynamic manifest is to be considered invalid by the host, +including plugin descriptors whose URIs were discovered using this API.

+ +

Accessing Data

+ +

Whenever a host wants to access data using this API, it could:

+ +
    +
  1. Call lv2_dyn_manifest_open().
  2. +
  3. Create a FILE for functions to write data to (e.g. using tmpfile()).
  4. +
  5. Get a list of exposed subject URIs using + lv2_dyn_manifest_get_subjects().
  6. +
  7. Call lv2_dyn_manifest_get_data() for each URI of interest to + get the data related to that URI (which can be written to any FILE).
  8. +
  9. Call lv2_dyn_manifest_close().
  10. +
  11. Parse the content of the FILE(s).
  12. +
  13. Free/delete/unlink the FILE(s).
  14. +
+ +

Each call to the above mentioned dynamic manifest functions MUST write a +complete, valid Turtle document (including all needed prefix definitions) to +the output FILE.

+ +

Each call to lv2_dyn_manifest_open() causes the (re)generation of the +dynamic manifest data, and invalidates all data fetched before the call.

+ +

In case the plugin library uses this same API to access other dynamic +manifests, it MUST implement some mechanism to avoid potentially endless loops +(such as A loads B, B loads A, etc.) and, in case such a loop is detected, the +operation MUST fail. For this purpose, use of a static boolean flag is +suggested.

+ +

Threading Rules

+ +

All of the functions defined by this specification belong to the Discovery +class.

+""" . + +dman:DynManifest + a rdfs:Class ; + rdfs:subClassOf lv2:Resource ; + rdfs:label "Dynamic manifest generator" ; + rdfs:subClassOf [ + a owl:Restriction ; + owl:onProperty lv2:binary ; + owl:minCardinality 1 ; + rdfs:comment """A DynManifest has at least 1 lv2:binary. +The binary must be a library with at least the functions described in +lv2_dyn_manifest.h implemented. +""" + ] ; + rdfs:comment """ +The class which represents a dynamic manifest generator. + +There MUST NOT be any instances of :DynManifest in the generated manifest. + +All relative URIs in the generated data MUST be relative to the base path +that would be used to parse a normal LV2 manifest (the bundle path). +""" . diff --git a/ns/ext/dynmanifest/ext.pc.in b/ns/ext/dynmanifest/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/dynmanifest/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/dynmanifest/lv2-dynmanifest.doap.ttl b/ns/ext/dynmanifest/lv2-dynmanifest.doap.ttl new file mode 100644 index 0000000..f47c381 --- /dev/null +++ b/ns/ext/dynmanifest/lv2-dynmanifest.doap.ttl @@ -0,0 +1,43 @@ +@prefix dcs: . +@prefix doap: . +@prefix foaf: . +@prefix rdfs: . + + + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + foaf:mbox ; + rdfs:seeAlso . + + + a doap:Project ; + doap:license ; + doap:name "LV2 Dynamic Manifest" ; + doap:homepage ; + doap:created "2009-06-13" ; + doap:shortdesc "An LV2-based specification for dynamic data generation." ; + doap:programming-language "C" ; + doap:developer [ + a foaf:Person ; + foaf:name "Stefano D'Angelo" + ] ; + doap:release [ + doap:revision "1.1" ; + doap:created "2011-11-17" ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Improve documentation." + ] + ] + ] , [ + doap:revision "1.0" ; + doap:created "2010-04-10" ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Initial release." + ] + ] + ] . diff --git a/ns/ext/dynmanifest/manifest.ttl b/ns/ext/dynmanifest/manifest.ttl new file mode 100644 index 0000000..6718092 --- /dev/null +++ b/ns/ext/dynmanifest/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 1 ; + lv2:microVersion 1 ; + rdfs:seeAlso , + . diff --git a/ns/ext/dynmanifest/waf b/ns/ext/dynmanifest/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/dynmanifest/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/dynmanifest/wscript b/ns/ext/dynmanifest/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/dynmanifest/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/event/event-helpers.h b/ns/ext/event/event-helpers.h new file mode 100644 index 0000000..75ba14b --- /dev/null +++ b/ns/ext/event/event-helpers.h @@ -0,0 +1,246 @@ +/* lv2_event_helpers.h - Helper functions for the LV2 events extension. + * + * Copyright (C) 2008-2009 David Robillard + * + * 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 + */ + +#ifndef LV2_EVENT_HELPERS_H +#define LV2_EVENT_HELPERS_H + +#include +#include +#include +#include +#include +#include "lv2/lv2plug.in/ns/ext/event/event.h" + +/** @file + * Helper functions for the LV2 Event extension + * . + * + * These functions are provided for convenience only, use of them is not + * required for supporting lv2ev (i.e. the events extension is defined by the + * raw buffer format described in lv2_event.h and NOT by this API). + * + * Note that these functions are all static inline which basically means: + * do not take the address of these functions. */ + + +/** Pad a size to 64 bits (for event sizes) */ +static inline uint16_t +lv2_event_pad_size(uint16_t size) +{ + return (size + 7) & (~7); +} + + +/** Initialize (empty, reset..) an existing event buffer. + * The contents of buf are ignored entirely and overwritten, except capacity + * which is unmodified. */ +static inline void +lv2_event_buffer_reset(LV2_Event_Buffer* buf, + uint16_t stamp_type, + uint8_t *data) +{ + buf->data = data; + buf->header_size = sizeof(LV2_Event_Buffer); + buf->stamp_type = stamp_type; + buf->event_count = 0; + buf->size = 0; +} + + +/** Allocate a new, empty event buffer. */ +static inline LV2_Event_Buffer* +lv2_event_buffer_new(uint32_t capacity, uint16_t stamp_type) +{ + const size_t size = sizeof(LV2_Event_Buffer) + capacity; + LV2_Event_Buffer* buf = (LV2_Event_Buffer*)malloc(size); + if (buf != NULL) { + buf->capacity = capacity; + lv2_event_buffer_reset(buf, stamp_type, (uint8_t *)(buf + 1)); + return buf; + } else { + return NULL; + } +} + + +/** An iterator over an LV2_Event_Buffer. + * + * Multiple simultaneous read iterators over a single buffer is fine, + * but changing the buffer invalidates all iterators (e.g. RW Lock). */ +typedef struct { + LV2_Event_Buffer* buf; + uint32_t offset; +} LV2_Event_Iterator; + + +/** Reset an iterator to point to the start of @a buf. + * @return True if @a iter is valid, otherwise false (buffer is empty) */ +static inline bool +lv2_event_begin(LV2_Event_Iterator* iter, + LV2_Event_Buffer* buf) +{ + iter->buf = buf; + iter->offset = 0; + return (buf->size > 0); +} + + +/** Check if @a iter is valid. + * @return True if @a iter is valid, otherwise false (past end of buffer) */ +static inline bool +lv2_event_is_valid(LV2_Event_Iterator* iter) +{ + return (iter->offset < iter->buf->size); +} + + +/** Advance @a iter forward one event. + * @a iter must be valid. + * @return True if @a iter is valid, otherwise false (reached end of buffer) */ +static inline bool +lv2_event_increment(LV2_Event_Iterator* iter) +{ + assert(lv2_event_is_valid(iter)); + + LV2_Event* const ev = (LV2_Event*)( + (uint8_t*)iter->buf->data + iter->offset); + + iter->offset += lv2_event_pad_size(sizeof(LV2_Event) + ev->size); + + return true; +} + + +/** Dereference an event iterator (get the event currently pointed at). + * @a iter must be valid. + * @a data if non-NULL, will be set to point to the contents of the event + * returned. + * @return A Pointer to the event @a iter is currently pointing at, or NULL + * if the end of the buffer is reached (in which case @a data is + * also set to NULL). */ +static inline LV2_Event* +lv2_event_get(LV2_Event_Iterator* iter, + uint8_t** data) +{ + assert(lv2_event_is_valid(iter)); + + LV2_Event* const ev = (LV2_Event*)( + (uint8_t*)iter->buf->data + iter->offset); + + if (data) + *data = (uint8_t*)ev + sizeof(LV2_Event); + + return ev; +} + + +/** Write an event at @a iter. + * The event (if any) pointed to by @a iter will be overwritten, and @a iter + * incremented to point to the following event (i.e. several calls to this + * function can be done in sequence without twiddling iter in-between). + * @return True if event was written, otherwise false (buffer is full). */ +static inline bool +lv2_event_write(LV2_Event_Iterator* iter, + uint32_t frames, + uint32_t subframes, + uint16_t type, + uint16_t size, + const uint8_t* data) +{ + if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size) + return false; + + LV2_Event* const ev = (LV2_Event*)( + (uint8_t*)iter->buf->data + iter->offset); + + ev->frames = frames; + ev->subframes = subframes; + ev->type = type; + ev->size = size; + memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size); + ++iter->buf->event_count; + + size = lv2_event_pad_size(sizeof(LV2_Event) + size); + iter->buf->size += size; + iter->offset += size; + + return true; +} + + +/** Reserve space for an event in the buffer and return a pointer to + the memory where the caller can write the event data, or NULL if there + is not enough room in the buffer. */ +static inline uint8_t* +lv2_event_reserve(LV2_Event_Iterator* iter, + uint32_t frames, + uint32_t subframes, + uint16_t type, + uint16_t size) +{ + size = lv2_event_pad_size(size); + if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size) + return NULL; + + LV2_Event* const ev = (LV2_Event*)((uint8_t*)iter->buf->data + + iter->offset); + + ev->frames = frames; + ev->subframes = subframes; + ev->type = type; + ev->size = size; + ++iter->buf->event_count; + + size = lv2_event_pad_size(sizeof(LV2_Event) + size); + iter->buf->size += size; + iter->offset += size; + + return (uint8_t*)ev + sizeof(LV2_Event); +} + + +/** Write an event at @a iter. + * The event (if any) pointed to by @a iter will be overwritten, and @a iter + * incremented to point to the following event (i.e. several calls to this + * function can be done in sequence without twiddling iter in-between). + * @return True if event was written, otherwise false (buffer is full). */ +static inline bool +lv2_event_write_event(LV2_Event_Iterator* iter, + const LV2_Event* ev, + const uint8_t* data) +{ + if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + ev->size) + return false; + + LV2_Event* const write_ev = (LV2_Event*)( + (uint8_t*)iter->buf->data + iter->offset); + + *write_ev = *ev; + memcpy((uint8_t*)write_ev + sizeof(LV2_Event), data, ev->size); + ++iter->buf->event_count; + + const uint16_t size = lv2_event_pad_size(sizeof(LV2_Event) + ev->size); + iter->buf->size += size; + iter->offset += size; + + return true; +} + +#endif /* LV2_EVENT_HELPERS_H */ + diff --git a/ns/ext/event/event.h b/ns/ext/event/event.h new file mode 100644 index 0000000..2c340ba --- /dev/null +++ b/ns/ext/event/event.h @@ -0,0 +1,281 @@ +/* + LV2 Event Extension + Copyright 2008-2011 David Robillard + Copyright 2006-2007 Lars Luthman + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef LV2_EVENT_H +#define LV2_EVENT_H + +#define LV2_EVENT_URI "http://lv2plug.in/ns/ext/event" +#define LV2_EVENT_AUDIO_STAMP 0 + +#include + +/** + @file event.h + C API for the LV2 Event extension . + + This extension is a generic transport mechanism for time stamped events + of any type (e.g. MIDI, OSC, ramps, etc). Each port can transport mixed + events of any type; the type of events and timestamps are defined by a URI + which is mapped to an integer by the host for performance reasons. + + This extension requires the host to support the LV2 URI Map extension. + Any host which supports this extension MUST guarantee that any call to + the LV2 URI Map uri_to_id function with the URI of this extension as the + 'map' argument returns a value within the range of uint16_t. +*/ + +/** + The best Pulses Per Quarter Note for tempo-based uint32_t timestamps. + Equal to 2^12 * 5 * 7 * 9 * 11 * 13 * 17, which is evenly divisble + by all integers from 1 through 18 inclusive, and powers of 2 up to 2^12. +*/ +static const uint32_t LV2_EVENT_PPQN = 3136573440U; + +/** + An LV2 event (header only). + + LV2 events are generic time-stamped containers for any type of event. + The type field defines the format of a given event's contents. + + This struct defines the header of an LV2 event. An LV2 event is a single + chunk of POD (plain old data), usually contained in a flat buffer (see + LV2_EventBuffer below). Unless a required feature says otherwise, hosts may + assume a deep copy of an LV2 event can be created safely using a simple: + + memcpy(ev_copy, ev, sizeof(LV2_Event) + ev->size); (or equivalent) +*/ +typedef struct { + + /** + The frames portion of timestamp. The units used here can optionally be + set for a port (with the lv2ev:timeUnits property), otherwise this is + audio frames, corresponding to the sample_count parameter of the LV2 run + method (e.g. frame 0 is the first frame for that call to run). + */ + uint32_t frames; + + /** + The sub-frames portion of timestamp. The units used here can optionally + be set for a port (with the lv2ev:timeUnits property), otherwise this is + 1/(2^32) of an audio frame. + */ + uint32_t subframes; + + /** + The type of this event, as a number which represents some URI + defining an event type. This value MUST be some value previously + returned from a call to the uri_to_id function defined in the LV2 + URI map extension (see lv2_uri_map.h). + There are special rules which must be followed depending on the type + of an event. If the plugin recognizes an event type, the definition + of that event type will describe how to interpret the event, and + any required behaviour. Otherwise, if the type is 0, this event is a + non-POD event and lv2_event_unref MUST be called if the event is + 'dropped' (see above). Even if the plugin does not understand an event, + it may pass the event through to an output by simply copying (and NOT + calling lv2_event_unref). These rules are designed to allow for generic + event handling plugins and large non-POD events, but with minimal hassle + on simple plugins that "don't care" about these more advanced features. + */ + uint16_t type; + + /** + The size of the data portion of this event in bytes, which immediately + follows. The header size (12 bytes) is not included in this value. + */ + uint16_t size; + + /* size bytes of data follow here */ + +} LV2_Event; + + +/** + A buffer of LV2 events (header only). + + Like events (which this contains) an event buffer is a single chunk of POD: + the entire buffer (including contents) can be copied with a single memcpy. + The first contained event begins sizeof(LV2_EventBuffer) bytes after the + start of this struct. + + After this header, the buffer contains an event header (defined by struct + LV2_Event), followed by that event's contents (padded to 64 bits), followed + by another header, etc: + + | | | | | | | + | | | | | | | | | | | | | | | | | | | | | | | | | + |FRAMES |SUBFRMS|TYP|LEN|DATA..DATA..PAD|FRAMES | ... +*/ +typedef struct { + + /** + The contents of the event buffer. This may or may not reside in the + same block of memory as this header, plugins must not assume either. + The host guarantees this points to at least capacity bytes of allocated + memory (though only size bytes of that are valid events). + */ + uint8_t* data; + + /** + The size of this event header in bytes (including everything). + + This is to allow for extending this header in the future without + breaking binary compatibility. Whenever this header is copied, + it MUST be done using this field (and NOT the sizeof this struct). + */ + uint16_t header_size; + + /** + The type of the time stamps for events in this buffer. + As a special exception, '0' always means audio frames and subframes + (1/UINT32_MAX'th of a frame) in the sample rate passed to instantiate. + + INPUTS: The host must set this field to the numeric ID of some URI + defining the meaning of the frames/subframes fields of contained events + (obtained by the LV2 URI Map uri_to_id function with the URI of this + extension as the 'map' argument, see lv2_uri_map.h). The host must + never pass a plugin a buffer which uses a stamp type the plugin does not + 'understand'. The value of this field must never change, except when + connect_port is called on the input port, at which time the host MUST + have set the stamp_type field to the value that will be used for all + subsequent run calls. + + OUTPUTS: The plugin may set this to any value that has been returned + from uri_to_id with the URI of this extension for a 'map' argument. + When connected to a buffer with connect_port, output ports MUST set this + field to the type of time stamp they will be writing. On any call to + connect_port on an event input port, the plugin may change this field on + any output port, it is the responsibility of the host to check if any of + these values have changed and act accordingly. + */ + uint16_t stamp_type; + + /** + The number of events in this buffer. + + INPUTS: The host must set this field to the number of events contained + in the data buffer before calling run(). The plugin must not change + this field. + + OUTPUTS: The plugin must set this field to the number of events it has + written to the buffer before returning from run(). Any initial value + should be ignored by the plugin. + */ + uint32_t event_count; + + /** + The size of the data buffer in bytes. + This is set by the host and must not be changed by the plugin. + The host is allowed to change this between run() calls. + */ + uint32_t capacity; + + /** + The size of the initial portion of the data buffer containing data. + + INPUTS: The host must set this field to the number of bytes used + by all events it has written to the buffer (including headers) + before calling the plugin's run(). + The plugin must not change this field. + + OUTPUTS: The plugin must set this field to the number of bytes + used by all events it has written to the buffer (including headers) + before returning from run(). + Any initial value should be ignored by the plugin. + */ + uint32_t size; + +} LV2_Event_Buffer; + + +/** + Opaque pointer to host data. +*/ +typedef void* LV2_Event_Callback_Data; + + +/** + Non-POD events feature. + + To support this feature the host must pass an LV2_Feature struct to the + plugin's instantiate method with URI "http://lv2plug.in/ns/ext/event" + and data pointed to an instance of this struct. Note this feature + is not mandatory to support the event extension. +*/ +typedef struct { + + /** + Opaque pointer to host data. + + The plugin MUST pass this to any call to functions in this struct. + Otherwise, it must not be interpreted in any way. + */ + LV2_Event_Callback_Data callback_data; + + /** + Take a reference to a non-POD event. + + If a plugin receives an event with type 0, it means the event is a + pointer to some object in memory and not a flat sequence of bytes + in the buffer. When receiving a non-POD event, the plugin already + has an implicit reference to the event. If the event is stored AND + passed to an output, lv2_event_ref MUST be called on that event. + If the event is only stored OR passed through, this is not necessary + (as the plugin already has 1 implicit reference). + + @param event An event received at an input that will not be copied to + an output or stored in any way. + + @param context The calling context. Like event types, this is a mapped + URI, see lv2_context.h. Simple plugin with just a run() method should + pass 0 here (the ID of the 'standard' LV2 run context). The host + guarantees that this function is realtime safe iff @a context is + realtime safe. + + PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS. + */ + uint32_t (*lv2_event_ref)(LV2_Event_Callback_Data callback_data, + LV2_Event* event); + + /** + Drop a reference to a non-POD event. + + If a plugin receives an event with type 0, it means the event is a + pointer to some object in memory and not a flat sequence of bytes + in the buffer. If the plugin does not pass the event through to + an output or store it internally somehow, it MUST call this function + on the event (more information on using non-POD events below). + + @param event An event received at an input that will not be copied to an + output or stored in any way. + + @param context The calling context. Like event types, this is a mapped + URI, see lv2_context.h. Simple plugin with just a run() method should + pass 0 here (the ID of the 'standard' LV2 run context). The host + guarantees that this function is realtime safe iff @a context is + realtime safe. + + PLUGINS THAT VIOLATE THESE RULES MAY CAUSE CRASHES AND MEMORY LEAKS. + */ + uint32_t (*lv2_event_unref)(LV2_Event_Callback_Data callback_data, + LV2_Event* event); + +} LV2_Event_Feature; + + +#endif /* LV2_EVENT_H */ diff --git a/ns/ext/event/event.ttl b/ns/ext/event/event.ttl new file mode 100644 index 0000000..d207a7a --- /dev/null +++ b/ns/ext/event/event.ttl @@ -0,0 +1,194 @@ +# LV2 Event Extension +# Copyright 2008-2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix doap: . +@prefix ev: . +@prefix foaf: . +@prefix lv2: . +@prefix lv2ev: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . + + + a lv2:Specification ; + owl:deprecated true ; + doap:license ; + doap:name "LV2 Event" ; + doap:shortdesc "A port-based real-time generic event interface." ; + rdfs:seeAlso ; + doap:release [ + doap:revision "1.3" ; + doap:created "2011-11-23" + ] ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] , [ + a foaf:Person ; + foaf:name "Lars Luthman" ; + ] ; + lv2:documentation """ +

This extension is deprecated. New +implementations should use LV2 Atom +instead.

+ +

This extension defines a generic time-stamped event port type, which can be +used to create plugins that read and write real-time events, such as MIDI, +OSC, or any other type of event payload. The type(s) of event supported by +a port is defined in the data file for a plugin, for example:

+
+<http://example.org/some-plugin>
+    lv2:port [
+        a ev:EventPort, lv2:InputPort ;
+        lv2:index 0 ;
+        ev:supportsEvent <http://lv2plug.in/ns/ext/midi#MidiEvent> ;
+        lv2:symbol "midi_input" ;
+        lv2:name "MIDI input" ;
+    ] .
+
+""" . + +ev:EventPort a rdfs:Class ; + rdfs:label "Event port" ; + rdfs:subClassOf lv2:Port ; + rdfs:comment """ +Ports of this type will be connected to a struct of type LV2_Event_Buffer, +defined in event.h. These ports contain a sequence of generic events +(possibly several types mixed in a single stream), the specific types of +which are defined by some URI in another LV2 extension. +""" . + + +ev:Event a rdfs:Class ; + rdfs:label "LV2 event" ; + rdfs:comment """ +A single generic time-stamped event. + +An lv2ev:EventPort contains an LV2_Event_Buffer which contains a sequence +of these events. The binary format of LV2 events is defined by the +LV2_Event struct in event.h. + +Specific event types (e.g. MIDI, OSC) are defined by extensions, and should +be rdfs:subClassOf this class. +""" . + + +ev:TimeStamp a rdfs:Class ; + rdfs:label "LV2 event time stamp" ; + rdfs:comment """ +The time stamp of an Event. + +This defines the meaning of the 'frames' and 'subframes' fields of an +LV2_Event (both unsigned 32-bit integers). +""" . + + +ev:FrameStamp a rdfs:Class ; + rdfs:subClassOf ev:TimeStamp ; + rdfs:label "Audio frame time stamp" ; + rdfs:comment """ +The default time stamp unit for an LV2 event: the frames field represents +audio frames (in the sample rate passed to intantiate), and the subframes +field is 1/UINT32_MAX of a frame. +""" . + + +ev:generic a lv2:PortProperty ; + rdfs:label "Generic event port" ; + rdfs:comment """ +Indicates that this port does something meaningful for any event type +(e.g. event mixers, delays, serialisers, etc). If this property is set, hosts +should consider the port suitable for any type of event. Otherwise, hosts +should consider the port 'appropriate' only for the specific event types +listed with :supportsEvent. Note that plugins must gracefully handle unknown +event types whether or not this property is present. +""" . + + +ev:supportsEvent a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range ev:Event ; + rdfs:label "Supports event type" ; + rdfs:comment """ +Indicates that this port supports or "understands" a certain event type. +For input ports, this means the plugin understands and does something useful +with events of this type. For output ports, this means the plugin may generate +events of this type. If the plugin never actually generates events of this type, +but might pass them through from an input, this property should not be set (use +ev:inheritsEvent for that). +Plugins with event input ports must always gracefully handle any type of event, +even if it does not 'support' it. This property should always be set for +event types the plugin understands/generates so hosts can discover plugins +appropriate for a given scenario (e.g. plugins with a MIDI input). +Hosts are not expected to consider event ports suitable for some type of +event if the relevant :supportsEvent property is not set, unless the +lv2ev:generic property for that port is also set. +""" . + + +ev:inheritsEvent a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range lv2:Port ; + rdfs:label "Inherits event type" ; + rdfs:comment """ +Indicates that this output port might pass through events that arrived at some +other input port (or generate an event of the same type as events arriving at +that input). The host must always check the stamp type of all outputs when +connecting an input, but this property should be set whenever it applies. +""" . + + +ev:supportsTimeStamp a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range ev:TimeStamp ; + rdfs:label "Supports time stamp type" ; + rdfs:comment """ +Indicates that this port supports or "understands" a certain time stamp type. +Meaningful only for input ports, the host must never connect a port to an +event buffer with a time stamp type that isn't supported by the port. +""" . + + +ev:generatesTimeStamp a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range ev:TimeStamp ; + rdfs:label "Outputs time stamp type" ; + rdfs:comment """ +Indicates that this port may output a certain time stamp type, regardless of +the time stamp type of any input ports. If the port outputs stamps based on +what type inputs are connected to, this property should not be set (use the +ev:inheritsTimeStamp property for that). Hosts MUST check the time_stamp value +of any output port buffers after a call to connect_port on ANY event input +port on the plugin. If the plugin changes the stamp_type field of an output +event buffer during a call to run(), the plugin must call the +stamp_type_changed function provided by the host in the LV2_Event_Feature +struct, if it is non-NULL. +""" . + + +ev:inheritsTimeStamp a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range lv2:Port ; + rdfs:label "Inherits time stamp type" ; + rdfs:comment """ +Indicates that this port follows the time stamp type of an input port. +This property is not necessary, but it should be set for outputs that +base their output type on an input port so the host can make more sense +of the plugin and provide a more sensible interface. +""" . + diff --git a/ns/ext/event/ext.pc.in b/ns/ext/event/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/event/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/event/manifest.ttl b/ns/ext/event/manifest.ttl new file mode 100644 index 0000000..2b1ff43 --- /dev/null +++ b/ns/ext/event/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 1 ; + lv2:microVersion 3 ; + rdfs:seeAlso . + diff --git a/ns/ext/event/waf b/ns/ext/event/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/event/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/event/wscript b/ns/ext/event/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/event/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/files/ext.pc.in b/ns/ext/files/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/files/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/files/files.h b/ns/ext/files/files.h new file mode 100644 index 0000000..623587a --- /dev/null +++ b/ns/ext/files/files.h @@ -0,0 +1,134 @@ +/* + Copyright 2010-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file files.h + C API for the LV2 Files extension . +*/ + +#ifndef LV2_FILES_H +#define LV2_FILES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define LV2_FILES_URI "http://lv2plug.in/ns/ext/files" +#define LV2_FILES_PATH_SUPPORT_URI LV2_FILES_URI "#pathSupport" +#define LV2_FILES_NEW_FILE_SUPPORT_URI LV2_FILES_URI "#newFileSupport" + +typedef void* LV2_Files_Host_Data; + +/** + files:pathSupport feature struct. + + To support this feature, the host MUST pass an LV2_Feature struct with @a + URI @ref LV2_FILES_PATH_SUPPORT_URI and @a data pointed to an instance of + this struct. +*/ +typedef struct { + + /** + Opaque host data. + */ + LV2_Files_Host_Data host_data; + + /** + Map an absolute path to an abstract path for use in plugin state. + @param host_data MUST be the @a host_data member of this struct. + @param absolute_path The absolute path of a file. + @return An abstract path suitable for use in plugin state. + + The plugin MUST use this function to map any paths that will be stored + in plugin state. The returned value is an abstract path which MAY not + be an actual file system path; @ref absolute_path MUST be used to map it + to an actual path in order to use the file. + + Hosts MAY map paths in any way (e.g. by creating symbolic links within + the plugin's state directory or storing a list of referenced files for + later export). Plugins MUST NOT make any assumptions about abstract + paths except that they can be mapped to an absolute path using @ref + absolute_path. Particularly when restoring from state, this absolute + path MAY not be the same as the original absolute path, but the host + MUST guarantee it refers to a file with contents equivalent to the + original. + + This function may only be called within the context of + LV2_Persist.save() or LV2_Persist.restore(). The caller is responsible + for freeing the returned value. + */ + char* (*abstract_path)(LV2_Files_Host_Data host_data, + const char* absolute_path); + + /** + Map an abstract path from plugin state to an absolute path. + @param host_data MUST be the @a host_data member of this struct. + @param abstract_path An abstract path (e.g. a path from plugin state). + @return An absolute file system path. + + Since abstract paths are not necessarily actual file paths (or at least + not necessarily absolute paths), this function MUST be used in order to + actually open or otherwise use the file referred to by an abstract path. + + This function may only be called within the context of + LV2_Persist.save() or LV2_Persist.restore(). The caller is responsible + for freeing the returned value. + */ + char* (*absolute_path)(LV2_Files_Host_Data host_data, + const char* abstract_path); + +} LV2_Files_Path_Support; + +/** + files:newFileSupport feature struct. + + To support this feature, the host MUST pass an LV2_Feature struct with @a + URI @ref LV2_FILES_NEW_FILE_SUPPORT_URI and @a data pointed to an instance + of this struct. +*/ +typedef struct { + + /** + Opaque host data. + */ + LV2_Files_Host_Data host_data; + + /** + Return an absolute path the plugin may use to create a new file. + @param host_data MUST be the @a host_data member of this struct. + @param relative_path The relative path of the file. + @return The absolute path to use for the new file. + + The plugin can assume @a relative_path is relative to a namespace + dedicated to that plugin instance; hosts MUST ensure this, e.g. by + giving each plugin instance its own state directory. The returned path + is absolute and thus suitable for creating and using a file, but NOT + suitable for storing in plugin state (it MUST be mapped to an abstract + path using @ref LV2_Files_Path_Support::abstract_path to do so). + + This function may be called from any non-realtime context. The caller + is responsible for freeing the returned value. + */ + char* (*new_file_path)(LV2_Files_Host_Data host_data, + const char* relative_path); + +} LV2_Files_New_File_Support; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_FILES_H */ diff --git a/ns/ext/files/files.ttl b/ns/ext/files/files.ttl new file mode 100644 index 0000000..d3ff8a5 --- /dev/null +++ b/ns/ext/files/files.ttl @@ -0,0 +1,115 @@ +# LV2 Files Extension +# Copyright 2010-2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix atom: . +@prefix doap: . +@prefix files: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a lv2:Specification ; + doap:name "LV2 Files" ; + doap:shortdesc "A standard for referring to files in plugin state." ; + doap:license ; + doap:release [ + doap:revision "0.2" ; + doap:created "2011-04-05" + ] ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + lv2:documentation """ +

This extension provides a mechanism for plugins to portably refer to files +in persistent plugin state (using the LV2 Persist extension), and create +instance-local files in host-defined locations (e.g. for recording).

+ +

The motivating idea behind this extension is that all details of file +management MUST be handled by the host since different hosts may have very +different requirements. Plugins MUST NOT make any assumption about file system +locations beyond what is explicitly guaranteed by this extension.

+ +

This extension defines two features: files:newFileSupport allows plugins to +create new files within an instance-specific namespace at any time (except in +realtime contexts); while files:pathSupport allows plugins to refer to file +paths in plugin state in a way transparent to the host.

+ +

To create a new file, the plugin MUST request a path from the host using +LV2_Files_New_File_Support::new_file_path(). Thus, the host may choose an +appropriate location for the file (e.g. a writable path on the appropriate disk +volume or a path within a session directory) using information not available to +the plugin.

+ +

To store a path in persistent state, the plugin MUST map it to an +abstract path using LV2_Files_Path_Support::abstract_path(). To use a +path loaded from persistent state, the plugin MUST map the (abstract) path to +an absolute path using LV2_Files_Path_Support::absolute_path(). Thus, the host +can manage all paths used in a session and support exporting sessions to a +portable self-contained format for archival or distribution.

""" . + +files:pathSupport a lv2:Feature ; + rdfs:label "Support for storing file paths in plugin state" ; + lv2:documentation """ +

This feature allows plugins to refer to pre-existing or newly created files +in persistent plugin state in a portable way. To support this feature a host +MUST pass a LV2_Files_Path_Support structure to the plugin's +LV2_Descriptor::instantiate() method as an LV2_Feature with LV2_Feature::URI = +LV2_FILES_PATH_SUPPORT_URI and LV2_Feature::data pointed to an instance of +LV2_Files_Path_Support.

+ +

Plugins MUST use the functions provided by this feature to handle +all paths saved to, or restored from, persistent plugin state; +otherwise broken and/or non-portable state will silently be created resulting +in a broken user experience.

+""" . + +files:newFileSupport a lv2:Feature ; + rdfs:label "Support for creating new files" ; + lv2:documentation """ +

This feature allows plugins to create new files local to that plugin +instance. To support this feature a host MUST pass a +LV2_Files_New_File_Support structure to the plugin's +LV2_Descriptor::instantiate() method as an LV2_Feature with LV2_Feature::URI = +LV2_FILES_NEW_FILE_SUPPORT_URI and LV2_Feature::data pointed to an instance of +LV2_Files_New_File_Support.

+""" . + +files:AbstractPath a rdfs:Class ; + rdfs:label "File Path" ; + lv2:documentation """ +

An abstract path to a file in persistent plugin state.

+ +

The format of a files:AbstractPath is a C string escaped or otherwise +restricted in a system-specific manner. This URI, +http://lv2plug.in/ns/ext/files#AbstractPath, mapped to an integer, +should be used as the type parameter to a +LV2_Persist_Store_Function; and will likewise be returned by the corresponding +call to a LV2_Persist_Retrieve_Function.

+ +

Abstract paths reside in a namespace specific to a plugin instance. +Typical hosts are expected to implement this by giving each plugin instance its +own state directory.

+ +

When storing and retrieving an abstract path, the plugin MUST NOT assume the +same path will be restored. However, the restored path will refer to a file +with equivalent contents to the original.

+""" . diff --git a/ns/ext/files/manifest.ttl b/ns/ext/files/manifest.ttl new file mode 100644 index 0000000..d0233c4 --- /dev/null +++ b/ns/ext/files/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 2 ; + rdfs:seeAlso . + diff --git a/ns/ext/files/waf b/ns/ext/files/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/files/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/files/wscript b/ns/ext/files/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/files/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/host-info/ext.pc.in b/ns/ext/host-info/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/host-info/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/host-info/host-info.ttl b/ns/ext/host-info/host-info.ttl new file mode 100644 index 0000000..127f4cc --- /dev/null +++ b/ns/ext/host-info/host-info.ttl @@ -0,0 +1,118 @@ +# LV2 Host Info Extension +# PROVISIONAL +# Copyright (C) 2009 David Robillard +# +# 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 hi: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix owl: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . +@prefix amb: . + + a lv2:Specification ; + doap:license ; + doap:name "LV2 Host Info" ; + doap:shortdesc "A format for describing LV2 hosts." ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + lv2:documentation """ +

This specification defines various properties to represent useful information +about LV2 hosts. Currently, the primary use of this specification is to describe which +extensions are supported by a given host.

+ +

The extensions supported by a host can be described like this:

+
+@prefix hi: <http://lv2plug.in/ns/ext/host-info#> .
+
+<http://example.org/some-host>
+    a hi:Host ;
+    doap:name "Foo Rack" ;
+    hi:supportsExtension [
+        hi:extension <http://example.org/some-extension> ;
+        hi:sinceVersion "1.2.0"
+    ] .
+
+""" . + + +## Core Classes / Properties + +hi:Host a rdfs:Class ; + rdfs:label "LV2 Host" ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty doap:name ; + owl:someValuesFrom xsd:string ; + owl:minCardinality 1 ; + rdfs:comment "A hi:Host MUST have at least one string doap:name" + ] ; + rdfs:comment """ +An application that supports loading LV2 plugins, or performs other +LV2 related functionality. +""" . + +hi:supportsExtension a rdf:Property ; + rdfs:domain hi:Host ; + rdfs:range hi:ExtensionSupport ; + rdfs:label "supports extension" ; + rdfs:comment "Relates a Host to its ExtensionSupport" . + +hi:ExtensionSupport a rdfs:Class ; + rdfs:label "Extension Support" ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty hi:sinceVersion ; + owl:someValuesFrom xsd:string ; + owl:minCardinality 1 ; + rdfs:comment """ +A hi:ExtensionSupport MUST have at least one string hi:sinceVersion +""" ] ; + rdfs:comment "A description of the support for an extension by a Host" . + +hi:extension a rdf:Property ; + rdfs:domain hi:ExtensionSupport ; + rdfs:range lv2:Specification ; + rdfs:label "extension" ; + rdfs:comment "Indicates the extension supported by a host." . + +hi:sinceVersion a rdf:Property ; + rdfs:domain hi:ExtensionSupport ; + rdfs:range xsd:string ; + rdfs:label "since version" ; + rdfs:comment """ +The initial version of a host which supported an extension. +This property MUST always be given +""" . + +hi:untilVersion a rdf:Property ; + rdfs:domain hi:ExtensionSupport ; + rdfs:range xsd:string ; + rdfs:label "until version" ; + rdfs:comment """ +The final version of a host which supported an extension. This property can +be used if support for an extension was discontinued in a host for some reason. +""" . + diff --git a/ns/ext/host-info/manifest.ttl b/ns/ext/host-info/manifest.ttl new file mode 100644 index 0000000..ae1e097 --- /dev/null +++ b/ns/ext/host-info/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/host-info/waf b/ns/ext/host-info/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/host-info/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/host-info/wscript b/ns/ext/host-info/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/host-info/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/instance-access/ext.pc.in b/ns/ext/instance-access/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/instance-access/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/instance-access/instance-access.h b/ns/ext/instance-access/instance-access.h new file mode 100644 index 0000000..7e18ee4 --- /dev/null +++ b/ns/ext/instance-access/instance-access.h @@ -0,0 +1,38 @@ +/* + LV2 Instance Access Extension + Copyright 2008-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef LV2_INSTANCE_ACCESS_H +#define LV2_INSTANCE_ACCESS_H + +#define LV2_INSTANCE_ACCESS_URI "http://lv2plug.in/ns/ext/instance-access" + + +/** @file + * C header for the LV2 Instance Access extension + * . + * + * This extension defines a method for (e.g.) plugin UIs to get a direct + * handle to an LV2 plugin instance (LV2_Handle), if possible. + * + * To support this feature the host must pass an LV2_Feature struct to the + * UI instantiate method with URI "http://lv2plug.in/ns/ext/instance-access" + * and data pointed directly to the LV2_Handle of the plugin instance. + */ + + +#endif /* LV2_INSTANCE_ACCESS_H */ + diff --git a/ns/ext/instance-access/instance-access.ttl b/ns/ext/instance-access/instance-access.ttl new file mode 100644 index 0000000..f3d1a42 --- /dev/null +++ b/ns/ext/instance-access/instance-access.ttl @@ -0,0 +1,80 @@ +# LV2 Instance Access Extension +# Copyright 2008-2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix dcs: . +@prefix doap: . +@prefix foaf: . +@prefix ia: . +@prefix lv2: . +@prefix lv2ev: . +@prefix rdf: . +@prefix rdfs: . + + + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + foaf:mbox ; + rdfs:seeAlso . + + + a lv2:Specification ; + doap:license ; + doap:name "LV2 Instance Access" ; + doap:shortdesc "Provides access to the LV2_Handle of a plugin." ; + doap:developer ; + doap:release [ + doap:revision "1.4" ; + doap:created "2011-11-14" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Update packaging." + ] , [ + rdfs:label "Improve documentation." + ] + ] + ] , [ + doap:revision "1.2" ; + doap:created "2011-05-26" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Add build system for installation." + ] , [ + rdfs:label "Switch to ISC license." + ] + ] + ] , [ + doap:revision "1.0" ; + doap:created "2010-10-04" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Initial release." + ] + ] + ] ; + lv2:documentation """ +

This extension defines a feature which allows plugin UIs to get a direct +handle to an LV2 plugin instance (LV2_Handle), if possible.

+ +

To support this feature the host must pass an LV2_Feature struct to the UI +instantiate method with URI "http://lv2plug.in/ns/ext/instance-access" and data +pointed directly to the LV2_Handle of the plugin instance.

+""" . diff --git a/ns/ext/instance-access/manifest.ttl b/ns/ext/instance-access/manifest.ttl new file mode 100644 index 0000000..d6412c5 --- /dev/null +++ b/ns/ext/instance-access/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 1 ; + lv2:microVersion 4 ; + rdfs:seeAlso . + diff --git a/ns/ext/instance-access/waf b/ns/ext/instance-access/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/instance-access/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/instance-access/wscript b/ns/ext/instance-access/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/instance-access/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/midi/ext.pc.in b/ns/ext/midi/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/midi/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/midi/manifest.ttl b/ns/ext/midi/manifest.ttl new file mode 100644 index 0000000..a8e194e --- /dev/null +++ b/ns/ext/midi/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 1 ; + lv2:microVersion 4 ; + rdfs:seeAlso . + diff --git a/ns/ext/midi/midi.ttl b/ns/ext/midi/midi.ttl new file mode 100644 index 0000000..0b66f42 --- /dev/null +++ b/ns/ext/midi/midi.ttl @@ -0,0 +1,115 @@ +# LV2 MIDI Extension +# Copyright 2008-2011 David Robillard +# Copyright 2006 Lars Luthman +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix dcs: . +@prefix atom: . +@prefix doap: . +@prefix ev: . +@prefix foaf: . +@prefix lv2: . +@prefix midi: . +@prefix rdfs: . + + + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + foaf:mbox ; + rdfs:seeAlso . + +_:larsl + a foaf:Person ; + foaf:name "Lars Luthman" ; + foaf:mbox . + + + a lv2:Specification ; + doap:license ; + doap:name "LV2 MIDI" ; + doap:shortdesc "A data type for raw MIDI." ; + doap:maintainer ; + doap:developer _:larsl ; + doap:release [ + doap:revision "1.4" ; + doap:created "2011-11-14" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Update packaging." + ] , [ + rdfs:label "Improve documentation." + ] + ] + ] , [ + doap:revision "1.2" ; + doap:created "2011-05-26" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Add build system for installation." + ] , [ + rdfs:label "Switch to ISC license." + ] + ] + ] , [ + doap:revision "1.0" ; + doap:created "2010-10-04" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Initial release." + ] + ] + ] ; + lv2:documentation """ +

This extension defines a data type for a MIDI message, midi:MidiEvent, which +is normalized for fast and convenient processing by plugins. It is +particularly useful as the payload of an Atom or Event.

+""" . + +midi:MidiEvent + a rdfs:Class ; + rdfs:label "LV2 MIDI message." ; + rdfs:subClassOf ev:Event , + atom:Atom ; + lv2:documentation """ +

A single raw MIDI message (i.e. a sequence of bytes).

+ +

This is equivalent to a standard MIDI messages, except with the following +restrictions to simplify handling:

+
    +
  • Running status is not allowed, every message must have its own status + byte.
  • + +
  • Note On messages with velocity 0 are not allowed. These messages are + equivalent to Note Off in standard MIDI streams, but here only proper Note + Off messages are allowed.
  • + +
  • "Realtime messages" (status bytes 0xF8 to 0xFF) are allowed, but may + not occur inside other messages like they can in standard MIDI streams.
  • + +
  • All messages are complete valid MIDI messages. This means, for example, + that only the first byte in each event (the status byte) may have the eighth + bit set, that Note On and Note Off events are always 3 bytes long, etc. + Where messages are communicated, the writer is responsible for writing valid + messages, and the reader may assume that all events are valid.
  • +
+""" . diff --git a/ns/ext/midi/waf b/ns/ext/midi/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/midi/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/midi/wscript b/ns/ext/midi/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/midi/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/osc/ext.pc.in b/ns/ext/osc/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/osc/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/osc/lv2_osc.c b/ns/ext/osc/lv2_osc.c new file mode 100644 index 0000000..afea2c9 --- /dev/null +++ b/ns/ext/osc/lv2_osc.c @@ -0,0 +1,238 @@ +/* LV2 OSC Messages Extension + * Copyright (C) 2007-2009 David Robillard + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include "lv2_osc.h" +#include "lv2_osc_print.h" + +/*#ifndef BIG_ENDIAN + #ifndef LITTLE_ENDIAN + #warning This code requires BIG_ENDIAN or LITTLE_ENDIAN to be defined + #warning Assuming little endian. THIS MAY BREAK HORRIBLY! + #endif +#endif*/ + +#define lv2_osc_swap32(x) \ +({ \ + uint32_t __x = (x); \ + ((uint32_t)( \ + (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ + (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ + (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ + (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ +}) + +#define lv2_osc_swap64(x) \ +({ \ + uint64_t __x = (x); \ + ((uint64_t)( \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ + (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \ +}) + + +/** Pad a size to a multiple of 32 bits */ +inline static uint32_t +lv2_osc_pad_size(uint32_t size) +{ + return size + 3 - ((size-1) % 4); +} + + +inline static uint32_t +lv2_osc_string_size(const char *s) +{ + return lv2_osc_pad_size((uint32_t)strlen(s) + 1); +} + + +static inline uint32_t +lv2_osc_blob_size(const void* blob) +{ + return sizeof(uint32_t) + lv2_osc_pad_size(*((uint32_t*)blob)); +} + + +uint32_t +lv2_osc_arg_size(char type, const LV2_OSC_Argument* arg) +{ + switch (type) { + case 'c': + case 'i': + case 'f': + case 'S': // Symbol (URI-mapped integer) + return 4; + + case 'h': + case 'd': + return 8; + + case 's': + return lv2_osc_string_size(&arg->s); + + case 'b': + return lv2_osc_blob_size(&arg->b); + + default: + fprintf(stderr, "Warning: unknown OSC type '%c'.", type); + return 0; + } +} + + +void +lv2_osc_argument_swap_byte_order(char type, LV2_OSC_Argument* arg) +{ + switch (type) { + case 'i': + case 'f': + case 'b': + case 'c': + *(int32_t*)arg = lv2_osc_swap32(*(int32_t*)arg); + break; + + case 'h': + case 'd': + *(int64_t*)arg = lv2_osc_swap64(*(int64_t*)arg); + break; + } +} + + +/** Convert a message from network byte order to host byte order. */ +void +lv2_osc_message_swap_byte_order(LV2_OSC_Event* msg) +{ + const char* const types = lv2_osc_get_types(msg); + + for (uint32_t i=0; i < msg->argument_count; ++i) + lv2_osc_argument_swap_byte_order(types[i], lv2_osc_get_argument(msg, i)); +} + + +/** Not realtime safe, returned value must be free()'d by caller. */ +LV2_OSC_Event* +lv2_osc_message_new(const char* path, const char* types, ...) +{ + /* FIXME: path only */ + + LV2_OSC_Event* result = malloc(sizeof(LV2_OSC_Event) + + 4 + lv2_osc_string_size(path)); + + const uint32_t path_size = lv2_osc_string_size(path); + result->data_size = path_size + 4; // 4 for types + result->argument_count = 0; + result->types_offset = lv2_osc_string_size(path) + 1; + (&result->data)[result->types_offset - 1] = ','; + (&result->data)[result->types_offset] = '\0'; + + memcpy(&result->data, path, strlen(path) + 1); + + return result; +} + + +/** Create a new LV2_OSC_Event from a raw OSC message. + * + * If \a out_buf is NULL, new memory will be allocated. Otherwise the returned + * value will be equal to buf, unless there is insufficient space in which + * case NULL is returned. + */ +LV2_OSC_Event* +lv2_osc_message_from_raw(uint32_t out_buf_size, + void* out_buf, + uint32_t raw_msg_size, + void* raw_msg) +{ + const uint32_t message_header_size = (sizeof(uint32_t) * 4); + + const uint32_t path_size = lv2_osc_string_size((char*)raw_msg); + const uint32_t types_len = strlen((char*)(raw_msg + path_size + 1)); + uint32_t index_size = types_len * sizeof(uint32_t); + + if (out_buf == NULL) { + out_buf_size = message_header_size + index_size + raw_msg_size; + out_buf = malloc((size_t)out_buf_size); + } else if (out_buf && out_buf_size < message_header_size + raw_msg_size) { + return NULL; + } + + LV2_OSC_Event* write_loc = (LV2_OSC_Event*)(out_buf); + write_loc->argument_count = types_len; + write_loc->data_size = index_size + raw_msg_size; + + // Copy raw message + memcpy(&write_loc->data + index_size, raw_msg, raw_msg_size); + + write_loc->types_offset = index_size + path_size + 1; + const char* const types = lv2_osc_get_types(write_loc); + + // Calculate/Write index + uint32_t args_base_offset = write_loc->types_offset + lv2_osc_string_size(types) - 1; + uint32_t arg_offset = 0; + + for (uint32_t i=0; i < write_loc->argument_count; ++i) { + ((uint32_t*)&write_loc->data)[i] = args_base_offset + arg_offset; + const LV2_OSC_Argument* const arg = (LV2_OSC_Argument*)(&write_loc->data + args_base_offset + arg_offset); + // Special case because size is still big-endian +#ifndef BIG_ENDIAN + if (types[i] == 'b') // special case because size is still big-endian + arg_offset += lv2_osc_swap32(*((int32_t*)arg)); + else +#endif + arg_offset += lv2_osc_arg_size(types[i], arg); + } + + /*printf("Index:\n"); + for (uint32_t i=0; i < write_loc->argument_count; ++i) { + printf("%u ", ((uint32_t*)&write_loc->data)[i]); + } + printf("\n"); + + printf("Data:\n"); + for (uint32_t i=0; i < (write_loc->argument_count * 4) + size; ++i) { + printf("%3u", i % 10); + } + printf("\n"); + for (uint32_t i=0; i < (write_loc->argument_count * 4) + size; ++i) { + char c = *(((char*)&write_loc->data) + i); + if (c >= 32 && c <= 126) + printf("%3c", c); + else + printf("%3d", (int)c); + } + printf("\n");*/ + + // Swap to host byte order if necessary +#ifndef BIG_ENDIAN + lv2_osc_message_swap_byte_order(write_loc); +#endif + + printf("Created message:\n"); + lv2_osc_message_print(write_loc); + + return write_loc; +} diff --git a/ns/ext/osc/lv2_osc_print.c b/ns/ext/osc/lv2_osc_print.c new file mode 100644 index 0000000..5282d46 --- /dev/null +++ b/ns/ext/osc/lv2_osc_print.c @@ -0,0 +1,66 @@ +/* LV2 OSC Messages Extension - Pretty printing methods + * Copyright (C) 2007-2009 David Robillard + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "lv2_osc_print.h" + +void +lv2_osc_argument_print(char type, const LV2_OSC_Argument* arg) +{ + int32_t blob_size; + + switch (type) { + case 'c': + printf("%c", arg->c); break; + case 'i': + printf("%d", arg->i); break; + case 'f': + printf("%f", arg->f); break; + case 'h': + printf("%ld", arg->h); break; + case 'd': + printf("%f", arg->d); break; + case 's': + printf("\"%s\"", &arg->s); break; + /*case 'S': + printf("\"%s\"", &arg->S); break;*/ + case 'b': + blob_size = *((int32_t*)arg); + printf("{ "); + for (int32_t i=0; i < blob_size; ++i) + printf("%X, ", (&arg->b)[i+4]); + printf(" }"); + break; + default: + printf("?"); + } +} + + +void +lv2_osc_print(const LV2_OSC_Event* msg) +{ + const char* const types = lv2_osc_get_types(msg); + + printf("%s (%s) ", lv2_osc_get_path(msg), types); + for (uint32_t i=0; i < msg->argument_count; ++i) { + lv2_osc_argument_print(types[i], lv2_osc_get_argument(msg, i)); + printf(" "); + } + printf("\n"); +} + diff --git a/ns/ext/osc/lv2_osc_test.c b/ns/ext/osc/lv2_osc_test.c new file mode 100644 index 0000000..3f76d41 --- /dev/null +++ b/ns/ext/osc/lv2_osc_test.c @@ -0,0 +1,55 @@ +#include +#include +#include +#include +#include "lv2_osc.h" +#include "lv2_osc_print.h" + +int +main() +{ + lo_message lo_msg = lo_message_new(); + //lo_message_add_symbol(lo_msg, "a_sym"); + lo_message_add_string(lo_msg, "Hello World"); + lo_message_add_char(lo_msg, 'a'); + lo_message_add_int32(lo_msg, 1234); + lo_message_add_float(lo_msg, 0.1234); + lo_message_add_int64(lo_msg, 5678); + lo_message_add_double(lo_msg, 0.5678); + + + /*unsigned char blob_data[] = { 0,1,2,3,4,5,6,7,8,9 }; + lo_blob blob = lo_blob_new(10, blob_data); + lo_message_add_blob(lo_msg, blob);*/ + + /* Leaks like a sieve */ + + size_t raw_msg_size = 0; + void* raw_msg = lo_message_serialise(lo_msg, "/foo/bar", NULL, &raw_msg_size); + + LV2Message* msg = lv2_osc_message_from_raw(0.0, 0, NULL, raw_msg_size, raw_msg); + assert(msg); + + LV2OSCBuffer* buf = lv2_osc_buffer_new(1024); + + int ret = lv2_osc_buffer_append_message(buf, msg); + if (ret) + fprintf(stderr, "Message append failed: %s", strerror(ret)); + + lo_message lo_msg_2 = lo_message_new(); + lo_message_add_string(lo_msg_2, "Another message"); + + raw_msg = lo_message_serialise(lo_msg_2, "/baz", NULL, &raw_msg_size); + + msg = lv2_osc_message_from_raw(0.0, 0, NULL, raw_msg_size, raw_msg); + assert(msg); + + ret = lv2_osc_buffer_append_message(buf, msg); + if (ret) + fprintf(stderr, "Message append failed: %s", strerror(ret)); + + printf("\nBuffer contents:\n\n"); + lv2_osc_buffer_print(buf); + + return 0; +} diff --git a/ns/ext/osc/manifest.ttl b/ns/ext/osc/manifest.ttl new file mode 100644 index 0000000..7209b05 --- /dev/null +++ b/ns/ext/osc/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/osc/osc-print.h b/ns/ext/osc/osc-print.h new file mode 100644 index 0000000..ceebbf7 --- /dev/null +++ b/ns/ext/osc/osc-print.h @@ -0,0 +1,42 @@ +/* LV2 OSC Messages Extension - Pretty printing methods + * Copyright (C) 2007-2009 David Robillard + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** @file + * Helper functions for printing LV2 OSC messages as defined by the + * LV2 OSC extension . + */ + +#ifndef LV2_OSC_PRINT_H +#define LV2_OSC_PRINT_H + +#include "lv2/lv2plug.in/ns/ext/osc/osc.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void +lv2_osc_argument_print(char type, const LV2_OSC_Argument* arg); + +void +lv2_osc_message_print(const LV2_OSC_Event* msg); + +#ifdef __cplusplus +} +#endif + +#endif /* LV2_OSC_PRINT_H */ diff --git a/ns/ext/osc/osc.h b/ns/ext/osc/osc.h new file mode 100644 index 0000000..05e39cc --- /dev/null +++ b/ns/ext/osc/osc.h @@ -0,0 +1,119 @@ +/* LV2 OSC Messages Extension + * Copyright (C) 2007-2009 David Robillard + * + * This header is free software; you can redistribute it and/or modify it + * under the terms of the GNU 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LV2_OSC_H +#define LV2_OSC_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file + * C header for the LV2 OSC extension . + * This extension defines a format for (raw) OSC messages/events. + */ + + +/** Argument (in a message). + * + * The name of the element in this union directly corresponds to the OSC + * type tag character in LV2_Event::types. + */ +typedef union { + /* Standard OSC types */ + int32_t i; /**< 32 bit signed integer */ + float f; /**< 32 bit IEEE-754 floating point number ("float") */ + char s; /**< Standard C, NULL terminated string */ + uint8_t b; /**< Blob (int32 size then size bytes padded to 32 bits) */ + + /* "Nonstandard" OSC types (defined in the OSC standard) */ + int64_t h; /* 64 bit signed integer */ + // t /* OSC-timetag */ + double d; /* 64 bit IEEE 754 floating point number ("double") */ + // S /* Symbol, represented as an OSC-string */ + int32_t c; /* Character, represented as a 32-bit integer */ + // r /* 32 bit RGBA color */ + // m /* 4 byte MIDI message. Bytes from MSB to LSB are: port id, status byte, data1, data2 */ + // T /* True. No bytes are allocated in the argument data. */ + // F /* False. No bytes are allocated in the argument data. */ + // N /* Nil. No bytes are allocated in the argument data. */ + // I /* Infinitum. No bytes are allocated in the argument data. */ + // [ /* The beginning of an array. */ + // ] /* The end of an array. */ +} LV2_OSC_Argument; + + + +/** Message. + * + * This is an OSC message at heart, but with some additional cache information + * to allow fast access to parameters. This is the payload of an LV2_Event, + * time stamp and size (being generic) are in the containing header. + */ +typedef struct { + uint32_t data_size; /**< Total size of data, in bytes */ + uint32_t argument_count; /**< Number of arguments in data */ + uint32_t types_offset; /**< Offset of types string in data */ + + /** Take the address of this member to get a pointer to the remaining data. + * + * Contents are an argument index: + * uint32_t argument_index[argument_count] + * + * followed by a standard OSC message: + * char path[path_length] (padded OSC string) + * char types[argument_count] (padded OSC string) + * void data[data_size] + */ + char data; + +} LV2_OSC_Event; + +LV2_OSC_Event* lv2_osc_event_new(const char* path, const char* types, ...); + +LV2_OSC_Event* lv2_osc_event_from_raw(uint32_t out_buf_size, void* out_buf, + uint32_t raw_msg_size, void* raw_msg); + +static inline uint32_t lv2_osc_get_osc_message_size(const LV2_OSC_Event* msg) + { return (msg->argument_count * sizeof(char) + 1) + msg->data_size; } + +static inline const void* lv2_osc_get_osc_message(const LV2_OSC_Event* msg) + { return (const void*)(&msg->data + (sizeof(uint32_t) * msg->argument_count)); } + +static inline const char* lv2_osc_get_path(const LV2_OSC_Event* msg) + { return (const char*)(&msg->data + (sizeof(uint32_t) * msg->argument_count)); } + +static inline const char* lv2_osc_get_types(const LV2_OSC_Event* msg) + { return (const char*)(&msg->data + msg->types_offset); } + +static inline LV2_OSC_Argument* lv2_osc_get_argument(const LV2_OSC_Event* msg, uint32_t i) + { return (LV2_OSC_Argument*)(&msg->data + ((uint32_t*)&msg->data)[i]); } + +/* +int lv2_osc_buffer_append_message(LV2_Event_Buffer* buf, LV2_Event* msg); +int lv2_osc_buffer_append(LV2_Event_Buffer* buf, double time, const char* path, const char* types, ...); +void lv2_osc_buffer_compact(LV2_Event_Buffer* buf); +*/ + +#ifdef __cplusplus +} +#endif + +#endif /* LV2_OSC_H */ diff --git a/ns/ext/osc/osc.ttl b/ns/ext/osc/osc.ttl new file mode 100644 index 0000000..c83a69d --- /dev/null +++ b/ns/ext/osc/osc.ttl @@ -0,0 +1,39 @@ +# LV2 OSC Messages Extension +# Copyright (C) 2007 David Robillard +# +# 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 osc: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + doap:name "LV2 OSC Events" ; + doap:shortdesc "A data type for raw OSC." ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] . diff --git a/ns/ext/osc/waf b/ns/ext/osc/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/osc/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/osc/wscript b/ns/ext/osc/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/osc/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/parameter/ext.pc.in b/ns/ext/parameter/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/parameter/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/parameter/manifest.ttl b/ns/ext/parameter/manifest.ttl new file mode 100644 index 0000000..d7af7ff --- /dev/null +++ b/ns/ext/parameter/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/parameter/parameter.ttl b/ns/ext/parameter/parameter.ttl new file mode 100644 index 0000000..191aa81 --- /dev/null +++ b/ns/ext/parameter/parameter.ttl @@ -0,0 +1,111 @@ +# LV2 Parameter Extension +# Copyright (C) 2010 David Robillard +# +# 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 atom: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix param: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a lv2:Specification ; + doap:name "LV2 Parameter" ; + doap:shortdesc "Dynamic message-controlled LV2 plugin parameters." ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + rdfs:comment """ +""" . + + +param:Parameter a rdfs:Class ; a lv2:Resource ; + rdfs:label "Parameter" ; + lv2:documentation """ +

A parameter on an LV2 plugin. Parameters can be manipulated to alter +the behaviour or output of a plugin. Unlike lv2:ControlPort:

+
    +
  • A parameter may have any data type
  • +
  • Parameters can be dynamically added or removed
  • +
  • Parameter values can be manipulated by the plugin
  • +
+ +

Note that plugins are not required to support this potential functionality, +parameters can be used to provide a basic LADSPA-like set of floating point +parameters in a more extensible manner.

+ +

Parameters are essentially controls that are not 1:1 associated with ports +(manipulation of parameters can be accomplished by e.g. sending messages +to a command port).

+""" . + + +param:supportsType a rdf:Property ; + rdfs:domain param:Parameter ; + rdfs:range atom:AtomType ; + rdfs:label "supports type" ; + lv2:documentation """ +

Indicates that a Parameter has values of a particular type. A Parameter may +support many types. Parameter values are always LV2 Atoms as defined by the LV2 Atom Extension Any type of LV2 +Atom may be used as a parameter value.

+""" . + + +param:value a rdf:Property ; + rdfs:domain param:Parameter ; + rdfs:label "value" ; + rdfs:comment """ +Indicates that a Parameter has a certain value. A Parameter has at most +one value at any given time. The type of the value specified must be +one of the types specified by param:supportsType. When used in a plugin +data file this property specifies the default value of a parameter. +""" . + + +param:minimum a rdf:Property ; + rdfs:domain param:Parameter ; + rdfs:label "minimum" ; + rdfs:comment """ +Specifies the minimum value of a Parameter (for Parameters with comparable +types for which this makes sense). The type of the minimum must be one of +the types specified by param:supportsType. The host MAY attempt to set a +parameter to any value (of a legal type), i.e. the plugin MUST NOT assume +attempts to change a parameter are within range and SHOULD clamp accordingly. +""" . + + +param:maximum a rdf:Property ; + rdfs:domain param:Parameter ; + rdfs:label "maximum" ; + rdfs:comment """ +Specifies the maximum value of a Parameter (for Parameters with comparable +types for which this makes sense). The type of the maximum must be one of +the types specified by param:supportsType. The host MAY attempt to set a +parameter to any value (of a legal type), i.e. the plugin MUST NOT assume +attempts to change a parameter are within range and SHOULD clamp accordingly. +""" . + diff --git a/ns/ext/parameter/waf b/ns/ext/parameter/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/parameter/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/parameter/wscript b/ns/ext/parameter/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/parameter/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/port-groups/ext.pc.in b/ns/ext/port-groups/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/port-groups/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/port-groups/manifest.ttl b/ns/ext/port-groups/manifest.ttl new file mode 100644 index 0000000..ff4205b --- /dev/null +++ b/ns/ext/port-groups/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/port-groups/port-groups.ttl b/ns/ext/port-groups/port-groups.ttl new file mode 100644 index 0000000..b584a25 --- /dev/null +++ b/ns/ext/port-groups/port-groups.ttl @@ -0,0 +1,490 @@ +# LV2 Port Groups Extension +# PROVISIONAL +# Copyright (C) 2009 David Robillard +# Copyright (C) 2008-2009 Lars Luthman +# +# 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 pg: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix owl: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . +@prefix amb: . + + a lv2:Specification ; + doap:license ; + doap:name "LV2 Port Groups" ; + doap:shortdesc "Multi-channel groups of LV2 ports." ; + rdfs:comment "Defines semantic groupings of LV2 ports" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "Lars Luthman" ; + foaf:mbox + ] , [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] . + + +## Core Classes / Properties + +pg:Group a rdfs:Class ; + rdfs:label "LV2 Port Group" ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty lv2:symbol ; + owl:someValuesFrom xsd:string ; + owl:cardinality 1 ; + rdfs:comment """ +A pg:Group MUST have exactly one string lv2:symbol. This symbol must be +unique according to the same rules as the lv2:symbol for an lv2:Port, where +group symbols and port symbols reside in the same namespace. In other words, +a group on a plugin MUST NOT have the same symbol as another group or a port +on that plugin. Rationale: Hosts or bindings may find it useful to construct +an identifier to refer to groups for the same reasons this is useful for ports. +""" + ] ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty pg:hasRole ; + owl:someValuesFrom pg:RoleAssignment ; + owl:minCardinality 1 ; + rdfs:comment "A Group MUST have at least one role assignment" + ] ; + rdfs:comment """ +A grouping of ports that can be logically considered a single "stream", e.g. +two audio ports in a group may form a stereo stream. The pg:source predicate +can also be used to describe this correspondence between separate ports/groups. +""" . + +pg:index a rdf:Property ; + rdfs:domain pg:RoleAssignment ; + rdfs:range xsd:nonNegativeInteger ; + rdfs:label "index" ; + rdfs:comment "Index of a role within some group" . + +pg:RoleAssignment a rdfs:Class ; + rdfs:label "Role Assignment" ; + rdfs:comment "A numbered role within some Group." ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty pg:index ; + owl:cardinality 1 ; + rdfs:comment """ +A RoleAssignment MUST have exactly one index. +""" ] ; + rdfs:subClassOf [ a owl:Restriction ; + owl:onProperty pg:role ; + owl:cardinality 1 ; + rdfs:comment """ +A RoleAssignment MUST have exactly one role. +""" ] ; + rdfs:comment """ +All group definitions MUST define the order of channels. Note that this +does not have anything to do with port indices, this information is only +defined here for use by other extensions. For simply assigning groups +and roles to a basic LV2 plugin, index is irrelevant. +""" . + +pg:hasChannel a rdf:Property ; + rdfs:domain pg:Group ; + rdfs:range pg:Channel ; + rdfs:label "Has port with role" ; + rdfs:comment """ +Indicates that a group always has a port with a particular role. +""" . + +pg:sideChainOf a rdf:Property ; + rdfs:domain pg:Group , lv2:Port ; + rdfs:range pg:Group , lv2:Port ; + rdfs:label "Side-chain of" ; + rdfs:comment """ +Indicates that this port or group should be considered a "side chain" of +some other port or group. The precise definition of "side chain" depends +on the plugin, but in general this group should be considered a modifier to +some other group, rather than an independent input itself. +""" . + +pg:subGroupOf a rdf:Property ; + rdfs:domain pg:Group ; + rdfs:range pg:Group ; + rdfs:label "Sub-group of" ; + rdfs:comment """ +Indicates that this group is a child of another group. This property has +no meaning with respect to plugin execution, but the host may find this +information useful (e.g. to provide a compact user interface). Note that +all groups on a plugin MUST have a unique symbol with respect to the plugin +as documented for pg:Group, i.e. sub-groups must have a unique symbol among +all groups and ports on the plugin. +""" . + +pg:source a rdf:Property ; + rdfs:domain pg:Group , lv2:Port ; + rdfs:range pg:Group , lv2:Port ; + rdfs:label "Source group" ; + rdfs:comment """ +Indicates that this port or group should be considered the "result" of +some other port or group. This property only makes sense on groups with +outputs when the source is a group with inputs. This can be used to convey +a relationship between corresponding input and output groups with different +types, e.g. a mono->stereo plugin. +""" . + +pg:mainGroup a rdf:Property ; + rdfs:domain lv2:Plugin ; + rdfs:range pg:Group ; + rdfs:label "Main port group" ; + rdfs:comment """ +Indicates that this group should be considered the "main" inputs/outputs of +the plugin, e.g. it probably makes sense to just connect main groups and set +some controls. A plugin MUST NOT have more than one :mainGroup property. +High-level hosts that simply want to insert an plugin in a given stream +should use this property to determine where the plugin 'fits'. +""" . + +pg:inGroup a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range pg:Group ; + rdfs:label "In port group" ; + rdfs:comment """ +Indicates that this port is a part of a group of ports on the plugin. +Ports that have a meaningful "role" that may be useful to hosts SHOULD also +have a :role property, otherwise ports in the group have no meaningful order. +""" . + +pg:Role a rdfs:Class ; + rdfs:label "Port role" ; + rdfs:comment """ +The role of a port with respect to its plugin or group. If the port is a +member of a group (has an :inGroup property) the role is relevant with respect +to that group. Otherwise the role is relevant with respect to the plugin. +""" . + +pg:role a rdf:Property ; + rdfs:domain pg:Port , pg:RoleAssignment; + rdfs:range pg:Role ; + rdfs:label "Role" ; + rdfs:comment """ +Indicates that this port has a particular role with respect to its enclosing +plugin or group (whichever is smaller). A port may have several roles if it +makes sense to do so (though some Role or Group definition may forbid this). +""" . + + +# Discrete + +pg:DiscreteGroup a rdfs:Class ; + rdfs:subClassOf pg:Group ; + rdfs:comment """ +"Discrete" channel configurations. These groups are divided into channels +where each represents a particular speaker location. The position of sound +in one of these groups depends on a particular speaker configuration. +""" . + +pg:leftChannel a pg:Role ; rdfs:label "Left" . +pg:rightChannel a pg:Role ; rdfs:label "Right" . +pg:centerChannel a pg:Role ; rdfs:label "Center" . +pg:sideChannel a pg:Role ; rdfs:label "Side" . +pg:centerLeftChannel a pg:Role ; rdfs:label "Center Left" . +pg:centerRightChannel a pg:Role ; rdfs:label "Center Right" . +pg:sideLeftChannel a pg:Role ; rdfs:label "Side Left" . +pg:sideRightChannel a pg:Role ; rdfs:label "Side Right" . +pg:rearLeftChannel a pg:Role ; rdfs:label "Rear Left" . +pg:rearRightChannel a pg:Role ; rdfs:label "Rear Right" . +pg:rearCenterChannel a pg:Role ; rdfs:label "Rear Center" . +pg:lfeChannel a pg:Role ; rdfs:label "Sub (LFE)" . + +pg:MonoGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "Mono" ; + pg:hasRole [ pg:index 0; pg:role pg:centerChannel ] . + +pg:StereoGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "Stereo" ; + pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ; + pg:hasRole [ pg:index 1; pg:role pg:rightChannel ] . + +pg:MidSideGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "Mid-Side Stereo" ; + pg:hasRole [ pg:index 0; pg:role pg:centerChannel ] ; + pg:hasRole [ pg:index 1; pg:role pg:sideChannel ] . + +pg:ThreePointZeroGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "3.0 Surround" ; + pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ; + pg:hasRole [ pg:index 1; pg:role pg:rightChannel ] ; + pg:hasRole [ pg:index 2; pg:role pg:rearCenterChannel ] . + +pg:FourPointZeroGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "4.0 Surround (Quadraphonic)" ; + pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ; + pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ; + pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ; + pg:hasRole [ pg:index 3; pg:role pg:rearCenterChannel ] . + +pg:FivePointZeroGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "5.0 Surround (3-2 stereo)" ; + pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ; + pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ; + pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ; + pg:hasRole [ pg:index 3; pg:role pg:rearLeftChannel ] ; + pg:hasRole [ pg:index 4; pg:role pg:rearRightChannel ] . + +pg:FivePointOneGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "5.1 Surround (3-2 stereo)" ; + pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ; + pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ; + pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ; + pg:hasRole [ pg:index 3; pg:role pg:rearLeftChannel ] ; + pg:hasRole [ pg:index 4; pg:role pg:rearRightChannel ] ; + pg:hasRole [ pg:index 5; pg:role pg:lfeChannel ] . + +pg:SixPointOneGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "6.1 Surround" ; + pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ; + pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ; + pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ; + pg:hasRole [ pg:index 3; pg:role pg:sideLeftChannel ] ; + pg:hasRole [ pg:index 4; pg:role pg:sideRightChannel ] ; + pg:hasRole [ pg:index 5; pg:role pg:rearCenterChannel ] ; + pg:hasRole [ pg:index 6; pg:role pg:lfeChannel ] . + +pg:SevenPointOneGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "7.1 Surround" ; + pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ; + pg:hasRole [ pg:index 1; pg:role pg:centerChannel ] ; + pg:hasRole [ pg:index 2; pg:role pg:rightChannel ] ; + pg:hasRole [ pg:index 3; pg:role pg:sideLeftChannel ] ; + pg:hasRole [ pg:index 4; pg:role pg:sideRightChannel ] ; + pg:hasRole [ pg:index 5; pg:role pg:rearLeftChannel ] ; + pg:hasRole [ pg:index 6; pg:role pg:rearRightChannel ] ; + pg:hasRole [ pg:index 7; pg:role pg:lfeChannel ] . + +pg:SevenPointOneWideGroup a rdfs:Class ; + rdfs:subClassOf pg:DiscreteGroup ; + rdfs:label "7.1 Surround (Wide)" ; + pg:hasRole [ pg:index 0; pg:role pg:leftChannel ] ; + pg:hasRole [ pg:index 1; pg:role pg:centerLeftChannel ] ; + pg:hasRole [ pg:index 2; pg:role pg:centerChannel ] ; + pg:hasRole [ pg:index 3; pg:role pg:centerRightChannel ] ; + pg:hasRole [ pg:index 4; pg:role pg:rightChannel ] ; + pg:hasRole [ pg:index 5; pg:role pg:leftRearChannel ] ; + pg:hasRole [ pg:index 6; pg:role pg:rightRearChannel ] ; + pg:hasRole [ pg:index 7; pg:role pg:lfeChannel ] . + + +# Ambisonic + +pg:AmbisonicGroup a rdfs:Class ; + rdfs:subClassOf pg:Group ; + rdfs:comment """ +"Ambisonic" channel configurations. These groups are divided into channels +which together represent a position in an abstract n-dimensional space. +The position of sound in one of these groups does not depend on a particular +speaker configuration; a decoder can be used to convert an ambisonic stream +for any speaker configuration. +""" . + +#amb:ACN0 a pg:Role ; rdfs:label "ACN 0 (W)" . +#amb:ACN1 a pg:Role ; rdfs:label "ACN 1 (Y)" . +#amb:ACN2 a pg:Role ; rdfs:label "ACN 2 (Z)" . +#amb:ACN3 a pg:Role ; rdfs:label "ACN 3 (X)" . +#amb:ACN4 a pg:Role ; rdfs:label "ACN 4 (V)" . +#amb:ACN5 a pg:Role ; rdfs:label "ACN 5 (T)" . +#amb:ACN6 a pg:Role ; rdfs:label "ACN 6 (R)" . +#amb:ACN7 a pg:Role ; rdfs:label "ACN 7 (S)" . +#amb:ACN8 a pg:Role ; rdfs:label "ACN 8 (U)" . +#amb:ACN9 a pg:Role ; rdfs:label "ACN 9 (Q)" . +#amb:ACN10 a pg:Role ; rdfs:label "ACN 10 (O)" . +#amb:ACN11 a pg:Role ; rdfs:label "ACN 11 (M)" . +#amb:ACN12 a pg:Role ; rdfs:label "ACN 12 (K)" . +#amb:ACN13 a pg:Role ; rdfs:label "ACN 13 (L)" . +#amb:ACN14 a pg:Role ; rdfs:label "ACN 14 (N)" . +#amb:ACN15 a pg:Role ; rdfs:label "ACN 15 (P)" . + +pg:AmbisonicBH1P0Group a rdfs:Class ; + rdfs:subClassOf pg:AmbisonicGroup ; + rdfs:label "Ambisonic B stream of horizontal order 1 and peripheral order 0." ; + pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ; + pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ; + pg:hasRole [ pg:index 2; pg:role amb:ACN3 ] . + +pg:AmbisonicBH1P1Group a rdfs:Class ; + rdfs:subClassOf pg:AmbisonicGroup ; + rdfs:label "Ambisonic B stream of horizontal order 1 and peripheral order 1." ; + pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ; + pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ; + pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ; + pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] . + +pg:AmbisonicBH2P0Group a rdfs:Class ; + rdfs:subClassOf pg:AmbisonicGroup ; + rdfs:label "Ambisonic B stream of horizontal order 2 and peripheral order 0." ; + pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ; + pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ; + pg:hasRole [ pg:index 2; pg:role amb:ACN3 ] ; + pg:hasRole [ pg:index 3; pg:role amb:ACN4 ] ; + pg:hasRole [ pg:index 4; pg:role amb:ACN8 ] . + +pg:AmbisonicBH2P1Group a rdfs:Class ; + rdfs:subClassOf pg:AmbisonicGroup ; + rdfs:label "Ambisonic B stream of horizontal order 2 and peripheral order 1." ; + pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ; + pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ; + pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ; + pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ; + pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ; + pg:hasRole [ pg:index 5; pg:role amb:ACN8 ] . + +pg:AmbisonicBH2P2Group a rdfs:Class ; + rdfs:subClassOf pg:AmbisonicGroup ; + rdfs:label "Ambisonic B stream of horizontal order 2 and peripheral order 2." ; + pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ; + pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ; + pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ; + pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ; + pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ; + pg:hasRole [ pg:index 5; pg:role amb:ACN5 ] ; + pg:hasRole [ pg:index 6; pg:role amb:ACN6 ] ; + pg:hasRole [ pg:index 7; pg:role amb:ACN7 ] ; + pg:hasRole [ pg:index 8; pg:role amb:ACN8 ] . + +pg:AmbisonicBH3P0Group a rdfs:Class ; + rdfs:subClassOf pg:AmbisonicGroup ; + rdfs:label "Ambisonic B stream of horizontal order 3 and peripheral order 0." ; + pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ; + pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ; + pg:hasRole [ pg:index 2; pg:role amb:ACN3 ] ; + pg:hasRole [ pg:index 3; pg:role amb:ACN4 ] ; + pg:hasRole [ pg:index 4; pg:role amb:ACN8 ] ; + pg:hasRole [ pg:index 5; pg:role amb:ACN9 ] ; + pg:hasRole [ pg:index 6; pg:role amb:ACN15 ] . + +pg:AmbisonicBH3P1Group a rdfs:Class ; + rdfs:subClassOf pg:AmbisonicGroup ; + rdfs:label "Ambisonic B stream of horizontal order 3 and peripheral order 1." ; + pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ; + pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ; + pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ; + pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ; + pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ; + pg:hasRole [ pg:index 5; pg:role amb:ACN8 ] ; + pg:hasRole [ pg:index 6; pg:role amb:ACN9 ] ; + pg:hasRole [ pg:index 7; pg:role amb:ACN15 ] . + +pg:AmbisonicBH3P2Group a rdfs:Class ; + rdfs:subClassOf pg:AmbisonicGroup ; + rdfs:label "Ambisonic B stream of horizontal order 3 and peripheral order 2." ; + pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ; + pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ; + pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ; + pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ; + pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ; + pg:hasRole [ pg:index 5; pg:role amb:ACN5 ] ; + pg:hasRole [ pg:index 6; pg:role amb:ACN6 ] ; + pg:hasRole [ pg:index 7; pg:role amb:ACN7 ] ; + pg:hasRole [ pg:index 8; pg:role amb:ACN8 ] ; + pg:hasRole [ pg:index 9; pg:role amb:ACN9 ] ; + pg:hasRole [ pg:index 10; pg:role amb:ACN15 ] . + +pg:AmbisonicBH3P3Group a rdfs:Class ; + rdfs:subClassOf pg:AmbisonicGroup ; + rdfs:label "Ambisonic B stream of horizontal order 3 and peripheral order 3." ; + pg:hasRole [ pg:index 0; pg:role amb:ACN0 ] ; + pg:hasRole [ pg:index 1; pg:role amb:ACN1 ] ; + pg:hasRole [ pg:index 2; pg:role amb:ACN2 ] ; + pg:hasRole [ pg:index 3; pg:role amb:ACN3 ] ; + pg:hasRole [ pg:index 4; pg:role amb:ACN4 ] ; + pg:hasRole [ pg:index 5; pg:role amb:ACN5 ] ; + pg:hasRole [ pg:index 6; pg:role amb:ACN6 ] ; + pg:hasRole [ pg:index 7; pg:role amb:ACN7 ] ; + pg:hasRole [ pg:index 8; pg:role amb:ACN8 ] ; + pg:hasRole [ pg:index 9; pg:role amb:ACN9 ] ; + pg:hasRole [ pg:index 10; pg:role amb:ACN10 ] ; + pg:hasRole [ pg:index 11; pg:role amb:ACN11 ] ; + pg:hasRole [ pg:index 12; pg:role amb:ACN12 ] ; + pg:hasRole [ pg:index 13; pg:role amb:ACN13 ] ; + pg:hasRole [ pg:index 14; pg:role amb:ACN14 ] ; + pg:hasRole [ pg:index 15; pg:role amb:ACN15 ] . + + +# Controls + +pg:ControlGroup a rdfs:Class ; + rdfs:subClassOf pg:Group ; + rdfs:comment """ +A group representing a set of associated controls. +""" . + +pg:amplitude a pg:Role ; rdfs:label "Amplitude" . +pg:attack a pg:Role ; rdfs:label "Attack" . +pg:cutoffFrequency a pg:Role ; rdfs:label "Cutoff Frequency" . +pg:decay a pg:Role ; rdfs:label "Decay" . +pg:delay a pg:Role ; rdfs:label "Delay" . +pg:frequency a pg:Role ; rdfs:label "Frequency" . +pg:hold a pg:Role ; rdfs:label "Hold" . +pg:pulseWidth a pg:Role ; rdfs:label "Pulse Width" . +pg:ratio a pg:Role ; rdfs:label "Ratio" . +pg:release a pg:Role ; rdfs:label "Release" . +pg:resonance a pg:Role ; rdfs:label "Resonance" . +pg:sustain a pg:Role ; rdfs:label "Sustain" . +pg:threshold a pg:Role ; rdfs:label "Threshold" . +pg:waveform a pg:Role ; rdfs:label "Waveform" . + +pg:EnvelopeControlGroup a rdfs:Class ; + rdfs:subClassOf pg:ControlGroup ; + rdfs:label "Controls for a DAHDSR envelope." ; + pg:mayHavePort pg:delay ; + pg:mayHavePort pg:attack ; + pg:mayHavePort pg:hold ; + pg:mayHavePort pg:decay ; + pg:mayHavePort pg:sustain ; + pg:mayHavePort pg:release . + +pg:OscillatorControlGroup a rdfs:Class ; + rdfs:subClassOf pg:ControlGroup ; + rdfs:label "Controls for an oscillator." ; + pg:mayHavePort pg:frequency ; + pg:mayHavePort pg:amplitude ; + pg:mayHavePort pg:waveform ; + pg:mayHavePort pg:pulseWidth . + +pg:FilterControlGroup a rdfs:Class ; + rdfs:subClassOf pg:ControlGroup ; + rdfs:label "Controls for a filter." ; + pg:mayHavePort pg:cutoffFrequency ; + pg:mayHavePort pg:resonance . + +pg:CompressorControlGroup a rdfs:Class ; + rdfs:subClassOf pg:ControlGroup ; + rdfs:label "Controls for a compressor." ; + pg:mayHavePort pg:threshold ; + pg:mayHavePort pg:ratio . + diff --git a/ns/ext/port-groups/waf b/ns/ext/port-groups/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/port-groups/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/port-groups/wscript b/ns/ext/port-groups/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/port-groups/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/port-props/ext.pc.in b/ns/ext/port-props/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/port-props/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/port-props/manifest.ttl b/ns/ext/port-props/manifest.ttl new file mode 100644 index 0000000..b4afe2f --- /dev/null +++ b/ns/ext/port-props/manifest.ttl @@ -0,0 +1,8 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . diff --git a/ns/ext/port-props/port-props.ttl b/ns/ext/port-props/port-props.ttl new file mode 100644 index 0000000..d811959 --- /dev/null +++ b/ns/ext/port-props/port-props.ttl @@ -0,0 +1,217 @@ +@prefix pprops: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a lv2:Specification ; + doap:name "LV2 Port Properties" ; + doap:release [ + doap:revision "0.1" ; + doap:created "2011-11-01" + ] ; + doap:created "2009-01-01" ; + doap:shortdesc "Additional properties for LV2 plugin ports." ; + doap:maintainer [ + a foaf:Person ; + foaf:name "Krzysztof Foltman" + ] , [ + a foaf:Person ; + foaf:name "David Robillard" ; + rdfs:seeAlso + ] ; + lv2:documentation """ +

This extension defines several useful properties for LV2 plugin ports, which +can be used in plugin descriptions to better describe ports. Using this +metadata, hosts can build better UIs for plugins, and provide more advanced +automatic functionality.

+""" . + +pprops:trigger + a lv2:PortProperty ; + rdfs:label "Trigger" ; + rdfs:comment """ +Indicates that the data item corresponds to a momentary event that has been +detected (control output ports) or is to be triggered (control input ports). +For input ports, the port needs to be reset to lv2:default value after run() +function of the plugin has returned. If the control port is assigned a GUI +widget by the host, the widget should be of auto-off (momentary, one-shot) type +- for example, a push button if the port is also declared as lv2:toggled, or a +series of push button or auto-clear input box with a "Send" button if the port +is also lv2:integer. +""" . + +pprops:supportsStrictBounds + a lv2:Feature ; + rdfs:label "Supports strict bounds" ; + rdfs:comment """ +Indicates use of host support for pprops:hasStrictBounds port property. A +plugin that specifies it as optional feature can omit value clamping for +hasStrictBounds ports, if the feature is supported by the host. When specified +as required feature, it indicates that the plugin does not do any clamping for +input ports that have a pprops:hasStrictBounds property. +""" . + +pprops:hasStrictBounds + a lv2:PortProperty ; + rdfs:label "Has strict bounds" ; + rdfs:comment """ +For hosts that support pprops:supportsStrictBounds, this indicates that the +value of the port should never exceed the port's minimum and maximum control +points. For input ports, it moves the responsibility for limiting the range of +values to host, if it supports pprops:supportsStrictBounds. For output ports, +it indicates that values within specified range are to be expected, and +breaking that should be considered by the host as error in plugin +implementation. +""" . + +pprops:expensive + a lv2:PortProperty ; + rdfs:label "Changes trigger expensive calculation" ; + rdfs:comment """ +Input ports only. Indicates that any changes to the port value may trigger +expensive background calculation (e.g. regenerate some lookup tables in a +background thread). Any value changes may have not have immediate effect, or +may cause silence or diminished-quality version of the output until background +processing is finished. Ports having this property are typically not well +suited for connection to outputs of other plugins, and should not be offered as +connection targets or for automation by default. +""" . + +pprops:causesArtifacts + a lv2:PortProperty ; + rdfs:label "May cause audio artifacts when changed" ; + rdfs:comment """ +Input ports only. Indicates that any changes to the port value may produce +slight artifacts to produced audio signals (zipper noise and other results of +signal discontinuities). Connecting ports of this type to continuous signals +is not recommended, and when presenting a list of automation targets, those +ports may be marked as artifact-producing. +""" . + +pprops:continuousCV + a lv2:PortProperty ; + rdfs:label "Carries a smooth modulation signal" ; + rdfs:comment """ +Indicates that the port carries a "smooth" modulation signal. Control input +ports of this type are well-suited for being connected to sources of smooth +signals (knobs with smoothing, modulation rate oscillators, output ports with +continuousCV type, etc.). Typically, the plugin with ports which have this +property will implement appropriate smoothing to avoid audio artifacts. For +output ports, this property suggests the value of the port is likely to change +frequently, and describes a smooth signal (e.g. successive values may be +considered points along a curve). +""" . + +pprops:discreteCV + a lv2:PortProperty ; + rdfs:label "Carries a discrete modulation signal" ; + rdfs:comment """ +Indicates that the port carries a "discrete" modulation signal. Input ports of +this type are well-suited for being connected to sources of discrete signals +(switches, buttons, classifiers, event detectors, etc.). May be combined with +pprops:trigger property. For output ports, this property suggests the value of +the port describe discrete values that should be interpreted as steps (and not +points along a curve). +""" . + +pprops:reportsBpm + a lv2:PortProperty ; + rdfs:label "Carries the current tempo expressed in BPM" ; + rdfs:comment """ +Indicates that the port is used to pass the current tempo in context of the +plugin (which may be current song tempo, or tempo of a particular subset of the +song, or the subgraph the plugin resides in). For input ports, the host may +automatically feed the port with current tempo and hide the port from the user, +unless the user or other factors encourage different behaviour. +""" . + +pprops:reportsBeatsPerBar + a lv2:PortProperty ; + rdfs:label "Carries the current number of beats in a bar" ; + rdfs:comment """ +Indicates that the port may be used to pass the current number of beats in a +bar. """ . + +pprops:reportsBeatUnit + a lv2:PortProperty ; + rdfs:label "Carries the current beat size" ; + rdfs:comment """ +Indicates that the port may be used to pass the current size of a beat (4 for a +crochet/quarter note, 8 for a quaver/eighth note, etc.). +""" . + +pprops:logarithmic + a lv2:PortProperty ; + rdfs:label "Port value uses a logarithmic scale" ; + rdfs:comment """ +Indicates that port value behaviour within specified range (bounds) is a value +using logarithmic scale. The lower and upper bounds must be specified, and +must be of the same sign. +""" . + +pprops:notAutomatic + a lv2:PortProperty ; + rdfs:label "Port is not intended as a CV input" ; + rdfs:comment """ +Indicates that the port is not primarily intended to be fed with modulation +signals from external sources (other plugins, etc.). It is merely a UI hint +and hosts may allow the user to override it. +""" . + +pprops:notOnGUI + a lv2:PortProperty ; + rdfs:label "Port is not to be displayed on a GUI or equivalent" ; + rdfs:comment """ +Indicates that the port is not primarily intended to be represented by a +separate control in the user interface window (or any similar mechanism used +for direct, immediate control of control ports). It is merely a UI hint and +hosts may allow the user to override it. +""" . + +pprops:priority + a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range xsd:float ; + rdfs:label "Relative usefulness of a port" ; + rdfs:comment """ +Indicates how (typically) useful is the port comparing to other ports with that +property (higher value = more important). The values do not need to be unique, +and ports can be grouped based on their priorities. +""" . + +pprops:rangeSteps + a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range xsd:nonNegativeInteger ; + rdfs:label "Number of value quantization steps" ; + lv2:documentation """ +

This value indicates into how many evenly-divided points the (control) port +range shoujld be divided for step-wise control. This may be used for changing +the value with step-based controllers like arrow keys, mouse wheel, rotary +encoders, etc.

+ +

Note that when used with a pprops:logarithmic port, the steps are +logarithmic too, and port value can be calculated as:

+ +
+value = lower * pow(upper / lower, step / (steps - 1))
+
+ +

and the step from value is:

+ +
+step = (steps - 1) * log(value / lower) / log(upper / lower)
+
+ +

where:

+
    +
  • value is the port value
  • +
  • step is the step number (0..steps)
  • +
  • steps is the number of steps (= value of :rangeSteps property)
  • +
  • lower and upper are the bounds
  • +
+""" . diff --git a/ns/ext/port-props/waf b/ns/ext/port-props/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/port-props/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/port-props/wscript b/ns/ext/port-props/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/port-props/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/presets/ext.pc.in b/ns/ext/presets/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/presets/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/presets/manifest.ttl b/ns/ext/presets/manifest.ttl new file mode 100644 index 0000000..51985ab --- /dev/null +++ b/ns/ext/presets/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 2 ; + lv2:microVersion 2 ; + rdfs:seeAlso . + diff --git a/ns/ext/presets/presets.ttl b/ns/ext/presets/presets.ttl new file mode 100644 index 0000000..ebe6d0f --- /dev/null +++ b/ns/ext/presets/presets.ttl @@ -0,0 +1,113 @@ +# LV2 Presets Extension +# Copyright 2009-2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix dcs: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix owl: . +@prefix pset: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + foaf:mbox ; + rdfs:seeAlso . + + + a lv2:Specification ; + doap:license ; + doap:name "LV2 Presets" ; + doap:shortdesc "Presets for LV2 plugins. " ; + doap:maintainer ; + doap:release [ + doap:revision "2.2" ; + doap:created "2011-11-14" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Update packaging." + ] , [ + rdfs:label "Improve documentation." + ] + ] + ] , [ + doap:revision "2.0" ; + doap:created "2010-10-04" ; + doap:file-release ; + dcs:blame ; + dcs:changeset [ + dcs:item [ + rdfs:label "Initial release." + ] + ] + ] ; + rdfs:comment """ +Defines presets (e.g. named sets of control values) for LV2 plugins. +""" . + +pset:Preset + a rdfs:Class ; + rdfs:subClassOf lv2:PluginBase ; + rdfs:label "LV2 Preset" ; + rdfs:subClassOf [ + a owl:Restriction ; + owl:onProperty rdfs:label ; + owl:someValuesFrom xsd:string ; + rdfs:comment "A Preset MUST have at least one string rdfs:label." + ] ; + rdfs:comment """ +A Preset for an LV2 Plugin. A preset can be considered an "overlay" on a +Plugin. Rather than attempting to define all valid predicates for a Preset +(which is not possible since presets may need to specify values for things +defined in other extensions), the presets extension simply provides this +class which can be augmented with any data in the exact same fashion as the +definition of a Plugin. + +A Preset SHOULD have at least one pset:appliesTo property. +Each Port on a Preset MUST have at least a lv2:symbol property and a +pset:value property. +""" . + +pset:appliesTo + a rdf:Property ; + rdfs:domain pset:Preset ; + rdfs:range lv2:Plugin ; + rdfs:label "Applies to" ; + rdfs:comment """ +Specifies the Plugin(s) a Preset may be applied to. When a Preset applies +to a Plugin, that Preset SHOULD have ports for every control port on that +plugin, each of which SHOULD have a pset:value property. If the Preset is +missing ports, or refers to ports which do not exist on the Plugin, then +the host SHOULD apply all the values in the preset that do match the Plugin. + +The Preset MAY have any other values that should be applied to the Plugin +in some way. The host SHOULD simply ignore any values on a Preset it does +not understand. +""" . + +pset:value + a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:label "Has value" ; + rdfs:comment """ +Specifies the value of a Port on some Preset. This property is used +in a similar way to e.g. lv2:default. +""" . diff --git a/ns/ext/presets/waf b/ns/ext/presets/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/presets/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/presets/wscript b/ns/ext/presets/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/presets/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/pui/ext.pc.in b/ns/ext/pui/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/pui/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/pui/manifest.ttl b/ns/ext/pui/manifest.ttl new file mode 100644 index 0000000..1229118 --- /dev/null +++ b/ns/ext/pui/manifest.ttl @@ -0,0 +1,8 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification; + lv2:minorVersion 0; + lv2:microVersion 1; + rdfs:seeAlso . diff --git a/ns/ext/pui/pui.h b/ns/ext/pui/pui.h new file mode 100644 index 0000000..caa7deb --- /dev/null +++ b/ns/ext/pui/pui.h @@ -0,0 +1,374 @@ +/************************************************************************ + * + * Plugin UI extension for LV2 + * + * Copyright (C) 2006-2011 Lars Luthman + * + * Based on lv2.h, which was + * + * Copyright (C) 2000-2002 Richard W.E. Furse, Paul Barton-Davis, + * Stefan Westerfeld + * Copyright (C) 2006 Steve Harris, David Robillard. + * + * 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.1 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA. + * + ***********************************************************************/ + +/** + @file pui.h C API for the LV2 UI extension . + + This file specifies a C API for communication between an LV2 host and an + LV2 UI. The interface is similar to the one used for actual LV2 plugins. + + The entry point is the function lv2ui_descriptor(). +*/ + +#ifndef LV2_PUI_H +#define LV2_PUI_H + +#include + +/** The URI of this extension (note this is not the same as the prefix). */ +#define LV2_PUI_URI "http://lv2plug.in/ns/ext/pui" + +/** The numerical ID returned by LV2_PUI_Host_Descriptor::port_index() for + invalid port symbols. */ +#define LV2_PUI_INVALID_PORT_INDEX ((uint32_t)-1) + +/** The full URI for the pui:floatControl PortProtocol. */ +#define LV2_PUI_FLOAT_CONTROL_URI "http://lv2plug.in/ns/ext/pui#floatControl" + +/** The full URI for the pui:floatPeakRMS PortProtocol. */ +#define LV2_PUI_FLOAT_PEAK_RMS_URI "http://lv2plug.in/ns/ext/pui#floatPeakRMS" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + A data type that is used to pass peak and RMS values for a period of + audio data at an input or output port to an UI, using port_event. See the + documentation for pui:floatPeakRMS for details about how and when this + should be done. +*/ +typedef struct _LV2_PUI_Peak_RMS_Data { + + /** + The start of the measurement period. This is just a running counter that + must not be interpreted as any sort of global frame position. It should + only be interpreted relative to the starts of other measurement periods + in port_event() calls to the same plugin instance. + + This counter is allowed to overflow, in which case it should just wrap + around. + */ + uint32_t period_start; + + /** + The size of the measurement period, in the same units as period_start. + */ + uint32_t period_size; + + /** + The peak value for the measurement period. This should be the maximal + value for abs(sample) over all the samples in the period. + */ + float peak; + + /** + The RMS value for the measurement period. This should be the root mean + square value of the samples in the period, equivalent to + sqrt((pow(sample1, 2) + pow(sample2, 2) + ... + pow(sampleN, 2)) / N) + where N is period_size. + */ + float rms; + +} LV2_PUI_Peak_RMS_Data; + +/** + A pointer to a widget or other type of UI. + The actual type is defined by the type of the UI defined in the RDF data. + All the functionality provided by this extension is toolkit independent, the + host only needs to pass the necessary callbacks and display the widget, if + possible. Plugins may have several UIs, in various toolkits. +*/ +typedef void* LV2_PUI_Widget; + +/** + Handle for a particular instance of a UI. + It is valid to compare this to NULL (0 for C++) but otherwise the host MUST + NOT attempt to interpret it. The UI may use it to reference internal + instance data. +*/ +typedef void* LV2_PUI_Handle; + +/** + Handle for host functions and data provided to a UI. + An object of this type is passed to the UI's instantiate() function, and the + UI must in turn pass it as the first parameter to the callbacks in + LV2_PUI_Host_Descriptor. The host may use it to reference internal data, such + as the plugin instance that the UI is associated with. The UI MUST NOT + interpret the value of an LV2_PUI_Host_Handle in any way. +*/ +typedef void* LV2_PUI_Host_Handle; + +/** + Host-provided functions that the UI can use to control the plugin instance. + + A pointer to an object of this type is passed to the lv2ui_descriptor() + function. + + The host MUST provide non-NULL values for all the function pointers. +*/ +typedef struct _LV2_PUI_Host_Descriptor { + + /** + Send data to one of the plugin's input ports. + + The @c buffer parameter MUST point to a block of data @c buffer_size + bytes large. The contents of this buffer and what the host should do + with it depends on the value of the @c port_protocol parameter. + + The @c port_protocol parameter MUST be a numeric ID for a + pui:PortProtocol. Numeric IDs for PortProtocols are retrieved using the + port_protocol_id() function. + + The @c buffer is only valid during the time of this function call, so if + the host wants to keep it for later use it has to copy the contents to an + internal buffer. + + @param host_handle The @c host_handle that was passed to the UI's + instantiate() function. + @param port_index The index of the port that the data should be written + to, as returned by port_index(). + @param buffer_size The size of the data pointed to by @c buffer, in + bytes. + @param port_protocol The numeric ID of the Port Protocol to use, + as returned by port_protocol_id(). + */ + void (*write_port)(LV2_PUI_Host_Handle host_handle, + uint32_t port_index, + uint32_t buffer_size, + uint32_t port_protocol, + void const* buffer); + + /** + Return the numerical index for a port. + This index is used when writing data to ports using write_port() and whe + receiving data using port_event(). If @c port_symbol is not a valid port + symbol for @c plugin the host it MUST return + LV2_PUI_INVALID_PORT_INDEX. For performance reasons it may be a good idea + to cache port indices in the UI at instantiation time. + + @param host_handle The LV2_PUI_Host_Handle that was passed to the UI's + instantiate() function. + @param port_symbol The port's symbol, as defined in the RDF data for + the plugin. + */ + uint32_t (*port_index)(LV2_PUI_Host_Handle host_handle, + char const* port_symbol); + + /** + Subscribe to updates for a port. + This means that the host will call the UI's port_event() function when + the port value changes (as defined by the PortProtocol). + + Calling this function with the same @c port_index and @c port_protocol + as an already active subscription has no effect. + + @param host_handle The @c host_handle that was passed to the UI's + instantiate() function. + @param port_index The index of the port, as returned by port_index(). + @param port_protocol The numeric ID of the PortProtocol, as + returned by port_protocol_id(). + */ + void (*subscribe_to_port)(LV2_PUI_Host_Handle host_handle, + uint32_t port_index, + uint32_t port_protocol, + const LV2_Feature* const* features); + + /** + Unsubscribe from updates for a port. + This means that the host will cease calling calling port_event() when + the port value changes. + + Calling this function with a @c port_index and @c port_protocol that + does not refer to an active port subscription has no effect. + + @param host_handle The @c host_handle that was passed to the UI's + instantiate() function. + @param port_index The index of the port, as returned by port_index(). + @param port_protocol The numeric ID of the PortProtocol, as + returned by port_protocol_id(). + */ + void (*unsubscribe_from_port)(LV2_PUI_Host_Handle host_handle, + uint32_t port_index, + uint32_t port_protocol, + const LV2_Feature* const* features); + + +} LV2_PUI_Host_Descriptor; + +/** + This struct contains the implementation of an UI. A pointer to an + object of this type is returned by the lv2ui_descriptor() function. +*/ +typedef struct _LV2_PUI_Descriptor { + + /** + The URI for this UI (not for the plugin it controls). + */ + char const* URI; + + /** + Create a new UI object and return a handle to it. This function works + similarly to the instantiate() member in LV2_Descriptor. + + @param descriptor The descriptor for the UI to instantiate. + + @param plugin_uri The URI of the plugin that this UI will control. + + @param bundle_path The path to the bundle containing the RDF data that + references this shared object file, with trailing separator (e.g. '/'). + + @param host_descriptor A pointer to an object that contains function + pointers that the UI instance should use to control the plugin + instance. This pointer MUST be valid until cleanup() is called for this + UI instance. + + @param host_handle A handle that the host may use to reference internal + data. It MUST be passed as the first parameter to the function + pointers in @c host_descriptor, and MUST NOT be interpreted in any other + way by the UI. + + @param features A NULL-terminated array of LV2_Feature pointers. The + host must pass all feature URIs that it and the UI supports and any + additional data, just like in the LV2 plugin instantiate() + function. Note that UI features and plugin features are NOT necessarily + the same; @c features will probably not be the same array as the one the + plugin host passes to a plugin. + */ + LV2_PUI_Handle (*instantiate)( + struct _LV2_PUI_Descriptor const* descriptor, + char const* plugin_uri, + char const* bundle_path, + LV2_PUI_Host_Descriptor const* host_descriptor, + LV2_PUI_Host_Handle host_handle, + LV2_Feature const* const* features); + + /** + Return the widget pointer for the UI object. + This MUST return the same value during the entire lifetime of the UI + object. + */ + LV2_PUI_Widget (*get_widget)(LV2_PUI_Handle ui); + + /** + Destroy the UI object and the associated widget. + The host must not try to access the widget after calling this function. + */ + void (*cleanup)(LV2_PUI_Handle ui); + + /** + Notify the UI that something has happened to a subscribed port. + + This is called by the host when something happens at a plugin port that + has been subscribed to using + LV2_PUI_Host_Descriptor::add_port_subscription(). + + The @c buffer is only valid during the time of this function call, so if + the UI wants to keep it for later use it has to copy the contents to an + internal buffer. + + @param ui A handle for the UI object. + @param port_index The index of the port that has changed, as returned by + LV2_PUI_Host_Descriptor::port_index(). + @param buffer_size The size of the data buffer in bytes. + @param port_protocol The format of the data buffer, as returned by + LV2_PUI_Host_Descriptor::port_protocol_id(). + @param buffer A pointer to the data buffer. + */ + void (*port_event)(LV2_PUI_Handle ui, + uint32_t port_index, + uint32_t buffer_size, + uint32_t port_protocol, + void const* buffer); + + /** + Return a data structure associated with an extension URI. + + This facility can be used by extensions to extend the LV2_PUI_Descriptor + API. This function adheres to the same rules as + LV2_Descriptor::extension_data, except it applies to UIs rather than + plugins. + */ + void const* (*extension_data)(char const* uri); + +} LV2_PUI_Descriptor; + +typedef void* LV2_PUI_Lib_Data; + +/** + Descriptor for a plugin UI library. + + Each plugin UI shared library has exactly one of these objects, accessed + via the lv2_pui_lib_descriptor() function in that library. +*/ +typedef struct { + /** + Opaque library data which must be passed as the first parameter to + all the methods of this struct. + */ + LV2_PUI_Lib_Data lib_data; + + void (*cleanup)(LV2_PUI_Lib_Data lib_data); + + /** + Prototype for UI accessor function. + + This function follows the same rules as lv2_descriptor(), except it + applies to UIs rather than plugins. + */ + LV2_PUI_Descriptor const* (*pui_descriptor)(LV2_PUI_Lib_Data lib_data, + uint32_t index); + +} LV2_PUI_Lib_Descriptor; + +/** + Prototype for UI library accessor function. + + This is the entry point for a plugin UI library. Hosts load this symbol + from the library and call this function to obtain a library descriptor which + can be used to access all the UIs contained in this library. The returned + object must not be destroyed (with LV2_PUI_Lib_Descriptor::cleanup()) until + all UIs loaded from that library have been destroyed. +*/ +LV2_PUI_Lib_Descriptor const* lv2_pui_lib_descriptor( + const char* bundle_path, + LV2_Feature const* const* features); + +/** + Type of the lv2_pui_lib_descriptor() function in a UI library. +*/ +typedef LV2_PUI_Lib_Descriptor const* (*LV2_PUI_Lib_Descriptor_Func)( + const char* bundle_path, + LV2_Feature const* const* features); + +#ifdef __cplusplus +} +#endif + +#endif /* LV2_PUI_H */ diff --git a/ns/ext/pui/pui.ttl b/ns/ext/pui/pui.ttl new file mode 100644 index 0000000..c035e56 --- /dev/null +++ b/ns/ext/pui/pui.ttl @@ -0,0 +1,282 @@ +# LV2 Plugin UI Extension +# Copyright (C) 2010-2011 Lars Luthman +# +# Based on lv2.ttl, which is +# Copyright (C) 2006-2008 Steve Harris, David Robillard +# +# This extension should be considered a replacement for the earlier +# in-process UI extension with the URI . +# Hosts and plugins that used that extension should use this one instead. +# The earlier in-process UI extension is not compatible with LV2 revision 3 +# and later and may break in subtle ways. +# +# 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 doap: . +@prefix foaf: . +@prefix lv2: . +@prefix pui: . +@prefix rdf: . +@prefix rdfs: . + + + a lv2:Specification ; + doap:license ; + doap:name "LV2 UI" ; + doap:shortdesc "Generic UI interface for LV2 plugins." ; + doap:release [ + doap:revision "0.1" ; + doap:created "2011-03-26" + ] ; + doap:maintainer [ + a foaf:Person ; + foaf:name "Lars Luthman" ; + foaf:mbox + ] ; + lv2:documentation """ +

This extension defines an interface that can be used to create UIs for +plugins. The UIs are code that reside in shared object files in an LV2 +bundle and are referenced in the RDF data using the triples:

+
+@prefix pui:     <http://lv2plug.in/ns/ext/pui#> .
+<http://example.org/my-ui>  a             pui:Gtk2UI ;
+                            lv2:appliesTo <http://example.org/my-plugin> ;
+                            pui:binary     <my-ui.so> .
+
+

... where http://example.org/my-plugin is the URI of the plugin, +http://example.org/my-ui is the URI of the plugin UI and +my-ui.so is the relative URI to the shared object file. While it +is possible to have the plugin UI and the plugin in the same shared object file +it is probably a good idea to keep them separate so that hosts that don't want +UIs don't have to load the UI code.

+ +

A UI MUST specify its class in the RDF data and the class MUST be a proper +subclass of pui:UI, in this case pui:Gtk2UI. The class defines what type the +UI is, e.g. what graphics toolkit it uses. There are no UI classes defined in +this extension, those are specified separately (and anyone can define their +own).

+ +

It's entirely possible to have multiple UIs for the same plugin, or to have +the UI for a plugin in a different bundle from the actual plugin - this way +people other than the plugin author can write plugin UIs independently without +editing the original plugin bundle. It is also possible to have one UI that +works with several different plugins.

+ +

UIs should also be written in such a way that the host may load several +instances of an UI, or different UIs, and use them with the same plugin +instance.

+ +

Note that the process that loads the shared object file containing the UI +code and the process that loads the shared object file containing the actual +plugin implementation do not have to be the same. There are many valid reasons +for having the plugin and the UI in different processes, or even on different +machines. This means that you can not use singletons and +global variables and expect them to refer to the same objects in the UI and the +actual plugin. The function callback interface defined in the header pui.h is +all you can expect to work.

+""" . + +pui:UI + a rdfs:Class ; + rdfs:subClassOf lv2:Feature ; + rdfs:label "UI" ; + lv2:documentation """ +

The class which represents an LV2 plugin UI. +

+ +

To be used by a host a UI MUST have at least the following properties:

+
    +
  • rdf:type (with object a proper subclass of pui:UI)
  • +
  • doap:name (one without language tag)
  • +
  • lv2:binary (with a shared object file as object)
  • +
  • lv2:appliesTo (with a LV2 plugin as object)
  • +
+ +

The rdf:type of an UI is used by the host to decide whether it supports the +UI and how to handle the LV2_PUI_Widget object that is returned by the UIs +get_widget() function. For example, a type of pui:Gtk2UI might tell the +host that LV2_PUI_Widget is a pointer to an object of a type defined in the +Gtk+ library. No UI types are defined in this extension, that is intentionally +left for other extensions.

+ +

The doap:name property should be at most a few words in length using title +capitalization, e.g. "Flashy Mixer GUI". Use lv2:documentation for more +detailed descriptions.

+ +

UIs may have optional or required features, specified using lv2:optionalFeature +or lv2:requiredFeature. The same rules apply here as for plugins; a host MUST +pass the LV2_Feature objects for all features it supports to the UI's +instantiate() function, a host SHOULD NOT try to instantiate an UI if it +doesn't support all of its required features, and an UI MUST fail to +instantiate if the host doesn't pass all required features to instantiate(). +

+ +

For details about the C API used to load UIs, see the file pui.h. +

+""" . + +pui:PortProtocol + a rdfs:Class ; + rdfs:subClassOf lv2:Feature ; + rdfs:label "Port protocol" ; + lv2:documentation """ +

A PortProtocol defines a certain way of communicating port data between UI +and plugin. PortProtocols can be specified in additional extensions, and +those extensions MUST specify: +

+ +
    +
  1. Which plugin port types the buffer type is valid for
  2. +
  3. When the host should call port_event() in LV2_PUI_Descriptor
  4. +
  5. The format of the data in the buffer passed to port_event()
  6. +
  7. The format of the data in the buffer passed to write_port()
  8. +
  9. What happens when the UI calls write_port() in LV2_PUI_Host_Descriptor
  10. +
  11. What data (if any) should be passed in the LV2_Feature data pointer.
  12. +
+ +

For an example, see pui:floatControl or pui:floatPeakRMS. +

+ +

PortProtocol is a subclass of lv2:Feature, so UIs use lv2:optionalFeature and +lv2:requiredFeature to specify which PortProtocols they want to use. +

+""" . + +pui:floatControl + a pui:PortProtocol ; + rdfs:label "Floating point value" ; + lv2:documentation """ +

The rules (see pui:PortProtocol) for this port protocol are:

+
    +
  1. This PortProtocol is valid for ports with the type lv2:ControlPort.
  2. +
  3. The host SHOULD call port_event() as soon as possible when the port value + has changed, but the plugin MUST NOT depend on a call for every change or + the timing of the calls. However, the host MUST do the calls in the same + order that the value changes occur in.
  4. +
  5. The format of the data in the buffer passed to port_event() is a single + float, and the buffer size is sizeof(float).
  6. +
  7. Same as 3.
  8. +
  9. The host SHOULD change the port value as soon as possible when write_port() + is called, but the UI MUST NOT depend on a change for every call or the + timing of the changes. However, the host MUST do the changes in the same + order that the function calls occur in.
  10. +
  11. The data pointer in the LV2_Feature object for this feature should be + NULL.
  12. +
+""" . + +pui:floatPeakRMS + a pui:PortProtocol ; + rdfs:label "Peak and RMS for a period of audio data" ; + lv2:documentation """ +

This port protocol defines a way for the host to send continuous peak +and RMS measurements of the audio signal at a certain port to the UI. The +intended use is visualisation, e.g. an animated meter widget that shows +the level of the audio input or output.

+ +

A contiguous sequence of audio samples for which a single peak value +and a single RMS value have been computed is called a measurement +period.

+ +

The rules (see pui:PortProtocol) for this port protocol are:

+
    +
  1. This PortProtocol is valid for ports with the type lv2:AudioPort.
  2. +
  3. The host SHOULD call port_event() at regular intervals. The measurement + periods used for calls to port_event() for the same port SHOULD be + contiguous (i.e. the measurement period for one call should begin right + after the end of the measurement period for the previous call ends) unless + the UI has removed and re-added the port subscription between those calls. + However, UIs MUST NOT depend on either the regularity of the calls or the + contiguity of the measurement periods; hosts may change the call rate + or skip calls for performance or other reasons. Measurement periods for + different calls to port_event() for the same port MUST NOT overlap.
  4. +
  5. The format of the data in the buffer passed to port_event() is a single + LV2_PUI_Peak_RMS_Data object, and the buffer size is + sizeof(LV2_PUI_Peak_RMS_Data).
  6. +
  7. The UI MUST NOT call write_port() with the ID for this port protocol as + the port_protocol parameter.
  8. +
  9. The host MUST ignore any write_port() calls with the ID for this port + protocol as the port_protocol parameter.
  10. +
  11. The data pointer in the LV2_Feature object for this feature should be + NULL.
  12. +
+""" . + +pui:events + a pui:PortProtocol ; + rdfs:label "Event buffer" ; + lv2:documentation """ +
    +
  1. This PortProtocol is valid for ports with the type ev:EventPort.
  2. +
  3. The host MUST call port_event() whenever there is an event in an input port + prior to the plugin instance's run() function is called, and whenever there + is an event in an output port after run() has been called. The UI MUST NOT + depend on the timing of the calls. However, the host MUST do the calls in + the same order that the events occur in. The host is allowed and encouraged + to bundle multiple events into a single port_event() call if it improves + performance.
  4. +
  5. The data buffer passed to port_event() is an LV2_Event_Buffer, as specified + in the Event extension. The stamp_type MUST be ignored. The frames and + subframes fields of every event in the buffer MUST be ignored. Events with + type 0 (reference counted events) MUST be ignored.
  6. +
  7. The data buffer passed to write_event() is an LV2_Event_Buffer, as + specified in the Event extension. The stamp_type MUST be ignored. The + frames and subframes fields of every event in the buffer MUST be + ignored. The host MUST NOT pass events with type 0 (references) unless the + UI supports the feature "http://lv2plug.in/ns/ext/event".
  8. +
  9. The host MUST pass all the events in the buffer to the plugin instance's + event port in the same order, but the plugin and the UI MUST NOT depend on + the timing of the events, or on whether they are all sent to the plugin in + the same run() call or distributed over multiple calls.
  10. +
  11. The data pointer in the LV2_Feature object for this feature should be + NULL.
  12. +
+""" . + +pui:Gtk2UI + a rdfs:Class ; + rdfs:subClassOf pui:UI ; + rdfs:label "Gtk+ UI" ; + lv2:documentation """ +

The class which represents a Gtk+ UI. For a successfully created instance of +an UI of this class, the get_widget() function MUST return a pointer to a valid +GtkWidget object compatible with Gtk+ version 2.0. The host MUST ensure that +the Gtk+ library has been initialised and that the Glib main loop is running +before an UI of this type is instantiated.

+ +

Unless otherwise specified by extensions, all function pointers in +LV2_PUI_Descriptor may only be called from the thread that runs the Glib main +loop.

+""" . + +pui:noHostResize + a lv2:Feature ; + rdfs:label "No host resize" ; + lv2:documentation """ +

This Feature should only be used with UIs.

+ +

When this Feature is active the host SHOULD NOT resize the UI widget to any +other size than its natural size, which the host should be able to determine +via the API of whatever toolkit the UI is implemented in. However, the UI MUST +NOT break if the widget is resized to another size. This Feature can be used +for example when the widget uses a fixed-size pixmap interface.

+ +

The data pointer in the LV2_Feature object for this Feature should be set to +NULL.

+""" . diff --git a/ns/ext/pui/waf b/ns/ext/pui/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/pui/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/pui/wscript b/ns/ext/pui/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/pui/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/reference/ext.pc.in b/ns/ext/reference/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/reference/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/reference/manifest.ttl b/ns/ext/reference/manifest.ttl new file mode 100644 index 0000000..e25c54d --- /dev/null +++ b/ns/ext/reference/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/reference/reference.h b/ns/ext/reference/reference.h new file mode 100644 index 0000000..26ef4c3 --- /dev/null +++ b/ns/ext/reference/reference.h @@ -0,0 +1,161 @@ +/* + Copyright 2008-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file reference.h C header for the LV2 Reference extension + . +*/ + +#ifndef LV2_REFERENCE_H +#define LV2_REFERENCE_H + +#define LV2_REFERENCE_URI "http://lv2plug.in/ns/ext/reference" +#define LV2_REFERENCE_BLOB_SUPPORT_URI LV2_REFERENCE_URI "#blobSupport" + +#include +#include + +#include "lv2/lv2plug.in/ns/ext/atom/atom.h" + +/** + Dynamically Allocated Data. + + This is an opaque piece of data of any type, dynamically allocated in memory. + Unlike an "atom", a "blob" is not necessarily POD. Non-POD data is referred + to by a "reference (a special case of atom with type 0). + + This is a pointer to host data which is opaque to the plugin. Plugins MUST + NOT interpret this data in any way, except via host-provided functions in + LV2_Blob_Support. +*/ +typedef void* LV2_Blob; + +typedef LV2_Atom LV2_Reference; + +typedef void* LV2_Blob_Support_Data; + +typedef void (*LV2_Blob_Destroy)(LV2_Blob* blob); + +/** + The data field of the LV2_Feature for reference:blobSupport. + + A host which supports blobs must pass an LV2_Feature to the plugin's + instantiate method with 'URI' = "http://lv2plug.in/ns/ext/reference#blobSupport" + and 'data' pointing to an instance of this struct. All fields of this struct + MUST be set to non-NULL values by the host, except possibly 'data'. +*/ +typedef struct { + + /** + Pointer to opaque host data. + + The plugin MUST pass this to any call to functions in this struct. + Otherwise, the plugin MUST NOT interpret this value in any way. + */ + LV2_Blob_Support_Data data; + + /** + The size of a reference, in bytes. + + This value is provided by the host so plugins can allocate large enough + chunks of memory to store references. Note a reference is an LV2_Reference + with type reference:Reference, hence ref_size is a uint16, like + LV2_Reference.size. + */ + uint16_t ref_size; + + /** + Return the Blob referred to by @a ref. + + The returned value MUST NOT be used in any way other than by calling + methods defined in LV2_Blob_Support (e.g. it MUST NOT be directly + accessed, copied, or destroyed). The actual payload of the blob can + be accessed with LV2_Blob_Support.blob_get. + */ + LV2_Blob (*ref_get)(LV2_Blob_Support_Data data, + LV2_Reference* ref); + + /** + Copy a reference. + This copies a reference but not the blob it refers to, + i.e. after this call @a dst and @a src refer to the same LV2_Blob. + */ + void (*ref_copy)(LV2_Blob_Support_Data data, + LV2_Reference* dst, + LV2_Reference* src); + + /** + Reset (release) a reference. + After this call, @a ref is invalid. Implementations must be sure to + call this function when necessary, or memory leaks will result. The + specific times this is necessary MUST be defined by any extensions that + define a mechanism for transporting references. The standard semantics are: +
  • Whenever passed a Reference (e.g. via a Port) and run, the + plugin owns that reference.
  • +
  • The plugin owns any reference it creates (e.g. by using blob_new or + ref_copy).
  • +
  • For any reference it owns, the plugin MUST either: +
    • Copy the reference and store it (to be used in future runs and + released later).
    • +
    • Copy the reference to an output port exactly once.
    • +
    • Release it with ref_reset.
  • +
+ */ + void (*ref_reset)(LV2_Blob_Support_Data data, + LV2_Reference* ref); + + /** + Initialize a reference to point to a newly allocated Blob. + + @param data Must be the data member of this struct. + @param ref Pointer to an area of memory at least as large as + the ref_size field of this struct. On return, this will + be the unique reference to the new blob, which is owned by the + caller. Assumed to be uninitialised, i.e. the caller MUST NOT + pass a valid reference since this could cause a memory leak. + @param destroy Function to destroy this blob. This function + MUST clean up any resources contained in the blob, but MUST NOT + attempt to free the memory pointed to by its LV2_Blob* parameter + (since this is allocated by the host). + @param type ID of type of blob to allocate. + @param size Size of blob to allocate in bytes. + */ + void (*blob_new)(LV2_Blob_Support_Data data, + LV2_Reference* ref, + LV2_Blob_Destroy destroy, + uint32_t type, + size_t size); + + /** + Get blob's type as an ID. + + The return value may be any type URI, mapped to an integer with the + URI Map extension with context = NULL. + */ + uint32_t (*blob_type)(LV2_Blob blob); + + /** + Get blob's body. + + Returns a pointer to the start of the blob data. The format of this + data is defined by the return value of the type method. It MUST NOT + be used in any way by code which does not understand that type. + */ + void* (*blob_data)(LV2_Blob blob); + +} LV2_Blob_Support; + +#endif /* LV2_REFERENCE_H */ diff --git a/ns/ext/reference/reference.ttl b/ns/ext/reference/reference.ttl new file mode 100644 index 0000000..1e030ee --- /dev/null +++ b/ns/ext/reference/reference.ttl @@ -0,0 +1,82 @@ +# LV2 Reference Extension +# Copyright 2007-2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix atom: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix reference: . + + + a lv2:Specification ; + doap:name "LV2 Reference" ; + doap:shortdesc "A reference data type for using non-POD data." ; + doap:release [ + doap:revision "0.1" ; + doap:created "2011-07-22" + ] ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + lv2:documentation """ +

This extension defines a mechanism for working with generic/opaque +dynamically allocated memory, called a "Blob", which is +(unlike an Atom) not necessarily POD. Blobs are accessed via a +reference:Reference, which is a special case of Atom that always has type = +0, is not POD, and can only be copied using host provided functions. +This allows plugins and hosts to work with data of any type at all.

+""" . + +reference:Reference a rdfs:Class ; + rdfs:subClassOf atom:Atom ; + rdfs:label "Reference" ; + lv2:documentation """ +

Reference to an lv2:Blob. The actual contents of a Reference are opaque and +host specific, and must not be copied, serialized, or otherwise interpreted by +a plugin, except via functions provided by the host in LV2_Blob_Support.

+ +

A Reference is a special case of Atom with type = 0. +"Null" is the unique Atom with type = 0 and +size = 0.

+""" . + +reference:blobSupport a lv2:Feature ; + rdfs:label "Blob support" ; + lv2:documentation """ +

Support for dynamically allocated blobs. If a host supports this feature, +it MUST pass a LV2_Feature with URI +http://lv2plug.in/ns/ext/atom#blobSupport and data pointing to a +LV2_Blob_Support.

+""" . + +reference:Blob a rdfs:Class ; + rdfs:label "Blob" ; + lv2:documentation """ +

Base class for all dynamically allocated blobs. An LV2_Blob is an opaque +pointer to host data. The type and data of a blob can be accessed via +host-provided functions in LV2_Blob_Support. The type of a blob can be any URI +that describes a data format. Blobs are always allocated by the host, and +unlike atoms are not necessarily POD.

+ +

Blob data MUST NOT be used in any way by an implementation that does not +understand that blob type (unlike Atoms, meaningful type-oblivious use +of a Blob is impossible).

+""" . diff --git a/ns/ext/reference/waf b/ns/ext/reference/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/reference/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/reference/wscript b/ns/ext/reference/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/reference/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/resize-port/ext.pc.in b/ns/ext/resize-port/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/resize-port/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/resize-port/manifest.ttl b/ns/ext/resize-port/manifest.ttl new file mode 100644 index 0000000..37d1b42 --- /dev/null +++ b/ns/ext/resize-port/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/resize-port/resize-port.h b/ns/ext/resize-port/resize-port.h new file mode 100644 index 0000000..7f014a3 --- /dev/null +++ b/ns/ext/resize-port/resize-port.h @@ -0,0 +1,57 @@ +/* LV2 Resize Port Extension + * Copyright (C) 2007-2009 David Robillard + * + * This header is free software; you can redistribute it and/or modify it + * under the terms of the GNU 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 General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef LV2_RESIZE_PORT_H +#define LV2_RESIZE_PORT_H + +#include +#include +#include + +#define LV2_RESIZE_PORT_URI "http://lv2plug.in/ns/ext/resize-port" + +typedef void* LV2_Resize_Port_Feature_Data; + +typedef struct { + + LV2_Resize_Port_Feature_Data data; + + /** Resize a port buffer to at least @a size bytes. + * + * This function MAY return false, in which case the port buffer was + * not resized and the port is still connected to the same location. + * Plugins MUST gracefully handle this situation. + * + * This function MUST NOT be called from any context other than + * the context associated with the port of the given index. + * + * The host MUST preserve the contents of the port buffer when + * resizing. + * + * Plugins MAY resize a port many times in a single run callback. + * Hosts SHOULD make this an inexpensive as possible (i.e. plugins + * can liberally use this function in a similar way to realloc). + */ + bool (*resize_port)(LV2_Resize_Port_Feature_Data data, + uint32_t index, + size_t size); + +} LV2_Resize_Port_Feature; + +#endif /* LV2_RESIZE_PORT_H */ + diff --git a/ns/ext/resize-port/resize-port.ttl b/ns/ext/resize-port/resize-port.ttl new file mode 100644 index 0000000..baa1f7f --- /dev/null +++ b/ns/ext/resize-port/resize-port.ttl @@ -0,0 +1,80 @@ +# LV2 Contexts Extension +# +# Allows for an LV2 plugin to have several independent contexts, each with its +# own run callback and associated ports. +# +# Copyright (C) 2007 David Robillard +# +# 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 rsz: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + + a lv2:Specification ; + a lv2:Feature ; + doap:name "LV2 Resize Port Extension" ; + doap:shortdesc "Dynamically sized LV2 port buffers." ; + lv2:documentation """ +

An extension that allows LV2 plugins to request a resize of an output port.

+ +

Any host which supports this extension must pass an LV2_Feature to +the plugin's instantiate method with URI http://lv2plug.in/ns/ext/resize-port +and a pointer to a LV2_Resize_Port_Feature structure (see +resize-port.h for details). This structure +provides a resize_port function which plugins may use to resize output +port buffers as necessary.

+ +

This extension also defines several predicates useful for describing the +amount of space required for a particular port buffer.

+""" . + +rsz:asLargeAs a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range lv2:Symbol ; + rdfs:label "as large as" ; + rdfs:comment """ +Indicates that a port requires at least as much buffer space as the port +with the given symbol on the same plugin instance. This may be used for +any ports, but is generally most useful to indicate an output port must +be at least as large as some input port (because it will copy from it). +If a port is asLargeAs several ports, it is asLargeAs the largest such port +(not the sum of those ports' sizes). + +The host guarantees that whenever an ObjectPort's run method is called, +any output O that is obj:asLargeAs an input I is connected to a buffer large +enough to copy I, or NULL if the port is lv2:connectionOptional. +""" . + +rsz:minimumSize a rdf:Property ; + rdfs:domain lv2:Port ; + rdfs:range lv2:Symbol ; + rdfs:label "minimum size" ; + rdfs:comment """ +Indicates that a port requires a buffer at least this large, in bytes. +Any host that supports the resize-port feature MUST connect any port with a +minimumSize specified to a buffer at least as large as the value given for +this property. Any host, especially those that do NOT support dynamic port +resizing, SHOULD do so or reduced functionality may result. +""" . diff --git a/ns/ext/resize-port/waf b/ns/ext/resize-port/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/resize-port/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/resize-port/wscript b/ns/ext/resize-port/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/resize-port/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/state/ext.pc.in b/ns/ext/state/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/state/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/state/manifest.ttl b/ns/ext/state/manifest.ttl new file mode 100644 index 0000000..7894a22 --- /dev/null +++ b/ns/ext/state/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 2 ; + rdfs:seeAlso . + diff --git a/ns/ext/state/state.h b/ns/ext/state/state.h new file mode 100644 index 0000000..4e1c28a --- /dev/null +++ b/ns/ext/state/state.h @@ -0,0 +1,258 @@ +/* + Copyright 2010-2011 David Robillard + Copyright 2010 Leonard Ritter + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file + C API for the LV2 State extension . +*/ + +#ifndef LV2_STATE_H +#define LV2_STATE_H + +#include +#include +#include + +#include "lv2/lv2plug.in/ns/lv2core/lv2.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define LV2_STATE_URI "http://lv2plug.in/ns/ext/state" + +#define LV2_STATE_INTERFACE_URI LV2_STATE_URI "#Interface" + +typedef void* LV2_State_Handle; + +/** + Flags describing value characteristics. + + These flags are used along with the value's type URI to determine how to + (de-)serialise the value data, or whether it is even possible to do so. +*/ +typedef enum { + + /** + Plain Old Data. + + Values with this flag contain no references to non-stateent or + non-global resources (e.g. pointers, handles, local paths, etc.). It is + safe to copy POD values with a simple memcpy and store them for use at + any time in the future on a machine with a compatible architecture + (e.g. the same endianness and alignment). + + Implementations MUST NOT attempt to copy or serialise a non-POD value if + they do not understand its type (and thus know how to correctly do so). + */ + LV2_STATE_IS_POD = 1, + + /** + Portable (architecture independent) data. + + Values with this flag are in a format that is usable on any + architecture, i.e. if the value is saved on one machine it can safely be + restored on another machine regardless of endianness, alignment, etc. + */ + LV2_STATE_IS_PORTABLE = 1 << 1, + + /** + Native data. + + This flag is used by the host to indicate that the saved data is only + going to be used locally in the currently running process (e.g. for + instance duplication or snapshots), so the plugin should use the most + efficient representation possible and not worry about serialisation + and portability. + */ + LV2_STATE_IS_NATIVE = 1 << 2 + +} LV2_State_Flags; + +/** + A host-provided function to store a property. + @param handle Must be the handle passed to LV2_State_Interface.save(). + @param key The key (predicate) to store @c value under (URI mapped integer). + @param value Pointer to the value (object) to be stored. + @param size The size of the data at @c value in bytes. + @param type The type of @c value (URI). + @param flags LV2_State_Flags for @c value. + @return 0 on success, otherwise a non-zero error code. + + The host passes a callback of this type to LV2_State_Interface.save(). This callback + is called repeatedly by the plugin within LV2_State_Interface.save() to store all + the statements that describe its current state. + + The host MAY fail to store a property if the type is not understood and is + not LV2_STATE_IS_POD and/or LV2_STATE_IS_PORTABLE. Implementations are + encouraged to use POD and portable values (e.g. string literals) wherever + possible, and use common types (e.g. types from + http://lv2plug.in/ns/ext/atom) regardless, since hosts are likely to already + contain the necessary implementation. + + Note that @c size MUST be > 0, and @c value MUST point to a valid region of + memory @c size bytes long (this is required to make restore unambiguous). + + The plugin MUST NOT attempt to use this function outside of the + LV2_State_Interface.restore() context. +*/ +typedef int (*LV2_State_Store_Function)(LV2_State_Handle handle, + uint32_t key, + const void* value, + size_t size, + uint32_t type, + uint32_t flags); + +/** + A host-provided function to retrieve a property. + @param handle Must be the handle passed to + LV2_State_Interface.restore(). + @param key The key (predicate) of the property to retrieve (URI). + @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. + @param flags (Output) If non-NULL, set to the LV2_State_Flags for + the returned value. + @return A pointer to the restored value (object), or NULL if no value + has been stored under @c key. + + A callback of this type is passed by the host to + LV2_State_Interface.restore(). This callback is called repeatedly by the + plugin within LV2_State_Interface.restore() to retrieve any properties it + requires to restore its state. + + The returned value MUST remain valid until LV2_State_Interface.restore() + returns. + + The plugin MUST NOT attempt to use this function, or any value returned from + it, outside of the LV2_State_Interface.restore() context. Returned values + MAY be copied for later use if necessary, assuming the plugin knows how to + do so correctly (e.g. the value is POD, or the plugin understands the type). +*/ +typedef const void* (*LV2_State_Retrieve_Function)(LV2_State_Handle handle, + uint32_t key, + size_t* size, + uint32_t* type, + uint32_t* flags); + +/** + State Extension Data. + + When the plugin's extension_data is called with argument LV2_STATE_URI, + the plugin MUST return an LV2_State 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 ports change incompatibly). 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_State_Interface { + + /** + Save plugin state using a host-provided @c store callback. + + @param instance The instance handle of the plugin. + @param store The host-provided store callback. + @param handle An opaque pointer to host data, e.g. the map or + file where the values are to be stored. If @c store is called, this MUST + be passed as its handle parameter. + @param flags Flags describing desires properties of this save. The + plugin SHOULD use these values to determine the most appropriate and/or + efficient serialisation, but is not required to do so. + @param features Extensible parameter for passing any additional + features to be used for this save. + + 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 @c handle pointer and @c 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 instant in time. + */ + void (*save)(LV2_Handle instance, + LV2_State_Store_Function store, + LV2_State_Handle handle, + uint32_t flags, + const LV2_Feature *const * features); + + + /** + Restore plugin state using a host-provided @c retrieve callback. + + @param instance The instance handle of the plugin. + @param retrieve The host-provided retrieve callback. + @param handle An opaque pointer to host data, e.g. the map or + file from which the values are to be restored. If @c retrieve is + called, this MUST be passed as its handle parameter. + @param flags Currently unused. + @param features Extensible parameter for passing any additional + features to be used for this restore. + + The plugin MAY assume a restored value was set by a previous call to + LV2_State_Interface.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 @c handle pointer and @c 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_State_Retrieve_Function retrieve, + LV2_State_Handle handle, + uint32_t flags, + const LV2_Feature *const * features); + +} LV2_State_Interface; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_STATE_H */ diff --git a/ns/ext/state/state.ttl b/ns/ext/state/state.ttl new file mode 100644 index 0000000..c79188e --- /dev/null +++ b/ns/ext/state/state.ttl @@ -0,0 +1,231 @@ +# LV2 State Extension +# Copyright 2010-2011 David Robillard +# Copyright 2010 Leonard Ritter +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix state: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . + + + a lv2:Specification ; + doap:name "LV2 State" ; + doap:shortdesc "An interface for LV2 plugins to save and restore state." ; + doap:license ; + doap:release [ + doap:revision "0.2" ; + doap:created "2011-11-14" + ] ; + doap:developer [ + a foaf:Person ; + foaf:name "Leonard Ritter" ; + foaf:homepage ; + ] ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + lv2:documentation """ +

This extension provides a mechanism for plugins to save and restore state +across instances, allowing hosts to save, restore, clone, or take a snapshot of +a plugin instance's state at any point in time. The intention is for a plugin +instance's state to be completely described by port values (as with all +LV2 plugins) and a simple dictionary.

+ +

The state described by this extension is conceptually a single +key/value dictionary, where keys are URIDs and values are type-tagged blobs of +any type. The plugin provides an LV2_State_Interface for working with this +state. To save or restore, the host calls LV2_State_Interface::save() or +LV2_State_Interface::restore(), passing a callback to be used for handling a +single key/value pair. The host is free to implement saving and restoring in +any way; the actual mechanism is completely abstract from the plugin's +perspective.

+ +

Because state is a simple dictionary, hosts and plugins can work with it +easily from many languages and protocols. Keys are URIDs for performance +reasons as well as RDF compatibility, which makes it simple to serialise state +in many formats (e.g. any RDF syntax, JSON, XML, key/value databases such as +BDB, etc.). In particular, state can be elegantly described in a plugin's +Turtle description, which is useful for e.g. presets or default state. +Specific keys may be described in Turtle on the fly or in extensions, +allowing plugins to use common well-defined keys.

+ +

This extension defines a conceptual model of state and a mechanism for +saving and restoring it, but no interface for manipulating it dynamically. +While no such mechanism is defined here, dynamic control of plugins SHOULD be +achieved by generic manipulations of the same conceptual state dictionary used +by this extension (e.g. plugin->set(key, value)). Accordingly, +plugins SHOULD use meaningful and well-defined keys wherever possible.

+ +

In pseudo code, a typical use case in a plugin is:

+
+#define NS_EG   "http://example.org/"
+#define NS_ATOM "http://lv2plug.in/ns/ext/atom#"
+
+LV2_Handle my_instantiate(...)
+{
+    MyPlugin* plugin = ...;
+    plugin->uris.atom_String = map_uri(NS_ATOM "String");
+    plugin->uris.eg_greeting = map_uri(NS_EG "greeting");
+    plugin->state.greeting   = strdup("Hello");
+    return plugin;
+}
+
+void my_save(LV2_Handle                 instance,
+             LV2_State_Store_Function   store,
+             void*                      handle,
+             uint32_t                   flags,
+             const LV2_Feature *const * features)
+
+{
+    MyPlugin*   plugin   = (MyPlugin*)instance;
+    const char* greeting = plugin->state.greeting;
+
+    store(handle,
+          plugin->uris.eg_greeting,
+          greeting,
+          strlen(greeting) + 1,
+          plugin->uris.atom_String,
+          LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
+}
+
+void my_restore(LV2_Handle                  instance,
+                LV2_State_Retrieve_Function retrieve,
+                void*                       handle,
+                uint32_t                    flags,
+                const LV2_Feature *const *   features)
+{
+    MyPlugin* plugin = (MyPlugin*)instance;
+
+    size_t      size;
+    uint32_t    type;
+    uint32_t    flags;
+    const char* greeting = retrieve(handle,
+                                    plugin->uris.eg_greeting,
+                                    &size,
+                                    &type,
+                                    &flags);
+
+    if (greeting) {
+        free(plugin->state->greeting);
+        plugin->state->greeting = strdup(greeting);
+    } else {
+        plugin->state->greeting = strdup("Hello");
+    }
+}
+
+const void* my_extension_data(const char* uri)
+{
+    static const LV2_State_Interface state_iface = { my_save, my_restore };
+    if (!strcmp(uri, LV2_STATE_INTERFACE_URI)) {
+        return &state_iface;
+    }
+}
+
+ +

Similarly, a typical use case in a host is:

+
+int store_callback(void*       handle,
+                   uint32_t    key,
+                   const void* value,
+                   size_t      size,
+                   uint32_t    type,
+                   uint32_t    flags)
+{
+    if ((flags & LV2_STATE_IS_POD)) {
+        /* We only care about POD since we're keeping state in memory only.
+           If this was for disk or network storage/transmission,
+           LV2_STATE_IS_PORTABLE would have to be checked as well.
+        */
+        Map* state_map = (Map*)handle;
+        state_map->insert(key, Value(copy(value), size, type, pod));
+        return 0;
+    } else {
+        return 1; /* Non-POD events are unsupported. */
+    }
+}
+
+Map get_plugin_state(LV2_Handle instance)
+{
+    LV2_State* state = instance.extension_data("http://lv2plug.in/ns/ext/state");
+    Map state_map;
+    /** Request a fast/native/POD save, since we're just copying in memory */
+    state.save(instance, store_callback, &state_map,
+               LV2_STATE_IS_POD|LV2_STATE_IS_NATIVE);
+    return state_map;
+}
+
+""" . + +state:Interface + a rdfs:Class ; + rdfs:subClassOf lv2:ExtensionData ; + lv2:documentation """ +

A structure (LV2_State_Interface) which contains functions to be called by +the host to save and restore state. In order to support this extension, the +plugin must return a valid LV2_State_Interface from +LV2_Descriptor::extension_data() when it is called with +LV2_STATE_INTERFACE_URI.

+ +

The plugin data file should describe this like so:

+
+@prefix state: <http://lv2plug.in/ns/ext/state#> .
+
+<plugin>
+    a lv2:Plugin ;
+    lv2:extensionData state:Interface .
+
+""" . + +state: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 state:InstanceState as the subject (see state: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 State extension. +""" . + +state:instanceState + a rdf:Property ; + rdfs:range state:InstanceState ; + lv2:documentation """ +

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.:

+
+@prefix eg: <http://example.org/> .
+
+<plugininstance> state:instanceState [
+    eg:somekey "some value" ;
+    eg:someotherkey "some other value" ;
+    eg:favourite-number 2
+] .
+
+

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 State extension.

+""" . diff --git a/ns/ext/state/waf b/ns/ext/state/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/state/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/state/wscript b/ns/ext/state/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/state/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/string-port/ext.pc.in b/ns/ext/string-port/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/string-port/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/string-port/manifest.ttl b/ns/ext/string-port/manifest.ttl new file mode 100644 index 0000000..d0e618e --- /dev/null +++ b/ns/ext/string-port/manifest.ttl @@ -0,0 +1,8 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . diff --git a/ns/ext/string-port/string-port.h b/ns/ext/string-port/string-port.h new file mode 100644 index 0000000..e7fc8c7 --- /dev/null +++ b/ns/ext/string-port/string-port.h @@ -0,0 +1,58 @@ +/* lv2_string_port.h - C header file for LV2 string port extension. + * Draft Revision 3 + * Copyright (C) 2008 Krzysztof Foltman + * + * 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 String Port extension + * . + */ + +#ifndef LV2_STRING_PORT_H +#define LV2_STRING_PORT_H + +#include + +/** URI for the string port transfer mechanism feature */ +#define LV2_STRING_PORT_URI "http://lv2plug.in/ns/ext/string-port#StringTransfer" + +/** Flag: port data has been updated; for input ports, this flag is set by +the host. For output ports, this flag is set by the plugin. */ +#define LV2_STRING_DATA_CHANGED_FLAG 1 + +/** structure for string port data */ +typedef struct +{ + /** Buffer for UTF-8 encoded zero-terminated string value; host-allocated */ + char *data; + + /** Length in bytes (not characters), not including zero byte */ + size_t len; + + /** Output ports: storage space in bytes; must be >= RDF-specified requirements */ + size_t storage; + + /** Flags defined above */ + uint32_t flags; + + /** Undefined (pad to 8 bytes) */ + uint32_t pad; + +} LV2_String_Data; + +#endif + diff --git a/ns/ext/string-port/string-port.ttl b/ns/ext/string-port/string-port.ttl new file mode 100644 index 0000000..f36fa7a --- /dev/null +++ b/ns/ext/string-port/string-port.ttl @@ -0,0 +1,105 @@ +# LV2 String Port Extension. +# Draft Revision 3 +# Copyright (C) 2008 Krzysztof Foltman +# +# 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 sp: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification ; + doap:license ; + doap:name "LV2 String Ports" ; + doap:maintainer [ + a foaf:Person ; + foaf:name "Krzysztof Foltman" ; + ] ; + lv2:documentation """ +

Defines ports which contain string data.

+ +

UI issues

+

When using port_event / write_port (and possible other communication +mechanisms), the format parameter should contain the numeric value of URI +LV2_STRING_PORT_URI (mapped with http://lv2plug.in/ns/extensions/ui specified +as map URI).

+ +

It's probably possible to use ports belonging to message context +<http://lv2plug.in/ns/ext/contexts#MessageContext> for transfer. However, +contexts mechanism does not offer any way to notify the message recipient about +which ports have been changed. To remedy that, this extension defines a flag +LV2_STRING_DATA_CHANGED_FLAG that carries that information inside a port value +structure.

+ +

Storage

+

The value of string port are assumed to be "persistent": if a host saves and +restores a state of a plugin (e.g. control port values), the values of input +string ports should also be assumed to belong to that state. This also applies +to message context: if a session is being restored, the host MUST resend the +last value that was sent to the port before session has been saved. In other +words, string port values "stick" to message ports.

+""" . + +sp:StringTransfer a lv2:Feature ; + rdfs:label "String data transfer via LV2_String_Data" . + +sp:StringPort a lv2:Port ; + rdfs:label "String port" ; + lv2:documentation """ +

Indicates that the port data points to a LV2_String_Data structure +as defined in accompanying header file.

+ +

Input Port Semantics

+

If the port does not have a context specified (it runs in the default, +realtime audio processing context), the values in the structure and the actual +string data MUST remain unchanged for the time a run() function of a plugin +is executed. However, if the port belongs to a different context, the same +data MUST remain unchanged only for the time a run() or message_process() +function of a given context is executed.

+ +

Output Port Semantics

+

The plugin may only change the string or length in a run() function (if +the port belongs to default context) or in context-defined counterparts +(if the port belongs to another context). Because of that, using default +context output string ports is contraindicated for longer strings.

+""" . + +sp:default a rdf:Property ; + rdfs:label "Default value" ; + rdfs:domain sp:StringPort ; + rdfs:range xsd:string ; + rdfs:comment """ +Gives a default value for a string port. +""" . + +sp:requiredSpace a rdf:Property ; + rdfs:label "Required storage space in bytes" ; + rdfs:domain sp:StringPort ; + rdfs:range xsd:nonNegativeInteger ; + rdfs:comment """ +Specifies required buffer space for output string ports and those of +input string ports that are meant to be GUI-controlled. The host MUST +allocate a buffer of at least required size to accommodate for all values +that can be produced by the plugin. +""" . + diff --git a/ns/ext/string-port/waf b/ns/ext/string-port/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/string-port/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/string-port/wscript b/ns/ext/string-port/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/string-port/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/time/ext.pc.in b/ns/ext/time/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/time/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/time/manifest.ttl b/ns/ext/time/manifest.ttl new file mode 100644 index 0000000..2657388 --- /dev/null +++ b/ns/ext/time/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/time/time.h b/ns/ext/time/time.h new file mode 100644 index 0000000..f3b2e77 --- /dev/null +++ b/ns/ext/time/time.h @@ -0,0 +1,131 @@ +/* + Copyright 2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file time.h C header for the LV2 Time extension + . +*/ + +#ifndef LV2_TIME_H +#define LV2_TIME_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + Time states. +*/ +typedef enum { + LV2_TIME_STOPPED = 0, /**< Transport halted */ + LV2_TIME_ROLLING = 1, /**< Transport playing */ +} LV2_Time_State; + +/** + Bits indicating properties of an LV2_Time_Position. +*/ +typedef enum { + LV2_TIME_HAS_BBT = 1 /**< Has Bar, Beat, Tick */ +} LV2_Time_Flags; + +/** + Description of a position and/or tempo. + + This struct is used as the payload of an event to notify the plugin about + time state, such as position and tempo. +*/ +typedef struct { + /** + @{ + @name Mandatory Fields + */ + + /** + Frame number on the timeline. + */ + uint64_t frame; + + /** + Bit field of LV2_Time_Flags values indicating which fields + of this struct are valid. + */ + uint32_t flags; + + /** + Transport state. + */ + LV2_Time_State state; + + /** + @} + @{ + @name LV2_TIME_BBT fields + These fields are valid iff the LV2_TIME_BBT bit is set in @ref flags. + */ + + /** + Current bar. + The first bar is number 0 (but should be represented in a UI as bar 1). + */ + int64_t bar; + + /** + Beat within the current bar. + The first beat is number 0. + Always <= @ref beats_per_bar. + */ + int32_t beat; + + /** + Tick within the current beat. + The first tick is number 0. + Always <= @ref ticks_per_beat. + */ + int32_t tick; + + /** + Number of beats per bar (top of time signature). + */ + int32_t beats_per_bar; + + /** + Type of note that counts as one beat (bottom of time signature). + */ + int32_t beat_type; + + /** + Number of ticks per beat. + Typically this is a large integer with many even divisors. + */ + int32_t ticks_per_beat; + + /** + Current tempo, in beats per minute. + */ + double beats_per_minute; + + /** + @} + */ +} LV2_Time_Position; + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* LV2_TIME_H */ diff --git a/ns/ext/time/time.ttl b/ns/ext/time/time.ttl new file mode 100644 index 0000000..40bfdbb --- /dev/null +++ b/ns/ext/time/time.ttl @@ -0,0 +1,57 @@ +# LV2 Time Extension +# Copyright 2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix time: . +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . + + + a lv2:Specification ; + doap:name "LV2 Time" ; + doap:shortdesc "A data type for transport speed and position." ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + lv2:documentation """ +

This extension defines a structure type, LV2_Time_Position, which +describes a tempo and position along a timeline. This can be used as +an event payload by the host to notify plugins about the current +tempo and position.

+""" . + +time:Position + a rdfs:Class ; + rdfs:label "LV2 time position" ; + lv2:documentation """ +

Type for an LV2_Time_Position struct. This can be mapped to an integer and +used as the type field of an event to indicate that the event payload is an +LV2_Time_Positon struct. Plugins SHOULD indicate that a port supports time +information using the ev:supports predicate, e.g.:

+
+<plugin> lv2:port [
+    a lv2:InputPort , ev:EventPort ;
+    lv2:name "control" ;
+    lv2:index 0 ;
+    ev:supportsEvent time:Position
+] .
+
+""" . diff --git a/ns/ext/time/waf b/ns/ext/time/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/time/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/time/wscript b/ns/ext/time/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/time/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/ui-resize/ext.pc.in b/ns/ext/ui-resize/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/ui-resize/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/ui-resize/manifest.ttl b/ns/ext/ui-resize/manifest.ttl new file mode 100644 index 0000000..ca5cdf9 --- /dev/null +++ b/ns/ext/ui-resize/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . + diff --git a/ns/ext/ui-resize/ui-resize.h b/ns/ext/ui-resize/ui-resize.h new file mode 100644 index 0000000..cf5ccc6 --- /dev/null +++ b/ns/ext/ui-resize/ui-resize.h @@ -0,0 +1,58 @@ +/* + Copyright 2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef LV2_UI_RESIZE_H +#define LV2_UI_RESIZE_H + +#define LV2_UI_RESIZE_URI "http://lv2plug.in/ns/ext/ui-resize" + +typedef void* LV2_UI_Resize_Feature_Data; + +/** + UI Resize Feature. + + This structure may be used in two ways: as a feature passed by the host + (e.g. via the features parameter of LV2UI_Descriptor::instantiate()) or + as a feature exposed by a UI (e.g. via LV2UI_Descriptor::extension_data()). + + In both cases, the URI to be used is + http://lv2plug.in/ns/ext/ui-resize#UIResize +*/ +typedef struct { + + LV2_UI_Resize_Feature_Data data; + + /** + Request or notify a size change. + + When this struct is provided by the host, the UI may call this + function to notify the host that a size change is desired, or notify + the host of the initial size of the UI. + + When this struct is provided by the plugin, the host may call this + function in the UI thread to notify the UI that it should change its + size to the given dimensions. + + @return 0 on success. + */ + int (*ui_resize)(LV2_UI_Resize_Feature_Data data, + int width, + int height); + +} LV2_UI_Resize_Feature; + +#endif /* LV2_UI_RESIZE_H */ + diff --git a/ns/ext/ui-resize/ui-resize.ttl b/ns/ext/ui-resize/ui-resize.ttl new file mode 100644 index 0000000..5e2a5a8 --- /dev/null +++ b/ns/ext/ui-resize/ui-resize.ttl @@ -0,0 +1,43 @@ +# LV2 UI Resize Extension +# Copyright 2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix uirsz: . +@prefix lv2: . +@prefix rdf: . +@prefix rdfs: . +@prefix xsd: . +@prefix doap: . +@prefix foaf: . + + + a lv2:Specification ; + doap:name "LV2 UI Resize Extension" ; + doap:shortdesc "A feature for self-resizing plugin UIs." ; + doap:license ; + lv2:documentation """ +

An extension that allows LV2 plugin UIs to notify the host about size +changes, or for the host to notify plugin UIs about size changes.

+""" . + +uirsz:UIResize + a lv2:Feature ; + lv2:documentation """ +

A feature that allows the UI to notify the host about its current size, or +request a size change. This feature corresponds to the LV2_UI_Resize_Feature +struct, which should be passed with the feature URI +http://lv2plug.in/ns/ext/ui-resize#UIResize. This struct may also +be provided by the UI as extension data using the same URI, in which case it +is used by the host to request that the UI change its size.

+""" . diff --git a/ns/ext/ui-resize/waf b/ns/ext/ui-resize/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/ui-resize/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/ui-resize/wscript b/ns/ext/ui-resize/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/ui-resize/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/uri-map/ext.pc.in b/ns/ext/uri-map/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/uri-map/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/uri-map/manifest.ttl b/ns/ext/uri-map/manifest.ttl new file mode 100644 index 0000000..eb78686 --- /dev/null +++ b/ns/ext/uri-map/manifest.ttl @@ -0,0 +1,8 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 1 ; + lv2:microVersion 2 ; + rdfs:seeAlso . diff --git a/ns/ext/uri-map/uri-map.h b/ns/ext/uri-map/uri-map.h new file mode 100644 index 0000000..6767cd1 --- /dev/null +++ b/ns/ext/uri-map/uri-map.h @@ -0,0 +1,92 @@ +/* + Copyright 2008-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file + C header for the LV2 URI Map extension . + + This extension defines a simple mechanism for plugins to map URIs to + integers, usually for performance reasons (e.g. processing events typed by + URIs in real time). The expected use case is for plugins to map URIs to + integers for things they 'understand' at instantiation time, and store those + values for use in the audio thread without doing any string comparison. + This allows the extensibility of RDF with the performance of integers (or + centrally defined enumerations). +*/ + +#ifndef LV2_URI_MAP_H +#define LV2_URI_MAP_H + +#define LV2_URI_MAP_URI "http://lv2plug.in/ns/ext/uri-map" + +#include + +/** + Opaque pointer to host data. +*/ +typedef void* LV2_URI_Map_Callback_Data; + +/** + URI Map Feature. + + To support this feature the host must pass an LV2_Feature struct to the + plugin's instantiate method with URI "http://lv2plug.in/ns/ext/uri-map" + and data pointed to an instance of this struct. +*/ +typedef struct { + + /** + Opaque pointer to host data. + + The plugin MUST pass this to any call to functions in this struct. + Otherwise, it must not be interpreted in any way. + */ + LV2_URI_Map_Callback_Data callback_data; + + /** + Get the numeric ID of a URI from the host. + + @param callback_data Must be the callback_data member of this struct. + @param map The 'context' of this URI. Certain extensions may define a + URI that must be passed here with certain restrictions on the return + value (e.g. limited range). This value may be NULL if the plugin needs + an ID for a URI in general. Extensions SHOULD NOT define a context + unless there is a specific need to do so, e.g. to restrict the range of + the returned value. + @param uri The URI to be mapped to an integer ID. + + This function is referentially transparent; any number of calls with the + same arguments is guaranteed to return the same value over the life of a + plugin instance (though the same URI may return different values with a + different map parameter). However, this function is not necessarily very + fast: plugins SHOULD cache any IDs they might need in performance + critical situations. + + The return value 0 is reserved and indicates that an ID for that URI + could not be created for whatever reason. Extensions MAY define more + precisely what this means in a certain context, but in general plugins + SHOULD handle this situation as gracefully as possible. However, hosts + SHOULD NOT return 0 from this function in non-exceptional circumstances + (e.g. the URI map SHOULD be dynamic). Hosts that statically support only + a fixed set of URIs should not expect plugins to function correctly. + */ + uint32_t (*uri_to_id)(LV2_URI_Map_Callback_Data callback_data, + const char* map, + const char* uri); + +} LV2_URI_Map_Feature; + +#endif /* LV2_URI_MAP_H */ diff --git a/ns/ext/uri-map/uri-map.ttl b/ns/ext/uri-map/uri-map.ttl new file mode 100644 index 0000000..b0a5399 --- /dev/null +++ b/ns/ext/uri-map/uri-map.ttl @@ -0,0 +1,57 @@ +# LV2 URI Map Extension +# Copyright 2008-2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix lv2ev: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix umap: . + + + a lv2:Specification , + lv2:Feature ; + owl:deprecated true ; + doap:license ; + doap:name "LV2 URI Map" ; + doap:shortdesc "A feature for mapping URIs to integers." ; + doap:release [ + doap:revision "1.2" ; + doap:created "2011-05-26" + ] ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] , [ + a foaf:Person ; + foaf:name "Lars Luthman" + ] ; + lv2:documentation """ +

This extension is deprecated. New +implementations should use LV2 URID +instead.

+ +

This extension defines a simple mechanism for plugins to map URIs to +integers, usually for performance reasons (e.g. processing events typed by URIs +in real time). The expected use case is for plugins to map URIs to integers +for things they 'understand' at instantiation time, and store those values for +use in the audio thread without doing any string comparison. This allows the +extensibility of RDF with the performance of integers (or centrally defined +enumerations).

+""" . diff --git a/ns/ext/uri-map/waf b/ns/ext/uri-map/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/uri-map/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/uri-map/wscript b/ns/ext/uri-map/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/uri-map/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/uri-unmap/ext.pc.in b/ns/ext/uri-unmap/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/uri-unmap/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/uri-unmap/manifest.ttl b/ns/ext/uri-unmap/manifest.ttl new file mode 100644 index 0000000..217e7b6 --- /dev/null +++ b/ns/ext/uri-unmap/manifest.ttl @@ -0,0 +1,8 @@ +@prefix lv2: . +@prefix rdfs: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 1 ; + rdfs:seeAlso . diff --git a/ns/ext/uri-unmap/uri-unmap.h b/ns/ext/uri-unmap/uri-unmap.h new file mode 100644 index 0000000..d6cb900 --- /dev/null +++ b/ns/ext/uri-unmap/uri-unmap.h @@ -0,0 +1,81 @@ +/* lv2_uri_unmap.h - C header file for the LV2 URI Unmap extension. + * + * Copyright (C) 2010 David Robillard + * + * 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 URI Map extension . + */ + +#ifndef LV2_URI_UNMAP_H +#define LV2_URI_UNMAP_H + +#define LV2_URI_UNMAP_URI "http://lv2plug.in/ns/ext/uri-unmap" + +#include + + +/** Opaque pointer to host data. */ +typedef void* LV2_URI_Unmap_Callback_Data; + + +/** The data field of the LV2_Feature for the URI Unmap extension. + * + * To support this extension the host must pass an LV2_Feature struct to the + * plugin's instantiate method with URI "http://lv2plug.in/ns/ext/uri-unmap" + * and data pointed to an instance of this struct. + */ +typedef struct { + + /** Opaque pointer to host data. + * + * The plugin MUST pass this to any call to functions in this struct. + * Otherwise, it must not be interpreted in any way. + */ + LV2_URI_Unmap_Callback_Data callback_data; + + /** Get the numeric ID of a URI from the host. + * + * @param callback_data Must be the callback_data member of this struct. + * @param map The 'context' used to map this URI. + * @param id The URI ID to unmap. + * @return The string form of @a id, or NULL on error. + * + * The @a id MUST be a value previously returned from + * LV2_Uri_Map_Feature.uri_to_id. + * + * The returned string is owned by the host and MUST NOT be freed by + * the plugin or stored for a long period of time (e.g. across run + * invocations) without copying. + * + * This function is referentially transparent - any number of calls with + * the same arguments is guaranteed to return the same value over the life + * of a plugin instance (though the same ID may return different values + * with a different map parameter). + * + * This function may be called from any non-realtime thread, possibly + * concurrently (hosts may simply use a mutex to meet these requirements). + */ + const char* (*id_to_uri)(LV2_URI_Unmap_Callback_Data callback_data, + const char* map, + uint32_t id); + +} LV2_URI_Unmap_Feature; + + +#endif /* LV2_URI_UNMAP_H */ + diff --git a/ns/ext/uri-unmap/uri-unmap.ttl b/ns/ext/uri-unmap/uri-unmap.ttl new file mode 100644 index 0000000..053bb37 --- /dev/null +++ b/ns/ext/uri-unmap/uri-unmap.ttl @@ -0,0 +1,46 @@ +# LV2 URI Unmap Extension +# Copyright (C) 2010 David Robillard +# +# 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 unmap: . +@prefix lv2: . +@prefix lv2ev: . +@prefix rdf: . +@prefix rdfs: . +@prefix doap: . +@prefix foaf: . + + a lv2:Specification , lv2:Feature ; + doap:license ; + doap:name "LV2 URI Unmap" ; + doap:shortdesc "A feature for unmapping URIs from integers." ; + doap:maintainer [ + a foaf:Person ; + foaf:name "David Robillard" ; + foaf:homepage ; + rdfs:seeAlso + ] ; + lv2:documentation """ +

This extension is the opposite of the LV2 URI Map extension. It allows +the host to pass an id_to_uri function to the plugin which can be used for +unmapping an integer (previously mapped using the URI map extension's +uri_to_id) back to a string.

""" . + diff --git a/ns/ext/uri-unmap/waf b/ns/ext/uri-unmap/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/uri-unmap/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/uri-unmap/wscript b/ns/ext/uri-unmap/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/uri-unmap/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file diff --git a/ns/ext/urid/ext.pc.in b/ns/ext/urid/ext.pc.in new file mode 120000 index 0000000..1cdad2a --- /dev/null +++ b/ns/ext/urid/ext.pc.in @@ -0,0 +1 @@ +../../../ext.pc.in \ No newline at end of file diff --git a/ns/ext/urid/manifest.ttl b/ns/ext/urid/manifest.ttl new file mode 100644 index 0000000..c77aff6 --- /dev/null +++ b/ns/ext/urid/manifest.ttl @@ -0,0 +1,9 @@ +@prefix lv2: . +@prefix rdfs: . +@prefix urid: . + + + a lv2:Specification ; + lv2:minorVersion 0 ; + lv2:microVersion 2 ; + rdfs:seeAlso . diff --git a/ns/ext/urid/urid.h b/ns/ext/urid/urid.h new file mode 100644 index 0000000..d36d0dd --- /dev/null +++ b/ns/ext/urid/urid.h @@ -0,0 +1,113 @@ +/* + Copyright 2011 Gabriel M. Beddingfield + Copyright 2008-2011 David Robillard + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +/** + @file + C header for the LV2 URID extension +*/ + +#ifndef LV2_URID_H +#define LV2_URID_H + +#define LV2_URID_URI "http://lv2plug.in/ns/ext/urid" + +#include + +/** + Opaque pointer to host data for LV2_URID_Map. +*/ +typedef void* LV2_URID_Map_Handle; + +/** + Opaque pointer to host data for LV2_URID_Unmap. +*/ +typedef void* LV2_URID_Unmap_Handle; + +/** + URI mapped to an integer. +*/ +typedef uint32_t LV2_URID; + +/** + URI Map (http://lv2plug.in/ns/ext/urid#map). +*/ +typedef struct { + /** + Opaque pointer to host data. + + This MUST be passed to map_uri() whenever it is called. + Otherwise, it must not be interpreted in any way. + */ + LV2_URID_Map_Handle handle; + + /** + Get the numeric ID of a URI. + + If the ID does not already exist, it will be created. + + This function is referentially transparent; any number of calls with the + same arguments is guaranteed to return the same value over the life of a + plugin instance. Note, however, that several URIs MAY resolve to the + same ID if the host considers those URIs equivalent. + + This function is not necessarily very fast or RT-safe: plugins SHOULD + cache any IDs they might need in performance critical situations. + + The return value 0 is reserved and indicates that an ID for that URI + could not be created for whatever reason. However, hosts SHOULD NOT + return 0 from this function in non-exceptional circumstances (i.e. the + URI map SHOULD be dynamic). + + @param handle Must be the callback_data member of this struct. + @param uri The URI to be mapped to an integer ID. + */ + LV2_URID (*map)(LV2_URID_Map_Handle handle, + const char* uri); +} LV2_URID_Map; + +/** + URI Unmap (http://lv2plug.in/ns/ext/urid#unmap). +*/ +typedef struct { + /** + Opaque pointer to host data. + + This MUST be passed to unmap() whenever it is called. + Otherwise, it must not be interpreted in any way. + */ + LV2_URID_Unmap_Handle handle; + + /** + Get the URI for a previously mapped numeric ID. + + Returns NULL if @c urid is not yet mapped. Otherwise, the corresponding + URI is returned in a canonical form. This MAY not be the exact same + string that was originally passed to LV2_URID_Map::map(), but it MUST be + an identical URI according to the URI syntax specification (RFC3986). A + non-NULL return for a given @c urid will always be the same for the life + of the plugin. Plugins that intend to perform string comparison on + unmapped URIs SHOULD first canonicalise URI strings with a call to + map_uri() followed by a call to unmap_uri(). + + @param handle Must be the callback_data member of this struct. + @param urid The ID to be mapped back to the URI string. + */ + const char* (*unmap)(LV2_URID_Unmap_Handle handle, + LV2_URID urid); +} LV2_URID_Unmap; + +#endif /* LV2_URID_H */ diff --git a/ns/ext/urid/urid.ttl b/ns/ext/urid/urid.ttl new file mode 100644 index 0000000..a87b368 --- /dev/null +++ b/ns/ext/urid/urid.ttl @@ -0,0 +1,67 @@ +# LV2 URID Extension +# Copyright 2011 Gabriel M. Beddingfield +# Copyright 2008-2011 David Robillard +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +@prefix doap: . +@prefix foaf: . +@prefix lv2: . +@prefix rdfs: . +@prefix urid: . + + + a lv2:Specification ; + doap:license ; + doap:name "LV2 URID" ; + doap:shortdesc "Features for mapping URIs to and from integers." ; + doap:release [ + doap:revision "0.2" ; + doap:created "2011-01-04" + ] ; + doap:developer [ + a foaf:Person ; + foaf:name "Gabriel M. Beddingfield" ; + foaf:homepage + ] ; + lv2:documentation """ +

This extension defines a simple mechanism for plugins to map URIs to and +from integers, usually for performance reasons (e.g. processing events typed by +URIs in real time). Typically, plugins map URIs to integers for things they +"understand" at instantiation time, and store those values for use in the audio +thread without doing any string comparison. This allows for the extensibility +of RDF but with the performance of integers.

+ +

This extension is intended as an improved and simpler replacement for the uri-map extension, since the +map context parameter has been found problematic.

+""" . + +urid:map + a lv2:Feature ; + lv2:documentation """ +

A feature which is used to map URIs to integers. To support this feature, +the host must pass an LV2_Feature to LV2_Descriptor::instantiate() with +URI http://lv2plug.in/ns/ext/urid#map and data pointed +to an instance of LV2_URID_Map.

+""" . + +urid:unmap + a lv2:Feature ; + lv2:documentation """ +

A feature which is used to unmap URIs previously mapped to integers by +urid:map. To support this feature, the host must pass an LV2_Feature to +LV2_Descriptor::instantiate() with URI +http://lv2plug.in/ns/ext/urid#unmap and data pointed to an +instance of LV2_URID_Unmap.

+""" . diff --git a/ns/ext/urid/waf b/ns/ext/urid/waf new file mode 120000 index 0000000..917d5c5 --- /dev/null +++ b/ns/ext/urid/waf @@ -0,0 +1 @@ +../../../waf \ No newline at end of file diff --git a/ns/ext/urid/wscript b/ns/ext/urid/wscript new file mode 120000 index 0000000..cf8cbae --- /dev/null +++ b/ns/ext/urid/wscript @@ -0,0 +1 @@ +../../../ext.wscript \ No newline at end of file -- cgit v1.2.1