Mercurial > hg > pub > prymula > com
comparison DPF-Prymula-audioplugins/dpf/distrho/src/lv2/event-helpers.h @ 3:84e66ea83026
DPF-Prymula-audioplugins-0.231015-2
author | prymula <prymula76@outlook.com> |
---|---|
date | Mon, 16 Oct 2023 21:53:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:cf2cb71d31dd | 3:84e66ea83026 |
---|---|
1 /* | |
2 Copyright 2008-2015 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 /** | |
18 @file event-helpers.h Helper functions for the LV2 Event extension | |
19 <http://lv2plug.in/ns/ext/event>. | |
20 */ | |
21 | |
22 #ifndef LV2_EVENT_HELPERS_H | |
23 #define LV2_EVENT_HELPERS_H | |
24 | |
25 #include <stdint.h> | |
26 #include <stdlib.h> | |
27 #include <string.h> | |
28 | |
29 #include "event.h" | |
30 | |
31 #ifdef __cplusplus | |
32 extern "C" { | |
33 #else | |
34 # include <stdbool.h> | |
35 #endif | |
36 | |
37 /** @file | |
38 * Helper functions for the LV2 Event extension | |
39 * <http://lv2plug.in/ns/ext/event>. | |
40 * | |
41 * These functions are provided for convenience only, use of them is not | |
42 * required for supporting lv2ev (i.e. the events extension is defined by the | |
43 * raw buffer format described in lv2_event.h and NOT by this API). | |
44 * | |
45 * Note that these functions are all static inline which basically means: | |
46 * do not take the address of these functions. */ | |
47 | |
48 | |
49 /** Pad a size to 64 bits (for event sizes) */ | |
50 static inline uint16_t | |
51 lv2_event_pad_size(uint16_t size) | |
52 { | |
53 return (uint16_t)(size + 7U) & (uint16_t)(~7U); | |
54 } | |
55 | |
56 | |
57 /** Initialize (empty, reset..) an existing event buffer. | |
58 * The contents of buf are ignored entirely and overwritten, except capacity | |
59 * which is unmodified. */ | |
60 static inline void | |
61 lv2_event_buffer_reset(LV2_Event_Buffer* buf, | |
62 uint16_t stamp_type, | |
63 uint8_t* data) | |
64 { | |
65 buf->data = data; | |
66 buf->header_size = sizeof(LV2_Event_Buffer); | |
67 buf->stamp_type = stamp_type; | |
68 buf->event_count = 0; | |
69 buf->size = 0; | |
70 } | |
71 | |
72 | |
73 /** Allocate a new, empty event buffer. */ | |
74 static inline LV2_Event_Buffer* | |
75 lv2_event_buffer_new(uint32_t capacity, uint16_t stamp_type) | |
76 { | |
77 const size_t size = sizeof(LV2_Event_Buffer) + capacity; | |
78 LV2_Event_Buffer* buf = (LV2_Event_Buffer*)malloc(size); | |
79 if (buf != NULL) { | |
80 buf->capacity = capacity; | |
81 lv2_event_buffer_reset(buf, stamp_type, (uint8_t *)(buf + 1)); | |
82 return buf; | |
83 } else { | |
84 return NULL; | |
85 } | |
86 } | |
87 | |
88 | |
89 /** An iterator over an LV2_Event_Buffer. | |
90 * | |
91 * Multiple simultaneous read iterators over a single buffer is fine, | |
92 * but changing the buffer invalidates all iterators (e.g. RW Lock). */ | |
93 typedef struct { | |
94 LV2_Event_Buffer* buf; | |
95 uint32_t offset; | |
96 } LV2_Event_Iterator; | |
97 | |
98 | |
99 /** Reset an iterator to point to the start of `buf`. | |
100 * @return True if `iter` is valid, otherwise false (buffer is empty) */ | |
101 static inline bool | |
102 lv2_event_begin(LV2_Event_Iterator* iter, | |
103 LV2_Event_Buffer* buf) | |
104 { | |
105 iter->buf = buf; | |
106 iter->offset = 0; | |
107 return (buf->size > 0); | |
108 } | |
109 | |
110 | |
111 /** Check if `iter` is valid. | |
112 * @return True if `iter` is valid, otherwise false (past end of buffer) */ | |
113 static inline bool | |
114 lv2_event_is_valid(LV2_Event_Iterator* iter) | |
115 { | |
116 return (iter->buf && (iter->offset < iter->buf->size)); | |
117 } | |
118 | |
119 | |
120 /** Advance `iter` forward one event. | |
121 * `iter` must be valid. | |
122 * @return True if `iter` is valid, otherwise false (reached end of buffer) */ | |
123 static inline bool | |
124 lv2_event_increment(LV2_Event_Iterator* iter) | |
125 { | |
126 if (!lv2_event_is_valid(iter)) { | |
127 return false; | |
128 } | |
129 | |
130 LV2_Event* const ev = (LV2_Event*)( | |
131 (uint8_t*)iter->buf->data + iter->offset); | |
132 | |
133 iter->offset += lv2_event_pad_size( | |
134 (uint16_t)((uint16_t)sizeof(LV2_Event) + ev->size)); | |
135 | |
136 return true; | |
137 } | |
138 | |
139 | |
140 /** Dereference an event iterator (get the event currently pointed at). | |
141 * `iter` must be valid. | |
142 * `data` if non-NULL, will be set to point to the contents of the event | |
143 * returned. | |
144 * @return A Pointer to the event `iter` is currently pointing at, or NULL | |
145 * if the end of the buffer is reached (in which case `data` is | |
146 * also set to NULL). */ | |
147 static inline LV2_Event* | |
148 lv2_event_get(LV2_Event_Iterator* iter, | |
149 uint8_t** data) | |
150 { | |
151 if (!lv2_event_is_valid(iter)) { | |
152 return NULL; | |
153 } | |
154 | |
155 LV2_Event* const ev = (LV2_Event*)( | |
156 (uint8_t*)iter->buf->data + iter->offset); | |
157 | |
158 if (data) | |
159 *data = (uint8_t*)ev + sizeof(LV2_Event); | |
160 | |
161 return ev; | |
162 } | |
163 | |
164 | |
165 /** Write an event at `iter`. | |
166 * The event (if any) pointed to by `iter` will be overwritten, and `iter` | |
167 * incremented to point to the following event (i.e. several calls to this | |
168 * function can be done in sequence without twiddling iter in-between). | |
169 * @return True if event was written, otherwise false (buffer is full). */ | |
170 static inline bool | |
171 lv2_event_write(LV2_Event_Iterator* iter, | |
172 uint32_t frames, | |
173 uint32_t subframes, | |
174 uint16_t type, | |
175 uint16_t size, | |
176 const uint8_t* data) | |
177 { | |
178 if (!iter->buf) | |
179 return false; | |
180 | |
181 if (iter->buf->capacity - iter->buf->size < sizeof(LV2_Event) + size) | |
182 return false; | |
183 | |
184 LV2_Event* const ev = (LV2_Event*)( | |
185 (uint8_t*)iter->buf->data + iter->offset); | |
186 | |
187 ev->frames = frames; | |
188 ev->subframes = subframes; | |
189 ev->type = type; | |
190 ev->size = size; | |
191 memcpy((uint8_t*)ev + sizeof(LV2_Event), data, size); | |
192 ++iter->buf->event_count; | |
193 | |
194 size = lv2_event_pad_size((uint16_t)(sizeof(LV2_Event) + size)); | |
195 iter->buf->size += size; | |
196 iter->offset += size; | |
197 | |
198 return true; | |
199 } | |
200 | |
201 | |
202 /** Reserve space for an event in the buffer and return a pointer to | |
203 the memory where the caller can write the event data, or NULL if there | |
204 is not enough room in the buffer. */ | |
205 static inline uint8_t* | |
206 lv2_event_reserve(LV2_Event_Iterator* iter, | |
207 uint32_t frames, | |
208 uint32_t subframes, | |
209 uint16_t type, | |
210 uint16_t size) | |
211 { | |
212 const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + size); | |
213 if (iter->buf->capacity - iter->buf->size < total_size) | |
214 return NULL; | |
215 | |
216 LV2_Event* const ev = (LV2_Event*)( | |
217 (uint8_t*)iter->buf->data + iter->offset); | |
218 | |
219 ev->frames = frames; | |
220 ev->subframes = subframes; | |
221 ev->type = type; | |
222 ev->size = size; | |
223 ++iter->buf->event_count; | |
224 | |
225 const uint16_t padded_size = lv2_event_pad_size(total_size); | |
226 iter->buf->size += padded_size; | |
227 iter->offset += padded_size; | |
228 | |
229 return (uint8_t*)ev + sizeof(LV2_Event); | |
230 } | |
231 | |
232 | |
233 /** Write an event at `iter`. | |
234 * The event (if any) pointed to by `iter` will be overwritten, and `iter` | |
235 * incremented to point to the following event (i.e. several calls to this | |
236 * function can be done in sequence without twiddling iter in-between). | |
237 * @return True if event was written, otherwise false (buffer is full). */ | |
238 static inline bool | |
239 lv2_event_write_event(LV2_Event_Iterator* iter, | |
240 const LV2_Event* ev, | |
241 const uint8_t* data) | |
242 { | |
243 const uint16_t total_size = (uint16_t)(sizeof(LV2_Event) + ev->size); | |
244 if (iter->buf->capacity - iter->buf->size < total_size) | |
245 return false; | |
246 | |
247 LV2_Event* const write_ev = (LV2_Event*)( | |
248 (uint8_t*)iter->buf->data + iter->offset); | |
249 | |
250 *write_ev = *ev; | |
251 memcpy((uint8_t*)write_ev + sizeof(LV2_Event), data, ev->size); | |
252 ++iter->buf->event_count; | |
253 | |
254 const uint16_t padded_size = lv2_event_pad_size(total_size); | |
255 iter->buf->size += padded_size; | |
256 iter->offset += padded_size; | |
257 | |
258 return true; | |
259 } | |
260 | |
261 #ifdef __cplusplus | |
262 } /* extern "C" */ | |
263 #endif | |
264 | |
265 #endif /* LV2_EVENT_HELPERS_H */ |