Das BlinkenSendButtons
[ardour.git] / libs / evoral / src / Sequence.cpp
1 /* This file is part of Evoral.
2  * Copyright (C) 2008 Dave 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 #define __STDC_LIMIT_MACROS 1
20 #include <algorithm>
21 #include <cmath>
22 #include <iostream>
23 #include <limits>
24 #include <stdexcept>
25 #include <stdint.h>
26 #include "evoral/Control.hpp"
27 #include "evoral/ControlList.hpp"
28 #include "evoral/ControlSet.hpp"
29 #include "evoral/EventSink.hpp"
30 #include "evoral/MIDIParameters.hpp"
31 #include "evoral/Sequence.hpp"
32 #include "evoral/TypeMap.hpp"
33 #include "evoral/midi_util.h"
34
35 //#define DEBUG_SEQUENCE 1
36 #ifdef DEBUG_SEQUENCE
37         #include <boost/format.hpp>
38         using boost::format;
39         #define DUMP(x) cerr << (x);
40 #else
41         #define DUMP(x)
42 #endif
43
44 using namespace std;
45
46 namespace Evoral {
47
48 template<typename Time>
49 void Sequence<Time>::write_lock() {
50         _lock.writer_lock();
51         _control_lock.lock();
52 }
53
54 template<typename Time>
55 void Sequence<Time>::write_unlock() {
56         _lock.writer_unlock();
57         _control_lock.unlock();
58 }
59
60 template<typename Time>
61 void Sequence<Time>::read_lock() const {
62         _lock.reader_lock();
63 }
64
65 template<typename Time>
66 void Sequence<Time>::read_unlock() const {
67         _lock.reader_unlock();
68 }
69
70
71 // Read iterator (const_iterator)
72
73 template<typename Time>
74 Sequence<Time>::const_iterator::const_iterator()
75         : _seq(NULL)
76         , _is_end(true)
77         , _locked(false)
78         , _control_iter(_control_iters.end())
79 {
80         _event = boost::shared_ptr< Event<Time> >(new Event<Time>());
81 }
82
83 template<typename Time>
84 Sequence<Time>::const_iterator::const_iterator(const Sequence<Time>& seq, Time t)
85         : _seq(&seq)
86         , _type(NIL)
87         , _is_end((t == DBL_MAX) || seq.empty())
88         , _locked(!_is_end)
89         , _note_iter(seq.notes().end())
90         , _sysex_iter(seq.sysexes().end())
91         , _control_iter(_control_iters.end())
92 {
93         DUMP(format("Created Iterator @ %1% (is end: %2%)\n)") % t % _is_end);
94         
95         if (_is_end) {
96                 return;
97         }
98
99         seq.read_lock();
100
101         // Find first note which begins after t
102         for (typename Sequence<Time>::Notes::const_iterator i = seq.notes().begin();
103                         i != seq.notes().end(); ++i) {
104                 if ((*i)->time() >= t) {
105                         _note_iter = i;
106                         break;
107                 }
108         }
109         assert(_note_iter == seq.notes().end() || (*_note_iter)->time() >= t);
110         
111         // Find first sysex event after t
112         for (typename Sequence<Time>::SysExes::const_iterator i = seq.sysexes().begin();
113                         i != seq.sysexes().end(); ++i) {
114                 if ((*i)->time() >= t) {
115                         _sysex_iter = i;
116                         break;
117                 }
118         }
119         assert(_sysex_iter == seq.sysexes().end() || (*_sysex_iter)->time() >= t);
120
121         // Find first control event after t
122         ControlIterator earliest_control(boost::shared_ptr<ControlList>(), DBL_MAX, 0.0);
123         _control_iters.reserve(seq._controls.size());
124         bool   found                  = false;
125         size_t earliest_control_index = 0;
126         for (Controls::const_iterator i = seq._controls.begin(); i != seq._controls.end(); ++i) {
127                 DUMP(format("Iterator: control: %1%\n") % seq._type_map.to_symbol(i->first));
128                 double x, y;
129                 bool ret = i->second->list()->rt_safe_earliest_event_unlocked(t, DBL_MAX, x, y);
130                 if (!ret) {
131                         DUMP(format("Iterator: CC %1% (size %2%) has no events past %3%\n")
132                                         % i->first.id() % i->second->list()->size() % t);
133                         continue;
134                 }
135
136                 assert(x >= 0);
137
138                 if (y < i->first.min() || y > i->first.max()) {
139                         cerr << "ERROR: Controller value " << y
140                                 << " out of range [" << i->first.min() << "," << i->first.max()
141                                 << "], event ignored" << endl;
142                         continue;
143                 }
144                 
145                 DUMP(format("Iterator: CC %1% added (%2%, %3%)\n") % i->first.id() % x % y);
146
147                 const ControlIterator new_iter(i->second->list(), x, y);
148                 _control_iters.push_back(new_iter);
149
150                 // Found a new earliest_control
151                 if (x < earliest_control.x) {
152                         earliest_control = new_iter;
153                         earliest_control_index = _control_iters.size() - 1;
154                         found = true;
155                 }
156         }
157
158         if (found) {
159                 _control_iter = _control_iters.begin() + earliest_control_index;
160         } else {
161                 _control_iter = _control_iters.end();
162         }
163         
164         // Now find the earliest event overall and point to it
165         Time earliest_t = t;
166
167         if (_note_iter != seq.notes().end()) {
168                 _type = NOTE_ON;
169                 earliest_t = (*_note_iter)->time();
170         }
171         
172         if (_sysex_iter != seq.sysexes().end() && (*_sysex_iter)->time() < earliest_t) {
173                 _type = SYSEX;
174                 earliest_t = (*_sysex_iter)->time();
175         }
176
177         if (_control_iter != _control_iters.end()
178                         && earliest_control.list && earliest_control.x >= t
179                         && earliest_control.x < earliest_t) {
180                 _type = CONTROL;
181                 earliest_t = earliest_control.x;
182         }
183         
184         switch (_type) {
185         case NOTE_ON:
186                 DUMP(format("Starting at note on event @ %1%\n") % earliest_t);
187                 _event = boost::shared_ptr< Event<Time> >(
188                                 new Event<Time>((*_note_iter)->on_event(), true));
189                 _active_notes.push(*_note_iter);
190                 break;
191         case SYSEX:
192                 DUMP(format("Starting at sysex event @ %1%\n") % earliest_t);
193                 _event = boost::shared_ptr< Event<Time> >(
194                                 new Event<Time>(*(*_sysex_iter), true));
195                 break;
196         case CONTROL:
197                 DUMP(format("Starting at control event @ %1%\n") % earliest_t);
198                 seq.control_to_midi_event(_event, earliest_control);
199                 break;
200         default:
201                 break;
202         }
203
204         if (_type == NIL || !_event || _event->size() == 0) {
205                 DUMP(format("Starting at end @ %1%\n") % t);
206                 _type   = NIL;
207                 _is_end = true;
208                 _locked = false;
209                 _seq->read_unlock();
210         } else {
211                 DUMP(format("New iterator = %1% : %2% @ %3%\n")
212                                 % (int)_event->event_type()
213                                 % (int)((MIDIEvent<Time>*)_event.get())->type()
214                                 % _event->time());
215                 assert(midi_event_is_valid(_event->buffer(), _event->size()));
216         }
217 }
218
219 template<typename Time>
220 Sequence<Time>::const_iterator::~const_iterator()
221 {
222         if (_locked) {
223                 _seq->read_unlock();
224         }
225 }
226
227 template<typename Time>
228 void
229 Sequence<Time>::const_iterator::invalidate()
230 {
231         while (!_active_notes.empty()) {
232                 _active_notes.pop();
233         }
234         _type = NIL;
235         _is_end = true;
236         if (_seq) {
237                 _note_iter = _seq->notes().end();
238                 _sysex_iter = _seq->sysexes().end();
239         }
240         _control_iter = _control_iters.end();
241         if (_locked) {
242                 _seq->read_unlock();
243                 _locked = false;
244         }
245 }
246
247 template<typename Time>
248 const typename Sequence<Time>::const_iterator&
249 Sequence<Time>::const_iterator::operator++()
250 {
251         if (_is_end) {
252                 throw std::logic_error("Attempt to iterate past end of Sequence");
253         }
254         
255         DUMP("Sequence::const_iterator++\n");
256         assert(_event && _event->buffer() && _event->size() > 0);
257         
258         const MIDIEvent<Time>& ev = *((MIDIEvent<Time>*)_event.get());
259
260         if (!(     ev.is_note()
261                         || ev.is_cc()
262                         || ev.is_pgm_change()
263                         || ev.is_pitch_bender()
264                         || ev.is_channel_pressure()
265                         || ev.is_sysex()) ) {
266                 cerr << "WARNING: Unknown event (type " << _type << "): " << hex
267                         << int(ev.buffer()[0]) << int(ev.buffer()[1]) << int(ev.buffer()[2]) << endl;
268         }
269         
270         double x   = 0.0;
271         double y   = 0.0;
272         bool   ret = false;
273         
274         // Increment past current event
275         switch (_type) {
276         case NOTE_ON:
277                 ++_note_iter;
278                 break;
279         case NOTE_OFF:
280                 break;
281         case CONTROL:
282                 // Increment current controller iterator
283                 ret = _control_iter->list->rt_safe_earliest_event_unlocked(
284                                 _control_iter->x, DBL_MAX, x, y, false);
285                 assert(!ret || x > _control_iter->x);
286                 if (ret) {
287                         _control_iter->x = x;
288                         _control_iter->y = y;
289                 } else {
290                         _control_iter->list.reset();
291                         _control_iter->x = DBL_MAX;
292                         _control_iter->y = DBL_MAX;
293                 }
294         
295                 // Find the controller with the next earliest event time
296                 _control_iter = _control_iters.begin();
297                 for (ControlIterators::iterator i = _control_iters.begin();
298                                 i != _control_iters.end(); ++i) {
299                         if (i->x < _control_iter->x) {
300                                 _control_iter = i;
301                         }
302                 }
303                 break;
304         case SYSEX:
305                 ++_sysex_iter;
306                 break;
307         default:
308                 assert(false);
309         }
310
311         // Now find the earliest event overall and point to it
312         _type = NIL;
313         Time earliest_t = std::numeric_limits<Time>::max();
314
315         // Next earliest note on
316         if (_note_iter != _seq->notes().end()) {
317                 _type = NOTE_ON;
318                 earliest_t = (*_note_iter)->time();
319         }
320
321         // Use the next note off iff it's earlier or the same time as the note on
322         if (!_seq->percussive() && (!_active_notes.empty())) {
323                 if (_type == NIL || _active_notes.top()->end_time() <= earliest_t) {
324                         _type = NOTE_OFF;
325                         earliest_t = _active_notes.top()->end_time();
326                 }
327         }
328
329         // Use the next earliest controller iff it's earlier than the note event
330         if (_control_iter != _control_iters.end() && _control_iter->x != DBL_MAX) {
331                 if (_type == NIL || _control_iter->x < earliest_t) {
332                         _type = CONTROL;
333                         earliest_t = _control_iter->x;
334                 }
335         }
336         
337         // Use the next earliest SysEx iff it's earlier than the controller
338         if (_sysex_iter != _seq->sysexes().end()) {
339                 if (_type == NIL || (*_sysex_iter)->time() < earliest_t) {
340                         _type = SYSEX;
341                         earliest_t = (*_sysex_iter)->time();
342                 }
343         }
344
345         // Set event to reflect new position
346         switch (_type) {
347         case NOTE_ON:
348                 DUMP("iterator = note on\n");
349                 *_event = (*_note_iter)->on_event();
350                 _active_notes.push(*_note_iter);
351                 break;
352         case NOTE_OFF:
353                 DUMP("iterator = note off\n");
354                 assert(!_active_notes.empty());
355                 *_event = _active_notes.top()->off_event();
356                 _active_notes.pop();
357                 break;
358         case CONTROL:
359                 DUMP("iterator = control\n");
360                 _seq->control_to_midi_event(_event, *_control_iter);
361                 break;
362         case SYSEX:
363                 DUMP("iterator = sysex\n");
364                 *_event = *(*_sysex_iter);
365                 break;
366         default:
367                 DUMP("iterator = end\n");
368                 _is_end = true;
369         }
370
371         assert(_is_end || (_event->size() > 0 && _event->buffer() && _event->buffer()[0] != '\0'));
372
373         return *this;
374 }
375
376 template<typename Time>
377 bool
378 Sequence<Time>::const_iterator::operator==(const const_iterator& other) const
379 {
380         if (_seq != other._seq) {
381                 return false;
382         } else if (_is_end || other._is_end) {
383                 return (_is_end == other._is_end);
384         } else if (_type != other._type) {
385                 return false;
386         } else {
387                 return (_event == other._event);
388         }
389 }
390
391 template<typename Time>
392 typename Sequence<Time>::const_iterator&
393 Sequence<Time>::const_iterator::operator=(const const_iterator& other)
394 {
395         if (_seq != other._seq) {
396                 if (_locked) {
397                         _seq->read_unlock();
398                 }
399                 if (other._locked) {
400                    other._seq->read_lock();
401                 }
402         } else if (!_locked && other._locked) {
403                 _seq->read_lock();
404         }
405
406         _seq           = other._seq;
407         _event         = other._event;
408         _active_notes  = other._active_notes;
409         _type          = other._type;
410         _is_end        = other._is_end;
411         _locked        = other._locked;
412         _note_iter     = other._note_iter;
413         _sysex_iter    = other._sysex_iter;
414         _control_iters = other._control_iters;
415         
416         if (other._control_iter == other._control_iters.end()) {
417                 _control_iter = _control_iters.end();
418         } else {
419                 const size_t index = other._control_iter - other._control_iters.begin();
420                 _control_iter  = _control_iters.begin() + index;
421         }
422
423         return *this;
424 }
425
426 // Sequence
427
428 template<typename Time>
429 Sequence<Time>::Sequence(const TypeMap& type_map, size_t size)
430         : _edited(false)
431         , _type_map(type_map)
432         , _notes(size)
433         , _writing(false)
434         , _end_iter(*this, DBL_MAX)
435         , _percussive(false)
436         , _lowest_note(127)
437         , _highest_note(0)
438 {
439         DUMP(format("Sequence (size %1%) constructed: %2%\n") % size % this);
440         assert(_end_iter._is_end);
441         assert( ! _end_iter._locked);
442 }
443
444 /** Write the controller event pointed to by \a iter to \a ev.
445  * The buffer of \a ev will be allocated or resized as necessary.
446  * The event_type of \a ev should be set to the expected output type.
447  * \return true on success
448  */
449 template<typename Time>
450 bool
451 Sequence<Time>::control_to_midi_event(
452                 boost::shared_ptr< Event<Time> >& ev,
453                 const ControlIterator&            iter) const
454 {
455         assert(iter.list.get());
456         const uint32_t event_type = iter.list->parameter().type();
457         
458         // initialize the event pointer with a new event, if necessary
459         if (!ev) {
460                 ev = boost::shared_ptr< Event<Time> >(new Event<Time>(event_type, 0, 3, NULL, true));
461         }
462         
463         uint8_t midi_type = _type_map.parameter_midi_type(iter.list->parameter());
464         ev->set_event_type(_type_map.midi_event_type(midi_type));
465         switch (midi_type) {
466         case MIDI_CMD_CONTROL:
467                 assert(iter.list.get());
468                 assert(iter.list->parameter().channel() < 16);
469                 assert(iter.list->parameter().id() <= INT8_MAX);
470                 assert(iter.y <= INT8_MAX);
471                 
472                 ev->time() = iter.x;
473                 ev->realloc(3);
474                 ev->buffer()[0] = MIDI_CMD_CONTROL + iter.list->parameter().channel();
475                 ev->buffer()[1] = (uint8_t)iter.list->parameter().id();
476                 ev->buffer()[2] = (uint8_t)iter.y;
477                 break;
478
479         case MIDI_CMD_PGM_CHANGE:
480                 assert(iter.list.get());
481                 assert(iter.list->parameter().channel() < 16);
482                 assert(iter.y <= INT8_MAX);
483                 
484                 ev->time() = iter.x;
485                 ev->realloc(2);
486                 ev->buffer()[0] = MIDI_CMD_PGM_CHANGE + iter.list->parameter().channel();
487                 ev->buffer()[1] = (uint8_t)iter.y;
488                 break;
489
490         case MIDI_CMD_BENDER:
491                 assert(iter.list.get());
492                 assert(iter.list->parameter().channel() < 16);
493                 assert(iter.y < (1<<14));
494                 
495                 ev->time() = iter.x;
496                 ev->realloc(3);
497                 ev->buffer()[0] = MIDI_CMD_BENDER + iter.list->parameter().channel();
498                 ev->buffer()[1] = uint16_t(iter.y) & 0x7F; // LSB
499                 ev->buffer()[2] = (uint16_t(iter.y) >> 7) & 0x7F; // MSB
500                 break;
501
502         case MIDI_CMD_CHANNEL_PRESSURE:
503                 assert(iter.list.get());
504                 assert(iter.list->parameter().channel() < 16);
505                 assert(iter.y <= INT8_MAX);
506
507                 ev->time() = iter.x;
508                 ev->realloc(2);
509                 ev->buffer()[0] = MIDI_CMD_CHANNEL_PRESSURE + iter.list->parameter().channel();
510                 ev->buffer()[1] = (uint8_t)iter.y;
511                 break;
512
513         default:
514                 return false;
515         }
516
517         return true;
518 }
519
520 /** Clear all events from the model.
521  */
522 template<typename Time>
523 void
524 Sequence<Time>::clear()
525 {
526         _lock.writer_lock();
527         _notes.clear();
528         for (Controls::iterator li = _controls.begin(); li != _controls.end(); ++li)
529                 li->second->list()->clear();
530         _lock.writer_unlock();
531 }
532
533 /** Begin a write of events to the model.
534  *
535  * If \a mode is Sustained, complete notes with length are constructed as note
536  * on/off events are received.  Otherwise (Percussive), only note on events are
537  * stored; note off events are discarded entirely and all contained notes will
538  * have length 0.
539  */
540 template<typename Time>
541 void
542 Sequence<Time>::start_write()
543 {
544         DUMP(format("%1% : start_write (percussive = %2%)\n") % this % _percussive);
545         write_lock();
546         _writing = true;
547         for (int i = 0; i < 16; ++i) {
548                 _write_notes[i].clear();
549         }
550         _dirty_controls.clear();
551         write_unlock();
552 }
553
554 /** Finish a write of events to the model.
555  *
556  * If \a delete_stuck is true and the current mode is Sustained, note on events
557  * that were never resolved with a corresonding note off will be deleted.
558  * Otherwise they will remain as notes with length 0.
559  */
560 template<typename Time>
561 void
562 Sequence<Time>::end_write(bool delete_stuck)
563 {
564         write_lock();
565         assert(_writing);
566
567         DUMP(format("%1% : end_write (%2% notes)\n") % this % _notes.size());
568
569         if (!_percussive && delete_stuck) {
570                 for (typename Notes::iterator n = _notes.begin(); n != _notes.end() ;) {
571                         if ((*n)->length() == 0) {
572                                 cerr << "WARNING: Stuck note lost: " << (*n)->note() << endl;
573                                 n = _notes.erase(n);
574                                 // we have to break here because erase invalidates the iterator
575                                 break;
576                         } else {
577                                 ++n;
578                         }
579                 }
580         }
581
582         for (int i = 0; i < 16; ++i) {
583                 if (!_write_notes[i].empty()) {
584                         cerr << "WARNING: Sequence<Time>::end_write: Channel " << i << " has "
585                                         << _write_notes[i].size() << " stuck notes" << endl;
586                 }
587                 _write_notes[i].clear();
588         }
589
590         for (ControlLists::const_iterator i = _dirty_controls.begin(); i != _dirty_controls.end(); ++i) {
591                 (*i)->mark_dirty();
592         }
593         
594         _writing = false;
595         write_unlock();
596 }
597
598 /** Append \a ev to model.  NOT realtime safe.
599  *
600  * Timestamps of events in \a buf are expected to be relative to
601  * the start of this model (t=0) and MUST be monotonically increasing
602  * and MUST be >= the latest event currently in the model.
603  */
604 template<typename Time>
605 void
606 Sequence<Time>::append(const Event<Time>& event)
607 {
608         write_lock();
609         _edited = true;
610         
611         const MIDIEvent<Time>& ev = (const MIDIEvent<Time>&)event;
612
613         assert(_notes.empty() || ev.time() >= _notes.back()->time());
614         assert(_writing);
615
616         if (!midi_event_is_valid(ev.buffer(), ev.size())) {
617                 cerr << "WARNING: Sequence ignoring illegal MIDI event" << endl;
618                 write_unlock();
619                 return;
620         }
621
622         if (ev.is_note_on()) {
623                 append_note_on_unlocked(ev.channel(), ev.time(), ev.note(), ev.velocity());
624         } else if (ev.is_note_off()) {
625                 append_note_off_unlocked(ev.channel(), ev.time(), ev.note());
626         } else if (ev.is_sysex()) {
627                 append_sysex_unlocked(ev);
628         } else if (!_type_map.type_is_midi(ev.event_type())) {
629                 printf("WARNING: Sequence: Unknown event type %X: ", ev.event_type());
630                 for (size_t i=0; i < ev.size(); ++i) {
631                         printf("%X ", ev.buffer()[i]);
632                 }
633                 printf("\n");
634         } else if (ev.is_cc()) {
635                 append_control_unlocked(
636                                 Evoral::MIDI::ContinuousController(ev.event_type(), ev.channel(), ev.cc_number()),
637                                 ev.time(), ev.cc_value());
638         } else if (ev.is_pgm_change()) {
639                 append_control_unlocked(
640                                 Evoral::MIDI::ProgramChange(ev.event_type(), ev.channel()),
641                                 ev.time(), ev.pgm_number());
642         } else if (ev.is_pitch_bender()) {
643                 append_control_unlocked(
644                                 Evoral::MIDI::PitchBender(ev.event_type(), ev.channel()),
645                                 ev.time(), double(  (0x7F & ev.pitch_bender_msb()) << 7
646                                         | (0x7F & ev.pitch_bender_lsb()) ));
647         } else if (ev.is_channel_pressure()) {
648                 append_control_unlocked(
649                                 Evoral::MIDI::ChannelPressure(ev.event_type(), ev.channel()),
650                                 ev.time(), ev.channel_pressure());
651         } else {
652                 printf("WARNING: Sequence: Unknown MIDI event type %X\n", ev.type());
653         }
654
655         write_unlock();
656 }
657
658 template<typename Time>
659 void
660 Sequence<Time>::append_note_on_unlocked(uint8_t chan, Time time, uint8_t note_num, uint8_t velocity)
661 {
662         DUMP(format("%1% c=%2% note %3% on @ %4% v=%5%\n")
663                         % this % (int)chan % (int)note_num % time % (int)velocity);
664         assert(note_num <= 127);
665         assert(chan < 16);
666         assert(_writing);
667         _edited = true;
668
669         if (velocity == 0) {
670                 append_note_off_unlocked(chan, time, note_num);
671                 return;
672         }
673
674         if (note_num < _lowest_note)
675                 _lowest_note = note_num;
676         if (note_num > _highest_note)
677                 _highest_note = note_num;
678
679         boost::shared_ptr< Note<Time> > new_note(new Note<Time>(chan, time, 0, note_num, velocity));
680         _notes.push_back(new_note);
681         if (!_percussive) {
682                 DUMP(format("Sustained: Appending active note on %1% channel %2%\n")
683                                 % (unsigned)(uint8_t)note_num % chan);
684                 _write_notes[chan].push_back(_notes.size() - 1);
685         } else {
686                 DUMP("Percussive: NOT appending active note on\n");
687          }
688 }
689
690 template<typename Time>
691 void
692 Sequence<Time>::append_note_off_unlocked(uint8_t chan, Time time, uint8_t note_num)
693 {
694         DUMP(format("%1% c=%2% note %3% off @ %4%\n")
695                         % this % (int)chan % (int)note_num % time);
696         assert(note_num <= 127);
697         assert(chan < 16);
698         assert(_writing);
699         _edited = true;
700
701         if (_percussive) {
702                 DUMP("Sequence Ignoring note off (percussive mode)\n");
703                 return;
704         }
705
706         /* FIXME: make _write_notes fixed size (127 noted) for speed */
707
708         /* FIXME: note off velocity for that one guy out there who actually has
709          * keys that send it */
710
711         bool resolved = false;
712
713         for (WriteNotes::iterator n = _write_notes[chan].begin(); n
714                         != _write_notes[chan].end(); ++n) {
715                 Note<Time>& note = *_notes[*n].get();
716                 if (note.note() == note_num) {
717                         assert(time >= note.time());
718                         note.set_length(time - note.time());
719                         _write_notes[chan].erase(n);
720                         DUMP(format("resolved note, length: %1%\n") % note.length());
721                         resolved = true;
722                         break;
723                 }
724         }
725
726         if (!resolved) {
727                 cerr << this << " spurious note off chan " << (int)chan
728                                 << ", note " << (int)note_num << " @ " << time << endl;
729         }
730 }
731
732 template<typename Time>
733 void
734 Sequence<Time>::append_control_unlocked(const Parameter& param, Time time, double value)
735 {
736         DUMP(format("%1% %2% @ %3%\t=\t%4% # controls: %5%\n")
737                         % this % _type_map.to_symbol(param) % time % value % _controls.size());
738         boost::shared_ptr<Control> c = control(param, true);
739         c->list()->rt_add(time, value);
740 }
741
742 template<typename Time>
743 void
744 Sequence<Time>::append_sysex_unlocked(const MIDIEvent<Time>& ev)
745 {
746         #ifdef DEBUG_SEQUENCE
747         cerr << this << " SysEx @ " << ev.time() << " \t= \t [ " << hex;
748         for (size_t i=0; i < ev.size(); ++i) {
749                 cerr << int(ev.buffer()[i]) << " ";
750         } cerr << "]" << endl;
751         #endif
752
753         boost::shared_ptr<MIDIEvent<Time> > event(new MIDIEvent<Time>(ev, true));
754         _sysexes.push_back(event);
755 }
756
757 template<typename Time>
758 void
759 Sequence<Time>::add_note_unlocked(const boost::shared_ptr< Note<Time> > note)
760 {
761         DUMP(format("%1% add note %2% @ %3%\n") % this % (int)note->note() % note->time());
762         _edited = true;
763         typename Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note,
764                         note_time_comparator);
765         _notes.insert(i, note);
766 }
767
768 template<typename Time>
769 void
770 Sequence<Time>::remove_note_unlocked(const boost::shared_ptr< const Note<Time> > note)
771 {
772         _edited = true;
773         DUMP(format("%1% remove note %2% @ %3%\n") % this % (int)note->note() % note->time());
774         for (typename Notes::iterator n = _notes.begin(); n != _notes.end(); ++n) {
775                 if (*(*n) == *note) {
776                         _notes.erase(n);
777                         break;
778                 }
779         }
780 }
781
782 template class Sequence<double>;
783
784 } // namespace Evoral
785