void
MappedBufMetaIterator::
fetchEventsNoncompeting(MappedInserterBase &inserter,
                 const RealTime& startTime,
                 const RealTime& endTime)
{
#ifdef DEBUG_META_ITERATOR
    SEQUENCER_DEBUG << "MBMI::fetchEventsNoncompeting "
                    << startTime << " -> "
                    << endTime << endl;
#endif
    Profiler profiler("MappedBufMetaIterator::fetchEventsNoncompeting", false);

    m_currentTime = endTime;
    
    // Activate segments that have anything playing during this
    // slice.  We include segments that end exactly when we start, but
    // not segments that start exactly when we end.
    for (segmentiterators::iterator i = m_iterators.begin();
         i != m_iterators.end();
         ++i) { 
        RealTime start, end;
        (*i)->getSegment()->getStartEnd(start, end);
        bool active = ((start < endTime) && (end >= startTime));
        (*i)->setActive(active, startTime);
    }

    // State variable to allow the outer loop to run until the inner
    // loop has nothing to do.
    bool innerLoopHasMore = false;
    do {
        innerLoopHasMore = false;

        for (size_t i = 0; i < m_iterators.size(); ++i) {
            MappedEventBuffer::iterator *iter = m_iterators[i];

#ifdef DEBUG_META_ITERATOR
            SEQUENCER_DEBUG << "MBMI::fetchEventsNoncompeting : "
                            << "checking segment #" << i << endl;
#endif

            if (!iter->getActive()) {
#ifdef DEBUG_META_ITERATOR
                SEQUENCER_DEBUG << "MBMI::fetchEventsNoncompeting : "
                                << "no more events to get for this slice"
                                << "in segment #" << i << endl;
#endif

                continue; // skip this iterator
            }

            if (iter->atEnd()) {
#ifdef DEBUG_META_ITERATOR
                SEQUENCER_DEBUG << "MBMI::fetchEventsNoncompeting : "
                                << endTime
                                << " reached end of segment #"
                                << i << endl;
#endif
                // Make this iterator abort early in future
                // iterations, since we know it's all done.
                iter->setInactive();
                continue;
            }

            // This locks the iterator's buffer against writes, lest
            // writing cause reallocating the buffer while we are
            // holding a pointer into it.  No function we call will
            // hold the `cur' pointer past its own scope, implying
            // that nothing holds it past an iteration of this loop,
            // which is this lock's scope.
            QReadLocker locker(iter->getLock());

            MappedEvent *cur = iter->peek();

            // We couldn't fetch an event or it failed a sanity check.
            // So proceed to the next iterator but keep looking at
            // this one - incrementing it does nothing useful, and it
            // might get more events.  But don't set innerLoopHasMore,
            // lest we loop forever waiting for a valid event.
            if (!cur || !cur->isValid()) { continue; }

            // If we got this far, make the mapper ready.  Do this
            // even if the note won't play during this slice, because
            // sometimes/always we prepare channels slightly ahead of
            // their first notes, to fix bug #1378
            if (!iter->isReady()) {
                iter->makeReady(inserter, startTime);
            }
            
            if (cur->getEventTime() < endTime) {
                // Increment the iterator, since we're taking this
                // event.  NB, in the other branch it is not yet used
                // so we leave `iter' where it is.
                ++(*iter);
                
                // If we got this far, we'll want to try the next
                // iteration, so note it.
                innerLoopHasMore = true;
                
#ifdef DEBUG_META_ITERATOR
                SEQUENCER_DEBUG << "MBMI::fetchEventsNoncompeting : " << endTime
                                << " seeing evt from segment #"
                                << i
                                << " : trackId: " << cur->getTrackId()
                                << " channel: " << (unsigned int) cur->getRecordedChannel()
                                << " - inst: " << cur->getInstrument()
                                << " - type: " << cur->getType()
                                << " - time: " << cur->getEventTime()
                                << " - duration: " << cur->getDuration()
                                << " - data1: " << (unsigned int)cur->getData1()
                                << " - data2: " << (unsigned int)cur->getData2()
                                << endl;
#endif

                if(iter->shouldPlay(cur, startTime)) {
                    iter->doInsert(inserter, *cur);
#ifdef DEBUG_META_ITERATOR
                    SEQUENCER_DEBUG << "Inserting event" << endl;
#endif

                } else {
#ifdef DEBUG_META_ITERATOR
                    SEQUENCER_DEBUG << "Skipping event" << endl;
#endif
                }
            } else {
                // This iterator has more events but they only sound
                // after the end of this slice, so it's done.
                iter->setInactive();

#ifdef DEBUG_META_ITERATOR
                SEQUENCER_DEBUG << "fetchEventsNoncompeting : Event is past end for segment #"
                                << i << endl;
#endif
            }
        }
    } while (innerLoopHasMore);

    return;
}
Beispiel #2
0
bool
operator<(const MappedEvent &a, const MappedEvent &b)
{
    return a.getEventTime() < b.getEventTime();
}