Skip to content

Commit

Permalink
Use controller syncables in EngineSync [WIP]
Browse files Browse the repository at this point in the history
  • Loading branch information
Holzhaus committed Mar 14, 2021
1 parent 4ae9c5c commit 1c2e1f8
Show file tree
Hide file tree
Showing 6 changed files with 129 additions and 3 deletions.
15 changes: 14 additions & 1 deletion src/controllers/controllermanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#include "controllers/controllerlearningeventfilter.h"
#include "controllers/defs_controllers.h"
#include "controllers/midi/portmidienumerator.h"
#include "engine/enginemaster.h"
#include "engine/sync/enginesync.h"
#include "moc_controllermanager.cpp"
#include "util/cmdlineargs.h"
#include "util/time.h"
Expand Down Expand Up @@ -78,9 +80,10 @@ bool controllerCompare(Controller *a,Controller *b) {
return a->getName() < b->getName();
}

ControllerManager::ControllerManager(UserSettingsPointer pConfig)
ControllerManager::ControllerManager(UserSettingsPointer pConfig, EngineMaster* pMixingEngine)
: QObject(),
m_pConfig(pConfig),
m_pMixingEngine(pMixingEngine),
// WARNING: Do not parent m_pControllerLearningEventFilter to
// ControllerManager because the CM is moved to its own thread and runs
// its own event loop.
Expand Down Expand Up @@ -192,7 +195,17 @@ void ControllerManager::updateControllerList() {

locker.relock();
if (newDeviceList != m_controllers) {
m_pMixingEngine->getEngineSync()->setControllerSyncables({});
m_controllers = newDeviceList;

QList<std::shared_ptr<Syncable>> controllerSyncables;
for (const auto* pController : qAsConst(m_controllers)) {
const std::shared_ptr<Syncable> pSyncable = pController->syncable();
if (pSyncable != nullptr) {
controllerSyncables.append(pSyncable);
}
}
m_pMixingEngine->getEngineSync()->setControllerSyncables(controllerSyncables);
locker.unlock();
emit devicesChanged();
}
Expand Down
4 changes: 3 additions & 1 deletion src/controllers/controllermanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
// Forward declaration(s)
class Controller;
class ControllerLearningEventFilter;
class EngineMaster;

/// Function to sort controllers by name
bool controllerCompare(Controller *a, Controller *b);
Expand All @@ -20,7 +21,7 @@ bool controllerCompare(Controller *a, Controller *b);
class ControllerManager : public QObject {
Q_OBJECT
public:
ControllerManager(UserSettingsPointer pConfig);
ControllerManager(UserSettingsPointer pConfig, EngineMaster* pMixingEngine);
virtual ~ControllerManager();

static const mixxx::Duration kPollInterval;
Expand Down Expand Up @@ -73,6 +74,7 @@ class ControllerManager : public QObject {

private:
UserSettingsPointer m_pConfig;
EngineMaster* m_pMixingEngine;
ControllerLearningEventFilter* m_pControllerLearningEventFilter;
QTimer m_pollTimer;
mutable QMutex m_mutex;
Expand Down
2 changes: 1 addition & 1 deletion src/coreservices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,7 @@ void CoreServices::initialize(QApplication* pApp) {
// but do not set up controllers until the end of the application startup
// (long)
qDebug() << "Creating ControllerManager";
m_pControllerManager = std::make_shared<ControllerManager>(pConfig);
m_pControllerManager = std::make_shared<ControllerManager>(pConfig, m_pEngine.get());

// Inhibit the screensaver if the option is set. (Do it before creating the preferences dialog)
int inhibit = pConfig->getValue<int>(ConfigKey("[Config]", "InhibitScreensaver"), -1);
Expand Down
46 changes: 46 additions & 0 deletions src/engine/sync/basesyncablelistener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ bool BaseSyncableListener::syncDeckExists() const {
return true;
}
}
for (const auto& pSyncable : qAsConst(m_controllerSyncables)) {
if (pSyncable->isSynchronized() && pSyncable->getBaseBpm() > 0) {
return true;
}
}
return false;
}

Expand Down Expand Up @@ -96,6 +101,13 @@ void BaseSyncableListener::setMasterBpm(Syncable* pSource, double bpm) {
}
pSyncable->setMasterBpm(bpm);
}
for (const auto& pSyncable : qAsConst(m_controllerSyncables)) {
if (pSyncable.get() == pSource ||
!pSyncable->isSynchronized()) {
continue;
}
pSyncable->setMasterBpm(bpm);
}
}

void BaseSyncableListener::setMasterInstantaneousBpm(Syncable* pSource, double bpm) {
Expand All @@ -109,6 +121,13 @@ void BaseSyncableListener::setMasterInstantaneousBpm(Syncable* pSource, double b
}
pSyncable->setInstantaneousBpm(bpm);
}
for (const auto& pSyncable : qAsConst(m_controllerSyncables)) {
if (pSyncable.get() == pSource ||
!pSyncable->isSynchronized()) {
continue;
}
pSyncable->setInstantaneousBpm(bpm);
}
}

