6ef1c49ee90cd2aeb85f574b552c1566a71b8fb9
[ardour.git] / libs / midi++2 / midi++ / event.h
1 /*
2     Copyright (C) 2007 Paul Davis 
3     Author: Dave Robillard
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19 */
20
21 #ifndef __libmidipp_midi_event_h__
22 #define __libmidipp_midi_event_h__
23
24 #include <stdint.h>
25 #include <cstdlib>
26 #include <cstring>
27 #include <assert.h>
28
29 #include <midi++/types.h>
30 #include <midi++/events.h>
31
32 /** If this is not defined, all methods of MidiEvent are RT safe
33  * but MidiEvent will never deep copy and (depending on the scenario)
34  * may not be usable in STL containers, signals, etc. 
35  */
36 #define MIDI_EVENT_ALLOW_ALLOC 1
37
38 namespace MIDI {
39
40
41 /** Identical to jack_midi_event_t, but with double timestamp
42  *
43  * time is either a frame time (from/to Jack) or a beat time (internal
44  * tempo time, used in MidiModel) depending on context.
45  */
46 struct Event {
47 #ifdef MIDI_EVENT_ALLOW_ALLOC
48         Event(double t=0, uint32_t s=0, uint8_t* b=NULL, bool owns_buffer=false)
49                 : _time(t)
50                 , _size(s)
51                 , _buffer(b)
52                 , _owns_buffer(owns_buffer)
53         {
54                 if (owns_buffer) {
55                         _buffer = (uint8_t*)malloc(_size);
56                         if (b)
57                                 memcpy(_buffer, b, _size);
58                         else
59                                 memset(_buffer, 0, _size);
60                 }
61         }
62         
63         /** Copy \a copy.
64          * 
65          * If \a owns_buffer is true, the buffer will be copied and this method
66          * is NOT REALTIME SAFE.  Otherwise both events share a buffer and
67          * memory management semantics are the caller's problem.
68          */
69         Event(const Event& copy, bool owns_buffer)
70                 : _time(copy._time)
71                 , _size(copy._size)
72                 , _buffer(copy._buffer)
73                 , _owns_buffer(owns_buffer)
74         {
75                 if (owns_buffer) {
76                         _buffer = (uint8_t*)malloc(_size);
77                         if (copy._buffer)
78                                 memcpy(_buffer, copy._buffer, _size);
79                         else
80                                 memset(_buffer, 0, _size);
81                 }
82         }
83         
84         ~Event() {
85                 if (_owns_buffer)
86                         free(_buffer);
87         }
88
89         inline const Event& operator=(const Event& copy) {
90                 _time = copy._time;
91                 if (_owns_buffer) {
92                         if (copy._buffer) {
93                                 if (!_buffer || _size < copy._size)
94                                         _buffer = (uint8_t*)::realloc(_buffer, copy._size);
95                                 memcpy(_buffer, copy._buffer, copy._size);
96                         } else {
97                                 free(_buffer);
98                                 _buffer = NULL;
99                         }
100                 } else {
101                         _buffer = copy._buffer;
102                 }
103
104                 _size = copy._size;
105                 return *this;
106         }
107         
108         inline void set (uint8_t* msg, size_t msglen, timestamp_t t) {
109                 if (_owns_buffer) {
110                         if (_size < msglen) {
111                                 free (_buffer);
112                                 _buffer = (uint8_t*) malloc (msglen);
113                         }
114                 } else {
115                         _buffer = (uint8_t*) malloc (msglen);
116                         _owns_buffer = true;
117                 }
118
119                 memcpy (_buffer, msg, msglen);
120                 _time = t;
121         }
122
123         inline bool operator==(const Event& other) const {
124                 if (_time != other._time)
125                         return false;
126
127                 if (_size != other._size)
128                         return false;
129
130                 if (_buffer == other._buffer)
131                         return true;
132
133                 for (size_t i=0; i < _size; ++i)
134                         if (_buffer[i] != other._buffer[i])
135                                 return false;
136
137                 return true;
138         }
139         
140         inline bool operator!=(const Event& other) const { return ! operator==(other); }
141
142         inline bool owns_buffer() const { return _owns_buffer; }
143         
144         inline void set_buffer(uint8_t* buf, bool own) {
145                 if (_owns_buffer) {
146                         free(_buffer);
147                         _buffer = NULL;
148                 }
149                 _buffer = buf;
150                 _owns_buffer = own;
151         }
152
153         inline void realloc(size_t size) {
154                 assert(_owns_buffer);
155                 _buffer = (uint8_t*) ::realloc(_buffer, size);
156         }
157
158 #else
159
160         inline void set_buffer(uint8_t* buf) { _buffer = buf; }
161
162 #endif // MIDI_EVENT_ALLOW_ALLOC
163
164         inline double      time()        const { return _time; }
165         inline double&     time()              { return _time; }
166         inline uint32_t    size()        const { return _size; }
167         inline uint32_t&   size()              { return _size; }
168         inline uint8_t     type()        const { return (_buffer[0] & 0xF0); }
169         inline uint8_t     channel()     const { return (_buffer[0] & 0x0F); }
170         inline bool        is_note_on()  const { return (type() == MIDI_CMD_NOTE_ON); }
171         inline bool        is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); }
172         inline bool        is_cc()       const { return (type() == MIDI_CMD_CONTROL); }
173         inline bool        is_note()     const { return (is_note_on() || is_note_off()); }
174         inline uint8_t     note()        const { return (_buffer[1]); }
175         inline uint8_t     velocity()    const { return (_buffer[2]); }
176         inline uint8_t     cc_number()   const { return (_buffer[1]); }
177         inline uint8_t     cc_value()    const { return (_buffer[2]); }
178         inline const uint8_t* buffer()      const { return _buffer; }
179         inline uint8_t*&      buffer()            { return _buffer; }
180
181 private:
182         double   _time;   /**< Sample index (or beat time) at which event is valid */
183         uint32_t _size;   /**< Number of uint8_ts of data in \a buffer */
184         uint8_t*    _buffer; /**< Raw MIDI data */
185
186 #ifdef MIDI_EVENT_ALLOW_ALLOC
187         bool _owns_buffer; /**< Whether buffer is locally allocated */
188 #endif
189 };
190
191
192 }
193
194 #endif /* __libmidipp_midi_event_h__ */