예제 #1
0
TEST_F(CueControlTest, LoadAutodetectedCues_QuantizeDisabled) {
    m_pQuantizeEnabled->set(0);

    TrackPointer pTrack = createTestTrack();
    pTrack->setSampleRate(44100);
    pTrack->setBpm(120.0);

    pTrack->setCuePoint(CuePosition(240.0, Cue::AUTOMATIC));

    auto pIntro = pTrack->createAndAddCue();
    pIntro->setType(Cue::INTRO);
    pIntro->setSource(Cue::AUTOMATIC);
    pIntro->setPosition(210.0);
    pIntro->setLength(120.0);

    auto pOutro = pTrack->createAndAddCue();
    pOutro->setType(Cue::OUTRO);
    pOutro->setSource(Cue::AUTOMATIC);
    pOutro->setPosition(770.0);
    pOutro->setLength(220.0);

    loadTrack(pTrack);

    EXPECT_DOUBLE_EQ(240.0, m_pCuePoint->get());
    EXPECT_DOUBLE_EQ(210.0, m_pIntroStartPosition->get());
    EXPECT_DOUBLE_EQ(330.0, m_pIntroEndPosition->get());
    EXPECT_DOUBLE_EQ(770.0, m_pOutroStartPosition->get());
    EXPECT_DOUBLE_EQ(990.0, m_pOutroEndPosition->get());
}
예제 #2
0
TEST_F(CueControlTest, LoadAutodetectedCues_QuantizeEnabled) {
    m_pQuantizeEnabled->set(1);

    TrackPointer pTrack = createTestTrack();
    pTrack->setSampleRate(44100);
    pTrack->setBpm(120.0);

    const int frameSize = 2;
    const int sampleRate = pTrack->getSampleRate();
    const double bpm = pTrack->getBpm();
    const double beatLength = (60.0 * sampleRate / bpm) * frameSize;

    pTrack->setCuePoint(CuePosition(1.9 * beatLength, Cue::AUTOMATIC));

    auto pIntro = pTrack->createAndAddCue();
    pIntro->setType(Cue::INTRO);
    pIntro->setSource(Cue::AUTOMATIC);
    pIntro->setPosition(2.1 * beatLength);
    pIntro->setLength(1.2 * beatLength);

    auto pOutro = pTrack->createAndAddCue();
    pOutro->setType(Cue::OUTRO);
    pOutro->setSource(Cue::AUTOMATIC);
    pOutro->setPosition(11.1 * beatLength);
    pOutro->setLength(4.4 * beatLength);

    loadTrack(pTrack);

    EXPECT_DOUBLE_EQ(2.0 * beatLength, m_pCuePoint->get());
    EXPECT_DOUBLE_EQ(2.0 * beatLength, m_pIntroStartPosition->get());
    EXPECT_DOUBLE_EQ(4.0 * beatLength, m_pIntroEndPosition->get());
    EXPECT_DOUBLE_EQ(11.0 * beatLength, m_pOutroStartPosition->get());
    EXPECT_DOUBLE_EQ(16.0 * beatLength, m_pOutroEndPosition->get());
}
예제 #3
0
TEST_F(CueControlTest, LoadTrackWithDetectedCues) {
    TrackPointer pTrack = createTestTrack();
    pTrack->setCuePoint(CuePosition(100.0, Cue::AUTOMATIC));
    auto pIntro = pTrack->createAndAddCue();
    pIntro->setType(Cue::INTRO);
    pIntro->setSource(Cue::AUTOMATIC);
    pIntro->setPosition(100.0);
    pIntro->setLength(0.0);
    auto pOutro = pTrack->createAndAddCue();
    pOutro->setType(Cue::OUTRO);
    pOutro->setSource(Cue::AUTOMATIC);
    pOutro->setPosition(-1.0);
    pOutro->setLength(200.0);

    loadTrack(pTrack);

    EXPECT_DOUBLE_EQ(100.0, m_pCuePoint->get());
    EXPECT_DOUBLE_EQ(100.0, m_pIntroStartPosition->get());
    EXPECT_DOUBLE_EQ(-1.0, m_pIntroEndPosition->get());
    EXPECT_DOUBLE_EQ(-1.0, m_pOutroStartPosition->get());
    EXPECT_DOUBLE_EQ(200.0, m_pOutroEndPosition->get());
    EXPECT_TRUE(m_pIntroStartEnabled->toBool());
    EXPECT_FALSE(m_pIntroEndEnabled->toBool());
    EXPECT_FALSE(m_pOutroStartEnabled->toBool());
    EXPECT_TRUE(m_pOutroEndEnabled->toBool());
}
예제 #4
0
TEST_F(CueControlTest, SeekOnLoadMainCue) {
    m_pSeekOnLoadMode->slotSet(SEEK_ON_LOAD_MAIN_CUE);

    TrackPointer pTrack = createTestTrack();
    pTrack->setCuePoint(CuePosition(100.0, Cue::MANUAL));

    loadTrack(pTrack);

    EXPECT_DOUBLE_EQ(100.0, m_pCuePoint->get());
    EXPECT_DOUBLE_EQ(100.0, getCurrentSample());

    // Move cue and check if track is following it.
    pTrack->setCuePoint(CuePosition(200.0, Cue::MANUAL));
    ProcessBuffer();

    EXPECT_DOUBLE_EQ(200.0, m_pCuePoint->get());
    EXPECT_DOUBLE_EQ(200.0, getCurrentSample());
}
예제 #5
0
TEST_F(CueControlTest, SeekOnLoadZeroPos) {
    m_pSeekOnLoadMode->slotSet(SEEK_ON_LOAD_ZERO_POS);

    TrackPointer pTrack = createTestTrack();
    pTrack->setCuePoint(CuePosition(100.0, Cue::MANUAL));

    loadTrack(pTrack);

    EXPECT_DOUBLE_EQ(100.0, m_pCuePoint->get());
    EXPECT_DOUBLE_EQ(0.0, getCurrentSample());
}
예제 #6
0
TEST_F(CueControlTest, SeekOnLoadDefault_CueRecallDisabled) {
    m_pSeekOnLoadMode->slotSet(SEEK_ON_LOAD_DEFAULT);

    // Note: CueRecall uses inverse logic (0 means enabled).
    config()->set(ConfigKey("[Controls]", "CueRecall"), ConfigValue(1));

    TrackPointer pTrack = createTestTrack();
    pTrack->setCuePoint(CuePosition(100.0, Cue::MANUAL));

    loadTrack(pTrack);

    EXPECT_DOUBLE_EQ(100.0, m_pCuePoint->get());
    EXPECT_DOUBLE_EQ(0.0, getCurrentSample());
}
예제 #7
0
// Moves the cue point to current position or to closest beat in case
// quantize is enabled
void CueControl::cueSet(double v) {
    if (!v)
        return;

    QMutexLocker lock(&m_mutex);
    double closestBeat = m_pClosestBeat->get();
    double cue = (m_pQuantizeEnabled->get() > 0.0 && closestBeat != -1) ?
            closestBeat : getCurrentSample();
    m_pCuePoint->set(cue);
    TrackPointer pLoadedTrack = m_pLoadedTrack;
    lock.unlock();

    // Store cue point in loaded track
    if (pLoadedTrack) {
        pLoadedTrack->setCuePoint(cue);
    }
}
예제 #8
0
TEST_F(CueControlTest, SeekOnLoadDefault_NoCue) {
    m_pSeekOnLoadMode->slotSet(SEEK_ON_LOAD_DEFAULT);

    TrackPointer pTrack = createTestTrack();

    loadTrack(pTrack);

    EXPECT_DOUBLE_EQ(-1.0, m_pCuePoint->get());
    EXPECT_DOUBLE_EQ(0.0, getCurrentSample());

    // Set cue and check if track is seeked to it.
    pTrack->setCuePoint(CuePosition(200.0, Cue::MANUAL));
    ProcessBuffer();

    EXPECT_DOUBLE_EQ(200.0, m_pCuePoint->get());
    EXPECT_DOUBLE_EQ(200.0, getCurrentSample());
}
예제 #9
0
// Moves the cue point to current position or to closest beat in case
// quantize is enabled
void CueControl::cueSet(double v) {
    if (!v)
        return;

    QMutexLocker lock(&m_mutex);
    double cue = (m_pQuantizeEnabled->get() > 0.0 && m_pClosestBeat->get() != -1) ?
            floor(m_pClosestBeat->get()) : floor(getCurrentSample());
    if (!even(static_cast<int>(cue))) {
        cue--;
    }
    m_pCuePoint->set(cue);
    TrackPointer pLoadedTrack = m_pLoadedTrack;
    lock.unlock();

    // Store cue point in loaded track
    if (pLoadedTrack) {
        pLoadedTrack->setCuePoint(cue);
    }
}
예제 #10
0
void CueControl::trackLoaded(TrackPointer pNewTrack, TrackPointer pOldTrack) {
    QMutexLocker lock(&m_mutex);

    DEBUG_ASSERT(m_pLoadedTrack == pOldTrack);
    if (m_pLoadedTrack) {
        disconnect(m_pLoadedTrack.get(), 0, this, 0);
        for (int i = 0; i < m_iNumHotCues; ++i) {
            detachCue(i);
        }

        m_pCueIndicator->setBlinkValue(ControlIndicator::OFF);
        m_pCuePoint->set(-1.0);
        m_pLoadedTrack.reset();
    }

    if (!pNewTrack) {
        return;
    }
    m_pLoadedTrack = pNewTrack;

    connect(m_pLoadedTrack.get(), SIGNAL(cuesUpdated()),
            this, SLOT(trackCuesUpdated()),
            Qt::DirectConnection);

    CuePointer pLoadCue;
    for (const CuePointer& pCue: m_pLoadedTrack->getCuePoints()) {
        if (pCue->getType() == Cue::CUE) {
            continue; // skip
        }
        if (pCue->getType() == Cue::LOAD) {
            DEBUG_ASSERT(!pLoadCue);
            pLoadCue = pCue;
        }
        int hotcue = pCue->getHotCue();
        if (hotcue != -1) {
            attachCue(pCue, hotcue);
        }
    }
    double cuePoint;
    if (pLoadCue) {
        cuePoint = pLoadCue->getPosition();
    } else {
        // If no load cue point is stored, read from track
        cuePoint = m_pLoadedTrack->getCuePoint();
    }
    m_pCuePoint->set(cuePoint);

    // Need to unlock before emitting any signals to prevent deadlock.
    lock.unlock();

    // Use pNewTrack here, because m_pLoadedTrack might have been reset
    // immediately after leaving the locking scope!
    pNewTrack->setCuePoint(cuePoint);

    // If cue recall is ON in the prefs, then we're supposed to seek to the cue
    // point on song load. Note that [Controls],cueRecall == 0 corresponds to "ON", not OFF.
    bool cueRecall = (getConfig()->getValueString(
                ConfigKey("[Controls]","CueRecall"), "0").toInt() == 0);
    if (cueRecall && (cuePoint >= 0.0)) {
        seekExact(cuePoint);
    } else if (!(m_pVinylControlEnabled->get() &&
            m_pVinylControlMode->get() == MIXXX_VCMODE_ABSOLUTE)) {
        // If cuerecall is off, seek to zero unless
        // vinylcontrol is on and set to absolute.  This allows users to
        // load tracks and have the needle-drop be maintained.
        seekExact(0.0);
    }

    trackCuesUpdated();
}