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
26 #include <calf/lv2_event.h>
27 #include <calf/lv2_uri_map.h>
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
;
39 /// Map an URI through an URI map
40 uint32_t map_uri(const char *ns
, const char *URI
)
43 return uri_map
->uri_to_id(uri_map
->callback_data
, ns
, URI
);
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
;
54 virtual void map_uris()
59 /// A mixin for adding the event feature and URI map to the small plugin
61 class event_mixin
: public T
64 /// Event feature pointer
65 LV2_Event_Feature
*event_feature
;
66 virtual void use_feature(const char *URI
, void *data
) {
67 if (!strcmp(URI
, LV2_EVENT_URI
))
69 event_feature
= (LV2_Event_Feature
*)data
;
71 T::use_feature(URI
, data
);
73 /// Create a reference
74 inline void ref_event(LV2_Event
*event
) { event_feature
->lv2_event_ref(event_feature
->callback_data
, event
); }
75 /// Destroy a reference
76 inline void unref_event(LV2_Event
*event
) { event_feature
->lv2_event_unref(event_feature
->callback_data
, event
); }
79 /// A mixin for adding the URI map and MIDI event type retrieval to small plugins
81 class midi_mixin
: public virtual event_mixin
<T
>
84 /// MIDI event ID, as resolved using the URI map feature
85 uint32_t midi_event_type
;
86 virtual void map_uris() {
87 midi_event_type
= this->map_uri("http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/ext/midi#MidiEvent");
88 printf("MIDI event type = %d\n", midi_event_type
);
89 event_mixin
<T
>::map_uris();
93 /// A mixin for adding the URI map and MIDI event type retrieval to small plugins
95 class message_mixin
: public virtual event_mixin
<T
>
98 /// MIDI event ID, as resolved using the URI map feature
99 uint32_t message_event_type
;
100 virtual void map_uris() {
101 message_event_type
= this->map_uri("http://lv2plug.in/ns/ext/event", "http://lv2plug.in/ns/dev/msg#MessageEvent");
102 printf("Message event type = %d\n", message_event_type
);
103 event_mixin
<T
>::map_uris();
107 /// LV2 event structure + payload as 0-length array for easy access
108 struct lv2_event
: public LV2_Event
111 inline lv2_event
&operator=(const lv2_event
&src
) {
112 *(LV2_Event
*)this = (const LV2_Event
&)src
;
113 memcpy(data
, src
.data
, src
.size
);
116 /// Returns a 64-bit timestamp for easy and inefficient comparison
117 inline uint64_t timestamp() const {
118 return ((uint64_t)frames
<< 32) | subframes
;
121 /// forbid default constructor - this object cannot be constructed, only obtained via cast from LV2_Event* (or &) to lv2_event* (or &)
123 /// forbid copy constructor - see default constructor
124 lv2_event(const lv2_event
&) {}
127 /// A read-only iterator-like object for reading from event buffers
128 class event_port_read_iterator
131 const LV2_Event_Buffer
*buffer
;
134 /// Default constructor creating a useless iterator you can assign to
135 event_port_read_iterator()
141 /// Create an iterator based on specified buffer and index/offset values
142 event_port_read_iterator(const LV2_Event_Buffer
*_buffer
, uint32_t _offset
= 0)
148 /// Are any data left to be read?
149 inline operator bool() const {
150 return offset
< buffer
->size
;
154 inline const lv2_event
&operator*() const {
155 return *(const lv2_event
*)(buffer
->data
+ offset
);
157 /// Pointer to member
158 inline const lv2_event
*operator->() const {
162 /// Move to the next element
163 inline event_port_read_iterator
operator++() {
164 offset
+= ((**this).size
+ 19) &~7;
168 /// Move to the next element
169 inline event_port_read_iterator
operator++(int) {
170 event_port_read_iterator old
= *this;
171 offset
+= ((**this).size
+ 19) &~7;
176 /// A write-only iterator-like object for writing to event buffers
177 class event_port_write_iterator
180 LV2_Event_Buffer
*buffer
;
182 /// Default constructor creating a useless iterator you can assign to
183 event_port_write_iterator()
188 /// Create a write iterator based on specified buffer and index/offset values
189 event_port_write_iterator(LV2_Event_Buffer
*_buffer
)
194 /// @return the remaining buffer space
195 inline uint32_t space_left() const {
196 return buffer
->capacity
- buffer
->size
;
198 /// @return write pointer
199 inline lv2_event
&operator*() {
200 return *(lv2_event
*)(buffer
->data
+ buffer
->size
);
202 /// Pointer to member
203 inline lv2_event
*operator->() {
206 /// Move to the next element after the current one has been written (must be called after each write)
207 inline event_port_write_iterator
operator++() {
208 buffer
->size
+= ((**this).size
+ 19) &~7;
209 buffer
->event_count
++;
212 /// Move to the next element after the current one has been written
213 inline lv2_event
*operator++(int) {
214 lv2_event
*ptr
= &**this;
215 buffer
->size
+= ((**this).size
+ 19) &~7;
216 buffer
->event_count
++;
221 template<class Iter1
, class Iter2
>
222 class event_port_merge_iterator
228 event_port_merge_iterator() {}
229 event_port_merge_iterator(const Iter1
&_first
, const Iter2
&_second
)
234 /// @retval true if any of the iterators have any data left
235 inline operator bool() const {
236 return ((bool)first
) || ((bool)second
);
238 inline bool select_first() const
244 return first
->timestamp() < second
->timestamp();
246 /// Returns the earliest of (*first, *second)
247 inline const lv2_event
&operator*() const {
253 assert((bool)second
);
256 /// Pointer to member
257 inline const lv2_event
*operator->() const {
261 inline event_port_merge_iterator
operator++() {
268 /// Postfix increment
269 inline event_port_merge_iterator
operator++(int) {
270 event_port_merge_iterator ptr
= *this;