MIDI robustness.
[ardour.git] / libs / evoral / evoral / Event.hpp
1 /* This file is part of Evoral.
2  * Copyright (C) 2008 Dave 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 #ifndef EVORAL_EVENT_HPP
20 #define EVORAL_EVENT_HPP
21
22 #include <stdint.h>
23 #include <cstdlib>
24 #include <cstring>
25 #include <sstream>
26 #include <assert.h>
27 #include "evoral/types.hpp"
28
29
30 /** If this is not defined, all methods of MidiEvent are RT safe
31  * but MidiEvent will never deep copy and (depending on the scenario)
32  * may not be usable in STL containers, signals, etc. 
33  */
34 #define EVORAL_EVENT_ALLOC 1
35
36 namespace Evoral {
37
38
39 /** An event (much like a type generic jack_midi_event_t)
40  *
41  * Template parameter Time is the type of the time stamp used for this event.
42  */
43 template<typename Time>
44 struct Event {
45 #ifdef EVORAL_EVENT_ALLOC
46         Event(EventType type=0, Time time=0, uint32_t size=0, uint8_t* buf=NULL, bool alloc=false);
47         
48         /** Copy \a copy.
49          * 
50          * If \a alloc is true, the buffer will be copied and this method
51          * is NOT REALTIME SAFE.  Otherwise both events share a buffer and
52          * memory management semantics are the caller's problem.
53          */
54         Event(const Event& copy, bool alloc);
55         
56         ~Event();
57
58         inline const Event& operator=(const Event& copy) {
59                 _type = copy._type;
60                 _time = copy._time;
61                 if (_owns_buf) {
62                         if (copy._buf) {
63                                 if (copy._size > _size) {
64                                         _buf = (uint8_t*)::realloc(_buf, copy._size);
65                                 }
66                                 memcpy(_buf, copy._buf, copy._size);
67                         } else {
68                                 free(_buf);
69                                 _buf = NULL;
70                         }
71                 } else {
72                         _buf = copy._buf;
73                 }
74
75                 _size = copy._size;
76                 return *this;
77         }
78
79         inline void shallow_copy(const Event& copy) {
80                 if (_owns_buf) {
81                         free(_buf);
82                         _buf = false;
83                         _owns_buf = false;
84                 }
85
86                 _type = copy._type;
87                 _time = copy._time;
88                 _size = copy._size;
89                 _buf  = copy._buf;
90         }
91         
92         inline void set(uint8_t* buf, uint32_t size, Time t) {
93                 if (_owns_buf) {
94                         if (_size < size) {
95                                 _buf = (uint8_t*) ::realloc(_buf, size);
96                         }
97                         memcpy (_buf, buf, size);
98                 } else {
99                         _buf = buf;
100                 }
101
102                 _time = t;
103                 _size = size;
104         }
105
106         inline bool operator==(const Event& other) const {
107                 if (_type != other._type)
108                         return false;
109
110                 if (_time != other._time)
111                         return false;
112
113                 if (_size != other._size)
114                         return false;
115
116                 if (_buf == other._buf)
117                         return true;
118
119                 for (uint32_t i=0; i < _size; ++i)
120                         if (_buf[i] != other._buf[i])
121                                 return false;
122
123                 return true;
124         }
125         
126         inline bool operator!=(const Event& other) const { return ! operator==(other); }
127
128         inline bool owns_buffer() const { return _owns_buf; }
129         
130         inline void set_buffer(uint32_t size, uint8_t* buf, bool own) {
131                 if (_owns_buf) {
132                         free(_buf);
133                         _buf = NULL;
134                 }
135                 _size     = size;
136                 _buf      = buf;
137                 _owns_buf = own;
138         }
139
140         inline void realloc(uint32_t size) {
141                 if (_owns_buf) {
142                         if (size > _size)
143                                 _buf = (uint8_t*) ::realloc(_buf, size);
144                 } else {
145                         _buf = (uint8_t*) ::malloc(size);
146                         _owns_buf = true;
147                 }
148
149                 _size = size;
150         }
151         
152         inline void clear() {
153                 _type = 0;
154                 _time = 0;
155                 _size = 0;
156                 _buf  = NULL;
157         }
158
159 #else
160
161         inline void set_buffer(uint8_t* buf) { _buf = buf; }
162
163 #endif // EVORAL_EVENT_ALLOC
164
165         inline EventType   event_type()            const { return _type; }
166         inline void        set_event_type(EventType t)   { _type = t; }
167         inline Time        time()                  const { return _time; }
168         inline Time&       time()                        { return _time; }
169         inline uint32_t    size()                  const { return _size; }
170         inline uint32_t&   size()                        { return _size; }
171
172         inline const uint8_t* buffer()             const { return _buf; }
173         inline uint8_t*&      buffer()                   { return _buf; }
174
175 protected:
176         EventType _type; /**< Type of event (application relative, NOT MIDI 'type') */
177         Time      _time; /**< Sample index (or beat time) at which event is valid */
178         uint32_t  _size; /**< Number of uint8_ts of data in \a buffer */
179         uint8_t*  _buf;  /**< Raw MIDI data */
180
181 #ifdef EVORAL_EVENT_ALLOC
182         bool _owns_buf; /**< Whether buffer is locally allocated */
183 #endif
184 };
185
186
187 } // namespace Evoral
188
189 #endif // EVORAL_EVENT_HPP
190