summaryrefslogtreecommitdiff
path: root/libs/ardour/ardour
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2016-11-08 20:34:45 -0500
committerDavid Robillard <d@drobilla.net>2016-11-08 20:34:45 -0500
commitc61373212a87e519276d4c011994e2d37c77ee16 (patch)
tree216e0fcd47e24cd8db0511a074d2d203cb18fa5e /libs/ardour/ardour
parent72297c0ca31400767177bbcb9310721c481a7dd8 (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.h56
-rw-r--r--libs/ardour/ardour/midi_model.h4
-rw-r--r--libs/ardour/ardour/midi_playlist.h3
-rw-r--r--libs/ardour/ardour/midi_region.h4
-rw-r--r--libs/ardour/ardour/midi_source.h22
-rw-r--r--libs/ardour/ardour/playlist.h2
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);