Improve import status messages slightly.
[ardour.git] / libs / ardour / midi_buffer.cc
index df4ee135588d62836ac0ada366b0adf0738ca7f6..ae3071a53cd673fed85841a7530b9b8446840f50 100644 (file)
 */
 
 #include <iostream>
-#include <ardour/midi_buffer.h>
-
-#ifdef __x86_64__
-static const int CPU_CACHE_ALIGN = 64;
-#else
-static const int CPU_CACHE_ALIGN = 16; /* arguably 32 on most arches, but it matters less */
-#endif
+#include "pbd/malign.h"
+#include "ardour/midi_buffer.h"
 
 using namespace std;
 using namespace ARDOUR;
 
-
 // FIXME: mirroring for MIDI buffers?
 MidiBuffer::MidiBuffer(size_t capacity)
        : Buffer(DataType::MIDI, capacity)
-       , _size(0)
        , _data(0)
 {
        if (capacity) {
@@ -60,12 +53,8 @@ MidiBuffer::resize(size_t size)
 
        _size = 0;
        _capacity = size;
+       cache_aligned_malloc ((void**) &_data, _capacity);
 
-#ifdef NO_POSIX_MEMALIGN
-       _data = (uint8_t*)malloc(_capacity);
-#else
-       posix_memalign((void**)&_data, CPU_CACHE_ALIGN, _capacity);
-#endif 
        assert(_data);
 }
 
@@ -84,39 +73,42 @@ MidiBuffer::copy(const MidiBuffer& copy)
  * Note that offset and nframes refer to sample time, NOT buffer offsets or event counts.
  */
 void
-MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
+MidiBuffer::read_from (const Buffer& src, nframes_t nframes, nframes_t dst_offset, nframes_t src_offset)
 {
-       assert(src.type() == DataType::MIDI);
-       assert(&src != this);
+       assert (src.type() == DataType::MIDI);
+       assert (&src != this);
 
-       const MidiBuffer& msrc = (MidiBuffer&)src;
+       const MidiBuffer& msrc = (MidiBuffer&) src;
        
-       assert(_capacity >= msrc.size());
+       assert (_capacity >= msrc.size());
 
-       if (offset == 0) {
-               clear();
-               assert(_size == 0);
+       if (dst_offset == 0) {
+               clear ();
+               assert (_size == 0);
        }
+
+       /* XXX use dst_offset somehow */
        
        for (MidiBuffer::const_iterator i = msrc.begin(); i != msrc.end(); ++i) {
-               const Evoral::MIDIEvent ev(*i, false);
-               /*cout << this << " MidiBuffer::read_from event type: " << int(ev.type())
-                               << " time: " << ev.time() << " size: " << ev.size()
-                               << " status: " << (int)*ev.buffer() << " buffer size: " << _size << endl;*/
-               if (ev.time() < offset) {
-                       //cout << "MidiBuffer::read_from skipped event before " << offset << endl;
-               } else if (ev.time() < (nframes + offset)) {
-                       //cout << "MidiBuffer::read_from appending event" << endl;
-                       push_back(ev);
-               } else {
-                       //cerr << "MidiBuffer::read_from skipped event after "
-                       //      << nframes << " + " << offset << endl;
+               const Evoral::MIDIEvent<TimeType> ev(*i, false);
+               if (ev.time() >= src_offset && ev.time() < (nframes+src_offset)) {
+                       push_back (ev);
                }
        }
 
        _silent = src.silent();
 }
 
+void
+MidiBuffer::merge_from (const Buffer& src, nframes_t /*nframes*/, nframes_t /*dst_offset*/, nframes_t /*src_offset*/)
+{
+       const MidiBuffer* mbuf = dynamic_cast<const MidiBuffer*>(&src);
+       assert (mbuf);
+       assert (mbuf != this);
+
+       /* XXX use nframes, and possible offsets */
+       merge_in_place (*mbuf);
+}
 
 /** Push an event into the buffer.
  *
@@ -126,19 +118,53 @@ MidiBuffer::read_from(const Buffer& src, nframes_t nframes, nframes_t offset)
  * @return false if operation failed (not enough room)
  */
 bool
-MidiBuffer::push_back(const Evoral::MIDIEvent& ev)
+MidiBuffer::push_back(const Evoral::MIDIEvent<TimeType>& ev)
 {
-       const size_t stamp_size = sizeof(Evoral::EventTime);
+       const size_t stamp_size = sizeof(TimeType);
+       /*cerr << "MidiBuffer: pushing event @ " << ev.time()
+               << " size = " << ev.size() << endl;*/
+       
        if (_size + stamp_size + ev.size() >= _capacity) {
                cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
                return false;
        }
 
+       if (!Evoral::midi_event_is_valid(ev.buffer(), ev.size())) {
+               cerr << "WARNING: MidiBuffer ignoring illegal MIDI event" << endl;
+               return false;
+       }
+
+       push_back(ev.time(), ev.size(), ev.buffer());
+       
+       return true;
+}
+
+
+/** Push an event into the buffer.
+ * @return false if operation failed (not enough room)
+ */
+bool
+MidiBuffer::push_back(TimeType time, size_t size, const uint8_t* data)
+{
+       const size_t stamp_size = sizeof(TimeType);
+       /*cerr << "MidiBuffer: pushing event @ " << ev.time()
+               << " size = " << ev.size() << endl;*/
+       
+       if (_size + stamp_size + size >= _capacity) {
+               cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
+               return false;
+       }
+
+       if (!Evoral::midi_event_is_valid(data, size)) {
+               cerr << "WARNING: MidiBuffer ignoring illegal MIDI event" << endl;
+               return false;
+       }
+
        uint8_t* const write_loc = _data + _size;
-       *((Evoral::EventTime*)write_loc) = ev.time();
-       memcpy(write_loc + stamp_size, ev.buffer(), ev.size());
+       *((TimeType*)write_loc) = time;
+       memcpy(write_loc + stamp_size, data, size);
 
-       _size += stamp_size + ev.size();
+       _size += stamp_size + size;
        _silent = false;
        
        return true;
@@ -155,14 +181,19 @@ MidiBuffer::push_back(const Evoral::MIDIEvent& ev)
 bool
 MidiBuffer::push_back(const jack_midi_event_t& ev)
 {
-       const size_t stamp_size = sizeof(Evoral::EventTime);
+       const size_t stamp_size = sizeof(TimeType);
        if (_size + stamp_size + ev.size >= _capacity) {
                cerr << "MidiBuffer::push_back failed (buffer is full)" << endl;
                return false;
        }
+       
+       if (!Evoral::midi_event_is_valid(ev.buffer, ev.size)) {
+               cerr << "WARNING: MidiBuffer ignoring illegal MIDI event" << endl;
+               return false;
+       }
 
        uint8_t* const write_loc = _data + _size;
-       *((Evoral::EventTime*)write_loc) = ev.time;
+       *((TimeType*)write_loc) = ev.time;
        memcpy(write_loc + stamp_size, ev.buffer, ev.size);
 
        _size += stamp_size + ev.size;
@@ -180,15 +211,19 @@ MidiBuffer::push_back(const jack_midi_event_t& ev)
  * location, or the buffer will be corrupted and very nasty things will happen.
  */
 uint8_t*
-MidiBuffer::reserve(Evoral::EventTime time, size_t size)
+MidiBuffer::reserve(TimeType time, size_t size)
 {
-       const size_t stamp_size = sizeof(Evoral::EventTime);
+       const size_t stamp_size = sizeof(TimeType);
        if (_size + stamp_size + size >= _capacity) {
                return 0;
        }
 
-       uint8_t* const write_loc = _data + _size;
-       *((Evoral::EventTime*)write_loc) = time;
+       // write timestamp
+       uint8_t* write_loc = _data + _size;
+       *((TimeType*)write_loc) = time;
+       
+       // move write_loc to begin of MIDI buffer data to write to
+       write_loc += stamp_size;
 
        _size += stamp_size + size;
        _silent = false;
@@ -198,11 +233,11 @@ MidiBuffer::reserve(Evoral::EventTime time, size_t size)
 
 
 void
-MidiBuffer::silence(nframes_t dur, nframes_t offset)
+MidiBuffer::silence (nframes_t /*nframes*/, nframes_t /*offset*/)
 {
-       // FIXME use parameters
-       if (offset != 0)
-               cerr << "WARNING: MidiBuffer::silence w/ offset != 0 (not implemented)" << endl;
+       /* XXX iterate over existing events, find all in range given by offset & nframes,
+          and delete them.
+       */
 
        _size = 0;
        _silent = true;