diff options
author | David Robillard <d@drobilla.net> | 2015-03-01 13:33:25 -0500 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2015-03-05 17:30:31 -0500 |
commit | a8aae56d92699e4545b5f8a69742f9a1c75ad238 (patch) | |
tree | ae3c14f1b78fbfddf126b44e533692b137d93f28 /libs/ardour/ardour/midi_playlist.h | |
parent | 09f1571fc0c9dd164601cfd3d12fac31a084b9f6 (diff) |
Handle edits while playing precisely.
This avoids stuck notes if active notes are edited, but without stopping all
active notes in the region on any edit as before.
This implementation injects note ons in places that aren't actually note
starts. Depending on how percussive the instrument is, this may not be
desired. In the future, an option for this would be an improvement, but there
are other places where "start notes in the middle" is a reasonable option. I
think that should be handled universally if we're to do it at all, so not
considering it a part of this fix for now.
Diffstat (limited to 'libs/ardour/ardour/midi_playlist.h')
-rw-r--r-- | libs/ardour/ardour/midi_playlist.h | 36 |
1 files changed, 29 insertions, 7 deletions
diff --git a/libs/ardour/ardour/midi_playlist.h b/libs/ardour/ardour/midi_playlist.h index f49593bd85..614a5e1c1f 100644 --- a/libs/ardour/ardour/midi_playlist.h +++ b/libs/ardour/ardour/midi_playlist.h @@ -23,8 +23,15 @@ #include <vector> #include <list> +#include <boost/utility.hpp> + #include "ardour/ardour.h" +#include "ardour/midi_model.h" +#include "ardour/midi_state_tracker.h" +#include "ardour/note_fixer.h" #include "ardour/playlist.h" +#include "evoral/Beats.hpp" +#include "evoral/Note.hpp" #include "evoral/Parameter.hpp" namespace Evoral { @@ -34,10 +41,10 @@ template<typename Time> class EventSink; namespace ARDOUR { -class Session; +class BeatsFramesConverter; class MidiRegion; +class Session; class Source; -class MidiStateTracker; template<typename T> class MidiRingBuffer; @@ -80,6 +87,15 @@ public: std::set<Evoral::Parameter> contained_automation(); + /** Handle a region edit during read. + * + * This must be called before the command is applied to the model. Events + * are injected into the playlist output to compensate for edits to active + * notes and maintain coherent output and tracker state. + */ + void region_edited(boost::shared_ptr<Region> region, + const MidiModel::NoteDiffCommand* cmd); + /** Clear all note trackers. */ void reset_note_trackers (); @@ -91,18 +107,24 @@ public: void resolve_note_trackers (Evoral::EventSink<framepos_t>& dst, framepos_t time); protected: - void remove_dependents (boost::shared_ptr<Region> region); private: - void dump () const; + typedef Evoral::Note<Evoral::Beats> Note; + typedef Evoral::Event<framepos_t> Event; - bool region_changed (const PBD::PropertyChange&, boost::shared_ptr<Region>); + struct RegionTracker : public boost::noncopyable { + MidiStateTracker tracker; ///< Active note tracker + NoteFixer fixer; ///< Edit compensation + }; - NoteMode _note_mode; + typedef std::map< Region*, boost::shared_ptr<RegionTracker> > NoteTrackers; + + void dump () const; - typedef std::map<Region*,MidiStateTracker*> NoteTrackers; NoteTrackers _note_trackers; + NoteMode _note_mode; + framepos_t _read_end; }; } /* namespace ARDOUR */ |