Fix crash when playing back MIDI within a loop.
[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 #ifdef NO_POSIX_MEMALIGN
45         _data = (LV2_Event_Buffer*)malloc(sizeof(LV2_Event_Buffer) + capacity);
46         int ret = (_data != NULL) ? 0 : -1;
47 #else
48         int ret = posix_memalign((void**)&_data, 16, sizeof(LV2_Event_Buffer) + capacity);
49 #endif
50
51         if (ret != 0) {
52                 cerr << "Failed to allocate event buffer.  Aborting." << endl;
53                 exit(EXIT_FAILURE);
54         }
55
56         _data->event_count = 0;
57         _data->capacity = (uint32_t)capacity;
58         _data->size = 0;
59         _data->data = reinterpret_cast<uint8_t*>(_data + 1);
60
61         reset();
62 }
63
64
65 LV2EventBuffer::~LV2EventBuffer()
66 {
67         free(_data);
68 }
69
70
71 /** Increment the read position by one event.
72  *
73  * \return true if increment was successful, or false if end of buffer reached.
74  */
75 bool
76 LV2EventBuffer::increment() const
77 {
78         if (lv2_event_is_valid(&_iter)) {
79                 lv2_event_increment(&_iter);
80                 return true;
81         } else {
82                 return false;
83         }
84 }
85
86
87 /** \return true iff the cursor is valid (ie get_event is safe)
88  */
89 bool
90 LV2EventBuffer::is_valid() const
91 {
92         return lv2_event_is_valid(&_iter);
93 }
94
95
96 /** Read an event from the current position in the buffer
97  * 
98  * \return true if read was successful, or false if end of buffer reached
99  */
100 bool
101 LV2EventBuffer::get_event(uint32_t* frames,
102                           uint32_t* subframes, 
103                           uint16_t* type, 
104                           uint16_t* size, 
105                           uint8_t** data) const
106 {
107         if (lv2_event_is_valid(&_iter)) {
108                 LV2_Event* ev = lv2_event_get(&_iter, data);
109                 *frames = ev->frames;
110                 *subframes = ev->subframes;
111                 *type = ev->type;
112                 *size = ev->size;
113                 return true;
114         } else {
115                 return false;
116         }
117 }
118
119
120 /** Append an event to the buffer.
121  *
122  * \a timestamp must be >= the latest event in the buffer.
123  *
124  * \return true on success
125  */
126 bool
127 LV2EventBuffer::append(uint32_t       frames,
128                        uint32_t       subframes,
129                        uint16_t       type,
130                        uint16_t       size,
131                        const uint8_t* data)
132 {
133 #ifndef NDEBUG
134         if (lv2_event_is_valid(&_iter)) {
135                 LV2_Event* last_event = lv2_event_get(&_iter, NULL);
136                 assert(last_event->frames < frames
137                                 || (last_event->frames == frames && last_event->subframes <= subframes));
138         }
139 #endif
140
141         /*cout << "Appending event type " << type << ", size " << size
142                 << " @ " << frames << "." << subframes << endl;*/
143
144         if (!lv2_event_write(&_iter, frames, subframes, type, size, data)) {
145                 cerr << "ERROR: Failed to write event." << endl;
146                 return false;
147         } else {
148                 _latest_frames = frames;
149                 _latest_subframes = subframes;
150                 return true;
151         }
152 }
153
154
155 /** Append a buffer of events to the buffer.
156  *
157  * \a timestamp must be >= the latest event in the buffer.
158  *
159  * \return true on success
160  */
161 bool
162 LV2EventBuffer::append(const LV2_Event_Buffer* buf)
163 {
164         uint8_t** data = NULL;
165         bool      ret  = true;
166
167         LV2_Event_Iterator iter;
168         for (lv2_event_begin(&iter, _data); lv2_event_is_valid(&iter); lv2_event_increment(&iter)) {
169                 LV2_Event* ev = lv2_event_get(&iter, data);
170
171 #ifndef NDEBUG
172                 assert((ev->frames > _latest_frames)
173                                 || (ev->frames == _latest_frames
174                                         && ev->subframes >= _latest_subframes));
175 #endif
176
177                 if (!(ret = append(ev->frames, ev->subframes, ev->type, ev->size, *data))) {
178                         cerr << "ERROR: Failed to write event." << endl;
179                         break;
180                 }
181
182                 _latest_frames = ev->frames;
183                 _latest_subframes = ev->subframes;
184         }
185         
186         return ret;
187 }
188
189
190 } // namespace ARDOUR
191