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