From e23cbdf285952349a52a7e63348608e9bf81746c Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Sat, 27 Apr 2024 14:16:57 +0000 Subject: [PATCH 1/4] AutoDJProcessor: Move DeckAttributes into its own file This is a first step in generalizing the transition logic in AutoDJProcessor to enable it to also be applied to tracks in the queue instead of just the current decks. The code of DeckAttributes has not been changed at all (yet), and is simply copy-pasted from autodjprocessor.(cpp|h). --- CMakeLists.txt | 1 + src/library/autodj/autodjprocessor.cpp | 91 -------------- src/library/autodj/autodjprocessor.h | 126 +------------------ src/library/autodj/track/deckattributes.cpp | 96 ++++++++++++++ src/library/autodj/track/deckattributes.h | 132 ++++++++++++++++++++ 5 files changed, 230 insertions(+), 216 deletions(-) create mode 100644 src/library/autodj/track/deckattributes.cpp create mode 100644 src/library/autodj/track/deckattributes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 0d81e2ff824d..69f85c2abbcb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1388,6 +1388,7 @@ add_library( src/library/autodj/autodjprocessor.cpp src/library/autodj/dlgautodj.cpp src/library/autodj/dlgautodj.ui + src/library/autodj/track/deckattributes.cpp src/library/banshee/bansheedbconnection.cpp src/library/banshee/bansheefeature.cpp src/library/banshee/bansheeplaylistmodel.cpp diff --git a/src/library/autodj/autodjprocessor.cpp b/src/library/autodj/autodjprocessor.cpp index 466e75ab1f4d..1ccfd50cc9d7 100644 --- a/src/library/autodj/autodjprocessor.cpp +++ b/src/library/autodj/autodjprocessor.cpp @@ -21,97 +21,6 @@ constexpr double kMinimumTrackDurationSec = 0.2; constexpr bool sDebug = false; } // anonymous namespace -DeckAttributes::DeckAttributes(int index, - BaseTrackPlayer* pPlayer) - : index(index), - group(pPlayer->getGroup()), - startPos(kKeepPosition), - fadeBeginPos(1.0), - fadeEndPos(1.0), - isFromDeck(false), - loading(false), - m_orientation(group, "orientation"), - m_playPos(group, "playposition"), - m_play(group, "play"), - m_repeat(group, "repeat"), - m_introStartPos(group, "intro_start_position"), - m_introEndPos(group, "intro_end_position"), - m_outroStartPos(group, "outro_start_position"), - m_outroEndPos(group, "outro_end_position"), - m_trackSamples(group, "track_samples"), - m_sampleRate(group, "track_samplerate"), - m_rateRatio(group, "rate_ratio"), - m_pPlayer(pPlayer) { - connect(m_pPlayer, &BaseTrackPlayer::newTrackLoaded, - this, &DeckAttributes::slotTrackLoaded); - connect(m_pPlayer, &BaseTrackPlayer::loadingTrack, - this, &DeckAttributes::slotLoadingTrack); - connect(m_pPlayer, &BaseTrackPlayer::playerEmpty, - this, &DeckAttributes::slotPlayerEmpty); - m_playPos.connectValueChanged(this, &DeckAttributes::slotPlayPosChanged); - m_play.connectValueChanged(this, &DeckAttributes::slotPlayChanged); - m_introStartPos.connectValueChanged(this, &DeckAttributes::slotIntroStartPositionChanged); - m_introEndPos.connectValueChanged(this, &DeckAttributes::slotIntroEndPositionChanged); - m_outroStartPos.connectValueChanged(this, &DeckAttributes::slotOutroStartPositionChanged); - m_outroEndPos.connectValueChanged(this, &DeckAttributes::slotOutroEndPositionChanged); - m_rateRatio.connectValueChanged(this, &DeckAttributes::slotRateChanged); - m_orientation.connectValueChanged(this, &DeckAttributes::slotOrientationChanged); -} - -DeckAttributes::~DeckAttributes() { -} - -void DeckAttributes::slotPlayChanged(double v) { - emit playChanged(this, v > 0.0); -} - -void DeckAttributes::slotPlayPosChanged(double v) { - emit playPositionChanged(this, v); -} - -void DeckAttributes::slotIntroStartPositionChanged(double v) { - emit introStartPositionChanged(this, v); -} - -void DeckAttributes::slotIntroEndPositionChanged(double v) { - emit introEndPositionChanged(this, v); -} - -void DeckAttributes::slotOutroStartPositionChanged(double v) { - emit outroStartPositionChanged(this, v); -} - -void DeckAttributes::slotOutroEndPositionChanged(double v) { - emit outroEndPositionChanged(this, v); -} - -void DeckAttributes::slotTrackLoaded(TrackPointer pTrack) { - emit trackLoaded(this, pTrack); -} - -void DeckAttributes::slotLoadingTrack(TrackPointer pNewTrack, TrackPointer pOldTrack) { - //qDebug() << "DeckAttributes::slotLoadingTrack"; - emit loadingTrack(this, pNewTrack, pOldTrack); -} - -void DeckAttributes::slotPlayerEmpty() { - emit playerEmpty(this); -} - -void DeckAttributes::slotRateChanged(double v) { - Q_UNUSED(v); - emit rateChanged(this); -} - -void DeckAttributes::slotOrientationChanged(double v) { - Q_UNUSED(v); - emit orientationChanged(this); -} - -TrackPointer DeckAttributes::getLoadedTrack() const { - return m_pPlayer != nullptr ? m_pPlayer->getLoadedTrack() : TrackPointer(); -} - AutoDJProcessor::AutoDJProcessor( QObject* pParent, UserSettingsPointer pConfig, diff --git a/src/library/autodj/autodjprocessor.h b/src/library/autodj/autodjprocessor.h index 61e7dc9acc50..d35701aed9ed 100644 --- a/src/library/autodj/autodjprocessor.h +++ b/src/library/autodj/autodjprocessor.h @@ -9,7 +9,7 @@ #include "control/controlproxy.h" #include "control/controlpushbutton.h" #include "control/pollingcontrolproxy.h" -#include "engine/channels/enginechannel.h" +#include "library/autodj/track/deckattributes.h" #include "library/playlisttablemodel.h" #include "preferences/usersettings.h" #include "track/track_decl.h" @@ -18,132 +18,8 @@ class TrackCollectionManager; class PlayerManagerInterface; -class BaseTrackPlayer; typedef QList QModelIndexList; -class DeckAttributes : public QObject { - Q_OBJECT - public: - DeckAttributes(int index, - BaseTrackPlayer* pPlayer); - virtual ~DeckAttributes(); - - bool isLeft() const { - return m_orientation.get() == static_cast(EngineChannel::LEFT); - } - - bool isRight() const { - return m_orientation.get() == static_cast(EngineChannel::RIGHT); - } - - bool isPlaying() const { - return m_play.toBool(); - } - - void stop() { - m_play.set(0.0); - } - - void play() { - m_play.set(1.0); - } - - double playPosition() const { - return m_playPos.get(); - } - - void setPlayPosition(double playpos) { - m_playPos.set(playpos); - } - - bool isRepeat() const { - return m_repeat.toBool(); - } - - void setRepeat(bool enabled) { - m_repeat.set(enabled ? 1.0 : 0.0); - } - - mixxx::audio::FramePos introStartPosition() const { - return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_introStartPos.get()); - } - - mixxx::audio::FramePos introEndPosition() const { - return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_introEndPos.get()); - } - - mixxx::audio::FramePos outroStartPosition() const { - return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_outroStartPos.get()); - } - - mixxx::audio::FramePos outroEndPosition() const { - return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_outroEndPos.get()); - } - - mixxx::audio::SampleRate sampleRate() const { - return mixxx::audio::SampleRate::fromDouble(m_sampleRate.get()); - } - - mixxx::audio::FramePos trackEndPosition() const { - return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_trackSamples.get()); - } - - double rateRatio() const { - return m_rateRatio.get(); - } - - TrackPointer getLoadedTrack() const; - - signals: - void playChanged(DeckAttributes* pDeck, bool playing); - void playPositionChanged(DeckAttributes* pDeck, double playPosition); - void introStartPositionChanged(DeckAttributes* pDeck, double introStartPosition); - void introEndPositionChanged(DeckAttributes* pDeck, double introEndPosition); - void outroStartPositionChanged(DeckAttributes* pDeck, double outtroStartPosition); - void outroEndPositionChanged(DeckAttributes* pDeck, double outroEndPosition); - void trackLoaded(DeckAttributes* pDeck, TrackPointer pTrack); - void loadingTrack(DeckAttributes* pDeck, TrackPointer pNewTrack, TrackPointer pOldTrack); - void playerEmpty(DeckAttributes* pDeck); - void rateChanged(DeckAttributes* pDeck); - void orientationChanged(DeckAttributes* pDeck); - - private slots: - void slotPlayPosChanged(double v); - void slotPlayChanged(double v); - void slotIntroStartPositionChanged(double v); - void slotIntroEndPositionChanged(double v); - void slotOutroStartPositionChanged(double v); - void slotOutroEndPositionChanged(double v); - void slotTrackLoaded(TrackPointer pTrack); - void slotLoadingTrack(TrackPointer pNewTrack, TrackPointer pOldTrack); - void slotPlayerEmpty(); - void slotRateChanged(double v); - void slotOrientationChanged(double v); - - public: - int index; - QString group; - double startPos; // Set in toDeck nature - double fadeBeginPos; // set in fromDeck nature - double fadeEndPos; // set in fromDeck nature - bool isFromDeck; - bool loading; // The data is inconsistent during loading a deck - - private: - ControlProxy m_orientation; - ControlProxy m_playPos; - ControlProxy m_play; - ControlProxy m_repeat; - ControlProxy m_introStartPos; - ControlProxy m_introEndPos; - ControlProxy m_outroStartPos; - ControlProxy m_outroEndPos; - ControlProxy m_trackSamples; - ControlProxy m_sampleRate; - ControlProxy m_rateRatio; - BaseTrackPlayer* m_pPlayer; -}; - class AutoDJProcessor : public QObject { Q_OBJECT public: diff --git a/src/library/autodj/track/deckattributes.cpp b/src/library/autodj/track/deckattributes.cpp new file mode 100644 index 000000000000..1f3563dce45d --- /dev/null +++ b/src/library/autodj/track/deckattributes.cpp @@ -0,0 +1,96 @@ +#include "library/autodj/track/deckattributes.h" + +#include "mixer/basetrackplayer.h" +#include "moc_deckattributes.cpp" + +namespace { +constexpr double kKeepPosition = -1.0; +} // anonymous namespace + +DeckAttributes::DeckAttributes(int index, + BaseTrackPlayer* pPlayer) + : index(index), + group(pPlayer->getGroup()), + startPos(kKeepPosition), + fadeBeginPos(1.0), + fadeEndPos(1.0), + isFromDeck(false), + loading(false), + m_orientation(group, "orientation"), + m_playPos(group, "playposition"), + m_play(group, "play"), + m_repeat(group, "repeat"), + m_introStartPos(group, "intro_start_position"), + m_introEndPos(group, "intro_end_position"), + m_outroStartPos(group, "outro_start_position"), + m_outroEndPos(group, "outro_end_position"), + m_trackSamples(group, "track_samples"), + m_sampleRate(group, "track_samplerate"), + m_rateRatio(group, "rate_ratio"), + m_pPlayer(pPlayer) { + connect(m_pPlayer, &BaseTrackPlayer::newTrackLoaded, this, &DeckAttributes::slotTrackLoaded); + connect(m_pPlayer, &BaseTrackPlayer::loadingTrack, this, &DeckAttributes::slotLoadingTrack); + connect(m_pPlayer, &BaseTrackPlayer::playerEmpty, this, &DeckAttributes::slotPlayerEmpty); + m_playPos.connectValueChanged(this, &DeckAttributes::slotPlayPosChanged); + m_play.connectValueChanged(this, &DeckAttributes::slotPlayChanged); + m_introStartPos.connectValueChanged(this, &DeckAttributes::slotIntroStartPositionChanged); + m_introEndPos.connectValueChanged(this, &DeckAttributes::slotIntroEndPositionChanged); + m_outroStartPos.connectValueChanged(this, &DeckAttributes::slotOutroStartPositionChanged); + m_outroEndPos.connectValueChanged(this, &DeckAttributes::slotOutroEndPositionChanged); + m_rateRatio.connectValueChanged(this, &DeckAttributes::slotRateChanged); + m_orientation.connectValueChanged(this, &DeckAttributes::slotOrientationChanged); +} + +DeckAttributes::~DeckAttributes() { +} + +void DeckAttributes::slotPlayChanged(double v) { + emit playChanged(this, v > 0.0); +} + +void DeckAttributes::slotPlayPosChanged(double v) { + emit playPositionChanged(this, v); +} + +void DeckAttributes::slotIntroStartPositionChanged(double v) { + emit introStartPositionChanged(this, v); +} + +void DeckAttributes::slotIntroEndPositionChanged(double v) { + emit introEndPositionChanged(this, v); +} + +void DeckAttributes::slotOutroStartPositionChanged(double v) { + emit outroStartPositionChanged(this, v); +} + +void DeckAttributes::slotOutroEndPositionChanged(double v) { + emit outroEndPositionChanged(this, v); +} + +void DeckAttributes::slotTrackLoaded(TrackPointer pTrack) { + emit trackLoaded(this, pTrack); +} + +void DeckAttributes::slotLoadingTrack(TrackPointer pNewTrack, TrackPointer pOldTrack) { + // qDebug() << "DeckAttributes::slotLoadingTrack"; + emit loadingTrack(this, pNewTrack, pOldTrack); +} + +void DeckAttributes::slotPlayerEmpty() { + emit playerEmpty(this); +} + +void DeckAttributes::slotRateChanged(double v) { + Q_UNUSED(v); + emit rateChanged(this); +} + +void DeckAttributes::slotOrientationChanged(double v) { + Q_UNUSED(v); + emit orientationChanged(this); +} + +TrackPointer DeckAttributes::getLoadedTrack() const { + return m_pPlayer != nullptr ? m_pPlayer->getLoadedTrack() : TrackPointer(); +} diff --git a/src/library/autodj/track/deckattributes.h b/src/library/autodj/track/deckattributes.h new file mode 100644 index 000000000000..2f00bb378853 --- /dev/null +++ b/src/library/autodj/track/deckattributes.h @@ -0,0 +1,132 @@ +#pragma once + +#include "audio/frame.h" +#include "audio/types.h" +#include "control/controlproxy.h" +#include "engine/channels/enginechannel.h" +#include "track/track_decl.h" + +class BaseTrackPlayer; + +class DeckAttributes : public QObject { + Q_OBJECT + public: + DeckAttributes(int index, + BaseTrackPlayer* pPlayer); + virtual ~DeckAttributes(); + + bool isLeft() const { + return m_orientation.get() == static_cast(EngineChannel::LEFT); + } + + bool isRight() const { + return m_orientation.get() == static_cast(EngineChannel::RIGHT); + } + + bool isPlaying() const { + return m_play.toBool(); + } + + void stop() { + m_play.set(0.0); + } + + void play() { + m_play.set(1.0); + } + + double playPosition() const { + return m_playPos.get(); + } + + void setPlayPosition(double playpos) { + m_playPos.set(playpos); + } + + bool isRepeat() const { + return m_repeat.toBool(); + } + + void setRepeat(bool enabled) { + m_repeat.set(enabled ? 1.0 : 0.0); + } + + mixxx::audio::FramePos introStartPosition() const { + return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_introStartPos.get()); + } + + mixxx::audio::FramePos introEndPosition() const { + return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_introEndPos.get()); + } + + mixxx::audio::FramePos outroStartPosition() const { + return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_outroStartPos.get()); + } + + mixxx::audio::FramePos outroEndPosition() const { + return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_outroEndPos.get()); + } + + mixxx::audio::SampleRate sampleRate() const { + return mixxx::audio::SampleRate::fromDouble(m_sampleRate.get()); + } + + mixxx::audio::FramePos trackEndPosition() const { + return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_trackSamples.get()); + } + + double rateRatio() const { + return m_rateRatio.get(); + } + + TrackPointer getLoadedTrack() const; + + signals: + void playChanged(DeckAttributes* pDeck, bool playing); + void playPositionChanged(DeckAttributes* pDeck, double playPosition); + void introStartPositionChanged(DeckAttributes* pDeck, double introStartPosition); + void introEndPositionChanged(DeckAttributes* pDeck, double introEndPosition); + void outroStartPositionChanged(DeckAttributes* pDeck, double outtroStartPosition); + void outroEndPositionChanged(DeckAttributes* pDeck, double outroEndPosition); + void trackLoaded(DeckAttributes* pDeck, TrackPointer pTrack); + void loadingTrack(DeckAttributes* pDeck, TrackPointer pNewTrack, TrackPointer pOldTrack); + void playerEmpty(DeckAttributes* pDeck); + void rateChanged(DeckAttributes* pDeck); + void orientationChanged(DeckAttributes* pDeck); + + private slots: + void slotPlayPosChanged(double v); + void slotPlayChanged(double v); + void slotIntroStartPositionChanged(double v); + void slotIntroEndPositionChanged(double v); + void slotOutroStartPositionChanged(double v); + void slotOutroEndPositionChanged(double v); + void slotTrackLoaded(TrackPointer pTrack); + void slotLoadingTrack(TrackPointer pNewTrack, TrackPointer pOldTrack); + void slotPlayerEmpty(); + void slotRateChanged(double v); + void slotOrientationChanged(double v); + + public: + int index; + QString group; + double startPos; // Set in toDeck nature + double fadeBeginPos; // set in fromDeck nature + double fadeEndPos; // set in fromDeck nature + bool isFromDeck; + bool loading; // The data is inconsistent during loading a deck + + private: + ControlProxy m_orientation; + ControlProxy m_playPos; + ControlProxy m_play; + ControlProxy m_repeat; + ControlProxy m_introStartPos; + ControlProxy m_introEndPos; + ControlProxy m_outroStartPos; + ControlProxy m_outroEndPos; + ControlProxy m_trackSamples; + ControlProxy m_sampleRate; + ControlProxy m_rateRatio; + BaseTrackPlayer* m_pPlayer; +}; From e0e698558e3bf257cbbebf9ed59a1715abc1cdfb Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Tue, 4 Aug 2026 13:00:30 +0000 Subject: [PATCH 2/4] AutoDJProcessor: Move kKeepPosition to DeckAttributes::kKeepPosition --- src/library/autodj/autodjprocessor.cpp | 2 +- src/library/autodj/track/deckattributes.cpp | 6 +----- src/library/autodj/track/deckattributes.h | 4 ++++ 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/library/autodj/autodjprocessor.cpp b/src/library/autodj/autodjprocessor.cpp index 1ccfd50cc9d7..7893b3b5f674 100644 --- a/src/library/autodj/autodjprocessor.cpp +++ b/src/library/autodj/autodjprocessor.cpp @@ -13,7 +13,7 @@ const QString kControlGroup = QStringLiteral("[AutoDJ]"); const char* kTransitionPreferenceName = "Transition"; const char* kTransitionModePreferenceName = "TransitionMode"; constexpr double kTransitionPreferenceDefault = 10.0; -constexpr double kKeepPosition = -1.0; +constexpr double kKeepPosition = DeckAttributes::kKeepPosition; // A track needs to be longer than two callbacks to not stop AutoDJ constexpr double kMinimumTrackDurationSec = 0.2; diff --git a/src/library/autodj/track/deckattributes.cpp b/src/library/autodj/track/deckattributes.cpp index 1f3563dce45d..78898e03016d 100644 --- a/src/library/autodj/track/deckattributes.cpp +++ b/src/library/autodj/track/deckattributes.cpp @@ -3,15 +3,11 @@ #include "mixer/basetrackplayer.h" #include "moc_deckattributes.cpp" -namespace { -constexpr double kKeepPosition = -1.0; -} // anonymous namespace - DeckAttributes::DeckAttributes(int index, BaseTrackPlayer* pPlayer) : index(index), group(pPlayer->getGroup()), - startPos(kKeepPosition), + startPos(DeckAttributes::kKeepPosition), fadeBeginPos(1.0), fadeEndPos(1.0), isFromDeck(false), diff --git a/src/library/autodj/track/deckattributes.h b/src/library/autodj/track/deckattributes.h index 2f00bb378853..b5690865b44d 100644 --- a/src/library/autodj/track/deckattributes.h +++ b/src/library/autodj/track/deckattributes.h @@ -11,6 +11,10 @@ class BaseTrackPlayer; class DeckAttributes : public QObject { Q_OBJECT public: + /// Special value for startPos that indicates the deck + /// should start playing from its current position. + static constexpr double kKeepPosition = -1.0; + DeckAttributes(int index, BaseTrackPlayer* pPlayer); virtual ~DeckAttributes(); From 905de28add10b9ba9949d62a9cb22af254e952ea Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Mon, 3 Aug 2026 14:02:30 +0200 Subject: [PATCH 3/4] AutoDJProcessor: Add documentation comment to DeckAttributes class --- src/library/autodj/track/deckattributes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/library/autodj/track/deckattributes.h b/src/library/autodj/track/deckattributes.h index b5690865b44d..b492def6b666 100644 --- a/src/library/autodj/track/deckattributes.h +++ b/src/library/autodj/track/deckattributes.h @@ -8,6 +8,7 @@ class BaseTrackPlayer; +/// Exposes the attributes of the track loaded in a certain player deck. class DeckAttributes : public QObject { Q_OBJECT public: From 3839b3466a3b6af18d73b48894b91c824f823102 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Sun, 9 Aug 2026 20:52:50 +0200 Subject: [PATCH 4/4] DeckAttributes: Add DeckAttributes::kSkipToNextTrack for use in AutoDJProcessor --- src/library/autodj/track/deckattributes.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/library/autodj/track/deckattributes.h b/src/library/autodj/track/deckattributes.h index b492def6b666..783426584bb3 100644 --- a/src/library/autodj/track/deckattributes.h +++ b/src/library/autodj/track/deckattributes.h @@ -16,6 +16,10 @@ class DeckAttributes : public QObject { /// should start playing from its current position. static constexpr double kKeepPosition = -1.0; + /// Special value for startPos that indicates a track + /// should be skipped because it is too short. + static constexpr double kSkipToNextTrack = -2.0; + DeckAttributes(int index, BaseTrackPlayer* pPlayer); virtual ~DeckAttributes();