summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Schürmann <daschuer@mixxx.org>2019-11-10 12:07:48 +0100
committerGitHub <noreply@github.com>2019-11-10 12:07:48 +0100
commitb4c9ca1d67af901529bb9494686016bb7fea56e4 (patch)
treef4e1a032da621bdcc5037b6658139b895a78e340 /src
parentddff7f6ff8e062a7be66157ec8fdf5e06c2262ac (diff)
parent1ab1853f270f01f0cb78acaaf85a12a811df5b71 (diff)
Merge pull request #2103 from Be-ing/autodj_intro_outro
make better use of intro/outro markers with AutoDJ
Diffstat (limited to 'src')
-rw-r--r--src/analyzer/analyzersilence.cpp108
-rw-r--r--src/analyzer/analyzersilence.h4
-rw-r--r--src/engine/cachingreader/cachingreader.cpp6
-rw-r--r--src/engine/cachingreader/cachingreader.h6
-rw-r--r--src/engine/cachingreader/cachingreaderworker.cpp21
-rw-r--r--src/engine/controls/bpmcontrol.cpp8
-rw-r--r--src/engine/controls/cuecontrol.cpp460
-rw-r--r--src/engine/controls/cuecontrol.h34
-rw-r--r--src/engine/controls/vinylcontrolcontrol.cpp2
-rw-r--r--src/engine/enginebuffer.cpp31
-rw-r--r--src/engine/readaheadmanager.h9
-rw-r--r--src/library/autodj/autodjfeature.cpp15
-rw-r--r--src/library/autodj/autodjprocessor.cpp1215
-rw-r--r--src/library/autodj/autodjprocessor.h97
-rw-r--r--src/library/autodj/dlgautodj.cpp128
-rw-r--r--src/library/autodj/dlgautodj.h19
-rw-r--r--src/library/autodj/dlgautodj.ui122
-rw-r--r--src/library/dao/cuedao.cpp12
-rw-r--r--src/library/dao/trackdao.cpp2
-rw-r--r--src/library/dlgtrackinfo.cpp24
-rw-r--r--src/mixer/basetrackplayer.cpp11
-rw-r--r--src/mixer/playermanager.cpp17
-rw-r--r--src/mixer/playermanager.h2
-rw-r--r--src/preferences/dialog/dlgprefautodj.cpp23
-rw-r--r--src/preferences/dialog/dlgprefautodj.h1
-rw-r--r--src/preferences/dialog/dlgprefautodjdlg.ui33
-rw-r--r--src/preferences/dialog/dlgprefdeck.cpp131
-rw-r--r--src/preferences/dialog/dlgprefdeck.h13
-rw-r--r--src/preferences/dialog/dlgprefdeckdlg.ui98
-rw-r--r--src/skin/legacyskinparser.cpp1
-rw-r--r--src/test/analyzersilence_test.cpp142
-rw-r--r--src/test/autodjprocessor_test.cpp626
-rw-r--r--src/test/cuecontrol_test.cpp270
-rw-r--r--src/track/cue.cpp75
-rw-r--r--src/track/cue.h70
-rw-r--r--src/track/track.cpp22
-rw-r--r--src/track/track.h4
-rw-r--r--src/waveform/renderers/waveformmark.cpp4
-rw-r--r--src/waveform/renderers/waveformmark.h13
-rw-r--r--src/waveform/renderers/waveformrendermark.cpp2
-rw-r--r--src/widget/wlibrary.cpp7
-rw-r--r--src/widget/wlibrary.h9
-rw-r--r--src/widget/woverview.cpp123
-rw-r--r--src/widget/woverview.h3
-rw-r--r--src/widget/wtracktableview.cpp52
-rw-r--r--src/widget/wtracktableview.h4
46 files changed, 2440 insertions, 1639 deletions
diff --git a/src/analyzer/analyzersilence.cpp b/src/analyzer/analyzersilence.cpp
index 9d5c814f1e..bde8445bef 100644
--- a/src/analyzer/analyzersilence.cpp
+++ b/src/analyzer/analyzersilence.cpp
@@ -9,40 +9,15 @@ constexpr float kSilenceThreshold = 0.001;
// TODO: Change the above line to:
//constexpr float kSilenceThreshold = db2ratio(-60.0f);
-bool shouldUpdateMainCue(CuePosition mainCue) {
- return mainCue.getSource() != Cue::MANUAL ||
- mainCue.getPosition() == -1.0 ||
- mainCue.getPosition() == 0.0;
-}
-
-bool hasIntroCueStart(const Cue& introCue) {
- return introCue.getPosition() != -1.0;
-}
-
-bool hasOutroCueEnd(const Cue& outroCue) {
- return outroCue.getEndPosition() > 0.0;
-}
-
-bool needsIntroCueStart(const Cue& introCue) {
- return introCue.getSource() != Cue::MANUAL &&
- !hasIntroCueStart(introCue);
-}
+bool shouldAnalyze(TrackPointer pTrack) {
+ CuePointer pIntroCue = pTrack->findCueByType(Cue::Type::Intro);
+ CuePointer pOutroCue = pTrack->findCueByType(Cue::Type::Outro);
+ CuePointer pAudibleSound = pTrack->findCueByType(Cue::Type::AudibleSound);
-bool needsOutroCueEnd(const Cue& outroCue) {
- return outroCue.getSource() != Cue::MANUAL &&
- !hasOutroCueEnd(outroCue);
-}
-
-bool shouldAnalyze(TrackPointer tio) {
- CuePointer pIntroCue = tio->findCueByType(Cue::INTRO);
- if (!pIntroCue) {
- return true;
- }
- CuePointer pOutroCue = tio->findCueByType(Cue::OUTRO);
- if (!pOutroCue) {
+ if (!pIntroCue || !pOutroCue || !pAudibleSound || pAudibleSound->getLength() <= 0) {
return true;
}
- return needsIntroCueStart(*pIntroCue) || needsOutroCueEnd(*pOutroCue);
+ return false;
}
} // anonymous namespace
@@ -56,11 +31,11 @@ AnalyzerSilence::AnalyzerSilence(UserSettingsPointer pConfig)
m_iSignalEnd(-1) {
}
-bool AnalyzerSilence::initialize(TrackPointer tio, int sampleRate, int totalSamples) {
+bool AnalyzerSilence::initialize(TrackPointer pTrack, int sampleRate, int totalSamples) {
Q_UNUSED(sampleRate);
Q_UNUSED(totalSamples);
- if (!shouldAnalyze(tio)) {
+ if (!shouldAnalyze(pTrack)) {
return false;
}
@@ -100,7 +75,7 @@ bool AnalyzerSilence::processSamples(const CSAMPLE* pIn, const int iLen) {
void AnalyzerSilence::cleanup() {
}
-void AnalyzerSilence::storeResults(TrackPointer tio) {
+void AnalyzerSilence::storeResults(TrackPointer pTrack) {
if (m_iSignalStart < 0) {
m_iSignalStart = 0;
}
@@ -114,32 +89,53 @@ void AnalyzerSilence::storeResults(TrackPointer tio) {
m_iSignalEnd = m_iFramesProcessed;
}
- double introStart = mixxx::kAnalysisChannels * m_iSignalStart;
- double outroEnd = mixxx::kAnalysisChannels * m_iSignalEnd;
+ double firstSound = mixxx::kAnalysisChannels * m_iSignalStart;
+ double lastSound = mixxx::kAnalysisChannels * m_iSignalEnd;
- if (shouldUpdateMainCue(tio->getCuePoint())) {
- tio->setCuePoint(CuePosition(introStart, Cue::AUTOMATIC));
+ CuePointer pAudibleSound = pTrack->findCueByType(Cue::Type::AudibleSound);
+ if (pAudibleSound == nullptr) {
+ pAudibleSound = pTrack->createAndAddCue();
+ pAudibleSound->setType(Cue::Type::AudibleSound);
}
-
- CuePointer pIntroCue = tio->findCueByType(Cue::INTRO);
- if (!pIntroCue) {
- pIntroCue = tio->createAndAddCue();
- pIntroCue->setType(Cue::INTRO);
- pIntroCue->setSource(Cue::AUTOMATIC);
- }
- if (pIntroCue->getSource() != Cue::MANUAL) {
- pIntroCue->setPosition(introStart);
- pIntroCue->setLength(0.0);
+ // The user has no way to directly edit the AudibleSound cue. If the user
+ // has deleted the Intro or Outro Cue, this analysis will be rerun when
+ // the track is loaded again. In this case, adjust the AudibleSound Cue's
+ // positions. This could be helpful, for example, when the track length
+ // is changed in a different program, or the silence detection threshold
+ // is changed.
+ pAudibleSound->setStartPosition(firstSound);
+ pAudibleSound->setEndPosition(lastSound);
+
+ CuePointer pIntroCue = pTrack->findCueByType(Cue::Type::Intro);
+
+ double mainCue = pTrack->getCuePoint().getPosition();
+ double introStart = firstSound;
+ // Before Mixxx 2.3, the default position for the main cue was 0.0. In this
+ // case, move the main cue point to the first sound. This case can be
+ // distinguished from a user intentionally setting the main cue position
+ // to 0.0 at a later time after analysis because in that case the intro cue
+ // would have already been created by this analyzer.
+ bool upgradingWithMainCueAtDefault = (mainCue == 0.0 && pIntroCue == nullptr);
+ if (mainCue == Cue::kNoPosition || upgradingWithMainCueAtDefault) {
+ pTrack->setCuePoint(CuePosition(firstSound));
+ // NOTE: the actual default for this ConfigValue is set in DlgPrefDeck.
+ } else if (m_pConfig->getValue(ConfigKey("[Controls]", "SetIntroStartAtMainCue"), false) &&
+ pIntroCue == nullptr) {
+ introStart = mainCue;
}
- CuePointer pOutroCue = tio->findCueByType(Cue::OUTRO);
- if (!pOutroCue) {
- pOutroCue = tio->createAndAddCue();
- pOutroCue->setType(Cue::OUTRO);
- pOutroCue->setSource(Cue::AUTOMATIC);
+ if (pIntroCue == nullptr) {
+ pIntroCue = pTrack->createAndAddCue();
+ pIntroCue->setType(Cue::Type::Intro);
+ pIntroCue->setStartPosition(introStart);
+ pIntroCue->setEndPosition(Cue::kNoPosition);
}
- if (pOutroCue->getSource() != Cue::MANUAL) {
- pOutroCue->setPosition(-1.0);
- pOutroCue->setLength(outroEnd);
+
+ CuePointer pOutroCue = pTrack->findCueByType(Cue::Type::Outro);
+ if (pOutroCue == nullptr) {
+ pOutroCue = pTrack->createAndAddCue();
+ pOutroCue->setType(Cue::Type::Outro);
+ pOutroCue->setStartPosition(Cue::kNoPosition);
+ pOutroCue->setEndPosition(lastSound);
}
}
diff --git a/src/analyzer/analyzersilence.h b/src/analyzer/analyzersilence.h
index b0b94f9c79..9c27b5c1e6 100644
--- a/src/analyzer/analyzersilence.h
+++ b/src/analyzer/analyzersilence.h
@@ -11,9 +11,9 @@ class AnalyzerSilence : public Analyzer {
explicit AnalyzerSilence(UserSettingsPointer pConfig);
~AnalyzerSilence() override = default;
- bool initialize(TrackPointer tio, int sampleRate, int totalSamples) override;
+ bool initialize(TrackPointer pTrack, int sampleRate, int totalSamples) override;
bool processSamples(const CSAMPLE* pIn, const int iLen) override;
- void storeResults(TrackPointer tio) override;
+ void storeResults(TrackPointer pTrack) override;
void cleanup() override;
private:
diff --git a/src/engine/cachingreader/cachingreader.cpp b/src/engine/cachingreader/cachingreader.cpp
index edaf66b42b..fa045c4eb3 100644
--- a/src/engine/cachingreader/cachingreader.cpp
+++ b/src/engine/cachingreader/cachingreader.cpp
@@ -40,9 +40,8 @@ const SINT kNumberOfCachedChunksInMemory = 80;
} // anonymous namespace
-
CachingReader::CachingReader(QString group,
- UserSettingsPointer config)
+ UserSettingsPointer config)
: m_pConfig(config),
// Limit the number of in-flight requests to the worker. This should
// prevent to overload the worker when it is not able to fetch those
@@ -63,7 +62,6 @@ CachingReader::CachingReader(QString group,
m_lruCachingReaderChunk(nullptr),
m_sampleBuffer(CachingReaderChunk::kSamples * kNumberOfCachedChunksInMemory),
m_worker(group, &m_chunkReadRequestFIFO, &m_readerStatusUpdateFIFO) {
-
m_allocatedCachingReaderChunks.reserve(kNumberOfCachedChunksInMemory);
// Divide up the allocated raw memory buffer into total_chunks
// chunks. Initialize each chunk to hold nothing and add it to the free
@@ -265,7 +263,7 @@ void CachingReader::process() {
// TRACK_LOADED without a chunk in between, assert this here.
DEBUG_ASSERT(m_state.load() == STATE_TRACK_LOADING ||
(m_state.load() == STATE_TRACK_LOADED &&
- !m_mruCachingReaderChunk && !m_lruCachingReaderChunk));
+ !m_mruCachingReaderChunk && !m_lruCachingReaderChunk));
// now purge also the recently used chunk list from the old track.
if (m_mruCachingReaderChunk || m_lruCachingReaderChunk) {
DEBUG_ASSERT(m_state.load() == STATE_TRACK_LOADING);
diff --git a/src/engine/cachingreader/cachingreader.h b/src/engine/cachingreader/cachingreader.h
index ca0df4d7d2..acec6c0ec5 100644
--- a/src/engine/cachingreader/cachingreader.h
+++ b/src/engine/cachingreader/cachingreader.h
@@ -5,11 +5,11 @@
#define ENGINE_CACHINGREADER_H
#include <QAtomicInt>
-#include <QList>
-#include <QVector>
-#include <QLinkedList>
#include <QHash>
+#include <QLinkedList>
+#include <QList>
#include <QVarLengthArray>
+#include <QVector>
#include "util/types.h"
#include "preferences/usersettings.h"
diff --git a/src/engine/cachingreader/cachingreaderworker.cpp b/src/engine/cachingreader/cachingreaderworker.cpp
index ddfe9f3dbc..070a9993a2 100644
--- a/src/engine/cachingreader/cachingreaderworker.cpp
+++ b/src/engine/cachingreader/cachingreaderworker.cpp
@@ -42,8 +42,7 @@ ReaderStatusUpdate CachingReaderWorker::processReadRequest(
chunkFrameIndexRange <= m_pAudioSource->frameIndexRange());
if (chunkFrameIndexRange.empty()) {
ReaderStatusUpdate result;
- result.init(CHUNK_READ_INVALID, pChunk,
- m_pAudioSource ? m_pAudioSource->frameIndexRange() : mixxx::IndexRange());
+ result.init(CHUNK_READ_INVALID, pChunk, m_pAudioSource ? m_pAudioSource->frameIndexRange() : mixxx::IndexRange());
return result;
}
@@ -71,8 +70,7 @@ ReaderStatusUpdate CachingReaderWorker::processReadRequest(
}
ReaderStatusUpdate result;
- result.init(status, pChunk,
- m_pAudioSource ? m_pAudioSource->frameIndexRange() : mixxx::IndexRange());
+ result.init(status, pChunk, m_pAudioSource ? m_pAudioSource->frameIndexRange() : mixxx::IndexRange());
return result;
}
@@ -139,14 +137,13 @@ void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) {
QString filename = pTrack->getLocation();
if (filename.isEmpty() || !pTrack->checkFileExists()) {
kLogger.warning()
- << m_group
- << "File not found"
- << filename;
+ << m_group
+ << "File not found"
+ << filename;
const auto update = ReaderStatusUpdate::trackUnloaded();
m_pReaderStatusFIFO->writeBlocking(&update, 1);
emit trackLoadFailed(
- pTrack, QString("The file '%1' could not be found.")
- .arg(QDir::toNativeSeparators(filename)));
+ pTrack, QString("The file '%1' could not be found.").arg(QDir::toNativeSeparators(filename)));
return;
}
@@ -161,7 +158,7 @@ void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) {
const auto update = ReaderStatusUpdate::trackUnloaded();
m_pReaderStatusFIFO->writeBlocking(&update, 1);
emit trackLoadFailed(
- pTrack, QString("The file '%1' could not be loaded").arg(filename));
+ pTrack, QString("The file '%1' could not be loaded").arg(filename));
return;
}
@@ -177,7 +174,7 @@ void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) {
const auto update = ReaderStatusUpdate::trackUnloaded();
m_pReaderStatusFIFO->writeBlocking(&update, 1);
emit trackLoadFailed(
- pTrack, QString("The file '%1' is empty and could not be loaded").arg(filename));
+ pTrack, QString("The file '%1' is empty and could not be loaded").arg(filename));
return;
}
@@ -190,7 +187,7 @@ void CachingReaderWorker::loadTrack(const TrackPointer& pTrack) {
const auto update =
ReaderStatusUpdate::trackLoaded(
- m_pAudioSource->frameIndexRange());
+ m_pAudioSource->frameIndexRange());
m_pReaderStatusFIFO->writeBlocking(&update, 1);
// Emit that the track is loaded.
diff --git a/src/engine/controls/bpmcontrol.cpp b/src/engine/controls/bpmcontrol.cpp
index 301a2fd8fd..cd0725d1dd 100644
--- a/src/engine/controls/bpmcontrol.cpp
+++ b/src/engine/controls/bpmcontrol.cpp
@@ -37,7 +37,7 @@ constexpr SINT kSamplesPerFrame = 2;
}
BpmControl::BpmControl(QString group,
- UserSettingsPointer pConfig)
+ UserSettingsPointer pConfig)
: EngineControl(group, pConfig),
m_tapFilter(this, kBpmTapFilterLength, kBpmTapMaxInterval),
m_dSyncInstantaneousBpm(0.0),
@@ -96,8 +96,10 @@ BpmControl::BpmControl(QString group,
// bpm_up_small / bpm_down_small steps by kBpmRangeSmallStep
m_pEngineBpm = new ControlLinPotmeter(
ConfigKey(group, "bpm"),
- kBpmRangeMin, kBpmRangeMax,
- kBpmRangeStep, kBpmRangeSmallStep,
+ kBpmRangeMin,
+ kBpmRangeMax,
+ kBpmRangeStep,
+ kBpmRangeSmallStep,
true);
connect(m_pEngineBpm, &ControlObject::valueChanged,
this, &BpmControl::slotUpdateRateSlider,
diff --git a/src/engine/controls/cuecontrol.cpp b/src/engine/controls/cuecontrol.cpp
index 1e1fd43a5f..3a160eded7 100644
--- a/src/engine/controls/cuecontrol.cpp
+++ b/src/engine/controls/cuecontrol.cpp
@@ -52,12 +52,10 @@ CueControl::CueControl(QString group,
m_pClosestBeat = ControlObject::getControl(ConfigKey(group, "beat_closest"));
m_pCuePoint = new ControlObject(ConfigKey(group, "cue_point"));
- m_pCuePoint->set(-1.0);
+ m_pCuePoint->set(Cue::kNoPosition);
m_pCueMode = new ControlObject(ConfigKey(group, "cue_mode"));
- m_pSeekOnLoadMode = new ControlObject(ConfigKey(group, "seekonload_mode"));
-
m_pCueSet = new ControlPushButton(ConfigKey(group, "cue_set"));
m_pCueSet->setButtonMode(ControlPushButton::TRIGGER);
connect(m_pCueSet, &ControlObject::valueChanged,
@@ -117,7 +115,7 @@ CueControl::CueControl(QString group,
m_pPlayIndicator = new ControlIndicator(ConfigKey(group, "play_indicator"));
m_pIntroStartPosition = new ControlObject(ConfigKey(group, "intro_start_position"));
- m_pIntroStartPosition->set(-1.0);
+ m_pIntroStartPosition->set(Cue::kNoPosition);
m_pIntroStartEnabled = new ControlObject(ConfigKey(group, "intro_start_enabled"));
m_pIntroStartEnabled->setReadOnly();
@@ -138,7 +136,7 @@ CueControl::CueControl(QString group,
Qt::DirectConnection);
m_pIntroEndPosition = new ControlObject(ConfigKey(group, "intro_end_position"));
- m_pIntroEndPosition->set(-1.0);
+ m_pIntroEndPosition->set(Cue::kNoPosition);
m_pIntroEndEnabled = new ControlObject(ConfigKey(group, "intro_end_enabled"));
m_pIntroEndEnabled->setReadOnly();
@@ -159,7 +157,7 @@ CueControl::CueControl(QString group,
Qt::DirectConnection);
m_pOutroStartPosition = new ControlObject(ConfigKey(group, "outro_start_position"));
- m_pOutroStartPosition->set(-1.0);
+ m_pOutroStartPosition->set(Cue::kNoPosition);
m_pOutroStartEnabled = new ControlObject(ConfigKey(group, "outro_start_enabled"));
m_pOutroStartEnabled->setReadOnly();
@@ -180,7 +178,7 @@ CueControl::CueControl(QString group,
Qt::DirectConnection);
m_pOutroEndPosition = new ControlObject(ConfigKey(group, "outro_end_position"));
- m_pOutroEndPosition->set(-1.0);
+ m_pOutroEndPosition->set(Cue::kNoPosition);
m_pOutroEndEnabled = new ControlObject(ConfigKey(group, "outro_end_enabled"));
m_pOutroEndEnabled->setReadOnly();
@@ -207,7 +205,6 @@ CueControl::CueControl(QString group,
CueControl::~CueControl() {
delete m_pCuePoint;
delete m_pCueMode;
- delete m_pSeekOnLoadMode;
delete m_pCueSet;
delete m_pCueClear;
delete m_pCueGoto;
@@ -306,19 +303,19 @@ void CueControl::trackLoaded(TrackPointer pNewTrack) {
QMutexLocker lock(&m_mutex);
if (m_pLoadedTrack) {
disconnect(m_pLoadedTrack.get(), 0, this, 0);
- for (const auto& pControl: m_hotcueControls) {
+ for (const auto& pControl : m_hotcueControls) {
detachCue(pControl);
}
m_pCueIndicator->setBlinkValue(ControlIndicator::OFF);
- m_pCuePoint->set(-1.0);
- m_pIntroStartPosition->set(-1.0);
+ m_pCuePoint->set(Cue::kNoPosition);
+ m_pIntroStartPosition->set(Cue::kNoPosition);
m_pIntroStartEnabled->forceSet(0.0);
- m_pIntroEndPosition->set(-1.0);
+ m_pIntroEndPosition->set(Cue::kNoPosition);
m_pIntroEndEnabled->forceSet(0.0);
- m_pOutroStartPosition->set(-1.0);
+ m_pOutroStartPosition->set(Cue::kNoPosition);
m_pOutroStartEnabled->forceSet(0.0);
- m_pOutroEndPosition->set(-1.0);
+ m_pOutroEndPosition->set(Cue::kNoPosition);
m_pOutroEndEnabled->forceSet(0.0);
m_pLoadedTrack.reset();
}
@@ -336,11 +333,11 @@ void CueControl::trackLoaded(TrackPointer pNewTrack) {
this, &CueControl::trackBeatsUpdated,
Qt::DirectConnection);
- CuePointer pLoadCue;
- for (const CuePointer& pCue: m_pLoadedTrack->getCuePoints()) {
- if (pCue->getType() == Cue::LOAD) {
- DEBUG_ASSERT(!pLoadCue);
- pLoadCue = pCue;
+ CuePointer pMainCue;
+ for (const CuePointer& pCue : m_pLoadedTrack->getCuePoints()) {
+ if (pCue->getType() == Cue::Type::MainCue) {
+ DEBUG_ASSERT(!pMainCue);
+ pMainCue = pCue;
}
}
@@ -349,60 +346,73 @@ void CueControl::trackLoaded(TrackPointer pNewTrack) {
// Use pNewTrack from now, because m_pLoadedTrack might have been reset
// immediately after leaving the locking scope!
-
// Because of legacy, we store the (load) cue point twice and need to
// sync both values.
- // The Cue::LOAD from getCuePoints() has the priority
- CuePosition cuePoint;
- if (pLoadCue) {
- cuePoint.setPosition(pLoadCue->getPosition());
+ // The Cue::Type::MainCue from getCuePoints() has the priority
+ CuePosition mainCuePoint;
+ if (pMainCue) {
+ mainCuePoint.setPosition(pMainCue->getPosition());
// adjust the track cue accordingly
- pNewTrack->setCuePoint(cuePoint);
+ pNewTrack->setCuePoint(mainCuePoint);
} else {
// If no load cue point is stored, read from track
// Note: This is 0:00 for new tracks
- cuePoint = pNewTrack->getCuePoint();
+ mainCuePoint = pNewTrack->getCuePoint();
// Than add the load cue to the list of cue
CuePointer pCue(pNewTrack->createAndAddCue());
- pCue->setPosition(cuePoint.getPosition());
- pCue->setHotCue(-1);
- pCue->setType(Cue::LOAD);
+ pCue->setStartPosition(mainCuePoint.getPosition());
+ pCue->setHotCue(Cue::kNoHotCue);
+ pCue->setType(Cue::Type::MainCue);
}
- m_pCuePoint->set(cuePoint.getPosition());
+ m_pCuePoint->set(mainCuePoint.getPosition());
// Update COs with cues from track.
loadCuesFromTrack();
// Seek track according to SeekOnLoadMode.
- SeekOnLoadMode seekOnLoadMode = getSeekOnLoadMode();
+ SeekOnLoadMode seekOnLoadMode = getSeekOnLoadPreference();
+
+ CuePointer pAudibleSound = pNewTrack->findCueByType(Cue::Type::AudibleSound);
+ double firstSound = Cue::kNoPosition;
+ if (pAudibleSound) {
+ firstSound = pAudibleSound->getPosition();
+ }
+
switch (seekOnLoadMode) {
- case SEEK_ON_LOAD_ZERO_POS:
- seekExact(0.0);
+ case SeekOnLoadMode::Beginning:
+ // This allows users to load tracks and have the needle-drop be maintained.
+ if (!(m_pVinylControlEnabled->get() &&
+ m_pVinylControlMode->get() == MIXXX_VCMODE_ABSOLUTE)) {
+ seekExact(0.0);
+ }
break;
- case SEEK_ON_LOAD_MAIN_CUE: {
- double cuePointPosition = cuePoint.getPosition();
- if (cuePointPosition != -1) {
- seekExact(cuePointPosition);
+ case SeekOnLoadMode::FirstSound:
+ if (firstSound != Cue::kNoPosition) {
+ seekExact(firstSound);
+ } else {
+ seekExact(0.0);
}
break;
- }
- case SEEK_ON_LOAD_INTRO_CUE:
- seekExact(m_pIntroStartPosition->get());
+ case SeekOnLoadMode::MainCue:
+ if (mainCuePoint.getPosition() != Cue::kNoPosition) {
+ seekExact(mainCuePoint.getPosition());
+ } else {
+ seekExact(0.0);
+ }
break;
- default:
- // Respect cue recall preference option.
- if (isCueRecallEnabled() && m_pCuePoint->get() != -1.0) {
- // If cue recall is ON and main cue point is set, seek to it.
- seekExact(m_pCuePoint->get());
- } else if (!(m_pVinylControlEnabled->get() &&
- m_pVinylControlMode->get() == MIXXX_VCMODE_ABSOLUTE)) {
- // Otherwise, seek to zero unless vinylcontrol is on and
- // set to absolute. This allows users to load tracks and
- // have the needle-drop be maintained.
+ case SeekOnLoadMode::IntroStart: {
+ double introStart = m_pIntroStartPosition->get();
+ if (introStart != Cue::kNoPosition) {
+ seekExact(introStart);
+ } else {
seekExact(0.0);
}
break;
}
+ default:
+ seekExact(0.0);
+ break;
+ }
}
void CueControl::cueUpdated() {
@@ -419,15 +429,16 @@ void CueControl::loadCuesFromTrack() {
return;
for (const CuePointer& pCue: m_pLoadedTrack->getCuePoints()) {
- if (!pLoadCue && pCue->getType() == Cue::LOAD) {
+ if (pCue->getType() == Cue::Type::MainCue) {
+ DEBUG_ASSERT(!pLoadCue); // There should be only one MainCue cue
pLoadCue = pCue;
- } else if (pCue->getType() == Cue::INTRO) {
- DEBUG_ASSERT(!pIntroCue); // There should be only one INTRO cue
+ } else if (pCue->getType() == Cue::Type::Intro) {
+ DEBUG_ASSERT(!pIntroCue); // There should be only one Intro cue
pIntroCue = pCue;
- } else if (pCue->getType() == Cue::OUTRO) {
- DEBUG_ASSERT(!pOutroCue); // There should be only one OUTRO cue
+ } else if (pCue->getType() == Cue::Type::Outro) {
+ DEBUG_ASSERT(!pOutroCue); // There should be only one Outro cue
pOutroCue = pCue;
- } else if (pCue->getType() == Cue::CUE && pCue->getHotCue() != -1) {
+ } else if (pCue->getType() == Cue::Type::HotCue && pCue->getHotCue() != Cue::kNoHotCue) {
int hotcue = pCue->getHotCue();
HotcueControl* pControl = m_hotcueControls.value(hotcue, NULL);
@@ -452,47 +463,43 @@ void CueControl::loadCuesFromTrack() {
}
}
- if (pLoadCue) {
- double position = pLoadCue->getPosition();
- Cue::CueSource source = pLoadCue->getSource();
-
- m_pCuePoint->set(quantizeCuePoint(position, source, QuantizeMode::ClosestBeat));
- } else {
- m_pCuePoint->set(-1.0);
- }
-
if (pIntroCue) {
double startPosition = pIntroCue->getPosition();
double endPosition = pIntroCue->getEndPosition();
- Cue::CueSource source = pIntroCue->getSource();
- m_pIntroStartPosition->set(quantizeCuePoint(startPosition, source, QuantizeMode::PreviousBeat));
- m_pIntroStartEnabled->forceSet(startPosition == -1.0 ? 0.0 : 1.0);
- m_pIntroEndPosition->set(quantizeCuePoint(endPosition, source, QuantizeMode::NextBeat));
- m_pIntroEndEnabled->forceSet(endPosition == -1.0 ? 0.0 : 1.0);
+ m_pIntroStartPosition->set(quantizeCuePoint(startPosition, QuantizeMode::PreviousBeat));
+ m_pIntroStartEnabled->forceSet(startPosition == Cue::kNoPosition ? 0.0 : 1.0);
+ m_pIntroEndPosition->set(quantizeCuePoint(endPosition, QuantizeMode::NextBeat));
+ m_pIntroEndEnabled->forceSet(endPosition == Cue::kNoPosition ? 0.0 : 1.0);
} else {
- m_pIntroStartPosition->set(-1.0);
+ m_pIntroStartPosition->set(Cue::kNoPosition);
m_pIntroStartEnabled->forceSet(0.0);
- m_pIntroEndPosition->set(-1.0);
+ m_pIntroEndPosition->set(Cue::kNoPosition);
m_pIntroEndEnabled->forceSet(0.0);
}
if (