+ uint32_t samples_read = g_atomic_int_get(const_cast<gint*>(&_samples_read_from_ringbuffer));
+ uint32_t samples_written = g_atomic_int_get(const_cast<gint*>(&_samples_written_to_ringbuffer));
+
+ /*
+ cerr << name() << " MDS written: " << samples_written << " - read: " << samples_read <<
+ " = " << samples_written - samples_read
+ << " + " << disk_samples_to_consume << " < " << midi_readahead << " = " << need_butler << ")" << endl;
+ */
+
+ /* samples_read will generally be less than samples_written, but
+ * immediately after an overwrite, we can end up having read some data
+ * before we've written any. we don't need to trip an assert() on this,
+ * but we do need to check so that the decision on whether or not we
+ * need the butler is done correctly.
+ */
+
+ /* furthermore..
+ *
+ * Doing heavy GUI operations[1] can stall also the butler.
+ * The RT-thread meanwhile will happily continue and
+ * ‘samples_read’ (from buffer to output) will become larger
+ * than ‘samples_written’ (from disk to buffer).
+ *
+ * The disk-stream is now behind..
+ *
+ * In those cases the butler needs to be summed to refill the buffer (done now)
+ * AND we need to skip (samples_read - samples_written). ie remove old events
+ * 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
+ * of a track with a large (think beethoven :) midi-region also did the
+ * trick. The playhead stalls for 2 or 3 sec, until the context-menu shows.
+ *
+ * In both cases the root cause is that redrawing MIDI regions on the GUI is still very slow
+ * and can stall
+ */
+ if (samples_read <= samples_written) {
+ if ((samples_written - samples_read) + disk_samples_to_consume < midi_readahead) {
+ butler_required = true;
+ }
+ } else {
+ butler_required = true;
+ }