This commit is contained in:
parent
aa3472e9d1
commit
65096786e1
5 changed files with 80 additions and 20 deletions
|
@ -86,7 +86,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void prepareDecoder();
|
void prepareDecoder();
|
||||||
void bufferMore(uint bytes);
|
inline bool bufferMore(uint bytes);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CStreamFileSource(const CStreamFileSource &);
|
CStreamFileSource(const CStreamFileSource &);
|
||||||
|
|
|
@ -55,6 +55,9 @@ public:
|
||||||
virtual void setLooping(bool l);
|
virtual void setLooping(bool l);
|
||||||
/// Play
|
/// Play
|
||||||
virtual void play();
|
virtual void play();
|
||||||
|
protected:
|
||||||
|
void stopInt();
|
||||||
|
public:
|
||||||
/// Stop playing
|
/// Stop playing
|
||||||
virtual void stop();
|
virtual void stop();
|
||||||
/// Get playing state. Return false even if the source has stopped on its own.
|
/// Get playing state. Return false even if the source has stopped on its own.
|
||||||
|
|
|
@ -60,6 +60,9 @@ bool CSourceMusicChannel::play(const std::string &filepath, bool async, bool loo
|
||||||
m_Sound.setMusicFilePath(filepath, async, loop);
|
m_Sound.setMusicFilePath(filepath, async, loop);
|
||||||
|
|
||||||
m_Source = new CStreamFileSource(&m_Sound, false, NULL, NULL, NULL, NULL);
|
m_Source = new CStreamFileSource(&m_Sound, false, NULL, NULL, NULL, NULL);
|
||||||
|
m_Source->setSourceRelativeMode(true);
|
||||||
|
m_Source->setPos(NLMISC::CVector::Null);
|
||||||
|
m_Source->setRelativeGain(m_Gain);
|
||||||
|
|
||||||
m_Source->play();
|
m_Source->play();
|
||||||
|
|
||||||
|
|
|
@ -65,13 +65,18 @@ void CStreamFileSource::play()
|
||||||
|
|
||||||
if (m_Thread->isRunning() && m_WaitingForPlay)
|
if (m_Thread->isRunning() && m_WaitingForPlay)
|
||||||
{
|
{
|
||||||
nldebug("play waiting %s", getStreamFileSound()->getFilePath().c_str());
|
|
||||||
if (m_NextBuffer || !m_FreeBuffers)
|
if (m_NextBuffer || !m_FreeBuffers)
|
||||||
{
|
{
|
||||||
|
nldebug("play waiting, play stream %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
CStreamSource::play();
|
CStreamSource::play();
|
||||||
|
if (!_Playing && !m_WaitingForPlay)
|
||||||
|
{
|
||||||
|
nldebug("playing not possible or necessary for some reason");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
nldebug("play waiting, hop onto waiting list %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
m_WaitingForPlay = true;
|
m_WaitingForPlay = true;
|
||||||
CAudioMixerUser *mixer = CAudioMixerUser::instance();
|
CAudioMixerUser *mixer = CAudioMixerUser::instance();
|
||||||
mixer->addSourceWaitingForPlay(this);
|
mixer->addSourceWaitingForPlay(this);
|
||||||
|
@ -79,7 +84,7 @@ void CStreamFileSource::play()
|
||||||
}
|
}
|
||||||
else if (!_Playing)
|
else if (!_Playing)
|
||||||
{
|
{
|
||||||
nldebug("play waiting %s", getStreamFileSound()->getFilePath().c_str());
|
nldebug("play go %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
if (!m_WaitingForPlay)
|
if (!m_WaitingForPlay)
|
||||||
{
|
{
|
||||||
// thread may be stopping from stop call
|
// thread may be stopping from stop call
|
||||||
|
@ -98,12 +103,18 @@ void CStreamFileSource::play()
|
||||||
if (!getStreamFileSound()->getAsync())
|
if (!getStreamFileSound()->getAsync())
|
||||||
{
|
{
|
||||||
// wait until at least one buffer is ready
|
// wait until at least one buffer is ready
|
||||||
while (!(m_NextBuffer || !m_FreeBuffers) && m_WaitingForPlay)
|
while (!(m_NextBuffer || !m_FreeBuffers) && m_WaitingForPlay && m_Thread->isRunning())
|
||||||
NLMISC::nlSleep(10);
|
|
||||||
CStreamSource::play();
|
|
||||||
if (!_Playing)
|
|
||||||
{
|
{
|
||||||
nlwarning("Failed to synchronously start playing a file stream source. This happens when all physical tracks are in use. Use a Highest Priority sound");
|
nldebug("wait buffer");
|
||||||
|
NLMISC::nlSleep(100);
|
||||||
|
}
|
||||||
|
if (m_WaitingForPlay && m_Thread->isRunning())
|
||||||
|
{
|
||||||
|
CStreamSource::play();
|
||||||
|
if (!_Playing)
|
||||||
|
{
|
||||||
|
nlwarning("Failed to synchronously start playing a file stream source. This happens when all physical tracks are in use. Use a Highest Priority sound");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -135,7 +146,19 @@ void CStreamFileSource::stop()
|
||||||
{
|
{
|
||||||
nldebug("stop %s", getStreamFileSound()->getFilePath().c_str());
|
nldebug("stop %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
|
|
||||||
CStreamSource::stop();
|
CStreamSource::stopInt();
|
||||||
|
|
||||||
|
nldebug("stopInt ok");
|
||||||
|
|
||||||
|
if (_Spawn)
|
||||||
|
{
|
||||||
|
if (_SpawnEndCb != NULL)
|
||||||
|
_SpawnEndCb(this, _CbUserParam);
|
||||||
|
m_Thread->wait();
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
nldebug("stop ok");
|
||||||
|
|
||||||
// thread will check _Playing to stop
|
// thread will check _Playing to stop
|
||||||
}
|
}
|
||||||
|
@ -229,30 +252,41 @@ void CStreamFileSource::prepareDecoder()
|
||||||
this->preAllocate(bytes * 2);
|
this->preAllocate(bytes * 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStreamFileSource::bufferMore(uint bytes) // buffer from bytes (minimum) to bytes * 2 (maximum)
|
inline bool CStreamFileSource::bufferMore(uint bytes) // buffer from bytes (minimum) to bytes * 2 (maximum)
|
||||||
{
|
{
|
||||||
uint8 *buffer = this->lock(bytes * 2);
|
uint8 *buffer = this->lock(bytes * 2);
|
||||||
if (buffer)
|
if (buffer)
|
||||||
{
|
{
|
||||||
uint32 result = m_AudioDecoder->getNextBytes(buffer, bytes, bytes * 2);
|
uint32 result = m_AudioDecoder->getNextBytes(buffer, bytes, bytes * 2);
|
||||||
this->unlock(result);
|
this->unlock(result);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStreamFileSource::run()
|
void CStreamFileSource::run()
|
||||||
{
|
{
|
||||||
nldebug("run");
|
nldebug("run %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
|
uint dumpI = 0;
|
||||||
|
|
||||||
bool looping = _Looping;
|
bool looping = _Looping;
|
||||||
if (getStreamFileSound()->getAsync())
|
if (getStreamFileSound()->getAsync())
|
||||||
prepareDecoder();
|
prepareDecoder();
|
||||||
uint samples, bytes;
|
uint samples, bytes;
|
||||||
this->getRecommendedBufferSize(samples, bytes);
|
this->getRecommendedBufferSize(samples, bytes);
|
||||||
bufferMore(bytes);
|
uint32 recSleep = 40;
|
||||||
|
uint32 doSleep = 10;
|
||||||
while (_Playing || m_WaitingForPlay)
|
while (_Playing || m_WaitingForPlay)
|
||||||
{
|
{
|
||||||
if (!m_AudioDecoder->isMusicEnded())
|
if (!m_AudioDecoder->isMusicEnded())
|
||||||
{
|
{
|
||||||
|
++dumpI;
|
||||||
|
if (!(dumpI % 100))
|
||||||
|
{
|
||||||
|
nldebug("buffer %s %s %s", _Playing ? "PLAYING" : "NP", m_WaitingForPlay ? "WAITING" : "NW", getStreamFileSound()->getFilePath().c_str());
|
||||||
|
nldebug("gain %f", hasPhysicalSource() ? getPhysicalSource()->getGain() : -1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
bool newLooping = _Looping;
|
bool newLooping = _Looping;
|
||||||
if (looping != newLooping)
|
if (looping != newLooping)
|
||||||
{
|
{
|
||||||
|
@ -260,14 +294,19 @@ void CStreamFileSource::run()
|
||||||
looping = newLooping;
|
looping = newLooping;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferMore(bytes);
|
// reduce sleeping time if nothing was buffered
|
||||||
NLMISC::nlSleep(this->getRecommendedSleepTime());
|
if (bufferMore(bytes)) recSleep = doSleep = this->getRecommendedSleepTime();
|
||||||
|
else doSleep = recSleep >> 2; // /4
|
||||||
|
NLMISC::nlSleep(doSleep);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// wait until done playing buffers
|
// wait until done playing buffers
|
||||||
while (this->hasFilledBuffersAvailable())
|
while (this->hasFilledBuffersAvailable() && (_Playing || m_WaitingForPlay))
|
||||||
|
{
|
||||||
|
nldebug("music ended, wait until done %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
NLMISC::nlSleep(40);
|
NLMISC::nlSleep(40);
|
||||||
|
}
|
||||||
// stop the physical source
|
// stop the physical source
|
||||||
// if (hasPhysicalSource())
|
// if (hasPhysicalSource())
|
||||||
// getPhysicalSource()->stop();
|
// getPhysicalSource()->stop();
|
||||||
|
@ -284,6 +323,11 @@ void CStreamFileSource::run()
|
||||||
delete m_AudioDecoder;
|
delete m_AudioDecoder;
|
||||||
m_AudioDecoder = NULL;
|
m_AudioDecoder = NULL;
|
||||||
}
|
}
|
||||||
|
// drop buffers
|
||||||
|
m_FreeBuffers = 3;
|
||||||
|
m_NextBuffer = 0;
|
||||||
|
|
||||||
|
nldebug("run end %s", getStreamFileSound()->getFilePath().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
} /* namespace NLSOUND */
|
} /* namespace NLSOUND */
|
||||||
|
|
|
@ -160,7 +160,8 @@ void CStreamSource::play()
|
||||||
_SpawnEndCb(this, _CbUserParam);
|
_SpawnEndCb(this, _CbUserParam);
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
// nldebug("CStreamSource %p : play FAILED !", (CAudioMixerUser::IMixerEvent*)this);
|
nldebug("CStreamSource %p : play FAILED, source is too far away !", (CAudioMixerUser::IMixerEvent*)this);
|
||||||
|
m_WaitingForPlay = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,6 +217,7 @@ void CStreamSource::play()
|
||||||
_SpawnEndCb(this, _CbUserParam);
|
_SpawnEndCb(this, _CbUserParam);
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
m_WaitingForPlay = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,8 +234,7 @@ void CStreamSource::play()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stop playing
|
void CStreamSource::stopInt()
|
||||||
void CStreamSource::stop()
|
|
||||||
{
|
{
|
||||||
CAutoMutex<CMutex> autoMutex(m_BufferMutex);
|
CAutoMutex<CMutex> autoMutex(m_BufferMutex);
|
||||||
|
|
||||||
|
@ -248,7 +249,10 @@ void CStreamSource::stop()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_Playing)
|
if (!_Playing)
|
||||||
|
{
|
||||||
|
m_WaitingForPlay = false;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (hasPhysicalSource())
|
if (hasPhysicalSource())
|
||||||
releasePhysicalSource();
|
releasePhysicalSource();
|
||||||
|
@ -258,14 +262,20 @@ void CStreamSource::stop()
|
||||||
m_FreeBuffers = 3;
|
m_FreeBuffers = 3;
|
||||||
m_NextBuffer = 0;
|
m_NextBuffer = 0;
|
||||||
|
|
||||||
|
m_WaitingForPlay = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Stop playing
|
||||||
|
void CStreamSource::stop()
|
||||||
|
{
|
||||||
|
stopInt();
|
||||||
|
|
||||||
if (_Spawn)
|
if (_Spawn)
|
||||||
{
|
{
|
||||||
if (_SpawnEndCb != NULL)
|
if (_SpawnEndCb != NULL)
|
||||||
_SpawnEndCb(this, _CbUserParam);
|
_SpawnEndCb(this, _CbUserParam);
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_WaitingForPlay = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CStreamSource::setPos(const NLMISC::CVector& pos)
|
void CStreamSource::setPos(const NLMISC::CVector& pos)
|
||||||
|
|
Loading…
Reference in a new issue