From bafea3b7ab859f97953c84eaa67713a37156e444 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Fri, 22 Dec 2006 22:22:01 +0000 Subject: [PATCH] GetPosition() -> GetHardwareFrame; handle timing retry in the driver, so the logic is available to the driver --- stepmania/src/RageSound.cpp | 38 ++----------------- stepmania/src/RageSound.h | 3 +- stepmania/src/RageSoundManager.cpp | 4 +- stepmania/src/RageSoundManager.h | 3 +- stepmania/src/arch/Sound/RageSoundDriver.h | 3 +- .../RageSoundDriver_Generic_Software.cpp | 35 +++++++++++++++++ .../Sound/RageSoundDriver_Generic_Software.h | 3 ++ 7 files changed, 49 insertions(+), 40 deletions(-) diff --git a/stepmania/src/RageSound.cpp b/stepmania/src/RageSound.cpp index 331af2c581..70d28b07d9 100644 --- a/stepmania/src/RageSound.cpp +++ b/stepmania/src/RageSound.cpp @@ -477,7 +477,7 @@ float RageSound::GetLengthSeconds() } /* Get the position in frames. */ -int64_t RageSound::GetPositionSecondsInternal( bool *bApproximate ) const +int64_t RageSound::GetPositionSecondsInternal( bool *bApproximate, RageTimer *pTimer ) const { LockMut( m_Mutex ); @@ -499,7 +499,7 @@ int64_t RageSound::GetPositionSecondsInternal( bool *bApproximate ) const } /* Get our current hardware position. */ - int64_t iCurrentHardwareFrame = SOUNDMAN->GetPosition(); + int64_t iCurrentHardwareFrame = SOUNDMAN->GetPosition( pTimer ); /* It's sometimes possible for the hardware position to move backwards, usually * on underrun. We can try to prevent this in each driver, but it's an obscure @@ -543,39 +543,7 @@ float RageSound::GetPositionSeconds( bool *bApproximate, RageTimer *pTimestamp ) { LockMut( m_Mutex ); - if( pTimestamp == NULL ) - { - const int64_t iPositionFrames = GetPositionSecondsInternal( bApproximate ); - return iPositionFrames / float(samplerate()); - } - - /* - * We may have unpredictable scheduling delays between updating the timestamp - * and reading the sound position. If we're preempted while doing this and - * it may have caused the timestamp to not match the returned time, retry. - * - * As a failsafe, only allow a few attempts. If this has to try more than - * a few times, then probably we have thread contention that's causing more - * severe performance problems, anyway. - */ - int iTries = 3; - int64_t iPositionFrames; - do - { - pTimestamp->Touch(); - iPositionFrames = GetPositionSecondsInternal( bApproximate ); - } while( --iTries && pTimestamp->Ago() > 0.002f ); - - if( iTries == 0 ) - { - static bool bLogged = false; - if( !bLogged ) - { - bLogged = true; - LOG->Warn( "RageSound::GetPositionSeconds: too many tries" ); - } - } - + const int64_t iPositionFrames = GetPositionSecondsInternal( bApproximate, pTimestamp ); return iPositionFrames / float(samplerate()); } diff --git a/stepmania/src/RageSound.h b/stepmania/src/RageSound.h index 66003429ca..d59046f760 100644 --- a/stepmania/src/RageSound.h +++ b/stepmania/src/RageSound.h @@ -186,7 +186,8 @@ private: RString m_sError; - int64_t GetPositionSecondsInternal( bool *bApproximate=NULL ) const; + int64_t GetPositionSecondsInternal( bool *bApproximate = NULL, RageTimer *pTimer = NULL ) const; + bool SetPositionFrames( int frames = -1 ); int GetData( char *pBuffer, int iSize ); void Fail( RString sReason ); diff --git a/stepmania/src/RageSoundManager.cpp b/stepmania/src/RageSoundManager.cpp index bac1551c24..08c55643f1 100644 --- a/stepmania/src/RageSoundManager.cpp +++ b/stepmania/src/RageSoundManager.cpp @@ -103,11 +103,11 @@ bool RageSoundManager::Pause( RageSoundBase *pSound, bool bPause ) return m_pDriver->PauseMixing( pSound, bPause ); } -int64_t RageSoundManager::GetPosition() const +int64_t RageSoundManager::GetPosition( RageTimer *pTimer ) const { if( m_pDriver == NULL ) return 0; - return m_pDriver->GetPosition(); + return m_pDriver->GetHardwareFrame( pTimer ); } void RageSoundManager::Update() diff --git a/stepmania/src/RageSoundManager.h b/stepmania/src/RageSoundManager.h index c4ee67d887..27f9861849 100644 --- a/stepmania/src/RageSoundManager.h +++ b/stepmania/src/RageSoundManager.h @@ -13,6 +13,7 @@ class RageSoundDriver; struct RageSoundParams; class RageSoundReader; class RageSoundReader_Preload; +class RageTimer; class RageSoundManager { @@ -37,7 +38,7 @@ public: void StartMixing( RageSoundBase *snd ); /* used by RageSound */ void StopMixing( RageSoundBase *snd ); /* used by RageSound */ bool Pause( RageSoundBase *snd, bool bPause ); /* used by RageSound */ - int64_t GetPosition() const; /* used by RageSound */ + int64_t GetPosition( RageTimer *pTimer ) const; /* used by RageSound */ void RegisterSound( RageSound *p ); /* used by RageSound */ void UnregisterSound( RageSound *p ); /* used by RageSound */ int GetUniqueID(); /* used by RageSound */ diff --git a/stepmania/src/arch/Sound/RageSoundDriver.h b/stepmania/src/arch/Sound/RageSoundDriver.h index b2b08a2f02..565d95ae59 100644 --- a/stepmania/src/arch/Sound/RageSoundDriver.h +++ b/stepmania/src/arch/Sound/RageSoundDriver.h @@ -5,6 +5,7 @@ #include "arch/RageDriver.h" class RageSoundBase; +class RageTimer; class RageSoundDriver: public RageDriver { public: @@ -36,7 +37,7 @@ public: /* Get the current hardware frame position, in the same time base as passed to * RageSound::CommitPlayingPosition. */ - virtual int64_t GetPosition() const = 0; + virtual int64_t GetHardwareFrame( RageTimer *pTimer ) const = 0; /* When a sound is finished playing (GetDataToPlay returns 0) and the sound has * been completely flushed (so GetPosition is no longer meaningful), call diff --git a/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.cpp b/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.cpp index 47a98c6234..92e61e9691 100644 --- a/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.cpp +++ b/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.cpp @@ -445,6 +445,41 @@ RageSound_Generic_Software::~RageSound_Generic_Software() } } +int64_t RageSound_Generic_Software::GetHardwareFrame( RageTimer *pTimestamp ) const +{ + if( pTimestamp == NULL ) + return GetPosition(); + + /* + * We may have unpredictable scheduling delays between updating the timestamp + * and reading the sound position. If we're preempted while doing this and + * it may have caused the timestamp to not match the returned time, retry. + * + * As a failsafe, only allow a few attempts. If this has to try more than + * a few times, then probably we have thread contention that's causing more + * severe performance problems, anyway. + */ + int iTries = 3; + int64_t iPositionFrames; + do + { + pTimestamp->Touch(); + iPositionFrames = GetPosition(); + } while( --iTries && pTimestamp->Ago() > 0.002f ); + + if( iTries == 0 ) + { + static bool bLogged = false; + if( !bLogged ) + { + bLogged = true; + LOG->Warn( "RageSound_Generic_Software::GetHardwareFrame: too many tries" ); + } + } + + return iPositionFrames; +} + /* * (c) 2002-2004 Glenn Maynard * All rights reserved. diff --git a/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.h b/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.h index 96a1b07954..d46b4c1654 100644 --- a/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.h +++ b/stepmania/src/arch/Sound/RageSoundDriver_Generic_Software.h @@ -20,6 +20,9 @@ public: RageSound_Generic_Software(); virtual ~RageSound_Generic_Software(); + virtual int64_t GetHardwareFrame( RageTimer *pTimer ) const; + virtual int64_t GetPosition() const = 0; + protected: /* Start the decoding. This should be called once the hardware is set up and * GetSampleRate will return the correct value. */