=== modified file 'mixxx/src/basetrackplayer.cpp' --- mixxx/src/basetrackplayer.cpp 2012-11-25 09:33:00 +0000 +++ mixxx/src/basetrackplayer.cpp 2012-11-27 07:07:16 +0000 @@ -58,9 +58,7 @@ pEngineBuffer->addControl(pClockControl); CueControl* pCueControl = new CueControl(pSafeGroupName, pConfig); - connect(this, SIGNAL(unloadingTrack(TrackPointer)), - pCueControl, SLOT(unloadTrack(TrackPointer))); - pEngineBuffer->addCueControl(pCueControl); + pEngineBuffer->addControl(pCueControl); // Connect our signals and slots with the EngineBuffer's signals and // slots. This will let us know when the reader is done loading a track, and === modified file 'mixxx/src/engine/bpmcontrol.cpp' --- mixxx/src/engine/bpmcontrol.cpp 2012-11-23 16:48:13 +0000 +++ mixxx/src/engine/bpmcontrol.cpp 2012-11-27 07:07:16 +0000 @@ -325,7 +325,7 @@ double dThisNextBeat = m_pBeats->findNextBeat(dThisPosition); if (dThisPrevBeat == -1 || dThisNextBeat == -1 || - dOtherEnginePlayPos == -1 || dOtherLength == 0) { + dOtherEnginePlayPos == -1 || dOtherLength == 0) { return false; } === modified file 'mixxx/src/engine/cuecontrol.cpp' --- mixxx/src/engine/cuecontrol.cpp 2012-11-25 09:33:00 +0000 +++ mixxx/src/engine/cuecontrol.cpp 2012-11-27 07:07:16 +0000 @@ -164,14 +164,13 @@ pControl->getEnabled()->set(0); } -// WARNING: Always called from the EngineWorker thread pool -double CueControl::loadTrack(TrackPointer pTrack) { +void CueControl::trackLoaded(TrackPointer pTrack) { QMutexLocker lock(&m_mutex); if (m_pLoadedTrack) - unloadTrack(m_pLoadedTrack); + trackUnloaded(m_pLoadedTrack); if (!pTrack) { - return 0; + return; } m_pLoadedTrack = pTrack; @@ -204,14 +203,17 @@ ConfigKey("[Controls]","CueRecall")).toInt(); //If cue recall is ON in the prefs, then we're supposed to seek to the cue //point on song load. Note that cueRecall == 0 corresponds to "ON", not OFF. - double loadCuePoint = 0; if (loadCue && cueRecall == 0) { - loadCuePoint = loadCue->getPosition(); + double loadCuePoint = loadCue->getPosition(); + + // Need to unlock before emitting any signals to prevent deadlock. + lock.unlock(); + + emit(seekAbs(loadCuePoint)); } - return loadCuePoint; } -void CueControl::unloadTrack(TrackPointer pTrack) { +void CueControl::trackUnloaded(TrackPointer pTrack) { QMutexLocker lock(&m_mutex); disconnect(pTrack.data(), 0, this, 0); for (int i = 0; i < m_iNumHotCues; ++i) { === modified file 'mixxx/src/engine/cuecontrol.h' --- mixxx/src/engine/cuecontrol.h 2012-11-20 21:24:37 +0000 +++ mixxx/src/engine/cuecontrol.h 2012-11-27 07:07:16 +0000 @@ -87,10 +87,10 @@ virtual ~CueControl(); virtual void hintReader(QList& hintList); - double loadTrack(TrackPointer pTrack); public slots: - void unloadTrack(TrackPointer pTrack); + void trackLoaded(TrackPointer pTrack); + void trackUnloaded(TrackPointer pTrack); private slots: void cueUpdated(); === modified file 'mixxx/src/engine/enginebuffer.cpp' --- mixxx/src/engine/enginebuffer.cpp 2012-11-27 05:38:13 +0000 +++ mixxx/src/engine/enginebuffer.cpp 2012-11-27 07:08:37 +0000 @@ -37,7 +37,6 @@ #include "engine/ratecontrol.h" #include "engine/bpmcontrol.h" #include "engine/quantizecontrol.h" -#include "engine/cuecontrol.h" #ifdef __VINYLCONTROL__ #include "engine/vinylcontrolcontrol.h" @@ -78,15 +77,14 @@ m_pScaleST(NULL), m_bScalerChanged(false), m_bLastBufferPaused(true), - m_bBufferPause(true), + m_iTrackLoading(0), m_fRampValue(0.0), m_iRampState(ENGINE_RAMP_NONE), m_pDitherBuffer(new CSAMPLE[MAX_BUFFER_LEN]), m_iDitherBufferReadIndex(0), m_pCrossFadeBuffer(new CSAMPLE[MAX_BUFFER_LEN]), m_iCrossFadeSamples(0), - m_iLastBufferSize(0), - m_cueControl(NULL) { + m_iLastBufferSize(0) { // Generate dither values for (int i = 0; i < MAX_BUFFER_LEN; ++i) { @@ -383,21 +381,13 @@ int iTrackSampleRate, int iTrackNumSamples) { m_pause.lock(); + m_iTrackLoading = 0; visualPlaypos->set(-1); m_pCurrentTrack = pTrack; file_srate_old = iTrackSampleRate; file_length_old = iTrackNumSamples; - // TODO(XXX): Not sure if updating the COs here is critical, because - // all user classes are still having the old track as current m_pTrackSamples->set(iTrackNumSamples); m_pTrackSampleRate->set(iTrackSampleRate); - double seekAbs = 0; - if (m_cueControl) { - seekAbs = m_cueControl->loadTrack(pTrack); - } - slotControlSeekAbs(seekAbs); - // enable Buffer processing - m_bBufferPause = false; m_pause.unlock(); emit(trackLoaded(pTrack)); @@ -421,7 +411,7 @@ return; m_pause.lock(); - m_bBufferPause = true; + m_iTrackLoading = 0; m_pTrackSamples->set(0); m_pTrackSampleRate->set(0); TrackPointer pTrack = m_pCurrentTrack; @@ -467,8 +457,10 @@ void EngineBuffer::slotControlPlay(double v) { - // If no track is currently loaded, turn play off. - if (v > 0.0 && !m_pCurrentTrack) { + // If no track is currently loaded, turn play off. If a track is loading + // allow the set since it might apply to a track we are loading due to the + // asynchrony. + if (v > 0.0 && !m_pCurrentTrack && m_iTrackLoading == 0) { playButton->set(0.0f); } } @@ -552,7 +544,14 @@ bool bCurBufferPaused = false; double rate = 0; - if (!m_bBufferPause && m_pause.tryLock()) { + bool bTrackLoading = m_iTrackLoading != 0; + + if (bTrackLoading) { + m_pTrackSamples->set(0); + m_pTrackSampleRate->set(0); + } + + if (!bTrackLoading && m_pause.tryLock()) { float sr = m_pSampleRate->get(); double baserate = 0.0f; @@ -762,7 +761,7 @@ // release the pauselock m_pause.unlock(); - } else { // if (!m_bBufferPause && m_pause.tryLock()) { + } else { // if (!bTrackLoading && m_pause.tryLock()) { // If we can't get the pause lock then this buffer will be silence. bCurBufferPaused = true; } @@ -904,10 +903,7 @@ // WARNING: This method runs in the GUI thread void EngineBuffer::slotLoadTrack(TrackPointer pTrack) { // Pause EngineBuffer from processing frames - m_pause.lock(); - m_bBufferPause = true; - m_pTrackSamples->set(0); // stop renderer - m_pause.unlock(); + m_iTrackLoading = 1; //Stop playback playButtonCOT->slotSet(0.0); @@ -917,11 +913,6 @@ m_pReader->wake(); } -void EngineBuffer::addCueControl(CueControl* pControl) { - m_cueControl = pControl; - addControl(static_cast(pControl)); -} - void EngineBuffer::addControl(EngineControl* pControl) { // Connect to signals from EngineControl here... m_engineLock.lock(); === modified file 'mixxx/src/engine/enginebuffer.h' --- mixxx/src/engine/enginebuffer.h 2012-11-27 05:38:13 +0000 +++ mixxx/src/engine/enginebuffer.h 2012-11-27 07:07:16 +0000 @@ -20,6 +20,8 @@ #include #include +#include + #include "defs.h" #include "engine/engineobject.h" #include "trackinfoobject.h" @@ -48,7 +50,6 @@ class EngineBufferScaleST; class EngineWorkerScheduler; class EngineMaster; -class CueControl; struct Hint; @@ -98,7 +99,6 @@ // Add an engine control to the EngineBuffer void addControl(EngineControl* pControl); - void addCueControl(CueControl* pControl); // Return the current rate (not thread-safe) double getRate(); @@ -218,7 +218,7 @@ ControlObject* m_pTrackSampleRate; ControlPushButton *playButton, *buttonBeatSync, *playStartButton, *stopStartButton, *stopButton; - ControlObjectThreadMain *playButtonCOT, *playStartButtonCOT, *stopButtonCOT; + ControlObjectThreadMain *playButtonCOT, *playStartButtonCOT; ControlObject *fwdButton, *backButton; ControlPushButton* m_pSlipButton; ControlObject* m_pSlipPosition; @@ -256,7 +256,7 @@ float m_fLastSampleValue[2]; /** Is true if the previous buffer was silent due to pausing */ bool m_bLastBufferPaused; - bool m_bBufferPause; + QAtomicInt m_iTrackLoading; float m_fRampValue; int m_iRampState; //int m_iRampIter; @@ -271,8 +271,6 @@ CSAMPLE* m_pCrossFadeBuffer; int m_iCrossFadeSamples; int m_iLastBufferSize; - - CueControl* m_cueControl; }; #endif