3c1cc000bd964572801ecf8ccb39fadc4a3b51cd
[ardour.git] / libs / evoral / src / Event.cpp
1 /* This file is part of Evoral.
2  * Copyright (C) 2008 David Robillard <http://drobilla.net>
3  * Copyright (C) 2000-2008 Paul Davis
4  *
5  * Evoral is free software; you can redistribute it and/or modify it under the
6  * terms of the GNU General Public License as published by the Free Software
7  * Foundation; either version 2 of the License, or (at your option) any later
8  * version.
9  *
10  * Evoral is distributed in the hope that it will be useful, but WITHOUT ANY
11  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18
19 #include <glib.h>
20 #include "evoral/Event.hpp"
21
22 namespace Evoral {
23
24 static event_id_t _event_id_counter = 0;
25
26 event_id_t
27 event_id_counter()
28 {
29         return g_atomic_int_get (&_event_id_counter);
30 }
31
32 void
33 init_event_id_counter(event_id_t n)
34 {
35         g_atomic_int_set (&_event_id_counter, n);
36 }
37
38 event_id_t
39 next_event_id ()
40 {
41         /* libsmf supports reading variable-length data up to 4 bytes only.
42          * so we wrap around at 2^(4 * 7) - 1
43          *
44          * interestingly enough libsmf happily writes data longer than that, but then
45          * fails to load it in ./libs/evoral/src/libsmf/smf_load.c:237
46          * g_critical("SMF error: Variable Length Quantities longer than four bytes are not supported yet.");
47          *
48          * event-IDs only have to be unique per .mid file.
49          * Previously (Ardour 4.2ish) Ardour re-generated those IDs when loading the
50          * file but that lead to .mid files being modified on every load/save.
51          *
52          * For now just assume that by the time 2^28 is reached, files with low ids have vanished.
53          * There is only one user who managed to get to 268 million events so far.
54          * quite a feat: id-counter="6483089" event-counter="276390506"
55          * Eventually a proper solution will have to be implemented.
56          */
57         return g_atomic_int_add (&_event_id_counter, 1) & 268435455;
58 }
59
60 #ifdef EVORAL_EVENT_ALLOC
61
62 template<typename Timestamp>
63 Event<Timestamp>::Event(EventType type, Timestamp time, uint32_t size, uint8_t* buf, bool alloc)
64         : _type(type)
65         , _original_time(time)
66         , _nominal_time(time)
67         , _size(size)
68         , _buf(buf)
69         , _id(-1)
70         , _owns_buf(alloc)
71 {
72         if (alloc) {
73                 _buf = (uint8_t*)malloc(_size);
74                 if (buf) {
75                         memcpy(_buf, buf, _size);
76                 } else {
77                         memset(_buf, 0, _size);
78                 }
79         }
80 }
81
82 template<typename Timestamp>
83 Event<Timestamp>::Event(EventType      type,
84                         Timestamp      time,
85                         uint32_t       size,
86                         const uint8_t* buf)
87         : _type(type)
88         , _original_time(time)
89         , _nominal_time(time)
90         , _size(size)
91         , _buf((uint8_t*)malloc(size))
92         , _id(-1)
93         , _owns_buf(true)
94 {
95         memcpy(_buf, buf, _size);
96 }
97
98 template<typename Timestamp>
99 Event<Timestamp>::Event(const Event& copy, bool owns_buf)
100         : _type(copy._type)
101         , _original_time(copy._original_time)
102         , _nominal_time(copy._nominal_time)
103         , _size(copy._size)
104         , _buf(copy._buf)
105         , _id (next_event_id ())
106         , _owns_buf(owns_buf)
107 {
108         if (owns_buf) {
109                 _buf = (uint8_t*)malloc(_size);
110                 if (copy._buf) {
111                         memcpy(_buf, copy._buf, _size);
112                 } else {
113                         memset(_buf, 0, _size);
114                 }
115         }
116 }
117
118 template<typename Timestamp>
119 Event<Timestamp>::~Event() {
120         if (_owns_buf) {
121                 free(_buf);
122         }
123 }
124
125 template<typename Timestamp>
126 void
127 Event<Timestamp>::assign(const Event& other)
128 {
129         _id = other._id;
130         _type = other._type;
131         _original_time = other._original_time;
132         _nominal_time = other._nominal_time;
133         _owns_buf = other._owns_buf;
134         if (_owns_buf) {
135                 if (other._buf) {
136                         if (other._size > _size) {
137                                 _buf = (uint8_t*)::realloc(_buf, other._size);
138                         }
139                         memcpy(_buf, other._buf, other._size);
140                 } else {
141                         free(_buf);
142                         _buf = NULL;
143                 }
144         } else {
145                 _buf = other._buf;
146         }
147
148         _size = other._size;
149 }
150
151 template<typename Timestamp>
152 void
153 Event<Timestamp>::set (const uint8_t* buf, uint32_t size, Timestamp t)
154 {
155         if (_owns_buf) {
156                 if (_size < size) {
157                         _buf = (uint8_t*) ::realloc(_buf, size);
158                 }
159                 memcpy (_buf, buf, size);
160         } else {
161                 /* XXX this is really dangerous given the
162                    const-ness of buf. The API should really
163                    intervene here.
164                 */
165                 _buf = const_cast<uint8_t*> (buf);
166         }
167
168         _original_time = t;
169         _nominal_time = t;
170         _size = size;
171 }
172
173 template<typename Timestamp>
174 void
175 Event<Timestamp>::set_time (Timestamp t)
176 {
177         _nominal_time = t;
178 }
179
180 template<typename Timestamp>
181 void
182 Event<Timestamp>::set_original_time (Timestamp t)
183 {
184         _original_time = t;
185 }
186
187 #endif // EVORAL_EVENT_ALLOC
188
189 template class Event<Evoral::Beats>;
190 template class Event<double>;
191 template class Event<int64_t>;
192
193 } // namespace Evoral
194