- /* frames_read will generally be less than frames_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.
- */
+ /* 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;
+ }