Skip to content

Commit

Permalink
LoopingControl: store beatloop size when there's no loop to store
Browse files Browse the repository at this point in the history
  • Loading branch information
ronso0 committed May 19, 2024
1 parent c22cc95 commit efb1b81
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 6 deletions.
33 changes: 27 additions & 6 deletions src/engine/controls/loopingcontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ LoopingControl::LoopingControl(const QString& group,
m_bAdjustingLoopOut(false),
m_bAdjustingLoopInOld(false),
m_bAdjustingLoopOutOld(false),
m_bLoopOutPressedWhileLoopDisabled(false) {
m_bLoopOutPressedWhileLoopDisabled(false),
m_prevLoopSize(-1) {
m_currentPosition.setValue(mixxx::audio::kStartFramePos);
m_pActiveBeatLoop = nullptr;
m_pRateControl = nullptr;
Expand Down Expand Up @@ -797,11 +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.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 @@ -819,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 @@ -1331,6 +1336,13 @@ void LoopingControl::storeLoopInfo() {
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();
}
}

Expand All @@ -1343,6 +1355,15 @@ void LoopingControl::restoreLoopInfo() {
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
2 changes: 2 additions & 0 deletions src/engine/controls/loopingcontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ class LoopingControl : public EngineControl {
void restoreLoopInfo();

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

Expand Down Expand Up @@ -223,6 +224,7 @@ class LoopingControl : public EngineControl {
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 efb1b81

Please sign in to comment.