Fix displaying of notes in auto-created MIDI region when it's the first region in...
[ardour.git] / libs / ardour / ardour / 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 __ardour_midi_event_h__
22 #define __ardour_midi_event_h__
23
24 #include <ardour/types.h>
25 #include <ardour/midi_events.h>
26 #include <stdint.h>
27
28 /** If this is not defined, all methods of MidiEvent are RT safe
29  * but MidiEvent will never deep copy and (depending on the scenario)
30  * may not be usable in STL containers, signals, etc. */
31 #define MIDI_EVENT_ALLOW_ALLOC 1
32
33 namespace ARDOUR {
34
35
36 /** Identical to jack_midi_event_t, but with double timestamp
37  *
38  * time is either a frame time (from/to Jack) or a beat time (internal
39  * tempo time, used in MidiModel) depending on context.
40  */
41 struct MidiEvent {
42 #ifdef MIDI_EVENT_ALLOW_ALLOC
43         MidiEvent(double t=0, uint32_t s=0, Byte* b=NULL, bool owns_buffer=false)
44                 : _time(t)
45                 , _size(s)
46                 , _buffer(b)
47                 , _owns_buffer(owns_buffer)
48         {
49                 if (owns_buffer) {
50                         _buffer = (Byte*)malloc(_size);
51                         if (b)
52                                 memcpy(_buffer, b, _size);
53                         else
54                                 memset(_buffer, 0, _size);
55                 }
56         }
57         
58         /** Copy \a copy.
59          * 
60          * If \a owns_buffer is true, the buffer will be copied and this method
61          * is NOT REALTIME SAFE.  Otherwise both events share a buffer and
62          * memory management semantics are the caller's problem.
63          */
64         MidiEvent(const MidiEvent& copy, bool owns_buffer)
65                 : _time(copy._time)
66                 , _size(copy._size)
67                 , _buffer(copy._buffer)
68                 , _owns_buffer(owns_buffer)
69         {
70                 if (owns_buffer) {
71                         _buffer = (Byte*)malloc(_size);
72                         if (copy._buffer)
73                                 memcpy(_buffer, copy._buffer, _size);
74                         else
75                                 memset(_buffer, 0, _size);
76                 }
77         }
78         
79         ~MidiEvent() {
80                 if (_owns_buffer)
81                         free(_buffer);
82         }
83
84         inline const MidiEvent& operator=(const MidiEvent& copy) {
85                 _time = copy._time;
86                 if (_owns_buffer) {
87                         if (copy._buffer) {
88                                 if (!_buffer || _size < copy._size)
89                                         _buffer = (Byte*)realloc(_buffer, copy._size);
90                                 memcpy(_buffer, copy._buffer, copy._size);
91                         } else {
92                                 free(_buffer);
93                                 _buffer = NULL;
94                         }
95                 } else {
96                         _buffer = copy._buffer;
97                 }
98
99                 _size = copy._size;
100                 return *this;
101         }
102         
103         inline bool operator==(const MidiEvent& other) const {
104                 if (_time != other._time)
105                         return false;
106
107                 if (_size != other._size)
108                         return false;
109
110                 if (_buffer == other._buffer)
111                         return true;
112
113                 for (size_t i=0; i < _size; ++i)
114                         if (_buffer[i] != other._buffer[i])
115                                 return false;
116
117                 return true;
118         }
119         
120         inline bool operator!=(const MidiEvent& other) const { return ! operator==(other); }
121
122         inline bool owns_buffer() const { return _owns_buffer; }
123         
124         inline void set_buffer(Byte* buf, bool own) {
125                 if (_owns_buffer) {
126                         free(_buffer);
127                         _buffer = NULL;
128                 }
129                 _buffer = buf;
130                 _owns_buffer = own;
131         }
132
133 #else
134
135         inline void set_buffer(Byte* buf) { _buffer = buf; }
136
137 #endif // MIDI_EVENT_ALLOW_ALLOC
138
139         inline double      time()        const { return _time; }
140         inline double&     time()              { return _time; }
141         inline uint32_t    size()        const { return _size; }
142         inline uint32_t&   size()              { return _size; }
143         inline uint8_t     type()        const { return (_buffer[0] & 0xF0); }
144         inline uint8_t     channel()     const { return (_buffer[0] & 0x0F); }
145         inline bool        is_note_on()  const { return (type() == MIDI_CMD_NOTE_ON); }
146         inline bool        is_note_off() const { return (type() == MIDI_CMD_NOTE_OFF); }
147         inline bool        is_cc()       const { return (type() == MIDI_CMD_CONTROL); }
148         inline bool        is_note()     const { return (is_note_on() || is_note_off()); }
149         inline uint8_t     note()        const { return (_buffer[1]); }
150         inline uint8_t     velocity()    const { return (_buffer[2]); }
151         inline uint8_t     cc_number()   const { return (_buffer[1]); }
152         inline uint8_t     cc_value()    const { return (_buffer[2]); }
153         inline const Byte* buffer()      const { return _buffer; }
154         inline Byte*&      buffer()            { return _buffer; }
155
156 private:
157         double   _time;   /**< Sample index (or beat time) at which event is valid */
158         uint32_t _size;   /**< Number of bytes of data in \a buffer */
159         Byte*    _buffer; /**< Raw MIDI data */
160
161 #ifdef MIDI_EVENT_ALLOW_ALLOC
162         bool _owns_buffer; /**< Whether buffer is locally allocated */
163 #endif
164 };
165
166
167 } // namespace ARDOUR
168
169 #endif /* __ardour_midi_event_h__ */