summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDaniel Schürmann <daschuer@mixxx.org>2019-01-06 01:04:08 +0100
committerDaniel Schürmann <daschuer@mixxx.org>2019-01-06 01:10:00 +0100
commit5a4444d520f97321bfdae6cd22c28fa1a7f835ec (patch)
treefa487c171372273ee7c2efc4b3ad94903f80402e /src
parent03dff4353f2fdec2d72fd0d384545bf681e71022 (diff)
Added new VisualsManager class
Diffstat (limited to 'src')
-rw-r--r--src/engine/enginebuffer.cpp49
-rw-r--r--src/engine/enginebuffer.h11
-rw-r--r--src/engine/enginedeck.cpp1
-rw-r--r--src/mixer/basetrackplayer.cpp4
-rw-r--r--src/mixer/basetrackplayer.h2
-rw-r--r--src/mixer/deck.cpp3
-rw-r--r--src/mixer/deck.h1
-rw-r--r--src/mixer/playermanager.cpp11
-rw-r--r--src/mixer/playermanager.h3
-rw-r--r--src/mixer/previewdeck.cpp3
-rw-r--r--src/mixer/previewdeck.h1
-rw-r--r--src/mixer/sampler.cpp3
-rw-r--r--src/mixer/sampler.h1
-rw-r--r--src/mixxx.cpp7
-rw-r--r--src/mixxx.h2
-rw-r--r--src/test/signalpathtest.h15
-rw-r--r--src/waveform/visualplayposition.cpp11
-rw-r--r--src/waveform/visualplayposition.h1
-rw-r--r--src/waveform/visualsmanager.cpp66
-rw-r--r--src/waveform/visualsmanager.h55
-rw-r--r--src/waveform/waveformwidgetfactory.cpp6
-rw-r--r--src/waveform/waveformwidgetfactory.h4
22 files changed, 184 insertions, 76 deletions
diff --git a/src/engine/enginebuffer.cpp b/src/engine/enginebuffer.cpp
index f5c8a68170..7788221ac1 100644
--- a/src/engine/enginebuffer.cpp
+++ b/src/engine/enginebuffer.cpp
@@ -50,7 +50,7 @@ const SINT kSamplesPerFrame = 2; // Engine buffer uses Stereo frames only
} // anonymous namespace
-EngineBuffer::EngineBuffer(QString group, UserSettingsPointer pConfig,
+EngineBuffer::EngineBuffer(const QString& group, UserSettingsPointer pConfig,
EngineChannel* pChannel, EngineMaster* pMixingEngine)
: m_group(group),
m_pConfig(pConfig),
@@ -72,8 +72,6 @@ EngineBuffer::EngineBuffer(QString group, UserSettingsPointer pConfig,
m_rate_old(0.),
m_trackSamplesOld(0),
m_trackSampleRateOld(0),
- m_iSamplesSinceLastIndicatorUpdate(0),
- m_iUiSlowTick(0),
m_dSlipPosition(0.),
m_dSlipRate(1.0),
m_bSlipEnabledProcessing(false),
@@ -146,14 +144,6 @@ EngineBuffer::EngineBuffer(QString group, UserSettingsPointer pConfig,
m_pSlipButton = new ControlPushButton(ConfigKey(m_group, "slip_enabled"));
m_pSlipButton->setButtonMode(ControlPushButton::TOGGLE);
- // BPM to display in the UI (updated more slowly than the actual bpm)
- m_visualBpm = new ControlObject(ConfigKey(m_group, "visual_bpm"));
- m_visualKey = new ControlObject(ConfigKey(m_group, "visual_key"));
-
- m_timeElapsed = new ControlObject(ConfigKey(m_group, "time_elapsed"));
- m_timeRemaining = new ControlObject(ConfigKey(m_group, "time_remaining"));
- m_pEndOfTrack = std::make_unique<ControlObject>(ConfigKey(group, "end_of_track"));
-
m_playposSlider = new ControlLinPotmeter(
ConfigKey(m_group, "playposition"), 0.0, 1.0, 0, 0, true);
connect(m_playposSlider, SIGNAL(valueChanged(double)),
@@ -282,15 +272,10 @@ EngineBuffer::~EngineBuffer() {
delete m_playStartButton;
delete m_stopStartButton;
- delete m_timeElapsed;
- delete m_timeRemaining;
-
delete m_startButton;
delete m_endButton;
delete m_stopButton;
delete m_playposSlider;
- delete m_visualBpm;
- delete m_visualKey;
delete m_pSlipButton;
delete m_pRepeat;
@@ -550,11 +535,6 @@ void EngineBuffer::ejectTrack() {
TrackPointer pTrack = m_pCurrentTrack;
m_pCurrentTrack.reset();
m_playButton->set(0.0);
- m_visualBpm->set(0.0);
- m_visualKey->set(0.0);
- m_timeElapsed->set(0);
- m_timeRemaining->set(0);
- m_pEndOfTrack->set(0.0);
m_playposSlider->set(0);
m_pCueControl->resetIndicators();
doSeekFractional(0.0, SEEK_EXACT);
@@ -1224,35 +1204,8 @@ void EngineBuffer::updateIndicators(double speed, int iBufferSize) {
// Update indicators that are only updated after every
// sampleRate/kiUpdateRate samples processed. (e.g. playposSlider)
if (m_iSamplesSinceLastIndicatorUpdate > (kSamplesPerFrame * m_pSampleRate->get() / kiPlaypositionUpdateRate)) {
- double timeRemaining = (1.0 - fFractionalPlaypos) * tempoTrackSeconds;
- m_timeRemaining->set(timeRemaining);
- m_timeElapsed->set(tempoTrackSeconds - timeRemaining);
-
- auto pFactory = WaveformWidgetFactory::instance();
- double remainingTimeTriggerSeconds = pFactory ? pFactory->getEndOfTrackWarningTime() : 0;
-
- if (!m_playButton->toBool() || // not playing
- m_pLoopingControl->isLoopingEnabled() || // in loop
- tempoTrackSeconds <= remainingTimeTriggerSeconds || // track too short
- timeRemaining > remainingTimeTriggerSeconds // before the trigger
- ) {
- m_pEndOfTrack->set(0.0);
- } else {
- m_pEndOfTrack->set(1.0);
- }
-
m_playposSlider->set(fFractionalPlaypos);
m_pCueControl->updateIndicators();
-
- // Update the BPM even more slowly
- m_iUiSlowTick = (m_iUiSlowTick + 1) % kiBpmUpdateCnt;
- if (m_iUiSlowTick == 0) {
- m_visualBpm->set(m_pBpmControl->getBpm());
- }
- m_visualKey->set(m_pKeyControl->getKey());
-
- // Reset sample counter
- m_iSamplesSinceLastIndicatorUpdate = 0;
}
// Update visual control object, this needs to be done more often than the
diff --git a/src/engine/enginebuffer.h b/src/engine/enginebuffer.h
index b1be907595..1a477d67a2 100644
--- a/src/engine/enginebuffer.h
+++ b/src/engine/enginebuffer.h
@@ -76,8 +76,6 @@ const int kiTempLength = 200000;
// Rate at which the playpos slider is updated
const int kiPlaypositionUpdateRate = 15; // updates per second
-// Number of kiUpdateRates that go by before we update BPM.
-const int kiBpmUpdateCnt = 4; // about 3.75 updates per sec
class EngineBuffer : public EngineObject {
Q_OBJECT
@@ -113,7 +111,7 @@ class EngineBuffer : public EngineObject {
KEYLOCK_ENGINE_COUNT,
};
- EngineBuffer(QString _group, UserSettingsPointer pConfig,
+ EngineBuffer(const QString& group, UserSettingsPointer pConfig,
EngineChannel* pChannel, EngineMaster* pMixingEngine);
virtual ~EngineBuffer();
@@ -311,7 +309,6 @@ class EngineBuffer : public EngineObject {
QMutex m_pause;
// Used in update of playpos slider
int m_iSamplesSinceLastIndicatorUpdate;
- int m_iUiSlowTick;
// The location where the track would have been had slip not been engaged
double m_dSlipPosition;
@@ -332,19 +329,13 @@ class EngineBuffer : public EngineObject {
ControlObject* m_backButton;
ControlPushButton* m_pSlipButton;
- ControlObject* m_visualBpm;
- ControlObject* m_visualKey;
ControlObject* m_pQuantize;
ControlObject* m_pMasterRate;
- ControlObject* m_timeElapsed;
- ControlObject* m_timeRemaining;
ControlPotmeter* m_playposSlider;
ControlProxy* m_pSampleRate;
ControlProxy* m_pKeylockEngine;
ControlPushButton* m_pKeylock;
- std::unique_ptr<ControlObject> m_pEndOfTrack;
-
// This ControlProxys is created as parent to this and deleted by
// the Qt object tree. This helps that they are deleted by the creating
// thread, which is required to avoid segfaults.
diff --git a/src/engine/enginedeck.cpp b/src/engine/enginedeck.cpp
index 0304e055b7..65453be3cf 100644
--- a/src/engine/enginedeck.cpp
+++ b/src/engine/enginedeck.cpp
@@ -25,6 +25,7 @@
#include "engine/enginepregain.h"
#include "engine/enginevumeter.h"
#include "util/sample.h"
+#include "waveform/waveformwidgetfactory.h"
EngineDeck::EngineDeck(const ChannelHandleAndGroup& handle_group,
UserSettingsPointer pConfig,
diff --git a/src/mixer/basetrackplayer.cpp b/src/mixer/basetrackplayer.cpp
index f4a50db2a7..10fdcbf793 100644
--- a/src/mixer/basetrackplayer.cpp
+++ b/src/mixer/basetrackplayer.cpp
@@ -1,3 +1,4 @@
+#include <waveform/visualsmanager.h>
#include <QMessageBox>
#include "mixer/basetrackplayer.h"
@@ -28,6 +29,7 @@ BaseTrackPlayerImpl::BaseTrackPlayerImpl(QObject* pParent,
UserSettingsPointer pConfig,
EngineMaster* pMixingEngine,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineChannel::ChannelOrientation defaultOrientation,
const QString& group,
bool defaultMaster,
@@ -106,6 +108,8 @@ BaseTrackPlayerImpl::BaseTrackPlayerImpl(QObject* pParent,
m_pReplayGain = std::make_unique<ControlProxy>(group, "replaygain", this);
m_pPlay = std::make_unique<ControlProxy>(group, "play", this);
m_pPlay->connectValueChanged(SLOT(slotPlayToggled(double)));
+
+ pVisualsManager->addDeck(group);
}
BaseTrackPlayerImpl::~BaseTrackPlayerImpl() {
diff --git a/src/mixer/basetrackplayer.h b/src/mixer/basetrackplayer.h
index e814497fb0..ce50d5a441 100644
--- a/src/mixer/basetrackplayer.h
+++ b/src/mixer/basetrackplayer.h
@@ -17,6 +17,7 @@ class ControlObject;
class ControlPotmeter;
class ControlProxy;
class EffectsManager;
+class VisualsManager;
// Interface for not leaking implementation details of BaseTrackPlayer into the
// rest of Mixxx. Also makes testing a lot easier.
@@ -53,6 +54,7 @@ class BaseTrackPlayerImpl : public BaseTrackPlayer {
UserSettingsPointer pConfig,
EngineMaster* pMixingEngine,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineChannel::ChannelOrientation defaultOrientation,
const QString& group,
bool defaultMaster,
diff --git a/src/mixer/deck.cpp b/src/mixer/deck.cpp
index 5e68611188..9b584a8024 100644
--- a/src/mixer/deck.cpp
+++ b/src/mixer/deck.cpp
@@ -4,10 +4,11 @@ Deck::Deck(QObject* pParent,
UserSettingsPointer pConfig,
EngineMaster* pMixingEngine,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineChannel::ChannelOrientation defaultOrientation,
const QString& group) :
BaseTrackPlayerImpl(pParent, pConfig, pMixingEngine, pEffectsManager,
- defaultOrientation, group, true, false) {
+ pVisualsManager, defaultOrientation, group, true, false) {
}
Deck::~Deck() {
diff --git a/src/mixer/deck.h b/src/mixer/deck.h
index d596985ee6..561c37b032 100644
--- a/src/mixer/deck.h
+++ b/src/mixer/deck.h
@@ -12,6 +12,7 @@ class Deck : public BaseTrackPlayerImpl {
UserSettingsPointer pConfig,
EngineMaster* pMixingEngine,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineChannel::ChannelOrientation defaultOrientation,
const QString& group);
virtual ~Deck();
diff --git a/src/mixer/playermanager.cpp b/src/mixer/playermanager.cpp
index 866c3f7b12..5a3ed6b547 100644
--- a/src/mixer/playermanager.cpp
+++ b/src/mixer/playermanager.cpp
@@ -34,11 +34,13 @@ QAtomicPointer<ControlProxy> PlayerManager::m_pCOPNumPreviewDecks;
PlayerManager::PlayerManager(UserSettingsPointer pConfig,
SoundManager* pSoundManager,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineMaster* pEngine) :
m_mutex(QMutex::Recursive),
m_pConfig(pConfig),
m_pSoundManager(pSoundManager),
m_pEffectsManager(pEffectsManager),
+ m_pVisualsManager(pVisualsManager),
m_pEngine(pEngine),
// NOTE(XXX) LegacySkinParser relies on these controls being Controls
// and not ControlProxies.
@@ -339,7 +341,7 @@ void PlayerManager::addDeckInner() {
}
Deck* pDeck = new Deck(this, m_pConfig, m_pEngine, m_pEffectsManager,
- orientation, group);
+ m_pVisualsManager, orientation, group);
connect(pDeck, SIGNAL(noPassthroughInputConfigured()),
this, SIGNAL(noDeckPassthroughInputConfigured()));
connect(pDeck, SIGNAL(noVinylControlInputConfigured()),
@@ -405,8 +407,8 @@ void PlayerManager::addSamplerInner() {
EngineChannel::ChannelOrientation orientation = EngineChannel::CENTER;
Sampler* pSampler = new Sampler(this, m_pConfig, m_pEngine,
- m_pEffectsManager, orientation, group);
- if (m_pAnalyzerQueue) {
+ m_pEffectsManager, m_pVisualsManager, orientation, group);
+ if (m_pAnalyzerQueue) {
connect(pSampler, SIGNAL(newTrackLoaded(TrackPointer)),
m_pAnalyzerQueue, SLOT(slotAnalyseTrack(TrackPointer)));
}
@@ -431,8 +433,7 @@ void PlayerManager::addPreviewDeckInner() {
EngineChannel::ChannelOrientation orientation = EngineChannel::CENTER;
PreviewDeck* pPreviewDeck = new PreviewDeck(this, m_pConfig, m_pEngine,
- m_pEffectsManager, orientation,
- group);
+ m_pEffectsManager, m_pVisualsManager, orientation, group);
if (m_pAnalyzerQueue) {
connect(pPreviewDeck, SIGNAL(newTrackLoaded(TrackPointer)),
m_pAnalyzerQueue, SLOT(slotAnalyseTrack(TrackPointer)));
diff --git a/src/mixer/playermanager.h b/src/mixer/playermanager.h
index 98d8ba60ef..2958d58ee0 100644
--- a/src/mixer/playermanager.h
+++ b/src/mixer/playermanager.h
@@ -25,6 +25,7 @@ class PreviewDeck;
class Sampler;
class SamplerBank;
class SoundManager;
+class VisualsManager;
// For mocking PlayerManager.
class PlayerManagerInterface {
@@ -60,6 +61,7 @@ class PlayerManager : public QObject, public PlayerManagerInterface {
PlayerManager(UserSettingsPointer pConfig,
SoundManager* pSoundManager,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineMaster* pEngine);
virtual ~PlayerManager();
@@ -241,6 +243,7 @@ class PlayerManager : public QObject, public PlayerManagerInterface {
UserSettingsPointer m_pConfig;
SoundManager* m_pSoundManager;
EffectsManager* m_pEffectsManager;
+ VisualsManager* m_pVisualsManager;
EngineMaster* m_pEngine;
SamplerBank* m_pSamplerBank;
AnalyzerQueue* m_pAnalyzerQueue;
diff --git a/src/mixer/previewdeck.cpp b/src/mixer/previewdeck.cpp
index dba001ea16..f30ca48573 100644
--- a/src/mixer/previewdeck.cpp
+++ b/src/mixer/previewdeck.cpp
@@ -4,10 +4,11 @@ PreviewDeck::PreviewDeck(QObject* pParent,
UserSettingsPointer pConfig,
EngineMaster* pMixingEngine,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineChannel::ChannelOrientation defaultOrientation,
QString group) :
BaseTrackPlayerImpl(pParent, pConfig, pMixingEngine, pEffectsManager,
- defaultOrientation, group, false, true) {
+ pVisualsManager, defaultOrientation, group, false, true) {
}
PreviewDeck::~PreviewDeck() {
diff --git a/src/mixer/previewdeck.h b/src/mixer/previewdeck.h
index a5c6128770..63ad2b2768 100644
--- a/src/mixer/previewdeck.h
+++ b/src/mixer/previewdeck.h
@@ -10,6 +10,7 @@ class PreviewDeck : public BaseTrackPlayerImpl {
UserSettingsPointer pConfig,
EngineMaster* pMixingEngine,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineChannel::ChannelOrientation defaultOrientation,
QString group);
virtual ~PreviewDeck();
diff --git a/src/mixer/sampler.cpp b/src/mixer/sampler.cpp
index b086c1b2ca..d378e1839a 100644
--- a/src/mixer/sampler.cpp
+++ b/src/mixer/sampler.cpp
@@ -6,10 +6,11 @@ Sampler::Sampler(QObject* pParent,
UserSettingsPointer pConfig,
EngineMaster* pMixingEngine,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineChannel::ChannelOrientation defaultOrientation,
QString group) :
BaseTrackPlayerImpl(pParent, pConfig, pMixingEngine, pEffectsManager,
- defaultOrientation, group, true, false) {
+ pVisualsManager, defaultOrientation, group, true, false) {
}
Sampler::~Sampler() {
diff --git a/src/mixer/sampler.h b/src/mixer/sampler.h
index e2e0422ac3..20e7481338 100644
--- a/src/mixer/sampler.h
+++ b/src/mixer/sampler.h
@@ -10,6 +10,7 @@ class Sampler : public BaseTrackPlayerImpl {
UserSettingsPointer pConfig,
EngineMaster* pMixingEngine,
EffectsManager* pEffectsManager,
+ VisualsManager* pVisualsManager,
EngineChannel::ChannelOrientation defaultOrientation,
QString group);
virtual ~Sampler();
diff --git a/src/mixxx.cpp b/src/mixxx.cpp
index 6246dcc2a7..fa1f80da26 100644
--- a/src/mixxx.cpp
+++ b/src/mixxx.cpp
@@ -51,6 +51,7 @@
#include "sources/soundsourceproxy.h"
#include "track/track.h"
#include "waveform/waveformwidgetfactory.h"
+#include <waveform/visualsmanager.h>
#include "waveform/sharedglcontext.h"
#include "database/mixxxdb.h"
#include "util/debug.h"
@@ -264,6 +265,7 @@ void MixxxMainWindow::initialize(QApplication* pApp, const CmdlineArgs& args) {
// Needs to be created before CueControl (decks) and WTrackTableView.
m_pGuiTick = new GuiTick();
+ m_pVisualsManager = new VisualsManager();
#ifdef __VINYLCONTROL__
m_pVCManager = new VinylControlManager(this, pConfig, m_pSoundManager);
@@ -273,7 +275,7 @@ void MixxxMainWindow::initialize(QApplication* pApp, const CmdlineArgs& args) {
// Create the player manager. (long)
m_pPlayerManager = new PlayerManager(pConfig, m_pSoundManager,
- m_pEffectsManager, m_pEngine);
+ m_pEffectsManager, m_pVisualsManager, m_pEngine);
connect(m_pPlayerManager, SIGNAL(noMicrophoneInputConfigured()),
this, SLOT(slotNoMicrophoneInputConfigured()));
connect(m_pPlayerManager, SIGNAL(noDeckPassthroughInputConfigured()),
@@ -380,7 +382,7 @@ void MixxxMainWindow::initialize(QApplication* pApp, const CmdlineArgs& args) {
launchProgress(47);
WaveformWidgetFactory::createInstance(); // takes a long time
- WaveformWidgetFactory::instance()->startVSync(m_pGuiTick);
+ WaveformWidgetFactory::instance()->startVSync(m_pGuiTick, m_pVisualsManager);
WaveformWidgetFactory::instance()->setConfig(pConfig);
launchProgress(52);
@@ -671,6 +673,7 @@ void MixxxMainWindow::finalize() {
WaveformWidgetFactory::destroy();
delete m_pGuiTick;
+ delete m_pVisualsManager;
// Check for leaked ControlObjects and give warnings.
QList<QSharedPointer<ControlDoublePrivate> > leakedControls;
diff --git a/src/mixxx.h b/src/mixxx.h
index 4559890144..cb2549ed0a 100644
--- a/src/mixxx.h
+++ b/src/mixxx.h
@@ -39,6 +39,7 @@ class DlgPreferences;
class EffectsManager;
class EngineMaster;
class GuiTick;
+class VisualsManager;
class LaunchImage;
class Library;
class KeyboardEventFilter;
@@ -166,6 +167,7 @@ class MixxxMainWindow : public QMainWindow {
ControllerManager* m_pControllerManager;
GuiTick* m_pGuiTick;
+ VisualsManager* m_pVisualsManager;
VinylControlManager* m_pVCManager;
diff --git a/src/test/signalpathtest.h b/src/test/signalpathtest.h
index 4d5c0fcafc..8ba05359ce 100644
--- a/src/test/signalpathtest.h
+++ b/src/test/signalpathtest.h
@@ -26,6 +26,7 @@
#include "util/sample.h"
#include "util/types.h"
#include "waveform/guitick.h"
+#include "waveform/visualsmanager.h"
using ::testing::Return;
using ::testing::_;
@@ -58,27 +59,27 @@ class BaseSignalPathTest : public MixxxTest {
m_pChannelHandleFactory = new ChannelHandleFactory();
m_pNumDecks = new ControlObject(ConfigKey("[Master]", "num_decks"));
m_pEffectsManager = new EffectsManager(NULL, config(), m_pChannelHandleFactory);
+ m_pVisualsManager = new VisualsManager();
m_pEngineMaster = new TestEngineMaster(m_pConfig, "[Master]",
m_pEffectsManager, m_pChannelHandleFactory,
false);
m_pMixerDeck1 = new Deck(NULL, m_pConfig, m_pEngineMaster, m_pEffectsManager,
- EngineChannel::CENTER, m_sGroup1);
+ m_pVisualsManager, EngineChannel::CENTER, m_sGroup1);
m_pMixerDeck1->setupEqControls();
m_pMixerDeck2 = new Deck(NULL, m_pConfig, m_pEngineMaster, m_pEffectsManager,
- EngineChannel::CENTER, m_sGroup2);
+ m_pVisualsManager, EngineChannel::CENTER, m_sGroup2);
m_pMixerDeck2->setupEqControls();
m_pMixerDeck3 = new Deck(NULL, m_pConfig, m_pEngineMaster, m_pEffectsManager,
- EngineChannel::CENTER, m_sGroup3);
+ m_pVisualsManager, EngineChannel::CENTER, m_sGroup3);
m_pMixerDeck3->setupEqControls();
m_pChannel1 = m_pMixerDeck1->getEngineDeck();
m_pChannel2 = m_pMixerDeck2->getEngineDeck();
m_pChannel3 = m_pMixerDeck3->getEngineDeck();
- m_pPreview1 = new PreviewDeck(NULL, m_pConfig,
- m_pEngineMaster, m_pEffectsManager,
- EngineChannel::CENTER, m_sPreviewGroup);
+ m_pPreview1 = new PreviewDeck(NULL, m_pConfig, m_pEngineMaster, m_pEffectsManager,
+ m_pVisualsManager, EngineChannel::CENTER, m_sPreviewGroup);
ControlObject::set(ConfigKey(m_sPreviewGroup, "file_bpm"), 2.0);
// TODO(owilliams) Tests fail with this turned on because EngineSync is syncing
@@ -109,6 +110,7 @@ class BaseSignalPathTest : public MixxxTest {
// Deletes all EngineChannels added to it.
delete m_pEngineMaster;
delete m_pEffectsManager;
+ delete m_pVisualsManager;
delete m_pNumDecks;
}
@@ -201,6 +203,7 @@ class BaseSignalPathTest : public MixxxTest {
ChannelHandleFactory* m_pChannelHandleFactory;
ControlObject* m_pNumDecks;
std::unique_ptr<GuiTick> m_pGuiTick;
+ VisualsManager* m_pVisualsManager;
EffectsManager* m_pEffectsManager;
EngineSync* m_pEngineSync;
TestEngineMaster* m_pEngineMaster;
diff --git a/src/waveform/visualplayposition.cpp b/src/waveform/visualplayposition.cpp
index aae57cb5d0..8b4870307e 100644
--- a/src/waveform/visualplayposition.cpp
+++ b/src/waveform/visualplayposition.cpp
@@ -98,6 +98,17 @@ double VisualPlayPosition::getEnginePlayPos() {
}
}
+void VisualPlayPosition::getTrackTime(double* pPlayPosition, double* pTempoTrackSeconds) {
+ if (m_valid) {
+ VisualPlayPositionData data = m_data.getValue();
+ *pPlayPosition = data.m_enginePlayPos;
+ *pTempoTrackSeconds = data.m_tempoTrackSeconds;
+ } else {
+ *pPlayPosition = 0;
+ *pTempoTrackSeconds = 0;
+ }
+}
+
void VisualPlayPosition::slotAudioBufferSizeChanged(double sizeMillis) {
m_audioBufferMicros = static_cast<int>(sizeMillis * kMicrosPerMillis);
}
diff --git a/src/waveform/visualplayposition.h b/src/waveform/visualplayposition.h
index 699b3ae9e8..0095a3b57f 100644
--- a/src/waveform/visualplayposition.h
+++ b/src/waveform/visualplayposition.h
@@ -51,6 +51,7 @@ class VisualPlayPosition : public QObject {
double getAtNextVSync(VSyncThread* vsyncThread);
void getPlaySlipAt(int usFromNow, double* playPosition, double* slipPosition);
double getEnginePlayPos();
+ void getTrackTime(double* pPlayPosition, double* pTempoTrackSeconds);
// WARNING: Not thread safe. This function must only be called from the main
// thread.
diff --git a/src/waveform/visualsmanager.cpp b/src/waveform/visualsmanager.cpp
new file mode 100644
index 0000000000..aae8093c75
--- /dev/null
+++ b/src/waveform/visualsmanager.cpp
@@ -0,0 +1,66 @@
+#include "waveform/visualsmanager.h"
+
+#include "waveform/waveformwidgetfactory.h"
+#include "control/controlobject.h"
+
+namespace {
+ // Rate at which the playpos slider is updated
+ const int kUpdateRate = 15; // updates per second
+ // Number of kiUpdateRates that go by before we update BPM.
+ const int kSlowUpdateDivider = 4; // kUpdateRate / kSlowUpdateDivider = 3.75 updates per sec
+}
+
+DeckVisuals::DeckVisuals(const QString& group)
+ : m_group(group),
+ m_SlowTickCnt(0),
+ playButton(ConfigKey(group, "play")),
+ loopEnabled(ConfigKey(group, "loop_enabled")),
+ engineBpm(ConfigKey(group, "bpm")),
+ engineKey(ConfigKey(group, "key")) {
+ m_pTimeElapsed = std::make_unique<ControlObject>(ConfigKey(m_group, "time_elapsed"));
+ m_pTimeRemaining = std::make_unique<ControlObject>(ConfigKey(m_group, "time_remaining"));
+ m_pEndOfTrack = std::make_unique<ControlObject>(ConfigKey(group, "end_of_track"));
+ m_pVisualBpm = std::make_unique<ControlObject>(ConfigKey(m_group, "visual_bpm"));
+ m_pVisualKey = std::make_unique<ControlObject>(ConfigKey(m_group, "visual_key"));
+
+ // Control used to communicate ratio playpos to GUI thread
+ m_pVisualPlayPos = VisualPlayPosition::getVisualPlayPosition(m_group);
+
+ m_cpuTimer.start();
+}
+
+// this is called from WaveformWidgetFactory::render in the main thread with the
+// configured waveform frame rate
+void DeckVisuals::process(double remainingTimeTriggerSeconds) {
+ if (m_cpuTimer.elapsed() >= mixxx::Duration::fromMillis(1000 / kUpdateRate)) {
+ m_cpuTimer.restart();
+
+ double playPosition;
+ double tempoTrackSeconds;
+ m_pVisualPlayPos->getTrackTime(&playPosition, &tempoTrackSeconds);
+
+ double timeRemaining = (1.0 - playPosition) * tempoTrackSeconds;
+ m_pTimeRemaining->set(timeRemaining);
+ m_pTimeElapsed->set(tempoTrackSeconds - timeRemaining);
+
+ if (!playButton.toBool() || // not playing
+ loopEnabled.toBool() || // in loop
+ tempoTrackSeconds <= remainingTimeTriggerSeconds || // track too short
+ timeRemaining > remainingTimeTriggerSeconds // before the trigger
+ ) {
+ m_pEndOfTrack->set(0.0);
+ } else {
+ m_pEndOfTrack->set(1.0);
+ }
+
+ // m_playposSlider->set(fFractionalPlaypos);
+ // m_pCueControl->updateIndicators();
+
+ // Update the BPM even more slowly
+ m_SlowTickCnt = (m_SlowTickCnt + 1) % kSlowUpdateDivider;
+ if (m_SlowTickCnt == 0) {
+ m_pVisualBpm->set(engineBpm.get());
+ }
+ m_pVisualKey->set(engineKey.get());
+ }
+}
diff --git a/src/waveform/visualsmanager.h b/src/waveform/visualsmanager.h
new file mode 100644
index 0000000000..214f64b383
--- /dev/null
+++ b/src/waveform/visualsmanager.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include "control/controlobject.h"
+#include "control/controlproxy.h"
+#include "util/duration.h"
+#include "util/memory.h"
+#include "util/performancetimer.h"
+#include "waveform/visualplayposition.h"
+
+#include <vector>
+
+// This calss updates the controls used for widgets and
+// controler indicator, in a CPU saving way and outside the engine thread
+class DeckVisuals {
+ public:
+ DeckVisuals(const QString& group);
+ void process(double remainingTimeTriggerSeconds);
+
+ private:
+ QString m_group;
+ PerformanceTimer m_cpuTimer;
+ mixxx::Duration m_lastUpdateTime;
+ int m_SlowTickCnt;
+
+ std::unique_ptr<ControlObject> m_pTimeElapsed;
+ std::unique_ptr<ControlObject> m_pTimeRemaining;
+ std::unique_ptr<ControlObject> m_pEndOfTrack;
+ std::unique_ptr<ControlObject> m_pVisualBpm;
+ std::unique_ptr<ControlObject> m_pVisualKey;
+
+ ControlProxy playButton;
+ ControlProxy loopEnabled;
+ ControlProxy engineBpm;
+ ControlProxy engineKey;
+
+ //std::unique_ptr<ControlObject> m_playposSlider;
+
+ QSharedPointer<VisualPlayPosition> m_pVisualPlayPos;
+};
+
+class VisualsManager {
+ public:
+ void addDeck(const QString& group) {
+ m_deckVisuals.push_back(
+ std::make_unique<DeckVisuals>(group));
+ }
+
+ void process(double remainingTimeTriggerSeconds) {
+ for (const auto& d: m_deckVisuals) {
+ d->process(remainingTimeTriggerSeconds);
+ }
+ }
+ private:
+ std::vector<std::unique_ptr<DeckVisuals> > m_deckVisuals;
+};
diff --git a/src/waveform/waveformwidgetfactory.cpp b/src/waveform/waveformwidgetfactory.cpp
index 8db15f9e2e..78917a673d 100644
--- a/src/waveform/waveformwidgetfactory.cpp
+++ b/src/waveform/waveformwidgetfactory.cpp
@@ -25,6 +25,7 @@
#include "waveform/widgets/waveformwidgetabstract.h"
#include "widget/wwaveformviewer.h"
#include "waveform/guitick.h"
+#include "waveform/visualsmanager.h"
#include "waveform/vsyncthread.h"
#include "util/cmdlineargs.h"
#include "util/performancetimer.h"
@@ -103,6 +104,7 @@ WaveformWidgetFactory::WaveformWidgetFactory() :
m_beatGridAlpha(90),
m_vsyncThread(NULL),
m_pGuiTick(nullptr),
+ m_pVisualsManager(nullptr),
m_frameCnt(0),
m_actualFrameRate(0),
m_vSyncType(0),
@@ -596,6 +598,7 @@ void WaveformWidgetFactory::render() {
}
}
+ m_pVisualsManager->process(m_endOfTrackWarningTime);
m_pGuiTick->process();
//qDebug() << "refresh end" << m_vsyncThread->elapsed();
@@ -835,8 +838,9 @@ int WaveformWidgetFactory::findIndexOf(WWaveformViewer* viewer) const {
return -1;
}
-void WaveformWidgetFactory::startVSync(GuiTick* pGuiTick) {
+void WaveformWidgetFactory::startVSync(GuiTick* pGuiTick, VisualsManager* pVisualsManager) {
m_pGuiTick = pGuiTick;
+ m_pVisualsManager = pVisualsManager;
m_vsyncThread = new VSyncThread(this);
m_vsyncThread->start(QThread::NormalPriority);
diff --git a/src/waveform/waveformwidgetfactory.h b/src/waveform/waveformwidgetfactory.h
index 1991d1c2df..75aafd39c7 100644
--- a/src/waveform/waveformwidgetfactory.h
+++ b/src/waveform/waveformwidgetfactory.h
@@ -17,6 +17,7 @@ class WaveformWidgetAbstract;
class QTimer;
class VSyncThread;
class GuiTick;
+class VisualsManager;
class WaveformWidgetAbstractHandle {
public:
@@ -102,7 +103,7 @@ class WaveformWidgetFactory : public QObject, publi