Skip to content

Commit

Permalink
Merge pull request #11828 from daschuer/sync_lock_algorithm
Browse files Browse the repository at this point in the history
Expose [BPM],sync_lock_algorithm option in deck preferences.
  • Loading branch information
ronso0 authored Nov 16, 2023
2 parents 9c0af81 + bd77c26 commit a89f676
Show file tree
Hide file tree
Showing 6 changed files with 112 additions and 49 deletions.
2 changes: 2 additions & 0 deletions src/defs_urls.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
MIXXX_MANUAL_URL "/chapters/preferences.html#library"
#define MIXXX_MANUAL_CUE_MODES_URL \
MIXXX_MANUAL_URL "/chapters/user_interface.html#using-cue-modes"
#define MIXXX_MANUAL_SYNC_MODES_URL \
MIXXX_MANUAL_URL "/chapters/djing_with_mixxx#sync-lock-with-dynamic-tempo"
#define MIXXX_MANUAL_BEATS_URL \
MIXXX_MANUAL_URL "/chapters/preferences.html#beat-detection"
#define MIXXX_MANUAL_KEY_URL \
Expand Down
6 changes: 3 additions & 3 deletions src/engine/sync/enginesync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,10 +275,10 @@ Syncable* EngineSync::pickNewLeader(Syncable* pEnablingSyncable) {
}

