diff DPF-Prymula-audioplugins/dpf/distrho/src/lv2/event-helpers.h @ 3:84e66ea83026

DPF-Prymula-audioplugins-0.231015-2
author prymula <prymula76@outlook.com>
date Mon, 16 Oct 2023 21:53:34 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DPF-Prymula-audioplugins/dpf/distrho/src/lv2/event-helpers.h	Mon Oct 16 21:53:34 2023 +0200
@@ -0,0 +1,265 @@
+/*
+  Copyright 2008-2015 David Robillard <http://drobilla.net>
+
+  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 event-helpers.h Helper functions for the LV2 Event extension
+   <http://lv2plug.in/ns/ext/event>.
+*/
+
+#ifndef LV2_EVENT_HELPERS_H
+#define LV2_EVENT_HELPERS_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "event.h"
+
+#ifdef __cplusplus
+extern "C" {
+#else
+#    include <stdbool.h>
+#endif
+
+/** @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 (uint16_t)(size + 7U) & (uint16_t)(~7U);
+}
+
+
+/** 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 `buf`.
+ * @return True if `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 `iter` is valid.
+ * @return True if `iter` is valid, otherwise false (past end of buffer) */
+static inline bool
+lv2_event_is_valid(LV2_Event_Iterator* iter)
+{
+	return (iter->buf && (iter->offset < iter->buf->size));
+}
+
+
+/** Advance `iter` forward one event.
+ * `iter` must be valid.
+ * @return True if `iter` is valid, otherwise false (reached end of buffer) */
+static inline bool
+lv2_event_increment(LV2_Event_Iterator* iter)
+{
+	if (!lv2_event_is_valid(iter)) {
+		return false;
+	}
+
+	LV2_Event* const ev = (LV2_Event*)(
+			(uint8_t*)iter->buf->data + iter->offset);
+
+	iter->offset += lv2_event_pad_size(
+		(uint16_t)((uint16_t)sizeof(LV2_Event) + ev->size));
+
+	return true;
+}
+
+
+/** Dereference an event iterator (get the event currently pointed at).
+ * `iter` must be valid.
+ * `data` if non-NULL, will be set to point to the contents of the event
+ *         returned.
+ * @return A Pointer to the event `iter` is currently pointing at, or NULL
+ *         if the end of the buffer is reached (in which case `data` is
+ *         also set to NULL). */
+static inline LV2_Event*
+lv2_event_get(LV2_Event_Iterator* iter,
+              uint8_t**           data)
+{
+	if (!lv2_event_is_valid(iter)) {
+		return NULL;
+	}
+
+	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 `iter`.
+ * The event (if any) pointed to by `iter` will be overwritten, and `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)
+		return false;
+
+	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((uint16_t)(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)
+{
+	const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + size);
+	if (iter->buf->capacity - iter->buf->size < total_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;
+
+	const uint16_t padded_size = lv2_event_pad_size(total_size);
+	iter->buf->size += padded_size;
+	iter->offset    += padded_size;
+
+	return (uint8_t*)ev + sizeof(LV2_Event);
+}
+
+
+/** Write an event at `iter`.
+ * The event (if any) pointed to by `iter` will be overwritten, and `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)
+{
+	const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + ev->size);
+	if (iter->buf->capacity - iter->buf->size < total_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 padded_size = lv2_event_pad_size(total_size);
+	iter->buf->size += padded_size;
+	iter->offset    += padded_size;
+
+	return true;
+}
+
+#ifdef __cplusplus
+}  /* extern "C" */
+#endif
+
+#endif /* LV2_EVENT_HELPERS_H */