cont’d work on a16dd7c, fixes #6170
authorRobin Gareus <robin@gareus.org>
Thu, 12 Mar 2015 14:21:31 +0000 (15:21 +0100)
committerRobin Gareus <robin@gareus.org>
Thu, 12 Mar 2015 14:23:05 +0000 (15:23 +0100)
libs/ardour/ardour/midi_ring_buffer.h
libs/ardour/midi_diskstream.cc
libs/ardour/midi_ring_buffer.cc

index 0d27de3c16caeae5872bc054528446f5ab099226..d89d85b2d7c2bc85c4b3610639cb9a660f8ec537 100644 (file)
@@ -49,6 +49,7 @@ public:
        inline bool read_contents(uint32_t size, uint8_t* buf);
 
        size_t read(MidiBuffer& dst, framepos_t start, framepos_t end, framecnt_t offset=0, bool stop_on_overflow_in_destination=false);
+       size_t skip_to(framepos_t start);
 
        void dump(std::ostream& dst);
        void flush (framepos_t start, framepos_t end);
index 80faab1f9d463da428521c226b1917d5414c3b4d..cd7e530a4294d05a82d4954fa9c2d4c042eb8508 100644 (file)
@@ -621,7 +621,7 @@ MidiDiskstream::commit (framecnt_t playback_distance)
         *
         * In those cases the butler needs to be summed to refill the buffer (done now)
         * AND we need to skip (frames_read - frames_written). ie remove old events
-        * before playback_sample from the rinbuffer. (not yet done)
+        * before playback_sample from the rinbuffer.
         *
         * [1] one way to do so is described at #6170.
         * For me just popping up the context-menu on a MIDI-track header
@@ -1440,6 +1440,8 @@ MidiDiskstream::get_playback (MidiBuffer& dst, framecnt_t nframes)
 
        size_t events_read = 0; 
 
+       _playback_buf->skip_to (playback_sample);
+
        if (loc) {
                framepos_t effective_start;
 
index 9fbd9dfdff78183d683c495160a3289261954857..5bd3f947e27ad6ace2fe33769b93bb598791ea92 100644 (file)
@@ -60,6 +60,10 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
                ev_time = *(reinterpret_cast<T*>((uintptr_t)peekbuf));
                ev_size = *(reinterpret_cast<uint32_t*>((uintptr_t)(peekbuf + sizeof(T) + sizeof (Evoral::EventType))));
 
+               if (this->read_space() < ev_size) {
+                       break;;
+               }
+
                if (ev_time >= end) {
                        DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MRB event @ %1 past end @ %2\n", ev_time, end));
                        break;
@@ -124,6 +128,59 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
        return count;
 }
 
+template<typename T>
+size_t
+MidiRingBuffer<T>::skip_to(framepos_t start)
+{
+       if (this->read_space() == 0) {
+               return 0;
+       }
+
+       T                 ev_time;
+       uint32_t          ev_size;
+       size_t            count = 0;
+       const size_t      prefix_size = sizeof(T) + sizeof(Evoral::EventType) + sizeof(uint32_t);
+
+       while (this->read_space() >= prefix_size) {
+
+               uint8_t peekbuf[prefix_size];
+               this->peek (peekbuf, prefix_size);
+
+               ev_time = *(reinterpret_cast<T*>((uintptr_t)peekbuf));
+               ev_size = *(reinterpret_cast<uint32_t*>((uintptr_t)(peekbuf + sizeof(T) + sizeof (Evoral::EventType))));
+
+               if (ev_time >= start) {
+                       return count;
+               }
+
+               if (this->read_space() < ev_size) {
+                       continue;
+               }
+
+               this->increment_read_ptr (prefix_size);
+
+               uint8_t status;
+               bool r = this->peek (&status, sizeof(uint8_t));
+               assert (r); // If this failed, buffer is corrupt, all hope is lost
+
+               ++count;
+
+               if (ev_size < 8) {
+                       this->increment_read_ptr (ev_size);
+               } else {
+                       // we only track note on/off, 8 bytes are plenty.
+                       uint8_t write_loc[8];
+                       bool success = read_contents (ev_size, write_loc);
+                       if (success) {
+                               _tracker.track(write_loc);
+                       }
+               }
+       }
+       return count;
+}
+
+
+
 template<typename T>
 void
 MidiRingBuffer<T>::flush (framepos_t /*start*/, framepos_t end)