aboutsummaryrefslogtreecommitdiffstats
path: root/ns/ext/atom/atom-buffer.h
diff options
context:
space:
mode:
Diffstat (limited to 'ns/ext/atom/atom-buffer.h')
-rw-r--r--ns/ext/atom/atom-buffer.h163
1 files changed, 163 insertions, 0 deletions
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 <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 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 <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+
+#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 */