Merge branch 'bugfix/al_context'

This commit is contained in:
Lukas Dürrenberger 2014-12-30 10:44:08 +01:00
commit d4e6b84afc
14 changed files with 372 additions and 77 deletions

View File

@ -0,0 +1,70 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
#ifndef SFML_ALRESOURCE_HPP
#define SFML_ALRESOURCE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
/// \brief Base class for classes that require an OpenAL context
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API AlResource
{
protected:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
AlResource();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~AlResource();
};
} // namespace sf
#endif // SFML_ALRESOURCE_HPP
////////////////////////////////////////////////////////////
/// \class sf::AlResource
/// \ingroup audio
///
/// This class is for internal use only, it must be the base
/// of every class that requires a valid OpenAL context in
/// order to work.
///
////////////////////////////////////////////////////////////

View File

@ -29,6 +29,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Time.hpp>
#include <string>
#include <vector>
@ -49,7 +50,7 @@ class InputStream;
/// \brief Storage for audio samples defining a sound
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundBuffer
class SFML_AUDIO_API SoundBuffer : AlResource
{
public:

View File

@ -29,6 +29,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/Time.hpp>
#include <vector>
@ -41,7 +42,7 @@ namespace sf
/// \brief Abstract base class for capturing sound data
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundRecorder
class SFML_AUDIO_API SoundRecorder : AlResource
{
public:

View File

@ -29,6 +29,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Export.hpp>
#include <SFML/Audio/AlResource.hpp>
#include <SFML/System/Vector3.hpp>
@ -38,7 +39,7 @@ namespace sf
/// \brief Base class defining a sound's properties
///
////////////////////////////////////////////////////////////
class SFML_AUDIO_API SoundSource
class SFML_AUDIO_API SoundSource : AlResource
{
public:

View File

@ -91,19 +91,6 @@ void alCheckError(const std::string& file, unsigned int line)
}
}
////////////////////////////////////////////////////////////
/// Make sure that OpenAL is initialized
////////////////////////////////////////////////////////////
void ensureALInit()
{
// The audio device is instantiated on demand rather than at global startup,
// which solves a lot of weird crashes and errors.
// It is destroyed at global exit which is fine.
static AudioDevice globalDevice;
}
} // namespace priv
} // namespace sf

View File

@ -64,12 +64,6 @@ namespace priv
////////////////////////////////////////////////////////////
void alCheckError(const std::string& file, unsigned int line);
////////////////////////////////////////////////////////////
/// Make sure that OpenAL is initialized
///
////////////////////////////////////////////////////////////
void ensureALInit();
} // namespace priv
} // namespace sf

View File

@ -0,0 +1,78 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2014 Laurent Gomila (laurent.gom@gmail.com)
//
// This software is provided 'as-is', without any express or implied warranty.
// In no event will the authors be held liable for any damages arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it freely,
// subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented;
// you must not claim that you wrote the original software.
// If you use this software in a product, an acknowledgment
// in the product documentation would be appreciated but is not required.
//
// 2. Altered source versions must be plainly marked as such,
// and must not be misrepresented as being the original software.
//
// 3. This notice may not be removed or altered from any source distribution.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/AlResource.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
namespace
{
// OpenAL resources counter and its mutex
unsigned int count = 0;
sf::Mutex mutex;
// The audio device is instantiated on demand rather than at global startup,
// which solves a lot of weird crashes and errors.
// It is destroyed when it is no longer needed.
sf::priv::AudioDevice* globalDevice;
}
namespace sf
{
////////////////////////////////////////////////////////////
AlResource::AlResource()
{
// Protect from concurrent access
Lock lock(mutex);
// If this is the very first resource, trigger the global device initialization
if (count == 0)
globalDevice = new priv::AudioDevice;
// Increment the resources counter
count++;
}
////////////////////////////////////////////////////////////
AlResource::~AlResource()
{
// Protect from concurrent access
Lock lock(mutex);
// Decrement the resources counter
count--;
// If there's no more resource alive, we can destroy the device
if (count == 0)
delete globalDevice;
}
} // namespace sf

