2 Copyright 2008-2012 David Robillard <http://drobilla.net>
4 Permission to use, copy, modify, and/or distribute this software for any
5 purpose with or without fee is hereby granted, provided that the above
6 copyright notice and this permission notice appear in all copies.
8 THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 #include "lv2/lv2plug.in/ns/ext/atom/atom.h"
23 #include "lv2/lv2plug.in/ns/ext/event/event.h"
25 #include "lv2_evbuf.h"
27 struct LV2_Evbuf_Impl {
31 LV2_Event_Buffer event;
32 LV2_Atom_Port_Buffer atom;
36 static inline uint32_t
37 lv2_evbuf_pad_size(uint32_t size)
39 return (size + 7) & (~7);
43 lv2_evbuf_new(uint32_t capacity, LV2_Evbuf_Type type, uint32_t atom_type)
45 // FIXME: memory must be 64-bit aligned
46 LV2_Evbuf* evbuf = (LV2_Evbuf*)malloc(
47 sizeof(LV2_Evbuf) + sizeof(LV2_Atom_Sequence) + capacity);
48 evbuf->capacity = capacity;
49 lv2_evbuf_set_type(evbuf, type, atom_type);
50 lv2_evbuf_reset(evbuf);
55 lv2_evbuf_free(LV2_Evbuf* evbuf)
61 lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type, uint32_t atom_type)
66 evbuf->buf.event.data = (uint8_t*)(evbuf + 1);
67 evbuf->buf.event.capacity = evbuf->capacity;
70 evbuf->buf.atom.data = (LV2_Atom*)(evbuf + 1);
71 evbuf->buf.atom.size = sizeof(LV2_Atom_Port_Buffer);
72 evbuf->buf.atom.capacity = evbuf->capacity;
73 evbuf->buf.atom.data->type = atom_type;
74 evbuf->buf.atom.data->size = 0;
77 lv2_evbuf_reset(evbuf);
81 lv2_evbuf_reset(LV2_Evbuf* evbuf)
83 switch (evbuf->type) {
85 evbuf->buf.event.header_size = sizeof(LV2_Event_Buffer);
86 evbuf->buf.event.stamp_type = LV2_EVENT_AUDIO_STAMP;
87 evbuf->buf.event.event_count = 0;
88 evbuf->buf.event.size = 0;
91 evbuf->buf.atom.data->size = 0;
96 lv2_evbuf_get_size(LV2_Evbuf* evbuf)
98 switch (evbuf->type) {
100 return evbuf->buf.event.size;
102 return evbuf->buf.atom.data->size;
108 lv2_evbuf_get_buffer(LV2_Evbuf* evbuf)
110 switch (evbuf->type) {
111 case LV2_EVBUF_EVENT:
112 return &evbuf->buf.event;
114 return &evbuf->buf.atom;
120 lv2_evbuf_begin(LV2_Evbuf* evbuf)
122 LV2_Evbuf_Iterator iter = { evbuf, 0 };
127 lv2_evbuf_end(LV2_Evbuf* evbuf)
129 const size_t size = lv2_evbuf_get_size(evbuf);
130 const LV2_Evbuf_Iterator iter = { evbuf, lv2_evbuf_pad_size(size) };
135 lv2_evbuf_is_valid(LV2_Evbuf_Iterator iter)
137 return iter.offset < lv2_evbuf_get_size(iter.evbuf);
141 lv2_evbuf_next(LV2_Evbuf_Iterator iter)
143 if (!lv2_evbuf_is_valid(iter)) {
147 LV2_Evbuf* evbuf = iter.evbuf;
148 uint32_t offset = iter.offset;
150 switch (evbuf->type) {
151 case LV2_EVBUF_EVENT:
152 size = ((LV2_Event*)(evbuf->buf.event.data + offset))->size;
153 offset += lv2_evbuf_pad_size(sizeof(LV2_Event) + size);
156 size = ((LV2_Atom_Event*)
157 ((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, evbuf->buf.atom.data)
158 + offset))->body.size;
159 offset += lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
163 LV2_Evbuf_Iterator next = { evbuf, offset };
168 lv2_evbuf_get(LV2_Evbuf_Iterator iter,
175 *frames = *subframes = *type = *size = 0;
178 if (!lv2_evbuf_is_valid(iter)) {
182 LV2_Event_Buffer* ebuf;
184 LV2_Atom_Port_Buffer* abuf;
186 switch (iter.evbuf->type) {
187 case LV2_EVBUF_EVENT:
188 ebuf = &iter.evbuf->buf.event;
189 ev = (LV2_Event*)ebuf->data + iter.offset;
190 *frames = ev->frames;
191 *subframes = ev->subframes;
194 *data = (uint8_t*)ev + sizeof(LV2_Event);
197 abuf = &iter.evbuf->buf.atom;
198 aev = (LV2_Atom_Event*)(
199 (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, abuf->data)
201 *frames = aev->time.frames;
203 *type = aev->body.type;
204 *size = aev->body.size;
205 *data = LV2_ATOM_BODY(&aev->body);
213 lv2_evbuf_write(LV2_Evbuf_Iterator* iter,
220 LV2_Event_Buffer* ebuf;
222 LV2_Atom_Port_Buffer* abuf;
224 switch (iter->evbuf->type) {
225 case LV2_EVBUF_EVENT:
226 ebuf = &iter->evbuf->buf.event;
227 if (ebuf->capacity - ebuf->size < sizeof(LV2_Event) + size) {
231 ev = (LV2_Event*)(ebuf->data + iter->offset);
233 ev->subframes = subframes;
236 memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size);
238 size = lv2_evbuf_pad_size(sizeof(LV2_Event) + size);
240 ebuf->event_count += 1;
241 iter->offset += size;
244 abuf = &iter->evbuf->buf.atom;
245 if (abuf->capacity - abuf->data->size < sizeof(LV2_Atom_Event) + size) {
249 aev = (LV2_Atom_Event*)(
250 (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, abuf->data)
252 aev->time.frames = frames;
253 aev->body.type = type;
254 aev->body.size = size;
255 memcpy(LV2_ATOM_BODY(&aev->body), data, size);
257 size = lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
258 abuf->data->size += size;
259 iter->offset += size;