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 <score_plugin_lv2_export.h>
38
39#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
40#include <lv2/lv2plug.in/ns/ext/atom/forge.h>
41#include <lv2/lv2plug.in/ns/ext/atom/util.h>
42
43#include <assert.h>
44#include <stdbool.h>
45#include <stdint.h>
46#include <stdlib.h>
47#include <string.h>
48
49#include <memory>
50
51// An abstract/opaque LV2 atom:Sequence buffer.
52//
54{
55 SCORE_PLUGIN_LV2_EXPORT static uint32_t sequence_type;
56 SCORE_PLUGIN_LV2_EXPORT static uint32_t chunk_type;
57
58 uint32_t capacity;
59 alignas(8) LV2_Atom_Sequence atoms;
60 LV2_Atom_Buffer(uint32_t capacity, uint32_t ct, uint32_t seq_type, bool input)
61 : capacity{capacity}
62 {
63 chunk_type = ct;
64 sequence_type = seq_type;
65 reset(input);
66 }
67
68 void reset(bool input)
69 {
70 if(input)
71 {
72 atoms.atom.size = sizeof(LV2_Atom_Sequence_Body);
73 atoms.atom.type = sequence_type;
74 }
75 else
76 {
77 atoms.atom.size = capacity;
78 atoms.atom.type = chunk_type;
79 }
80 }
81
82 // Return the total padded size of events stored in a LV2 atom:Sequence
83 // buffer.
84 //
85 uint32_t get_size()
86 {
87 if(atoms.atom.type == sequence_type)
88 return atoms.atom.size - sizeof(LV2_Atom_Sequence_Body);
89 else
90 return 0;
91 }
92
93 // Return the actual LV2 atom:Sequence implementation.
94 LV2_Atom_Sequence* get_sequence(LV2_Atom_Buffer* buf) { return &buf->atoms; }
95};
96
97static_assert(__builtin_offsetof(LV2_Atom_Buffer, atoms) == 8);
98// An iterator over an atom:Sequence buffer.
99//
101{
103 : buf{b}
104 {
105 }
106
107 LV2_Atom_Buffer* buf{};
108 uint32_t offset{};
109
110 // Pad a size to 64 bits (for LV2 atom:Sequence event sizes).
111 static uint32_t pad_size(uint32_t size) { return (size + 7) & (~7); }
112
113 // Reset an iterator to point to the start of an LV2 atom:Sequence buffer.
114 //
115 bool begin(LV2_Atom_Buffer* buf)
116 {
117 this->buf = buf;
118 offset = 0;
119
120 return (buf->atoms.atom.size > 0);
121 }
122
123 // Reset an iterator to point to the end of an LV2 atom:Sequence buffer.
124 //
125 bool end(LV2_Atom_Buffer* buf)
126 {
127 this->buf = buf;
128 offset = pad_size(buf->get_size());
129
130 return (offset < buf->capacity - sizeof(LV2_Atom_Event));
131 }
132
133 // Check if a LV2 atom:Sequenece buffer iterator is valid.
134 //
135 bool is_valid() { return offset < buf->get_size(); }
136
137 // Advance a LV2 atom:Sequenece buffer iterator forward one event.
138 //
139 bool increment()
140 {
141 if(!is_valid())
142 return false;
143
144 LV2_Atom_Sequence* atoms = &buf->atoms;
145 uint32_t size
146 = ((LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + offset))
147 ->body.size;
148 offset += pad_size(sizeof(LV2_Atom_Event) + size);
149
150 return true;
151 }
152
153 // Get the event currently pointed at a LV2 atom:Sequence buffer iterator.
154 //
155 LV2_Atom_Event* get(uint8_t** data)
156 {
157 if(!is_valid())
158 return NULL;
159
160 auto atoms = &buf->atoms;
161 auto ev
162 = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + offset);
163
164 *data = (uint8_t*)LV2_ATOM_BODY(&ev->body);
165
166 return ev;
167 }
168
169 // Write an event at a LV2 atom:Sequence buffer iterator.
170 bool write(
171 uint32_t frames, uint32_t /*subframes*/, uint32_t type, uint32_t size,
172 const uint8_t* data)
173 {
174 LV2_Atom_Sequence* atoms = &buf->atoms;
175 if(buf->capacity - sizeof(LV2_Atom) - atoms->atom.size
176 < sizeof(LV2_Atom_Event) + size)
177 return false;
178
179 LV2_Atom_Event* ev
180 = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atoms) + offset);
181
182 ev->time.frames = frames;
183 ev->body.type = type;
184 ev->body.size = size;
185
186 memcpy(LV2_ATOM_BODY(&ev->body), data, size);
187
188 size = pad_size(sizeof(LV2_Atom_Event) + size);
189 atoms->atom.size += size;
190 offset += size;
191
192 return true;
193 }
194};
195
197{
198 LV2_Atom_Buffer* buf{};
199 AtomBuffer(uint32_t capacity, uint32_t chunk_type, uint32_t seq_type, bool input)
200 {
201 // Note : isn't the second sizeof redundant ?
202 buf = (LV2_Atom_Buffer*)::operator new(
203 sizeof(LV2_Atom_Buffer) + sizeof(LV2_Atom_Sequence) + capacity);
204 new(buf) LV2_Atom_Buffer(capacity, chunk_type, seq_type, input);
205 }
206
207 AtomBuffer() = delete;
208 AtomBuffer(const AtomBuffer&) = delete;
209 AtomBuffer& operator=(const AtomBuffer&) = delete;
210 AtomBuffer(AtomBuffer&& other) noexcept
211 : buf{other.buf}
212 {
213 other.buf = nullptr;
214 }
215 AtomBuffer& operator=(AtomBuffer&& other) noexcept
216 {
217 if(this != &other)
218 {
219 ::operator delete(buf);
220 buf = other.buf;
221 other.buf = nullptr;
222 }
223 return *this;
224 }
225 ~AtomBuffer() { ::operator delete(buf); }
226};
227
228#endif // LV2_ATOM_HELPERS_H
229
230// end of lv2_atom_helpers.h
Definition lv2_atom_helpers.hpp:197
Definition lv2_atom_helpers.hpp:101
Definition lv2_atom_helpers.hpp:54