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 
95 static_assert(__builtin_offsetof(LV2_Atom_Buffer, atoms) == 8);
96 // An iterator over an atom:Sequence buffer.
97 //
98 struct Iterator
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