mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-04 04:39:33 +01:00
locating no longer interrupts process()
This commit is contained in:
parent
ccc3cc14a2
commit
baa0805d1e
2 changed files with 86 additions and 76 deletions
|
|
@ -1452,7 +1452,6 @@ class LIBARDOUR_API Session : public PBD::StatefulDestructible, public PBD::Scop
|
|||
PostTransportReverse|
|
||||
PostTransportCurveRealloc|
|
||||
PostTransportAudition|
|
||||
PostTransportLocate|
|
||||
PostTransportStop|
|
||||
PostTransportClearSubstate);
|
||||
|
||||
|
|
|
|||
|
|
@ -239,7 +239,7 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
uint32_t n;
|
||||
boost::shared_ptr<ChannelList> c = channels.reader();
|
||||
ChannelList::iterator chan;
|
||||
frameoffset_t playback_distance = nframes;
|
||||
frameoffset_t playback_distance;
|
||||
MonitorState ms = _route->monitoring_state ();
|
||||
|
||||
if (_active) {
|
||||
|
|
@ -269,15 +269,17 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
interpolation.set_speed (speed);
|
||||
midi_interpolation.set_speed (speed);
|
||||
playback_distance = midi_interpolation.distance (nframes);
|
||||
}
|
||||
|
||||
if (speed < 0.0) {
|
||||
playback_distance = -playback_distance;
|
||||
if (speed < 0.0) {
|
||||
playback_distance = -playback_distance;
|
||||
}
|
||||
} else {
|
||||
playback_distance = nframes;
|
||||
}
|
||||
|
||||
BufferSet& scratch_bufs (_session.get_scratch_buffers (bufs.count()));
|
||||
const bool still_locating = _session.locate_pending();
|
||||
|
||||
if (!result_required || ((ms & MonitoringDisk) == 0)) {
|
||||
if (!result_required || ((ms & MonitoringDisk) == 0) || still_locating) {
|
||||
|
||||
/* no need for actual disk data, just advance read pointer and return */
|
||||
|
||||
|
|
@ -285,6 +287,12 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
(*chan)->buf->increment_read_ptr (playback_distance);
|
||||
}
|
||||
|
||||
/* if monitoring disk but locating, put silence in the buffers */
|
||||
|
||||
if (still_locating && (ms == MonitoringDisk)) {
|
||||
bufs.silence (playback_distance, 0);
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
/* we need audio data from disk */
|
||||
|
|
@ -302,7 +310,7 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
for (n = 0, chan = c->begin(); chan != c->end(); ++chan, ++n) {
|
||||
|
||||
ChannelInfo* chaninfo (*chan);
|
||||
AudioBuffer& buf (bufs.get_audio (n%n_buffers));
|
||||
AudioBuffer& output (bufs.get_audio (n%n_buffers));
|
||||
Sample* disk_signal = 0; /* assignment not really needed but it keeps the compiler quiet and helps track bugs */
|
||||
|
||||
if (ms & MonitoringInput) {
|
||||
|
|
@ -310,7 +318,7 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
disk_signal = scratch_bufs.get_audio(n).data ();
|
||||
} else {
|
||||
/* no input stream needed, just overwrite buffers */
|
||||
disk_signal = buf.data ();
|
||||
disk_signal = output.data ();
|
||||
}
|
||||
|
||||
chaninfo->buf->get_read_vector (&(*chan)->rw_vector);
|
||||
|
|
@ -373,7 +381,7 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
|
||||
if ((speed != 0.0) && (ms & MonitoringInput)) {
|
||||
/* mix the disk signal into the input signal (already in bufs) */
|
||||
mix_buffers_no_gain (buf.data(), disk_signal, speed == 0.0 ? nframes : playback_distance);
|
||||
mix_buffers_no_gain (output.data(), disk_signal, speed == 0.0 ? nframes : playback_distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -381,83 +389,86 @@ DiskReader::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame,
|
|||
/* MIDI data handling */
|
||||
|
||||
if (!_session.declick_out_pending()) {
|
||||
if (ms & MonitoringDisk) {
|
||||
if (ms & MonitoringDisk && !still_locating) {
|
||||
get_midi_playback (bufs.get_midi (0), playback_distance, ms, scratch_bufs, speed, playback_distance);
|
||||
}
|
||||
}
|
||||
|
||||
if (speed < 0.0) {
|
||||
playback_sample -= playback_distance;
|
||||
} else {
|
||||
playback_sample += playback_distance;
|
||||
}
|
||||
if (!still_locating) {
|
||||
|
||||
if (_playlists[DataType::AUDIO]) {
|
||||
if (!c->empty()) {
|
||||
if (_slaved) {
|
||||
if (c->front()->buf->write_space() >= c->front()->buf->bufsize() / 2) {
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: slaved, write space = %2 of %3\n", name(), c->front()->buf->write_space(),
|
||||
c->front()->buf->bufsize()));
|
||||
if (speed < 0.0) {
|
||||
playback_sample -= playback_distance;
|
||||
} else {
|
||||
playback_sample += playback_distance;
|
||||
}
|
||||
|
||||
if (_playlists[DataType::AUDIO]) {
|
||||
if (!c->empty()) {
|
||||
if (_slaved) {
|
||||
if (c->front()->buf->write_space() >= c->front()->buf->bufsize() / 2) {
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: slaved, write space = %2 of %3\n", name(), c->front()->buf->write_space(),
|
||||
c->front()->buf->bufsize()));
|
||||
_need_butler = true;
|
||||
}
|
||||
} else {
|
||||
if ((framecnt_t) c->front()->buf->write_space() >= _chunk_frames) {
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: write space = %2 of %3\n", name(), c->front()->buf->write_space(),
|
||||
_chunk_frames));
|
||||
_need_butler = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_playlists[DataType::MIDI]) {
|
||||
/* MIDI butler needed part */
|
||||
|
||||
uint32_t frames_read = g_atomic_int_get(const_cast<gint*>(&_frames_read_from_ringbuffer));
|
||||
uint32_t frames_written = g_atomic_int_get(const_cast<gint*>(&_frames_written_to_ringbuffer));
|
||||
|
||||
/*
|
||||
cerr << name() << " MDS written: " << frames_written << " - read: " << frames_read <<
|
||||
" = " << frames_written - frames_read
|
||||
<< " + " << playback_distance << " < " << midi_readahead << " = " << need_butler << ")" << endl;
|
||||
*/
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* furthermore..
|
||||
*
|
||||
* Doing heavy GUI operations[1] can stall also the butler.
|
||||
* The RT-thread meanwhile will happily continue and
|
||||
* ‘frames_read’ (from buffer to output) will become larger
|
||||
* than ‘frames_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 (frames_read - frames_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 (frames_read <= frames_written) {
|
||||
if ((frames_written - frames_read) + playback_distance < midi_readahead) {
|
||||
_need_butler = true;
|
||||
}
|
||||
} else {
|
||||
if ((framecnt_t) c->front()->buf->write_space() >= _chunk_frames) {
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1: write space = %2 of %3\n", name(), c->front()->buf->write_space(),
|
||||
_chunk_frames));
|
||||
_need_butler = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (_playlists[DataType::MIDI]) {
|
||||
/* MIDI butler needed part */
|
||||
|
||||
uint32_t frames_read = g_atomic_int_get(const_cast<gint*>(&_frames_read_from_ringbuffer));
|
||||
uint32_t frames_written = g_atomic_int_get(const_cast<gint*>(&_frames_written_to_ringbuffer));
|
||||
|
||||
/*
|
||||
cerr << name() << " MDS written: " << frames_written << " - read: " << frames_read <<
|
||||
" = " << frames_written - frames_read
|
||||
<< " + " << playback_distance << " < " << midi_readahead << " = " << need_butler << ")" << endl;
|
||||
*/
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
/* furthermore..
|
||||
*
|
||||
* Doing heavy GUI operations[1] can stall also the butler.
|
||||
* The RT-thread meanwhile will happily continue and
|
||||
* ‘frames_read’ (from buffer to output) will become larger
|
||||
* than ‘frames_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 (frames_read - frames_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 (frames_read <= frames_written) {
|
||||
if ((frames_written - frames_read) + playback_distance < midi_readahead) {
|
||||
_need_butler = true;
|
||||
}
|
||||
} else {
|
||||
_need_butler = true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_TRACE (DEBUG::Butler, string_compose ("%1 reader run, needs butler = %2\n", name(), _need_butler));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue