diff options
author | Jan Holthuis <jan.holthuis@ruhr-uni-bochum.de> | 2021-03-05 14:40:35 +0100 |
---|---|---|
committer | Jan Holthuis <jan.holthuis@ruhr-uni-bochum.de> | 2021-03-05 14:40:35 +0100 |
commit | 20893add4b98176c1ad06df47e0fc922ab5577be (patch) | |
tree | 618ba94fa4f971df95b6dcf0f5c95bcac7744da4 /src | |
parent | eff873a190efa9233d33481158af9e31377282c8 (diff) | |
parent | 31557b7d6279b5ce59ba79dd970c1b569ea01eab (diff) |
Merge branch '2.3' of github.com:mixxxdj/mixxx
Diffstat (limited to 'src')
39 files changed, 880 insertions, 976 deletions
diff --git a/src/analyzer/analyzerbeats.cpp b/src/analyzer/analyzerbeats.cpp index 67dd45d17f..2036e041fa 100644 --- a/src/analyzer/analyzerbeats.cpp +++ b/src/analyzer/analyzerbeats.cpp @@ -46,7 +46,7 @@ AnalyzerBeats::AnalyzerBeats(UserSettingsPointer pConfig, bool enforceBpmDetecti m_iMaxBpm(9999) { } -bool AnalyzerBeats::initialize(TrackPointer tio, int sampleRate, int totalSamples) { +bool AnalyzerBeats::initialize(TrackPointer pTrack, int sampleRate, int totalSamples) { if (totalSamples == 0) { return false; } @@ -58,7 +58,7 @@ bool AnalyzerBeats::initialize(TrackPointer tio, int sampleRate, int totalSample return false; } - bool bpmLock = tio->isBpmLocked(); + bool bpmLock = pTrack->isBpmLocked(); if (bpmLock) { qDebug() << "Track is BpmLocked: Beat calculation will not start"; return false; @@ -106,8 +106,7 @@ bool AnalyzerBeats::initialize(TrackPointer tio, int sampleRate, int totalSample m_iCurrentSample = 0; // if we can load a stored track don't reanalyze it - bool bShouldAnalyze = shouldAnalyze(tio); - + bool bShouldAnalyze = shouldAnalyze(pTrack); DEBUG_ASSERT(!m_pPlugin); if (bShouldAnalyze) { @@ -136,11 +135,11 @@ bool AnalyzerBeats::initialize(TrackPointer tio, int sampleRate, int totalSample return bShouldAnalyze; } -bool AnalyzerBeats::shouldAnalyze(TrackPointer tio) const { +bool AnalyzerBeats::shouldAnalyze(TrackPointer pTrack) const { int iMinBpm = m_bpmSettings.getBpmRangeStart(); int iMaxBpm = m_bpmSettings.getBpmRangeEnd(); - bool bpmLock = tio->isBpmLocked(); + bool bpmLock = pTrack->isBpmLocked(); if (bpmLock) { qDebug() << "Track is BpmLocked: Beat calculation will not start"; return false; @@ -153,7 +152,7 @@ bool AnalyzerBeats::shouldAnalyze(TrackPointer tio) const { // If the track already has a Beats object then we need to decide whether to // analyze this track or not. - mixxx::BeatsPointer pBeats = tio->getBeats(); + const mixxx::BeatsPointer pBeats = pTrack->getBeats(); if (!pBeats) { return true; } @@ -221,7 +220,7 @@ void AnalyzerBeats::cleanup() { m_pPlugin.reset(); } -void AnalyzerBeats::storeResults(TrackPointer tio) { +void AnalyzerBeats::storeResults(TrackPointer pTrack) { VERIFY_OR_DEBUG_ASSERT(m_pPlugin) { return; } @@ -237,7 +236,6 @@ void AnalyzerBeats::storeResults(TrackPointer tio) { QHash<QString, QString> extraVersionInfo = getExtraVersionInfo( m_pluginId, m_bPreferencesFastAnalysis); pBeats = BeatFactory::makePreferredBeats( - *tio, beats, extraVersionInfo, m_bPreferencesFixedTempo, @@ -251,21 +249,21 @@ void AnalyzerBeats::storeResults(TrackPointer tio) { } else { float bpm = m_pPlugin->getBpm(); qDebug() << "AnalyzerBeats plugin detected constant BPM: " << bpm; - pBeats = BeatFactory::makeBeatGrid(*tio, bpm, 0.0f); + pBeats = BeatFactory::makeBeatGrid(m_iSampleRate, bpm, 0.0f); } - mixxx::BeatsPointer pCurrentBeats = tio->getBeats(); + mixxx::BeatsPointer pCurrentBeats = pTrack->getBeats(); // If the track has no beats object then set our newly generated one // regardless of beat lock. if (!pCurrentBeats) { - tio->setBeats(pBeats); + pTrack->setBeats(pBeats); return; } // If the track received the beat lock while we were analyzing it then we // abort setting it. - if (tio->isBpmLocked()) { + if (pTrack->isBpmLocked()) { qDebug() << "Track was BPM-locked as we were analyzing it. Aborting analysis."; return; } @@ -278,7 +276,7 @@ void AnalyzerBeats::storeResults(TrackPointer tio) { qDebug() << "Replacing 0-BPM beatgrid with a" << pBeats->getBpm() << "beatgrid."; } - tio->setBeats(pBeats); + pTrack->setBeats(pBeats); return; } @@ -287,7 +285,7 @@ void AnalyzerBeats::storeResults(TrackPointer tio) { double currentFirstBeat = pCurrentBeats->findNextBeat(0); double newFirstBeat = pBeats->findNextBeat(0); if (currentFirstBeat == 0.0 && newFirstBeat > 0) { - pCurrentBeats->translate(newFirstBeat); + pTrack->setBeats(pCurrentBeats->translate(newFirstBeat)); } } diff --git a/src/analyzer/analyzerbeats.h b/src/analyzer/analyzerbeats.h index 1169fd0436..4efb2f3075 100644 --- a/src/analyzer/analyzerbeats.h +++ b/src/analyzer/analyzerbeats.h @@ -26,13 +26,13 @@ class AnalyzerBeats : public Analyzer { static QList<mixxx::AnalyzerPluginInfo> availablePlugins(); static mixxx::AnalyzerPluginInfo defaultPlugin(); - bool initialize(TrackPointer tio, int sampleRate, int totalSamples) override; + bool initialize(TrackPointer pTrack, int sampleRate, int totalSamples) override; bool processSamples(const CSAMPLE *pIn, const int iLen) override; void storeResults(TrackPointer tio) override; void cleanup() override; private: - bool shouldAnalyze(TrackPointer tio) const; + bool shouldAnalyze(TrackPointer pTrack) const; static QHash<QString, QString> getExtraVersionInfo( const QString& pluginId, bool bPreferencesFastAnalysis); diff --git a/src/controllers/dlgprefcontroller.cpp b/src/controllers/dlgprefcontroller.cpp index 971253bf95..8120412b53 100644 --- a/src/controllers/dlgprefcontroller.cpp +++ b/src/controllers/dlgprefcontroller.cpp @@ -14,6 +14,7 @@ #include "controllers/controllerlearningeventfilter.h" #include "controllers/controllermanager.h" #include "controllers/defs_controllers.h" +#include "controllers/midi/legacymidicontrollermapping.h" #include "defs_urls.h" #include "moc_dlgprefcontroller.cpp" #include "preferences/usersettings.h" @@ -21,6 +22,13 @@ namespace { const QString kMappingExt(".midi.xml"); + +QString mappingNameToPath(const QString& directory, const QString& mappingName) { + // While / is allowed for the display name we can't use it for the file name. + QString fileName = QString(mappingName).replace(QChar('/'), QChar('-')); + return directory + fileName + kMappingExt; +} + } // namespace DlgPrefController::DlgPrefController( @@ -134,11 +142,7 @@ DlgPrefController::~DlgPrefController() { } void DlgPrefController::showLearningWizard() { - // If the user has checked the "Enabled" checkbox but they haven't hit OK to - // apply it yet, prompt them to apply the settings before we open the - // learning dialog. If we don't apply the settings first and open the - // device, the dialog won't react to controller messages. - if (m_ui.chkEnabledDevice->isChecked() && !m_pController->isOpen()) { + if (isDirty()) { QMessageBox::StandardButton result = QMessageBox::question(this, tr("Apply device settings?"), tr("Your settings must be applied before starting the learning " @@ -155,6 +159,11 @@ void DlgPrefController::showLearningWizard() { } slotApply(); + if (!m_pMapping) { + m_pMapping = std::shared_ptr<LegacyControllerMapping>(new LegacyMidiControllerMapping()); + emit applyMapping(m_pController, m_pMapping, true); + } + // Note that DlgControllerLearning is set to delete itself on close using // the Qt::WA_DeleteOnClose attribute (so this "new" doesn't leak memory) m_pDlgControllerLearning = new DlgControllerLearning(this, m_pController); @@ -187,7 +196,43 @@ void DlgPrefController::showLearningWizard() { connect(m_pDlgControllerLearning, &DlgControllerLearning::stopLearning, this, - &DlgPrefController::mappingEnded); + &DlgPrefController::slotStopLearning); +} + +void DlgPrefController::slotStopLearning() { + VERIFY_OR_DEBUG_ASSERT(m_pMapping) { + emit mappingEnded(); + return; + } + + applyMappingChanges(); + if (m_pMapping->filePath().isEmpty()) { + // This mapping was created when the learning wizard was started + if (m_pMapping->isDirty()) { + QString mappingName = askForMappingName(); + QString mappingPath = mappingNameToPath(m_pUserDir, mappingName); + m_pMapping->setName(mappingName); + if (m_pMapping->saveMapping(mappingPath)) { + qDebug() << "Mapping saved as" << mappingPath; + m_pMapping->setFilePath(mappingPath); + m_pMapping->setDirty(false); + emit applyMapping(m_pController, m_pMapping, true); + enumerateMappings(mappingPath); + } else { + qDebug() << "Failed to save mapping as" << mappingPath; + // Discard the new mapping and disable the controller + m_pMapping.reset(); + emit applyMapping(m_pController, m_pMapping, false); + } + } else { + // No changes made to the new mapping, discard it and disable the + // controller + m_pMapping.reset(); + emit applyMapping(m_pController, m_pMapping, false); + } + } + + emit mappingEnded(); } void DlgPrefController::midiInputMappingsLearned( @@ -329,6 +374,7 @@ QString DlgPrefController::mappingFileLinks( } void DlgPrefController::enumerateMappings(const QString& selectedMappingPath) { + m_ui.comboBoxMapping->blockSignals(true); m_ui.comboBoxMapping->clear(); // qDebug() << "Enumerating mappings for controller" << m_pController->getName(); @@ -386,6 +432,8 @@ void DlgPrefController::enumerateMappings(const QString& selectedMappingPath) { m_ui.comboBoxMapping->setCurrentIndex(index); m_ui.chkEnabledDevice->setEnabled(true); } + m_ui.comboBoxMapping->blockSignals(false); + slotMappingSelected(m_ui.comboBoxMapping->currentIndex()); } MappingInfo DlgPrefController::enumerateMappingsFromEnumerator( @@ -413,14 +461,14 @@ MappingInfo DlgPrefController::enumerateMappingsFromEnumerator( } void DlgPrefController::slotUpdate() { - enumerateMappings(m_pControllerManager->getConfiguredMappingFileForDevice( - m_pController->getName())); - // Check if the controller is open. bool deviceOpen = m_pController->isOpen(); // Check/uncheck the "Enabled" box m_ui.chkEnabledDevice->setChecked(deviceOpen); + enumerateMappings(m_pControllerManager->getConfiguredMappingFileForDevice( + m_pController->getName())); + // If the controller is not mappable, disable the input and output mapping // sections and the learning wizard button. bool isMappable = m_pController->isMappable(); @@ -469,6 +517,10 @@ void DlgPrefController::slotApply() { return; } + QString mappingPath = mappingPathFromIndex(m_ui.comboBoxMapping->currentIndex()); + m_pMapping = LegacyControllerMappingFileHandler::loadMapping( + mappingPath, QDir(resourceMappingsPath(m_pConfig))); + // Load the resulting mapping (which has been mutated by the input/output // table models). The controller clones the mapping so we aren't touching // the same mapping. @@ -482,9 +534,18 @@ QUrl DlgPrefController::helpUrl() const { return QUrl(MIXXX_MANUAL_CONTROLLERS_URL); } +QString DlgPrefController::mappingPathFromIndex(int index) const { + if (index == 0) { + // "No Mapping" item + return QString(); + } + + return m_ui.comboBoxMapping->itemData(index).toString(); +} + void DlgPrefController::slotMappingSelected(int chosenIndex) { - QString mappingPath; - if (chosenIndex == 0) { + QString mappingPath = mappingPathFromIndex(chosenIndex); + if (mappingPath.isEmpty()) { // User picked "No Mapping" item m_ui.chkEnabledDevice->setEnabled(false); @@ -500,8 +561,6 @@ void DlgPrefController::slotMappingSelected(int chosenIndex) { m_ui.chkEnabledDevice->setChecked(true); setDirty(true); } - - mappingPath = m_ui.comboBoxMapping->itemData(chosenIndex).toString(); } // Check if the mapping is different from the configured mapping @@ -595,49 +654,8 @@ void DlgPrefController::saveMapping() { if (!saveAsNew) { newFilePath = oldFilePath; } else { - QString saveMappingTitle = tr("Save user mapping"); - QString saveMappingLabel = tr("Enter the name for saving the mapping to the user folder."); - QString savingFailedTitle = tr("Saving mapping failed"); - QString invalidNameLabel = - tr("A mapping cannot have a blank name and may not contain " - "special characters."); - QString fileExistsLabel = tr("A mapping file with that name already exists."); - // Only allow the name to contain letters, numbers, whitespaces and _-+()/ - const QRegExp rxRemove = QRegExp("[^[(a-zA-Z0-9\\_\\-\\+\\(\\)\\/|\\s]"); - - // Choose a new file (base) name - bool validMappingName = false; - while (!validMappingName) { - QString userDir = m_pUserDir; - bool ok = false; - mappingName = QInputDialog::getText(nullptr, - saveMappingTitle, - saveMappingLabel, - QLineEdit::Normal, - mappingName, - &ok) - .remove(rxRemove) - .trimmed(); - if (!ok) { - return; - } - if (mappingName.isEmpty()) { - QMessageBox::warning(nullptr, - savingFailedTitle, - invalidNameLabel); - continue; - } - // While / is allowed for the display name we can't use it for the file name. - QString fileName = mappingName.replace(QString("/"), QString("-")); - newFilePath = userDir + fileName + kMappingExt; - if (QFile::exists(newFilePath)) { - QMessageBox::warning(nullptr, - savingFailedTitle, - fileExistsLabel); - continue; - } - validMappingName = true; - } + mappingName = askForMappingName(mappingName); + newFilePath = mappingNameToPath(m_pUserDir, mappingName); m_pMapping->setName(mappingName); qDebug() << "Mapping renamed to" << m_pMapping->name(); } @@ -654,6 +672,53 @@ void DlgPrefController::saveMapping() { enumerateMappings(m_pMapping->filePath()); } +QString DlgPrefController::askForMappingName(const QString& prefilledName) const { + QString saveMappingTitle = tr("Save user mapping"); + QString saveMappingLabel = tr("Enter the name for saving the mapping to the user folder."); + QString savingFailedTitle = tr("Saving mapping failed"); + QString invalidNameLabel = + tr("A mapping cannot have a blank name and may not contain " + "special characters."); + QString fileExistsLabel = tr("A mapping file with that name already exists."); + // Only allow the name to contain letters, numbers, whitespaces and _-+()/ + const QRegExp rxRemove = QRegExp("[^[(a-zA-Z0-9\\_\\-\\+\\(\\)\\/|\\s]"); + + // Choose a new file (base) name + bool validMappingName = false; + QString mappingName = prefilledName; + while (!validMappingName) { + QString userDir = m_pUserDir; + bool ok = false; + mappingName = QInputDialog::getText(nullptr, + saveMappingTitle, + saveMappingLabel, + QLineEdit::Normal, + mappingName, + &ok) + .remove(rxRemove) + .trimmed(); + if (!ok) { + continue; + } + if (mappingName.isEmpty()) { + QMessageBox::warning(nullptr, + savingFailedTitle, + invalidNameLabel); + continue; + } + // While / is allowed for the display name we can't use it for the file name. + QString newFilePath = mappingNameToPath(userDir, mappingName); + if (QFile::exists(newFilePath)) { + QMessageBox::warning(nullptr, + savingFailedTitle, + fileExistsLabel); + continue; + } + validMappingName = true; + } + return mappingName; +} + void DlgPrefController::initTableView(QTableView* pTable) { // Enable selection by rows and extended selection (ctrl/shift click) pTable->setSelectionBehavior(QAbstractItemView::SelectRows); diff --git a/src/controllers/dlgprefcontroller.h b/src/controllers/dlgprefcontroller.h index a277a91317..2bbd47bf01 100644 --- a/src/controllers/dlgprefcontroller.h +++ b/src/controllers/dlgprefcontroller.h @@ -51,6 +51,8 @@ class DlgPrefController : public DlgPreferencePage { /// Used to selected the current mapping in the combobox and display the /// mapping information. void slotShowMapping(std::shared_ptr<LegacyControllerMapping> mapping); + /// Called when the Controller Learning Wizard is closed. + void slotStopLearning(); // Input mappings void addInputMapping(); @@ -72,6 +74,8 @@ class DlgPrefController : public DlgPreferencePage { QString mappingDescription(const std::shared_ptr<LegacyControllerMapping> pMapping) const; QString mappingSupportLinks(const std::shared_ptr<LegacyControllerMapping> pMapping) const; QString mappingFileLinks(const std::shared_ptr<LegacyControllerMapping> pMapping) const; + QString mappingPathFromIndex(int index) const; + QString askForMappingName(const QString& prefilledName = QString()) const; void applyMappingChanges(); void saveMapping(); void initTableView(QTableView* pTable); diff --git a/src/controllers/midi/portmidicontroller.cpp b/src/controllers/midi/portmidicontroller.cpp index d7eea579aa..04215af108 100644 --- a/src/controllers/midi/portmidicontroller.cpp +++ b/src/controllers/midi/portmidicontroller.cpp @@ -118,16 +118,6 @@ bool PortMidiController::poll() { return false; } - // Returns true if events are available or an error code. - PmError gotEvents = m_pInputDevice->poll(); - if (gotEvents == FALSE) { - return false; - } - if (gotEvents < 0) { - qWarning() << "PortMidi error:" << Pm_GetErrorText(gotEvents); - return false; - } - int numEvents = m_pInputDevice->read(m_midiBuffer, MIXXX_PORTMIDI_BUFFER_LEN); //qDebug() << "PortMidiController::poll()" << numEvents; diff --git a/src/engine/controls/bpmcontrol.cpp b/src/engine/controls/bpmcontrol.cpp index 9374bf4950..7e932797e9 100644 --- a/src/engine/controls/bpmcontrol.cpp +++ b/src/engine/controls/bpmcontrol.cpp @@ -161,39 +161,67 @@ double BpmControl::getBpm() const { } void BpmControl::slotAdjustBeatsFaster(double v) { - mixxx::BeatsPointer pBeats = m_pBeats; - if (v > 0 && pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_SETBPM)) { + if (v <= 0) { + return; + } + const TrackPointer pTrack = getEngineBuffer()->getLoadedTrack(); + if (!pTrack) { + return; + } + const mixxx::BeatsPointer pBeats = pTrack->getBeats(); + if (pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_SETBPM)) { double bpm = pBeats->getBpm(); double adjustedBpm = bpm + kBpmAdjustStep; - pBeats->setBpm(adjustedBpm); + pTrack->setBeats(pBeats->setBpm(adjustedBpm)); } } void BpmControl::slotAdjustBeatsSlower(double v) { - mixxx::BeatsPointer pBeats = m_pBeats; - if (v > 0 && pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_SETBPM)) { + if (v <= 0) { + return; + } + const TrackPointer pTrack = getEngineBuffer()->getLoadedTrack(); + if (!pTrack) { + return; + } + const mixxx::BeatsPointer pBeats = pTrack->getBeats(); + if (pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_SETBPM)) { double bpm = pBeats->getBpm(); double adjustedBpm = math_max(kBpmAdjustMin, bpm - kBpmAdjustStep); - pBeats->setBpm(adjustedBpm); + pTrack->setBeats(pBeats->setBpm(adjustedBpm)); } } void BpmControl::slotTranslateBeatsEarlier(double v) { - mixxx::BeatsPointer pBeats = m_pBeats; - if (v > 0 && pBeats && + if (v <= 0) { + return; + } + const TrackPointer pTrack = getEngineBuffer()->getLoadedTrack(); + if (!pTrack) { + return; + } + const mixxx::BeatsPointer pBeats = pTrack->getBeats(); + if (pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_TRANSLATE)) { const double translate_dist = getSampleOfTrack().rate * -.01; - pBeats->translate(translate_dist); + pTrack->setBeats(pBeats->translate(translate_dist)); } } void BpmControl::slotTranslateBeatsLater(double v) { - mixxx::BeatsPointer pBeats = m_pBeats; - if (v > 0 && pBeats && + if (v <= 0) { + return; + } + const TrackPointer pTrack = getEngineBuffer()->getLoadedTrack(); + if (!pTrack) { + return; + } + const mixxx::BeatsPointer pBeats = pTrack->getBeats(); + if (pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_TRANSLATE)) { // TODO(rryan): Track::getSampleRate is possibly inaccurate! const double translate_dist = getSampleOfTrack().rate * .01; - pBeats->translate(translate_dist); + pTrack->setBeats(pBeats->translate(translate_dist)); } } @@ -211,11 +239,14 @@ void BpmControl::slotTapFilter(double averageLength, int numSamples) { return; } - mixxx::BeatsPointer pBeats = m_pBeats; + const TrackPointer pTrack = getEngineBuffer()->getLoadedTrack(); + if (!pTrack) { + return; + } + const mixxx::BeatsPointer pBeats = pTrack->getBeats(); if (!pBeats) { return; } - double rateRatio = m_pRateRatio->get(); if (rateRatio == 0.0) { return; @@ -224,7 +255,7 @@ void BpmControl::slotTapFilter(double averageLength, int numSamples) { // (60 seconds per minute) * (1000 milliseconds per second) / (X millis per // beat) = Y beats/minute double averageBpm = 60.0 * 1000.0 / averageLength / rateRatio; - pBeats->setBpm(averageBpm); + pTrack->setBeats(pBeats->setBpm(averageBpm)); } void BpmControl::slotControlBeatSyncPhase(double value) { @@ -590,7 +621,7 @@ bool BpmControl::getBeatContextNoLookup( double BpmControl::getNearestPositionInPhase( double dThisPosition, bool respectLoops, bool playing) { // Without a beatgrid, we don't know the phase offset. - mixxx::BeatsPointer pBeats = m_pBeats; + const mixxx::BeatsPointer pBeats = m_pBeats; if (!pBeats) { return dThisPosition; } @@ -977,34 +1008,45 @@ void BpmControl::trackBeatsUpdated(mixxx::BeatsPointer pBeats) { } void BpmControl::slotBeatsTranslate(double v) { - mixxx::BeatsPointer pBeats = m_pBeats; - if (v > 0 && pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_TRANSLATE)) { + if (v <= 0) { + return; + } + TrackPointer pTrack = getEngineBuffer()->getLoadedTrack(); + const mixxx::BeatsPointer pBeats = pTrack->getBeats(); + if (pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_TRANSLATE)) { double currentSample = getSampleOfTrack().current; double closestBeat = pBeats->findClosestBeat(currentSample); int delta = static_cast<int>(currentSample - closestBeat); if (delta % 2 != 0) { delta--; } - pBeats->translate(delta); + pTrack->setBeats(pBeats->translate(delta)); } } void BpmControl::slotBeatsTranslateMatchAlignment(double v) { - mixxx::BeatsPointer pBeats = m_pBeats; - if (v > 0 && pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_TRANSLATE)) { + if (v <= 0) { + return; + } + TrackPointer pTrack = getEngineBuffer()->getLoadedTrack(); + if (!pTrack) { + return; + } + const mixxx::BeatsPointer pBeats = pTrack->getBeats(); + if (pBeats && (pBeats->getCapabilities() & mixxx::Beats::BEATSCAP_TRANSLATE)) { // Must reset the user offset *before* calling getPhaseOffset(), // otherwise it will always return 0 if master sync is active. m_dUserOffset.setValue(0.0); double offset = getPhaseOffset(getSampleOfTrack().current); - pBeats->translate(-offset); + pTrack->setBeats(pBeats->translate(-offset)); } } double BpmControl::updateLocalBpm() { double prev_local_bpm = m_pLocalBpm->get(); double local_bpm = 0; - mixxx::BeatsPointer pBeats = m_pBeats; + const mixxx::BeatsPointer pBeats = m_pBeats; if (pBeats) { local_bpm = pBeats->getBpmAroundPosition( getSampleOfTrack().current, kLocalBpmSpan); diff --git a/src/engine/controls/clockcontrol.cpp b/src/engine/controls/clockcontrol.cpp index 22cd4707bc..6dc574ea4b 100644 --- a/src/engine/controls/clockcontrol.cpp +++ b/src/engine/controls/clockcontrol.cpp @@ -47,7 |