mirror of
https://github.com/Ardour/ardour.git
synced 2026-01-06 05:35:47 +01:00
fix behaviour of AsyncMIDIPort so that large amounts of data are handled well.
Increased the size of the FIFO that acts as the intermediate between writers and the MidiBuffer. Changed implementation of ::write() to notice if MidiBuffer::push_back() fails, and then just leave data queued for subsequent calls to ::flush_output_fifo(). Note: the logic here will be broken by invalid events/data, which ALSO cause MidiBuffer::push_back() to return false. That needs fixing
This commit is contained in:
parent
cdd415cdaf
commit
f74eab854a
1 changed files with 30 additions and 9 deletions
|
|
@ -47,7 +47,7 @@ AsyncMIDIPort::AsyncMIDIPort (string const & name, PortFlags flags)
|
|||
, _currently_in_cycle (false)
|
||||
, _last_write_timestamp (0)
|
||||
, have_timer (false)
|
||||
, output_fifo (512)
|
||||
, output_fifo (2048)
|
||||
, input_fifo (1024)
|
||||
, _xthread (true)
|
||||
{
|
||||
|
|
@ -68,7 +68,7 @@ void
|
|||
AsyncMIDIPort::flush_output_fifo (MIDI::pframes_t nframes)
|
||||
{
|
||||
RingBuffer< Evoral::Event<double> >::rw_vector vec = { { 0, 0 }, { 0, 0 } };
|
||||
size_t written;
|
||||
size_t written = 0;
|
||||
|
||||
output_fifo.get_read_vector (&vec);
|
||||
|
||||
|
|
@ -77,22 +77,34 @@ AsyncMIDIPort::flush_output_fifo (MIDI::pframes_t nframes)
|
|||
if (vec.len[0]) {
|
||||
Evoral::Event<double>* evp = vec.buf[0];
|
||||
|
||||
assert (evp->size());
|
||||
assert (evp->buffer());
|
||||
|
||||
for (size_t n = 0; n < vec.len[0]; ++n, ++evp) {
|
||||
mb.push_back (evp->time(), evp->size(), evp->buffer());
|
||||
if (mb.push_back (evp->time(), evp->size(), evp->buffer())) {
|
||||
written++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vec.len[1]) {
|
||||
Evoral::Event<double>* evp = vec.buf[1];
|
||||
|
||||
assert (evp->size());
|
||||
assert (evp->buffer());
|
||||
|
||||
for (size_t n = 0; n < vec.len[1]; ++n, ++evp) {
|
||||
mb.push_back (evp->time(), evp->size(), evp->buffer());
|
||||
if (mb.push_back (evp->time(), evp->size(), evp->buffer())) {
|
||||
written++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((written = vec.len[0] + vec.len[1]) != 0) {
|
||||
output_fifo.increment_read_idx (written);
|
||||
}
|
||||
/* do this "atomically" after we're done pushing events into the
|
||||
* MidiBuffer
|
||||
*/
|
||||
|
||||
output_fifo.increment_read_idx (written);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -211,12 +223,21 @@ AsyncMIDIPort::write (const MIDI::byte * msg, size_t msglen, MIDI::timestamp_t t
|
|||
}
|
||||
|
||||
if (vec.len[0]) {
|
||||
if (!vec.buf[0]->owns_buffer()) {
|
||||
/* force each event inside the ringbuffer to own its
|
||||
own buffer, but let that be null and of zero size
|
||||
initially. When ::set() is called, the buffer will
|
||||
be allocated to hold a *copy* of the data we're
|
||||
storing, and then that buffer will be used over and
|
||||
over, occasionally being upwardly resized as
|
||||
necessary.
|
||||
*/
|
||||
if (!vec.buf[0]->owns_buffer()) {
|
||||
vec.buf[0]->set_buffer (0, 0, true);
|
||||
}
|
||||
vec.buf[0]->set (msg, msglen, timestamp);
|
||||
} else {
|
||||
if (!vec.buf[1]->owns_buffer()) {
|
||||
/* see comment in previous branch of if() statement */
|
||||
if (!vec.buf[1]->owns_buffer()) {
|
||||
vec.buf[1]->set_buffer (0, 0, true);
|
||||
}
|
||||
vec.buf[1]->set (msg, msglen, timestamp);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue