13
0

cont’d work on a16dd7c, fixes #6170

This commit is contained in:
Robin Gareus 2015-03-12 15:21:31 +01:00
parent a16dd7c071
commit 7bb9d04859
3 changed files with 61 additions and 1 deletions

View 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);

View 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;

View 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)