void CueControl::attachCue(CuePointer pCue, int hotCue) { HotcueControl* pControl = m_hotcueControl.value(hotCue, NULL); if (pControl == NULL) { return; } if (pControl->getCue() != NULL) { detachCue(pControl->getHotcueNumber()); } connect(pCue.data(), SIGNAL(updated()), this, SLOT(cueUpdated()), Qt::DirectConnection); pControl->getPosition()->set(pCue->getPosition()); pControl->getEnabled()->set(pCue->getPosition() == -1 ? 0.0 : 1.0); // set pCue only if all other data is in place // because we have a null check for valid data else where in the code pControl->setCue(pCue); }
void CueControl::trackLoaded(TrackPointer pNewTrack, TrackPointer pOldTrack) { Q_UNUSED(pOldTrack); QMutexLocker lock(&m_mutex); if (m_pLoadedTrack) { disconnect(m_pLoadedTrack.data(), 0, this, 0); for (int i = 0; i < m_iNumHotCues; ++i) { detachCue(i); } // Store the cue point in a load cue. double cuePoint = m_pCuePoint->get(); if (cuePoint != -1 && cuePoint != 0.0) { CuePointer loadCue; const QList<CuePointer> cuePoints(m_pLoadedTrack->getCuePoints()); QListIterator<CuePointer> it(cuePoints); while (it.hasNext()) { CuePointer pCue(it.next()); if (pCue->getType() == Cue::LOAD) { loadCue = pCue; break; } } if (!loadCue) { loadCue = m_pLoadedTrack->addCue(); loadCue->setType(Cue::LOAD); loadCue->setLength(0); } loadCue->setPosition(cuePoint); } m_pCueIndicator->setBlinkValue(ControlIndicator::OFF); m_pCuePoint->set(-1.0); m_pLoadedTrack.clear(); } if (pNewTrack.isNull()) { return; } m_pLoadedTrack = pNewTrack; connect(pNewTrack.data(), SIGNAL(cuesUpdated()), this, SLOT(trackCuesUpdated()), Qt::DirectConnection); CuePointer loadCue; const QList<CuePointer> cuePoints(pNewTrack->getCuePoints()); QListIterator<CuePointer> it(cuePoints); while (it.hasNext()) { CuePointer pCue(it.next()); if (pCue->getType() == Cue::LOAD) { loadCue = pCue; } else if (pCue->getType() != Cue::CUE) { continue; } int hotcue = pCue->getHotCue(); if (hotcue != -1) attachCue(pCue, hotcue); } double loadCuePoint = 0.0; // 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 (loadCue != NULL) { m_pCuePoint->set(loadCue->getPosition()); if (cueRecall) { loadCuePoint = loadCue->getPosition(); } } else { // If no cue point is stored, set one at track start m_pCuePoint->set(0.0); } // Need to unlock before emitting any signals to prevent deadlock. lock.unlock(); // If cueRecall is on, seek to it even if we didn't find a cue value (we'll // seek to 0. if (cueRecall) { seekExact(loadCuePoint); } 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); } }
void HotcueControl::setCue(CuePointer pCue) { setPosition(pCue->getPosition()); // set pCue only if all other data is in place // because we have a null check for valid data else where in the code m_pCue = pCue; }
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(); }
TEST_F(CueControlTest, OutroCue_SetStartEnd_ClearStartEnd) { TrackPointer pTrack = createAndLoadFakeTrack(); // Set outro start cue setCurrentSample(750.0); m_pOutroStartSet->slotSet(1); m_pOutroStartSet->slotSet(0); EXPECT_DOUBLE_EQ(750.0, m_pOutroStartPosition->get()); EXPECT_TRUE(m_pOutroStartEnabled->toBool()); EXPECT_DOUBLE_EQ(-1.0, m_pOutroEndPosition->get()); EXPECT_FALSE(m_pOutroEndEnabled->toBool()); CuePointer pCue = pTrack->findCueByType(Cue::OUTRO); EXPECT_NE(nullptr, pCue); if (pCue != nullptr) { EXPECT_DOUBLE_EQ(750.0, pCue->getPosition()); EXPECT_DOUBLE_EQ(0.0, pCue->getLength()); EXPECT_DOUBLE_EQ(Cue::MANUAL, pCue->getSource()); } // Set outro end cue setCurrentSample(1000.0); m_pOutroEndSet->slotSet(1); m_pOutroEndSet->slotSet(0); EXPECT_DOUBLE_EQ(750.0, m_pOutroStartPosition->get()); EXPECT_TRUE(m_pOutroStartEnabled->toBool()); EXPECT_DOUBLE_EQ(1000.0, m_pOutroEndPosition->get()); EXPECT_TRUE(m_pOutroEndEnabled->toBool()); pCue = pTrack->findCueByType(Cue::OUTRO); EXPECT_NE(nullptr, pCue); if (pCue != nullptr) { EXPECT_DOUBLE_EQ(750.0, pCue->getPosition()); EXPECT_DOUBLE_EQ(250.0, pCue->getLength()); EXPECT_DOUBLE_EQ(Cue::MANUAL, pCue->getSource()); } // Clear outro start cue m_pOutroStartClear->slotSet(1); m_pOutroStartClear->slotSet(0); EXPECT_DOUBLE_EQ(-1.0, m_pOutroStartPosition->get()); EXPECT_FALSE(m_pOutroStartEnabled->toBool()); EXPECT_DOUBLE_EQ(1000.0, m_pOutroEndPosition->get()); EXPECT_TRUE(m_pOutroEndEnabled->toBool()); pCue = pTrack->findCueByType(Cue::OUTRO); EXPECT_NE(nullptr, pCue); if (pCue != nullptr) { EXPECT_DOUBLE_EQ(-1.0, pCue->getPosition()); EXPECT_DOUBLE_EQ(1000.0, pCue->getLength()); EXPECT_DOUBLE_EQ(Cue::MANUAL, pCue->getSource()); } // Clear outro end cue m_pOutroEndClear->slotSet(1); m_pOutroEndClear->slotSet(0); EXPECT_DOUBLE_EQ(-1.0, m_pOutroStartPosition->get()); EXPECT_FALSE(m_pOutroStartEnabled->toBool()); EXPECT_DOUBLE_EQ(-1.0, m_pOutroEndPosition->get()); EXPECT_FALSE(m_pOutroEndEnabled->toBool()); EXPECT_EQ(nullptr, pTrack->findCueByType(Cue::OUTRO)); }