View File

@ -29,12 +29,18 @@
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/Audio/Listener.hpp>
#include <SFML/System/Err.hpp>
#include <memory>
namespace
{
ALCdevice* audioDevice = NULL;
ALCcontext* audioContext = NULL;
float listenerVolume = 100.f;
sf::Vector3f listenerPosition (0.f, 0.f, 0.f);
sf::Vector3f listenerDirection(0.f, 0.f, -1.f);
sf::Vector3f listenerUpVector (0.f, 1.f, 0.f);
}
namespace sf
@ -56,6 +62,17 @@ AudioDevice::AudioDevice()
{
// Set the context as the current one (we'll only need one)
alcMakeContextCurrent(audioContext);
// Apply the listener properties the user might have set
float orientation[] = {listenerDirection.x,
listenerDirection.y,
listenerDirection.z,
listenerUpVector.x,
listenerUpVector.y,
listenerUpVector.z};
alCheck(alListenerf(AL_GAIN, listenerVolume * 0.01f));
alCheck(alListener3f(AL_POSITION, listenerPosition.x, listenerPosition.y, listenerPosition.z));
alCheck(alListenerfv(AL_ORIENTATION, orientation));
}
else
{
@ -86,7 +103,13 @@ AudioDevice::~AudioDevice()
////////////////////////////////////////////////////////////
bool AudioDevice::isExtensionSupported(const std::string& extension)
{
ensureALInit();
// Create a temporary audio device in case none exists yet.
// This device will not be used in this function and merely
// makes sure there is a valid OpenAL device for extension
// queries if none has been created yet.
std::auto_ptr<AudioDevice> device;
if (!audioDevice)
device.reset(new AudioDevice);
if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
@ -98,7 +121,13 @@ bool AudioDevice::isExtensionSupported(const std::string& extension)
////////////////////////////////////////////////////////////
int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
{
ensureALInit();
// Create a temporary audio device in case none exists yet.
// This device will not be used in this function and merely
// makes sure there is a valid OpenAL device for format
// queries if none has been created yet.
std::auto_ptr<AudioDevice> device;
if (!audioDevice)
device.reset(new AudioDevice);
// Find the good format according to the number of channels
int format = 0;
@ -120,6 +149,80 @@ int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
return format;
}
////////////////////////////////////////////////////////////
void AudioDevice::setGlobalVolume(float volume)
{
if (audioContext)
alCheck(alListenerf(AL_GAIN, volume * 0.01f));
listenerVolume = volume;
}
////////////////////////////////////////////////////////////
float AudioDevice::getGlobalVolume()
{
return listenerVolume;
}
////////////////////////////////////////////////////////////
void AudioDevice::setPosition(const Vector3f& position)
{
if (audioContext)
alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));
listenerPosition = position;
}
////////////////////////////////////////////////////////////
Vector3f AudioDevice::getPosition()
{
return listenerPosition;
}
////////////////////////////////////////////////////////////
void AudioDevice::setDirection(const Vector3f& direction)
{
if (audioContext)
{
float orientation[] = {direction.x, direction.y, direction.z, listenerUpVector.x, listenerUpVector.y, listenerUpVector.z};
alCheck(alListenerfv(AL_ORIENTATION, orientation));
}
listenerDirection = direction;
}
////////////////////////////////////////////////////////////
Vector3f AudioDevice::getDirection()
{
return listenerDirection;
}
////////////////////////////////////////////////////////////
void AudioDevice::setUpVector(const Vector3f& upVector)
{
if (audioContext)
{
float orientation[] = {listenerDirection.x, listenerDirection.y, listenerDirection.z, upVector.x, upVector.y, upVector.z};
alCheck(alListenerfv(AL_ORIENTATION, orientation));
}
listenerUpVector = upVector;
}
////////////////////////////////////////////////////////////
Vector3f AudioDevice::getUpVector()
{
return listenerUpVector;
}
} // namespace priv
} // namespace sf

