summaryrefslogtreecommitdiff
path: root/libs/ardour
diff options
context:
space:
mode:
Diffstat (limited to 'libs/ardour')
-rw-r--r--libs/ardour/ardour/midi_diskstream.h1
-rw-r--r--libs/ardour/ardour/midi_port.h1
-rw-r--r--libs/ardour/ardour/midi_ring_buffer.h1
-rw-r--r--libs/ardour/midi_diskstream.cc15
-rw-r--r--libs/ardour/midi_port.cc6
-rw-r--r--libs/ardour/midi_ring_buffer.cc34
-rw-r--r--libs/ardour/midi_track.cc35
7 files changed, 87 insertions, 6 deletions
diff --git a/libs/ardour/ardour/midi_diskstream.h b/libs/ardour/ardour/midi_diskstream.h
index 23ae7addb0..99513734da 100644
--- a/libs/ardour/ardour/midi_diskstream.h
+++ b/libs/ardour/ardour/midi_diskstream.h
@@ -63,6 +63,7 @@ class MidiDiskstream : public Diskstream
float capture_buffer_load() const;
void get_playback (MidiBuffer& dst, framecnt_t);
+ void flush_playback (framepos_t, framepos_t);
void set_record_enabled (bool yn);
diff --git a/libs/ardour/ardour/midi_port.h b/libs/ardour/ardour/midi_port.h
index 84575ca351..5dc55398cb 100644
--- a/libs/ardour/ardour/midi_port.h
+++ b/libs/ardour/ardour/midi_port.h
@@ -45,6 +45,7 @@ class MidiPort : public Port {
void transport_stopped ();
void realtime_locate ();
void reset ();
+ void require_resolve ();
bool input_active() const { return _input_active; }
void set_input_active (bool yn);
diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h
index 4b352b3c4d..c6756933aa 100644
--- a/libs/ardour/ardour/midi_ring_buffer.h
+++ b/libs/ardour/ardour/midi_ring_buffer.h
@@ -55,6 +55,7 @@ public:
size_t read(MidiBuffer& dst, framepos_t start, framepos_t end, framecnt_t offset=0, bool stop_on_overflow_in_destination=false);
void dump(std::ostream& dst);
+ void flush (framepos_t start, framepos_t end);
/** Set the channel filtering mode.
* @param mask If mode is FilterChannels, each bit represents a midi channel:
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index a8757d7575..5e2a6e23b9 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -506,6 +506,14 @@ MidiDiskstream::seek (framepos_t frame, bool complete_refill)
Glib::Mutex::Lock lm (state_lock);
int ret = -1;
+ if (g_atomic_int_get (&_frames_read_from_ringbuffer) == 0) {
+ /* we haven't read anything since the last seek,
+ so flush all note trackers to prevent
+ wierdness
+ */
+ reset_tracker ();
+ }
+
_playback_buf->reset();
_capture_buf->reset();
g_atomic_int_set(&_frames_read_from_ringbuffer, 0);
@@ -1269,6 +1277,13 @@ MidiDiskstream::use_pending_capture_data (XMLNode& /*node*/)
return 0;
}
+void
+MidiDiskstream::flush_playback (framepos_t start, framepos_t end)
+{
+ _playback_buf->flush (start, end);
+ g_atomic_int_add (&_frames_read_from_ringbuffer, end - start);
+}
+
/** Writes playback events from playback_sample for nframes to dst, translating time stamps
* so that an event at playback_sample has time = 0
*/
diff --git a/libs/ardour/midi_port.cc b/libs/ardour/midi_port.cc
index 9a7d3eeb27..63004f658b 100644
--- a/libs/ardour/midi_port.cc
+++ b/libs/ardour/midi_port.cc
@@ -189,6 +189,12 @@ MidiPort::flush_buffers (pframes_t nframes)
}
void
+MidiPort::require_resolve ()
+{
+ _resolve_required = true;
+}
+
+void
MidiPort::transport_stopped ()
{
_resolve_required = true;
diff --git a/libs/ardour/midi_ring_buffer.cc b/libs/ardour/midi_ring_buffer.cc
index 30f42aba19..786ed3c080 100644
--- a/libs/ardour/midi_ring_buffer.cc
+++ b/libs/ardour/midi_ring_buffer.cc
@@ -98,7 +98,9 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
break;
} else if (ev_time + loop_offset < start) {
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MRB event @ %1 before start @ %2\n", ev_time, start));
- break;
+ this->increment_read_ptr (prefix_size);
+ this->increment_read_ptr (ev_size);
+ continue;
} else {
DEBUG_TRACE (DEBUG::MidiDiskstreamIO, string_compose ("MRB event @ %1 in range %2 .. %3\n", ev_time, start, end));
}
@@ -195,6 +197,36 @@ MidiRingBuffer<T>::read(MidiBuffer& dst, framepos_t start, framepos_t end, frame
template<typename T>
void
+MidiRingBuffer<T>::flush (framepos_t start, framepos_t end)
+{
+ const size_t prefix_size = sizeof(T) + sizeof(Evoral::EventType) + sizeof(uint32_t);
+
+ while (this->read_space() >= prefix_size) {
+ uint8_t peekbuf[prefix_size];
+ bool success;
+ uint32_t ev_size;
+ T ev_time;
+
+ success = this->peek (peekbuf, prefix_size);
+ /* this cannot fail, because we've already verified that there
+ is prefix_space to read
+ */
+ assert (success);
+
+ ev_time = *((T*) peekbuf);
+
+ if (ev_time >= end) {
+ break;
+ }
+
+ ev_size = *((uint32_t*)(peekbuf + sizeof(T) + sizeof (Evoral::EventType)));
+ this->increment_read_ptr (prefix_size);
+ this->increment_read_ptr (ev_size);
+ }
+}
+
+template<typename T>
+void
MidiRingBuffer<T>::dump(ostream& str)
{
size_t rspace;
diff --git a/libs/ardour/midi_track.cc b/libs/ardour/midi_track.cc
index 8847bf13bc..a8a0e218a6 100644
--- a/libs/ardour/midi_track.cc
+++ b/libs/ardour/midi_track.cc
@@ -309,6 +309,7 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
return dret;
}
+
_silent = false;
if ((dret = diskstream->process (transport_frame, nframes, playback_distance)) != 0) {
@@ -329,9 +330,18 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
at least potentially (depending on monitoring options)
*/
+ /* because the playback buffer is event based and not a
+ * continuous stream, we need to make sure that we empty
+ * it of events every cycle to avoid it filling up with events
+ * read from disk, while we are actually monitoring input
+ */
+
+ diskstream->flush_playback (start_frame, end_frame);
+
passthru (start_frame, end_frame, nframes, 0);
} else {
+
/*
XXX is it true that the earlier test on n_outputs()
means that we can avoid checking it again here? i think
@@ -343,7 +353,6 @@ MidiTrack::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame
/* copy the diskstream data to all output buffers */
- //const size_t limit = n_process_buffers().n_audio();
BufferSet& bufs = _session.get_scratch_buffers (n_process_buffers());
MidiBuffer& mbuf (bufs.get_midi (0));
@@ -735,12 +744,28 @@ MidiTrack::act_on_mute ()
void
MidiTrack::set_monitoring (MonitorChoice mc)
{
- Track::set_monitoring (mc);
+ if (mc != _monitoring) {
- boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
+ Track::set_monitoring (mc);
+
+ /* monitoring state changed, so flush out any on notes at the
+ * port level.
+ */
- if (md) {
- md->reset_tracker ();
+ PortSet& ports (_output->ports());
+
+ for (PortSet::iterator p = ports.begin(); p != ports.end(); ++p) {
+ boost::shared_ptr<MidiPort> mp = boost::dynamic_pointer_cast<MidiPort> (*p);
+ if (mp) {
+ mp->require_resolve ();
+ }
+ }
+
+ boost::shared_ptr<MidiDiskstream> md (midi_diskstream());
+
+ if (md) {
+ md->reset_tracker ();
+ }
}
}