diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6a539cef4eb4..133e3c2ce0e1 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -44,7 +44,7 @@ jobs:
RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY: ${{ secrets.RRYAN_AT_MIXXX_DOT_ORG_GPG_PRIVATE_KEY }}
sync:
- if: ${{ github.ref != 'refs/heads/main' }} && ${{ github.repository == 'mixxxdj/mixxx' }}
+ if: ${{ github.ref != 'refs/heads/main' && github.repository == 'mixxxdj/mixxx' }}
uses: ./.github/workflows/sync_branches.yml
secrets:
MIXXX_BRANCH_SYNC_PAT: ${{ secrets.MIXXX_BRANCH_SYNC_PAT }}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8d6204845c62..205a5c06a1b3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5045,7 +5045,7 @@ if(NOT CPACK_DEBIAN_PACKAGE_RELEASE)
set(CPACK_DEBIAN_PACKAGE_RELEASE 1)
endif()
-set(CPACK_DEBIAN_DISTRIBUTION_RELEASES noble oracular plucky questing)
+set(CPACK_DEBIAN_DISTRIBUTION_RELEASES noble plucky questing)
set(CPACK_DEBIAN_SOURCE_DIR ${CMAKE_SOURCE_DIR})
set(
CPACK_DEBIAN_UPLOAD_PPA_SCRIPT
diff --git a/res/translations/mixxx_fr.ts b/res/translations/mixxx_fr.ts
index d6e7afd382ad..cd4cbd3d31b3 100644
--- a/res/translations/mixxx_fr.ts
+++ b/res/translations/mixxx_fr.ts
@@ -3763,7 +3763,7 @@ traceĀ : ci-dessus + messages de profilage
Auto DJ Track Source
- Auto DJ Source de piste
+ Auto DJ source de piste
diff --git a/src/engine/controls/ratecontrol.cpp b/src/engine/controls/ratecontrol.cpp
index af0979bc03b1..7a889d62bb00 100644
--- a/src/engine/controls/ratecontrol.cpp
+++ b/src/engine/controls/ratecontrol.cpp
@@ -628,3 +628,10 @@ void RateControl::notifyWrapAround(mixxx::audio::FramePos triggerPos,
void RateControl::notifySeek(mixxx::audio::FramePos position) {
m_pScratchController->notifySeek(position);
}
+
+void RateControl::resetPositionScratchController() {
+ // Resets the scratch state to avoid engine freeze due to insanley high rate
+ // reported on track load while scratching.
+ // https://github.com/mixxxdj/mixxx/issues/15082
+ m_pScratchController->reset();
+}
diff --git a/src/engine/controls/ratecontrol.h b/src/engine/controls/ratecontrol.h
index 594a0824d70d..ed4c61084558 100644
--- a/src/engine/controls/ratecontrol.h
+++ b/src/engine/controls/ratecontrol.h
@@ -77,6 +77,7 @@ class RateControl : public EngineControl {
void notifyWrapAround(mixxx::audio::FramePos triggerPos,
mixxx::audio::FramePos targetPos);
void notifySeek(mixxx::audio::FramePos position) override;
+ void resetPositionScratchController();
public slots:
void slotRateRangeChanged(double);
diff --git a/src/engine/enginebuffer.cpp b/src/engine/enginebuffer.cpp
index 9461197e4d5c..50f31f0e614c 100644
--- a/src/engine/enginebuffer.cpp
+++ b/src/engine/enginebuffer.cpp
@@ -648,13 +648,19 @@ void EngineBuffer::ejectTrack() {
if (pOldTrack) {
notifyTrackLoaded(TrackPointer(), pOldTrack);
+ } else {
+ // When not invoking notifyTrackLoaded() call this separately
+ m_pRateControl->resetPositionScratchController();
}
+
m_iTrackLoading = 0;
m_pChannelToCloneFrom = nullptr;
}
void EngineBuffer::notifyTrackLoaded(
TrackPointer pNewTrack, TrackPointer pOldTrack) {
+ m_pRateControl->resetPositionScratchController();
+
if (pOldTrack) {
disconnect(
pOldTrack.get(),
diff --git a/src/engine/positionscratchcontroller.cpp b/src/engine/positionscratchcontroller.cpp
index 9ca0b54dc0bc..3f1067714381 100644
--- a/src/engine/positionscratchcontroller.cpp
+++ b/src/engine/positionscratchcontroller.cpp
@@ -329,3 +329,13 @@ void PositionScratchController::notifySeek(mixxx::audio::FramePos position) {
// distance traveled in m_samplePosDeltaSum
m_seekSamplePos = newPos;
}
+
+void PositionScratchController::reset() {
+ // Resets the scratch state to avoid engine freeze due to insanley high rate
+ // reported on track load while scratching.
+ // https://github.com/mixxxdj/mixxx/issues/15082
+ m_pScratchEnable->set(0.0);
+ m_isScratching = false;
+ m_inertiaEnabled = false;
+ m_rate = 0;
+}
diff --git a/src/engine/positionscratchcontroller.h b/src/engine/positionscratchcontroller.h
index 9cd57632b7bb..688851cd8143 100644
--- a/src/engine/positionscratchcontroller.h
+++ b/src/engine/positionscratchcontroller.h
@@ -33,6 +33,7 @@ class PositionScratchController : public QObject {
return m_rate;
}
void notifySeek(mixxx::audio::FramePos position);
+ void reset();
private slots:
void slotUpdateFilterParameters(double sampleRate);
diff --git a/src/library/dlgtrackinfomulti.cpp b/src/library/dlgtrackinfomulti.cpp
index 7977dd55bc71..b1918b63364a 100644
--- a/src/library/dlgtrackinfomulti.cpp
+++ b/src/library/dlgtrackinfomulti.cpp
@@ -314,7 +314,10 @@ void DlgTrackInfoMulti::loadTracks(const QList& pTracks) {
m_pLoadedTracks.clear();
}
for (const auto& pTrack : pTracks) {
- m_pLoadedTracks.insert(pTrack.get()->getId(), pTrack);
+ if (pTrack.get()) {
+ m_pLoadedTracks.insert(pTrack.get()->getId(), pTrack);
+ }
+ // Skip unavailable tracks
}
updateFromTracks();
diff --git a/src/skin/legacy/tooltips.cpp b/src/skin/legacy/tooltips.cpp
index 60fac0eb51f8..ef1904316ba4 100644
--- a/src/skin/legacy/tooltips.cpp
+++ b/src/skin/legacy/tooltips.cpp
@@ -705,13 +705,13 @@ void Tooltips::addStandardTooltips() {
<< tr("Repeat")
<< tr("When active the track will repeat if you go past the end or reverse before the start.");
- add("eject") << tr("Eject") << tr("Ejects track from the player.")
- << tr("Un-ejects when no track is loaded, i.e. reloads the "
- "track that was ejected last (of any deck).")
- << QString("%1: %2").arg(doubleClick,
- "Reloads the last replaced track. "
- "If no track is loaded reloads the second-last "
- "ejected track.");
+ add("eject")
+ << tr("Eject") << tr("Ejects track from the player.")
+ << tr("Un-ejects when no track is loaded, i.e. reloads the "
+ "track that was ejected last (of any deck).")
+ << QString("%1: %2").arg(doubleClick,
+ tr("Reloads the last replaced track. If no track is "
+ "loaded reloads the second-last ejected track."));
add("hotcue") << tr("Hotcue")
<< QString("%1: %2").arg(leftClick,
diff --git a/src/widget/wtrackmenu.cpp b/src/widget/wtrackmenu.cpp
index 814df40c8533..e8e01c410baf 100644
--- a/src/widget/wtrackmenu.cpp
+++ b/src/widget/wtrackmenu.cpp
@@ -1283,7 +1283,7 @@ TrackIdList WTrackMenu::getTrackIds() const {
TrackIdList trackIds;
if (m_pTrackModel) {
trackIds.reserve(m_trackIndexList.size());
- for (const auto& index : m_trackIndexList) {
+ for (const auto& index : std::as_const(m_trackIndexList)) {
const auto trackId = m_pTrackModel->getTrackId(index);
if (!trackId.isValid()) {
// Skip unavailable tracks
@@ -1305,7 +1305,7 @@ QList WTrackMenu::getTrackRefs() const {
QList trackRefs;
if (m_pTrackModel) {
trackRefs.reserve(m_trackIndexList.size());
- for (const auto& index : m_trackIndexList) {
+ for (const auto& index : std::as_const(m_trackIndexList)) {
auto trackRef = TrackRef::fromFilePath(
m_pTrackModel->getTrackLocation(index),
m_pTrackModel->getTrackId(index));
@@ -1326,7 +1326,7 @@ QList WTrackMenu::getTrackRefs() const {
TrackPointer WTrackMenu::getFirstTrackPointer() const {
if (m_pTrackModel) {
- for (const auto& index : m_trackIndexList) {
+ for (const auto& index : std::as_const(m_trackIndexList)) {
const auto pTrack = m_pTrackModel->getTrack(index);
if (pTrack) {
return pTrack;
@@ -1341,7 +1341,7 @@ TrackPointer WTrackMenu::getFirstTrackPointer() const {
TrackPointerList WTrackMenu::getTrackPointers() const {
TrackPointerList tracks;
if (m_pTrackModel) {
- for (const auto& index : m_trackIndexList) {
+ for (const auto& index : std::as_const(m_trackIndexList)) {
const auto pTrack = m_pTrackModel->getTrack(index);
if (pTrack) {
tracks.append(pTrack);
@@ -2723,8 +2723,12 @@ void WTrackMenu::slotShowDlgTrackInfo() {
});
QList tracks;
tracks.reserve(getTrackCount());
- for (int i = 0; i < m_trackIndexList.size(); i++) {
- tracks.append(m_pTrackModel->getTrack(m_trackIndexList.at(i)));
+ for (const auto& index : std::as_const(m_trackIndexList)) {
+ const auto pTrack = m_pTrackModel->getTrack(index);
+ if (pTrack) {
+ tracks.append(pTrack);
+ }
+ // Skip unavailable tracks
}
m_pDlgTrackInfoMulti->loadTracks(tracks);
m_pDlgTrackInfoMulti->show();