Loading...
Searching...
No Matches
lv2_atom_helpers.hpp
1// lv2_atom_helpers.h
2//
3/****************************************************************************
4 Copyright (C) 2005-2013, rncbc aka Rui Nuno Capela. All rights reserved.
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20*****************************************************************************/
21
22/* Helper functions for LV2 atom:Sequence event buffer.
23 *
24 * tentatively adapted from:
25 *
26 * - lv2_evbuf.h,c - An abstract/opaque LV2 event buffer implementation.
27 *
28 * - event-helpers.h - Helper functions for the LV2 Event extension.
29 * <http://lv2plug.in/ns/ext/event>
30 *
31 * Copyright 2008-2012 David Robillard <http://drobilla.net>
32 */
33
34#ifndef LV2_ATOM_HELPERS_H
35#define LV2_ATOM_HELPERS_H
36
37#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
38#include <lv2/lv2plug.in/ns/ext/atom/forge.h>
39#include <lv2/lv2plug.in/ns/ext/atom/util.h>
40
41#include <assert.h>
42#include <stdbool.h>
43#include <stdint.h>
44#include <stdlib.h>
45#include <string.h>
46
47#include <memory>
48
49// An abstract/opaque LV2 atom:Sequence buffer.
50//
52{
53 static uint32_t sequence_type;
54 static uint32_t chunk_type;
55
56 uint32_t capacity;
57 alignas(8) LV2_Atom_Sequence atoms;
58 LV2_Atom_Buffer(uint32_t capacity, uint32_t ct, uint32_t seq_type, bool input)
59 : capacity{capacity}
60 {
61 chunk_type = ct;
62 sequence_type = seq_type;
63 reset(input);
64 }
65
66 void reset(bool input)
67 {
68 if(input)
69 {
70 atoms.atom.size = sizeof(LV2_Atom_Sequence_Body);
71 atoms.atom.type = sequence_type;
72 }
73 else
74 {
75 atoms.atom.size = capacity;
76 atoms.atom.type = chunk_type;
77 }
78 }
79
80 // Return the total padded size of events stored in a LV2 atom:Sequence
81 // buffer.
82 //
83 uint32_t get_size()
84 {
85 if(atoms.atom.type == sequence_type)
86 return atoms.atom.size - sizeof(LV2_Atom_Sequence_Body);
87 else
88 return 0;
89 }
90
91 // Return the actual LV2 atom:Sequence implementation.
92 LV2_Atom_Sequence* get_sequence(LV2_Atom_Buffer* buf) { return &buf->atoms; }
93};
94
95static_assert(__builtin_offsetof(LV2_Atom_Buffer, atoms) == 8);
96// An iterator over an atom:Sequence buffer.
97//
99{
101 : buf{b}
102 {
103 }
104
105 LV2_Atom_Buffer* buf{};
106 uint32_t offset{};
107
108 // Pad a size to 64 bits (for LV2 atom:Sequence event sizes).
109 static uint32_t pad_size(uint32_t size) { return (size + 7) & (~7); }
110
111 // Reset an iterator to point to the start of an LV2 atom:Sequence buffer.
112 //
113 bool begin(LV2_Atom_Buffer* buf)
114 {
115 this->buf = buf;
116 offset = 0;
117
118 return (buf->atoms.atom.size > 0);
119 }
120
121 // Reset an iterator to point to the end of an LV2 atom:Sequence buffer.
122 //
123 bool end(LV2_Atom_Buffer* buf)
124 {
125 this->buf = buf;
126 offset = pad_size(buf->get_size());
127
128 return (offset < buf->capacity - sizeof(LV2_Atom_Event));
129 }
130
131 // Check if a LV2 atom:Sequenece buffer iterator is valid.
132 //
133 bool is_valid() { return offset < buf->get_size(); }
134
135 // Advance a LV2 atom:Sequenece buffer iterator forward one event.
136 //
137 bool increment()
138 {
139 if(!is_valid())
140 return false;
141
142 LV2_Atom_Sequence* atoms = &buf->atoms;
143 uint32_t size
144 = ((LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + offset))
145 ->body.size;
146 offset += pad_size(sizeof(LV2_Atom_Event) + size);
147
148 return true;
149 }
150
151 // Get the event currently pointed at a LV2 atom:Sequence buffer iterator.
152 //
153 LV2_Atom_Event* get(uint8_t** data)
154 {
155 if(!is_valid())
156 return NULL;
157
158 auto atoms = &buf->atoms;
159 auto ev
160 = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + offset);
161
162 *data = (uint8_t*)LV2_ATOM_BODY(&ev->body);
163
164 return ev;
165 }
166
167 // Write an event at a LV2 atom:Sequence buffer iterator.
168 bool write(
169 uint32_t frames, uint32_t /*subframes*/, uint32_t type, uint32_t size,
170 const uint8_t* data)
171 {
172 LV2_Atom_Sequence* atoms = &buf->atoms;
173 if(buf->capacity - sizeof(LV2_Atom) - atoms->atom.size
174 < sizeof(LV2_Atom_Event) + size)
175 return false;
176
177 LV2_Atom_Event* ev
178 = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + offset);
179
180 ev->time.frames = frames;
181 ev->body.type = type;
182 ev->body.size = size;
183
184 memcpy(LV2_ATOM_BODY(&ev->body), data, size);
185
186 size = pad_size(sizeof(LV2_Atom_Event) + size);
187 atoms->atom.size += size;
188 offset += size;
189
190 return true;
191 }
192};
193
195{
196 LV2_Atom_Buffer* buf{};
197 AtomBuffer(uint32_t capacity, uint32_t chunk_type, uint32_t seq_type, bool input)
198 {
199 // Note : isn't the second sizeof redundant ?
200 buf = (LV2_Atom_Buffer*)::operator new(
201 sizeof(LV2_Atom_Buffer) + sizeof(LV2_Atom_Sequence) + capacity);
202 new(buf) LV2_Atom_Buffer(capacity, chunk_type, seq_type, input);
203 }
204
205 AtomBuffer() = delete;
206 AtomBuffer(const AtomBuffer&) = default;
207 AtomBuffer(AtomBuffer&&) = default;
208 AtomBuffer& operator=(const AtomBuffer&) = default;
209 AtomBuffer& operator=(AtomBuffer&&) = default;
210 ~AtomBuffer() { ::operator delete(buf); }
211};
212
213#endif // LV2_ATOM_HELPERS_H
214
215// end of lv2_atom_helpers.h
Definition lv2_atom_helpers.hpp:195
Definition lv2_atom_helpers.hpp:99
Definition lv2_atom_helpers.hpp:52