2 Copyright (C) 2013 Waves Audio Ltd.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 #include "pbd/debug.h"
21 #include "pbd/compose.h"
24 #include "waves_midi_event.h"
26 using namespace ARDOUR;
29 WavesMidiEvent::WavesMidiEvent (PmTimestamp timestamp)
31 , _timestamp (timestamp)
39 WavesMidiEvent::WavesMidiEvent (PmTimestamp timestamp, const uint8_t* data, size_t datalen)
41 , _timestamp (timestamp)
42 , _data (data && datalen ? new uint8_t[ (datalen < sizeof (PmMessage)) ? sizeof (PmMessage) : datalen] : NULL)
43 , _state (data && datalen ? COMPLETE : BROKEN)
45 DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "WavesMidiEvent::WavesMidiEvent (const WavesMidiEvent& source) : Size=%1---%2\n", _size, datalen));
46 if (_state == COMPLETE) {
47 DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "\t\t\t Allocated Size=%1\n", ((datalen < sizeof (PmMessage)) ? sizeof (PmMessage) : datalen)));
48 memcpy (_data, data, datalen);
51 if (DEBUG::WavesMIDI & PBD::debug_bits) {
53 for (size_t i=0; i < datalen; ++i) {
54 DEBUG_STR_APPEND(a,std::hex);
55 DEBUG_STR_APPEND(a,"0x");
56 DEBUG_STR_APPEND(a,(int)data[i]);
57 DEBUG_STR_APPEND(a,' ');
59 DEBUG_STR_APPEND(a,'\n');
60 DEBUG_TRACE (DEBUG::WavesMIDI, DEBUG_STR(a).str());
67 WavesMidiEvent::WavesMidiEvent (const WavesMidiEvent& source)
68 : _size (source.size ())
69 , _timestamp (source.timestamp ())
70 , _data ((source.size () && source.const_data ()) ? new uint8_t[ (source.size () < sizeof (PmMessage)) ? sizeof (PmMessage) : source.size ()] : NULL)
71 , _state (source.state () )
73 DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "WavesMidiEvent::WavesMidiEvent (const WavesMidiEvent& source) : Size=%1---%2\n", _size, source.size ()));
74 DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "\t\t\t Allocated Size=%1\n", ((source.size () < sizeof (PmMessage)) ? sizeof (PmMessage) : source.size ())));
75 if (_data && source.const_data ()) {
76 memcpy (_data, source.const_data (), source.size ());
79 if (DEBUG::WavesMIDI & PBD::debug_bits) {
81 for (size_t i=0; i < source.size(); ++i) {
82 DEBUG_STR_APPEND(a,std::hex);
83 DEBUG_STR_APPEND(a,"0x");
84 DEBUG_STR_APPEND(a,(int)source.const_data()[i]);
85 DEBUG_STR_APPEND(a,' ');
87 DEBUG_STR_APPEND(a,'\n');
88 DEBUG_TRACE (DEBUG::WavesMIDI, DEBUG_STR(a).str());
95 WavesMidiEvent::~WavesMidiEvent ()
101 WavesMidiEvent *WavesMidiEvent::append_data (const PmEvent &midi_event)
107 DEBUG_TRACE (DEBUG::WavesMIDI, "WavesMidiEvent::append_data (): NO case INCOMPLETE\n");
112 size_t message_size = _midi_message_size (midi_event.message);
113 uint8_t message_status = Pm_MessageStatus (midi_event.message);
115 if (_data == NULL) { // This is a first event to add
116 bool sysex = (message_status == SYSEX);
117 _data = new unsigned char [sysex ? PM_DEFAULT_SYSEX_BUFFER_SIZE : sizeof (PmMessage)];
120 DEBUG_TRACE (DEBUG::WavesMIDI, "WavesMidiEvent::append_data (): SHORT MSG\n");
121 * (PmMessage*)_data = 0;
122 switch (message_size) {
126 _size = message_size;
127 DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "WavesMidiEvent::append_data (): size = %1\n", _size));
130 DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "WavesMidiEvent::append_data (): WRONG MESSAGE SIZE (%1 not %2) %3 [%4 %5 %6 %7] %8\n",
133 (int) ((unsigned char*)&midi_event)[0],
134 (int) ((unsigned char*)&midi_event)[1],
135 (int) ((unsigned char*)&midi_event)[2],
136 (int) ((unsigned char*)&midi_event)[3],
141 memcpy (_data, &midi_event.message, _size);
143 DEBUG_TRACE (DEBUG::WavesMIDI, string_compose ( "\t\t\t size = %1\n", _size));
148 // Now let's parse to sysex msg
149 if (message_status >= REAL_TIME_FIRST) { // Nested Real Time MIDI event
150 WavesMidiEvent *waves_midi_message = new WavesMidiEvent (midi_event.timestamp);
151 waves_midi_message->append_data (midi_event);
152 return waves_midi_message;
155 if (message_status >= STATUS_FIRST && (message_status != EOX) && _size) { // Certainly it's a broken SYSEX case
156 WavesMidiEvent *waves_midi_message = new WavesMidiEvent (midi_event.timestamp);
157 waves_midi_message->append_data (midi_event);
158 return waves_midi_message;
161 const uint8_t* source_data ((uint8_t*)&midi_event.message);
163 for (size_t i = 0; i < sizeof (midi_event.message); ++i) {
164 _data[_size] = source_data[i];
167 if (source_data[i] == EOX) { // Ended SYSEX message
175 size_t WavesMidiEvent::_midi_message_size (PmMessage midi_message)
177 static int high_lengths[] = {
178 1, 1, 1, 1, 1, 1, 1, 1, /* 0x00 through 0x70 */
179 3, 3, 3, 3, 2, 2, 3, 1 /* 0x80 through 0xf0 */
182 static int low_lengths[] = {
183 1, 2, 3, 2, 1, 1, 1, 1, /* 0xf0 through 0xf7 */
184 1, 1, 1, 1, 1, 1, 1, 1 /* 0xf8 through 0xff */
187 int midi_message_status = Pm_MessageStatus (midi_message);
189 if (midi_message_status < STATUS_FIRST) {
190 return sizeof (midi_message);
193 int high = midi_message_status >> 4;
194 int low = midi_message_status & 0xF;
196 return (high != 0xF) ? high_lengths[high] : low_lengths[low];