You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
282 lines
7.0 KiB
282 lines
7.0 KiB
/*
|
|
Rosegarden
|
|
A sequencer and musical notation editor.
|
|
|
|
This program is Copyright 2000-2008
|
|
Guillaume Laurent <glaurent@telegraph-road.org>,
|
|
Chris Cannam <cannam@all-day-breakfast.com>,
|
|
Richard Bown <bownie@bownie.com>
|
|
|
|
This file is Copyright 2002
|
|
Randall Farmer <rfarme@simons-rock.edu>
|
|
with additional work by Chris Cannam.
|
|
|
|
The moral right of the authors to claim authorship of this work
|
|
has been asserted.
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version. See the file
|
|
COPYING included with this distribution for more information.
|
|
*/
|
|
|
|
// !!!TODO: handle timeslices
|
|
|
|
#include <list>
|
|
#include <utility>
|
|
|
|
#include "CompositionTimeSliceAdapter.h"
|
|
#include "Segment.h"
|
|
#include "Composition.h"
|
|
#include "Selection.h"
|
|
|
|
namespace Rosegarden {
|
|
|
|
using std::list;
|
|
using std::pair;
|
|
|
|
CompositionTimeSliceAdapter::CompositionTimeSliceAdapter(Composition *c,
|
|
timeT begin,
|
|
timeT end) :
|
|
m_composition(c),
|
|
m_begin(begin),
|
|
m_end(end)
|
|
{
|
|
if (begin == end) {
|
|
m_begin = 0;
|
|
m_end = c->getDuration();
|
|
}
|
|
|
|
for (Composition::iterator ci = m_composition->begin();
|
|
ci != m_composition->end(); ++ci) {
|
|
m_segmentList.push_back(*ci);
|
|
}
|
|
}
|
|
|
|
CompositionTimeSliceAdapter::CompositionTimeSliceAdapter(Composition *c,
|
|
SegmentSelection* s,
|
|
timeT begin,
|
|
timeT end) :
|
|
m_composition(c),
|
|
m_begin(begin),
|
|
m_end(end)
|
|
{
|
|
if (begin == end) {
|
|
m_begin = 0;
|
|
m_end = c->getDuration();
|
|
}
|
|
|
|
for (Composition::iterator ci = m_composition->begin();
|
|
ci != m_composition->end(); ++ci) {
|
|
if (!s || s->find(*ci) != s->end()) {
|
|
m_segmentList.push_back(*ci);
|
|
}
|
|
}
|
|
}
|
|
|
|
CompositionTimeSliceAdapter::CompositionTimeSliceAdapter(Composition *c,
|
|
const TrackSet &trackIDs,
|
|
timeT begin,
|
|
timeT end) :
|
|
m_composition(c),
|
|
m_begin(begin),
|
|
m_end(end)
|
|
{
|
|
if (begin == end) {
|
|
m_begin = 0;
|
|
m_end = c->getDuration();
|
|
}
|
|
|
|
for (Composition::iterator ci = m_composition->begin();
|
|
ci != m_composition->end(); ++ci) {
|
|
if (trackIDs.find((*ci)->getTrack()) != trackIDs.end()) {
|
|
m_segmentList.push_back(*ci);
|
|
}
|
|
}
|
|
}
|
|
|
|
CompositionTimeSliceAdapter::iterator
|
|
CompositionTimeSliceAdapter::begin() const
|
|
{
|
|
if (m_beginItr.m_a == 0) {
|
|
m_beginItr = iterator(this);
|
|
fill(m_beginItr, false);
|
|
}
|
|
return m_beginItr;
|
|
}
|
|
|
|
CompositionTimeSliceAdapter::iterator
|
|
CompositionTimeSliceAdapter::end() const
|
|
{
|
|
return iterator(this);
|
|
}
|
|
|
|
void
|
|
CompositionTimeSliceAdapter::fill(iterator &i, bool atEnd) const
|
|
{
|
|
// The segment iterators should all point to events starting at or
|
|
// after m_begin (if atEnd false) or at or before m_end (if atEnd true).
|
|
|
|
for (unsigned int k = 0; k < m_segmentList.size(); ++k) {
|
|
Segment::iterator j = m_segmentList[k]->findTime(atEnd ? m_end : m_begin);
|
|
i.m_segmentItrList.push_back(j);
|
|
}
|
|
|
|
// fill m_curEvent & m_curTrack
|
|
if (!atEnd) ++i;
|
|
}
|
|
|
|
CompositionTimeSliceAdapter::iterator&
|
|
CompositionTimeSliceAdapter::iterator::operator=(const iterator &i)
|
|
{
|
|
if (&i == this) return *this;
|
|
m_segmentItrList.clear();
|
|
|
|
for (segmentitrlist::const_iterator j = i.m_segmentItrList.begin();
|
|
j != i.m_segmentItrList.end(); ++j) {
|
|
m_segmentItrList.push_back(Segment::iterator(*j));
|
|
}
|
|
|
|
m_a = i.m_a;
|
|
m_curTrack = i.m_curTrack;
|
|
m_curEvent = i.m_curEvent;
|
|
m_needFill = i.m_needFill;
|
|
return *this;
|
|
}
|
|
|
|
CompositionTimeSliceAdapter::iterator::iterator(const iterator &i) :
|
|
m_a(i.m_a),
|
|
m_curEvent(i.m_curEvent),
|
|
m_curTrack(i.m_curTrack),
|
|
m_needFill(i.m_needFill)
|
|
{
|
|
for (segmentitrlist::const_iterator j = i.m_segmentItrList.begin();
|
|
j != i.m_segmentItrList.end(); ++j) {
|
|
m_segmentItrList.push_back(Segment::iterator(*j));
|
|
}
|
|
}
|
|
|
|
CompositionTimeSliceAdapter::iterator&
|
|
CompositionTimeSliceAdapter::iterator::operator++()
|
|
{
|
|
assert(m_a != 0);
|
|
|
|
// needFill is only set true for iterators created at end()
|
|
if (m_needFill) {
|
|
m_a->fill(*this, true);
|
|
m_needFill = false;
|
|
}
|
|
|
|
Event *e = 0;
|
|
unsigned int pos = 0;
|
|
|
|
for (unsigned int i = 0; i < m_a->m_segmentList.size(); ++i) {
|
|
|
|
if (!m_a->m_segmentList[i]->isBeforeEndMarker(m_segmentItrList[i])) continue;
|
|
|
|
if (!e || strictLessThan(*m_segmentItrList[i], e)) {
|
|
e = *m_segmentItrList[i];
|
|
m_curTrack = m_a->m_segmentList[i]->getTrack();
|
|
pos = i;
|
|
}
|
|
}
|
|
|
|
// Check whether we're past the end time, if there is one
|
|
if (!e || e->getAbsoluteTime() >= m_a->m_end) {
|
|
m_curEvent = 0;
|
|
m_curTrack = -1;
|
|
return *this;
|
|
}
|
|
|
|
// e is now an Event* less than or equal to any that the iterator
|
|
// hasn't already passed over
|
|
m_curEvent = e;
|
|
|
|
// m_segmentItrList[pos] is a segment::iterator that points to e
|
|
++m_segmentItrList[pos];
|
|
|
|
return *this;
|
|
}
|
|
|
|
CompositionTimeSliceAdapter::iterator&
|
|
CompositionTimeSliceAdapter::iterator::operator--()
|
|
{
|
|
assert(m_a != 0);
|
|
|
|
// needFill is only set true for iterators created at end()
|
|
if (m_needFill) {
|
|
m_a->fill(*this, true);
|
|
m_needFill = false;
|
|
}
|
|
|
|
Event *e = 0;
|
|
int pos = -1;
|
|
|
|
// Decrement is more subtle than increment. We have to scan the
|
|
// iterators available, and decrement the one that points to
|
|
// m_curEvent. Then to fill m_curEvent we need to find the next
|
|
// greatest event back that is not itself m_curEvent.
|
|
|
|
for (unsigned int i = 0; i < m_a->m_segmentList.size(); ++i) {
|
|
|
|
if (m_segmentItrList[i] == m_a->m_segmentList[i]->begin()) continue;
|
|
|
|
Segment::iterator si(m_segmentItrList[i]);
|
|
--si;
|
|
|
|
if (*si == m_curEvent) {
|
|
pos = i;
|
|
} else if (!e || !strictLessThan(*si, e)) {
|
|
e = *si;
|
|
m_curTrack = m_a->m_segmentList[i]->getTrack();
|
|
}
|
|
}
|
|
|
|
if (e) m_curEvent = e;
|
|
if (pos >= 0) {
|
|
--m_segmentItrList[pos];
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
bool
|
|
CompositionTimeSliceAdapter::iterator::operator==(const iterator& other) const {
|
|
return m_a == other.m_a && m_curEvent == other.m_curEvent;
|
|
}
|
|
|
|
bool
|
|
CompositionTimeSliceAdapter::iterator::operator!=(const iterator& other) const {
|
|
return !operator==(other);
|
|
}
|
|
|
|
Event *
|
|
CompositionTimeSliceAdapter::iterator::operator*() const {
|
|
return m_curEvent;
|
|
}
|
|
|
|
Event &
|
|
CompositionTimeSliceAdapter::iterator::operator->() const {
|
|
return *m_curEvent;
|
|
}
|
|
|
|
int
|
|
CompositionTimeSliceAdapter::iterator::getTrack() const {
|
|
return m_curTrack;
|
|
}
|
|
|
|
bool
|
|
CompositionTimeSliceAdapter::iterator::strictLessThan(Event *e1, Event *e2) {
|
|
// We need a complete ordering of events -- we can't cope with two events
|
|
// comparing equal. i.e. one of e1 < e2 and e2 < e1 must be true. The
|
|
// ordering can be arbitrary -- we just compare addresses for events the
|
|
// event comparator doesn't distinguish between. We know we're always
|
|
// dealing with event pointers, not copies of events.
|
|
if (*e1 < *e2) return true;
|
|
else if (*e2 < *e1) return false;
|
|
else return e1 < e2;
|
|
}
|
|
|
|
}
|