more MIDI editing tweaks ; flip mouse mode buttons around for MIDI so that "object...
[ardour.git] / libs / ardour / lv2_event_buffer.cc
1 /*
2     Copyright (C) 2009 Paul Davis 
3     Author: Dave 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 #define __STDC_LIMIT_MACROS 1
21 #include <stdint.h>
22 #include <iostream>
23 #include "lv2ext/lv2_event.h"
24 #include "lv2ext/lv2_event_helpers.h"
25 #include "ardour/lv2_event_buffer.h"
26
27 using namespace std;
28
29 namespace ARDOUR {
30
31
32 /** Allocate a new event buffer.
33  * \a capacity is in bytes (not number of events).
34  */
35 LV2EventBuffer::LV2EventBuffer(size_t capacity)
36         : _latest_frames(0)
37         , _latest_subframes(0)
38 {
39         if (capacity > UINT32_MAX) {
40                 cerr << "Event buffer size " << capacity << " too large, aborting." << endl;
41                 throw std::bad_alloc();
42         }
43
44         if (capacity == 0) {
45                 cerr << "ERROR: LV2 event buffer of size 0 created." << endl;
46                 capacity = 1024;
47         }
48
49 #ifdef NO_POSIX_MEMALIGN
50         _data = (LV2_Event_Buffer*)malloc(sizeof(LV2_Event_Buffer) + capacity);
51         int ret = (_data != NULL) ? 0 : -1;
52 #else
53         int ret = posix_memalign((void**)&_data, 16, sizeof(LV2_Event_Buffer) + capacity);
54 #endif
55
56         if (ret != 0) {
57                 cerr << "Failed to allocate event buffer.  Aborting." << endl;
58                 exit(EXIT_FAILURE);
59         }
60
61         _data->event_count = 0;
62         _data->capacity = (uint32_t)capacity;
63         _data->size = 0;
64         _data->data = reinterpret_cast<uint8_t*>(_data + 1);
65
66         reset();
67 }
68
69
70 LV2EventBuffer::~LV2EventBuffer()
71 {
72         free(_data);
73 }
74
75
76 /** Increment the read position by one event.
77  *
78  * \return true if increment was successful, or false if end of buffer reached.
79  */
80 bool
81 LV2EventBuffer::increment() const
82 {
83         if (lv2_event_is_valid(&_iter)) {
84                 lv2_event_increment(&_iter);
85                 return true;
86         } else {
87                 return false;
88         }
89 }
90
91
92 /** \return true iff the cursor is valid (ie get_event is safe)
93  */
94 bool
95 LV2EventBuffer::is_valid() const
96 {
97         return lv2_event_is_valid(&_iter);
98 }
99
100
101 /** Read an event from the current position in the buffer
102  * 
103  * \return true if read was successful, or false if end of buffer reached
104  */
105 bool
106 LV2EventBuffer::get_event(uint32_t* frames,
107                           uint32_t* subframes, 
108                           uint16_t* type, 
109                           uint16_t* size, 
110                           uint8_t** data) const
111 {
112         if (lv2_event_is_valid(&_iter)) {
113                 LV2_Event* ev = lv2_event_get(&_iter, data);
114                 *frames = ev->frames;
115                 *subframes = ev->subframes;
116                 *type = ev->type;
117                 *size = ev->size;
118                 return true;
119         } else {
120                 return false;
121         }
122 }
123
124
125 /** Append an event to the buffer.
126  *
127  * \a timestamp must be >= the latest event in the buffer.
128  *
129  * \return true on success
130  */
131 bool
132 LV2EventBuffer::append(uint32_t       frames,
133                        uint32_t       subframes,
134                        uint16_t       type,
135                        uint16_t       size,
136                        const uint8_t* data)
137 {
138 #ifndef NDEBUG
139         if (lv2_event_is_valid(&_iter)) {
140                 LV2_Event* last_event = lv2_event_get(&_iter, NULL);
141                 assert(last_event->frames < frames
142                                 || (last_event->frames == frames && last_event->subframes <= subframes));
143         }
144 #endif
145
146         /*cout << "Appending event type " << type << ", size " << size
147                 << " @ " << frames << "." << subframes << endl;
148         cout << "Buffer capacity " << _data->capacity << ", size " << _data->size << endl;*/
149
150         if (!lv2_event_write(&_iter, frames, subframes, type, size, data)) {
151                 cerr << "ERROR: Failed to write event." << endl;
152                 return false;
153         } else {
154                 _latest_frames = frames;
155                 _latest_subframes = subframes;
156                 return true;
157         }
158 }
159
160
161 /** Append a buffer of events to the buffer.
162  *
163  * \a timestamp must be >= the latest event in the buffer.
164  *
165  * \return true on success
166  */
167 bool
168 LV2EventBuffer::append(const LV2_Event_Buffer* /*buf*/)
169 {
170         uint8_t** data = NULL;
171         bool      ret  = true;
172
173         LV2_Event_Iterator iter;
174         for (lv2_event_begin(&iter, _data); lv2_event_is_valid(&iter); lv2_event_increment(&iter)) {
175                 LV2_Event* ev = lv2_event_get(&iter, data);
176
177 #ifndef NDEBUG
178                 assert((ev->frames > _latest_frames)
179                                 || (ev->frames == _latest_frames
180                                         && ev->subframes >= _latest_subframes));
181 #endif
182
183                 if (!(ret = append(ev->frames, ev->subframes, ev->type, ev->size, *data))) {
184                         cerr << "ERROR: Failed to write event." << endl;
185                         break;
186                 }
187
188                 _latest_frames = ev->frames;
189                 _latest_subframes = ev->subframes;
190         }
191         
192         return ret;
193 }
194
195
196 } // namespace ARDOUR
197