diff options
author | David Robillard <d@drobilla.net> | 2016-11-08 20:34:45 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2016-11-08 20:34:45 -0500 |
commit | c61373212a87e519276d4c011994e2d37c77ee16 (patch) | |
tree | 216e0fcd47e24cd8db0511a074d2d203cb18fa5e /libs/ardour/ardour | |
parent | 72297c0ca31400767177bbcb9310721c481a7dd8 (diff) |
Support multiple readers for MIDI source/model
Fixes the multiple reader issue #6541 properly without resorting to a
linear search kludge.
All the read state has been pulled out into a MidiCursor which the
caller is required to pass. The playlist keeps cursors for all the
regions it is reading, any number of cursors are allowed at a time.
MidiCursor should probably be made a smarter and more fool-proof
object (and/or possibly merged with some of the other tracker/fixer
stuff) but for now I wanted to keep it simple.
Diffstat (limited to 'libs/ardour/ardour')
-rw-r--r-- | libs/ardour/ardour/midi_cursor.h | 56 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_model.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_playlist.h | 3 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_region.h | 4 | ||||
-rw-r--r-- | libs/ardour/ardour/midi_source.h | 22 | ||||
-rw-r--r-- | libs/ardour/ardour/playlist.h | 2 |
6 files changed, 75 insertions, 16 deletions
diff --git a/libs/ardour/ardour/midi_cursor.h b/libs/ardour/ardour/midi_cursor.h new file mode 100644 index 0000000000..5cb89c87f5 --- /dev/null +++ b/libs/ardour/ardour/midi_cursor.h @@ -0,0 +1,56 @@ +/* + Copyright (C) 2016 Paul Davis + Author: David Robillard + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#ifndef __ardour_midi_cursor_h__ +#define __ardour_midi_cursor_h__ + +#include <set> + +#include <boost/utility.hpp> + +#include "ardour/types.h" +#include "evoral/Beats.hpp" +#include "evoral/Sequence.hpp" +#include "pbd/signals.h" + +namespace ARDOUR { + +struct MidiCursor : public boost::noncopyable { + MidiCursor() : last_read_end(0) {} + + void connect(PBD::Signal1<void, bool>& invalidated) { + connections.drop_connections(); + invalidated.connect_same_thread( + connections, boost::bind(&MidiCursor::invalidate, this, _1)); + } + + void invalidate(bool preserve_notes) { + iter.invalidate(preserve_notes ? &active_notes : NULL); + last_read_end = 0; + } + + Evoral::Sequence<Evoral::Beats>::const_iterator iter; + std::set<Evoral::Sequence<Evoral::Beats>::WeakNotePtr> active_notes; + framepos_t last_read_end; + PBD::ScopedConnectionList connections; +}; + +} + +#endif /* __ardour_midi_cursor_h__ */ diff --git a/libs/ardour/ardour/midi_model.h b/libs/ardour/ardour/midi_model.h index c5467cc58d..cdf7b3fd3b 100644 --- a/libs/ardour/ardour/midi_model.h +++ b/libs/ardour/ardour/midi_model.h @@ -292,8 +292,6 @@ public: void insert_silence_at_start (TimeType); void transpose (NoteDiffCommand *, const NotePtr, int); - std::set<WeakNotePtr>& active_notes() { return _active_notes; } - protected: int resolve_overlaps_unlocked (const NotePtr, void* arg = 0); @@ -327,8 +325,6 @@ private: // We cannot use a boost::shared_ptr here to avoid a retain cycle boost::weak_ptr<MidiSource> _midi_source; InsertMergePolicy _insert_merge_policy; - - std::set<WeakNotePtr> _active_notes; }; } /* namespace ARDOUR */ diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h index ad0a812cba..3c031a994f 100644 --- a/libs/ardour/ardour/midi_playlist.h +++ b/libs/ardour/ardour/midi_playlist.h @@ -26,6 +26,7 @@ #include <boost/utility.hpp> #include "ardour/ardour.h" +#include "ardour/midi_cursor.h" #include "ardour/midi_model.h" #include "ardour/midi_state_tracker.h" #include "ardour/note_fixer.h" @@ -112,12 +113,14 @@ public: protected: void remove_dependents (boost::shared_ptr<Region> region); + void region_going_away (boost::weak_ptr<Region> region); private: typedef Evoral::Note<Evoral::Beats> Note; typedef Evoral::Event<framepos_t> Event; struct RegionTracker : public boost::noncopyable { + MidiCursor cursor; ///< Cursor (iterator and read state) MidiStateTracker tracker; ///< Active note tracker NoteFixer fixer; ///< Edit compensation }; diff --git a/libs/ardour/ardour/midi_region.h b/libs/ardour/ardour/midi_region.h index 0ad60a900c..d3a6cbbbb8 100644 --- a/libs/ardour/ardour/midi_region.h +++ b/libs/ardour/ardour/midi_region.h @@ -45,6 +45,7 @@ template<typename Time> class EventSink; namespace ARDOUR { class MidiChannelFilter; +class MidiCursor; class MidiFilter; class MidiModel; class MidiSource; @@ -77,6 +78,7 @@ class LIBARDOUR_API MidiRegion : public Region framepos_t position, framecnt_t dur, Evoral::Range<framepos_t>* loop_range, + MidiCursor& cursor, uint32_t chan_n = 0, NoteMode mode = Sustained, MidiStateTracker* tracker = 0, @@ -86,6 +88,7 @@ class LIBARDOUR_API MidiRegion : public Region framepos_t position, framecnt_t dur, Evoral::Range<framepos_t>* loop_range, + MidiCursor& cursor, uint32_t chan_n = 0, NoteMode mode = Sustained) const; @@ -130,6 +133,7 @@ class LIBARDOUR_API MidiRegion : public Region framepos_t position, framecnt_t dur, Evoral::Range<framepos_t>* loop_range, + MidiCursor& cursor, uint32_t chan_n = 0, NoteMode mode = Sustained, MidiStateTracker* tracker = 0, diff --git a/libs/ardour/ardour/midi_source.h b/libs/ardour/ardour/midi_source.h index 4815263739..1ff0a08f71 100644 --- a/libs/ardour/ardour/midi_source.h +++ b/libs/ardour/ardour/midi_source.h @@ -36,8 +36,9 @@ namespace ARDOUR { class MidiChannelFilter; -class MidiStateTracker; +class MidiCursor; class MidiModel; +class MidiStateTracker; template<typename T> class MidiRingBuffer; @@ -87,18 +88,18 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha * \param tracker an optional pointer to MidiStateTracker object, for note on/off tracking. * \param filtered Parameters whose MIDI messages will not be returned. */ - virtual framecnt_t midi_read (const Lock& lock, Evoral::EventSink<framepos_t>& dst, framepos_t source_start, framepos_t start, framecnt_t cnt, Evoral::Range<framepos_t>* loop_range, + MidiCursor& cursor, MidiStateTracker* tracker, MidiChannelFilter* filter, const std::set<Evoral::Parameter>& filtered, - const double pulse, - const double start_beats) const; + const double pulse, + const double start_beats) const; /** Write data from a MidiRingBuffer to this source. * @param source Source to read from. @@ -175,10 +176,11 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha /** Reset cached information (like iterators) when things have changed. * @param lock Source lock, which must be held by caller. - * @param notes If non-NULL, currently active notes are added to this set. */ - void invalidate(const Glib::Threads::Mutex::Lock& lock, - std::set<Evoral::Sequence<Evoral::Beats>::WeakNotePtr>* notes=NULL); + void invalidate(const Glib::Threads::Mutex::Lock& lock); + + /** Thou shalt not emit this directly, use invalidate() instead. */ + mutable PBD::Signal1<void, bool> Invalidated; void set_note_mode(const Glib::Threads::Mutex::Lock& lock, NoteMode mode); @@ -230,11 +232,7 @@ class LIBARDOUR_API MidiSource : virtual public Source, public boost::enable_sha boost::shared_ptr<MidiModel> _model; bool _writing; - mutable Evoral::Sequence<Evoral::Beats>::const_iterator _model_iter; - mutable bool _model_iter_valid; - - mutable Evoral::Beats _length_beats; - mutable framepos_t _last_read_end; + Evoral::Beats _length_beats; /** The total duration of the current capture. */ framepos_t _capture_length; diff --git a/libs/ardour/ardour/playlist.h b/libs/ardour/ardour/playlist.h index 04615acb26..1530eede9f 100644 --- a/libs/ardour/ardour/playlist.h +++ b/libs/ardour/ardour/playlist.h @@ -276,6 +276,7 @@ public: RegionListProperty regions; /* the current list of regions in the playlist */ std::set<boost::shared_ptr<Region> > all_regions; /* all regions ever added to this playlist */ PBD::ScopedConnectionList region_state_changed_connections; + PBD::ScopedConnectionList region_drop_references_connections; DataType _type; int _sort_id; mutable gint block_notifications; @@ -359,6 +360,7 @@ public: virtual void remove_dependents (boost::shared_ptr<Region> /*region*/) {} + virtual void region_going_away (boost::weak_ptr<Region> /*region*/) {} virtual XMLNode& state (bool); |