diff options
Diffstat (limited to 'lv2')
| -rw-r--r-- | lv2/event-helpers.h | 243 | ||||
| -rw-r--r-- | lv2/event.h | 281 | ||||
| -rw-r--r-- | lv2/input_lv2.h | 2 | 
3 files changed, 525 insertions, 1 deletions
| diff --git a/lv2/event-helpers.h b/lv2/event-helpers.h new file mode 100644 index 0000000..b14f7d9 --- /dev/null +++ b/lv2/event-helpers.h @@ -0,0 +1,243 @@ +/* lv2_event_helpers.h - Helper functions for the LV2 events extension. + * + * Copyright (C) 2008-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 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 <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> +#include "event.h" + +/** @file + * Helper functions for the LV2 Event extension + * <http://lv2plug.in/ns/ext/event>. + * + * 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) +{ +	LV2_Event_Buffer* buf = (LV2_Event_Buffer*)malloc(sizeof(LV2_Event_Buffer) + capacity); +	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/lv2/event.h b/lv2/event.h new file mode 100644 index 0000000..2c340ba --- /dev/null +++ b/lv2/event.h @@ -0,0 +1,281 @@ +/* +  LV2 Event Extension +  Copyright 2008-2011 David Robillard <http://drobilla.net> +  Copyright 2006-2007 Lars Luthman <lars.luthman@gmail.com> + +  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 <stdint.h> + +/** +   @file event.h +   C API for the LV2 Event extension <http://lv2plug.in/ns/ext/event>. +  +   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/lv2/input_lv2.h b/lv2/input_lv2.h index f904237..73f242a 100644 --- a/lv2/input_lv2.h +++ b/lv2/input_lv2.h @@ -30,7 +30,7 @@  #include <audioinputengine.h>  #include <midimapper.h> -#include <lv2/lv2plug.in/ns/ext/event/event-helpers.h> +#include "event-helpers.h"  class InputLV2 : public AudioInputEngine {  public: | 
