From e23cbdf285952349a52a7e63348608e9bf81746c Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Sat, 27 Apr 2024 14:16:57 +0000 Subject: [PATCH 1/7] 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/7] 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/7] 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/7] 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(); From e69b72db61d6e61fa3a6682169ad1cd0ea91fb44 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Mon, 3 Aug 2026 14:14:36 +0200 Subject: [PATCH 5/7] DeckAttributes: Add TrackOrDeckAttributes as base class of DeckAttributes --- CMakeLists.txt | 1 + src/library/autodj/autodjprocessor.h | 1 + src/library/autodj/track/deckattributes.h | 24 +++++++-------- .../autodj/track/trackordeckattributes.cpp | 6 ++++ .../autodj/track/trackordeckattributes.h | 30 +++++++++++++++++++ 5 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 src/library/autodj/track/trackordeckattributes.cpp create mode 100644 src/library/autodj/track/trackordeckattributes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 69f85c2abbcb..8307fd85a37a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1389,6 +1389,7 @@ add_library( src/library/autodj/dlgautodj.cpp src/library/autodj/dlgautodj.ui src/library/autodj/track/deckattributes.cpp + src/library/autodj/track/trackordeckattributes.cpp src/library/banshee/bansheedbconnection.cpp src/library/banshee/bansheefeature.cpp src/library/banshee/bansheeplaylistmodel.cpp diff --git a/src/library/autodj/autodjprocessor.h b/src/library/autodj/autodjprocessor.h index d35701aed9ed..021b4039815e 100644 --- a/src/library/autodj/autodjprocessor.h +++ b/src/library/autodj/autodjprocessor.h @@ -10,6 +10,7 @@ #include "control/controlpushbutton.h" #include "control/pollingcontrolproxy.h" #include "library/autodj/track/deckattributes.h" +#include "library/autodj/track/trackordeckattributes.h" #include "library/playlisttablemodel.h" #include "preferences/usersettings.h" #include "track/track_decl.h" diff --git a/src/library/autodj/track/deckattributes.h b/src/library/autodj/track/deckattributes.h index 783426584bb3..82ee6363c5f9 100644 --- a/src/library/autodj/track/deckattributes.h +++ b/src/library/autodj/track/deckattributes.h @@ -1,15 +1,13 @@ #pragma once -#include "audio/frame.h" -#include "audio/types.h" #include "control/controlproxy.h" #include "engine/channels/enginechannel.h" -#include "track/track_decl.h" +#include "library/autodj/track/trackordeckattributes.h" class BaseTrackPlayer; /// Exposes the attributes of the track loaded in a certain player deck. -class DeckAttributes : public QObject { +class DeckAttributes : public TrackOrDeckAttributes { Q_OBJECT public: /// Special value for startPos that indicates the deck @@ -44,7 +42,7 @@ class DeckAttributes : public QObject { m_play.set(1.0); } - double playPosition() const { + double playPosition() const override { return m_playPos.get(); } @@ -60,35 +58,35 @@ class DeckAttributes : public QObject { m_repeat.set(enabled ? 1.0 : 0.0); } - mixxx::audio::FramePos introStartPosition() const { + mixxx::audio::FramePos introStartPosition() const override { return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_introStartPos.get()); } - mixxx::audio::FramePos introEndPosition() const { + mixxx::audio::FramePos introEndPosition() const override { return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_introEndPos.get()); } - mixxx::audio::FramePos outroStartPosition() const { + mixxx::audio::FramePos outroStartPosition() const override { return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_outroStartPos.get()); } - mixxx::audio::FramePos outroEndPosition() const { + mixxx::audio::FramePos outroEndPosition() const override { return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_outroEndPos.get()); } - mixxx::audio::SampleRate sampleRate() const { + mixxx::audio::SampleRate sampleRate() const override { return mixxx::audio::SampleRate::fromDouble(m_sampleRate.get()); } - mixxx::audio::FramePos trackEndPosition() const { + mixxx::audio::FramePos trackEndPosition() const override { return mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(m_trackSamples.get()); } - double rateRatio() const { + double rateRatio() const override { return m_rateRatio.get(); } - TrackPointer getLoadedTrack() const; + TrackPointer getLoadedTrack() const override; signals: void playChanged(DeckAttributes* pDeck, bool playing); diff --git a/src/library/autodj/track/trackordeckattributes.cpp b/src/library/autodj/track/trackordeckattributes.cpp new file mode 100644 index 000000000000..87b703cfb9f4 --- /dev/null +++ b/src/library/autodj/track/trackordeckattributes.cpp @@ -0,0 +1,6 @@ +#include "library/autodj/track/trackordeckattributes.h" + +#include "moc_trackordeckattributes.cpp" + +TrackOrDeckAttributes::~TrackOrDeckAttributes() { +} diff --git a/src/library/autodj/track/trackordeckattributes.h b/src/library/autodj/track/trackordeckattributes.h new file mode 100644 index 000000000000..6b4b154b4c04 --- /dev/null +++ b/src/library/autodj/track/trackordeckattributes.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +#include "audio/frame.h" +#include "audio/types.h" +#include "track/track_decl.h" + +/// Represents either a track in the Auto DJ queue, +/// or a player deck controlled by the Auto DJ processor. +class TrackOrDeckAttributes : public QObject { + Q_OBJECT + public: + virtual ~TrackOrDeckAttributes(); + + virtual mixxx::audio::FramePos introStartPosition() const = 0; + virtual mixxx::audio::FramePos introEndPosition() const = 0; + virtual mixxx::audio::FramePos outroStartPosition() const = 0; + virtual mixxx::audio::FramePos outroEndPosition() const = 0; + virtual mixxx::audio::SampleRate sampleRate() const = 0; + virtual mixxx::audio::FramePos trackEndPosition() const = 0; + virtual double playPosition() const = 0; + virtual double rateRatio() const = 0; + + virtual TrackPointer getLoadedTrack() const = 0; + + inline bool isEmpty() const { + return !getLoadedTrack(); + } +}; From d9db0a5f878da372e2600a88ce9aebdc2637f0a1 Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Mon, 3 Aug 2026 14:35:38 +0200 Subject: [PATCH 6/7] DeckAttributes: Move computed fade fields to TrackOrDeckAttributes --- src/library/autodj/autodjprocessor.cpp | 2 +- src/library/autodj/track/deckattributes.cpp | 4 ---- src/library/autodj/track/deckattributes.h | 15 +-------------- .../autodj/track/trackordeckattributes.cpp | 7 +++++++ src/library/autodj/track/trackordeckattributes.h | 14 ++++++++++++++ 5 files changed, 23 insertions(+), 19 deletions(-) diff --git a/src/library/autodj/autodjprocessor.cpp b/src/library/autodj/autodjprocessor.cpp index 7893b3b5f674..c0b8f6b44ef9 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 = DeckAttributes::kKeepPosition; +constexpr double kKeepPosition = TrackOrDeckAttributes::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 78898e03016d..c9819182c862 100644 --- a/src/library/autodj/track/deckattributes.cpp +++ b/src/library/autodj/track/deckattributes.cpp @@ -7,10 +7,6 @@ DeckAttributes::DeckAttributes(int index, BaseTrackPlayer* pPlayer) : index(index), group(pPlayer->getGroup()), - startPos(DeckAttributes::kKeepPosition), - fadeBeginPos(1.0), - fadeEndPos(1.0), - isFromDeck(false), loading(false), m_orientation(group, "orientation"), m_playPos(group, "playposition"), diff --git a/src/library/autodj/track/deckattributes.h b/src/library/autodj/track/deckattributes.h index 82ee6363c5f9..5dbd7be1f2dd 100644 --- a/src/library/autodj/track/deckattributes.h +++ b/src/library/autodj/track/deckattributes.h @@ -10,16 +10,7 @@ class BaseTrackPlayer; class DeckAttributes : public TrackOrDeckAttributes { Q_OBJECT public: - /// Special value for startPos that indicates the deck - /// 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); + DeckAttributes(int index, BaseTrackPlayer* pPlayer); virtual ~DeckAttributes(); bool isLeft() const { @@ -117,10 +108,6 @@ class DeckAttributes : public TrackOrDeckAttributes { 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: diff --git a/src/library/autodj/track/trackordeckattributes.cpp b/src/library/autodj/track/trackordeckattributes.cpp index 87b703cfb9f4..d3c797890fed 100644 --- a/src/library/autodj/track/trackordeckattributes.cpp +++ b/src/library/autodj/track/trackordeckattributes.cpp @@ -2,5 +2,12 @@ #include "moc_trackordeckattributes.cpp" +TrackOrDeckAttributes::TrackOrDeckAttributes() + : startPos(TrackOrDeckAttributes::kKeepPosition), + fadeBeginPos(1.0), + fadeEndPos(1.0), + isFromDeck(false) { +} + TrackOrDeckAttributes::~TrackOrDeckAttributes() { } diff --git a/src/library/autodj/track/trackordeckattributes.h b/src/library/autodj/track/trackordeckattributes.h index 6b4b154b4c04..2c8b3823835a 100644 --- a/src/library/autodj/track/trackordeckattributes.h +++ b/src/library/autodj/track/trackordeckattributes.h @@ -11,6 +11,15 @@ class TrackOrDeckAttributes : 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; + + /// Special value for startPos that indicates a track + /// should be skipped because it is too short. + static constexpr double kSkipToNextTrack = -2.0; + + TrackOrDeckAttributes(); virtual ~TrackOrDeckAttributes(); virtual mixxx::audio::FramePos introStartPosition() const = 0; @@ -27,4 +36,9 @@ class TrackOrDeckAttributes : public QObject { inline bool isEmpty() const { return !getLoadedTrack(); } + + double startPos; // Set for toDeck + double fadeBeginPos; // Set for fromDeck + double fadeEndPos; // Set for fromDeck + bool isFromDeck; }; From d9feb198f4f46a6e61e25467b441eb9f7367bf8b Mon Sep 17 00:00:00 2001 From: Lukas Waslowski Date: Mon, 3 Aug 2026 14:26:08 +0200 Subject: [PATCH 7/7] DeckAttributes: Add TrackAttributes for calculating the transition time between tracks --- CMakeLists.txt | 1 + src/library/autodj/autodjprocessor.h | 1 + src/library/autodj/track/trackattributes.cpp | 64 ++++++++++++++++++++ src/library/autodj/track/trackattributes.h | 26 ++++++++ 4 files changed, 92 insertions(+) create mode 100644 src/library/autodj/track/trackattributes.cpp create mode 100644 src/library/autodj/track/trackattributes.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 8307fd85a37a..9a2a3a912847 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1389,6 +1389,7 @@ add_library( src/library/autodj/dlgautodj.cpp src/library/autodj/dlgautodj.ui src/library/autodj/track/deckattributes.cpp + src/library/autodj/track/trackattributes.cpp src/library/autodj/track/trackordeckattributes.cpp src/library/banshee/bansheedbconnection.cpp src/library/banshee/bansheefeature.cpp diff --git a/src/library/autodj/autodjprocessor.h b/src/library/autodj/autodjprocessor.h index 021b4039815e..a1cd35865460 100644 --- a/src/library/autodj/autodjprocessor.h +++ b/src/library/autodj/autodjprocessor.h @@ -10,6 +10,7 @@ #include "control/controlpushbutton.h" #include "control/pollingcontrolproxy.h" #include "library/autodj/track/deckattributes.h" +#include "library/autodj/track/trackattributes.h" #include "library/autodj/track/trackordeckattributes.h" #include "library/playlisttablemodel.h" #include "preferences/usersettings.h" diff --git a/src/library/autodj/track/trackattributes.cpp b/src/library/autodj/track/trackattributes.cpp new file mode 100644 index 000000000000..bd579eb3af33 --- /dev/null +++ b/src/library/autodj/track/trackattributes.cpp @@ -0,0 +1,64 @@ +#include "library/autodj/track/trackattributes.h" + +#include "moc_trackattributes.cpp" +#include "track/track.h" + +TrackAttributes::TrackAttributes(TrackPointer pTrack) + : m_pTrack(pTrack) { +} + +mixxx::audio::FramePos TrackAttributes::introStartPosition() const { + auto pIntro = m_pTrack->findCueByType(mixxx::CueType::Intro); + if (pIntro) { + return pIntro->getPosition(); + } + return mixxx::audio::FramePos(); +} + +mixxx::audio::FramePos TrackAttributes::introEndPosition() const { + auto pIntro = m_pTrack->findCueByType(mixxx::CueType::Intro); + if (pIntro) { + return pIntro->getEndPosition(); + } + return mixxx::audio::FramePos(); +} + +mixxx::audio::FramePos TrackAttributes::outroStartPosition() const { + auto pOutro = m_pTrack->findCueByType(mixxx::CueType::Outro); + if (pOutro) { + return pOutro->getPosition(); + } + return mixxx::audio::FramePos(); +} + +mixxx::audio::FramePos TrackAttributes::outroEndPosition() const { + auto pOutro = m_pTrack->findCueByType(mixxx::CueType::Outro); + if (pOutro) { + return pOutro->getEndPosition(); + } + return mixxx::audio::FramePos(); +} + +mixxx::audio::SampleRate TrackAttributes::sampleRate() const { + return m_pTrack->getSampleRate(); +} + +double TrackAttributes::playPosition() const { + return 0.0; +} + +double TrackAttributes::rateRatio() const { + return 1.0; +} + +mixxx::audio::FramePos TrackAttributes::trackEndPosition() const { + // Instead of actually loading the file, we simply infer + // the number of frames from duration and sample rate stored + // in the database. This isn't entirely accurate due to + // rounding errors, but more than accurate enough for + // estimating the remaining play time of the AutoDJ queue. + double approxNumSamples = + m_pTrack->getSampleRate() * m_pTrack->getDuration(); + + return mixxx::audio::FramePos(approxNumSamples); +} diff --git a/src/library/autodj/track/trackattributes.h b/src/library/autodj/track/trackattributes.h new file mode 100644 index 000000000000..f320818d363f --- /dev/null +++ b/src/library/autodj/track/trackattributes.h @@ -0,0 +1,26 @@ +#pragma once + +#include "library/autodj/track/trackordeckattributes.h" + +/// Exposes the attributes of a track from the Auto DJ queue. +class TrackAttributes : public TrackOrDeckAttributes { + Q_OBJECT + public: + TrackAttributes(TrackPointer pTrack); + + virtual mixxx::audio::FramePos introStartPosition() const override; + virtual mixxx::audio::FramePos introEndPosition() const override; + virtual mixxx::audio::FramePos outroStartPosition() const override; + virtual mixxx::audio::FramePos outroEndPosition() const override; + virtual mixxx::audio::SampleRate sampleRate() const override; + virtual mixxx::audio::FramePos trackEndPosition() const override; + virtual double playPosition() const override; + virtual double rateRatio() const override; + + TrackPointer getLoadedTrack() const override { + return m_pTrack; + } + + private: + TrackPointer m_pTrack; +};