diff --git a/libs/ardour/ardour/disk_writer.h b/libs/ardour/ardour/disk_writer.h index 669c064ed7..bef6d77966 100644 --- a/libs/ardour/ardour/disk_writer.h +++ b/libs/ardour/ardour/disk_writer.h @@ -26,6 +26,7 @@ #include #include "ardour/disk_io.h" +#include "ardour/event_ring_buffer.h" #include "ardour/midi_buffer.h" namespace ARDOUR @@ -201,8 +202,8 @@ private: /** A buffer that we use to put newly-arrived MIDI data in for * the GUI to read (so that it can update itself). */ - MidiBuffer _gui_feed_buffer; - mutable Glib::Threads::Mutex _gui_feed_buffer_mutex; + mutable EventRingBuffer _gui_feed_fifo; + mutable Glib::Threads::Mutex _gui_feed_reset_mutex; }; } // namespace diff --git a/libs/ardour/disk_writer.cc b/libs/ardour/disk_writer.cc index 0c8d197480..3ea33de71c 100644 --- a/libs/ardour/disk_writer.cc +++ b/libs/ardour/disk_writer.cc @@ -60,7 +60,7 @@ DiskWriter::DiskWriter (Session& s, Track& t, string const & str, DiskIOProcesso , _accumulated_capture_offset (0) , _transport_looped (false) , _transport_loop_sample (0) - , _gui_feed_buffer(AudioEngine::instance()->raw_buffer_size (DataType::MIDI)) + , _gui_feed_fifo (AudioEngine::instance()->raw_buffer_size (DataType::MIDI)) { DiskIOProcessor::init (); _xruns.reserve (128); @@ -684,25 +684,18 @@ DiskWriter::run (BufferSet& bufs, samplepos_t start_sample, samplepos_t end_samp _samples_pending_write.fetch_add ((int) nframes); if (buf.size() != 0) { - Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex, Glib::Threads::TRY_LOCK); - - 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 (); - - 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. - */ - samplepos_t mpos = (*i).time() + start_sample - _accumulated_capture_offset; - if (mpos >= _first_recordable_sample) { - _gui_feed_buffer.push_back (mpos, Evoral::MIDI_EVENT, (*i).size(), (*i).buffer()); - } + /* Copy this data into our GUI feed buffer and tell the GUI + * that it can read it if it likes. + */ + for (MidiBuffer::iterator i = buf.begin(); i != buf.end(); ++i) { + /* This may fail if buf is larger than _gui_feed_fifo, but it's not really + * the end of the world if it does. + */ + samplepos_t mpos = (*i).time() + start_sample - _accumulated_capture_offset; + if (mpos >= _first_recordable_sample) { + _gui_feed_fifo.write (mpos, Evoral::MIDI_EVENT, (*i).size(), (*i).buffer()); } } - } if (cnt) { @@ -807,10 +800,18 @@ DiskWriter::finish_capture (std::shared_ptr c) std::shared_ptr DiskWriter::get_gui_feed_buffer () const { + Glib::Threads::Mutex::Lock lm (_gui_feed_reset_mutex); std::shared_ptr b (new MidiBuffer (AudioEngine::instance()->raw_buffer_size (DataType::MIDI))); - Glib::Threads::Mutex::Lock lm (_gui_feed_buffer_mutex); - b->copy (_gui_feed_buffer); + vector buffer (_gui_feed_fifo.capacity()); + samplepos_t time; + Evoral::EventType type; + uint32_t size; + + while (_gui_feed_fifo.read (&time, &type, &size, &buffer[0])) { + b->push_back (time, type, size, &buffer[0]); + } + return b; } @@ -1191,6 +1192,11 @@ DiskWriter::transport_stopped_wallclock (struct tm& when, time_t twhen, bool abo finish_capture (c); + { + Glib::Threads::Mutex::Lock lm (_gui_feed_reset_mutex); + _gui_feed_fifo.reset (); + } + /* butler is already stopped, but there may be work to do to flush remaining data to disk. */