Merge branch 'master' into saveas
[ardour.git] / libs / evoral / evoral / Event.hpp
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 #ifndef EVORAL_EVENT_HPP
20 #define EVORAL_EVENT_HPP
21
22 #include <cstdlib>
23 #include <cstring>
24 #include <sstream>
25 #include <stdint.h>
26
27 #include "evoral/visibility.h"
28 #include "evoral/types.hpp"
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 LIBEVORAL_API event_id_t event_id_counter();
39 LIBEVORAL_API event_id_t next_event_id();
40 LIBEVORAL_API void init_event_id_counter(event_id_t n);
41
42 /** An event (much like a type generic jack_midi_event_t)
43  *
44  * Template parameter Time is the type of the time stamp used for this event.
45  */
46 template<typename Time>
47 class LIBEVORAL_API Event {
48 public:
49 #ifdef EVORAL_EVENT_ALLOC
50         Event (EventType type=0, Time time=Time(), uint32_t size=0, uint8_t* buf=NULL, bool alloc=false);
51
52         Event (EventType type, Time time, uint32_t size, const uint8_t* buf);
53
54         /** Copy \a copy.
55          *
56          * If \a alloc is true, the buffer will be copied and this method
57          * is NOT REALTIME SAFE.  Otherwise both events share a buffer and
58          * memory management semantics are the caller's problem.
59          */
60         Event(const Event& copy, bool alloc);
61
62         ~Event();
63
64         const Event& operator=(const Event& copy);
65
66         void set(const uint8_t* buf, uint32_t size, Time t);
67
68         inline bool operator==(const Event& other) const {
69                 if (_type != other._type)
70                         return false;
71
72                 if (_nominal_time != other._nominal_time)
73                         return false;
74
75                 if (_original_time != other._original_time)
76                         return false;
77
78                 if (_size != other._size)
79                         return false;
80
81                 if (_buf == other._buf)
82                         return true;
83
84                 for (uint32_t i=0; i < _size; ++i)
85                         if (_buf[i] != other._buf[i])
86                                 return false;
87
88                 return true;
89         }
90
91         inline bool operator!=(const Event& other) const { return ! operator==(other); }
92
93         inline bool owns_buffer() const { return _owns_buf; }
94
95         inline void set_buffer(uint32_t size, uint8_t* buf, bool own) {
96                 if (_owns_buf) {
97                         free(_buf);
98                         _buf = NULL;
99                 }
100                 _size     = size;
101                 _buf      = buf;
102                 _owns_buf = own;
103         }
104
105         inline void realloc(uint32_t size) {
106                 if (_owns_buf) {
107                         if (size > _size)
108                                 _buf = (uint8_t*) ::realloc(_buf, size);
109                 } else {
110                         _buf = (uint8_t*) ::malloc(size);
111                         _owns_buf = true;
112                 }
113
114                 _size = size;
115         }
116
117         inline void clear() {
118                 _type          = 0;
119                 _original_time = Time();
120                 _nominal_time  = Time();
121                 _size          = 0;
122                 _buf           = NULL;
123         }
124
125 #else
126
127         inline void set_buffer(uint8_t* buf) { _buf = buf; }
128
129 #endif // EVORAL_EVENT_ALLOC
130
131         inline EventType      event_type()    const { return _type; }
132         inline Time           time()          const { return _nominal_time; }
133         inline Time           original_time() const { return _original_time; }
134         inline uint32_t       size()          const { return _size; }
135         inline const uint8_t* buffer()        const { return _buf; }
136         inline uint8_t*       buffer()              { return _buf; }
137
138         inline void set_event_type(EventType t) { _type = t; }
139
140         void set_time(Time);
141         void set_original_time(Time);
142
143         inline event_id_t id() const           { return _id; }
144         inline void       set_id(event_id_t n) { _id = n; }
145
146 protected:
147         EventType  _type; /**< Type of event (application relative, NOT MIDI 'type') */
148         Time       _original_time; /**< Sample index (or beat time) at which event is valid */
149         Time       _nominal_time; /**< Quantized version of _time, used in preference */
150         uint32_t   _size; /**< Number of uint8_ts of data in \a buffer */
151         uint8_t*   _buf;  /**< Raw MIDI data */
152         event_id_t _id; /** UUID for each event, should probably be 64bit or at least unsigned */
153 #ifdef EVORAL_EVENT_ALLOC
154         bool       _owns_buf; /**< Whether buffer is locally allocated */
155 #endif
156 };
157
158 template<typename Time>
159 /*LIBEVORAL_API*/ std::ostream& operator<<(std::ostream& o, const Evoral::Event<Time>& ev) {
160         o << "Event #" << ev.id() << " type = " << ev.event_type() << " @ " << ev.time();
161         o << std::hex;
162         for (uint32_t n = 0; n < ev.size(); ++n) {
163                 o << ' ' << (int) ev.buffer()[n];
164         }
165         o << std::dec;
166         return o;
167 }
168
169 } // namespace Evoral
170
171 #endif // EVORAL_EVENT_HPP
172