summaryrefslogtreecommitdiff
path: root/libs/evoral/src/Sequence.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libs/evoral/src/Sequence.cpp')
-rw-r--r--libs/evoral/src/Sequence.cpp110
1 files changed, 67 insertions, 43 deletions
diff --git a/libs/evoral/src/Sequence.cpp b/libs/evoral/src/Sequence.cpp
index 7781ea8907..2fc7bfb39a 100644
--- a/libs/evoral/src/Sequence.cpp
+++ b/libs/evoral/src/Sequence.cpp
@@ -35,21 +35,25 @@ using namespace std;
namespace Evoral {
-void Sequence::write_lock() {
+template<typename T>
+void Sequence<T>::write_lock() {
_lock.writer_lock();
_control_lock.lock();
}
-void Sequence::write_unlock() {
+template<typename T>
+void Sequence<T>::write_unlock() {
_lock.writer_unlock();
_control_lock.unlock();
}
-void Sequence::read_lock() const {
+template<typename T>
+void Sequence<T>::read_lock() const {
_lock.reader_lock();
}
-void Sequence::read_unlock() const {
+template<typename T>
+void Sequence<T>::read_unlock() const {
_lock.reader_unlock();
}
@@ -64,7 +68,8 @@ static ostream& errorout = cerr;
// Read iterator (const_iterator)
-Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t)
+template<typename T>
+Sequence<T>::const_iterator::const_iterator(const Sequence<T>& seq, T t)
: _seq(&seq)
, _is_end( (t == DBL_MAX) || seq.empty() )
, _locked( !_is_end )
@@ -79,7 +84,8 @@ Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t)
// find first note which begins after t
_note_iter = seq.notes().end();
- for (Sequence::Notes::const_iterator i = seq.notes().begin(); i != seq.notes().end(); ++i) {
+ for (typename Sequence<T>::Notes::const_iterator i = seq.notes().begin();
+ i != seq.notes().end(); ++i) {
if ((*i)->time() >= t) {
_note_iter = i;
break;
@@ -130,7 +136,7 @@ Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t)
&& (!earliest_control.list
|| (*_note_iter)->on_event().time() < earliest_control.x)) {
debugout << "Reading note on event @ " << (*_note_iter)->on_event().time() << endl;
- _event = boost::shared_ptr<Event>(new Event((*_note_iter)->on_event(), true));
+ _event = boost::shared_ptr< Event<T> >(new Event<T>((*_note_iter)->on_event(), true));
_active_notes.push(*_note_iter);
++_note_iter;
_control_iter = _control_iters.end();
@@ -152,22 +158,24 @@ Sequence::const_iterator::const_iterator(const Sequence& seq, EventTime t)
}
} else {
debugout << "New Iterator = " << _event->event_type();
- debugout << " : " << hex << (int)((MIDIEvent*)_event.get())->type();
+ debugout << " : " << hex << (int)((MIDIEvent<T>*)_event.get())->type();
debugout << " @ " << _event->time() << endl;
}
//assert(_is_end || (_event->buffer() && _event->buffer()[0] != '\0'));
}
-Sequence::const_iterator::~const_iterator()
+template<typename T>
+Sequence<T>::const_iterator::~const_iterator()
{
if (_locked) {
_seq->read_unlock();
}
}
-const
-Sequence::const_iterator& Sequence::const_iterator::operator++()
+template<typename T>
+const typename Sequence<T>::const_iterator&
+Sequence<T>::const_iterator::operator++()
{
if (_is_end) {
throw std::logic_error("Attempt to iterate past end of Sequence");
@@ -176,7 +184,7 @@ Sequence::const_iterator& Sequence::const_iterator::operator++()
debugout << "Iterator ++" << endl;
assert(_event->buffer() && _event->size() > 0);
- const MIDIEvent& ev = *((MIDIEvent*)_event.get());
+ const MIDIEvent<T>& ev = *((MIDIEvent<T>*)_event.get());
//debugout << "const_iterator::operator++: " << _event->to_string() << endl;
@@ -214,10 +222,10 @@ Sequence::const_iterator& Sequence::const_iterator::operator++()
}
}
- enum Type {NIL, NOTE_ON, NOTE_OFF, CONTROL};
+ enum Type { NIL, NOTE_ON, NOTE_OFF, CONTROL };
Type type = NIL;
- EventTime t = 0;
+ T t = 0;
// Next earliest note on
if (_note_iter != _seq->notes().end()) {
@@ -262,8 +270,9 @@ Sequence::const_iterator& Sequence::const_iterator::operator++()
return *this;
}
+template<typename T>
bool
-Sequence::const_iterator::operator==(const const_iterator& other) const
+Sequence<T>::const_iterator::operator==(const const_iterator& other) const
{
if (_is_end || other._is_end) {
return (_is_end == other._is_end);
@@ -272,8 +281,9 @@ Sequence::const_iterator::operator==(const const_iterator& other) const
}
}
-Sequence::const_iterator&
-Sequence::const_iterator::operator=(const const_iterator& other)
+template<typename T>
+typename Sequence<T>::const_iterator&
+Sequence<T>::const_iterator::operator=(const const_iterator& other)
{
if (_locked && _seq != other._seq) {
_seq->read_unlock();
@@ -292,7 +302,7 @@ Sequence::const_iterator::operator=(const const_iterator& other)
if (_event) {
*_event = *other._event.get();
} else {
- _event = boost::shared_ptr<Event>(new Event(*other._event, true));
+ _event = boost::shared_ptr< Event<T> >(new Event<T>(*other._event, true));
}
} else {
if (_event) {
@@ -305,7 +315,8 @@ Sequence::const_iterator::operator=(const const_iterator& other)
// Sequence
-Sequence::Sequence(const TypeMap& type_map, size_t size)
+template<typename T>
+Sequence<T>::Sequence(const TypeMap& type_map, size_t size)
: _read_iter(*this, DBL_MAX)
, _edited(false)
, _type_map(type_map)
@@ -326,8 +337,9 @@ Sequence::Sequence(const TypeMap& type_map, size_t size)
* adding \a offset to each event's timestamp.
* \return number of events written to \a dst
*/
+template<typename T>
size_t
-Sequence::read(EventSink& dst, timestamp_t start, timedur_t nframes, timestamp_t offset) const
+Sequence<T>::read(EventSink<T>& dst, timestamp_t start, timedur_t nframes, timestamp_t offset) const
{
debugout << this << " read @ " << start << " * " << nframes << " + " << offset << endl;
debugout << this << " # notes: " << n_notes() << endl;
@@ -370,13 +382,14 @@ Sequence::read(EventSink& dst, timestamp_t start, timedur_t nframes, timestamp_t
* The event_type of \a ev should be set to the expected output type.
* \return true on success
*/
+template<typename T>
bool
-Sequence::control_to_midi_event(boost::shared_ptr<Event>& ev, const ControlIterator& iter) const
+Sequence<T>::control_to_midi_event(boost::shared_ptr< Event<T> >& ev, const ControlIterator& iter) const
{
assert(iter.list.get());
const uint32_t event_type = iter.list->parameter().type();
if (!ev) {
- ev = boost::shared_ptr<Event>(new Event(event_type, 0, 3, NULL, true));
+ ev = boost::shared_ptr< Event<T> >(new Event<T>(event_type, 0, 3, NULL, true));
}
uint8_t midi_type = _type_map.parameter_midi_type(iter.list->parameter());
@@ -438,8 +451,9 @@ Sequence::control_to_midi_event(boost::shared_ptr<Event>& ev, const ControlItera
/** Clear all events from the model.
*/
+template<typename T>
void
-Sequence::clear()
+Sequence<T>::clear()
{
_lock.writer_lock();
_notes.clear();
@@ -457,8 +471,9 @@ Sequence::clear()
* stored; note off events are discarded entirely and all contained notes will
* have length 0.
*/
+template<typename T>
void
-Sequence::start_write()
+Sequence<T>::start_write()
{
debugout << this << " START WRITE, PERCUSSIVE = " << _percussive << endl;
write_lock();
@@ -476,8 +491,9 @@ Sequence::start_write()
* that were never resolved with a corresonding note off will be deleted.
* Otherwise they will remain as notes with length 0.
*/
+template<typename T>
void
-Sequence::end_write(bool delete_stuck)
+Sequence<T>::end_write(bool delete_stuck)
{
write_lock();
assert(_writing);
@@ -485,7 +501,7 @@ Sequence::end_write(bool delete_stuck)
debugout << this << " END WRITE: " << _notes.size() << " NOTES\n";
if (!_percussive && delete_stuck) {
- for (Notes::iterator n = _notes.begin(); n != _notes.end() ;) {
+ for (typename Notes::iterator n = _notes.begin(); n != _notes.end() ;) {
if ((*n)->length() == 0) {
errorout << "WARNING: Stuck note lost: " << (*n)->note() << endl;
n = _notes.erase(n);
@@ -499,7 +515,7 @@ Sequence::end_write(bool delete_stuck)
for (int i = 0; i < 16; ++i) {
if (!_write_notes[i].empty()) {
- errorout << "WARNING: Sequence::end_write: Channel " << i << " has "
+ errorout << "WARNING: Sequence<T>::end_write: Channel " << i << " has "
<< _write_notes[i].size() << " stuck notes" << endl;
}
_write_notes[i].clear();
@@ -519,13 +535,14 @@ Sequence::end_write(bool delete_stuck)
* the start of this model (t=0) and MUST be monotonically increasing
* and MUST be >= the latest event currently in the model.
*/
+template<typename T>
void
-Sequence::append(const Event& event)
+Sequence<T>::append(const Event<T>& event)
{
write_lock();
_edited = true;
- const MIDIEvent& ev = (const MIDIEvent&)event;
+ const MIDIEvent<T>& ev = (const MIDIEvent<T>&)event;
assert(_notes.empty() || ev.time() >= _notes.back()->time());
assert(_writing);
@@ -565,8 +582,9 @@ Sequence::append(const Event& event)
write_unlock();
}
+template<typename T>
void
-Sequence::append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note_num, uint8_t velocity)
+Sequence<T>::append_note_on_unlocked(uint8_t chan, T time, uint8_t note_num, uint8_t velocity)
{
debugout << this << " c" << (int)chan << " note " << (int)note_num << " off @ " << time << endl;
assert(note_num <= 127);
@@ -579,7 +597,7 @@ Sequence::append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note_num
if (note_num > _highest_note)
_highest_note = note_num;
- boost::shared_ptr<Note> new_note(new Note(chan, time, 0, note_num, velocity));
+ boost::shared_ptr< Note<T> > new_note(new Note<T>(chan, time, 0, note_num, velocity));
_notes.push_back(new_note);
if (!_percussive) {
debugout << "Sustained: Appending active note on " << (unsigned)(uint8_t)note_num << endl;
@@ -589,8 +607,9 @@ Sequence::append_note_on_unlocked(uint8_t chan, EventTime time, uint8_t note_num
}
}
+template<typename T>
void
-Sequence::append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note_num)
+Sequence<T>::append_note_off_unlocked(uint8_t chan, T time, uint8_t note_num)
{
debugout << this << " c" << (int)chan << " note " << (int)note_num << " off @ " << time << endl;
assert(note_num <= 127);
@@ -612,7 +631,7 @@ Sequence::append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note_nu
for (WriteNotes::iterator n = _write_notes[chan].begin(); n
!= _write_notes[chan].end(); ++n) {
- Note& note = *_notes[*n].get();
+ Note<T>& note = *_notes[*n].get();
if (note.note() == note_num) {
assert(time >= note.time());
note.set_length(time - note.time());
@@ -629,8 +648,9 @@ Sequence::append_note_off_unlocked(uint8_t chan, EventTime time, uint8_t note_nu
}
}
+template<typename T>
void
-Sequence::append_control_unlocked(const Parameter& param, EventTime time, double value)
+Sequence<T>::append_control_unlocked(const Parameter& param, T time, double value)
{
debugout << this << " " << _type_map.to_symbol(param) << " @ " << time << " \t= \t" << value
<< " # controls: " << _controls.size() << endl;
@@ -638,25 +658,26 @@ Sequence::append_control_unlocked(const Parameter& param, EventTime time, double
c->list()->rt_add(time, value);
}
-
+template<typename T>
void
-Sequence::add_note_unlocked(const boost::shared_ptr<Note> note)
+Sequence<T>::add_note_unlocked(const boost::shared_ptr< Note<T> > note)
{
debugout << this << " add note " << (int)note->note() << " @ " << note->time() << endl;
_edited = true;
- Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note,
+ typename Notes::iterator i = upper_bound(_notes.begin(), _notes.end(), note,
note_time_comparator);
_notes.insert(i, note);
}
+template<typename T>
void
-Sequence::remove_note_unlocked(const boost::shared_ptr<const Note> note)
+Sequence<T>::remove_note_unlocked(const boost::shared_ptr< const Note<T> > note)
{
_edited = true;
debugout << this << " remove note " << (int)note->note() << " @ " << note->time() << endl;
- for (Notes::iterator n = _notes.begin(); n != _notes.end(); ++n) {
- Note& _n = *(*n);
- const Note& _note = *note;
+ for (typename Notes::iterator n = _notes.begin(); n != _notes.end(); ++n) {
+ Note<T>& _n = *(*n);
+ const Note<T>& _note = *note;
// TODO: There is still the issue, that after restarting ardour
// persisted undo does not work, because of rounding errors in the
// event times after saving/restoring to/from MIDI files
@@ -675,10 +696,11 @@ Sequence::remove_note_unlocked(const boost::shared_ptr<const Note> note)
/** Slow! for debugging only. */
#ifndef NDEBUG
+template<typename T>
bool
-Sequence::is_sorted() const {
+Sequence<T>::is_sorted() const {
bool t = 0;
- for (Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n)
+ for (typename Notes::const_iterator n = _notes.begin(); n != _notes.end(); ++n)
if ((*n)->time() < t)
return false;
else
@@ -688,5 +710,7 @@ Sequence::is_sorted() const {
}
#endif
+template class Sequence<double>;
+
} // namespace Evoral