~ubuntu-branches/ubuntu/utopic/ardour3/utopic

« back to all changes in this revision

Viewing changes to libs/ardour/lv2_evbuf.c

  • Committer: Package Import Robot
  • Author(s): Felipe Sateler
  • Date: 2013-09-21 19:05:02 UTC
  • Revision ID: package-import@ubuntu.com-20130921190502-8gsftrku6jnzhd7v
Tags: upstream-3.4~dfsg
ImportĀ upstreamĀ versionĀ 3.4~dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
26
struct LV2_Evbuf_Impl {
 
27
        LV2_Evbuf_Type type;
 
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
 
61
lv2_evbuf_free(LV2_Evbuf* evbuf)
 
62
{
 
63
        free(evbuf);
 
64
}
 
65
 
 
66
void
 
67
lv2_evbuf_set_type(LV2_Evbuf* evbuf, LV2_Evbuf_Type type)
 
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
 
103
lv2_evbuf_get_size(LV2_Evbuf* evbuf)
 
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
 
119
lv2_evbuf_get_capacity(LV2_Evbuf* evbuf)
 
120
{
 
121
        return evbuf->capacity;
 
122
}
 
123
 
 
124
void*
 
125
lv2_evbuf_get_buffer(LV2_Evbuf* evbuf)
 
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
 
 
136
LV2_Evbuf_Iterator
 
137
lv2_evbuf_begin(LV2_Evbuf* evbuf)
 
138
{
 
139
        LV2_Evbuf_Iterator iter = { evbuf, 0 };
 
140
        return iter;
 
141
}
 
142
 
 
143
LV2_Evbuf_Iterator
 
144
lv2_evbuf_end(LV2_Evbuf* evbuf)
 
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
 
152
lv2_evbuf_is_valid(LV2_Evbuf_Iterator iter)
 
153
{
 
154
        return iter.offset < lv2_evbuf_get_size(iter.evbuf);
 
155
}
 
156
 
 
157
LV2_Evbuf_Iterator
 
158
lv2_evbuf_next(LV2_Evbuf_Iterator iter)
 
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*)(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*)
 
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
 
185
lv2_evbuf_get(LV2_Evbuf_Iterator iter,
 
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*)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*)(
 
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      = LV2_ATOM_BODY(&aev->body);
 
223
                break;
 
224
        }
 
225
 
 
226
        return true;
 
227
}
 
228
 
 
229
bool
 
230
lv2_evbuf_write(LV2_Evbuf_Iterator* iter,
 
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*)(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*)(
 
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
}