summaryrefslogtreecommitdiff
path: root/libs/evoral/evoral/Sequence.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/evoral/evoral/Sequence.hpp')
-rw-r--r--libs/evoral/evoral/Sequence.hpp65
1 files changed, 48 insertions, 17 deletions
diff --git a/libs/evoral/evoral/Sequence.hpp b/libs/evoral/evoral/Sequence.hpp
index abc147af8d..77d06a673e 100644
--- a/libs/evoral/evoral/Sequence.hpp
+++ b/libs/evoral/evoral/Sequence.hpp
@@ -31,6 +31,7 @@
#include "evoral/Parameter.hpp"
#include "evoral/ControlSet.hpp"
#include "evoral/ControlList.hpp"
+#include "evoral/PatchChange.hpp"
namespace Evoral {
@@ -101,7 +102,7 @@ public:
void append(const Event<Time>& ev, Evoral::event_id_t evid);
inline size_t n_notes() const { return _notes.size(); }
- inline bool empty() const { return _notes.size() == 0 && ControlSet::controls_empty(); }
+ inline bool empty() const { return _notes.empty() && _sysexes.empty() && _patch_changes.empty() && ControlSet::controls_empty(); }
inline static bool note_time_comparator(const boost::shared_ptr< const Note<Time> >& a,
const boost::shared_ptr< const Note<Time> >& b) {
@@ -177,6 +178,19 @@ public:
inline SysExes& sysexes() { return _sysexes; }
inline const SysExes& sysexes() const { return _sysexes; }
+ typedef boost::shared_ptr<PatchChange<Time> > PatchChangePtr;
+ typedef boost::shared_ptr<const PatchChange<Time> > constPatchChangePtr;
+
+ struct EarlierPatchChangeComparator {
+ inline bool operator() (constPatchChangePtr a, constPatchChangePtr b) const {
+ return a->time() < b->time();
+ }
+ };
+
+ typedef std::multiset<PatchChangePtr, EarlierPatchChangeComparator> PatchChanges;
+ inline PatchChanges& patch_changes () { return _patch_changes; }
+ inline const PatchChanges& patch_changes () const { return _patch_changes; }
+
private:
typedef std::priority_queue<NotePtr, std::deque<NotePtr>, LaterNoteEndComparator> ActiveNotes;
public:
@@ -208,19 +222,24 @@ public:
friend class Sequence<Time>;
typedef std::vector<ControlIterator> ControlIterators;
- enum MIDIMessageType { NIL, NOTE_ON, NOTE_OFF, CONTROL, SYSEX };
-
- const Sequence<Time>* _seq;
- boost::shared_ptr< Event<Time> > _event;
- mutable ActiveNotes _active_notes;
- MIDIMessageType _type;
- bool _is_end;
- typename Sequence::ReadLock _lock;
- typename Notes::const_iterator _note_iter;
- typename SysExes::const_iterator _sysex_iter;
- ControlIterators _control_iters;
- ControlIterators::iterator _control_iter;
- bool _force_discrete;
+ enum MIDIMessageType { NIL, NOTE_ON, NOTE_OFF, CONTROL, SYSEX, PATCH_CHANGE };
+
+ const Sequence<Time>* _seq;
+ boost::shared_ptr< Event<Time> > _event;
+ mutable ActiveNotes _active_notes;
+ /** If the iterator is pointing at a patch change, this is the index of the
+ * sub-message within that change.
+ */
+ int _active_patch_change_message;
+ MIDIMessageType _type;
+ bool _is_end;
+ typename Sequence::ReadLock _lock;
+ typename Notes::const_iterator _note_iter;
+ typename SysExes::const_iterator _sysex_iter;
+ typename PatchChanges::const_iterator _patch_change_iter;
+ ControlIterators _control_iters;
+ ControlIterators::iterator _control_iter;
+ bool _force_discrete;
};
const_iterator begin (
@@ -233,6 +252,7 @@ public:
const const_iterator& end() const { return _end_iter; }
typename Notes::const_iterator note_lower_bound (Time t) const;
+ typename PatchChanges::const_iterator patch_change_lower_bound (Time t) const;
bool control_to_midi_event(boost::shared_ptr< Event<Time> >& ev,
const ControlIterator& iter) const;
@@ -247,6 +267,9 @@ public:
bool add_note_unlocked (const NotePtr note, void* arg = 0);
void remove_note_unlocked(const constNotePtr note);
+ void add_patch_change_unlocked (const PatchChangePtr);
+ void remove_patch_change_unlocked (const constPatchChangePtr);
+
uint8_t lowest_note() const { return _lowest_note; }
uint8_t highest_note() const { return _highest_note; }
@@ -276,6 +299,7 @@ private:
void append_note_off_unlocked(NotePtr);
void append_control_unlocked(const Parameter& param, Time time, double value, Evoral::event_id_t);
void append_sysex_unlocked(const MIDIEvent<Time>& ev, Evoral::event_id_t);
+ void append_patch_change_unlocked (const PatchChange<Time>&, Evoral::event_id_t);
void get_notes_by_pitch (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const;
void get_notes_by_velocity (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const;
@@ -284,13 +308,20 @@ private:
const TypeMap& _type_map;
- Notes _notes; // notes indexed by time
- Pitches _pitches[16]; // notes indexed by channel+pitch
- SysExes _sysexes;
+ Notes _notes; // notes indexed by time
+ Pitches _pitches[16]; // notes indexed by channel+pitch
+ SysExes _sysexes;
+ PatchChanges _patch_changes;
typedef std::multiset<NotePtr, EarlierNoteComparator> WriteNotes;
WriteNotes _write_notes[16];
+ /** Current bank number on each channel so that we know what
+ * to put in PatchChange events when program changes are
+ * seen.
+ */
+ int _bank[16];
+
const const_iterator _end_iter;
bool _percussive;