View File

@ -28,6 +28,7 @@
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/Vector3.hpp>
#include <set>
#include <string>
@ -81,6 +82,106 @@ public:
///
////////////////////////////////////////////////////////////
static int getFormatFromChannelCount(unsigned int channelCount);
////////////////////////////////////////////////////////////
/// \brief Change the global volume of all the sounds and musics
///
/// The volume is a number between 0 and 100; it is combined with
/// the individual volume of each sound / music.
/// The default value for the volume is 100 (maximum).
///
/// \param volume New global volume, in the range [0, 100]
///
/// \see getGlobalVolume
///
////////////////////////////////////////////////////////////
static void setGlobalVolume(float volume);
////////////////////////////////////////////////////////////
/// \brief Get the current value of the global volume
///
/// \return Current global volume, in the range [0, 100]
///
/// \see setGlobalVolume
///
////////////////////////////////////////////////////////////
static float getGlobalVolume();
////////////////////////////////////////////////////////////
/// \brief Set the position of the listener in the scene
///
/// The default listener's position is (0, 0, 0).
///
/// \param position New listener's position
///
/// \see getPosition, setDirection
///
////////////////////////////////////////////////////////////
static void setPosition(const Vector3f& position);
////////////////////////////////////////////////////////////
/// \brief Get the current position of the listener in the scene
///
/// \return Listener's position
///
/// \see setPosition
///
////////////////////////////////////////////////////////////
static Vector3f getPosition();
////////////////////////////////////////////////////////////
/// \brief Set the forward vector of the listener in the scene
///
/// The direction (also called "at vector") is the vector
/// pointing forward from the listener's perspective. Together
/// with the up vector, it defines the 3D orientation of the
/// listener in the scene. The direction vector doesn't
/// have to be normalized.
/// The default listener's direction is (0, 0, -1).
///
/// \param direction New listener's direction
///
/// \see getDirection, setUpVector, setPosition
///
////////////////////////////////////////////////////////////
static void setDirection(const Vector3f& direction);
////////////////////////////////////////////////////////////
/// \brief Get the current forward vector of the listener in the scene
///
/// \return Listener's forward vector (not normalized)
///
/// \see setDirection
///
////////////////////////////////////////////////////////////
static Vector3f getDirection();
////////////////////////////////////////////////////////////
/// \brief Set the upward vector of the listener in the scene
///
/// The up vector is the vector that points upward from the
/// listener's perspective. Together with the direction, it
/// defines the 3D orientation of the listener in the scene.
/// The up vector doesn't have to be normalized.
/// The default listener's up vector is (0, 1, 0). It is usually
/// not necessary to change it, especially in 2D scenarios.
///
/// \param upVector New listener's up vector
///
/// \see getUpVector, setDirection, setPosition
///
////////////////////////////////////////////////////////////
static void setUpVector(const Vector3f& upVector);
////////////////////////////////////////////////////////////
/// \brief Get the current upward vector of the listener in the scene
///
/// \return Listener's upward vector (not normalized)
///
/// \see setUpVector
///
////////////////////////////////////////////////////////////
static Vector3f getUpVector();
};
} // namespace priv

View File

