Update to latest LV2 atom extension.
[ardour.git] / libs / ardour / lv2_evbuf.c
1 /*
2   Copyright 2008-2012 David Robillard <http://drobilla.net>
3
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.
7
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.
15 */
16
17 #include <string.h>
18 #include <stdlib.h>
19
20 #include "lv2/lv2plug.in/ns/ext/atom/atom.h"
21 #include "lv2/lv2plug.in/ns/ext/event/event.h"
22
23 #include "lv2_evbuf.h"
24
25 struct LV2_Evbuf_Impl {
26         LV2_Evbuf_Type type;
27         uint32_t       capacity;
28         uint32_t       atom_Chunk;
29         uint32_t       atom_Sequence;
30         union {
31                 LV2_Event_Buffer  event;
32                 LV2_Atom_Sequence atom;
33         } buf;
34 };
35
36 static inline uint32_t
37 lv2_evbuf_pad_size(uint32_t size)
38 {
39         return (size + 7) & (~7);
40 }
41
42 LV2_Evbuf*
43 lv2_evbuf_new(uint32_t       capacity,
44               LV2_Evbuf_Type type,
45               uint32_t       atom_Chunk,
46               uint32_t       atom_Sequence)
47 {
48         // FIXME: memory must be 64-bit aligned
49         LV2_Evbuf* evbuf = (LV2_Evbuf*)malloc(
50                 sizeof(LV2_Evbuf) + sizeof(LV2_Atom_Sequence) + capacity);
51         evbuf->capacity      = capacity;
52         evbuf->atom_Chunk    = atom_Chunk;
53         evbuf->atom_Sequence = atom_Sequence;
54         lv2_evbuf_set_type(evbuf, type);
55         lv2_evbuf_reset(evbuf, true);
56         return evbuf;
57 }
58
59 void
60 lv2_evbuf_free(LV2_Evbuf* evbuf)
61 {
62         free(evbuf);
63 }
64
65 void
66 lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type)
67 {
68         evbuf->type = type;
69         switch (type) {
70         case LV2_EVBUF_EVENT:
71                 evbuf->buf.event.data     = (uint8_t*)(evbuf + 1);
72                 evbuf->buf.event.capacity = evbuf->capacity;
73                 break;
74         case LV2_EVBUF_ATOM:
75                 break;
76         }
77         lv2_evbuf_reset(evbuf, true);
78 }
79
80 void
81 lv2_evbuf_reset(LV2_Evbuf* evbuf, bool input)
82 {
83         switch (evbuf->type) {
84         case LV2_EVBUF_EVENT:
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;
89                 break;
90         case LV2_EVBUF_ATOM:
91                 if (input) {
92                         evbuf->buf.atom.atom.size = 0;
93                         evbuf->buf.atom.atom.type = evbuf->atom_Sequence;
94                 } else {
95                         evbuf->buf.atom.atom.size = evbuf->capacity;
96                         evbuf->buf.atom.atom.type = evbuf->atom_Chunk;
97                 }
98         }
99 }
100
101 uint32_t
102 lv2_evbuf_get_size(LV2_Evbuf* evbuf)
103 {
104         switch (evbuf->type) {
105         case LV2_EVBUF_EVENT:
106                 return evbuf->buf.event.size;
107         case LV2_EVBUF_ATOM:
108                 return evbuf->buf.atom.atom.type == evbuf->atom_Sequence
109                         ? evbuf->buf.atom.atom.size
110                         : 0;
111         }
112         return 0;
113 }
114
115 void*
116 lv2_evbuf_get_buffer(LV2_Evbuf* evbuf)
117 {
118         switch (evbuf->type) {
119         case LV2_EVBUF_EVENT:
120                 return &evbuf->buf.event;
121         case LV2_EVBUF_ATOM:
122                 return &evbuf->buf.atom;
123         }
124         return NULL;
125 }
126
127 LV2_Evbuf_Iterator
128 lv2_evbuf_begin(LV2_Evbuf* evbuf)
129 {
130         LV2_Evbuf_Iterator iter = { evbuf, 0 };
131         return iter;
132 }
133
134 LV2_Evbuf_Iterator
135 lv2_evbuf_end(LV2_Evbuf* evbuf)
136 {
137         const size_t             size = lv2_evbuf_get_size(evbuf);
138         const LV2_Evbuf_Iterator iter = { evbuf, lv2_evbuf_pad_size(size) };
139         return iter;
140 }
141
142 bool
143 lv2_evbuf_is_valid(LV2_Evbuf_Iterator iter)
144 {
145         return iter.offset < lv2_evbuf_get_size(iter.evbuf);
146 }
147
148 LV2_Evbuf_Iterator
149 lv2_evbuf_next(LV2_Evbuf_Iterator iter)
150 {
151         if (!lv2_evbuf_is_valid(iter)) {
152                 return iter;
153         }
154
155         LV2_Evbuf* evbuf  = iter.evbuf;
156         uint32_t   offset = iter.offset;
157         uint32_t   size;
158         switch (evbuf->type) {
159         case LV2_EVBUF_EVENT:
160                 size    = ((LV2_Event*)(evbuf->buf.event.data + offset))->size;
161                 offset += lv2_evbuf_pad_size(sizeof(LV2_Event) + size);
162                 break;
163         case LV2_EVBUF_ATOM:
164                 size = ((LV2_Atom_Event*)
165                         ((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, &evbuf->buf.atom)
166                          + offset))->body.size;
167                 offset += lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
168                 break;
169         }
170
171         LV2_Evbuf_Iterator next = { evbuf, offset };
172         return next;
173 }
174
175 bool
176 lv2_evbuf_get(LV2_Evbuf_Iterator iter,
177               uint32_t*          frames,
178               uint32_t*          subframes,
179               uint32_t*          type,
180               uint32_t*          size,
181               uint8_t**          data)
182 {
183         *frames = *subframes = *type = *size = 0;
184         *data = NULL;
185
186         if (!lv2_evbuf_is_valid(iter)) {
187                 return false;
188         }
189
190         LV2_Event_Buffer*  ebuf;
191         LV2_Event*         ev;
192         LV2_Atom_Sequence* aseq;
193         LV2_Atom_Event*    aev;
194         switch (iter.evbuf->type) {
195         case LV2_EVBUF_EVENT:
196                 ebuf = &iter.evbuf->buf.event;
197                 ev = (LV2_Event*)ebuf->data + iter.offset;
198                 *frames    = ev->frames;
199                 *subframes = ev->subframes;
200                 *type      = ev->type;
201                 *size      = ev->size;
202                 *data      = (uint8_t*)ev + sizeof(LV2_Event);
203                 break;
204         case LV2_EVBUF_ATOM:
205                 aseq = (LV2_Atom_Sequence*)&iter.evbuf->buf.atom;
206                 aev = (LV2_Atom_Event*)(
207                         (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq)
208                         + iter.offset);
209                 *frames    = aev->time.frames;
210                 *subframes = 0;
211                 *type      = aev->body.type;
212                 *size      = aev->body.size;
213                 *data      = LV2_ATOM_BODY(&aev->body);
214                 break;
215         }
216
217         return true;
218 }
219
220 bool
221 lv2_evbuf_write(LV2_Evbuf_Iterator* iter,
222                 uint32_t            frames,
223                 uint32_t            subframes,
224                 uint32_t            type,
225                 uint32_t            size,
226                 const uint8_t*      data)
227 {
228         LV2_Event_Buffer*  ebuf;
229         LV2_Event*         ev;
230         LV2_Atom_Sequence* aseq;
231         LV2_Atom_Event*    aev;
232         switch (iter->evbuf->type) {
233         case LV2_EVBUF_EVENT:
234                 ebuf = &iter->evbuf->buf.event;
235                 if (ebuf->capacity - ebuf->size < sizeof(LV2_Event) + size) {
236                         return false;
237                 }
238
239                 ev = (LV2_Event*)(ebuf->data + iter->offset);
240                 ev->frames    = frames;
241                 ev->subframes = subframes;
242                 ev->type      = type;
243                 ev->size      = size;
244                 memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size);
245
246                 size               = lv2_evbuf_pad_size(sizeof(LV2_Event) + size);
247                 ebuf->size        += size;
248                 ebuf->event_count += 1;
249                 iter->offset      += size;
250                 break;
251         case LV2_EVBUF_ATOM:
252                 aseq = (LV2_Atom_Sequence*)&iter->evbuf->buf.atom;
253                 if (iter->evbuf->capacity - sizeof(LV2_Atom) - aseq->atom.size
254                     < sizeof(LV2_Atom_Event) + size) {
255                         return false;
256                 }
257
258                 aev = (LV2_Atom_Event*)(
259                         (char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, aseq)
260                         + iter->offset);
261                 aev->time.frames = frames;
262                 aev->body.type   = type;
263                 aev->body.size   = size;
264                 memcpy(LV2_ATOM_BODY(&aev->body), data, size);
265
266                 size             = lv2_evbuf_pad_size(sizeof(LV2_Atom_Event) + size);
267                 aseq->atom.size += size;
268                 iter->offset    += size;
269                 break;
270         }
271
272         return true;
273 }