1 /* This file is part of Evoral.
2 * Copyright (C) 2008 David Robillard <http://drobilla.net>
3 * Copyright (C) 2000-2008 Paul Davis
5 * Evoral is free software; you can redistribute it and/or modify it under the
6 * terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 2 of the License, or (at your option) any later
10 * Evoral is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for details.
14 * You should have received a copy of the GNU General Public License along
15 * with this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 #ifndef EVORAL_SEQUENCE_HPP
20 #define EVORAL_SEQUENCE_HPP
27 #include <boost/shared_ptr.hpp>
28 #include <glibmm/thread.h>
29 #include "evoral/types.hpp"
30 #include "evoral/Note.hpp"
31 #include "evoral/Parameter.hpp"
32 #include "evoral/ControlSet.hpp"
33 #include "evoral/ControlList.hpp"
34 #include "evoral/PatchChange.hpp"
39 template<typename Time
> class EventSink
;
40 template<typename Time
> class Note
;
41 template<typename Time
> class Event
;
43 /** An iterator over (the x axis of) a 2-d double coordinate space.
45 class ControlIterator
{
47 ControlIterator(boost::shared_ptr
<const ControlList
> al
, double ax
, double ay
)
53 boost::shared_ptr
<const ControlList
> list
;
59 /** This is a higher level view of events, with separate representations for
60 * notes (instead of just unassociated note on/off events) and controller data.
61 * Controller data is represented as a list of time-stamped float values. */
62 template<typename Time
>
63 class Sequence
: virtual public ControlSet
{
65 Sequence(const TypeMap
& type_map
);
66 Sequence(const Sequence
<Time
>& other
);
69 struct WriteLockImpl
{
70 WriteLockImpl(Glib::RWLock
& s
, Glib::Mutex
& c
)
71 : sequence_lock(new Glib::RWLock::WriterLock(s
))
72 , control_lock(new Glib::Mutex::Lock(c
))
78 Glib::RWLock::WriterLock
* sequence_lock
;
79 Glib::Mutex::Lock
* control_lock
;
84 typedef typename
boost::shared_ptr
<Evoral::Note
<Time
> > NotePtr
;
85 typedef typename
boost::shared_ptr
<const Evoral::Note
<Time
> > constNotePtr
;
87 typedef boost::shared_ptr
<Glib::RWLock::ReaderLock
> ReadLock
;
88 typedef boost::shared_ptr
<WriteLockImpl
> WriteLock
;
90 virtual ReadLock
read_lock() const { return ReadLock(new Glib::RWLock::ReaderLock(_lock
)); }
91 virtual WriteLock
write_lock() { return WriteLock(new WriteLockImpl(_lock
, _control_lock
)); }
95 bool percussive() const { return _percussive
; }
96 void set_percussive(bool p
) { _percussive
= p
; }
99 bool writing() const { return _writing
; }
100 void end_write(bool delete_stuck
=false);
102 void append(const Event
<Time
>& ev
, Evoral::event_id_t evid
);
104 inline size_t n_notes() const { return _notes
.size(); }
105 inline bool empty() const { return _notes
.empty() && _sysexes
.empty() && _patch_changes
.empty() && ControlSet::controls_empty(); }
107 inline static bool note_time_comparator(const boost::shared_ptr
< const Note
<Time
> >& a
,
108 const boost::shared_ptr
< const Note
<Time
> >& b
) {
109 return a
->time() < b
->time();
112 struct NoteNumberComparator
{
113 inline bool operator()(const boost::shared_ptr
< const Note
<Time
> > a
,
114 const boost::shared_ptr
< const Note
<Time
> > b
) const {
115 return a
->note() < b
->note();
119 struct EarlierNoteComparator
{
120 inline bool operator()(const boost::shared_ptr
< const Note
<Time
> > a
,
121 const boost::shared_ptr
< const Note
<Time
> > b
) const {
122 return a
->time() < b
->time();
126 struct LaterNoteComparator
{
127 typedef const Note
<Time
>* value_type
;
128 inline bool operator()(const boost::shared_ptr
< const Note
<Time
> > a
,
129 const boost::shared_ptr
< const Note
<Time
> > b
) const {
130 return a
->time() > b
->time();
134 struct LaterNoteEndComparator
{
135 typedef const Note
<Time
>* value_type
;
136 inline bool operator()(const boost::shared_ptr
< const Note
<Time
> > a
,
137 const boost::shared_ptr
< const Note
<Time
> > b
) const {
138 return a
->end_time() > b
->end_time();
142 typedef std::multiset
<NotePtr
, EarlierNoteComparator
> Notes
;
143 inline Notes
& notes() { return _notes
; }
144 inline const Notes
& notes() const { return _notes
; }
149 PitchLessThanOrEqual
,
151 PitchGreaterThanOrEqual
,
154 VelocityLessThanOrEqual
,
156 VelocityGreaterThanOrEqual
,
159 void get_notes (Notes
&, NoteOperator
, uint8_t val
, int chan_mask
= 0) const;
161 void remove_overlapping_notes ();
162 void trim_overlapping_notes ();
163 void remove_duplicate_notes ();
165 enum OverlapPitchResolution
{
170 bool overlapping_pitches_accepted() const { return _overlapping_pitches_accepted
; }
171 void overlapping_pitches_accepted(bool yn
) { _overlapping_pitches_accepted
= yn
; }
172 OverlapPitchResolution
overlap_pitch_resolution() const { return _overlap_pitch_resolution
; }
173 void set_overlap_pitch_resolution(OverlapPitchResolution opr
);
175 void set_notes (const Sequence
<Time
>::Notes
& n
);
177 typedef std::vector
< boost::shared_ptr
< Event
<Time
> > > SysExes
;
178 inline SysExes
& sysexes() { return _sysexes
; }
179 inline const SysExes
& sysexes() const { return _sysexes
; }
181 typedef boost::shared_ptr
<PatchChange
<Time
> > PatchChangePtr
;
182 typedef boost::shared_ptr
<const PatchChange
<Time
> > constPatchChangePtr
;
184 struct EarlierPatchChangeComparator
{
185 inline bool operator() (constPatchChangePtr a
, constPatchChangePtr b
) const {
186 return a
->time() < b
->time();
190 typedef std::multiset
<PatchChangePtr
, EarlierPatchChangeComparator
> PatchChanges
;
191 inline PatchChanges
& patch_changes () { return _patch_changes
; }
192 inline const PatchChanges
& patch_changes () const { return _patch_changes
; }
194 void dump (std::ostream
&) const;
197 typedef std::priority_queue
<NotePtr
, std::deque
<NotePtr
>, LaterNoteEndComparator
> ActiveNotes
;
201 class const_iterator
{
204 const_iterator(const Sequence
<Time
>& seq
, Time t
, bool, std::set
<Evoral::Parameter
> const &);
207 inline bool valid() const { return !_is_end
&& _event
; }
208 //inline bool locked() const { return _locked; }
212 const Event
<Time
>& operator*() const { return *_event
; }
213 const boost::shared_ptr
< Event
<Time
> > operator->() const { return _event
; }
214 const boost::shared_ptr
< Event
<Time
> > get_event_pointer() { return _event
; }
216 const const_iterator
& operator++(); // prefix only
218 bool operator==(const const_iterator
& other
) const;
219 bool operator!=(const const_iterator
& other
) const { return ! operator==(other
); }
221 const_iterator
& operator=(const const_iterator
& other
);
224 friend class Sequence
<Time
>;
226 typedef std::vector
<ControlIterator
> ControlIterators
;
227 enum MIDIMessageType
{ NIL
, NOTE_ON
, NOTE_OFF
, CONTROL
, SYSEX
, PATCH_CHANGE
};
229 const Sequence
<Time
>* _seq
;
230 boost::shared_ptr
< Event
<Time
> > _event
;
231 mutable ActiveNotes _active_notes
;
232 /** If the iterator is pointing at a patch change, this is the index of the
233 * sub-message within that change.
235 int _active_patch_change_message
;
236 MIDIMessageType _type
;
238 typename
Sequence::ReadLock _lock
;
239 typename
Notes::const_iterator _note_iter
;
240 typename
SysExes::const_iterator _sysex_iter
;
241 typename
PatchChanges::const_iterator _patch_change_iter
;
242 ControlIterators _control_iters
;
243 ControlIterators::iterator _control_iter
;
244 bool _force_discrete
;
247 const_iterator
begin (
249 bool force_discrete
= false,
250 std::set
<Evoral::Parameter
> const & f
= std::set
<Evoral::Parameter
> ()) const {
251 return const_iterator (*this, t
, force_discrete
, f
);
254 const const_iterator
& end() const { return _end_iter
; }
256 typename
Notes::const_iterator
note_lower_bound (Time t
) const;
257 typename
PatchChanges::const_iterator
patch_change_lower_bound (Time t
) const;
259 bool control_to_midi_event(boost::shared_ptr
< Event
<Time
> >& ev
,
260 const ControlIterator
& iter
) const;
262 bool edited() const { return _edited
; }
263 void set_edited(bool yn
) { _edited
= yn
; }
265 bool overlaps (const NotePtr
& ev
,
266 const NotePtr
& ignore_this_note
) const;
267 bool contains (const NotePtr
& ev
) const;
269 bool add_note_unlocked (const NotePtr note
, void* arg
= 0);
270 void remove_note_unlocked(const constNotePtr note
);
272 void add_patch_change_unlocked (const PatchChangePtr
);
273 void remove_patch_change_unlocked (const constPatchChangePtr
);
275 uint8_t lowest_note() const { return _lowest_note
; }
276 uint8_t highest_note() const { return _highest_note
; }
281 bool _overlapping_pitches_accepted
;
282 OverlapPitchResolution _overlap_pitch_resolution
;
283 mutable Glib::RWLock _lock
;
286 virtual int resolve_overlaps_unlocked (const NotePtr
, void* /* arg */ = 0) {
290 typedef std::multiset
<NotePtr
, NoteNumberComparator
> Pitches
;
291 inline Pitches
& pitches(uint8_t chan
) { return _pitches
[chan
&0xf]; }
292 inline const Pitches
& pitches(uint8_t chan
) const { return _pitches
[chan
&0xf]; }
295 friend class const_iterator
;
297 bool overlaps_unlocked (const NotePtr
& ev
, const NotePtr
& ignore_this_note
) const;
298 bool contains_unlocked (const NotePtr
& ev
) const;
300 void append_note_on_unlocked (NotePtr
, Evoral::event_id_t
);
301 void append_note_off_unlocked(NotePtr
);
302 void append_control_unlocked(const Parameter
& param
, Time time
, double value
, Evoral::event_id_t
);
303 void append_sysex_unlocked(const MIDIEvent
<Time
>& ev
, Evoral::event_id_t
);
304 void append_patch_change_unlocked (const PatchChange
<Time
>&, Evoral::event_id_t
);
306 void get_notes_by_pitch (Notes
&, NoteOperator
, uint8_t val
, int chan_mask
= 0) const;
307 void get_notes_by_velocity (Notes
&, NoteOperator
, uint8_t val
, int chan_mask
= 0) const;
309 void control_list_marked_dirty ();
311 const TypeMap
& _type_map
;
313 Notes _notes
; // notes indexed by time
314 Pitches _pitches
[16]; // notes indexed by channel+pitch
316 PatchChanges _patch_changes
;
318 typedef std::multiset
<NotePtr
, EarlierNoteComparator
> WriteNotes
;
319 WriteNotes _write_notes
[16];
321 /** Current bank number on each channel so that we know what
322 * to put in PatchChange events when program changes are
327 const const_iterator _end_iter
;
330 uint8_t _lowest_note
;
331 uint8_t _highest_note
;
335 } // namespace Evoral
337 // template<typename Time> std::ostream& operator<<(std::ostream& o, const Evoral::Sequence<Time>& s) { s.dump (o); return o; }
339 #endif // EVORAL_SEQUENCE_HPP