diff options
Diffstat (limited to 'ext/osc.lv2')
| -rw-r--r-- | ext/osc.lv2/lv2_osc.c | 314 | ||||
| -rw-r--r-- | ext/osc.lv2/lv2_osc.pc.in | 10 | ||||
| -rw-r--r-- | ext/osc.lv2/lv2_osc_print.c | 66 | ||||
| -rw-r--r-- | ext/osc.lv2/lv2_osc_test.c | 55 | ||||
| -rw-r--r-- | ext/osc.lv2/manifest.ttl | 7 | ||||
| -rw-r--r-- | ext/osc.lv2/osc-print.h | 42 | ||||
| -rw-r--r-- | ext/osc.lv2/osc.h | 123 | ||||
| -rw-r--r-- | ext/osc.lv2/osc.ttl | 56 | 
8 files changed, 673 insertions, 0 deletions
diff --git a/ext/osc.lv2/lv2_osc.c b/ext/osc.lv2/lv2_osc.c new file mode 100644 index 0000000..0c1d1e0 --- /dev/null +++ b/ext/osc.lv2/lv2_osc.c @@ -0,0 +1,314 @@ +/* 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 <http://www.gnu.org/licenses/>. + */ + +#include <errno.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#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': +		return 4; + +	case 'h': +	case 'd': +		return 8; + +	case 's': +		return lv2_osc_string_size(&arg->s); + +	/*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; +} + + +#if 0 +/** Allocate a new LV2OSCBuffer. + * + * This function is NOT realtime safe. + */ +LV2_OSCBuffer* +lv2_osc_buffer_new(uint32_t capacity) +{ +	LV2OSCBuffer* buf = (LV2OSCBuffer*)malloc((sizeof(uint32_t) * 3) + capacity); +	buf->capacity = capacity; +	buf->size = 0; +	buf->message_count = 0; +	memset(&buf->data, 0, capacity); +	return buf; +} + + +void +lv2_osc_buffer_clear(LV2OSCBuffer* buf) +{ +	buf->size = 0; +	buf->message_count = 0; +} + +int +lv2_osc_buffer_append_message(LV2OSCBuffer* buf, LV2_OSC_Event* msg) +{ +	const uint32_t msg_size = lv2_message_get_size(msg); + +	if (buf->capacity - buf->size - ((buf->message_count + 1) * sizeof(uint32_t)) < msg_size) +		return ENOBUFS; + +	char* write_loc = &buf->data + buf->size; + +	memcpy(write_loc, msg, msg_size); + +	// Index is written backwards, starting at end of data +	uint32_t* index_end = (uint32_t*)(&buf->data + buf->capacity - sizeof(uint32_t)); +	*(index_end - buf->message_count) = buf->size; + +	++buf->message_count; + +	buf->size += msg_size; + +	return 0; +} + +int +lv2_osc_buffer_append(LV2OSCBuffer* buf, double time, const char* path, const char* types, ...) +{ +	// FIXME: crazy unsafe +	LV2_OSC_Event* write_msg = (LV2_OSC_Event*)(&buf->data + buf->size); + +	write_msg->time = time; +	write_msg->data_size = 0; +	write_msg->argument_count = 0; +	write_msg->types_offset = strlen(path) + 1; + +	memcpy(&write_msg->data, path, write_msg->types_offset); + +	/*fprintf(stderr, "Append message:\n"); +	lv2_osc_message_print(write_msg); +	fprintf(stderr, "\n");*/ + +	uint32_t msg_size = lv2_message_get_size(write_msg); +	buf->size += msg_size; +	buf->message_count++; + +	return 0; +} +#endif + diff --git a/ext/osc.lv2/lv2_osc.pc.in b/ext/osc.lv2/lv2_osc.pc.in new file mode 100644 index 0000000..0424836 --- /dev/null +++ b/ext/osc.lv2/lv2_osc.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: lv2_osc +Version: @LV2_OSC_VERSION@ +Description: LV2 OSC message events extension +Libs: +Cflags: -I${includedir} diff --git a/ext/osc.lv2/lv2_osc_print.c b/ext/osc.lv2/lv2_osc_print.c new file mode 100644 index 0000000..5282d46 --- /dev/null +++ b/ext/osc.lv2/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 <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#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/ext/osc.lv2/lv2_osc_test.c b/ext/osc.lv2/lv2_osc_test.c new file mode 100644 index 0000000..3f76d41 --- /dev/null +++ b/ext/osc.lv2/lv2_osc_test.c @@ -0,0 +1,55 @@ +#include <assert.h> +#include <string.h> +#include <stdio.h> +#include <lo/lo.h> +#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/ext/osc.lv2/manifest.ttl b/ext/osc.lv2/manifest.ttl new file mode 100644 index 0000000..dc7c310 --- /dev/null +++ b/ext/osc.lv2/manifest.ttl @@ -0,0 +1,7 @@ +@prefix lv2:  <http://lv2plug.in/ns/lv2core#> . +@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> . + +<http://lv2plug.in/ns/ext/osc> +	a lv2:Specification ; +	rdfs:seeAlso <osc.ttl> . + diff --git a/ext/osc.lv2/osc-print.h b/ext/osc.lv2/osc-print.h new file mode 100644 index 0000000..7d590f3 --- /dev/null +++ b/ext/osc.lv2/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 <http://www.gnu.org/licenses/>. + */ + +/** @file + * Helper functions for printing LV2 OSC messages as defined by the + * LV2 OSC extension <http://lv2plug.in/ns/ext/osc>. + */ + +#ifndef LV2_OSC_PRINT_H +#define LV2_OSC_PRINT_H + +#include "ext/osc.lv2/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/ext/osc.lv2/osc.h b/ext/osc.lv2/osc.h new file mode 100644 index 0000000..23e49a9 --- /dev/null +++ b/ext/osc.lv2/osc.h @@ -0,0 +1,123 @@ +/* LV2 OSC Messages Extension + * Copyright (C) 2007-2009 David Robillard <http://drobilla.net> + * + * 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 <stdint.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** @file + * C header for the LV2 OSC extension <http://lv2plug.in/ns/ext/osc>. + * This extension uses (raw) OSC messages + * and a buffer format which contains a sequence of timestamped messages. + * Additional (ie beyond raw OSC) indexing information is stored in the buffer + * for performance, so that accessors for messages and arguments are very fast: + * O(1) and realtime safe, unless otherwise noted. + */ + + +/** 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/ext/osc.lv2/osc.ttl b/ext/osc.lv2/osc.ttl new file mode 100644 index 0000000..1cacdab --- /dev/null +++ b/ext/osc.lv2/osc.ttl @@ -0,0 +1,56 @@ +# LV2 OSC Messages Extension +# Copyright (C) 2007 David Robillard <d@drobilla.net> +#  +# 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:  <http://lv2plug.in/ns/ext/osc#> . +@prefix lv2:  <http://lv2plug.in/ns/lv2core#> . +@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 doap: <http://usefulinc.com/ns/doap#> . +@prefix foaf: <http://xmlns.com/foaf/0.1/> . + +<http://lv2plug.in/ns/ext/osc> a lv2:Specification ; +	doap:license <http://usefulinc.com/doap/licenses/mit> ; +	doap:name "LV2 OSC Events" ; +	rdfs:comment "Defines an LV2 event type for standard raw OSC" ; +	doap:maintainer [ +		a foaf:Person ; +		foaf:name "David Robillard" ; +		foaf:homepage <http://drobilla.net/> ; +		rdfs:seeAlso <http://drobilla.net/drobilla.xrdf> +	] . + + +####################### +## Plugin Properties ## +####################### + +osc:interfacePort a rdf:Property ; +	rdfs:domain  lv2:Plugin ; +	rdfs:range   lv2:Port ; +	rdfs:label   "Has a main OSC control port" ; +	rdfs:comment """ +Specifies a port that can be used as the OSC interface for the plugin as a +whole.  For example, if a host is providing an OSC interface to a plugin at +/some/osc/path/someplugin and a message /some/osc/path/someplugin/foo is +received, the message /foo should be sent to this port. +""" . +  |