Skip to content

Commit

Permalink
Merge pull request #12623 from ronso0/hotcue-no-redundant-loop-cue
Browse files Browse the repository at this point in the history
Hotcue: allow setting hotcue inside active, saved loop
  • Loading branch information
daschuer authored Jan 27, 2024
2 parents 19bb2d3 + f76b233 commit a51e8d6
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
20 changes: 19 additions & 1 deletion src/engine/controls/cuecontrol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,25 @@ void CueControl::hotcueSet(HotcueControl* pControl, double value, HotcueSetMode

bool loopEnabled = m_pLoopEnabled->toBool();
if (mode == HotcueSetMode::Auto) {
mode = loopEnabled ? HotcueSetMode::Loop : HotcueSetMode::Cue;
if (loopEnabled) {
// Don't create a hotcue at loop start if there is one already.
// This allows to set a hotuce inside an active, saved loop with
// 'hotcue_X_activate'.
auto* pSavedLoopControl = m_pCurrentSavedLoopControl.loadAcquire();
if (pSavedLoopControl &&
pSavedLoopControl->getPosition() ==
mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(
m_pLoopStartPosition->get()) &&
pSavedLoopControl->getEndPosition() ==
mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(
m_pLoopEndPosition->get())) {
mode = HotcueSetMode::Cue;
} else {
mode = HotcueSetMode::Loop;
}
} else {
mode = HotcueSetMode::Cue;
}
}

switch (mode) {
Expand Down
23 changes: 22 additions & 1 deletion src/test/hotcuecontrol_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ class HotcueControlTest : public BaseSignalPathTest {
m_pHotcue1EndPosition = std::make_unique<ControlProxy>(m_sGroup1, "hotcue_1_endposition");
m_pHotcue1Enabled = std::make_unique<ControlProxy>(m_sGroup1, "hotcue_1_enabled");
m_pHotcue1Clear = std::make_unique<ControlProxy>(m_sGroup1, "hotcue_1_clear");
m_pHotcue2Activate = std::make_unique<ControlProxy>(m_sGroup1, "hotcue_2_activate");
m_pHotcue2Enabled = std::make_unique<ControlProxy>(m_sGroup1, "hotcue_2_enabled");
m_pHotcue2Position = std::make_unique<ControlProxy>(m_sGroup1, "hotcue_2_position");
m_pHotcue2EndPosition = std::make_unique<ControlProxy>(m_sGroup1, "hotcue_2_endposition");
m_pQuantizeEnabled = std::make_unique<ControlProxy>(m_sGroup1, "quantize");
}

Expand Down Expand Up @@ -110,6 +114,10 @@ class HotcueControlTest : public BaseSignalPathTest {
std::unique_ptr<ControlProxy> m_pHotcue1EndPosition;
std::unique_ptr<ControlProxy> m_pHotcue1Enabled;
std::unique_ptr<ControlProxy> m_pHotcue1Clear;
std::unique_ptr<ControlProxy> m_pHotcue2Activate;
std::unique_ptr<ControlProxy> m_pHotcue2Enabled;
std::unique_ptr<ControlProxy> m_pHotcue2Position;
std::unique_ptr<ControlProxy> m_pHotcue2EndPosition;
std::unique_ptr<ControlProxy> m_pQuantizeEnabled;
};

Expand Down Expand Up @@ -250,7 +258,7 @@ TEST_F(HotcueControlTest, SetCueManual) {
.isValid());
}

TEST_F(HotcueControlTest, SetLoopAuto) {
TEST_F(HotcueControlTest, SetLoopAutoNoRedundantLoopCue) {
createAndLoadFakeTrack();

EXPECT_DOUBLE_EQ(static_cast<double>(HotcueControl::Status::Empty), m_pHotcue1Enabled->get());
Expand All @@ -270,6 +278,19 @@ TEST_F(HotcueControlTest, SetLoopAuto) {
EXPECT_DOUBLE_EQ(static_cast<double>(HotcueControl::Status::Active), m_pHotcue1Enabled->get());
EXPECT_FRAMEPOS_EQ_CONTROL(loopStartPosition, m_pHotcue1Position);
EXPECT_FRAMEPOS_EQ_CONTROL(loopEndPosition, m_pHotcue1EndPosition);

// Setting another hotcue inside the loop should create a regular hotcue
// at the current position, not a redundant loop cue.
setCurrentFramePosition(mixxx::audio::FramePos(195));
ProcessBuffer();

m_pHotcue2Activate->set(1);
m_pHotcue2Activate->set(0);
EXPECT_DOUBLE_EQ(static_cast<double>(HotcueControl::Status::Set), m_pHotcue2Enabled->get());
EXPECT_FRAMEPOS_EQ_CONTROL(currentFramePosition(), m_pHotcue2Position);
EXPECT_FALSE(mixxx::audio::FramePos::fromEngineSamplePosMaybeInvalid(
m_pHotcue2EndPosition->get())
.isValid());
}

TEST_F(HotcueControlTest, SetLoopManualWithLoop) {
Expand Down

0 comments on commit a51e8d6

Please sign in to comment.