@ -6,6 +6,8 @@ set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio)
set(SRC
${SRCROOT}/ALCheck.cpp
${SRCROOT}/ALCheck.hpp
${SRCROOT}/AlResource.cpp
${INCROOT}/AlResource.hpp
${SRCROOT}/AudioDevice.cpp
${SRCROOT}/AudioDevice.hpp
${INCROOT}/Export.hpp

View File

@ -26,16 +26,7 @@
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Audio/Listener.hpp>
#include <SFML/Audio/ALCheck.hpp>
namespace
{
float listenerVolume = 100.f;
sf::Vector3f listenerPosition (0.f, 0.f, 0.f);
sf::Vector3f listenerDirection(0.f, 0.f, -1.f);
sf::Vector3f listenerUpVector (0.f, 1.f, 0.f);
}
#include <SFML/Audio/AudioDevice.hpp>
namespace sf
@ -43,20 +34,14 @@ namespace sf
////////////////////////////////////////////////////////////
void Listener::setGlobalVolume(float volume)
{
if (volume != listenerVolume)
{
priv::ensureALInit();
alCheck(alListenerf(AL_GAIN, volume * 0.01f));
listenerVolume = volume;
}
priv::AudioDevice::setGlobalVolume(volume);
}
////////////////////////////////////////////////////////////
float Listener::getGlobalVolume()
{
return listenerVolume;
return priv::AudioDevice::getGlobalVolume();
}
@ -70,20 +55,14 @@ void Listener::setPosition(float x, float y, float z)
////////////////////////////////////////////////////////////
void Listener::setPosition(const Vector3f& position)
{
if (position != listenerPosition)
{
priv::ensureALInit();
alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));
listenerPosition = position;
}
priv::AudioDevice::setPosition(position);
}
////////////////////////////////////////////////////////////
Vector3f Listener::getPosition()
{
return listenerPosition;
return priv::AudioDevice::getPosition();
}
@ -97,21 +76,14 @@ void Listener::setDirection(float x, float y, float z)
////////////////////////////////////////////////////////////
void Listener::setDirection(const Vector3f& direction)
{
if (direction != listenerDirection)
{
priv::ensureALInit();
float orientation[] = {direction.x, direction.y, direction.z, listenerUpVector.x, listenerUpVector.y, listenerUpVector.z};
alCheck(alListenerfv(AL_ORIENTATION, orientation));
listenerDirection = direction;
}
priv::AudioDevice::setDirection(direction);
}
////////////////////////////////////////////////////////////
Vector3f Listener::getDirection()
{
return listenerDirection;
return priv::AudioDevice::getDirection();
}
@ -125,21 +97,14 @@ void Listener::setUpVector(float x, float y, float z)
////////////////////////////////////////////////////////////
void Listener::setUpVector(const Vector3f& upVector)
{
if (upVector != listenerUpVector)
{
priv::ensureALInit();
float orientation[] = {listenerDirection.x, listenerDirection.y, listenerDirection.z, upVector.x, upVector.y, upVector.z};
alCheck(alListenerfv(AL_ORIENTATION, orientation));
listenerUpVector = upVector;
}
priv::AudioDevice::setUpVector(upVector);
}
////////////////////////////////////////////////////////////
Vector3f Listener::getUpVector()
{
return listenerUpVector;
return priv::AudioDevice::getUpVector();
}
} // namespace sf

View File

@ -41,8 +41,6 @@ SoundBuffer::SoundBuffer() :
m_buffer (0),
m_duration()
{
priv::ensureALInit();
// Create the buffer
alCheck(alGenBuffers(1, &m_buffer));
}

View File

@ -51,8 +51,6 @@ m_sampleRate (0),
m_processingInterval(milliseconds(100)),
m_isCapturing (false)
{
priv::ensureALInit();
// Set the device name to the default device
m_deviceName = getDefaultDevice();
}

View File

@ -34,8 +34,6 @@ namespace sf
////////////////////////////////////////////////////////////
SoundSource::SoundSource()
{
priv::ensureALInit();
alCheck(alGenSources(1, &m_source));
alCheck(alSourcei(m_source, AL_BUFFER, 0));
}
@ -44,8 +42,6 @@ SoundSource::SoundSource()
////////////////////////////////////////////////////////////
SoundSource::SoundSource(const SoundSource& copy)
{
priv::ensureALInit();
alCheck(alGenSources(1, &m_source));
alCheck(alSourcei(m_source, AL_BUFFER, 0));