summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/ardour/ardour/midi_playlist.h10
-rw-r--r--libs/ardour/ardour/midi_ring_buffer.h2
-rw-r--r--libs/ardour/midi_diskstream.cc14
-rw-r--r--libs/ardour/midi_playlist.cc17
-rw-r--r--libs/ardour/midi_region.cc6
-rw-r--r--libs/ardour/midi_ring_buffer.cc2
-rw-r--r--libs/ardour/smf_source.cc7
7 files changed, 44 insertions, 14 deletions
diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h
index 2603de45f7..5e334d5546 100644
--- a/libs/ardour/ardour/midi_playlist.h
+++ b/libs/ardour/ardour/midi_playlist.h
@@ -63,7 +63,15 @@ public:
std::set<Evoral::Parameter> contained_automation();
- void clear_note_trackers ();
+ /** Clear all note trackers. */
+ void reset_note_trackers ();
+
+ /** Resolve all pending notes and clear all note trackers.
+ *
+ * @param dst Sink to write note offs to.
+ * @param time Time stamp of all written note offs.
+ */
+ void resolve_note_trackers (Evoral::EventSink<framepos_t>& dst, framepos_t time);
protected:
diff --git a/libs/ardour/ardour/midi_ring_buffer.h b/libs/ardour/ardour/midi_ring_buffer.h
index 15e4d2689b..0d27de3c16 100644
--- a/libs/ardour/ardour/midi_ring_buffer.h
+++ b/libs/ardour/ardour/midi_ring_buffer.h
@@ -54,7 +54,7 @@ public:
void flush (framepos_t start, framepos_t end);
void reset_tracker ();
- void loop_resolve (MidiBuffer& dst, framepos_t);
+ void resolve_tracker (MidiBuffer& dst, framepos_t);
private:
MidiStateTracker _tracker;
diff --git a/libs/ardour/midi_diskstream.cc b/libs/ardour/midi_diskstream.cc
index e2fd6d1681..e52a7c3ad7 100644
--- a/libs/ardour/midi_diskstream.cc
+++ b/libs/ardour/midi_diskstream.cc
@@ -606,12 +606,20 @@ MidiDiskstream::set_pending_overwrite (bool yn)
int
MidiDiskstream::overwrite_existing_buffers ()
{
- /* This is safe as long as the butler thread is suspended, which it should be */
+ /* Clear the playback buffer contents. This is safe as long as the butler
+ thread is suspended, which it should be. */
_playback_buf->reset ();
+ _playback_buf->reset_tracker ();
g_atomic_int_set (&_frames_read_from_ringbuffer, 0);
g_atomic_int_set (&_frames_written_to_ringbuffer, 0);
+ /* Resolve all currently active notes in the playlist. This is more
+ aggressive than it needs to be: ideally we would only resolve what is
+ absolutely necessary, but this seems difficult and/or impossible without
+ having the old data or knowing what change caused the overwrite. */
+ midi_playlist()->resolve_note_trackers (*_playback_buf, overwrite_frame);
+
read (overwrite_frame, disk_io_chunk_frames, false);
file_frame = overwrite_frame; // it was adjusted by ::read()
overwrite_queued = false;
@@ -1398,7 +1406,7 @@ MidiDiskstream::get_playback (MidiBuffer& dst, framecnt_t nframes)
beyond the loop end.
*/
- _playback_buf->loop_resolve (dst, 0);
+ _playback_buf->resolve_tracker (dst, 0);
}
if (loc->end() >= effective_start && loc->end() < effective_start + nframes) {
@@ -1489,7 +1497,7 @@ MidiDiskstream::reset_tracker ()
boost::shared_ptr<MidiPlaylist> mp (midi_playlist());
if (mp) {
- mp->clear_note_trackers ();
+ mp->reset_note_trackers ();
}
}
diff --git a/libs/ardour/midi_playlist.cc b/libs/ardour/midi_playlist.cc
index 36b6fce75f..63c3b49858 100644
--- a/libs/ardour/midi_playlist.cc
+++ b/libs/ardour/midi_playlist.cc
@@ -288,14 +288,27 @@ MidiPlaylist::read (Evoral::EventSink<framepos_t>& dst, framepos_t start, framec
}
void
-MidiPlaylist::clear_note_trackers ()
+MidiPlaylist::reset_note_trackers ()
{
Playlist::RegionWriteLock rl (this, false);
for (NoteTrackers::iterator n = _note_trackers.begin(); n != _note_trackers.end(); ++n) {
delete n->second;
}
- DEBUG_TRACE (DEBUG::MidiTrackers, string_compose ("%1 clears all note trackers\n", name()));
+ DEBUG_TRACE (DEBUG::MidiTrackers, string_compose ("%1 reset all note trackers\n", name()));
+ _note_trackers.clear ();
+}
+
+void
+MidiPlaylist::resolve_note_trackers (Evoral::EventSink<framepos_t>& dst, framepos_t time)
+{
+ Playlist::RegionWriteLock rl (this, false);
+
+ for (NoteTrackers::iterator n = _note_trackers.begin(); n != _note_trackers.end(); ++n) {
+ n->second->resolve_notes(dst, time);
+ delete n->second;
+ }
+ DEBUG_TRACE (DEBUG::MidiTrackers, string_compose ("%1 resolve all note trackers\n", name()));
_note_trackers.clear ();
}
diff --git a/libs/ardour/midi_region.cc b/libs/ardour/midi_region.cc
index f79e5ef203..e94e4e4854 100644
--- a/libs/ardour/midi_region.cc
+++ b/libs/ardour/midi_region.cc
@@ -414,6 +414,12 @@ MidiRegion::model_changed ()
void
MidiRegion::model_contents_changed ()
{
+ {
+ /* Invalidate source iterator to force reading new contents even if the
+ calls to read progress linearly. */
+ Glib::Threads::Mutex::Lock lm (midi_source(0)->mutex());
+ midi_source(0)->invalidate (lm);
+ }
send_change (PropertyChange (Properties::midi_data));
}
diff --git a/libs/ardour/midi_ring_buffer.cc b/libs/ardour/midi_ring_buffer.cc
index 0da3ba6835..9fbd9dfdff 100644
--- a/libs/ardour/midi_ring_buffer.cc
+++ b/libs/ardour/midi_ring_buffer.cc
@@ -241,7 +241,7 @@ MidiRingBuffer<T>::reset_tracker ()
template<typename T>
void
-MidiRingBuffer<T>::loop_resolve (MidiBuffer& dst, framepos_t t)
+MidiRingBuffer<T>::resolve_tracker (MidiBuffer& dst, framepos_t t)
{
_tracker.resolve_notes (dst, t);
}
diff --git a/libs/ardour/smf_source.cc b/libs/ardour/smf_source.cc
index 519d8bbf10..d1a82eb685 100644
--- a/libs/ardour/smf_source.cc
+++ b/libs/ardour/smf_source.cc
@@ -282,13 +282,8 @@ SMFSource::read_unlocked (const Lock& lock,
if (ev_frame_time < start + duration) {
destination.write (ev_frame_time, ev_type, ev_size, ev_buffer);
-
if (tracker) {
- if (ev_buffer[0] & MIDI_CMD_NOTE_ON) {
- tracker->add (ev_buffer[1], ev_buffer[0] & 0xf);
- } else if (ev_buffer[0] & MIDI_CMD_NOTE_OFF) {
- tracker->remove (ev_buffer[1], ev_buffer[0] & 0xf);
- }
+ tracker->track(ev_buffer);
}
} else {
break;