Tidy.
[ardour.git] / libs / ardour / ardour / midi_buffer.h
index 79a8391e72c6122c35c0be74fb0df963e51c4248..8ea5e32e81a404a09d18d1bbb010e9ee73287d9c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2006 Paul Davis 
+    Copyright (C) 2006-2009 Paul Davis 
     Author: Dave Robillard
     
     This program is free software; you can redistribute it and/or modify it
 #ifndef __ardour_midi_buffer_h__
 #define __ardour_midi_buffer_h__
 
+#include <evoral/midi_util.h>
+#include <midi++/event.h>
 #include <ardour/buffer.h>
-#include <ardour/midi_event.h>
+#include <ardour/event_type_map.h>
 
 namespace ARDOUR {
 
@@ -30,6 +32,8 @@ namespace ARDOUR {
 class MidiBuffer : public Buffer
 {
 public:
+       typedef nframes_t TimeType;
+
        MidiBuffer(size_t capacity);
        ~MidiBuffer();
 
@@ -39,27 +43,55 @@ public:
        
        void copy(const MidiBuffer& copy);
 
-       bool  push_back(const ARDOUR::MidiEvent& event);
-       bool  push_back(const jack_midi_event_t& event);
-       Byte* reserve(double time, size_t size);
-       
-       const MidiEvent& operator[](size_t i) const { assert(i < _size); return _events[i]; }
-       MidiEvent& operator[](size_t i) { assert(i < _size); return _events[i]; }
+       bool     push_back(const Evoral::MIDIEvent<TimeType>& event);
+       bool     push_back(const jack_midi_event_t& event);
+       uint8_t* reserve(TimeType time, size_t size);
 
-       bool merge(const MidiBuffer& a, const MidiBuffer& b);
+       void resize(size_t);
 
-private:
-       // FIXME: Jack needs to tell us this
-       static const size_t MAX_EVENT_SIZE = 4; // bytes
+       bool merge(const MidiBuffer& a, const MidiBuffer& b);
+       bool merge_in_place(const MidiBuffer &other);
        
-       /* We use _size as "number of events", so the size of _data is
-        * (_size * MAX_EVENT_SIZE)
-        */
+       template<typename BufferType, typename MIDIEventType>
+       struct iterator_base {
+               iterator_base<BufferType, MIDIEventType>(BufferType& b, size_t o) : buffer(b), offset(o) {}
+               inline MIDIEventType operator*() const {
+                       uint8_t* ev_start = buffer._data + offset + sizeof(TimeType);
+                       int event_size = Evoral::midi_event_size(ev_start);
+                       assert(event_size >= 0);
+                       return MIDIEventType(EventTypeMap::instance().midi_event_type(*ev_start),
+                                       *((TimeType*)(buffer._data + offset)),
+                                       event_size, ev_start);
+               }
+               inline iterator_base<BufferType, MIDIEventType>& operator++() {
+                       uint8_t* ev_start = buffer._data + offset + sizeof(TimeType);
+                       int event_size = Evoral::midi_event_size(ev_start);
+                       assert(event_size >= 0);
+                       offset += sizeof(TimeType) + event_size;
+                       return *this;
+               }
+               inline bool operator!=(const iterator_base<BufferType, MIDIEventType>& other) const {
+                       return (&buffer != &other.buffer) || (offset != other.offset);
+               }
+               BufferType&     buffer;
+               size_t          offset;
+       };
+       
+       typedef iterator_base< MidiBuffer, Evoral::MIDIEvent<TimeType> >             iterator;
+       typedef iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> > const_iterator;
+
+       iterator begin() { return iterator(*this, 0); }
+       iterator end()   { return iterator(*this, _size); }
 
-       /* FIXME: this is utter crap.  rewrite as a flat/packed buffer like MidiRingBuffer */
+       const_iterator begin() const { return const_iterator(*this, 0); }
+       const_iterator end()   const { return const_iterator(*this, _size); }
 
-       MidiEvent* _events; ///< Event structs that point to offsets in _data
-       Byte*      _data;   ///< MIDI, straight up.  No time stamps.
+private:
+       friend class iterator_base< MidiBuffer, Evoral::MIDIEvent<TimeType> >;
+       friend class iterator_base< const MidiBuffer, const Evoral::MIDIEvent<TimeType> >;
+       
+       size_t   _size; ///< Size in bytes of used portion of _data
+       uint8_t* _data; ///< timestamp, event, timestamp, event, ...
 };