aboutsummaryrefslogtreecommitdiff
path: root/osc.lv2
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2015-12-03 18:01:55 +0100
committerHanspeter Portner <dev@open-music-kontrollers.ch>2015-12-03 18:01:55 +0100
commitcd9b98d8931d4049e536743e842294a6b7bb93d1 (patch)
treed9e0eecf0febae8a539c93d123c95f2aa5a756ee /osc.lv2
parent44f28f133ecdf0f4570e541049d13470afe95346 (diff)
parent1eaabb4996f0e9d4e650413eaddefe65a1c7e1de (diff)
downloadsherlock.lv2-cd9b98d8931d4049e536743e842294a6b7bb93d1.tar.xz
Add 'osc.lv2/' from commit '1eaabb4996f0e9d4e650413eaddefe65a1c7e1de'
git-subtree-dir: osc.lv2 git-subtree-mainline: 44f28f133ecdf0f4570e541049d13470afe95346 git-subtree-split: 1eaabb4996f0e9d4e650413eaddefe65a1c7e1de
Diffstat (limited to 'osc.lv2')
-rw-r--r--osc.lv2/COPYING201
-rw-r--r--osc.lv2/README.md3
-rw-r--r--osc.lv2/lv2-osc.doap.ttl40
-rw-r--r--osc.lv2/lv2_osc.h704
-rw-r--r--osc.lv2/manifest.ttl23
-rw-r--r--osc.lv2/osc.ttl101
6 files changed, 1072 insertions, 0 deletions
diff --git a/osc.lv2/COPYING b/osc.lv2/COPYING
new file mode 100644
index 0000000..ddb9a46
--- /dev/null
+++ b/osc.lv2/COPYING
@@ -0,0 +1,201 @@
+ The Artistic License 2.0
+
+ Copyright (c) 2000-2006, The Perl Foundation.
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+Preamble
+
+This license establishes the terms under which a given free software
+Package may be copied, modified, distributed, and/or redistributed.
+The intent is that the Copyright Holder maintains some artistic
+control over the development of that Package while still keeping the
+Package available as open source and free software.
+
+You are always permitted to make arrangements wholly outside of this
+license directly with the Copyright Holder of a given Package. If the
+terms of this license do not permit the full use that you propose to
+make of the Package, you should contact the Copyright Holder and seek
+a different licensing arrangement.
+
+Definitions
+
+ "Copyright Holder" means the individual(s) or organization(s)
+ named in the copyright notice for the entire Package.
+
+ "Contributor" means any party that has contributed code or other
+ material to the Package, in accordance with the Copyright Holder's
+ procedures.
+
+ "You" and "your" means any person who would like to copy,
+ distribute, or modify the Package.
+
+ "Package" means the collection of files distributed by the
+ Copyright Holder, and derivatives of that collection and/or of
+ those files. A given Package may consist of either the Standard
+ Version, or a Modified Version.
+
+ "Distribute" means providing a copy of the Package or making it
+ accessible to anyone else, or in the case of a company or
+ organization, to others outside of your company or organization.
+
+ "Distributor Fee" means any fee that you charge for Distributing
+ this Package or providing support for this Package to another
+ party. It does not mean licensing fees.
+
+ "Standard Version" refers to the Package if it has not been
+ modified, or has been modified only in ways explicitly requested
+ by the Copyright Holder.
+
+ "Modified Version" means the Package, if it has been changed, and
+ such changes were not explicitly requested by the Copyright
+ Holder.
+
+ "Original License" means this Artistic License as Distributed with
+ the Standard Version of the Package, in its current version or as
+ it may be modified by The Perl Foundation in the future.
+
+ "Source" form means the source code, documentation source, and
+ configuration files for the Package.
+
+ "Compiled" form means the compiled bytecode, object code, binary,
+ or any other form resulting from mechanical transformation or
+ translation of the Source form.
+
+
+Permission for Use and Modification Without Distribution
+
+(1) You are permitted to use the Standard Version and create and use
+Modified Versions for any purpose without restriction, provided that
+you do not Distribute the Modified Version.
+
+
+Permissions for Redistribution of the Standard Version
+
+(2) You may Distribute verbatim copies of the Source form of the
+Standard Version of this Package in any medium without restriction,
+either gratis or for a Distributor Fee, provided that you duplicate
+all of the original copyright notices and associated disclaimers. At
+your discretion, such verbatim copies may or may not include a
+Compiled form of the Package.
+
+(3) You may apply any bug fixes, portability changes, and other
+modifications made available from the Copyright Holder. The resulting
+Package will still be considered the Standard Version, and as such
+will be subject to the Original License.
+
+
+Distribution of Modified Versions of the Package as Source
+
+(4) You may Distribute your Modified Version as Source (either gratis
+or for a Distributor Fee, and with or without a Compiled form of the
+Modified Version) provided that you clearly document how it differs
+from the Standard Version, including, but not limited to, documenting
+any non-standard features, executables, or modules, and provided that
+you do at least ONE of the following:
+
+ (a) make the Modified Version available to the Copyright Holder
+ of the Standard Version, under the Original License, so that the
+ Copyright Holder may include your modifications in the Standard
+ Version.
+
+ (b) ensure that installation of your Modified Version does not
+ prevent the user installing or running the Standard Version. In
+ addition, the Modified Version must bear a name that is different
+ from the name of the Standard Version.
+
+ (c) allow anyone who receives a copy of the Modified Version to
+ make the Source form of the Modified Version available to others
+ under
+
+ (i) the Original License or
+
+ (ii) a license that permits the licensee to freely copy,
+ modify and redistribute the Modified Version using the same
+ licensing terms that apply to the copy that the licensee
+ received, and requires that the Source form of the Modified
+ Version, and of any works derived from it, be made freely
+ available in that license fees are prohibited but Distributor
+ Fees are allowed.
+
+
+Distribution of Compiled Forms of the Standard Version
+or Modified Versions without the Source
+
+(5) You may Distribute Compiled forms of the Standard Version without
+the Source, provided that you include complete instructions on how to
+get the Source of the Standard Version. Such instructions must be
+valid at the time of your distribution. If these instructions, at any
+time while you are carrying out such distribution, become invalid, you
+must provide new instructions on demand or cease further distribution.
+If you provide valid instructions or cease distribution within thirty
+days after you become aware that the instructions are invalid, then
+you do not forfeit any of your rights under this license.
+
+(6) You may Distribute a Modified Version in Compiled form without
+the Source, provided that you comply with Section 4 with respect to
+the Source of the Modified Version.
+
+
+Aggregating or Linking the Package
+
+(7) You may aggregate the Package (either the Standard Version or
+Modified Version) with other packages and Distribute the resulting
+aggregation provided that you do not charge a licensing fee for the
+Package. Distributor Fees are permitted, and licensing fees for other
+components in the aggregation are permitted. The terms of this license
+apply to the use and Distribution of the Standard or Modified Versions
+as included in the aggregation.
+
+(8) You are permitted to link Modified and Standard Versions with
+other works, to embed the Package in a larger work of your own, or to
+build stand-alone binary or bytecode versions of applications that
+include the Package, and Distribute the result without restriction,
+provided the result does not expose a direct interface to the Package.
+
+
+Items That are Not Considered Part of a Modified Version
+
+(9) Works (including, but not limited to, modules and scripts) that
+merely extend or make use of the Package, do not, by themselves, cause
+the Package to be a Modified Version. In addition, such works are not
+considered parts of the Package itself, and are not subject to the
+terms of this license.
+
+
+General Provisions
+
+(10) Any use, modification, and distribution of the Standard or
+Modified Versions is governed by this Artistic License. By using,
+modifying or distributing the Package, you accept this license. Do not
+use, modify, or distribute the Package, if you do not accept this
+license.
+
+(11) If your Modified Version has been derived from a Modified
+Version made by someone other than you, you are nevertheless required
+to ensure that your Modified Version complies with the requirements of
+this license.
+
+(12) This license does not grant you the right to use any trademark,
+service mark, tradename, or logo of the Copyright Holder.
+
+(13) This license includes the non-exclusive, worldwide,
+free-of-charge patent license to make, have made, use, offer to sell,
+sell, import and otherwise transfer the Package with respect to any
+patent claims licensable by the Copyright Holder that are necessarily
+infringed by the Package. If you institute patent litigation
+(including a cross-claim or counterclaim) against any party alleging
+that the Package constitutes direct or contributory patent
+infringement, then this Artistic License to you shall terminate on the
+date that such litigation is filed.
+
+(14) Disclaimer of Warranty:
+THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS
+IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR
+NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL
+LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/osc.lv2/README.md b/osc.lv2/README.md
new file mode 100644
index 0000000..b48021f
--- /dev/null
+++ b/osc.lv2/README.md
@@ -0,0 +1,3 @@
+# osc.lv2
+
+## Open Sound Control Extension for the LV2 Plugin Specification
diff --git a/osc.lv2/lv2-osc.doap.ttl b/osc.lv2/lv2-osc.doap.ttl
new file mode 100644
index 0000000..15add6d
--- /dev/null
+++ b/osc.lv2/lv2-osc.doap.ttl
@@ -0,0 +1,40 @@
+# Copyright (c) 2015 Hanspeter Portner (dev@open-music-kontrollers.ch)
+#
+# This is free software: you can redistribute it and/or modify
+# it under the terms of the Artistic License 2.0 as published by
+# The Perl Foundation.
+#
+# This source 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
+# Artistic License 2.0 for more details.
+#
+# You should have received a copy of the Artistic License 2.0
+# along the source as a COPYING file. If not, obtain it from
+# http://www.perlfoundation.org/artistic_license_2_0.
+
+@prefix dcs: <http://ontologi.es/doap-changeset#> .
+@prefix doap: <http://usefulinc.com/ns/doap#> .
+@prefix foaf: <http://xmlns.com/foaf/0.1/> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix lic: <http://opensource.org/licenses/> .
+@prefix omk: <http://open-music-kontrollers.ch/ventosus#> .
+
+<http://open-music-kontrollers.ch/lv2/osc>
+ a doap:Project ;
+ doap:license lic:Artistic-2.0 ;
+ doap:name "LV2 OSC" ;
+ doap:shortdesc "A definition of atomified OSC." ;
+ doap:maintainer omk:me ;
+ doap:created "2015-06-19" ;
+ doap:developer omk:me ;
+ doap:release [
+ doap:revision "1.0" ;
+ doap:created "2015-06-19" ;
+ dcs:blame omk:me ;
+ dcs:changeset [
+ dcs:item [
+ rdfs:label "Initial release."
+ ]
+ ]
+ ] .
diff --git a/osc.lv2/lv2_osc.h b/osc.lv2/lv2_osc.h
new file mode 100644
index 0000000..bacbf11
--- /dev/null
+++ b/osc.lv2/lv2_osc.h
@@ -0,0 +1,704 @@
+/*
+ * Copyright (c) 2015 Hanspeter Portner (dev@open-music-kontrollers.ch)
+ *
+ * This is free software: you can redistribute it and/or modify
+ * it under the terms of the Artistic License 2.0 as published by
+ * The Perl Foundation.
+ *
+ * This source 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
+ * Artistic License 2.0 for more details.
+ *
+ * You should have received a copy of the Artistic License 2.0
+ * along the source as a COPYING file. If not, obtain it from
+ * http://www.perlfoundation.org/artistic_license_2_0.
+ */
+
+#ifndef _LV2_OSC_H_
+#define _LV2_OSC_H_
+
+#include <math.h> // INFINITY
+
+#include <lv2/lv2plug.in/ns/lv2core/lv2.h>
+#include <lv2/lv2plug.in/ns/ext/urid/urid.h>
+#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
+#include <lv2/lv2plug.in/ns/ext/atom/forge.h>
+#include <lv2/lv2plug.in/ns/ext/midi/midi.h>
+
+#define OSC_URI "http://open-music-kontrollers.ch/lv2/osc"
+#define OSC_PREFIX OSC_URI "#"
+
+#define OSC__Event OSC_PREFIX "Event" // event
+#define OSC__schedule OSC_PREFIX "schedule" // feature
+
+#define OSC__Bundle OSC_PREFIX "Bundle" // object otype
+#define OSC__Message OSC_PREFIX "Message" // object otype
+#define OSC__bundleTimestamp OSC_PREFIX "bundleTimestamp" // property key
+#define OSC__bundleItems OSC_PREFIX "bundleItems" // property key
+#define OSC__messagePath OSC_PREFIX "messagePath" // property key
+#define OSC__messageFormat OSC_PREFIX "messageFormat" // property key
+#define OSC__messageArguments OSC_PREFIX "messageArguments" // property key
+
+typedef void *osc_schedule_handle_t;
+typedef struct _osc_schedule_t osc_schedule_t;
+typedef struct _osc_forge_t osc_forge_t;
+
+typedef void (*osc_bundle_push_cb_t)(uint64_t timestamp, void *data);
+typedef void (*osc_bundle_pop_cb_t)(void *data);
+typedef void (*osc_message_cb_t)(const char *path, const char *fmt,
+ const LV2_Atom_Tuple *arguments, void *data);
+
+typedef int64_t (*osc_schedule_osc2frames_t)(osc_schedule_handle_t handle,
+ uint64_t timestamp);
+typedef uint64_t (*osc_schedule_frames2osc_t)(osc_schedule_handle_t handle,
+ int64_t frames);
+
+struct _osc_schedule_t {
+ osc_schedule_osc2frames_t osc2frames;
+ osc_schedule_frames2osc_t frames2osc;
+ osc_schedule_handle_t handle;
+};
+
+struct _osc_forge_t {
+ LV2_URID OSC_Event;
+
+ LV2_URID OSC_Bundle;
+ LV2_URID OSC_Message;
+
+ LV2_URID OSC_bundleTimestamp;
+ LV2_URID OSC_bundleItems;
+
+ LV2_URID OSC_messagePath;
+ LV2_URID OSC_messageFormat;
+ LV2_URID OSC_messageArguments;
+
+ LV2_URID MIDI_MidiEvent;
+
+ LV2_URID ATOM_Object;
+};
+
+static inline void
+osc_forge_init(osc_forge_t *oforge, LV2_URID_Map *map)
+{
+ oforge->OSC_Event = map->map(map->handle, OSC__Event);
+
+ oforge->OSC_Bundle = map->map(map->handle, OSC__Bundle);
+ oforge->OSC_Message = map->map(map->handle, OSC__Message);
+
+ oforge->OSC_bundleTimestamp = map->map(map->handle, OSC__bundleTimestamp);
+ oforge->OSC_bundleItems = map->map(map->handle, OSC__bundleItems);
+
+ oforge->OSC_messagePath = map->map(map->handle, OSC__messagePath);
+ oforge->OSC_messageFormat = map->map(map->handle, OSC__messageFormat);
+ oforge->OSC_messageArguments = map->map(map->handle, OSC__messageArguments);
+
+ oforge->MIDI_MidiEvent = map->map(map->handle, LV2_MIDI__MidiEvent);
+
+ oforge->ATOM_Object = map->map(map->handle, LV2_ATOM__Object);
+}
+
+static inline int
+osc_atom_is_bundle(osc_forge_t *oforge, const LV2_Atom_Object *obj)
+{
+ return (obj->atom.type == oforge->ATOM_Object)
+ && (obj->body.otype == oforge->OSC_Bundle);
+}
+
+static inline void
+osc_atom_bundle_unpack(osc_forge_t *oforge, const LV2_Atom_Object *obj,
+ const LV2_Atom_Long **timestamp, const LV2_Atom_Tuple **items)
+{
+ *timestamp = NULL;
+ *items = NULL;
+
+ LV2_Atom_Object_Query q [] = {
+ { oforge->OSC_bundleTimestamp, (const LV2_Atom **)timestamp },
+ { oforge->OSC_bundleItems, (const LV2_Atom **)items },
+ LV2_ATOM_OBJECT_QUERY_END
+ };
+
+ lv2_atom_object_query(obj, q);
+}
+
+static inline int
+osc_atom_is_message(osc_forge_t *oforge, const LV2_Atom_Object *obj)
+{
+ return (obj->atom.type == oforge->ATOM_Object)
+ && (obj->body.otype == oforge->OSC_Message);
+}
+
+static inline void
+osc_atom_message_unpack(osc_forge_t *oforge, const LV2_Atom_Object *obj,
+ const LV2_Atom_String **path, const LV2_Atom_String **format,
+ const LV2_Atom_Tuple **arguments)
+{
+ *path = NULL;
+ *format = NULL;
+ *arguments = NULL;
+
+ LV2_Atom_Object_Query q [] = {
+ { oforge->OSC_messagePath, (const LV2_Atom **)path },
+ { oforge->OSC_messageFormat, (const LV2_Atom **)format },
+ { oforge->OSC_messageArguments, (const LV2_Atom **)arguments },
+ LV2_ATOM_OBJECT_QUERY_END
+ };
+
+ lv2_atom_object_query(obj, q);
+}
+
+static inline void osc_atom_event_unroll(osc_forge_t *oforge,
+ const LV2_Atom_Object *obj, osc_bundle_push_cb_t bundle_push_cb,
+ osc_bundle_pop_cb_t bundle_pop_cb, osc_message_cb_t message_cb, void *data);
+
+static inline void
+osc_atom_message_unroll(osc_forge_t *oforge, const LV2_Atom_Object *obj,
+ osc_message_cb_t message_cb, void *data)
+{
+ const LV2_Atom_String* path;
+ const LV2_Atom_String* fmt;
+ const LV2_Atom_Tuple* args;
+
+ osc_atom_message_unpack(oforge, obj, &path, &fmt, &args);
+
+ const char *path_str = path ? LV2_ATOM_BODY_CONST(path) : NULL;
+ const char *fmt_str = fmt ? LV2_ATOM_BODY_CONST(fmt) : NULL;
+
+ if(message_cb)
+ message_cb(path_str, fmt_str, args, data);
+}
+
+static inline void
+osc_atom_bundle_unroll(osc_forge_t *oforge, const LV2_Atom_Object *obj,
+ osc_bundle_push_cb_t bundle_push_cb, osc_bundle_pop_cb_t bundle_pop_cb,
+ osc_message_cb_t message_cb, void *data)
+{
+ const LV2_Atom_Long* timestamp;
+ const LV2_Atom_Tuple* items;
+
+ osc_atom_bundle_unpack(oforge, obj, &timestamp, &items);
+
+ uint64_t timestamp_body = timestamp ? (uint64_t)timestamp->body : 1ULL;
+
+ if(bundle_push_cb)
+ bundle_push_cb(timestamp_body, data);
+
+ // iterate over tuple body
+ if(items)
+ {
+ for(const LV2_Atom *itr = lv2_atom_tuple_begin(items);
+ !lv2_atom_tuple_is_end(LV2_ATOM_BODY(items), items->atom.size, itr);
+ itr = lv2_atom_tuple_next(itr))
+ {
+ osc_atom_event_unroll(oforge, (const LV2_Atom_Object *)itr,
+ bundle_push_cb, bundle_pop_cb, message_cb, data);
+ }
+ }
+
+ if(bundle_pop_cb)
+ bundle_pop_cb(data);
+}
+
+static inline void
+osc_atom_event_unroll(osc_forge_t *oforge, const LV2_Atom_Object *obj,
+ osc_bundle_push_cb_t bundle_push_cb, osc_bundle_pop_cb_t bundle_pop_cb,
+ osc_message_cb_t message_cb, void *data)
+{
+ if(osc_atom_is_bundle(oforge, obj))
+ {
+ osc_atom_bundle_unroll(oforge, obj, bundle_push_cb, bundle_pop_cb,
+ message_cb, data);
+ }
+ else if(osc_atom_is_message(oforge, obj))
+ {
+ osc_atom_message_unroll(oforge, obj, message_cb, data);
+ }
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_bundle_push(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ LV2_Atom_Forge_Frame frame [2], uint64_t timestamp)
+{
+ if(!lv2_atom_forge_object(forge, &frame[0], 0, oforge->OSC_Bundle))
+ return 0;
+
+ if(!lv2_atom_forge_key(forge, oforge->OSC_bundleTimestamp))
+ return 0;
+ if(!lv2_atom_forge_long(forge, timestamp))
+ return 0;
+
+ if(!lv2_atom_forge_key(forge, oforge->OSC_bundleItems))
+ return 0;
+
+ return lv2_atom_forge_tuple(forge, &frame[1]);
+}
+
+static inline void
+osc_forge_bundle_pop(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ LV2_Atom_Forge_Frame frame [2])
+{
+ lv2_atom_forge_pop(forge, &frame[1]);
+ lv2_atom_forge_pop(forge, &frame[0]);
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_message_push(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ LV2_Atom_Forge_Frame frame [2], const char *path, const char *fmt)
+{
+ if(!lv2_atom_forge_object(forge, &frame[0], 0, oforge->OSC_Message))
+ return 0;
+
+ if(!lv2_atom_forge_key(forge, oforge->OSC_messagePath))
+ return 0;
+ if(!lv2_atom_forge_string(forge, path, strlen(path)))
+ return 0;
+
+ if(!lv2_atom_forge_key(forge, oforge->OSC_messageFormat))
+ return 0;
+ if(!lv2_atom_forge_string(forge, fmt, strlen(fmt)))
+ return 0;
+
+ if(!lv2_atom_forge_key(forge, oforge->OSC_messageArguments))
+ return 0;
+
+ return lv2_atom_forge_tuple(forge, &frame[1]);
+}
+
+static inline void
+osc_forge_message_pop(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ LV2_Atom_Forge_Frame frame [2])
+{
+ lv2_atom_forge_pop(forge, &frame[1]);
+ lv2_atom_forge_pop(forge, &frame[0]);
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_int32(osc_forge_t *oforge, LV2_Atom_Forge *forge, int32_t i)
+{
+ return lv2_atom_forge_int(forge, i);
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_float(osc_forge_t *oforge, LV2_Atom_Forge *forge, float f)
+{
+ return lv2_atom_forge_float(forge, f);
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_string(osc_forge_t *oforge, LV2_Atom_Forge *forge, const char *s)
+{
+ return lv2_atom_forge_string(forge, s, strlen(s));
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_symbol(osc_forge_t *oforge, LV2_Atom_Forge *forge, const char *s)
+{
+ return lv2_atom_forge_string(forge, s, strlen(s));
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_blob(osc_forge_t *oforge, LV2_Atom_Forge *forge, uint32_t size,
+ const uint8_t *b)
+{
+ LV2_Atom_Forge_Ref ref;
+ if(!(ref = lv2_atom_forge_atom(forge, size, forge->Chunk)))
+ return 0;
+ if(!(ref = lv2_atom_forge_raw(forge, b, size)))
+ return 0;
+ lv2_atom_forge_pad(forge, size);
+
+ return ref;
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_int64(osc_forge_t *oforge, LV2_Atom_Forge *forge, int64_t h)
+{
+ return lv2_atom_forge_long(forge, h);
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_double(osc_forge_t *oforge, LV2_Atom_Forge *forge, double d)
+{
+ return lv2_atom_forge_double(forge, d);
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_timestamp(osc_forge_t *oforge, LV2_Atom_Forge *forge, uint64_t t)
+{
+ return lv2_atom_forge_long(forge, t);
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_char(osc_forge_t *oforge, LV2_Atom_Forge *forge, char c)
+{
+ return lv2_atom_forge_int(forge, c);
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_midi(osc_forge_t *oforge, LV2_Atom_Forge *forge, uint32_t size,
+ const uint8_t *m)
+{
+ LV2_Atom_Forge_Ref ref;
+ if(!(ref = lv2_atom_forge_atom(forge, size, oforge->MIDI_MidiEvent)))
+ return 0;
+ if(!(ref = lv2_atom_forge_raw(forge, m, size)))
+ return 0;
+ lv2_atom_forge_pad(forge, size);
+
+ return ref;
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_message_varlist(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const char *path, const char *fmt, va_list args)
+{
+ LV2_Atom_Forge_Frame frame [2];
+ LV2_Atom_Forge_Ref ref;
+
+ if(!(ref = osc_forge_message_push(oforge, forge, frame, path, fmt)))
+ return 0;
+
+ for(const char *type = fmt; *type; type++)
+ {
+ switch(*type)
+ {
+ case 'i':
+ {
+ if(!(ref =osc_forge_int32(oforge, forge, va_arg(args, int32_t))))
+ return 0;
+ break;
+ }
+ case 'f':
+ {
+ if(!(ref = osc_forge_float(oforge, forge, (float)va_arg(args, double))))
+ return 0;
+ break;
+ }
+ case 's':
+ {
+ if(!(ref = osc_forge_string(oforge, forge, va_arg(args, const char *))))
+ return 0;
+ break;
+ }
+ case 'S':
+ {
+ if(!(ref = osc_forge_symbol(oforge, forge, va_arg(args, const char *))))
+ return 0;
+ break;
+ }
+ case 'b':
+ {
+ uint32_t size = va_arg(args, uint32_t);
+ const uint8_t *b = va_arg(args, const uint8_t *);
+ if(!(ref = osc_forge_blob(oforge, forge, size, b)))
+ return 0;
+ break;
+ }
+
+ case 'h':
+ {
+ if(!(ref = osc_forge_int64(oforge, forge, va_arg(args, int64_t))))
+ return 0;
+ break;
+ }
+ case 'd':
+ {
+ if(!(ref = osc_forge_double(oforge, forge, va_arg(args, double))))
+ return 0;
+ break;
+ }
+ case 't':
+ {
+ if(!(ref = osc_forge_timestamp(oforge, forge, va_arg(args, uint64_t))))
+ return 0;
+ break;
+ }
+
+ case 'c':
+ {
+ if(!(ref = osc_forge_char(oforge, forge, (char)va_arg(args, unsigned int))))
+ return 0;
+ break;
+ }
+ case 'm':
+ {
+ int32_t size = va_arg(args, int32_t);
+ const uint8_t *m = va_arg(args, const uint8_t *);
+ if(!(ref = osc_forge_midi(oforge, forge, size, m)))
+ return 0;
+ break;
+ }
+
+ case 'T':
+ case 'F':
+ case 'N':
+ case 'I':
+ {
+ break;
+ }
+
+ default: // unknown argument type
+ {
+ return 0;
+ }
+ }
+ }
+
+ osc_forge_message_pop(oforge, forge, frame);
+
+ return ref;
+}
+
+static inline LV2_Atom_Forge_Ref
+osc_forge_message_vararg(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const char *path, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ LV2_Atom_Forge_Ref ref;
+ ref = osc_forge_message_varlist(oforge, forge, path, fmt, args);
+
+ va_end(args);
+
+ return ref;
+}
+
+static inline const LV2_Atom *
+osc_deforge_int32(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, int32_t *i)
+{
+ if(!atom || (atom->type != forge->Int) )
+ return NULL;
+
+ *i = ((const LV2_Atom_Int *)atom)->body;
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_float(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, float *f)
+{
+ if(!atom || (atom->type != forge->Float) )
+ return NULL;
+
+ *f = ((const LV2_Atom_Float *)atom)->body;
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_string(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, const char **s)
+{
+ if(!atom || (atom->type != forge->String) )
+ return NULL;
+
+ *s = LV2_ATOM_BODY_CONST(atom);
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_symbol(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, const char **s)
+{
+ if(!atom || (atom->type != forge->String) )
+ return NULL;
+
+ *s = LV2_ATOM_BODY_CONST(atom);
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_blob(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, uint32_t *size, const uint8_t **b)
+{
+ if(!atom || (atom->type != forge->Chunk) )
+ return NULL;
+
+ *size = atom->size;
+ *b = LV2_ATOM_BODY_CONST(atom);
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_int64(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, int64_t *h)
+{
+ if(!atom || (atom->type != forge->Long) )
+ return NULL;
+
+ *h = ((const LV2_Atom_Long *)atom)->body;
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_double(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, double *d)
+{
+ if(!atom || (atom->type != forge->Double) )
+ return NULL;
+
+ *d = ((const LV2_Atom_Double *)atom)->body;
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_timestamp(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, uint64_t *t)
+{
+ if(!atom || (atom->type != forge->Long) )
+ return NULL;
+
+ *t = ((const LV2_Atom_Long *)atom)->body;
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_char(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, char *c)
+{
+ if(!atom || (atom->type != forge->Int) )
+ return NULL;
+
+ *c = ((const LV2_Atom_Int *)atom)->body;
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_midi(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, uint32_t *size, const uint8_t **m)
+{
+ if(!atom || (atom->type != oforge->MIDI_MidiEvent) )
+ return NULL;
+
+ *size = atom->size;
+ *m = LV2_ATOM_BODY_CONST(atom);
+
+ return lv2_atom_tuple_next(atom);
+}
+
+static inline const LV2_Atom *
+osc_deforge_message_varlist(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, const char *fmt, va_list args)
+{
+ for(const char *type = fmt; *type; type++)
+ {
+ switch(*type)
+ {
+ case 'i':
+ {
+ int32_t *i = va_arg(args, int32_t *);
+ if(!(atom = osc_deforge_int32(oforge, forge, atom, i)))
+ return NULL;
+ break;
+ }
+ case 'f':
+ {
+ float *f = va_arg(args, float *);
+ if(!(atom = osc_deforge_float(oforge, forge, atom, f)))
+ return NULL;
+ break;
+ }
+ case 's':
+ {
+ const char **s = va_arg(args, const char **);
+ if(!(atom = osc_deforge_string(oforge, forge, atom, s)))
+ return NULL;
+ break;
+ }
+ case 'S':
+ {
+ const char **s = va_arg(args, const char **);
+ if(!(atom = osc_deforge_symbol(oforge, forge, atom, s)))
+ return NULL;
+ break;
+ }
+ case 'b':
+ {
+ uint32_t *size = va_arg(args, uint32_t *);
+ const uint8_t **b = va_arg(args, const uint8_t **);
+ if(!(atom = osc_deforge_blob(oforge, forge, atom, size, b)))
+ return NULL;
+ break;
+ }
+
+ case 'h':
+ {
+ int64_t *h = va_arg(args, int64_t *);
+ if(!(atom = osc_deforge_int64(oforge, forge, atom, h)))
+ return NULL;
+ break;
+ }
+ case 'd':
+ {
+ double *d = va_arg(args, double *);
+ if(!(atom = osc_deforge_double(oforge, forge, atom, d)))
+ return NULL;
+ break;
+ }
+ case 't':
+ {
+ uint64_t *t = va_arg(args, uint64_t *);
+ if(!(atom = osc_deforge_timestamp(oforge, forge, atom, t)))
+ return NULL;
+ break;
+ }
+
+ case 'c':
+ {
+ char *c = va_arg(args, char *);
+ if(!(atom = osc_deforge_char(oforge, forge, atom, c)))
+ return NULL;
+ break;
+ }
+ case 'm':
+ {
+ uint32_t *size = va_arg(args, uint32_t *);
+ const uint8_t **m = va_arg(args, const uint8_t **);
+ if(!(atom = osc_deforge_midi(oforge, forge, atom, size, m)))
+ return NULL;
+ break;
+ }
+
+ case 'T':
+ case 'F':
+ case 'N':
+ case 'I':
+ {
+ break;
+ }
+
+ default: // unknown argument type
+ {
+ return NULL;
+ }
+ }
+ }
+
+ return atom;
+}
+
+static inline const LV2_Atom *
+osc_deforge_message_vararg(osc_forge_t *oforge, LV2_Atom_Forge *forge,
+ const LV2_Atom *atom, const char *fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ atom = osc_deforge_message_varlist(oforge, forge, atom, fmt, args);
+
+ va_end(args);
+
+ return atom;
+}
+
+#endif // _LV2_OSC_H_
diff --git a/osc.lv2/manifest.ttl b/osc.lv2/manifest.ttl
new file mode 100644
index 0000000..9f75ab3
--- /dev/null
+++ b/osc.lv2/manifest.ttl
@@ -0,0 +1,23 @@
+# Copyright (c) 2015 Hanspeter Portner (dev@open-music-kontrollers.ch)
+#
+# This is free software: you can redistribute it and/or modify
+# it under the terms of the Artistic License 2.0 as published by
+# The Perl Foundation.
+#
+# This source 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
+# Artistic License 2.0 for more details.
+#
+# You should have received a copy of the Artistic License 2.0
+# along the source as a COPYING file. If not, obtain it from
+# http://www.perlfoundation.org/artistic_license_2_0.
+
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+
+<http://open-music-kontrollers.ch/lv2/osc>
+ a lv2:Specification ;
+ lv2:minorVersion 1 ;
+ lv2:microVersion 0 ;
+ rdfs:seeAlso <osc.ttl> .
diff --git a/osc.lv2/osc.ttl b/osc.lv2/osc.ttl
new file mode 100644
index 0000000..efa9e32
--- /dev/null
+++ b/osc.lv2/osc.ttl
@@ -0,0 +1,101 @@
+# Copyright (c) 2015 Hanspeter Portner (dev@open-music-kontrollers.ch)
+#
+# This is free software: you can redistribute it and/or modify
+# it under the terms of the Artistic License 2.0 as published by
+# The Perl Foundation.
+#
+# This source 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
+# Artistic License 2.0 for more details.
+#
+# You should have received a copy of the Artistic License 2.0
+# along the source as a COPYING file. If not, obtain it from
+# http://www.perlfoundation.org/artistic_license_2_0.
+
+@prefix atom: <http://lv2plug.in/ns/ext/atom#> .
+@prefix lv2: <http://lv2plug.in/ns/lv2core#> .
+@prefix midi: <http://lv2plug.in/ns/midi#> .
+@prefix owl: <http://www.w3.org/2002/07/owl#> .
+@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
+@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
+@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
+@prefix osc: <http://open-music-kontrollers.ch/lv2/osc#> .
+
+<http://open-music-kontrollers.ch/lv2/osc>
+ a owl:Ontology ;
+ rdfs:seeAlso <lv2_osc.h> ,
+ <lv2-osc.doap.ttl> ;
+ lv2:documentation """
+ <p>This specification defines event data types for OSC bundles and message.
+ To signal support for OSC events on an atom:AtomPort with an atom:bufferType
+ of atom:Sequence, plugin authors should add atom:supports osc:Event to
+ the plugin specification.</p>
+ """ .
+
+osc:schedule
+ a lv2:Feature .
+
+osc:Event
+ a rdfs:Class ;
+ rdfs:subClassOf atom:Object ;
+ rdfs:label "OSC Event (Bundle or Message)" .
+
+osc:Bundle
+ a rdfs:Class ;
+ rdfs:subClassOf osc:Event ;
+ rdfs:label "OSC Bundle" .
+
+osc:Message
+ a rdfs:Class ;
+ rdfs:subClassOf osc:Event ;
+ rdfs:label "OSC Message" .
+
+osc:bundleTimestamp
+ a rdf:Property ,
+ owl:ObjectProperty ,
+ owl:FunctionalProperty ;
+ rdfs:domain osc:Bundle ;
+ rdfs:range atom:Long ;
+ rdfs:label "OSC Bundle Timestamp" .
+
+osc:bundleItems
+ a rdf:Property ,
+ owl:ObjectProperty ,
+ owl:FunctionalProperty ;
+ rdfs:domain osc:Bundle ;
+ rdfs:range atom:Tuple ;
+ rdfs:label "OSC Bundle Items" ;
+ lv2:documentation """
+ <p>Tuple of OSC Bundle Items (e.g. nested osc:Bundle's and/or
+ osc:Message's).</p>
+ """ .
+
+osc:messagePath
+ a rdf:Property ,
+ owl:ObjectProperty ,
+ owl:FunctionalProperty ;
+ rdfs:domain osc:Message ;
+ rdfs:range atom:String ;
+ rdfs:label "OSC Message Path" .
+
+osc:messageFormat
+ a rdf:Property ,
+ owl:ObjectProperty ,
+ owl:FunctionalProperty ;
+ rdfs:domain osc:Message ;
+ rdfs:range atom:String ;
+ rdfs:label "OSC Message Format" .
+
+osc:messageArguments
+ a rdf:Property ,
+ owl:ObjectProperty ,
+ owl:FunctionalProperty ;
+ rdfs:domain osc:Message ;
+ rdfs:range atom:Tuple ;
+ rdfs:label "OSC Message Arguments" ;
+ lv2:documentation """
+ <p>Tuple of OSC Message Arguments (e.g. Atom:Int, Atom:Long, Atom:Float,
+ Atom:Double, Atom:String, Atom:Chunk, Atom:Bool, Atom:Blank,
+ MIDI:MidiEvent).</p>
+ """ .