forward port automation handling changes from 2.x, upto and including about rev 6981...
[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 /** If this is not defined, all methods of MidiEvent are RT safe
30  * but MidiEvent will never deep copy and (depending on the scenario)
31  * may not be usable in STL containers, signals, etc.
32  */
33 #define EVORAL_EVENT_ALLOC 1
34
35 namespace Evoral {
36
37 event_id_t event_id_counter();
38 event_id_t next_event_id();
39 void init_event_id_counter (event_id_t n);
40
41 /** An event (much like a type generic jack_midi_event_t)
42  *
43  * Template parameter Time is the type of the time stamp used for this event.
44  */
45 template<typename Time>
46 struct Event {
47 #ifdef EVORAL_EVENT_ALLOC
48          Event (EventType type=0, Time time=0, uint32_t size=0, uint8_t* buf=NULL, bool alloc=false);
49
50         /** Copy \a copy.
51          *
52          * If \a alloc is true, the buffer will be copied and this method
53          * is NOT REALTIME SAFE.  Otherwise both events share a buffer and
54          * memory management semantics are the caller's problem.
55          */
56         Event(const Event& copy, bool alloc);
57
58         ~Event();
59
60         inline const Event& operator=(const Event& copy) {
61                 _id = copy.id(); // XXX is this right? do we want ID copy semantics?
62                 _type = copy._type;
63                 _original_time = copy._original_time;
64                 _nominal_time = copy._nominal_time;
65                 if (_owns_buf) {
66                         if (copy._buf) {
67                                 if (copy._size > _size) {
68                                         _buf = (uint8_t*)::realloc(_buf, copy._size);
69                                 }
70                                 memcpy(_buf, copy._buf, copy._size);
71                         } else {
72                                 free(_buf);
73                                 _buf = NULL;
74                         }
75                 } else {
76                         _buf = copy._buf;
77                 }
78
79                 _size = copy._size;
80                 return *this;
81         }
82
83         inline void set(uint8_t* buf, uint32_t size, Time t) {
84                 if (_owns_buf) {
85                         if (_size < size) {
86                                 _buf = (uint8_t*) ::realloc(_buf, size);
87                         }
88                         memcpy (_buf, buf, size);
89                 } else {
90                         _buf = buf;
91                 }
92
93                 _original_time = t;
94                 _nominal_time = t;
95                 _size = size;
96         }
97
98         inline bool operator==(const Event& other) const {
99                 if (_type != other._type)
100                         return false;
101
102                 if (_nominal_time != other._nominal_time)
103                         return false;
104
105                 if (_original_time != other._original_time)
106                         return false;
107
108                 if (_size != other._size)
109                         return false;
110
111                 if (_buf == other._buf)
112                         return true;
113
114                 for (uint32_t i=0; i < _size; ++i)
115                         if (_buf[i] != other._buf[i])
116                                 return false;
117
118                 return true;
119         }
120
121         inline bool operator!=(const Event& other) const { return ! operator==(other); }
122
123         inline bool owns_buffer() const { return _owns_buf; }
124
125         inline void set_buffer(uint32_t size, uint8_t* buf, bool own) {
126                 if (_owns_buf) {
127                         free(_buf);
128                         _buf = NULL;
129                 }
130                 _size     = size;
131                 _buf      = buf;
132                 _owns_buf = own;
133         }
134
135         inline void realloc(uint32_t size) {
136                 if (_owns_buf) {
137                         if (size > _size)
138                                 _buf = (uint8_t*) ::realloc(_buf, size);
139                 } else {
140                         _buf = (uint8_t*) ::malloc(size);
141                         _owns_buf = true;
142                 }
143
144                 _size = size;
145         }
146
147         inline void clear() {
148                 _type = 0;
149                 _original_time = 0;
150                 _nominal_time = 0;
151                 _size = 0;
152                 _buf  = NULL;
153         }
154
155 #else
156
157         inline void set_buffer(uint8_t* buf) { _buf = buf; }
158
159 #endif // EVORAL_EVENT_ALLOC
160
161         inline EventType   event_type()            const { return _type; }
162         inline void        set_event_type(EventType t)   { _type = t; }
163         inline Time        time()                  const { return _nominal_time; }
164         inline Time&       time()                        { return _nominal_time; }
165         inline Time        original_time()         const { return _original_time; }
166         inline Time&       original_time()               { return _original_time; }
167         inline uint32_t    size()                  const { return _size; }
168         inline uint32_t&   size()                        { return _size; }
169
170         inline const uint8_t* buffer()             const { return _buf; }
171         inline uint8_t*&      buffer()                   { return _buf; }
172
173         inline event_id_t id() const { return _id; }
174         inline void set_id (event_id_t n) { _id = n; }
175
176 protected:
177         EventType _type; /**< Type of event (application relative, NOT MIDI 'type') */
178         Time      _original_time; /**< Sample index (or beat time) at which event is valid */
179         Time      _nominal_time; /**< Quantized version of _time, used in preference */
180         uint32_t  _size; /**< Number of uint8_ts of data in \a buffer */
181         uint8_t*  _buf;  /**< Raw MIDI data */
182
183 #ifdef EVORAL_EVENT_ALLOC
184         bool      _owns_buf; /**< Whether buffer is locally allocated */
185 #endif
186         event_id_t  _id; /** UUID for each event, should probably be 64bit or at least unsigned */
187 };
188
189 } // namespace Evoral
190
191
192 template<typename Time>
193 std::ostream& operator<<(std::ostream& o, const Evoral::Event<Time>& ev) {
194         o << "Event #" << ev.id() << " type = " << ev.event_type() << " @ " << ev.time();
195         o << std::hex;
196         for (uint32_t n = 0; n < ev.size(); ++n) {
197                 o << ' ' << (int) ev.buffer()[n];
198         }
199         o << std::dec;
200         return o;
201 }
202
203
204 #endif // EVORAL_EVENT_HPP
205