Fix loading, recording & saving MIDI with PolyKeyPressure events.
[ardour.git] / libs / evoral / src / Sequence.cpp
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 #include <algorithm>
20 #include <cmath>
21 #include <iostream>
22 #include <limits>
23 #include <stdexcept>
24 #include <stdint.h>
25 #include <cstdio>
26
27 #if __clang__
28 #include "evoral/Note.hpp"
29 #endif
30
31 #include "pbd/compose.h"
32 #include "pbd/error.h"
33
34 #include "evoral/Beats.hpp"
35 #include "evoral/Control.hpp"
36 #include "evoral/ControlList.hpp"
37 #include "evoral/ControlSet.hpp"
38 #include "evoral/EventSink.hpp"
39 #include "evoral/ParameterDescriptor.hpp"
40 #include "evoral/Sequence.hpp"
41 #include "evoral/TypeMap.hpp"
42 #include "evoral/midi_util.h"
43
44 #include "pbd/i18n.h"
45
46 using namespace std;
47 using namespace PBD;
48
49 /** Minimum time between MIDI outputs from a single interpolated controller,
50     expressed in beats.  This is to limit the rate at which MIDI messages
51     are generated.  It is only applied to interpolated controllers.
52
53     XXX: This is a hack.  The time should probably be expressed in
54     seconds rather than beats, and should be configurable etc. etc.
55 */
56 static double const time_between_interpolated_controller_outputs = 1.0 / 256;
57
58 namespace Evoral {
59
60 // Read iterator (const_iterator)
61
62 template<typename Time>
63 Sequence<Time>::const_iterator::const_iterator()
64         : _seq(NULL)
65         , _event(boost::shared_ptr< Event<Time> >(new Event<Time>()))
66         , _active_patch_change_message (0)
67         , _type(NIL)
68         , _is_end(true)
69         , _control_iter(_control_iters.end())
70         , _force_discrete(false)
71 {
72 }
73
74 /** @param force_discrete true to force ControlLists to use discrete evaluation, otherwise false to get them to use their configured mode */
75 template<typename Time>
76 Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>&              seq,
77                                                Time                               t,
78                                                bool                               force_discrete,
79                                                const std::set<Evoral::Parameter>& filtered,
80                                                const std::set<WeakNotePtr>*       active_notes)
81         : _seq(&seq)
82         , _active_patch_change_message (0)
83         , _type(NIL)
84         , _is_end((t == DBL_MAX) || seq.empty())
85         , _note_iter(seq.notes().end())
86         , _sysex_iter(seq.sysexes().end())
87         , _patch_change_iter(seq.patch_changes().end())
88         , _control_iter(_control_iters.end())
89         , _force_discrete (force_discrete)
90 {
91         DEBUG_TRACE (DEBUG::Sequence, string_compose ("Created Iterator @ %1 (is end: %2)\n)", t, _is_end));
92
93         if (_is_end) {
94                 return;
95         }
96
97         _lock = seq.read_lock();
98
99         // Add currently active notes, if given
100         if (active_notes) {
101                 for (typename std::set<WeakNotePtr>::const_iterator i = active_notes->begin();
102                      i != active_notes->end(); ++i) {
103                         NotePtr note = i->lock();
104                         if (note && note->time() <= t && note->end_time() > t) {
105                                 _active_notes.push(note);
106                         }
107                 }
108         }
109
110         // Find first note which begins at or after t
111         _note_iter = seq.note_lower_bound(t);
112
113         // Find first sysex event at or after t
114         for (typename Sequence<Time>::SysExes::const_iterator i = seq.sysexes().begin();
115              i != seq.sysexes().end(); ++i) {
116                 if ((*i)->time() >= t) {
117                         _sysex_iter = i;
118                         break;
119                 }
120         }
121         assert(_sysex_iter == seq.sysexes().end() || (*_sysex_iter)->time() >= t);
122
123         // Find first patch event at or after t
124         for (typename Sequence<Time>::PatchChanges::const_iterator i = seq.patch_changes().begin(); i != seq.patch_changes().end(); ++i) {
125                 if ((*i)->time() >= t) {
126                         _patch_change_iter = i;
127                         break;
128                 }
129         }
130         assert (_patch_change_iter == seq.patch_changes().end() || (*_patch_change_iter)->time() >= t);
131
132         // Find first control event after t
133         _control_iters.reserve(seq._controls.size());
134         bool   found                  = false;
135         size_t earliest_control_index = 0;
136         double earliest_control_x     = DBL_MAX;
137         for (Controls::const_iterator i = seq._controls.begin(); i != seq._controls.end(); ++i) {
138
139                 if (filtered.find (i->first) != filtered.end()) {
140                         /* this parameter is filtered, so don't bother setting up an iterator for it */
141                         continue;
142                 }
143
144                 DEBUG_TRACE (DEBUG::Sequence, string_compose ("Iterator: control: %1\n", seq._type_map.to_symbol(i->first)));
145                 double x, y;
146                 bool ret;
147                 if (_force_discrete || i->second->list()->interpolation() == ControlList::Discrete) {
148                         ret = i->second->list()->rt_safe_earliest_event_discrete_unlocked (t.to_double(), x, y, true);
149                 } else {
150                         ret = i->second->list()->rt_safe_earliest_event_unlocked(t.to_double(), x, y, true);
151                 }
152                 if (!ret) {
153                         DEBUG_TRACE (DEBUG::Sequence, string_compose ("Iterator: CC %1 (size %2) has no events past %3\n",
154                                                                       i->first.id(), i->second->list()->size(), t));
155                         continue;
156                 }
157
158                 assert(x >= 0);
159
160                 const ParameterDescriptor& desc = seq.type_map().descriptor(i->first);
161                 if (y < desc.lower || y > desc.upper) {
162                         cerr << "ERROR: Controller value " << y
163                              << " out of range [" << desc.lower << "," << desc.upper
164                              << "], event ignored" << endl;
165                         continue;
166                 }
167
168                 DEBUG_TRACE (DEBUG::Sequence, string_compose ("Iterator: CC %1 added (%2, %3)\n", i->first.id(), x, y));
169
170                 const ControlIterator new_iter(i->second->list(), x, y);
171                 _control_iters.push_back(new_iter);
172
173                 // Found a new earliest_control
174                 if (x < earliest_control_x) {
175                         earliest_control_x     = x;
176                         earliest_control_index = _control_iters.size() - 1;
177                         found                  = true;
178                 }
179         }
180
181         if (found) {
182                 _control_iter = _control_iters.begin() + earliest_control_index;
183                 assert(_control_iter != _control_iters.end());
184                 assert(_control_iter->list);
185         } else {
186                 _control_iter = _control_iters.end();
187         }
188
189         // Choose the earliest event overall to point to
190         choose_next(t);
191
192         // Allocate a new event for storing the current event in MIDI format
193         _event = boost::shared_ptr< Event<Time> >(
194                 new Event<Time>(0, Time(), 4, NULL, true));
195
196         // Set event from chosen sub-iterator
197         set_event();
198
199         if (_is_end) {
200                 DEBUG_TRACE(DEBUG::Sequence,
201                             string_compose("Starting at end @ %1\n", t));
202         } else {
203                 DEBUG_TRACE(DEBUG::Sequence,
204                             string_compose("Starting at type 0x%1 : 0x%2 @ %3\n",
205                                            (int)_event->event_type(),
206                                            (int)((MIDIEvent<Time>*)_event.get())->type(),
207                                            _event->time()));
208         }
209 }
210
211 template<typename Time>
212 void
213 Sequence<Time>::const_iterator::invalidate(std::set< boost::weak_ptr< Note<Time> > >* notes)
214 {
215         while (!_active_notes.empty()) {
216                 if (notes) {
217                         notes->insert(_active_notes.top());
218                 }
219                 _active_notes.pop();
220         }
221         _type = NIL;
222         _is_end = true;
223         if (_seq) {
224                 _note_iter = _seq->notes().end();
225                 _sysex_iter = _seq->sysexes().end();
226                 _patch_change_iter = _seq->patch_changes().end();
227                 _active_patch_change_message = 0;
228         }
229         _control_iters.clear();
230         _control_iter = _control_iters.end();
231         _lock.reset();
232 }
233
234 template<typename Time>
235 Time
236 Sequence<Time>::const_iterator::choose_next(Time earliest_t)
237 {
238         _type = NIL;
239
240         // Next earliest note on
241         if (_note_iter != _seq->notes().end()) {
242                 _type      = NOTE_ON;
243                 earliest_t = (*_note_iter)->time();
244         }
245
246         // Use the next note off iff it's earlier or the same time as the note on
247         if ((!_active_notes.empty())) {
248                 if (_type == NIL || _active_notes.top()->end_time().to_double() <= earliest_t.to_double()) {
249                         _type      = NOTE_OFF;
250                         earliest_t = _active_notes.top()->end_time();
251                 }
252         }
253
254         // Use the next earliest controller iff it's earlier than the note event
255         if (_control_iter != _control_iters.end() &&
256             _control_iter->list && _control_iter->x != DBL_MAX) {
257                 if (_type == NIL || _control_iter->x < earliest_t.to_double()) {
258                         _type      = CONTROL;
259                         earliest_t = Time(_control_iter->x);
260                 }
261         }
262
263         // Use the next earliest SysEx iff it's earlier than the controller
264         if (_sysex_iter != _seq->sysexes().end()) {
265                 if (_type == NIL || (*_sysex_iter)->time() < earliest_t) {
266                         _type      = SYSEX;
267                         earliest_t = (*_sysex_iter)->time();
268                 }
269         }
270
271         // Use the next earliest patch change iff it's earlier than the SysEx
272         if (_patch_change_iter != _seq->patch_changes().end()) {
273                 if (_type == NIL || (*_patch_change_iter)->time() < earliest_t) {
274                         _type      = PATCH_CHANGE;
275                         earliest_t = (*_patch_change_iter)->time();
276                 }
277         }
278         return earliest_t;
279 }
280
281 template<typename Time>
282 void
283 Sequence<Time>::const_iterator::set_event()
284 {
285         switch (_type) {
286         case NOTE_ON:
287                 DEBUG_TRACE(DEBUG::Sequence, "iterator = note on\n");
288                 _event->assign ((*_note_iter)->on_event());
289                 _active_notes.push(*_note_iter);
290                 break;
291         case NOTE_OFF:
292                 DEBUG_TRACE(DEBUG::Sequence, "iterator = note off\n");
293                 assert(!_active_notes.empty());
294                 _event->assign (_active_notes.top()->off_event());
295                 // We don't pop the active note until we increment past it
296                 break;
297         case SYSEX:
298                 DEBUG_TRACE(DEBUG::Sequence, "iterator = sysex\n");
299                 _event->assign (*(*_sysex_iter));
300                 break;
301         case CONTROL:
302                 DEBUG_TRACE(DEBUG::Sequence, "iterator = control\n");
303                 _seq->control_to_midi_event(_event, *_control_iter);
304                 break;
305         case PATCH_CHANGE:
306                 DEBUG_TRACE(DEBUG::Sequence, "iterator = program change\n");
307                 _event->assign ((*_patch_change_iter)->message (_active_patch_change_message));
308                 break;
309         default:
310                 _is_end = true;
311                 break;
312         }
313
314         if (_type == NIL || !_event || _event->size() == 0) {
315                 DEBUG_TRACE(DEBUG::Sequence, "iterator = end\n");
316                 _type   = NIL;
317                 _is_end = true;
318         } else {
319                 assert(midi_event_is_valid(_event->buffer(), _event->size()));
320         }
321 }
322
323 template<typename Time>
324 const typename Sequence<Time>::const_iterator&
325 Sequence<Time>::const_iterator::operator++()
326 {
327         if (_is_end) {
328                 throw std::logic_error("Attempt to iterate past end of Sequence");
329         }
330
331         assert(_event && _event->buffer() && _event->size() > 0);
332
333         const MIDIEvent<Time>& ev = *((MIDIEvent<Time>*)_event.get());
334
335         if (!(     ev.is_note()
336                    || ev.is_cc()
337                    || ev.is_pgm_change()
338                    || ev.is_pitch_bender()
339                    || ev.is_channel_pressure()
340                    || ev.is_poly_pressure()
341                    || ev.is_sysex()) ) {
342                 cerr << "WARNING: Unknown event (type " << _type << "): " << hex
343                      << int(ev.buffer()[0]) << int(ev.buffer()[1]) << int(ev.buffer()[2]) << endl;
344         }
345
346         double x   = 0.0;
347         double y   = 0.0;
348         bool   ret = false;
349
350         // Increment past current event
351         switch (_type) {
352         case NOTE_ON:
353                 ++_note_iter;
354                 break;
355         case NOTE_OFF:
356                 _active_notes.pop();
357                 break;
358         case CONTROL:
359                 // Increment current controller iterator
360                 if (_force_discrete || _control_iter->list->interpolation() == ControlList::Discrete) {
361                         ret = _control_iter->list->rt_safe_earliest_event_discrete_unlocked (
362                                 _control_iter->x, x, y, false);
363                 } else {
364                         ret = _control_iter->list->rt_safe_earliest_event_linear_unlocked (
365                                 _control_iter->x + time_between_interpolated_controller_outputs, x, y, false);
366                 }
367                 assert(!ret || x > _control_iter->x);
368                 if (ret) {
369                         _control_iter->x = x;
370                         _control_iter->y = y;
371                 } else {
372                         _control_iter->list.reset();
373                         _control_iter->x = DBL_MAX;
374                         _control_iter->y = DBL_MAX;
375                 }
376
377                 // Find the controller with the next earliest event time
378                 _control_iter = _control_iters.begin();
379                 for (ControlIterators::iterator i = _control_iters.begin();
380                      i != _control_iters.end(); ++i) {
381                         if (i->x < _control_iter->x) {
382                                 _control_iter = i;
383                         }
384                 }
385                 break;
386         case SYSEX:
387                 ++_sysex_iter;
388                 break;
389         case PATCH_CHANGE:
390                 ++_active_patch_change_message;
391                 if (_active_patch_change_message == (*_patch_change_iter)->messages()) {
392                         ++_patch_change_iter;
393                         _active_patch_change_message = 0;
394                 }
395                 break;
396         default:
397                 assert(false);
398         }
399
400         // Choose the earliest event overall to point to
401         choose_next(std::numeric_limits<Time>::max());
402
403         // Set event from chosen sub-iterator
404         set_event();
405
406         assert(_is_end || (_event->size() > 0 && _event->buffer() && _event->buffer()[0] != '\0'));
407
408         return *this;
409 }
410
411 template<typename Time>
412 bool
413 Sequence<Time>::const_iterator::operator==(const const_iterator& other) const
414 {
415         if (_seq != other._seq) {
416                 return false;
417         } else if (_is_end || other._is_end) {
418                 return (_is_end == other._is_end);
419         } else if (_type != other._type) {
420                 return false;
421         } else {
422                 return (_event == other._event);
423         }
424 }
425
426 template<typename Time>
427 typename Sequence<Time>::const_iterator&
428 Sequence<Time>::const_iterator::operator=(const const_iterator& other)
429 {
430         _seq           = other._seq;
431         _event         = other._event;
432         _active_notes  = other._active_notes;
433         _type          = other._type;
434         _is_end        = other._is_end;
435         _note_iter     = other._note_iter;
436         _sysex_iter    = other._sysex_iter;
437         _patch_change_iter = other._patch_change_iter;
438         _control_iters = other._control_iters;
439         _force_discrete = other._force_discrete;
440         _active_patch_change_message = other._active_patch_change_message;
441
442         if (other._lock) {
443                 _lock = _seq->read_lock();
444         } else {
445                 _lock.reset();
446         }
447
448         if (other._control_iter == other._control_iters.end()) {
449                 _control_iter = _control_iters.end();
450         } else {
451                 const size_t index = other._control_iter - other._control_iters.begin();
452                 _control_iter  = _control_iters.begin() + index;
453         }
454
455         return *this;
456 }
457
458 // Sequence
459
460 template<typename Time>
461 Sequence<Time>::Sequence(const TypeMap& type_map)
462         : _edited(false)
463         , _overlapping_pitches_accepted (true)
464         , _overlap_pitch_resolution (FirstOnFirstOff)
465         , _writing(false)
466         , _type_map(type_map)
467         , _end_iter(*this, std::numeric_limits<Time>::max(), false, std::set<Evoral::Parameter> ())
468         , _percussive(false)
469         , _lowest_note(127)
470         , _highest_note(0)
471 {
472         DEBUG_TRACE (DEBUG::Sequence, string_compose ("Sequence constructed: %1\n", this));
473         assert(_end_iter._is_end);
474         assert( ! _end_iter._lock);
475
476         for (int i = 0; i < 16; ++i) {
477                 _bank[i] = 0;
478         }
479 }
480
481 template<typename Time>
482 Sequence<Time>::Sequence(const Sequence<Time>& other)
483         : ControlSet (other)
484         , _edited(false)
485         , _overlapping_pitches_accepted (other._overlapping_pitches_accepted)
486         , _overlap_pitch_resolution (other._overlap_pitch_resolution)
487         , _writing(false)
488         , _type_map(other._type_map)
489         , _end_iter(*this, std::numeric_limits<Time>::max(), false, std::set<Evoral::Parameter> ())
490         , _percussive(other._percussive)
491         , _lowest_note(other._lowest_note)
492         , _highest_note(other._highest_note)
493 {
494         for (typename Notes::const_iterator i = other._notes.begin(); i != other._notes.end(); ++i) {
495                 NotePtr n (new Note<Time> (**i));
496                 _notes.insert (n);
497         }
498
499         for (typename SysExes::const_iterator i = other._sysexes.begin(); i != other._sysexes.end(); ++i) {
500                 boost::shared_ptr<Event<Time> > n (new Event<Time> (**i, true));
501                 _sysexes.insert (n);
502         }
503
504         for (typename PatchChanges::const_iterator i = other._patch_changes.begin(); i != other._patch_changes.end(); ++i) {
505                 PatchChangePtr n (new PatchChange<Time> (**i));
506                 _patch_changes.insert (n);
507         }
508
509         for (int i = 0; i < 16; ++i) {
510                 _bank[i] = other._bank[i];
511         }
512
513         DEBUG_TRACE (DEBUG::Sequence, string_compose ("Sequence copied: %1\n", this));
514         assert(_end_iter._is_end);
515         assert(! _end_iter._lock);
516 }
517
518 /** Write the controller event pointed to by \a iter to \a ev.
519  * The buffer of \a ev will be allocated or resized as necessary.
520  * The event_type of \a ev should be set to the expected output type.
521  * \return true on success
522  */
523 template<typename Time>
524 bool
525 Sequence<Time>::control_to_midi_event(
526         boost::shared_ptr< Event<Time> >& ev,
527         const ControlIterator&            iter) const
528 {
529         assert(iter.list.get());
530         const uint32_t event_type = iter.list->parameter().type();
531
532         // initialize the event pointer with a new event, if necessary
533         if (!ev) {
534                 ev = boost::shared_ptr< Event<Time> >(new Event<Time>(event_type, Time(), 3, NULL, true));
535         }
536
537         uint8_t midi_type = _type_map.parameter_midi_type(iter.list->parameter());
538         ev->set_event_type(_type_map.midi_event_type(midi_type));
539         ev->set_id(-1);
540         switch (midi_type) {
541         case MIDI_CMD_CONTROL:
542                 assert(iter.list.get());
543                 assert(iter.list->parameter().channel() < 16);
544                 assert(iter.list->parameter().id() <= INT8_MAX);
545                 assert(iter.y <= INT8_MAX);
546
547                 ev->set_time(Time(iter.x));
548                 ev->realloc(3);
549                 ev->buffer()[0] = MIDI_CMD_CONTROL + iter.list->parameter().channel();
550                 ev->buffer()[1] = (uint8_t)iter.list->parameter().id();
551                 ev->buffer()[2] = (uint8_t)iter.y;
552                 break;
553
554         case MIDI_CMD_PGM_CHANGE:
555                 assert(iter.list.get());
556                 assert(iter.list->parameter().channel() < 16);
557                 assert(iter.y <= INT8_MAX);
558
559                 ev->set_time(Time(iter.x));
560                 ev->realloc(2);
561                 ev->buffer()[0] = MIDI_CMD_PGM_CHANGE + iter.list->parameter().channel();
562                 ev->buffer()[1] = (uint8_t)iter.y;
563                 break;
564
565         case MIDI_CMD_BENDER:
566                 assert(iter.list.get());
567                 assert(iter.list->parameter().channel() < 16);
568                 assert(iter.y < (1<<14));
569
570                 ev->set_time(Time(iter.x));
571                 ev->realloc(3);
572                 ev->buffer()[0] = MIDI_CMD_BENDER + iter.list->parameter().channel();
573                 ev->buffer()[1] = uint16_t(iter.y) & 0x7F; // LSB
574                 ev->buffer()[2] = (uint16_t(iter.y) >> 7) & 0x7F; // MSB
575                 break;
576
577         case MIDI_CMD_NOTE_PRESSURE:
578                 assert(iter.list.get());
579                 assert(iter.list->parameter().channel() < 16);
580                 assert(iter.list->parameter().id() <= INT8_MAX);
581                 assert(iter.y <= INT8_MAX);
582
583                 ev->set_time(Time(iter.x));
584                 ev->realloc(3);
585                 ev->buffer()[0] = MIDI_CMD_NOTE_PRESSURE + iter.list->parameter().channel();
586                 ev->buffer()[1] = (uint8_t)iter.list->parameter().id();
587                 ev->buffer()[2] = (uint8_t)iter.y;
588                 break;
589
590         case MIDI_CMD_CHANNEL_PRESSURE:
591                 assert(iter.list.get());
592                 assert(iter.list->parameter().channel() < 16);
593                 assert(iter.y <= INT8_MAX);
594
595                 ev->set_time(Time(iter.x));
596                 ev->realloc(2);
597                 ev->buffer()[0] = MIDI_CMD_CHANNEL_PRESSURE + iter.list->parameter().channel();
598                 ev->buffer()[1] = (uint8_t)iter.y;
599                 break;
600
601         default:
602                 return false;
603         }
604
605         return true;
606 }
607
608 /** Clear all events from the model.
609  */
610 template<typename Time>
611 void
612 Sequence<Time>::clear()
613 {
614         WriteLock lock(write_lock());
615         _notes.clear();
616         for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li)
617                 li->second->list()->clear();
618 }
619
620 /** Begin a write of events to the model.
621  *
622  * If \a mode is Sustained, complete notes with length are constructed as note
623  * on/off events are received.  Otherwise (Percussive), only note on events are
624  * stored; note off events are discarded entirely and all contained notes will
625  * have length 0.
626  */
627 template<typename Time>
628 void
629 Sequence<Time>::start_write()
630 {
631         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 : start_write (percussive = %2)\n", this, _percussive));
632         WriteLock lock(write_lock());
633         _writing = true;
634         for (int i = 0; i < 16; ++i) {
635                 _write_notes[i].clear();
636         }
637 }
638
639 /** Finish a write of events to the model.
640  *
641  * If \a delete_stuck is true and the current mode is Sustained, note on events
642  * that were never resolved with a corresonding note off will be deleted.
643  * Otherwise they will remain as notes with length 0.
644  */
645 template<typename Time>
646 void
647 Sequence<Time>::end_write (StuckNoteOption option, Time when)
648 {
649         WriteLock lock(write_lock());
650
651         if (!_writing) {
652                 return;
653         }
654
655         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 : end_write (%2 notes) delete stuck option %3 @ %4\n", this, _notes.size(), option, when));
656
657         for (typename Notes::iterator n = _notes.begin(); n != _notes.end() ;) {
658                 typename Notes::iterator next = n;
659                 ++next;
660
661                 if (!(*n)->length()) {
662                         switch (option) {
663                         case Relax:
664                                 break;
665                         case DeleteStuckNotes:
666                                 cerr << "WARNING: Stuck note lost: " << (*n)->note() << endl;
667                                 _notes.erase(n);
668                                 break;
669                         case ResolveStuckNotes:
670                                 if (when <= (*n)->time()) {
671                                         cerr << "WARNING: Stuck note resolution - end time @ "
672                                              << when << " is before note on: " << (**n) << endl;
673                                         _notes.erase (*n);
674                                 } else {
675                                         (*n)->set_length (when - (*n)->time());
676                                         cerr << "WARNING: resolved note-on with no note-off to generate " << (**n) << endl;
677                                 }
678                                 break;
679                         }
680                 }
681
682                 n = next;
683         }
684
685         for (int i = 0; i < 16; ++i) {
686                 _write_notes[i].clear();
687         }
688
689         _writing = false;
690 }
691
692
693 template<typename Time>
694 bool
695 Sequence<Time>::add_note_unlocked(const NotePtr note, void* arg)
696 {
697         /* This is the core method to add notes to a Sequence
698          */
699
700         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 add note %2 @ %3 dur %4\n", this, (int)note->note(), note->time(), note->length()));
701
702         if (resolve_overlaps_unlocked (note, arg)) {
703                 DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 DISALLOWED: note %2 @ %3\n", this, (int)note->note(), note->time()));
704                 return false;
705         }
706
707         if (note->id() < 0) {
708                 note->set_id (Evoral::next_event_id());
709         }
710
711         if (note->note() < _lowest_note)
712                 _lowest_note = note->note();
713         if (note->note() > _highest_note)
714                 _highest_note = note->note();
715
716         _notes.insert (note);
717         _pitches[note->channel()].insert (note);
718
719         _edited = true;
720
721         return true;
722 }
723
724 template<typename Time>
725 void
726 Sequence<Time>::remove_note_unlocked(const constNotePtr note)
727 {
728         bool erased = false;
729         bool id_matched = false;
730
731         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 remove note #%2 %3 @ %4\n", this, note->id(), (int)note->note(), note->time()));
732
733         /* first try searching for the note using the time index, which is
734          * faster since the container is "indexed" by time. (technically, this
735          * means that lower_bound() can do a binary search rather than linear)
736          *
737          * this may not work, for reasons explained below.
738          */
739
740         typename Sequence<Time>::Notes::iterator i;
741
742         for (i = note_lower_bound(note->time()); i != _notes.end() && (*i)->time() == note->time(); ++i) {
743
744                 if (*i == note) {
745
746                         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1\terasing note #%2 %3 @ %4\n", this, (*i)->id(), (int)(*i)->note(), (*i)->time()));
747                         _notes.erase (i);
748
749                         if (note->note() == _lowest_note || note->note() == _highest_note) {
750
751                                 _lowest_note = 127;
752                                 _highest_note = 0;
753
754                                 for (typename Sequence<Time>::Notes::iterator ii = _notes.begin(); ii != _notes.end(); ++ii) {
755                                         if ((*ii)->note() < _lowest_note)
756                                                 _lowest_note = (*ii)->note();
757                                         if ((*ii)->note() > _highest_note)
758                                                 _highest_note = (*ii)->note();
759                                 }
760                         }
761
762                         erased = true;
763                         break;
764                 }
765         }
766
767         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1\ttime-based lookup did not find note #%2 %3 @ %4\n", this, note->id(), (int)note->note(), note->time()));
768
769         if (!erased) {
770
771                 /* if the note's time property was changed in tandem with some
772                  * other property as the next operation after it was added to
773                  * the sequence, then at the point where we call this to undo
774                  * the add, the note we are targetting currently has a
775                  * different time property than the one we we passed via
776                  * the argument.
777                  *
778                  * in this scenario, we have no choice other than to linear
779                  * search the list of notes and find the note by ID.
780                  */
781
782                 for (i = _notes.begin(); i != _notes.end(); ++i) {
783
784                         if ((*i)->id() == note->id()) {
785
786                                 DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1\tID-based pass, erasing note #%2 %3 @ %4\n", this, (*i)->id(), (int)(*i)->note(), (*i)->time()));
787                                 _notes.erase (i);
788
789                                 if (note->note() == _lowest_note || note->note() == _highest_note) {
790
791                                         _lowest_note = 127;
792                                         _highest_note = 0;
793
794                                         for (typename Sequence<Time>::Notes::iterator ii = _notes.begin(); ii != _notes.end(); ++ii) {
795                                                 if ((*ii)->note() < _lowest_note)
796                                                         _lowest_note = (*ii)->note();
797                                                 if ((*ii)->note() > _highest_note)
798                                                         _highest_note = (*ii)->note();
799                                         }
800                                 }
801
802                                 erased = true;
803                                 id_matched = true;
804                                 break;
805                         }
806                 }
807         }
808
809         if (erased) {
810
811                 Pitches& p (pitches (note->channel()));
812
813                 typename Pitches::iterator j;
814
815                 /* if we had to ID-match above, we can't expect to find it in
816                  * pitches via note comparison either. so do another linear
817                  * search to locate it. otherwise, we can use the note index
818                  * to potentially speed things up.
819                  */
820
821                 if (id_matched) {
822
823                         for (j = p.begin(); j != p.end(); ++j) {
824                                 if ((*j)->id() == note->id()) {
825                                         p.erase (j);
826                                         break;
827                                 }
828                         }
829
830                 } else {
831
832                         /* Now find the same note in the "pitches" list (which indexes
833                          * notes by channel+time. We care only about its note number
834                          * so the search_note has all other properties unset.
835                          */
836
837                         NotePtr search_note (new Note<Time>(0, Time(), Time(), note->note(), 0));
838
839                         for (j = p.lower_bound (search_note); j != p.end() && (*j)->note() == note->note(); ++j) {
840
841                                 if ((*j) == note) {
842                                         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1\terasing pitch %2 @ %3\n", this, (int)(*j)->note(), (*j)->time()));
843                                         p.erase (j);
844                                         break;
845                                 }
846                         }
847                 }
848
849                 if (j == p.end()) {
850                         warning << string_compose ("erased note %1 not found in pitches for channel %2", *note, (int) note->channel()) << endmsg;
851                 }
852
853                 _edited = true;
854
855         } else {
856                 cerr << "Unable to find note to erase matching " << *note.get() << endmsg;
857         }
858 }
859
860 template<typename Time>
861 void
862 Sequence<Time>::remove_patch_change_unlocked (const constPatchChangePtr p)
863 {
864         typename Sequence<Time>::PatchChanges::iterator i = patch_change_lower_bound (p->time ());
865
866         while (i != _patch_changes.end() && ((*i)->time() == p->time())) {
867
868                 typename Sequence<Time>::PatchChanges::iterator tmp = i;
869                 ++tmp;
870
871                 if (**i == *p) {
872                         _patch_changes.erase (i);
873                 }
874
875                 i = tmp;
876         }
877 }
878
879 template<typename Time>
880 void
881 Sequence<Time>::remove_sysex_unlocked (const SysExPtr sysex)
882 {
883         typename Sequence<Time>::SysExes::iterator i = sysex_lower_bound (sysex->time ());
884         while (i != _sysexes.end() && (*i)->time() == sysex->time()) {
885
886                 typename Sequence<Time>::SysExes::iterator tmp = i;
887                 ++tmp;
888
889                 if (*i == sysex) {
890                         _sysexes.erase (i);
891                 }
892
893                 i = tmp;
894         }
895 }
896
897 /** Append \a ev to model.  NOT realtime safe.
898  *
899  * The timestamp of event is expected to be relative to
900  * the start of this model (t=0) and MUST be monotonically increasing
901  * and MUST be >= the latest event currently in the model.
902  */
903 template<typename Time>
904 void
905 Sequence<Time>::append(const Event<Time>& event, event_id_t evid)
906 {
907         WriteLock lock(write_lock());
908
909         const MIDIEvent<Time>& ev = (const MIDIEvent<Time>&)event;
910
911         assert(_notes.empty() || ev.time() >= (*_notes.rbegin())->time());
912         assert(_writing);
913
914         if (!midi_event_is_valid(ev.buffer(), ev.size())) {
915                 cerr << "WARNING: Sequence ignoring illegal MIDI event" << endl;
916                 return;
917         }
918
919         if (ev.is_note_on() && ev.velocity() > 0) {
920                 append_note_on_unlocked (ev, evid);
921         } else if (ev.is_note_off() || (ev.is_note_on() && ev.velocity() == 0)) {
922                 /* XXX note: event ID is discarded because we merge the on+off events into
923                    a single note object
924                 */
925                 append_note_off_unlocked (ev);
926         } else if (ev.is_sysex()) {
927                 append_sysex_unlocked(ev, evid);
928         } else if (ev.is_cc() && (ev.cc_number() == MIDI_CTL_MSB_BANK || ev.cc_number() == MIDI_CTL_LSB_BANK)) {
929                 /* note bank numbers in our _bank[] array, so that we can write an event when the program change arrives */
930                 if (ev.cc_number() == MIDI_CTL_MSB_BANK) {
931                         _bank[ev.channel()] &= ~(0x7f << 7);
932                         _bank[ev.channel()] |= ev.cc_value() << 7;
933                 } else {
934                         _bank[ev.channel()] &= ~0x7f;
935                         _bank[ev.channel()] |= ev.cc_value();
936                 }
937         } else if (ev.is_cc()) {
938                 append_control_unlocked(
939                         Parameter(ev.event_type(), ev.channel(), ev.cc_number()),
940                         ev.time(), ev.cc_value(), evid);
941         } else if (ev.is_pgm_change()) {
942                 /* write a patch change with this program change and any previously set-up bank number */
943                 append_patch_change_unlocked (PatchChange<Time> (ev.time(), ev.channel(), ev.pgm_number(), _bank[ev.channel()]), evid);
944         } else if (ev.is_pitch_bender()) {
945                 append_control_unlocked(
946                         Parameter(ev.event_type(), ev.channel()),
947                         ev.time(), double ((0x7F & ev.pitch_bender_msb()) << 7
948                                            | (0x7F & ev.pitch_bender_lsb())),
949                         evid);
950         } else if (ev.is_poly_pressure()) {
951                 append_control_unlocked (Parameter (ev.event_type(), ev.channel(), ev.poly_note()), ev.time(), ev.poly_pressure(), evid);
952         } else if (ev.is_channel_pressure()) {
953                 append_control_unlocked(
954                         Parameter(ev.event_type(), ev.channel()),
955                         ev.time(), ev.channel_pressure(), evid);
956         } else if (!_type_map.type_is_midi(ev.event_type())) {
957                 printf("WARNING: Sequence: Unknown event type %X: ", ev.event_type());
958                 for (size_t i=0; i < ev.size(); ++i) {
959                         printf("%X ", ev.buffer()[i]);
960                 }
961                 printf("\n");
962         } else {
963                 printf("WARNING: Sequence: Unknown MIDI event type %X\n", ev.type());
964         }
965
966         _edited = true;
967 }
968
969 template<typename Time>
970 void
971 Sequence<Time>::append_note_on_unlocked (const MIDIEvent<Time>& ev, event_id_t evid)
972 {
973         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 c=%2 note %3 on @ %4 v=%5\n", this,
974                                                       (int)ev.channel(), (int)ev.note(),
975                                                       ev.time(), (int)ev.velocity()));
976         assert(_writing);
977
978         if (ev.note() > 127) {
979                 error << string_compose (_("invalid note on number (%1) ignored"), (int) ev.note()) << endmsg;
980                 return;
981         } else if (ev.channel() >= 16) {
982                 error << string_compose (_("invalid note on channel (%1) ignored"), (int) ev.channel()) << endmsg;
983                 return;
984         } else if (ev.velocity() == 0) {
985                 // Note on with velocity 0 handled as note off by caller
986                 error << string_compose (_("invalid note on velocity (%1) ignored"), (int) ev.velocity()) << endmsg;
987                 return;
988         }
989
990         NotePtr note(new Note<Time>(ev.channel(), ev.time(), Time(), ev.note(), ev.velocity()));
991         note->set_id (evid);
992
993         add_note_unlocked (note);
994
995         DEBUG_TRACE (DEBUG::Sequence, string_compose ("Appending active note on %1 channel %2\n",
996                                                       (unsigned)(uint8_t)note->note(), note->channel()));
997         _write_notes[note->channel()].insert (note);
998
999 }
1000
1001 template<typename Time>
1002 void
1003 Sequence<Time>::append_note_off_unlocked (const MIDIEvent<Time>& ev)
1004 {
1005         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 c=%2 note %3 OFF @ %4 v=%5\n",
1006                                                       this, (int)ev.channel(),
1007                                                       (int)ev.note(), ev.time(), (int)ev.velocity()));
1008         assert(_writing);
1009
1010         if (ev.note() > 127) {
1011                 error << string_compose (_("invalid note off number (%1) ignored"), (int) ev.note()) << endmsg;
1012                 return;
1013         } else if (ev.channel() >= 16) {
1014                 error << string_compose (_("invalid note off channel (%1) ignored"), (int) ev.channel()) << endmsg;
1015                 return;
1016         }
1017
1018         _edited = true;
1019
1020         bool resolved = false;
1021
1022         /* _write_notes is sorted earliest-latest, so this will find the first matching note (FIFO) that
1023            matches this note (by pitch & channel). the MIDI specification doesn't provide any guidance
1024            whether to use FIFO or LIFO for this matching process, so SMF is fundamentally a lossy
1025            format.
1026         */
1027
1028         /* XXX use _overlap_pitch_resolution to determine FIFO/LIFO ... */
1029
1030         for (typename WriteNotes::iterator n = _write_notes[ev.channel()].begin(); n != _write_notes[ev.channel()].end(); ) {
1031
1032                 typename WriteNotes::iterator tmp = n;
1033                 ++tmp;
1034
1035                 NotePtr nn = *n;
1036                 if (ev.note() == nn->note() && nn->channel() == ev.channel()) {
1037                         assert(ev.time() >= nn->time());
1038
1039                         nn->set_length (ev.time() - nn->time());
1040                         nn->set_off_velocity (ev.velocity());
1041
1042                         _write_notes[ev.channel()].erase(n);
1043                         DEBUG_TRACE (DEBUG::Sequence, string_compose ("resolved note @ %2 length: %1\n", nn->length(), nn->time()));
1044                         resolved = true;
1045                         break;
1046                 }
1047
1048                 n = tmp;
1049         }
1050
1051         if (!resolved) {
1052                 cerr << this << " spurious note off chan " << (int)ev.channel()
1053                      << ", note " << (int)ev.note() << " @ " << ev.time() << endl;
1054         }
1055 }
1056
1057 template<typename Time>
1058 void
1059 Sequence<Time>::append_control_unlocked(const Parameter& param, Time time, double value, event_id_t /* evid */)
1060 {
1061         DEBUG_TRACE (DEBUG::Sequence, string_compose ("%1 %2 @ %3 = %4 # controls: %5\n",
1062                                                       this, _type_map.to_symbol(param), time, value, _controls.size()));
1063         boost::shared_ptr<Control> c = control(param, true);
1064         c->list()->add (time.to_double(), value, true, false);
1065         /* XXX control events should use IDs */
1066 }
1067
1068 template<typename Time>
1069 void
1070 Sequence<Time>::append_sysex_unlocked(const MIDIEvent<Time>& ev, event_id_t /* evid */)
1071 {
1072 #ifdef DEBUG_SEQUENCE
1073         cerr << this << " SysEx @ " << ev.time() << " \t= \t [ " << hex;
1074         for (size_t i=0; i < ev.size(); ++i) {
1075                 cerr << int(ev.buffer()[i]) << " ";
1076         } cerr << "]" << endl;
1077 #endif
1078
1079         boost::shared_ptr<MIDIEvent<Time> > event(new MIDIEvent<Time>(ev, true));
1080         /* XXX sysex events should use IDs */
1081         _sysexes.insert(event);
1082 }
1083
1084 template<typename Time>
1085 void
1086 Sequence<Time>::append_patch_change_unlocked (const PatchChange<Time>& ev, event_id_t id)
1087 {
1088         PatchChangePtr p (new PatchChange<Time> (ev));
1089
1090         if (p->id() < 0) {
1091                 p->set_id (id);
1092         }
1093
1094         _patch_changes.insert (p);
1095 }
1096
1097 template<typename Time>
1098 void
1099 Sequence<Time>::add_patch_change_unlocked (PatchChangePtr p)
1100 {
1101         if (p->id () < 0) {
1102                 p->set_id (Evoral::next_event_id ());
1103         }
1104
1105         _patch_changes.insert (p);
1106 }
1107
1108 template<typename Time>
1109 void
1110 Sequence<Time>::add_sysex_unlocked (SysExPtr s)
1111 {
1112         if (s->id () < 0) {
1113                 s->set_id (Evoral::next_event_id ());
1114         }
1115
1116         _sysexes.insert (s);
1117 }
1118
1119 template<typename Time>
1120 bool
1121 Sequence<Time>::contains (const NotePtr& note) const
1122 {
1123         ReadLock lock (read_lock());
1124         return contains_unlocked (note);
1125 }
1126
1127 template<typename Time>
1128 bool
1129 Sequence<Time>::contains_unlocked (const NotePtr& note) const
1130 {
1131         const Pitches& p (pitches (note->channel()));
1132         NotePtr search_note(new Note<Time>(0, Time(), Time(), note->note()));
1133
1134         for (typename Pitches::const_iterator i = p.lower_bound (search_note);
1135              i != p.end() && (*i)->note() == note->note(); ++i) {
1136
1137                 if (**i == *note) {
1138                         return true;
1139                 }
1140         }
1141
1142         return false;
1143 }
1144
1145 template<typename Time>
1146 bool
1147 Sequence<Time>::overlaps (const NotePtr& note, const NotePtr& without) const
1148 {
1149         ReadLock lock (read_lock());
1150         return overlaps_unlocked (note, without);
1151 }
1152
1153 template<typename Time>
1154 bool
1155 Sequence<Time>::overlaps_unlocked (const NotePtr& note, const NotePtr& without) const
1156 {
1157         Time sa = note->time();
1158         Time ea  = note->end_time();
1159
1160         const Pitches& p (pitches (note->channel()));
1161         NotePtr search_note(new Note<Time>(0, Time(), Time(), note->note()));
1162
1163         for (typename Pitches::const_iterator i = p.lower_bound (search_note);
1164              i != p.end() && (*i)->note() == note->note(); ++i) {
1165
1166                 if (without && (**i) == *without) {
1167                         continue;
1168                 }
1169
1170                 Time sb = (*i)->time();
1171                 Time eb = (*i)->end_time();
1172
1173                 if (((sb > sa) && (eb <= ea)) ||
1174                     ((eb >= sa) && (eb <= ea)) ||
1175                     ((sb > sa) && (sb <= ea)) ||
1176                     ((sa >= sb) && (sa <= eb) && (ea <= eb))) {
1177                         return true;
1178                 }
1179         }
1180
1181         return false;
1182 }
1183
1184 template<typename Time>
1185 void
1186 Sequence<Time>::set_notes (const typename Sequence<Time>::Notes& n)
1187 {
1188         _notes = n;
1189 }
1190
1191 // CONST iterator implementations (x3)
1192
1193 /** Return the earliest note with time >= t */
1194 template<typename Time>
1195 typename Sequence<Time>::Notes::const_iterator
1196 Sequence<Time>::note_lower_bound (Time t) const
1197 {
1198         NotePtr search_note(new Note<Time>(0, t, Time(), 0, 0));
1199         typename Sequence<Time>::Notes::const_iterator i = _notes.lower_bound(search_note);
1200         assert(i == _notes.end() || (*i)->time() >= t);
1201         return i;
1202 }
1203
1204 /** Return the earliest patch change with time >= t */
1205 template<typename Time>
1206 typename Sequence<Time>::PatchChanges::const_iterator
1207 Sequence<Time>::patch_change_lower_bound (Time t) const
1208 {
1209         PatchChangePtr search (new PatchChange<Time> (t, 0, 0, 0));
1210         typename Sequence<Time>::PatchChanges::const_iterator i = _patch_changes.lower_bound (search);
1211         assert (i == _patch_changes.end() || (*i)->time() >= t);
1212         return i;
1213 }
1214
1215 /** Return the earliest sysex with time >= t */
1216 template<typename Time>
1217 typename Sequence<Time>::SysExes::const_iterator
1218 Sequence<Time>::sysex_lower_bound (Time t) const
1219 {
1220         SysExPtr search (new Event<Time> (0, t));
1221         typename Sequence<Time>::SysExes::const_iterator i = _sysexes.lower_bound (search);
1222         assert (i == _sysexes.end() || (*i)->time() >= t);
1223         return i;
1224 }
1225
1226 // NON-CONST iterator implementations (x3)
1227
1228 /** Return the earliest note with time >= t */
1229 template<typename Time>
1230 typename Sequence<Time>::Notes::iterator
1231 Sequence<Time>::note_lower_bound (Time t)
1232 {
1233         NotePtr search_note(new Note<Time>(0, t, Time(), 0, 0));
1234         typename Sequence<Time>::Notes::iterator i = _notes.lower_bound(search_note);
1235         assert(i == _notes.end() || (*i)->time() >= t);
1236         return i;
1237 }
1238
1239 /** Return the earliest patch change with time >= t */
1240 template<typename Time>
1241 typename Sequence<Time>::PatchChanges::iterator
1242 Sequence<Time>::patch_change_lower_bound (Time t)
1243 {
1244         PatchChangePtr search (new PatchChange<Time> (t, 0, 0, 0));
1245         typename Sequence<Time>::PatchChanges::iterator i = _patch_changes.lower_bound (search);
1246         assert (i == _patch_changes.end() || (*i)->time() >= t);
1247         return i;
1248 }
1249
1250 /** Return the earliest sysex with time >= t */
1251 template<typename Time>
1252 typename Sequence<Time>::SysExes::iterator
1253 Sequence<Time>::sysex_lower_bound (Time t)
1254 {
1255         SysExPtr search (new Event<Time> (0, t));
1256         typename Sequence<Time>::SysExes::iterator i = _sysexes.lower_bound (search);
1257         assert (i == _sysexes.end() || (*i)->time() >= t);
1258         return i;
1259 }
1260
1261 template<typename Time>
1262 void
1263 Sequence<Time>::get_notes (Notes& n, NoteOperator op, uint8_t val, int chan_mask) const
1264 {
1265         switch (op) {
1266         case PitchEqual:
1267         case PitchLessThan:
1268         case PitchLessThanOrEqual:
1269         case PitchGreater:
1270         case PitchGreaterThanOrEqual:
1271                 get_notes_by_pitch (n, op, val, chan_mask);
1272                 break;
1273
1274         case VelocityEqual:
1275         case VelocityLessThan:
1276         case VelocityLessThanOrEqual:
1277         case VelocityGreater:
1278         case VelocityGreaterThanOrEqual:
1279                 get_notes_by_velocity (n, op, val, chan_mask);
1280                 break;
1281         }
1282 }
1283
1284 template<typename Time>
1285 void
1286 Sequence<Time>::get_notes_by_pitch (Notes& n, NoteOperator op, uint8_t val, int chan_mask) const
1287 {
1288         for (uint8_t c = 0; c < 16; ++c) {
1289
1290                 if (chan_mask != 0 && !((1<<c) & chan_mask)) {
1291                         continue;
1292                 }
1293
1294                 const Pitches& p (pitches (c));
1295                 NotePtr search_note(new Note<Time>(0, Time(), Time(), val, 0));
1296                 typename Pitches::const_iterator i;
1297                 switch (op) {
1298                 case PitchEqual:
1299                         i = p.lower_bound (search_note);
1300                         while (i != p.end() && (*i)->note() == val) {
1301                                 n.insert (*i);
1302                         }
1303                         break;
1304                 case PitchLessThan:
1305                         i = p.upper_bound (search_note);
1306                         while (i != p.end() && (*i)->note() < val) {
1307                                 n.insert (*i);
1308                         }
1309                         break;
1310                 case PitchLessThanOrEqual:
1311                         i = p.upper_bound (search_note);
1312                         while (i != p.end() && (*i)->note() <= val) {
1313                                 n.insert (*i);
1314                         }
1315                         break;
1316                 case PitchGreater:
1317                         i = p.lower_bound (search_note);
1318                         while (i != p.end() && (*i)->note() > val) {
1319                                 n.insert (*i);
1320                         }
1321                         break;
1322                 case PitchGreaterThanOrEqual:
1323                         i = p.lower_bound (search_note);
1324                         while (i != p.end() && (*i)->note() >= val) {
1325                                 n.insert (*i);
1326                         }
1327                         break;
1328
1329                 default:
1330                         //fatal << string_compose (_("programming error: %1 %2", X_("get_notes_by_pitch() called with illegal operator"), op)) << endmsg;
1331                         abort(); /* NOTREACHED*/
1332                 }
1333         }
1334 }
1335
1336 template<typename Time>
1337 void
1338 Sequence<Time>::get_notes_by_velocity (Notes& n, NoteOperator op, uint8_t val, int chan_mask) const
1339 {
1340         ReadLock lock (read_lock());
1341
1342         for (typename Notes::const_iterator i = _notes.begin(); i != _notes.end(); ++i) {
1343
1344                 if (chan_mask != 0 && !((1<<((*i)->channel())) & chan_mask)) {
1345                         continue;
1346                 }
1347
1348                 switch (op) {
1349                 case VelocityEqual:
1350                         if ((*i)->velocity() == val) {
1351                                 n.insert (*i);
1352                         }
1353                         break;
1354                 case VelocityLessThan:
1355                         if ((*i)->velocity() < val) {
1356                                 n.insert (*i);
1357                         }
1358                         break;
1359                 case VelocityLessThanOrEqual:
1360                         if ((*i)->velocity() <= val) {
1361                                 n.insert (*i);
1362                         }
1363                         break;
1364                 case VelocityGreater:
1365                         if ((*i)->velocity() > val) {
1366                                 n.insert (*i);
1367                         }
1368                         break;
1369                 case VelocityGreaterThanOrEqual:
1370                         if ((*i)->velocity() >= val) {
1371                                 n.insert (*i);
1372                         }
1373                         break;
1374                 default:
1375                         // fatal << string_compose (_("programming error: %1 %2", X_("get_notes_by_velocity() called with illegal operator"), op)) << endmsg;
1376                         abort(); /* NOTREACHED*/
1377
1378                 }
1379         }
1380 }
1381
1382 template<typename Time>
1383 void
1384 Sequence<Time>::set_overlap_pitch_resolution (OverlapPitchResolution opr)
1385 {
1386         _overlap_pitch_resolution = opr;
1387
1388         /* XXX todo: clean up existing overlaps in source data? */
1389 }
1390
1391 template<typename Time>
1392 void
1393 Sequence<Time>::control_list_marked_dirty ()
1394 {
1395         set_edited (true);
1396 }
1397
1398 template<typename Time>
1399 void
1400 Sequence<Time>::dump (ostream& str) const
1401 {
1402         typename Sequence<Time>::const_iterator i;
1403         str << "+++ dump\n";
1404         for (i = begin(); i != end(); ++i) {
1405                 str << *i << endl;
1406         }
1407         str << "--- dump\n";
1408 }
1409
1410 template class Sequence<Evoral::Beats>;
1411
1412 } // namespace Evoral