diff options
Diffstat (limited to 'src/base/Selection.cpp')
-rw-r--r-- | src/base/Selection.cpp | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/src/base/Selection.cpp b/src/base/Selection.cpp new file mode 100644 index 0000000..6e5ca2f --- /dev/null +++ b/src/base/Selection.cpp @@ -0,0 +1,318 @@ +// -*- c-basic-offset: 4 -*- + +/* + Rosegarden + A sequencer and musical notation editor. + + This program is Copyright 2000-2008 + Guillaume Laurent <[email protected]>, + Chris Cannam <[email protected]>, + Richard Bown <[email protected]> + + 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. +*/ + +#include "Selection.h" +#include "Segment.h" +#include "SegmentNotationHelper.h" +#include "BaseProperties.h" + +namespace Rosegarden { + +EventSelection::EventSelection(Segment& t) : + m_originalSegment(t), + m_beginTime(0), + m_endTime(0), + m_haveRealStartTime(false) +{ + t.addObserver(this); +} + +EventSelection::EventSelection(Segment& t, timeT beginTime, timeT endTime, bool overlap) : + m_originalSegment(t), + m_beginTime(0), + m_endTime(0), + m_haveRealStartTime(false) +{ + t.addObserver(this); + + Segment::iterator i = t.findTime(beginTime); + Segment::iterator j = t.findTime(endTime); + + if (i != t.end()) { + m_beginTime = (*i)->getAbsoluteTime(); + while (i != j) { + m_endTime = (*i)->getAbsoluteTime() + (*i)->getDuration(); + m_segmentEvents.insert(*i); + ++i; + } + m_haveRealStartTime = true; + } + + // Find events overlapping the beginning + // + if (overlap) { + i = t.findTime(beginTime); + + while (i != t.begin() && i != t.end() && i != j) { + + if ((*i)->getAbsoluteTime() + (*i)->getDuration() > beginTime) + { + m_segmentEvents.insert(*i); // duplicates are filtered automatically + m_beginTime = (*i)->getAbsoluteTime(); + } + else + break; + + --i; + } + + } + +} + +EventSelection::EventSelection(const EventSelection &sel) : + SegmentObserver(), + m_originalSegment(sel.m_originalSegment), + m_segmentEvents(sel.m_segmentEvents), + m_beginTime(sel.m_beginTime), + m_endTime(sel.m_endTime), + m_haveRealStartTime(sel.m_haveRealStartTime) +{ + m_originalSegment.addObserver(this); +} + +EventSelection::~EventSelection() +{ + m_originalSegment.removeObserver(this); +} + +void EventSelection::addEvent(Event *e) +{ + timeT eventDuration = e->getDuration(); + if (eventDuration == 0) eventDuration = 1; + + if (contains(e)) return; + + if (e->getAbsoluteTime() < m_beginTime || !m_haveRealStartTime) { + m_beginTime = e->getAbsoluteTime(); + m_haveRealStartTime = true; + } + if (e->getAbsoluteTime() + eventDuration > m_endTime) { + m_endTime = e->getAbsoluteTime() + eventDuration; + } + m_segmentEvents.insert(e); +} + +void EventSelection::addFromSelection(EventSelection *sel) +{ + for (eventcontainer::iterator i = sel->getSegmentEvents().begin(); + i != sel->getSegmentEvents().end(); ++i) { + if (!contains(*i)) addEvent(*i); + } +} + +void EventSelection::removeEvent(Event *e) +{ + std::pair<eventcontainer::iterator, eventcontainer::iterator> + interval = m_segmentEvents.equal_range(e); + + for (eventcontainer::iterator it = interval.first; + it != interval.second; it++) + { + if (*it == e) { + m_segmentEvents.erase(it); + return; + } + } +} + +bool EventSelection::contains(Event *e) const +{ + std::pair<eventcontainer::const_iterator, eventcontainer::const_iterator> + interval = m_segmentEvents.equal_range(e); + + for (eventcontainer::const_iterator it = interval.first; + it != interval.second; ++it) + { + if (*it == e) return true; + } + + return false; +} + +bool EventSelection::contains(const std::string &type) const +{ + for (eventcontainer::const_iterator i = m_segmentEvents.begin(); + i != m_segmentEvents.end(); ++i) { + if ((*i)->isa(type)) return true; + } + return false; +} + +timeT EventSelection::getTotalDuration() const +{ + return getEndTime() - getStartTime(); +} + +EventSelection::RangeList +EventSelection::getRanges() const +{ + RangeList ranges; + + Segment::iterator i = m_originalSegment.findTime(getStartTime()); + Segment::iterator j = i; + Segment::iterator k = m_originalSegment.findTime(getEndTime()); + + while (j != k) { + + for (j = i; j != k && contains(*j); ++j); + + if (j != i) { + ranges.push_back(RangeList::value_type(i, j)); + } + + for (i = j; i != k && !contains(*i); ++i); + j = i; + } + + return ranges; +} + +EventSelection::RangeTimeList +EventSelection::getRangeTimes() const +{ + RangeList ranges(getRanges()); + RangeTimeList rangeTimes; + + for (RangeList::iterator i = ranges.begin(); i != ranges.end(); ++i) { + timeT startTime = m_originalSegment.getEndTime(); + timeT endTime = m_originalSegment.getEndTime(); + if (i->first != m_originalSegment.end()) { + startTime = (*i->first)->getAbsoluteTime(); + } + if (i->second != m_originalSegment.end()) { + endTime = (*i->second)->getAbsoluteTime(); + } + rangeTimes.push_back(RangeTimeList::value_type(startTime, endTime)); + } + + return rangeTimes; +} + +void +EventSelection::eventRemoved(const Segment *s, Event *e) +{ + if (s == &m_originalSegment /*&& contains(e)*/) { + removeEvent(e); + } +} + +void +EventSelection::segmentDeleted(const Segment *) +{ + /* + std::cerr << "WARNING: EventSelection notified of segment deletion: this is probably a bug " + << "(selection should have been deleted before segment)" << std::endl; + */ +} + +bool SegmentSelection::hasNonAudioSegment() const +{ + for (const_iterator i = begin(); i != end(); ++i) { + if ((*i)->getType() == Segment::Internal) + return true; + } + return false; +} + + +TimeSignatureSelection::TimeSignatureSelection() { } + +TimeSignatureSelection::TimeSignatureSelection(Composition &composition, + timeT beginTime, + timeT endTime, + bool includeOpeningTimeSig) +{ + int n = composition.getTimeSignatureNumberAt(endTime); + + for (int i = composition.getTimeSignatureNumberAt(beginTime); + i <= n; + ++i) { + + if (i < 0) continue; + + std::pair<timeT, TimeSignature> sig = + composition.getTimeSignatureChange(i); + + if (sig.first < endTime) { + if (sig.first < beginTime) { + if (includeOpeningTimeSig) { + sig.first = beginTime; + } else { + continue; + } + } + addTimeSignature(sig.first, sig.second); + } + } +} + +TimeSignatureSelection::~TimeSignatureSelection() { } + +void +TimeSignatureSelection::addTimeSignature(timeT t, TimeSignature timeSig) +{ + m_timeSignatures.insert(timesigcontainer::value_type(t, timeSig)); +} + +TempoSelection::TempoSelection() { } + +TempoSelection::TempoSelection(Composition &composition, + timeT beginTime, + timeT endTime, + bool includeOpeningTempo) +{ + int n = composition.getTempoChangeNumberAt(endTime); + + for (int i = composition.getTempoChangeNumberAt(beginTime); + i <= n; + ++i) { + + if (i < 0) continue; + + std::pair<timeT, tempoT> change = composition.getTempoChange(i); + + if (change.first < endTime) { + if (change.first < beginTime) { + if (includeOpeningTempo) { + change.first = beginTime; + } else { + continue; + } + } + std::pair<bool, tempoT> ramping = + composition.getTempoRamping(i, false); + addTempo(change.first, change.second, + ramping.first ? ramping.second : -1); + } + } +} + +TempoSelection::~TempoSelection() { } + +void +TempoSelection::addTempo(timeT t, tempoT tempo, tempoT targetTempo) +{ + m_tempos.insert(tempocontainer::value_type + (t, tempochange(tempo, targetTempo))); +} + +} |