const SyncLockAlgorithm picker = static_cast<SyncLockAlgorithm>(
m_pConfig->getValue<int>(ConfigKey("[BPM]", "sync_lock_algorithm"),
PREFER_IMPLICIT_LEADER));
m_pConfig->getValue<int>(ConfigKey(kBpmConfigGroup, kSyncLockAlgorithmConfigKey),
PREFER_SOFT_LEADER));
switch (picker) {
case PREFER_IMPLICIT_LEADER:
case PREFER_SOFT_LEADER:
// Always pick a deck for a new leader.
if (playing_deck_count == 1) {
return first_playing_deck;
Expand Down
24 changes: 13 additions & 11 deletions src/engine/sync/enginesync.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,25 @@
class InternalClock;
class EngineChannel;

const QString kBpmConfigGroup = QStringLiteral("[BPM]");
const QString kSyncLockAlgorithmConfigKey = QStringLiteral("sync_lock_algorithm");

/// EngineSync is the heart of the Mixxx Sync Lock engine. It knows which objects
/// (Decks, Internal Clock, etc) are participating in Sync and what their statuses
/// are. It also orchestrates sync handoffs between different decks as they play,
/// stop, or request their status to change.
class EngineSync : public SyncableListener {
public:
// Remove pick SyncLockAlgorithm when new beatgrid detection
// and editing code is committed and we no longer need the lock bpm fallback option.
enum SyncLockAlgorithm {
// New behavior, which should work if beatgrids are reliable.
PREFER_SOFT_LEADER,
// Old 2.3 behavior, which works around some issues with bad beatgrid detection, mostly
// for auto DJ mode.
PREFER_LOCK_BPM
};

explicit EngineSync(UserSettingsPointer pConfig);
~EngineSync() override;

Expand Down Expand Up @@ -143,17 +156,6 @@ class EngineSync : public SyncableListener {
return false;
}

// TODO: Remove pick algorithms during 2.4 development phase when new beatgrid detection
// and editing code is committed and we no longer need the lock bpm fallback option.
// If this code makes it to release we will all be very sad.
enum SyncLockAlgorithm {
// New behavior, which should work if beatgrids are reliable.
PREFER_IMPLICIT_LEADER,
// Old 2.3 behavior, which works around some issues with bad beatgrid detection, mostly
// for auto DJ mode.
PREFER_LOCK_BPM
};

FRIEND_TEST(EngineSyncTest, EnableOneDeckInitsLeader);
FRIEND_TEST(EngineSyncTest, EnableOneDeckInitializesLeader);
FRIEND_TEST(EngineSyncTest, SyncToNonSyncDeck);
Expand Down
41 changes: 30 additions & 11 deletions src/preferences/dialog/dlgprefdeck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "control/controlproxy.h"
#include "defs_urls.h"
#include "engine/controls/ratecontrol.h"
#include "engine/sync/enginesync.h"
#include "mixer/basetrackplayer.h"
#include "mixer/playermanager.h"
#include "moc_dlgprefdeck.cpp"
Expand Down Expand Up @@ -259,9 +260,7 @@ DlgPrefDeck::DlgPrefDeck(QWidget* parent, UserSettingsPointer pConfig)
}
setRateRangeForAllDecks(m_iRateRangePercent);

//
// Key lock mode
//
connect(buttonGroupKeyLockMode,
QOverload<QAbstractButton*>::of(&QButtonGroup::buttonClicked),
this,
Expand All @@ -274,9 +273,7 @@ DlgPrefDeck::DlgPrefDeck(QWidget* parent, UserSettingsPointer pConfig)
pControl->set(static_cast<double>(m_keylockMode));
}

//
// Key unlock mode
//
connect(buttonGroupKeyUnlockMode,
QOverload<QAbstractButton*>::of(&QButtonGroup::buttonClicked),
this,
Expand All @@ -289,21 +286,23 @@ DlgPrefDeck::DlgPrefDeck(QWidget* parent, UserSettingsPointer pConfig)
pControl->set(static_cast<int>(m_keyunlockMode));
}

//
// Cue Mode
//

// Add "(?)" with a manual link to the label
labelCueMode->setText(labelCueMode->text() + QStringLiteral(" ") +
labelCueMode->setText(labelCueMode->text() + QChar(' ') +
coloredLinkString(
m_pLinkColor,
QStringLiteral("(?)"),
MIXXX_MANUAL_CUE_MODES_URL));

//
// Speed / Pitch reset configuration
//
// Sync Mode
// Add "(?)" with a manual link to the label
labelSyncMode->setText(labelSyncMode->text() + QChar(' ') +
coloredLinkString(
m_pLinkColor,
QStringLiteral("(?)"),
MIXXX_MANUAL_SYNC_MODES_URL));

// Speed / Pitch reset configuration
// Update "reset speed" and "reset pitch" check boxes
// TODO: All defaults should only be set in slotResetToDefaults.
int configSPAutoReset = m_pConfig->getValue<int>(
Expand Down Expand Up @@ -457,6 +456,16 @@ void DlgPrefDeck::slotUpdate() {
index = ComboBoxCueMode->findData(static_cast<int>(cueMode));
ComboBoxCueMode->setCurrentIndex(index);

const EngineSync::SyncLockAlgorithm syncLockAlgorithm =
static_cast<EngineSync::SyncLockAlgorithm>(m_pConfig->getValue<int>(
ConfigKey(kBpmConfigGroup, kSyncLockAlgorithmConfigKey),
EngineSync::SyncLockAlgorithm::PREFER_SOFT_LEADER));
if (syncLockAlgorithm == EngineSync::SyncLockAlgorithm::PREFER_SOFT_LEADER) {
radioButtonSoftLeader->setChecked(true);
} else {
radioButtonLockBpm->setChecked(true);
}

KeylockMode keylockMode =
static_cast<KeylockMode>(static_cast<int>(m_keylockModeControls[0]->get()));
if (keylockMode == KeylockMode::LockCurrentKey) {
Expand Down Expand Up @@ -542,6 +551,8 @@ void DlgPrefDeck::slotResetToDefaults() {
checkBoxResetSpeed->setChecked(false);
checkBoxResetPitch->setChecked(true);

radioButtonSoftLeader->setChecked(true);

radioButtonOriginalKey->setChecked(true);
radioButtonResetUnlockedKey->setChecked(true);
}
Expand Down Expand Up @@ -721,6 +732,14 @@ void DlgPrefDeck::slotApply() {
m_pConfig->set(ConfigKey("[Controls]", "SpeedAutoReset"),
ConfigValue(configSPAutoReset));

if (radioButtonSoftLeader->isChecked()) {
m_pConfig->setValue(ConfigKey(kBpmConfigGroup, kSyncLockAlgorithmConfigKey),
static_cast<int>(EngineSync::SyncLockAlgorithm::PREFER_SOFT_LEADER));
} else {
m_pConfig->setValue(ConfigKey(kBpmConfigGroup, kSyncLockAlgorithmConfigKey),
static_cast<int>(EngineSync::SyncLockAlgorithm::PREFER_LOCK_BPM));
}

m_pConfig->setValue(ConfigKey("[Controls]", "keylockMode"),
static_cast<int>(m_keylockMode));
// Set key lock behavior for every group
Expand Down
Loading

0 comments on commit a89f676

Please sign in to comment.