Fixed calling SoundStream::setPlayingOffset() unpausing a paused SoundStream (#203), guard m_isStreaming by a mutex, fixed calling SoundStream::pause() before the stream thread starts not properly pausing the stream (http://en.sfml-dev.org/forums/index.php?topic=15197.0), minor documentation fix in SoundStream. Signed-off-by: binary1248 <binary1248@hotmail.com>
This commit is contained in:
parent
1851dcb109
commit
09aae0240d
@ -32,6 +32,7 @@
|
|||||||
#include <SFML/Audio/SoundSource.hpp>
|
#include <SFML/Audio/SoundSource.hpp>
|
||||||
#include <SFML/System/Thread.hpp>
|
#include <SFML/System/Thread.hpp>
|
||||||
#include <SFML/System/Time.hpp>
|
#include <SFML/System/Time.hpp>
|
||||||
|
#include <SFML/System/Mutex.hpp>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
@ -65,8 +66,8 @@ public :
|
|||||||
/// \brief Start or resume playing the audio stream
|
/// \brief Start or resume playing the audio stream
|
||||||
///
|
///
|
||||||
/// This function starts the stream if it was stopped, resumes
|
/// This function starts the stream if it was stopped, resumes
|
||||||
/// it if it was paused, and restarts it from beginning if it
|
/// it if it was paused, and restarts it from the beginning if
|
||||||
/// was it already playing.
|
/// it was already playing.
|
||||||
/// This function uses its own thread so that it doesn't block
|
/// This function uses its own thread so that it doesn't block
|
||||||
/// the rest of the program while the stream is played.
|
/// the rest of the program while the stream is played.
|
||||||
///
|
///
|
||||||
@ -282,6 +283,8 @@ private :
|
|||||||
// Member data
|
// Member data
|
||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
Thread m_thread; ///< Thread running the background tasks
|
Thread m_thread; ///< Thread running the background tasks
|
||||||
|
mutable Mutex m_threadMutex; ///< Thread mutex
|
||||||
|
Status m_threadStartState; ///< State the thread starts in (Playing, Paused, Stopped)
|
||||||
bool m_isStreaming; ///< Streaming state (true = playing, false = stopped)
|
bool m_isStreaming; ///< Streaming state (true = playing, false = stopped)
|
||||||
unsigned int m_buffers[BufferCount]; ///< Sound buffers used to store temporary audio data
|
unsigned int m_buffers[BufferCount]; ///< Sound buffers used to store temporary audio data
|
||||||
unsigned int m_channelCount; ///< Number of channels (1 = mono, 2 = stereo, ...)
|
unsigned int m_channelCount; ///< Number of channels (1 = mono, 2 = stereo, ...)
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <SFML/Audio/ALCheck.hpp>
|
#include <SFML/Audio/ALCheck.hpp>
|
||||||
#include <SFML/System/Sleep.hpp>
|
#include <SFML/System/Sleep.hpp>
|
||||||
#include <SFML/System/Err.hpp>
|
#include <SFML/System/Err.hpp>
|
||||||
|
#include <SFML/System/Lock.hpp>
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#pragma warning(disable : 4355) // 'this' used in base member initializer list
|
#pragma warning(disable : 4355) // 'this' used in base member initializer list
|
||||||
@ -41,6 +42,8 @@ namespace sf
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
SoundStream::SoundStream() :
|
SoundStream::SoundStream() :
|
||||||
m_thread (&SoundStream::streamData, this),
|
m_thread (&SoundStream::streamData, this),
|
||||||
|
m_threadMutex (),
|
||||||
|
m_threadStartState(Stopped),
|
||||||
m_isStreaming (false),
|
m_isStreaming (false),
|
||||||
m_channelCount (0),
|
m_channelCount (0),
|
||||||
m_sampleRate (0),
|
m_sampleRate (0),
|
||||||
@ -89,6 +92,9 @@ void SoundStream::play()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Lock lock(m_threadMutex);
|
||||||
|
|
||||||
// If the sound is already playing (probably paused), just resume it
|
// If the sound is already playing (probably paused), just resume it
|
||||||
if (m_isStreaming)
|
if (m_isStreaming)
|
||||||
{
|
{
|
||||||
@ -96,12 +102,15 @@ void SoundStream::play()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_isStreaming = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Move to the beginning
|
// Move to the beginning
|
||||||
onSeek(Time::Zero);
|
onSeek(Time::Zero);
|
||||||
|
|
||||||
// Start updating the stream in a separate thread to avoid blocking the application
|
// Start updating the stream in a separate thread to avoid blocking the application
|
||||||
m_samplesProcessed = 0;
|
m_samplesProcessed = 0;
|
||||||
m_isStreaming = true;
|
m_threadStartState = Playing;
|
||||||
m_thread.launch();
|
m_thread.launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,6 +118,12 @@ void SoundStream::play()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::pause()
|
void SoundStream::pause()
|
||||||
{
|
{
|
||||||
|
// Handle pause() being called before the thread has started
|
||||||
|
{
|
||||||
|
Lock lock(m_threadMutex);
|
||||||
|
m_threadStartState = Paused;
|
||||||
|
}
|
||||||
|
|
||||||
alCheck(alSourcePause(m_source));
|
alCheck(alSourcePause(m_source));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,8 +131,13 @@ void SoundStream::pause()
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::stop()
|
void SoundStream::stop()
|
||||||
{
|
{
|
||||||
// Wait for the thread to terminate
|
// Request the thread to terminate
|
||||||
|
{
|
||||||
|
Lock lock(m_threadMutex);
|
||||||
m_isStreaming = false;
|
m_isStreaming = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for the thread to terminate
|
||||||
m_thread.wait();
|
m_thread.wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,8 +162,13 @@ SoundStream::Status SoundStream::getStatus() const
|
|||||||
Status status = SoundSource::getStatus();
|
Status status = SoundSource::getStatus();
|
||||||
|
|
||||||
// To compensate for the lag between play() and alSourceplay()
|
// To compensate for the lag between play() and alSourceplay()
|
||||||
if ((status == Stopped) && m_isStreaming)
|
if (status == Stopped)
|
||||||
status = Playing;
|
{
|
||||||
|
Lock lock(m_threadMutex);
|
||||||
|
|
||||||
|
if (m_isStreaming)
|
||||||
|
status = m_threadStartState;
|
||||||
|
}
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -152,6 +177,9 @@ SoundStream::Status SoundStream::getStatus() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::setPlayingOffset(Time timeOffset)
|
void SoundStream::setPlayingOffset(Time timeOffset)
|
||||||
{
|
{
|
||||||
|
// Get old playing status
|
||||||
|
Status oldStatus = getStatus();
|
||||||
|
|
||||||
// Stop the stream
|
// Stop the stream
|
||||||
stop();
|
stop();
|
||||||
|
|
||||||
@ -160,7 +188,12 @@ void SoundStream::setPlayingOffset(Time timeOffset)
|
|||||||
|
|
||||||
// Restart streaming
|
// Restart streaming
|
||||||
m_samplesProcessed = static_cast<Uint64>(timeOffset.asSeconds() * m_sampleRate * m_channelCount);
|
m_samplesProcessed = static_cast<Uint64>(timeOffset.asSeconds() * m_sampleRate * m_channelCount);
|
||||||
|
|
||||||
|
if (oldStatus == Stopped)
|
||||||
|
return;
|
||||||
|
|
||||||
m_isStreaming = true;
|
m_isStreaming = true;
|
||||||
|
m_threadStartState = oldStatus;
|
||||||
m_thread.launch();
|
m_thread.launch();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,19 +232,42 @@ bool SoundStream::getLoop() const
|
|||||||
////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////
|
||||||
void SoundStream::streamData()
|
void SoundStream::streamData()
|
||||||
{
|
{
|
||||||
|
bool requestStop = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
Lock lock(m_threadMutex);
|
||||||
|
|
||||||
|
// Check if the thread was launched Stopped
|
||||||
|
if (m_threadStartState == Stopped)
|
||||||
|
{
|
||||||
|
m_isStreaming = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the buffers
|
// Create the buffers
|
||||||
alCheck(alGenBuffers(BufferCount, m_buffers));
|
alCheck(alGenBuffers(BufferCount, m_buffers));
|
||||||
for (int i = 0; i < BufferCount; ++i)
|
for (int i = 0; i < BufferCount; ++i)
|
||||||
m_endBuffers[i] = false;
|
m_endBuffers[i] = false;
|
||||||
|
|
||||||
// Fill the queue
|
// Fill the queue
|
||||||
bool requestStop = fillQueue();
|
requestStop = fillQueue();
|
||||||
|
|
||||||
// Play the sound
|
// Play the sound
|
||||||
alCheck(alSourcePlay(m_source));
|
alCheck(alSourcePlay(m_source));
|
||||||
|
|
||||||
while (m_isStreaming)
|
// Check if the thread was launched Paused
|
||||||
|
if (m_threadStartState == Paused)
|
||||||
|
alCheck(alSourcePause(m_source));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (;;)
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
Lock lock(m_threadMutex);
|
||||||
|
if (!m_isStreaming)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// The stream has been interrupted!
|
// The stream has been interrupted!
|
||||||
if (SoundSource::getStatus() == Stopped)
|
if (SoundSource::getStatus() == Stopped)
|
||||||
{
|
{
|
||||||
@ -223,6 +279,7 @@ void SoundStream::streamData()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// End streaming
|
// End streaming
|
||||||
|
Lock lock(m_threadMutex);
|
||||||
m_isStreaming = false;
|
m_isStreaming = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -266,6 +323,7 @@ void SoundStream::streamData()
|
|||||||
<< "and initialize() has been called correctly" << std::endl;
|
<< "and initialize() has been called correctly" << std::endl;
|
||||||
|
|
||||||
// Abort streaming (exit main loop)
|
// Abort streaming (exit main loop)
|
||||||
|
Lock lock(m_threadMutex);
|
||||||
m_isStreaming = false;
|
m_isStreaming = false;
|
||||||
requestStop = true;
|
requestStop = true;
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user