diff options
author | Paul Davis <paul@linuxaudiosystems.com> | 2019-09-26 18:39:01 -0600 |
---|---|---|
committer | Paul Davis <paul@linuxaudiosystems.com> | 2019-09-26 18:39:56 -0600 |
commit | f5f452bf9c9637063a819a69980456767ea5da59 (patch) | |
tree | 166ebcce3aebf378dd1b21c811f416b737fe2a02 /libs/ardour/disk_writer.cc | |
parent | 9d65350600560abfbf324177c0bad66becb0ca50 (diff) |
Don't try to process MIDI input in a DiskWriter if it has no _midi_buf
... which implies it has no MIDI input port(s) either.
This fixes behaviour caused by BufferSet::get...() returning a valid MidiBuffer because it was
based on using the _available count within the BufferSet, even though the _count value
indicated there was no buffer available (to match the I/O configuration of the Route).
Diffstat (limited to 'libs/ardour/disk_writer.cc')
-rw-r--r-- | libs/ardour/disk_writer.cc | 135 |
1 files changed, 69 insertions, 66 deletions
diff --git a/libs/ardour/disk_writer.cc b/libs/ardour/disk_writer.cc index d9bf2fac1e..8f6a868f9f 100644 --- a/libs/ardour/disk_writer.cc +++ b/libs/ardour/disk_writer.cc @@ -515,88 +515,91 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp /* MIDI */ - // Pump entire port buffer into the ring buffer (TODO: split cycles?) - MidiBuffer& buf = bufs.get_midi (0); - boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack>(_route); - MidiChannelFilter* filter = mt ? &mt->capture_filter() : 0; + if (_midi_buf) { - assert (buf.size() == 0 || _midi_buf); + // Pump entire port buffer into the ring buffer (TODO: split cycles?) + MidiBuffer& buf = bufs.get_midi (0); + boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack>(_route); + MidiChannelFilter* filter = mt ? &mt->capture_filter() : 0; - for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) { - Evoral::Event<MidiBuffer::TimeType> ev (*i, false); - if (ev.time() + rec_offset > rec_nframes) { - break; - } + assert (buf.size() == 0 || _midi_buf); + + for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) { + Evoral::Event<MidiBuffer::TimeType> ev (*i, false); + if (ev.time() + rec_offset > rec_nframes) { + break; + } #ifndef NDEBUG - if (DEBUG_ENABLED(DEBUG::MidiIO)) { - const uint8_t* __data = ev.buffer(); - DEBUG_STR_DECL(a); - DEBUG_STR_APPEND(a, string_compose ("mididiskstream %1 capture event @ %2 + %3 sz %4 ", this, ev.time(), start_sample, ev.size())); - for (size_t i=0; i < ev.size(); ++i) { - DEBUG_STR_APPEND(a,hex); - DEBUG_STR_APPEND(a,"0x"); - DEBUG_STR_APPEND(a,(int)__data[i]); - DEBUG_STR_APPEND(a,' '); + if (DEBUG_ENABLED(DEBUG::MidiIO)) { + const uint8_t* __data = ev.buffer(); + DEBUG_STR_DECL(a); + DEBUG_STR_APPEND(a, string_compose ("mididiskstream %1 capture event @ %2 + %3 sz %4 ", this, ev.time(), start_sample, ev.size())); + for (size_t i=0; i < ev.size(); ++i) { + DEBUG_STR_APPEND(a,hex); + DEBUG_STR_APPEND(a,"0x"); + DEBUG_STR_APPEND(a,(int)__data[i]); + DEBUG_STR_APPEND(a,' '); + } + DEBUG_STR_APPEND(a,'\n'); + DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str()); } - DEBUG_STR_APPEND(a,'\n'); - DEBUG_TRACE (DEBUG::MidiIO, DEBUG_STR(a).str()); - } #endif - /* Write events to the capture buffer in samples from session start, - but ignoring looping so event time progresses monotonically. - The source knows the loop length so it knows exactly where the - event occurs in the series of recorded loops and can implement - any desirable behaviour. We don't want to send event with - transport time here since that way the source can not - reconstruct their actual time; future clever MIDI looping should - probably be implemented in the source instead of here. - */ - const samplecnt_t loop_offset = _num_captured_loops * loop_length; - const samplepos_t event_time = start_sample + loop_offset - _accumulated_capture_offset + ev.time(); - if (event_time < 0 || event_time < _first_recordable_sample) { - /* Event out of range, skip */ - continue; - } + /* Write events to the capture buffer in samples from session start, + but ignoring looping so event time progresses monotonically. + The source knows the loop length so it knows exactly where the + event occurs in the series of recorded loops and can implement + any desirable behaviour. We don't want to send event with + transport time here since that way the source can not + reconstruct their actual time; future clever MIDI looping should + probably be implemented in the source instead of here. + */ + const samplecnt_t loop_offset = _num_captured_loops * loop_length; + const samplepos_t event_time = start_sample + loop_offset - _accumulated_capture_offset + ev.time(); + if (event_time < 0 || event_time < _first_recordable_sample) { + /* Event out of range, skip */ + continue; + } - bool skip_event = false; - if (mt) { - /* skip injected immediate/out-of-band events */ - MidiBuffer const& ieb (mt->immediate_event_buffer()); - for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) { - if (*j == ev) { - skip_event = true; + bool skip_event = false; + if (mt) { + /* skip injected immediate/out-of-band events */ + MidiBuffer const& ieb (mt->immediate_event_buffer()); + for (MidiBuffer::const_iterator j = ieb.begin(); j != ieb.end(); ++j) { + if (*j == ev) { + skip_event = true; + } } } - } - if (skip_event) { - continue; - } + if (skip_event) { + continue; + } - if (!filter || !filter->filter(ev.buffer(), ev.size())) { - _midi_buf->write (event_time, ev.event_type(), ev.size(), ev.buffer()); + if (!filter || !filter->filter(ev.buffer(), ev.size())) { + _midi_buf->write (event_time, ev.event_type(), ev.size(), ev.buffer()); + } } - } - - g_atomic_int_add (const_cast<gint*>(&_samples_pending_write), nframes); - if (buf.size() != 0) { - Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::Threads::TRY_LOCK); + g_atomic_int_add (const_cast<gint*>(&_samples_pending_write), nframes); - if (lm.locked ()) { - /* Copy this data into our GUI feed buffer and tell the GUI - that it can read it if it likes. - */ - _gui_feed_buffer.clear (); + if (buf.size() != 0) { + Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::Threads::TRY_LOCK); - for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) { - /* This may fail if buf is larger than _gui_feed_buffer, but it's not really - the end of the world if it does. + if (lm.locked ()) { + /* Copy this data into our GUI feed buffer and tell the GUI + that it can read it if it likes. */ - _gui_feed_buffer.push_back ((*i).time() + start_sample, (*i).size(), (*i).buffer()); + _gui_feed_buffer.clear (); + + for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) { + /* This may fail if buf is larger than _gui_feed_buffer, but it's not really + the end of the world if it does. + */ + _gui_feed_buffer.push_back ((*i).time() + start_sample, (*i).size(), (*i).buffer()); + } } - } - DataRecorded (_midi_write_source); /* EMIT SIGNAL */ + DataRecorded (_midi_write_source); /* EMIT SIGNAL */ + } } _capture_captured += rec_nframes; |