void BaseSyncableListener::setMasterBeatDistance(Syncable* pSource, double beat_distance) {
Expand All @@ -122,6 +141,13 @@ void BaseSyncableListener::setMasterBeatDistance(Syncable* pSource, double beat_
}
pSyncable->setMasterBeatDistance(beat_distance);
}
for (const auto& pSyncable : qAsConst(m_controllerSyncables)) {
if (pSyncable.get() == pSource ||
!pSyncable->isSynchronized()) {
continue;
}
pSyncable->setMasterBeatDistance(beat_distance);
}
}

void BaseSyncableListener::setMasterParams(Syncable* pSource, double beat_distance,
Expand All @@ -137,6 +163,13 @@ void BaseSyncableListener::setMasterParams(Syncable* pSource, double beat_distan
}
pSyncable->setMasterParams(beat_distance, base_bpm, bpm);
}
for (const auto& pSyncable : qAsConst(m_controllerSyncables)) {
if (pSyncable.get() == pSource ||
!pSyncable->isSynchronized()) {
continue;
}
pSyncable->setMasterParams(beat_distance, base_bpm, bpm);
}
}

void BaseSyncableListener::checkUniquePlayingSyncable() {
Expand All @@ -155,6 +188,19 @@ void BaseSyncableListener::checkUniquePlayingSyncable() {
++playing_sync_decks;
}
}
for (const auto& pSyncable : qAsConst(m_controllerSyncables)) {
if (!pSyncable->isSynchronized()) {
continue;
}

if (pSyncable->isPlaying()) {
if (playing_sync_decks > 0) {
return;
}
unique_syncable = pSyncable.get();
++playing_sync_decks;
}
}
if (playing_sync_decks == 1) {
unique_syncable->notifyOnlyPlayingSyncable();
}
Expand Down
8 changes: 8 additions & 0 deletions src/engine/sync/basesyncablelistener.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#pragma once

#include <QList>
#include <memory>

#include "engine/sync/syncable.h"
#include "preferences/usersettings.h"

Expand All @@ -21,6 +24,10 @@ class BaseSyncableListener : public SyncableListener {
void onCallbackStart(int sampleRate, int bufferSize);
void onCallbackEnd(int sampleRate, int bufferSize);

void setControllerSyncables(const QList<std::shared_ptr<Syncable>>& syncables) {
m_controllerSyncables = syncables;
}

// Only for testing. Do not use.
Syncable* getSyncableForGroup(const QString& group);
Syncable* getMasterSyncable() override {
Expand Down Expand Up @@ -69,4 +76,5 @@ class BaseSyncableListener : public SyncableListener {
// The list of all Syncables registered with BaseSyncableListener via
// addSyncableDeck.
QList<Syncable*> m_syncables;
QList<std::shared_ptr<Syncable>> m_controllerSyncables;
};
57 changes: 57 additions & 0 deletions src/engine/sync/enginesync.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,29 @@ Syncable* EngineSync::pickMaster(Syncable* enabling_syncable) {
stopped_deck_count++;
}
}
for (const auto& pSyncable : qAsConst(m_controllerSyncables)) {
if (pSyncable->getBaseBpm() <= 0.0) {
continue;
}

if (pSyncable.get() != enabling_syncable) {
if (!pSyncable->isSynchronized()) {
continue;
}
}

if (pSyncable->isPlaying()) {
if (playing_deck_count == 0) {
first_playing_deck = pSyncable.get();
}
playing_deck_count++;
} else {
if (stopped_deck_count == 0) {
first_stopped_deck = pSyncable.get();
}
stopped_deck_count++;
}
}

if (playing_deck_count == 1) {
return first_playing_deck;
Expand Down Expand Up @@ -147,6 +170,28 @@ Syncable* EngineSync::findBpmMatchTarget(Syncable* requester) {
}
}

for (const auto& pOtherSyncable : qAsConst(m_controllerSyncables)) {
if (pOtherSyncable.get() == requester) {
continue;
}
if (pOtherSyncable->getBaseBpm() == 0.0) {
continue;
}

// If the other deck is playing we stop looking immediately. Otherwise continue looking
// for a playing deck with bpm > 0.0.
if (pOtherSyncable->isPlaying()) {
return pOtherSyncable.get();
}

// The target is not playing. If this is the first one we have seen,
// record it. If we never find a playing target, we'll return
// this one as a fallback.
if (!pStoppedTarget && !requester->isPlaying()) {
pStoppedTarget = pOtherSyncable.get();
}
}

return pStoppedTarget;
}

Expand Down Expand Up @@ -470,5 +515,17 @@ bool EngineSync::otherSyncedPlaying(const QString& group) {
othersInSync = true;
}
}
for (const auto& theSyncable : qAsConst(m_controllerSyncables)) {
bool isSynchonized = theSyncable->isSynchronized();
if (theSyncable->getGroup() == group) {
if (!isSynchonized) {
return false;
}
continue;
}
if (theSyncable->isPlaying() && isSynchonized) {
othersInSync = true;
}
}
return othersInSync;
}

0 comments on commit 1c2e1f8

Please sign in to comment.