Use ISC license for RDFF (same idea, MIT style, just prettier).
[ardour.git] / libs / ardour / lv2_event_buffer.cc
1 /*
2     Copyright (C) 2009 Paul Davis
3     Author: David Robillard
4
5     This program is free software; you can redistribute it and/or modify it
6     under the terms of the GNU General Public License as published by the Free
7     Software Foundation; either version 2 of the License, or (at your option)
8     any later version.
9
10     This program is distributed in the hope that it will be useful, but WITHOUT
11     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13     for more details.
14
15     You should have received a copy of the GNU General Public License along
16     with this program; if not, write to the Free Software Foundation, Inc.,
17     675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19
20 #include <stdint.h>
21 #include <iostream>
22 #include "lv2ext/lv2_event.h"
23 #include "lv2ext/lv2_event_helpers.h"
24 #include "ardour/lv2_event_buffer.h"
25
26 using namespace std;
27
28 namespace ARDOUR {
29
30
31 /** Allocate a new event buffer.
32  * \a capacity is in bytes (not number of events).
33  */
34 LV2EventBuffer::LV2EventBuffer(size_t capacity)
35         : _latest_frames(0)
36         , _latest_subframes(0)
37 {
38         if (capacity > UINT32_MAX) {
39                 cerr << "Event buffer size " << capacity << " too large, aborting." << endl;
40                 throw std::bad_alloc();
41         }
42
43         if (capacity == 0) {
44                 cerr << "ERROR: LV2 event buffer of size 0 created." << endl;
45                 capacity = 1024;
46         }
47
48 #ifdef NO_POSIX_MEMALIGN
49         _data = (LV2_Event_Buffer*)malloc(sizeof(LV2_Event_Buffer) + capacity);
50         int ret = (_data != NULL) ? 0 : -1;
51 #else
52         int ret = posix_memalign((void**)&_data, 16, sizeof(LV2_Event_Buffer) + capacity);
53 #endif
54
55         if (ret != 0) {
56                 cerr << "Failed to allocate event buffer.  Aborting." << endl;
57                 exit(EXIT_FAILURE);
58         }
59
60         _data->event_count = 0;
61         _data->capacity = (uint32_t)capacity;
62         _data->size = 0;
63         _data->data = reinterpret_cast<uint8_t*>(_data + 1);
64
65         reset();
66 }
67
68
69 LV2EventBuffer::~LV2EventBuffer()
70 {
71         free(_data);
72 }
73
74
75 /** Increment the read position by one event.
76  *
77  * \return true if increment was successful, or false if end of buffer reached.
78  */
79 bool
80 LV2EventBuffer::increment() const
81 {
82         if (lv2_event_is_valid(&_iter)) {
83                 lv2_event_increment(&_iter);
84                 return true;
85         } else {
86                 return false;
87         }
88 }
89
90
91 /** \return true iff the cursor is valid (ie get_event is safe)
92  */
93 bool
94 LV2EventBuffer::is_valid() const
95 {
96         return lv2_event_is_valid(&_iter);
97 }
98
99
100 /** Read an event from the current position in the buffer
101  *
102  * \return true if read was successful, or false if end of buffer reached
103  */
104 bool
105 LV2EventBuffer::get_event(uint32_t* frames,
106                           uint32_t* subframes,
107                           uint16_t* type,
108                           uint16_t* size,
109                           uint8_t** data) const
110 {
111         if (lv2_event_is_valid(&_iter)) {
112                 LV2_Event* ev = lv2_event_get(&_iter, data);
113                 *frames = ev->frames;
114                 *subframes = ev->subframes;
115                 *type = ev->type;
116                 *size = ev->size;
117                 return true;
118         } else {
119                 return false;
120         }
121 }
122
123
124 /** Append an event to the buffer.
125  *
126  * \a timestamp must be >= the latest event in the buffer.
127  *
128  * \return true on success
129  */
130 bool
131 LV2EventBuffer::append(uint32_t       frames,
132                        uint32_t       subframes,
133                        uint16_t       type,
134                        uint16_t       size,
135                        const uint8_t* data)
136 {
137 #ifndef NDEBUG
138         if (lv2_event_is_valid(&_iter)) {
139                 LV2_Event* last_event = lv2_event_get(&_iter, NULL);
140                 assert(last_event->frames < frames
141                                 || (last_event->frames == frames && last_event->subframes <= subframes));
142         }
143 #endif
144
145         /*cout << "Appending event type " << type << ", size " << size
146                 << " @ " << frames << "." << subframes << endl;
147         cout << "Buffer capacity " << _data->capacity << ", size " << _data->size << endl;*/
148
149         if (!lv2_event_write(&_iter, frames, subframes, type, size, data)) {
150                 cerr << "ERROR: Failed to write event." << endl;
151                 return false;
152         } else {
153                 _latest_frames = frames;
154                 _latest_subframes = subframes;
155                 return true;
156         }
157 }
158
159
160 /** Append a buffer of events to the buffer.
161  *
162  * \a timestamp must be >= the latest event in the buffer.
163  *
164  * \return true on success
165  */
166 bool
167 LV2EventBuffer::append(const LV2_Event_Buffer* /*buf*/)
168 {
169         uint8_t** data = NULL;
170         bool      ret  = true;
171
172         LV2_Event_Iterator iter;
173         for (lv2_event_begin(&iter, _data); lv2_event_is_valid(&iter); lv2_event_increment(&iter)) {
174                 LV2_Event* ev = lv2_event_get(&iter, data);
175
176 #ifndef NDEBUG
177                 assert((ev->frames > _latest_frames)
178                                 || (ev->frames == _latest_frames
179                                         && ev->subframes >= _latest_subframes));
180 #endif
181
182                 if (!(ret = append(ev->frames, ev->subframes, ev->type, ev->size, *data))) {
183                         cerr << "ERROR: Failed to write event." << endl;
184                         break;
185                 }
186
187                 _latest_frames = ev->frames;
188                 _latest_subframes = ev->subframes;
189         }
190
191         return ret;
192 }
193
194
195 } // namespace ARDOUR
196