/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Rosegarden A sequencer and musical notation editor. Copyright 2000-2011 the Rosegarden development team. See the AUTHORS file for more details. 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. */ #ifndef _OVERLAPS_H_ #define _OVERLAPS_H_ #include #include #include "Event.h" #include "Segment.h" #include "OverlapRange.h" namespace Rosegarden { /** * This class aims to pack in an unique object the list of notation * inconsistencies got when segments with differents clef, key or * transposition are overlapping on the same track : * 1 - To help to show a warning if such an inconsistency is displayed * in notation editor * 2 - To help to print out these inconsistencies as a text * * The template parameter may be Clef, Key or int (the last one to find out * transposition inconsistencies) */ template class Overlaps : public std::map > { public : Overlaps( std::vector segments ) { std::map >::clear(); for (std::vector::iterator i=segments.begin(); i!=segments.end(); ++i) { OverlapRange range = OverlapRange(); timeT segStart = (*i)->getStartTime(); timeT segEnd = (*i)->getEndMarkerTime(); // Start and ends of segments always are range limits insert(std::pair >(segStart, range)); insert(std::pair >(segEnd, range)); timeT currentTime, propertyTime; currentTime = segStart; for (;;) { bool fnd = getNextPropertyTime((*i), currentTime, propertyTime); if (!fnd) break; insert(std::pair >(propertyTime, range)); currentTime = propertyTime; } } // Complete the OverlapRange map typename std::map >::iterator it, next; for (it = this->begin(); it != this->end(); ++it) { timeT t1 = it->first; next = it; ++next; if (next == this->end()) { // The last element is only used to mark the end of the time range // this->erase(it); break; } timeT t2 = next->first; // Fill up the vector with segments for (std::vector::iterator i=segments.begin(); i!=segments.end(); ++i) { timeT segStart = (*i)->getStartTime(); timeT segEnd = (*i)->getEndMarkerTime(); if ((segStart <= t1) && (t2 <= segEnd)) { it->second.pushSegment(*i, t1); } } } } ~Overlaps() {} bool isConsistent(timeT t1, timeT t2) { typename std::map >::iterator i; if (!getFirst(t1, t2, i)) return true; if (! isConsistent(i)) return false; while (getNext(t2, i)) { if (! isConsistent(i)) return false; } return true; } bool isConsistent() { typename std::map >::iterator i, j; i = this->begin(); if (! isConsistent(i)) return false; ++i; j = i; ++j; while (j != this->end()) { if (! isConsistent(i)) return false; ++i; ++j; } return true; } bool getFirst(timeT t1, timeT t2, typename std::map >::iterator &it) { typename std::map >::iterator i, j; i = this->upper_bound(t1); if (i == this->end()) return false; j = i; --j; if (j == this->end()) { if (i->first > t2) return false; it = i; return true; } it = j; return true; } bool getNext(timeT t2, typename std::map >::iterator &it) { it++; if (it == this->end()) return false; typename std::map >::iterator next = it; next++; if (next == this->end()) return false; if (it->first > t2) return false; return true; } void getTimeRange(typename std::map >::iterator it, timeT &t1, timeT &t2) { t1 = it->first; it++; t2 = it->first; } bool isConsistent(typename std::map >::iterator it) { return ! it->second.isInconsistent(); } const std::vector * getSegments(typename std::map >::iterator it) { return it->second.getSegments(); } T getPropertyAtTime(Segment *segment, timeT time) const; protected : bool getNextPropertyTime(Segment *, timeT time, timeT &nextTime) const; private : //--------------- Data members --------------------------------- }; //------------- Specialized functions ----------------------------------- template <> inline Clef Overlaps::getPropertyAtTime(Segment *seg, timeT time) const { return seg->getClefAtTime(time); } template <> inline bool Overlaps::getNextPropertyTime(Segment *seg, timeT time, timeT &nextTime) const { return seg->getNextClefTime(time, nextTime); } template <> inline Key Overlaps::getPropertyAtTime(Segment *seg, timeT time) const { return seg->getKeyAtTime(time); } template <> inline bool Overlaps::getNextPropertyTime(Segment *seg, timeT time, timeT &nextTime) const { return seg->getNextKeyTime(time, nextTime); } template <> inline int Overlaps::getPropertyAtTime(Segment *seg, timeT) const { return seg->getTranspose(); } template <> inline bool Overlaps::getNextPropertyTime(Segment *, timeT time, timeT &nextTime) const { nextTime = time; return false; } } #endif // _OVERLAPS_H_