+ Filter: implement drawing optimization
[calf.git] / src / calf / lv2helpers.h
blobeb4d39ebf19c0ba140870130217c631ab3aedc0b
1 /* Calf DSP Library
2 * LV2-related helper classes and functions
4 * Copyright (C) 2001-2008 Krzysztof Foltman
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General
17 * Public License along with this program; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19 * Boston, MA 02111-1307, USA.
21 #ifndef CALF_LV2HELPERS_H
22 #define CALF_LV2HELPERS_H
24 #if USE_LV2
26 #include <calf/lv2_event.h>
27 #include <calf/lv2_uri_map.h>
29 class uri_map_access
31 public:
32 /// URI map feature pointer (previously in a mixin, but polymorphic ports made it necessary for most plugins)
33 LV2_URI_Map_Feature *uri_map;
35 uri_map_access()
36 : uri_map(NULL)
39 /// Map an URI through an URI map
40 uint32_t map_uri(const char *ns, const char *URI)
42 if (uri_map)
43 return uri_map->uri_to_id(uri_map->callback_data, ns, URI);
44 return 0;
46 /// Called on instantiation for every LV2 feature sent by a host
47 void use_feature(const char *URI, void *data) {
48 if (!strcmp(URI, LV2_URI_MAP_URI))
50 uri_map = (LV2_URI_Map_Feature *)data;
51 map_uris();
54 virtual void map_uris()
57 virtual ~uri_map_access() {}
60 /// A mixin for adding the event feature and URI map to the small plugin
61 template<class T>
62 class event_mixin: public T
64 public:
65 /// Event feature pointer
66 LV2_Event_Feature *event_feature;
67 virtual void use_feature(const char *URI, void *data) {
68 if (!strcmp(URI, LV2_EVENT_URI))
70 event_feature = (LV2_Event_Feature *)data;
72 T::use_feature(URI, data);
74 /// Create a reference
75 inline void ref_event(LV2_Event *event) { event_feature->lv2_event_ref(event_feature->callback_data, event); }
76 /// Destroy a reference
77 inline void unref_event(LV2_Event *event) { event_feature->lv2_event_unref(event_feature->callback_data, event); }
80 /// A mixin for adding the URI map and MIDI event type retrieval to small plugins
81 template<class T>
82 class midi_mixin: public virtual event_mixin<T>
84 public:
85 /// MIDI event ID, as resolved using the URI map feature
86 uint32_t midi_event_type;
87 virtual void map_uris() {
88 midi_event_type = this->map_uri("http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/ext/midi#MidiEvent");
89 printf("MIDI event type = %d\n", midi_event_type);
90 event_mixin<T>::map_uris();
94 /// A mixin for adding the URI map and MIDI event type retrieval to small plugins
95 template<class T>
96 class message_mixin: public virtual event_mixin<T>
98 public:
99 /// MIDI event ID, as resolved using the URI map feature
100 uint32_t message_event_type;
101 virtual void map_uris() {
102 message_event_type = this->map_uri("http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/dev/msg#MessageEvent");
103 printf("Message event type = %d\n", message_event_type);
104 event_mixin<T>::map_uris();
108 /// LV2 event structure + payload as 0-length array for easy access
109 struct lv2_event: public LV2_Event
111 uint8_t data[];
112 inline lv2_event &operator=(const lv2_event &src) {
113 *(LV2_Event *)this = (const LV2_Event &)src;
114 memcpy(data, src.data, src.size);
115 return *this;
117 /// Returns a 64-bit timestamp for easy and inefficient comparison
118 inline uint64_t timestamp() const {
119 return ((uint64_t)frames << 32) | subframes;
121 private:
122 /// forbid default constructor - this object cannot be constructed, only obtained via cast from LV2_Event* (or &) to lv2_event* (or &)
123 lv2_event() {}
124 /// forbid copy constructor - see default constructor
125 lv2_event(const lv2_event &) {}
128 /// A read-only iterator-like object for reading from event buffers
129 class event_port_read_iterator
131 protected:
132 const LV2_Event_Buffer *buffer;
133 uint32_t offset;
134 public:
135 /// Default constructor creating a useless iterator you can assign to
136 event_port_read_iterator()
137 : buffer(NULL)
138 , offset(0)
142 /// Create an iterator based on specified buffer and index/offset values
143 event_port_read_iterator(const LV2_Event_Buffer *_buffer, uint32_t _offset = 0)
144 : buffer(_buffer)
145 , offset(0)
149 /// Are any data left to be read?
150 inline operator bool() const {
151 return offset < buffer->size;
154 /// Read pointer
155 inline const lv2_event &operator*() const {
156 return *(const lv2_event *)(buffer->data + offset);
158 /// Pointer to member
159 inline const lv2_event *operator->() const {
160 return &**this;
163 /// Move to the next element
164 inline event_port_read_iterator operator++() {
165 offset += ((**this).size + 19) &~7;
166 return *this;
169 /// Move to the next element
170 inline event_port_read_iterator operator++(int) {
171 event_port_read_iterator old = *this;
172 offset += ((**this).size + 19) &~7;
173 return old;
177 /// A write-only iterator-like object for writing to event buffers
178 class event_port_write_iterator
180 protected:
181 LV2_Event_Buffer *buffer;
182 public:
183 /// Default constructor creating a useless iterator you can assign to
184 event_port_write_iterator()
185 : buffer(NULL)
189 /// Create a write iterator based on specified buffer and index/offset values
190 event_port_write_iterator(LV2_Event_Buffer *_buffer)
191 : buffer(_buffer)
195 /// @return the remaining buffer space
196 inline uint32_t space_left() const {
197 return buffer->capacity - buffer->size;
199 /// @return write pointer
200 inline lv2_event &operator*() {
201 return *(lv2_event *)(buffer->data + buffer->size);
203 /// Pointer to member
204 inline lv2_event *operator->() {
205 return &**this;
207 /// Move to the next element after the current one has been written (must be called after each write)
208 inline event_port_write_iterator operator++() {
209 buffer->size += ((**this).size + 19) &~7;
210 buffer->event_count ++;
211 return *this;
213 /// Move to the next element after the current one has been written
214 inline lv2_event *operator++(int) {
215 lv2_event *ptr = &**this;
216 buffer->size += ((**this).size + 19) &~7;
217 buffer->event_count ++;
218 return ptr;
222 template<class Iter1, class Iter2>
223 class event_port_merge_iterator
225 public:
226 Iter1 first;
227 Iter2 second;
228 public:
229 event_port_merge_iterator() {}
230 event_port_merge_iterator(const Iter1 &_first, const Iter2 &_second)
231 : first(_first)
232 , second(_second)
235 /// @retval true if any of the iterators have any data left
236 inline operator bool() const {
237 return ((bool)first) || ((bool)second);
239 inline bool select_first() const
241 if (!(bool)second)
242 return true;
243 if (!(bool)first)
244 return false;
245 return first->timestamp() < second->timestamp();
247 /// Returns the earliest of (*first, *second)
248 inline const lv2_event &operator*() const {
249 if (select_first())
251 assert((bool)first);
252 return *first;
254 assert((bool)second);
255 return *second;
257 /// Pointer to member
258 inline const lv2_event *operator->() const {
259 return &**this;
261 /// Prefix increment
262 inline event_port_merge_iterator operator++() {
263 if (select_first())
264 first++;
265 else
266 second++;
267 return *this;
269 /// Postfix increment
270 inline event_port_merge_iterator operator++(int) {
271 event_port_merge_iterator ptr = *this;
272 if (select_first())
273 first++;
274 else
275 second++;
276 return ptr;
280 #endif
281 #endif