Skip to content

Commit

Permalink
Merge pull request #12475 from ronso0/looproll-restore-prev-regular-loop
Browse files Browse the repository at this point in the history
store/restore regular loop when toggling rolling loops
  • Loading branch information
daschuer authored May 20, 2024
2 parents 5286fa2 + efb1b81 commit aea29e0
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 16 deletions.
70 changes: 57 additions & 13 deletions src/engine/controls/loopingcontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,8 @@ LoopingControl::LoopingControl(const QString& group,
m_bAdjustingLoopOut(false),
m_bAdjustingLoopInOld(false),
m_bAdjustingLoopOutOld(false),
m_bLoopOutPressedWhileLoopDisabled(false) {
m_oldLoopInfo = {mixxx::audio::kInvalidFramePos,
mixxx::audio::kInvalidFramePos,
LoopSeekMode::MovedOut};
m_loopInfo.setValue(m_oldLoopInfo);
m_bLoopOutPressedWhileLoopDisabled(false),
m_prevLoopSize(-1) {
m_currentPosition.setValue(mixxx::audio::kStartFramePos);
m_pActiveBeatLoop = nullptr;
m_pRateControl = nullptr;
Expand Down Expand Up @@ -801,14 +798,7 @@ void LoopingControl::setLoopInToCurrentPosition() {
// Clear the last active loop while saved loop (cue + info) remains untouched
void LoopingControl::slotLoopRemove() {
setLoopingEnabled(false);
LoopInfo loopInfo = m_loopInfo.getValue();
loopInfo.startPosition = mixxx::audio::kInvalidFramePos;
loopInfo.endPosition = mixxx::audio::kInvalidFramePos;
loopInfo.seekMode = LoopSeekMode::None;
m_loopInfo.setValue(loopInfo);
m_oldLoopInfo = loopInfo;
m_pCOLoopStartPosition->set(loopInfo.startPosition.toEngineSamplePosMaybeInvalid());
m_pCOLoopEndPosition->set(loopInfo.endPosition.toEngineSamplePosMaybeInvalid());
clearLoopInfoAndControls();
// The loop cue is stored by BaseTrackPlayerImpl::unloadTrack()
// if the loop is valid, else it is removed.
// We remove it here right away so the loop is not restored
Expand All @@ -826,6 +816,14 @@ void LoopingControl::slotLoopRemove() {
}
}

void LoopingControl::clearLoopInfoAndControls() {
LoopInfo loopInfo;
m_loopInfo.setValue(loopInfo);
m_oldLoopInfo = loopInfo;
m_pCOLoopStartPosition->set(loopInfo.startPosition.toEngineSamplePosMaybeInvalid());
m_pCOLoopEndPosition->set(loopInfo.endPosition.toEngineSamplePosMaybeInvalid());
}

void LoopingControl::slotLoopIn(double pressed) {
if (!m_pTrack) {
return;
Expand Down Expand Up @@ -1283,6 +1281,8 @@ void LoopingControl::slotBeatLoopActivateRoll(
return;
}

storeLoopInfo();

// Disregard existing loops (except beatlooprolls).
m_pSlipEnabled->set(1);
slotBeatLoop(pBeatLoopControl->getSize(), m_bLoopRollActive, true, forcedAnchor);
Expand Down Expand Up @@ -1320,8 +1320,50 @@ void LoopingControl::slotBeatLoopDeactivateRoll(BeatLoopingControl* pBeatLoopCon
}

// Return to the previous beatlooproll if necessary.
// Else previous regular beatloop if no rolling loops are active.
if (!m_activeLoopRolls.empty()) {
slotBeatLoop(m_activeLoopRolls.top(), m_bLoopRollActive, true);
} else {
restoreLoopInfo();
}
}

void LoopingControl::storeLoopInfo() {
if (m_bLoopRollActive || !m_activeLoopRolls.empty()) {
return;
}

LoopInfo loopInfo = m_loopInfo.getValue();
if (loopInfo.startPosition.isValid() && loopInfo.endPosition.isValid()) {
m_prevLoopInfo.setValue(loopInfo);
} else {
// If we don't have a valid loop, yet, we store the current beatloop size.
// This way this (default) value is available again for `beatloop_activate`
// after disaling the (last) rolling loop.
// Explicitly clear the last saved loop.
m_prevLoopInfo.setValue(LoopInfo{});
m_prevLoopSize = m_pCOBeatLoopSize->get();
}
}

void LoopingControl::restoreLoopInfo() {
if (m_bLoopRollActive || !m_activeLoopRolls.empty()) {
return;
}

LoopInfo prevLoopInfo = m_prevLoopInfo.getValue();
if (prevLoopInfo.startPosition.isValid() && prevLoopInfo.endPosition.isValid()) {
setLoop(prevLoopInfo.startPosition, prevLoopInfo.endPosition, false);
m_prevLoopInfo.setValue(LoopInfo{});
} else {
// This may happen when there was no loop set when we activated the
// rolling loop that triggered storeLoopInfo(). Re-apply the loop size
// we stored.
clearLoopInfoAndControls();
double prevLoopSize = m_prevLoopSize;
if (prevLoopSize > 0) {
m_pCOBeatLoopSize->setAndConfirm(m_prevLoopSize);
}
}
}

Expand Down Expand Up @@ -1659,6 +1701,7 @@ void LoopingControl::slotBeatLoopRollActivate(double pressed) {
m_activeLoopRolls.clear();
}
} else {
storeLoopInfo();
m_pSlipEnabled->set(1.0);
slotBeatLoop(m_pCOBeatLoopSize->get());
m_bLoopRollActive = true;
Expand All @@ -1672,6 +1715,7 @@ void LoopingControl::slotBeatLoopRollActivate(double pressed) {
m_bLoopRollActive = false;
m_activeLoopRolls.clear();
}
restoreLoopInfo();
}
}

Expand Down
13 changes: 10 additions & 3 deletions src/engine/controls/loopingcontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ class LoopingControl : public EngineControl {
};

struct LoopInfo {
mixxx::audio::FramePos startPosition;
mixxx::audio::FramePos endPosition;
LoopSeekMode seekMode;
mixxx::audio::FramePos startPosition = mixxx::audio::kInvalidFramePos;
mixxx::audio::FramePos endPosition = mixxx::audio::kInvalidFramePos;
LoopSeekMode seekMode = LoopSeekMode::None;
};

LoopInfo getLoopInfo() {
Expand Down Expand Up @@ -163,7 +163,12 @@ class LoopingControl : public EngineControl {
void setLoopingEnabled(bool enabled);
void setLoopInToCurrentPosition();
void setLoopOutToCurrentPosition();

void storeLoopInfo();
void restoreLoopInfo();

void clearActiveBeatLoop();
void clearLoopInfoAndControls();
void updateBeatLoopingControls();
bool currentLoopMatchesBeatloopSize(const LoopInfo& loopInfo) const;

Expand Down Expand Up @@ -218,6 +223,8 @@ class LoopingControl : public EngineControl {
bool m_bLoopOutPressedWhileLoopDisabled;
QStack<double> m_activeLoopRolls;
ControlValueAtomic<LoopInfo> m_loopInfo;
ControlValueAtomic<LoopInfo> m_prevLoopInfo;
double m_prevLoopSize;
LoopInfo m_oldLoopInfo;
ControlValueAtomic<mixxx::audio::FramePos> m_currentPosition;
ControlObject* m_pQuantizeEnabled;
Expand Down

0 comments on commit aea29e0

Please sign in to comment.