ardour
Sequence.hpp
Go to the documentation of this file.
1 /* This file is part of Evoral.
2  * Copyright (C) 2008 David Robillard <http://drobilla.net>
3  * Copyright (C) 2000-2008 Paul Davis
4  *
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
8  * version.
9  *
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.
13  *
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
17  */
18 
19 #ifndef EVORAL_SEQUENCE_HPP
20 #define EVORAL_SEQUENCE_HPP
21 
22 #include <vector>
23 #include <queue>
24 #include <set>
25 #include <list>
26 #include <utility>
27 #include <boost/shared_ptr.hpp>
28 #include <glibmm/threads.h>
29 
30 #include "evoral/visibility.h"
31 #include "evoral/types.hpp"
32 #include "evoral/Note.hpp"
33 #include "evoral/ControlSet.hpp"
34 #include "evoral/ControlList.hpp"
35 #include "evoral/PatchChange.hpp"
36 
37 namespace Evoral {
38 
39 class Parameter;
40 class TypeMap;
41 template<typename Time> class EventSink;
42 template<typename Time> class Note;
43 template<typename Time> class Event;
44 
47 class /*LIBEVORAL_API*/ ControlIterator {
48 public:
50  : list(al)
51  , x(ax)
52  , y(ay)
53  {}
54 
56  double x;
57  double y;
58 };
59 
60 
64 template<typename Time>
65 class LIBEVORAL_API Sequence : virtual public ControlSet {
66 public:
67  Sequence(const TypeMap& type_map);
68  Sequence(const Sequence<Time>& other);
69 
70 protected:
71  struct WriteLockImpl {
72  WriteLockImpl(Glib::Threads::RWLock& s, Glib::Threads::Mutex& c)
73  : sequence_lock(new Glib::Threads::RWLock::WriterLock(s))
74  , control_lock(new Glib::Threads::Mutex::Lock(c)) { }
76  delete sequence_lock;
77  delete control_lock;
78  }
79  Glib::Threads::RWLock::WriterLock* sequence_lock;
81  };
82 
83 public:
84 
88 
91 
92  virtual ReadLock read_lock() const { return ReadLock(new Glib::Threads::RWLock::ReaderLock(_lock)); }
93  virtual WriteLock write_lock() { return WriteLock(new WriteLockImpl(_lock, _control_lock)); }
94 
95  void clear();
96 
97  bool percussive() const { return _percussive; }
98  void set_percussive(bool p) { _percussive = p; }
99 
100  void start_write();
101  bool writing() const { return _writing; }
102 
106  ResolveStuckNotes
107  };
108 
109  void end_write (StuckNoteOption, Time when = Time());
110 
111  void append(const Event<Time>& ev, Evoral::event_id_t evid);
112 
113  const TypeMap& type_map() const { return _type_map; }
114 
115  inline size_t n_notes() const { return _notes.size(); }
116  inline bool empty() const { return _notes.empty() && _sysexes.empty() && _patch_changes.empty() && ControlSet::controls_empty(); }
117 
118  inline static bool note_time_comparator(const boost::shared_ptr< const Note<Time> >& a,
119  const boost::shared_ptr< const Note<Time> >& b) {
120  return a->time() < b->time();
121  }
122 
124  inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
125  const boost::shared_ptr< const Note<Time> > b) const {
126  return a->note() < b->note();
127  }
128  };
129 
131  inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
132  const boost::shared_ptr< const Note<Time> > b) const {
133  return a->time() < b->time();
134  }
135  };
136 
138  typedef const Note<Time>* value_type;
139  inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
140  const boost::shared_ptr< const Note<Time> > b) const {
141  return a->time() > b->time();
142  }
143  };
144 
146  typedef const Note<Time>* value_type;
147  inline bool operator()(const boost::shared_ptr< const Note<Time> > a,
148  const boost::shared_ptr< const Note<Time> > b) const {
149  return a->end_time() > b->end_time();
150  }
151  };
152 
153  typedef std::multiset<NotePtr, EarlierNoteComparator> Notes;
154  inline Notes& notes() { return _notes; }
155  inline const Notes& notes() const { return _notes; }
156 
168  };
169 
170  void get_notes (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const;
171 
172  void remove_overlapping_notes ();
173  void trim_overlapping_notes ();
174  void remove_duplicate_notes ();
175 
178  FirstOnFirstOff
179  };
180 
181  bool overlapping_pitches_accepted() const { return _overlapping_pitches_accepted; }
182  void overlapping_pitches_accepted(bool yn) { _overlapping_pitches_accepted = yn; }
183  OverlapPitchResolution overlap_pitch_resolution() const { return _overlap_pitch_resolution; }
184  void set_overlap_pitch_resolution(OverlapPitchResolution opr);
185 
186  void set_notes (const typename Sequence<Time>::Notes& n);
187 
190 
192  inline bool operator() (constSysExPtr a, constSysExPtr b) const {
193  return a->time() < b->time();
194  }
195  };
196 
197  typedef std::multiset<SysExPtr, EarlierSysExComparator> SysExes;
198  inline SysExes& sysexes() { return _sysexes; }
199  inline const SysExes& sysexes() const { return _sysexes; }
200 
203 
205  inline bool operator() (constPatchChangePtr a, constPatchChangePtr b) const {
206  return a->time() < b->time();
207  }
208  };
209 
210  typedef std::multiset<PatchChangePtr, EarlierPatchChangeComparator> PatchChanges;
211  inline PatchChanges& patch_changes () { return _patch_changes; }
212  inline const PatchChanges& patch_changes () const { return _patch_changes; }
213 
214  void dump (std::ostream&) const;
215 
216 private:
217  typedef std::priority_queue<NotePtr, std::deque<NotePtr>, LaterNoteEndComparator> ActiveNotes;
218 public:
219 
222  public:
223  const_iterator();
224  const_iterator(const Sequence<Time>& seq,
225  Time t,
226  bool force_discrete,
227  const std::set<Evoral::Parameter>& filtered,
228  const std::set<WeakNotePtr>* active_notes=NULL);
229 
230  inline bool valid() const { return !_is_end && _event; }
231 
232  void invalidate(std::set<WeakNotePtr>* notes);
233 
234  const Event<Time>& operator*() const { return *_event; }
235  const boost::shared_ptr< Event<Time> > operator->() const { return _event; }
237 
238  const const_iterator& operator++(); // prefix only
239 
240  bool operator==(const const_iterator& other) const;
241  bool operator!=(const const_iterator& other) const { return ! operator==(other); }
242 
243  const_iterator& operator=(const const_iterator& other);
244 
245  private:
246  friend class Sequence<Time>;
247 
248  Time choose_next(Time earliest_t);
249  void set_event();
250 
251  typedef std::vector<ControlIterator> ControlIterators;
252  enum MIDIMessageType { NIL, NOTE_ON, NOTE_OFF, CONTROL, SYSEX, PATCH_CHANGE };
253 
256  mutable ActiveNotes _active_notes;
262  bool _is_end;
264  typename Notes::const_iterator _note_iter;
265  typename SysExes::const_iterator _sysex_iter;
266  typename PatchChanges::const_iterator _patch_change_iter;
267  ControlIterators _control_iters;
268  ControlIterators::iterator _control_iter;
270  };
271 
272  const_iterator begin (
273  Time t = Time(),
274  bool force_discrete = false,
275  const std::set<Evoral::Parameter>& f = std::set<Evoral::Parameter>(),
276  const std::set<WeakNotePtr>* active_notes = NULL) const {
277  return const_iterator (*this, t, force_discrete, f, active_notes);
278  }
279 
280  const const_iterator& end() const { return _end_iter; }
281 
282  // CONST iterator implementations (x3)
283  typename Notes::const_iterator note_lower_bound (Time t) const;
284  typename PatchChanges::const_iterator patch_change_lower_bound (Time t) const;
285  typename SysExes::const_iterator sysex_lower_bound (Time t) const;
286 
287  // NON-CONST iterator implementations (x3)
288  typename Notes::iterator note_lower_bound (Time t);
289  typename PatchChanges::iterator patch_change_lower_bound (Time t);
290  typename SysExes::iterator sysex_lower_bound (Time t);
291 
292  bool control_to_midi_event(boost::shared_ptr< Event<Time> >& ev,
293  const ControlIterator& iter) const;
294 
295  bool edited() const { return _edited; }
296  void set_edited(bool yn) { _edited = yn; }
297 
298  bool overlaps (const NotePtr& ev,
299  const NotePtr& ignore_this_note) const;
300  bool contains (const NotePtr& ev) const;
301 
302  bool add_note_unlocked (const NotePtr note, void* arg = 0);
303  void remove_note_unlocked(const constNotePtr note);
304 
305  void add_patch_change_unlocked (const PatchChangePtr);
306  void remove_patch_change_unlocked (const constPatchChangePtr);
307 
308  void add_sysex_unlocked (const SysExPtr);
309  void remove_sysex_unlocked (const SysExPtr);
310 
311  uint8_t lowest_note() const { return _lowest_note; }
312  uint8_t highest_note() const { return _highest_note; }
313 
314 
315 protected:
316  bool _edited;
319  mutable Glib::Threads::RWLock _lock;
320  bool _writing;
321 
322  virtual int resolve_overlaps_unlocked (const NotePtr, void* /* arg */ = 0) {
323  return 0;
324  }
325 
326  typedef std::multiset<NotePtr, NoteNumberComparator> Pitches;
327  inline Pitches& pitches(uint8_t chan) { return _pitches[chan&0xf]; }
328  inline const Pitches& pitches(uint8_t chan) const { return _pitches[chan&0xf]; }
329 
330  virtual void control_list_marked_dirty ();
331 
332 private:
333  friend class const_iterator;
334 
335  bool overlaps_unlocked (const NotePtr& ev, const NotePtr& ignore_this_note) const;
336  bool contains_unlocked (const NotePtr& ev) const;
337 
338  void append_note_on_unlocked(const MIDIEvent<Time>& event, Evoral::event_id_t);
339  void append_note_off_unlocked(const MIDIEvent<Time>& event);
340  void append_control_unlocked(const Parameter& param, Time time, double value, Evoral::event_id_t);
341  void append_sysex_unlocked(const MIDIEvent<Time>& ev, Evoral::event_id_t);
342  void append_patch_change_unlocked(const PatchChange<Time>&, Evoral::event_id_t);
343 
344  void get_notes_by_pitch (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const;
345  void get_notes_by_velocity (Notes&, NoteOperator, uint8_t val, int chan_mask = 0) const;
346 
348 
349  Notes _notes; // notes indexed by time
350  Pitches _pitches[16]; // notes indexed by channel+pitch
351  SysExes _sysexes;
352  PatchChanges _patch_changes;
353 
354  typedef std::multiset<NotePtr, EarlierNoteComparator> WriteNotes;
355  WriteNotes _write_notes[16];
356 
361  int _bank[16];
362 
363  const const_iterator _end_iter;
365 
366  uint8_t _lowest_note;
367  uint8_t _highest_note;
368 };
369 
370 
371 } // namespace Evoral
372 
373 template<typename Time> /*LIBEVORAL_API*/ std::ostream& operator<<(std::ostream& o, const Evoral::Sequence<Time>& s) { s.dump (o); return o; }
374 
375 
376 #endif // EVORAL_SEQUENCE_HPP
377 
bool operator()(const boost::shared_ptr< const Note< Time > > a, const boost::shared_ptr< const Note< Time > > b) const
Definition: Sequence.hpp:147
SysExes & sysexes()
Definition: Sequence.hpp:198
boost::shared_ptr< const Evoral::Note< Time > > constNotePtr
Definition: Sequence.hpp:87
const PatchChanges & patch_changes() const
Definition: Sequence.hpp:212
std::multiset< NotePtr, EarlierNoteComparator > Notes
Definition: Sequence.hpp:153
OverlapPitchResolution _overlap_pitch_resolution
Definition: Sequence.hpp:318
boost::shared_ptr< const Event< Time > > constSysExPtr
Definition: Sequence.hpp:189
int32_t event_id_t
Definition: types.hpp:40
std::multiset< NotePtr, EarlierNoteComparator > WriteNotes
Definition: Sequence.hpp:354
boost::shared_ptr< const PatchChange< Time > > constPatchChangePtr
Definition: Sequence.hpp:202
bool overlapping_pitches_accepted() const
Definition: Sequence.hpp:181
bool operator()(const boost::shared_ptr< const Note< Time > > a, const boost::shared_ptr< const Note< Time > > b) const
Definition: Sequence.hpp:139
std::multiset< NotePtr, NoteNumberComparator > Pitches
Definition: Sequence.hpp:326
Definition: note.h:32
bool operator()(const boost::shared_ptr< const Note< Time > > a, const boost::shared_ptr< const Note< Time > > b) const
Definition: Sequence.hpp:124
boost::shared_ptr< Glib::Threads::RWLock::ReaderLock > ReadLock
Definition: Sequence.hpp:89
boost::weak_ptr< Evoral::Note< Time > > WeakNotePtr
Definition: Sequence.hpp:86
void set_edited(bool yn)
Definition: Sequence.hpp:296
boost::shared_ptr< Event< Time > > _event
Definition: Sequence.hpp:255
const SysExes & sysexes() const
Definition: Sequence.hpp:199
PatchChanges _patch_changes
Definition: Sequence.hpp:352
tuple f
Definition: signals.py:35
#define LIBEVORAL_API
Definition: visibility.h:45
const TypeMap & _type_map
Definition: Sequence.hpp:347
OverlapPitchResolution overlap_pitch_resolution() const
Definition: Sequence.hpp:183
uint8_t highest_note() const
Definition: Sequence.hpp:312
LIBEVORAL_API uint64_t Sequence
Definition: debug.cpp:3
const Pitches & pitches(uint8_t chan) const
Definition: Sequence.hpp:328
const const_iterator _end_iter
Definition: Sequence.hpp:363
uint8_t _lowest_note
Definition: Sequence.hpp:366
const Event< Time > & operator*() const
Definition: Sequence.hpp:234
ControlIterator(boost::shared_ptr< const ControlList > al, double ax, double ay)
Definition: Sequence.hpp:49
PatchChanges & patch_changes()
Definition: Sequence.hpp:211
bool writing() const
Definition: Sequence.hpp:101
Notes::const_iterator _note_iter
Definition: Sequence.hpp:264
const Sequence< Time > * _seq
Definition: Sequence.hpp:254
virtual WriteLock write_lock()
Definition: Sequence.hpp:93
const boost::shared_ptr< Event< Time > > get_event_pointer()
Definition: Sequence.hpp:236
const const_iterator & end() const
Definition: Sequence.hpp:280
Glib::Threads::Mutex::Lock * control_lock
Definition: Sequence.hpp:80
SysExes::const_iterator _sysex_iter
Definition: Sequence.hpp:265
boost::shared_ptr< Evoral::Note< Time > > NotePtr
Definition: Sequence.hpp:85
virtual ReadLock read_lock() const
Definition: Sequence.hpp:92
SysExes _sysexes
Definition: Sequence.hpp:351
WriteLockImpl(Glib::Threads::RWLock &s, Glib::Threads::Mutex &c)
Definition: Sequence.hpp:72
bool edited() const
Definition: Sequence.hpp:295
std::multiset< SysExPtr, EarlierSysExComparator > SysExes
Definition: Sequence.hpp:197
Pitches & pitches(uint8_t chan)
Definition: Sequence.hpp:327
bool _overlapping_pitches_accepted
Definition: Sequence.hpp:317
virtual bool controls_empty() const
Definition: ControlSet.hpp:65
uint8_t lowest_note() const
Definition: Sequence.hpp:311
boost::shared_ptr< WriteLockImpl > WriteLock
Definition: Sequence.hpp:90
Notes & notes()
Definition: Sequence.hpp:154
void set_percussive(bool p)
Definition: Sequence.hpp:98
const_iterator begin(Time t=Time(), bool force_discrete=false, const std::set< Evoral::Parameter > &f=std::set< Evoral::Parameter >(), const std::set< WeakNotePtr > *active_notes=NULL) const
Definition: Sequence.hpp:272
bool empty() const
Definition: Sequence.hpp:116
bool operator()(const boost::shared_ptr< const Note< Time > > a, const boost::shared_ptr< const Note< Time > > b) const
Definition: Sequence.hpp:131
PatchChanges::const_iterator _patch_change_iter
Definition: Sequence.hpp:266
static bool note_time_comparator(const boost::shared_ptr< const Note< Time > > &a, const boost::shared_ptr< const Note< Time > > &b)
Definition: Sequence.hpp:118
bool operator!=(const const_iterator &other) const
Definition: Sequence.hpp:241
bool operator==(Range< T > a, Range< T > b)
Definition: Range.hpp:144
ControlIterators::iterator _control_iter
Definition: Sequence.hpp:268
Glib::Threads::RWLock _lock
Definition: Sequence.hpp:319
boost::shared_ptr< const ControlList > list
Definition: Sequence.hpp:55
bool percussive() const
Definition: Sequence.hpp:97
std::multiset< PatchChangePtr, EarlierPatchChangeComparator > PatchChanges
Definition: Sequence.hpp:210
const TypeMap & type_map() const
Definition: Sequence.hpp:113
ControlIterators _control_iters
Definition: Sequence.hpp:267
std::vector< ControlIterator > ControlIterators
Definition: Sequence.hpp:251
virtual int resolve_overlaps_unlocked(const NotePtr, void *=0)
Definition: Sequence.hpp:322
uint8_t _highest_note
Definition: Sequence.hpp:367
boost::shared_ptr< PatchChange< Time > > PatchChangePtr
Definition: Sequence.hpp:201
std::priority_queue< NotePtr, std::deque< NotePtr >, LaterNoteEndComparator > ActiveNotes
Definition: Sequence.hpp:217
const Notes & notes() const
Definition: Sequence.hpp:155
Glib::Threads::RWLock::WriterLock * sequence_lock
Definition: Sequence.hpp:79
void overlapping_pitches_accepted(bool yn)
Definition: Sequence.hpp:182
const boost::shared_ptr< Event< Time > > operator->() const
Definition: Sequence.hpp:235
boost::shared_ptr< Event< Time > > SysExPtr
Definition: Sequence.hpp:188
size_t n_notes() const
Definition: Sequence.hpp:115