Source code changes.

* Changed newlines to \n.
* Removed whitespace before colons.
* Fixed several alignments.
This commit is contained in:
Stefan Schindler 2014-09-30 16:07:25 +02:00
parent b27cbd5036
commit f24ca9a840
268 changed files with 40227 additions and 40227 deletions

View file

@ -1,109 +1,109 @@
////////////////////////////////////////////////////////////
//
// 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/ALCheck.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void alCheckError(const std::string& file, unsigned int line)
{
// Get the last error
ALenum errorCode = alGetError();
if (errorCode != AL_NO_ERROR)
{
std::string error, description;
// Decode the error code
switch (errorCode)
{
case AL_INVALID_NAME :
{
error = "AL_INVALID_NAME";
description = "an unacceptable name has been specified";
break;
}
case AL_INVALID_ENUM :
{
error = "AL_INVALID_ENUM";
description = "an unacceptable value has been specified for an enumerated argument";
break;
}
case AL_INVALID_VALUE :
{
error = "AL_INVALID_VALUE";
description = "a numeric argument is out of range";
break;
}
case AL_INVALID_OPERATION :
{
error = "AL_INVALID_OPERATION";
description = "the specified operation is not allowed in the current state";
break;
}
case AL_OUT_OF_MEMORY :
{
error = "AL_OUT_OF_MEMORY";
description = "there is not enough memory left to execute the command";
break;
}
}
// Log the error
err() << "An internal OpenAL call failed in "
<< file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : "
<< error << ", " << description
<< std::endl;
}
}
////////////////////////////////////////////////////////////
/// 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
////////////////////////////////////////////////////////////
//
// 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/ALCheck.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void alCheckError(const std::string& file, unsigned int line)
{
// Get the last error
ALenum errorCode = alGetError();
if (errorCode != AL_NO_ERROR)
{
std::string error, description;
// Decode the error code
switch (errorCode)
{
case AL_INVALID_NAME:
{
error = "AL_INVALID_NAME";
description = "an unacceptable name has been specified";
break;
}
case AL_INVALID_ENUM:
{
error = "AL_INVALID_ENUM";
description = "an unacceptable value has been specified for an enumerated argument";
break;
}
case AL_INVALID_VALUE:
{
error = "AL_INVALID_VALUE";
description = "a numeric argument is out of range";
break;
}
case AL_INVALID_OPERATION:
{
error = "AL_INVALID_OPERATION";
description = "the specified operation is not allowed in the current state";
break;
}
case AL_OUT_OF_MEMORY:
{
error = "AL_OUT_OF_MEMORY";
description = "there is not enough memory left to execute the command";
break;
}
}
// Log the error
err() << "An internal OpenAL call failed in "
<< file.substr(file.find_last_of("\\/") + 1) << " (" << line << ") : "
<< error << ", " << description
<< std::endl;
}
}
////////////////////////////////////////////////////////////
/// 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

@ -1,78 +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.
//
////////////////////////////////////////////////////////////
#ifndef SFML_ALCHECK_HPP
#define SFML_ALCHECK_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <iostream>
#include <string>
#include <al.h>
#include <alc.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// Let's define a macro to quickly check every OpenAL API calls
////////////////////////////////////////////////////////////
#ifdef SFML_DEBUG
// If in debug mode, perform a test on every call
#define alCheck(x) x; sf::priv::alCheckError(__FILE__, __LINE__);
#else
// Else, we don't add any overhead
#define alCheck(Func) (Func)
#endif
////////////////////////////////////////////////////////////
/// Check the last OpenAL error
///
/// \param file Source file where the call is located
/// \param line Line number of the source file where the call is located
///
////////////////////////////////////////////////////////////
void alCheckError(const std::string& file, unsigned int line);
////////////////////////////////////////////////////////////
/// Make sure that OpenAL is initialized
///
////////////////////////////////////////////////////////////
void ensureALInit();
} // namespace priv
} // namespace sf
#endif // SFML_ALCHECK_HPP
////////////////////////////////////////////////////////////
//
// 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_ALCHECK_HPP
#define SFML_ALCHECK_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <iostream>
#include <string>
#include <al.h>
#include <alc.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// Let's define a macro to quickly check every OpenAL API calls
////////////////////////////////////////////////////////////
#ifdef SFML_DEBUG
// If in debug mode, perform a test on every call
#define alCheck(x) x; sf::priv::alCheckError(__FILE__, __LINE__);
#else
// Else, we don't add any overhead
#define alCheck(Func) (Func)
#endif
////////////////////////////////////////////////////////////
/// Check the last OpenAL error
///
/// \param file Source file where the call is located
/// \param line Line number of the source file where the call is located
///
////////////////////////////////////////////////////////////
void alCheckError(const std::string& file, unsigned int line);
////////////////////////////////////////////////////////////
/// Make sure that OpenAL is initialized
///
////////////////////////////////////////////////////////////
void ensureALInit();
} // namespace priv
} // namespace sf
#endif // SFML_ALCHECK_HPP

View file

@ -1,125 +1,125 @@
////////////////////////////////////////////////////////////
//
// 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/AudioDevice.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/Audio/Listener.hpp>
#include <SFML/System/Err.hpp>
namespace
{
ALCdevice* audioDevice = NULL;
ALCcontext* audioContext = NULL;
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
AudioDevice::AudioDevice()
{
// Create the device
audioDevice = alcOpenDevice(NULL);
if (audioDevice)
{
// Create the context
audioContext = alcCreateContext(audioDevice, NULL);
if (audioContext)
{
// Set the context as the current one (we'll only need one)
alcMakeContextCurrent(audioContext);
}
else
{
err() << "Failed to create the audio context" << std::endl;
}
}
else
{
err() << "Failed to open the audio device" << std::endl;
}
}
////////////////////////////////////////////////////////////
AudioDevice::~AudioDevice()
{
// Destroy the context
alcMakeContextCurrent(NULL);
if (audioContext)
alcDestroyContext(audioContext);
// Destroy the device
if (audioDevice)
alcCloseDevice(audioDevice);
}
////////////////////////////////////////////////////////////
bool AudioDevice::isExtensionSupported(const std::string& extension)
{
ensureALInit();
if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
else
return alIsExtensionPresent(extension.c_str()) != AL_FALSE;
}
////////////////////////////////////////////////////////////
int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
{
ensureALInit();
// Find the good format according to the number of channels
int format = 0;
switch (channelCount)
{
case 1 : format = AL_FORMAT_MONO16; break;
case 2 : format = AL_FORMAT_STEREO16; break;
case 4 : format = alGetEnumValue("AL_FORMAT_QUAD16"); break;
case 6 : format = alGetEnumValue("AL_FORMAT_51CHN16"); break;
case 7 : format = alGetEnumValue("AL_FORMAT_61CHN16"); break;
case 8 : format = alGetEnumValue("AL_FORMAT_71CHN16"); break;
default : format = 0; break;
}
// Fixes a bug on OS X
if (format == -1)
format = 0;
return format;
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/AudioDevice.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/Audio/Listener.hpp>
#include <SFML/System/Err.hpp>
namespace
{
ALCdevice* audioDevice = NULL;
ALCcontext* audioContext = NULL;
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
AudioDevice::AudioDevice()
{
// Create the device
audioDevice = alcOpenDevice(NULL);
if (audioDevice)
{
// Create the context
audioContext = alcCreateContext(audioDevice, NULL);
if (audioContext)
{
// Set the context as the current one (we'll only need one)
alcMakeContextCurrent(audioContext);
}
else
{
err() << "Failed to create the audio context" << std::endl;
}
}
else
{
err() << "Failed to open the audio device" << std::endl;
}
}
////////////////////////////////////////////////////////////
AudioDevice::~AudioDevice()
{
// Destroy the context
alcMakeContextCurrent(NULL);
if (audioContext)
alcDestroyContext(audioContext);
// Destroy the device
if (audioDevice)
alcCloseDevice(audioDevice);
}
////////////////////////////////////////////////////////////
bool AudioDevice::isExtensionSupported(const std::string& extension)
{
ensureALInit();
if ((extension.length() > 2) && (extension.substr(0, 3) == "ALC"))
return alcIsExtensionPresent(audioDevice, extension.c_str()) != AL_FALSE;
else
return alIsExtensionPresent(extension.c_str()) != AL_FALSE;
}
////////////////////////////////////////////////////////////
int AudioDevice::getFormatFromChannelCount(unsigned int channelCount)
{
ensureALInit();
// Find the good format according to the number of channels
int format = 0;
switch (channelCount)
{
case 1: format = AL_FORMAT_MONO16; break;
case 2: format = AL_FORMAT_STEREO16; break;
case 4: format = alGetEnumValue("AL_FORMAT_QUAD16"); break;
case 6: format = alGetEnumValue("AL_FORMAT_51CHN16"); break;
case 7: format = alGetEnumValue("AL_FORMAT_61CHN16"); break;
case 8: format = alGetEnumValue("AL_FORMAT_71CHN16"); break;
default: format = 0; break;
}
// Fixes a bug on OS X
if (format == -1)
format = 0;
return format;
}
} // namespace priv
} // namespace sf

View file

@ -1,91 +1,91 @@
////////////////////////////////////////////////////////////
//
// 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_AUDIODEVICE_HPP
#define SFML_AUDIODEVICE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <set>
#include <string>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief High-level wrapper around the audio API, it manages
/// the creation and destruction of the audio device and
/// context and stores the device capabilities
///
////////////////////////////////////////////////////////////
class AudioDevice
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
AudioDevice();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~AudioDevice();
////////////////////////////////////////////////////////////
/// \brief Check if an OpenAL extension is supported
///
/// This functions automatically finds whether it
/// is an AL or ALC extension, and calls the corresponding
/// function.
///
/// \param extension Name of the extension to test
///
/// \return True if the extension is supported, false if not
///
////////////////////////////////////////////////////////////
static bool isExtensionSupported(const std::string& extension);
////////////////////////////////////////////////////////////
/// \brief Get the OpenAL format that matches the given number of channels
///
/// \param channelCount Number of channels
///
/// \return Corresponding format
///
////////////////////////////////////////////////////////////
static int getFormatFromChannelCount(unsigned int channelCount);
};
} // namespace priv
} // namespace sf
#endif // SFML_AUDIODEVICE_HPP
////////////////////////////////////////////////////////////
//
// 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_AUDIODEVICE_HPP
#define SFML_AUDIODEVICE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <set>
#include <string>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief High-level wrapper around the audio API, it manages
/// the creation and destruction of the audio device and
/// context and stores the device capabilities
///
////////////////////////////////////////////////////////////
class AudioDevice
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
AudioDevice();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~AudioDevice();
////////////////////////////////////////////////////////////
/// \brief Check if an OpenAL extension is supported
///
/// This functions automatically finds whether it
/// is an AL or ALC extension, and calls the corresponding
/// function.
///
/// \param extension Name of the extension to test
///
/// \return True if the extension is supported, false if not
///
////////////////////////////////////////////////////////////
static bool isExtensionSupported(const std::string& extension);
////////////////////////////////////////////////////////////
/// \brief Get the OpenAL format that matches the given number of channels
///
/// \param channelCount Number of channels
///
/// \return Corresponding format
///
////////////////////////////////////////////////////////////
static int getFormatFromChannelCount(unsigned int channelCount);
};
} // namespace priv
} // namespace sf
#endif // SFML_AUDIODEVICE_HPP

View file

@ -1,65 +1,65 @@
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Audio)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio)
# all source files
set(SRC
${SRCROOT}/ALCheck.cpp
${SRCROOT}/ALCheck.hpp
${SRCROOT}/AudioDevice.cpp
${SRCROOT}/AudioDevice.hpp
${INCROOT}/Export.hpp
${SRCROOT}/Listener.cpp
${INCROOT}/Listener.hpp
${SRCROOT}/Music.cpp
${INCROOT}/Music.hpp
${SRCROOT}/Sound.cpp
${INCROOT}/Sound.hpp
${SRCROOT}/SoundBuffer.cpp
${INCROOT}/SoundBuffer.hpp
${SRCROOT}/SoundBufferRecorder.cpp
${INCROOT}/SoundBufferRecorder.hpp
${SRCROOT}/SoundFile.cpp
${SRCROOT}/SoundFile.hpp
${SRCROOT}/SoundRecorder.cpp
${INCROOT}/SoundRecorder.hpp
${SRCROOT}/SoundSource.cpp
${INCROOT}/SoundSource.hpp
${SRCROOT}/SoundStream.cpp
${INCROOT}/SoundStream.hpp
)
source_group("" FILES ${SRC})
# let CMake know about our additional audio libraries paths (on Windows and OSX)
if(SFML_OS_WINDOWS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/windows")
elseif(SFML_OS_MACOSX)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/osx")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
elseif(SFML_OS_ANDROID)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/android")
endif()
# find external libraries
if(NOT SFML_OS_ANDROID)
find_package(OpenAL REQUIRED)
find_package(Sndfile REQUIRED)
else()
find_host_package(OpenAL REQUIRED)
find_host_package(Sndfile REQUIRED)
endif()
include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
# build the list of external libraries to link
if(SFML_OS_ANDROID)
list(APPEND AUDIO_EXT_LIBS -landroid -lOpenSLES)
endif()
list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY})
# define the sfml-audio target
sfml_add_library(sfml-audio
SOURCES ${SRC}
DEPENDS sfml-system
EXTERNAL_LIBS ${AUDIO_EXT_LIBS})
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Audio)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Audio)
# all source files
set(SRC
${SRCROOT}/ALCheck.cpp
${SRCROOT}/ALCheck.hpp
${SRCROOT}/AudioDevice.cpp
${SRCROOT}/AudioDevice.hpp
${INCROOT}/Export.hpp
${SRCROOT}/Listener.cpp
${INCROOT}/Listener.hpp
${SRCROOT}/Music.cpp
${INCROOT}/Music.hpp
${SRCROOT}/Sound.cpp
${INCROOT}/Sound.hpp
${SRCROOT}/SoundBuffer.cpp
${INCROOT}/SoundBuffer.hpp
${SRCROOT}/SoundBufferRecorder.cpp
${INCROOT}/SoundBufferRecorder.hpp
${SRCROOT}/SoundFile.cpp
${SRCROOT}/SoundFile.hpp
${SRCROOT}/SoundRecorder.cpp
${INCROOT}/SoundRecorder.hpp
${SRCROOT}/SoundSource.cpp
${INCROOT}/SoundSource.hpp
${SRCROOT}/SoundStream.cpp
${INCROOT}/SoundStream.hpp
)
source_group("" FILES ${SRC})
# let CMake know about our additional audio libraries paths (on Windows and OSX)
if(SFML_OS_WINDOWS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/windows")
elseif(SFML_OS_MACOSX)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/osx")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
elseif(SFML_OS_ANDROID)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/AL")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libsndfile/android")
endif()
# find external libraries
if(NOT SFML_OS_ANDROID)
find_package(OpenAL REQUIRED)
find_package(Sndfile REQUIRED)
else()
find_host_package(OpenAL REQUIRED)
find_host_package(Sndfile REQUIRED)
endif()
include_directories(${OPENAL_INCLUDE_DIR} ${SNDFILE_INCLUDE_DIR})
# build the list of external libraries to link
if(SFML_OS_ANDROID)
list(APPEND AUDIO_EXT_LIBS -landroid -lOpenSLES)
endif()
list(APPEND AUDIO_EXT_LIBS ${OPENAL_LIBRARY} ${SNDFILE_LIBRARY})
# define the sfml-audio target
sfml_add_library(sfml-audio
SOURCES ${SRC}
DEPENDS sfml-system
EXTERNAL_LIBS ${AUDIO_EXT_LIBS})

View file

@ -1,145 +1,145 @@
////////////////////////////////////////////////////////////
//
// 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/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);
}
namespace sf
{
////////////////////////////////////////////////////////////
void Listener::setGlobalVolume(float volume)
{
if (volume != listenerVolume)
{
priv::ensureALInit();
alCheck(alListenerf(AL_GAIN, volume * 0.01f));
listenerVolume = volume;
}
}
////////////////////////////////////////////////////////////
float Listener::getGlobalVolume()
{
return listenerVolume;
}
////////////////////////////////////////////////////////////
void Listener::setPosition(float x, float y, float z)
{
setPosition(Vector3f(x, y, z));
}
////////////////////////////////////////////////////////////
void Listener::setPosition(const Vector3f& position)
{
if (position != listenerPosition)
{
priv::ensureALInit();
alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));
listenerPosition = position;
}
}
////////////////////////////////////////////////////////////
Vector3f Listener::getPosition()
{
return listenerPosition;
}
////////////////////////////////////////////////////////////
void Listener::setDirection(float x, float y, float z)
{
setDirection(Vector3f(x, y, 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;
}
}
////////////////////////////////////////////////////////////
Vector3f Listener::getDirection()
{
return listenerDirection;
}
////////////////////////////////////////////////////////////
void Listener::setUpVector(float x, float y, float z)
{
setUpVector(Vector3f(x, y, 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;
}
}
////////////////////////////////////////////////////////////
Vector3f Listener::getUpVector()
{
return listenerUpVector;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/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);
}
namespace sf
{
////////////////////////////////////////////////////////////
void Listener::setGlobalVolume(float volume)
{
if (volume != listenerVolume)
{
priv::ensureALInit();
alCheck(alListenerf(AL_GAIN, volume * 0.01f));
listenerVolume = volume;
}
}
////////////////////////////////////////////////////////////
float Listener::getGlobalVolume()
{
return listenerVolume;
}
////////////////////////////////////////////////////////////
void Listener::setPosition(float x, float y, float z)
{
setPosition(Vector3f(x, y, z));
}
////////////////////////////////////////////////////////////
void Listener::setPosition(const Vector3f& position)
{
if (position != listenerPosition)
{
priv::ensureALInit();
alCheck(alListener3f(AL_POSITION, position.x, position.y, position.z));
listenerPosition = position;
}
}
////////////////////////////////////////////////////////////
Vector3f Listener::getPosition()
{
return listenerPosition;
}
////////////////////////////////////////////////////////////
void Listener::setDirection(float x, float y, float z)
{
setDirection(Vector3f(x, y, 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;
}
}
////////////////////////////////////////////////////////////
Vector3f Listener::getDirection()
{
return listenerDirection;
}
////////////////////////////////////////////////////////////
void Listener::setUpVector(float x, float y, float z)
{
setUpVector(Vector3f(x, y, 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;
}
}
////////////////////////////////////////////////////////////
Vector3f Listener::getUpVector()
{
return listenerUpVector;
}
} // namespace sf

View file

@ -1,151 +1,151 @@
////////////////////////////////////////////////////////////
//
// 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/Music.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/Audio/SoundFile.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <fstream>
namespace sf
{
////////////////////////////////////////////////////////////
Music::Music() :
m_file (new priv::SoundFile),
m_duration()
{
}
////////////////////////////////////////////////////////////
Music::~Music()
{
// We must stop before destroying the file
stop();
delete m_file;
}
////////////////////////////////////////////////////////////
bool Music::openFromFile(const std::string& filename)
{
// First stop the music if it was already running
stop();
// Open the underlying sound file
if (!m_file->openRead(filename))
return false;
// Perform common initializations
initialize();
return true;
}
////////////////////////////////////////////////////////////
bool Music::openFromMemory(const void* data, std::size_t sizeInBytes)
{
// First stop the music if it was already running
stop();
// Open the underlying sound file
if (!m_file->openRead(data, sizeInBytes))
return false;
// Perform common initializations
initialize();
return true;
}
////////////////////////////////////////////////////////////
bool Music::openFromStream(InputStream& stream)
{
// First stop the music if it was already running
stop();
// Open the underlying sound file
if (!m_file->openRead(stream))
return false;
// Perform common initializations
initialize();
return true;
}
////////////////////////////////////////////////////////////
Time Music::getDuration() const
{
return m_duration;
}
////////////////////////////////////////////////////////////
bool Music::onGetData(SoundStream::Chunk& data)
{
Lock lock(m_mutex);
// Fill the chunk parameters
data.samples = &m_samples[0];
data.sampleCount = m_file->read(&m_samples[0], m_samples.size());
// Check if we have reached the end of the audio file
return data.sampleCount == m_samples.size();
}
////////////////////////////////////////////////////////////
void Music::onSeek(Time timeOffset)
{
Lock lock(m_mutex);
m_file->seek(timeOffset);
}
////////////////////////////////////////////////////////////
void Music::initialize()
{
// Compute the music duration
m_duration = seconds(static_cast<float>(m_file->getSampleCount()) / m_file->getSampleRate() / m_file->getChannelCount());
// Resize the internal buffer so that it can contain 1 second of audio samples
m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount());
// Initialize the stream
SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate());
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Music.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/Audio/SoundFile.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/System/Err.hpp>
#include <fstream>
namespace sf
{
////////////////////////////////////////////////////////////
Music::Music() :
m_file (new priv::SoundFile),
m_duration()
{
}
////////////////////////////////////////////////////////////
Music::~Music()
{
// We must stop before destroying the file
stop();
delete m_file;
}
////////////////////////////////////////////////////////////
bool Music::openFromFile(const std::string& filename)
{
// First stop the music if it was already running
stop();
// Open the underlying sound file
if (!m_file->openRead(filename))
return false;
// Perform common initializations
initialize();
return true;
}
////////////////////////////////////////////////////////////
bool Music::openFromMemory(const void* data, std::size_t sizeInBytes)
{
// First stop the music if it was already running
stop();
// Open the underlying sound file
if (!m_file->openRead(data, sizeInBytes))
return false;
// Perform common initializations
initialize();
return true;
}
////////////////////////////////////////////////////////////
bool Music::openFromStream(InputStream& stream)
{
// First stop the music if it was already running
stop();
// Open the underlying sound file
if (!m_file->openRead(stream))
return false;
// Perform common initializations
initialize();
return true;
}
////////////////////////////////////////////////////////////
Time Music::getDuration() const
{
return m_duration;
}
////////////////////////////////////////////////////////////
bool Music::onGetData(SoundStream::Chunk& data)
{
Lock lock(m_mutex);
// Fill the chunk parameters
data.samples = &m_samples[0];
data.sampleCount = m_file->read(&m_samples[0], m_samples.size());
// Check if we have reached the end of the audio file
return data.sampleCount == m_samples.size();
}
////////////////////////////////////////////////////////////
void Music::onSeek(Time timeOffset)
{
Lock lock(m_mutex);
m_file->seek(timeOffset);
}
////////////////////////////////////////////////////////////
void Music::initialize()
{
// Compute the music duration
m_duration = seconds(static_cast<float>(m_file->getSampleCount()) / m_file->getSampleRate() / m_file->getChannelCount());
// Resize the internal buffer so that it can contain 1 second of audio samples
m_samples.resize(m_file->getSampleRate() * m_file->getChannelCount());
// Initialize the stream
SoundStream::initialize(m_file->getChannelCount(), m_file->getSampleRate());
}
} // namespace sf

View file

@ -1,200 +1,200 @@
////////////////////////////////////////////////////////////
//
// 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/Sound.hpp>
#include <SFML/Audio/SoundBuffer.hpp>
#include <SFML/Audio/ALCheck.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Sound::Sound() :
m_buffer(NULL)
{
}
////////////////////////////////////////////////////////////
Sound::Sound(const SoundBuffer& buffer) :
m_buffer(NULL)
{
setBuffer(buffer);
}
////////////////////////////////////////////////////////////
Sound::Sound(const Sound& copy) :
SoundSource(copy),
m_buffer (NULL)
{
if (copy.m_buffer)
setBuffer(*copy.m_buffer);
setLoop(copy.getLoop());
}
////////////////////////////////////////////////////////////
Sound::~Sound()
{
stop();
if (m_buffer)
m_buffer->detachSound(this);
}
////////////////////////////////////////////////////////////
void Sound::play()
{
alCheck(alSourcePlay(m_source));
}
////////////////////////////////////////////////////////////
void Sound::pause()
{
alCheck(alSourcePause(m_source));
}
////////////////////////////////////////////////////////////
void Sound::stop()
{
alCheck(alSourceStop(m_source));
}
////////////////////////////////////////////////////////////
void Sound::setBuffer(const SoundBuffer& buffer)
{
// First detach from the previous buffer
if (m_buffer)
{
stop();
m_buffer->detachSound(this);
}
// Assign and use the new buffer
m_buffer = &buffer;
m_buffer->attachSound(this);
alCheck(alSourcei(m_source, AL_BUFFER, m_buffer->m_buffer));
}
////////////////////////////////////////////////////////////
void Sound::setLoop(bool loop)
{
alCheck(alSourcei(m_source, AL_LOOPING, loop));
}
////////////////////////////////////////////////////////////
void Sound::setPlayingOffset(Time timeOffset)
{
alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds()));
}
////////////////////////////////////////////////////////////
const SoundBuffer* Sound::getBuffer() const
{
return m_buffer;
}
////////////////////////////////////////////////////////////
bool Sound::getLoop() const
{
ALint loop;
alCheck(alGetSourcei(m_source, AL_LOOPING, &loop));
return loop != 0;
}
////////////////////////////////////////////////////////////
Time Sound::getPlayingOffset() const
{
ALfloat secs = 0.f;
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
return seconds(secs);
}
////////////////////////////////////////////////////////////
Sound::Status Sound::getStatus() const
{
return SoundSource::getStatus();
}
////////////////////////////////////////////////////////////
Sound& Sound::operator =(const Sound& right)
{
// Here we don't use the copy-and-swap idiom, because it would mess up
// the list of sound instances contained in the buffers
// Detach the sound instance from the previous buffer (if any)
if (m_buffer)
{
stop();
m_buffer->detachSound(this);
m_buffer = NULL;
}
// Copy the sound attributes
if (right.m_buffer)
setBuffer(*right.m_buffer);
setLoop(right.getLoop());
setPitch(right.getPitch());
setVolume(right.getVolume());
setPosition(right.getPosition());
setRelativeToListener(right.isRelativeToListener());
setMinDistance(right.getMinDistance());
setAttenuation(right.getAttenuation());
return *this;
}
////////////////////////////////////////////////////////////
void Sound::resetBuffer()
{
// First stop the sound in case it is playing
stop();
// Detach the buffer
if (m_buffer)
{
alCheck(alSourcei(m_source, AL_BUFFER, 0));
m_buffer->detachSound(this);
m_buffer = NULL;
}
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Sound.hpp>
#include <SFML/Audio/SoundBuffer.hpp>
#include <SFML/Audio/ALCheck.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Sound::Sound() :
m_buffer(NULL)
{
}
////////////////////////////////////////////////////////////
Sound::Sound(const SoundBuffer& buffer) :
m_buffer(NULL)
{
setBuffer(buffer);
}
////////////////////////////////////////////////////////////
Sound::Sound(const Sound& copy) :
SoundSource(copy),
m_buffer (NULL)
{
if (copy.m_buffer)
setBuffer(*copy.m_buffer);
setLoop(copy.getLoop());
}
////////////////////////////////////////////////////////////
Sound::~Sound()
{
stop();
if (m_buffer)
m_buffer->detachSound(this);
}
////////////////////////////////////////////////////////////
void Sound::play()
{
alCheck(alSourcePlay(m_source));
}
////////////////////////////////////////////////////////////
void Sound::pause()
{
alCheck(alSourcePause(m_source));
}
////////////////////////////////////////////////////////////
void Sound::stop()
{
alCheck(alSourceStop(m_source));
}
////////////////////////////////////////////////////////////
void Sound::setBuffer(const SoundBuffer& buffer)
{
// First detach from the previous buffer
if (m_buffer)
{
stop();
m_buffer->detachSound(this);
}
// Assign and use the new buffer
m_buffer = &buffer;
m_buffer->attachSound(this);
alCheck(alSourcei(m_source, AL_BUFFER, m_buffer->m_buffer));
}
////////////////////////////////////////////////////////////
void Sound::setLoop(bool loop)
{
alCheck(alSourcei(m_source, AL_LOOPING, loop));
}
////////////////////////////////////////////////////////////
void Sound::setPlayingOffset(Time timeOffset)
{
alCheck(alSourcef(m_source, AL_SEC_OFFSET, timeOffset.asSeconds()));
}
////////////////////////////////////////////////////////////
const SoundBuffer* Sound::getBuffer() const
{
return m_buffer;
}
////////////////////////////////////////////////////////////
bool Sound::getLoop() const
{
ALint loop;
alCheck(alGetSourcei(m_source, AL_LOOPING, &loop));
return loop != 0;
}
////////////////////////////////////////////////////////////
Time Sound::getPlayingOffset() const
{
ALfloat secs = 0.f;
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
return seconds(secs);
}
////////////////////////////////////////////////////////////
Sound::Status Sound::getStatus() const
{
return SoundSource::getStatus();
}
////////////////////////////////////////////////////////////
Sound& Sound::operator =(const Sound& right)
{
// Here we don't use the copy-and-swap idiom, because it would mess up
// the list of sound instances contained in the buffers
// Detach the sound instance from the previous buffer (if any)
if (m_buffer)
{
stop();
m_buffer->detachSound(this);
m_buffer = NULL;
}
// Copy the sound attributes
if (right.m_buffer)
setBuffer(*right.m_buffer);
setLoop(right.getLoop());
setPitch(right.getPitch());
setVolume(right.getVolume());
setPosition(right.getPosition());
setRelativeToListener(right.isRelativeToListener());
setMinDistance(right.getMinDistance());
setAttenuation(right.getAttenuation());
return *this;
}
////////////////////////////////////////////////////////////
void Sound::resetBuffer()
{
// First stop the sound in case it is playing
stop();
// Detach the buffer
if (m_buffer)
{
alCheck(alSourcei(m_source, AL_BUFFER, 0));
m_buffer->detachSound(this);
m_buffer = NULL;
}
}
} // namespace sf

View file

@ -1,286 +1,286 @@
////////////////////////////////////////////////////////////
//
// 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/SoundBuffer.hpp>
#include <SFML/Audio/SoundFile.hpp>
#include <SFML/Audio/Sound.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/System/Err.hpp>
#include <memory>
namespace sf
{
////////////////////////////////////////////////////////////
SoundBuffer::SoundBuffer() :
m_buffer (0),
m_duration()
{
priv::ensureALInit();
// Create the buffer
alCheck(alGenBuffers(1, &m_buffer));
}
////////////////////////////////////////////////////////////
SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
m_buffer (0),
m_samples (copy.m_samples),
m_duration(copy.m_duration),
m_sounds () // don't copy the attached sounds
{
// Create the buffer
alCheck(alGenBuffers(1, &m_buffer));
// Update the internal buffer with the new samples
update(copy.getChannelCount(), copy.getSampleRate());
}
////////////////////////////////////////////////////////////
SoundBuffer::~SoundBuffer()
{
// First detach the buffer from the sounds that use it (to avoid OpenAL errors)
for (SoundList::const_iterator it = m_sounds.begin(); it != m_sounds.end(); ++it)
(*it)->resetBuffer();
// Destroy the buffer
if (m_buffer)
alCheck(alDeleteBuffers(1, &m_buffer));
}
////////////////////////////////////////////////////////////
bool SoundBuffer::loadFromFile(const std::string& filename)
{
priv::SoundFile file;
if (file.openRead(filename))
return initialize(file);
else
return false;
}
////////////////////////////////////////////////////////////
bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
{
priv::SoundFile file;
if (file.openRead(data, sizeInBytes))
return initialize(file);
else
return false;
}
////////////////////////////////////////////////////////////
bool SoundBuffer::loadFromStream(InputStream& stream)
{
priv::SoundFile file;
if (file.openRead(stream))
return initialize(file);
else
return false;
}
////////////////////////////////////////////////////////////
bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate)
{
if (samples && sampleCount && channelCount && sampleRate)
{
// Copy the new audio samples
m_samples.assign(samples, samples + sampleCount);
// Update the internal buffer with the new samples
return update(channelCount, sampleRate);
}
else
{
// Error...
err() << "Failed to load sound buffer from samples ("
<< "array: " << samples << ", "
<< "count: " << sampleCount << ", "
<< "channels: " << channelCount << ", "
<< "samplerate: " << sampleRate << ")"
<< std::endl;
return false;
}
}
////////////////////////////////////////////////////////////
bool SoundBuffer::saveToFile(const std::string& filename) const
{
// Create the sound file in write mode
priv::SoundFile file;
if (file.openWrite(filename, getChannelCount(), getSampleRate()))
{
// Write the samples to the opened file
file.write(&m_samples[0], m_samples.size());
return true;
}
else
{
return false;
}
}
////////////////////////////////////////////////////////////
const Int16* SoundBuffer::getSamples() const
{
return m_samples.empty() ? NULL : &m_samples[0];
}
////////////////////////////////////////////////////////////
std::size_t SoundBuffer::getSampleCount() const
{
return m_samples.size();
}
////////////////////////////////////////////////////////////
unsigned int SoundBuffer::getSampleRate() const
{
ALint sampleRate;
alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate));
return sampleRate;
}
////////////////////////////////////////////////////////////
unsigned int SoundBuffer::getChannelCount() const
{
ALint channelCount;
alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount));
return channelCount;
}
////////////////////////////////////////////////////////////
Time SoundBuffer::getDuration() const
{
return m_duration;
}
////////////////////////////////////////////////////////////
SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
{
SoundBuffer temp(right);
std::swap(m_samples, temp.m_samples);
std::swap(m_buffer, temp.m_buffer);
std::swap(m_duration, temp.m_duration);
std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed
return *this;
}
////////////////////////////////////////////////////////////
bool SoundBuffer::initialize(priv::SoundFile& file)
{
// Retrieve the sound parameters
std::size_t sampleCount = file.getSampleCount();
unsigned int channelCount = file.getChannelCount();
unsigned int sampleRate = file.getSampleRate();
// Read the samples from the provided file
m_samples.resize(sampleCount);
if (file.read(&m_samples[0], sampleCount) == sampleCount)
{
// Update the internal buffer with the new samples
return update(channelCount, sampleRate);
}
else
{
return false;
}
}
////////////////////////////////////////////////////////////
bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate)
{
// Check parameters
if (!channelCount || !sampleRate || m_samples.empty())
return false;
// Find the good format according to the number of channels
ALenum format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
// Check if the format is valid
if (format == 0)
{
err() << "Failed to load sound buffer (unsupported number of channels: " << channelCount << ")" << std::endl;
return false;
}
// First make a copy of the list of sounds so we can reattach later
SoundList sounds(m_sounds);
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
(*it)->resetBuffer();
// Fill the buffer
ALsizei size = static_cast<ALsizei>(m_samples.size()) * sizeof(Int16);
alCheck(alBufferData(m_buffer, format, &m_samples[0], size, sampleRate));
// Compute the duration
m_duration = seconds(static_cast<float>(m_samples.size()) / sampleRate / channelCount);
// Now reattach the buffer to the sounds that use it
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
(*it)->setBuffer(*this);
return true;
}
////////////////////////////////////////////////////////////
void SoundBuffer::attachSound(Sound* sound) const
{
m_sounds.insert(sound);
}
////////////////////////////////////////////////////////////
void SoundBuffer::detachSound(Sound* sound) const
{
m_sounds.erase(sound);
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/SoundBuffer.hpp>
#include <SFML/Audio/SoundFile.hpp>
#include <SFML/Audio/Sound.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/System/Err.hpp>
#include <memory>
namespace sf
{
////////////////////////////////////////////////////////////
SoundBuffer::SoundBuffer() :
m_buffer (0),
m_duration()
{
priv::ensureALInit();
// Create the buffer
alCheck(alGenBuffers(1, &m_buffer));
}
////////////////////////////////////////////////////////////
SoundBuffer::SoundBuffer(const SoundBuffer& copy) :
m_buffer (0),
m_samples (copy.m_samples),
m_duration(copy.m_duration),
m_sounds () // don't copy the attached sounds
{
// Create the buffer
alCheck(alGenBuffers(1, &m_buffer));
// Update the internal buffer with the new samples
update(copy.getChannelCount(), copy.getSampleRate());
}
////////////////////////////////////////////////////////////
SoundBuffer::~SoundBuffer()
{
// First detach the buffer from the sounds that use it (to avoid OpenAL errors)
for (SoundList::const_iterator it = m_sounds.begin(); it != m_sounds.end(); ++it)
(*it)->resetBuffer();
// Destroy the buffer
if (m_buffer)
alCheck(alDeleteBuffers(1, &m_buffer));
}
////////////////////////////////////////////////////////////
bool SoundBuffer::loadFromFile(const std::string& filename)
{
priv::SoundFile file;
if (file.openRead(filename))
return initialize(file);
else
return false;
}
////////////////////////////////////////////////////////////
bool SoundBuffer::loadFromMemory(const void* data, std::size_t sizeInBytes)
{
priv::SoundFile file;
if (file.openRead(data, sizeInBytes))
return initialize(file);
else
return false;
}
////////////////////////////////////////////////////////////
bool SoundBuffer::loadFromStream(InputStream& stream)
{
priv::SoundFile file;
if (file.openRead(stream))
return initialize(file);
else
return false;
}
////////////////////////////////////////////////////////////
bool SoundBuffer::loadFromSamples(const Int16* samples, std::size_t sampleCount, unsigned int channelCount, unsigned int sampleRate)
{
if (samples && sampleCount && channelCount && sampleRate)
{
// Copy the new audio samples
m_samples.assign(samples, samples + sampleCount);
// Update the internal buffer with the new samples
return update(channelCount, sampleRate);
}
else
{
// Error...
err() << "Failed to load sound buffer from samples ("
<< "array: " << samples << ", "
<< "count: " << sampleCount << ", "
<< "channels: " << channelCount << ", "
<< "samplerate: " << sampleRate << ")"
<< std::endl;
return false;
}
}
////////////////////////////////////////////////////////////
bool SoundBuffer::saveToFile(const std::string& filename) const
{
// Create the sound file in write mode
priv::SoundFile file;
if (file.openWrite(filename, getChannelCount(), getSampleRate()))
{
// Write the samples to the opened file
file.write(&m_samples[0], m_samples.size());
return true;
}
else
{
return false;
}
}
////////////////////////////////////////////////////////////
const Int16* SoundBuffer::getSamples() const
{
return m_samples.empty() ? NULL : &m_samples[0];
}
////////////////////////////////////////////////////////////
std::size_t SoundBuffer::getSampleCount() const
{
return m_samples.size();
}
////////////////////////////////////////////////////////////
unsigned int SoundBuffer::getSampleRate() const
{
ALint sampleRate;
alCheck(alGetBufferi(m_buffer, AL_FREQUENCY, &sampleRate));
return sampleRate;
}
////////////////////////////////////////////////////////////
unsigned int SoundBuffer::getChannelCount() const
{
ALint channelCount;
alCheck(alGetBufferi(m_buffer, AL_CHANNELS, &channelCount));
return channelCount;
}
////////////////////////////////////////////////////////////
Time SoundBuffer::getDuration() const
{
return m_duration;
}
////////////////////////////////////////////////////////////
SoundBuffer& SoundBuffer::operator =(const SoundBuffer& right)
{
SoundBuffer temp(right);
std::swap(m_samples, temp.m_samples);
std::swap(m_buffer, temp.m_buffer);
std::swap(m_duration, temp.m_duration);
std::swap(m_sounds, temp.m_sounds); // swap sounds too, so that they are detached when temp is destroyed
return *this;
}
////////////////////////////////////////////////////////////
bool SoundBuffer::initialize(priv::SoundFile& file)
{
// Retrieve the sound parameters
std::size_t sampleCount = file.getSampleCount();
unsigned int channelCount = file.getChannelCount();
unsigned int sampleRate = file.getSampleRate();
// Read the samples from the provided file
m_samples.resize(sampleCount);
if (file.read(&m_samples[0], sampleCount) == sampleCount)
{
// Update the internal buffer with the new samples
return update(channelCount, sampleRate);
}
else
{
return false;
}
}
////////////////////////////////////////////////////////////
bool SoundBuffer::update(unsigned int channelCount, unsigned int sampleRate)
{
// Check parameters
if (!channelCount || !sampleRate || m_samples.empty())
return false;
// Find the good format according to the number of channels
ALenum format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
// Check if the format is valid
if (format == 0)
{
err() << "Failed to load sound buffer (unsupported number of channels: " << channelCount << ")" << std::endl;
return false;
}
// First make a copy of the list of sounds so we can reattach later
SoundList sounds(m_sounds);
// Detach the buffer from the sounds that use it (to avoid OpenAL errors)
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
(*it)->resetBuffer();
// Fill the buffer
ALsizei size = static_cast<ALsizei>(m_samples.size()) * sizeof(Int16);
alCheck(alBufferData(m_buffer, format, &m_samples[0], size, sampleRate));
// Compute the duration
m_duration = seconds(static_cast<float>(m_samples.size()) / sampleRate / channelCount);
// Now reattach the buffer to the sounds that use it
for (SoundList::const_iterator it = sounds.begin(); it != sounds.end(); ++it)
(*it)->setBuffer(*this);
return true;
}
////////////////////////////////////////////////////////////
void SoundBuffer::attachSound(Sound* sound) const
{
m_sounds.insert(sound);
}
////////////////////////////////////////////////////////////
void SoundBuffer::detachSound(Sound* sound) const
{
m_sounds.erase(sound);
}
} // namespace sf

View file

@ -1,68 +1,68 @@
////////////////////////////////////////////////////////////
//
// 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/SoundBufferRecorder.hpp>
#include <algorithm>
#include <iterator>
namespace sf
{
////////////////////////////////////////////////////////////
bool SoundBufferRecorder::onStart()
{
m_samples.clear();
m_buffer = SoundBuffer();
return true;
}
////////////////////////////////////////////////////////////
bool SoundBufferRecorder::onProcessSamples(const Int16* samples, std::size_t sampleCount)
{
std::copy(samples, samples + sampleCount, std::back_inserter(m_samples));
return true;
}
////////////////////////////////////////////////////////////
void SoundBufferRecorder::onStop()
{
if (!m_samples.empty())
m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), 1, getSampleRate());
}
////////////////////////////////////////////////////////////
const SoundBuffer& SoundBufferRecorder::getBuffer() const
{
return m_buffer;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/SoundBufferRecorder.hpp>
#include <algorithm>
#include <iterator>
namespace sf
{
////////////////////////////////////////////////////////////
bool SoundBufferRecorder::onStart()
{
m_samples.clear();
m_buffer = SoundBuffer();
return true;
}
////////////////////////////////////////////////////////////
bool SoundBufferRecorder::onProcessSamples(const Int16* samples, std::size_t sampleCount)
{
std::copy(samples, samples + sampleCount, std::back_inserter(m_samples));
return true;
}
////////////////////////////////////////////////////////////
void SoundBufferRecorder::onStop()
{
if (!m_samples.empty())
m_buffer.loadFromSamples(&m_samples[0], m_samples.size(), 1, getSampleRate());
}
////////////////////////////////////////////////////////////
const SoundBuffer& SoundBufferRecorder::getBuffer() const
{
return m_buffer;
}
} // namespace sf

View file

@ -1,451 +1,451 @@
////////////////////////////////////////////////////////////
//
// 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/SoundFile.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/ResourceStream.hpp>
#endif
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp>
#include <cstring>
#include <cctype>
namespace
{
// Convert a string to lower case
std::string toLower(std::string str)
{
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
*i = static_cast<char>(std::tolower(*i));
return str;
}
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
SoundFile::SoundFile() :
m_file (NULL),
m_sampleCount (0),
m_channelCount(0),
m_sampleRate (0)
{
#ifdef SFML_SYSTEM_ANDROID
m_resourceStream = NULL;
#endif
}
////////////////////////////////////////////////////////////
SoundFile::~SoundFile()
{
if (m_file)
sf_close(m_file);
#ifdef SFML_SYSTEM_ANDROID
if (m_resourceStream)
delete (priv::ResourceStream*)m_resourceStream;
#endif
}
////////////////////////////////////////////////////////////
std::size_t SoundFile::getSampleCount() const
{
return m_sampleCount;
}
////////////////////////////////////////////////////////////
unsigned int SoundFile::getChannelCount() const
{
return m_channelCount;
}
////////////////////////////////////////////////////////////
unsigned int SoundFile::getSampleRate() const
{
return m_sampleRate;
}
////////////////////////////////////////////////////////////
bool SoundFile::openRead(const std::string& filename)
{
#ifndef SFML_SYSTEM_ANDROID
// If the file is already opened, first close it
if (m_file)
sf_close(m_file);
// Open the sound file
SF_INFO fileInfo;
fileInfo.format = 0;
m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
if (!m_file)
{
err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
return false;
}
// Initialize the internal state from the loaded information
initialize(fileInfo);
return true;
#else
if (m_resourceStream)
delete (priv::ResourceStream*)m_resourceStream;
m_resourceStream = new priv::ResourceStream(filename);
return openRead(*(priv::ResourceStream*)m_resourceStream);
#endif
}
////////////////////////////////////////////////////////////
bool SoundFile::openRead(const void* data, std::size_t sizeInBytes)
{
// If the file is already opened, first close it
if (m_file)
sf_close(m_file);
// Prepare the memory I/O structure
SF_VIRTUAL_IO io;
io.get_filelen = &Memory::getLength;
io.read = &Memory::read;
io.seek = &Memory::seek;
io.tell = &Memory::tell;
// Initialize the memory data
m_memory.begin = static_cast<const char*>(data);
m_memory.current = m_memory.begin;
m_memory.size = sizeInBytes;
// Open the sound file
SF_INFO fileInfo;
fileInfo.format = 0;
m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory);
if (!m_file)
{
err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl;
return false;
}
// Initialize the internal state from the loaded information
initialize(fileInfo);
return true;
}
////////////////////////////////////////////////////////////
bool SoundFile::openRead(InputStream& stream)
{
// If the file is already opened, first close it
if (m_file)
sf_close(m_file);
// Prepare the memory I/O structure
SF_VIRTUAL_IO io;
io.get_filelen = &Stream::getLength;
io.read = &Stream::read;
io.seek = &Stream::seek;
io.tell = &Stream::tell;
// Initialize the stream data
m_stream.source = &stream;
m_stream.size = stream.getSize();
// Make sure that the stream's reading position is at the beginning
stream.seek(0);
// Open the sound file
SF_INFO fileInfo;
fileInfo.format = 0;
m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream);
if (!m_file)
{
err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl;
return false;
}
// Initialize the internal state from the loaded information
initialize(fileInfo);
return true;
}
////////////////////////////////////////////////////////////
bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate)
{
// If the file is already opened, first close it
if (m_file)
sf_close(m_file);
// Find the right format according to the file extension
int format = getFormatFromFilename(filename);
if (format == -1)
{
// Error : unrecognized extension
err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl;
return false;
}
// Fill the sound infos with parameters
SF_INFO fileInfos;
fileInfos.channels = channelCount;
fileInfos.samplerate = sampleRate;
fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16);
// Open the sound file for writing
m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
if (!m_file)
{
err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
return false;
}
// Set the sound parameters
m_channelCount = channelCount;
m_sampleRate = sampleRate;
m_sampleCount = 0;
return true;
}
////////////////////////////////////////////////////////////
std::size_t SoundFile::read(Int16* data, std::size_t sampleCount)
{
if (m_file && data && sampleCount)
return static_cast<std::size_t>(sf_read_short(m_file, data, sampleCount));
else
return 0;
}
////////////////////////////////////////////////////////////
void SoundFile::write(const Int16* data, std::size_t sampleCount)
{
if (m_file && data && sampleCount)
{
// Write small chunks instead of everything at once,
// to avoid a stack overflow in libsndfile (happens only with OGG format)
while (sampleCount > 0)
{
std::size_t count = sampleCount > 10000 ? 10000 : sampleCount;
sf_write_short(m_file, data, count);
data += count;
sampleCount -= count;
}
}
}
////////////////////////////////////////////////////////////
void SoundFile::seek(Time timeOffset)
{
if (m_file)
{
sf_count_t frameOffset = static_cast<sf_count_t>(timeOffset.asSeconds() * m_sampleRate);
sf_seek(m_file, frameOffset, SEEK_SET);
}
}
////////////////////////////////////////////////////////////
void SoundFile::initialize(SF_INFO fileInfo)
{
// Save the sound properties
m_channelCount = fileInfo.channels;
m_sampleRate = fileInfo.samplerate;
m_sampleCount = static_cast<std::size_t>(fileInfo.frames) * fileInfo.channels;
// Enable scaling for Vorbis files (float samples)
// @todo enable when it's faster (it currently has to iterate over the *whole* music)
//if (fileInfo.format & SF_FORMAT_VORBIS)
// sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
}
////////////////////////////////////////////////////////////
int SoundFile::getFormatFromFilename(const std::string& filename)
{
// Extract the extension
std::string ext = "wav";
std::string::size_type pos = filename.find_last_of(".");
if (pos != std::string::npos)
ext = toLower(filename.substr(pos + 1));
// Match every supported extension with its format constant
if (ext == "wav" ) return SF_FORMAT_WAV;
if (ext == "aif" ) return SF_FORMAT_AIFF;
if (ext == "aiff" ) return SF_FORMAT_AIFF;
if (ext == "au" ) return SF_FORMAT_AU;
if (ext == "raw" ) return SF_FORMAT_RAW;
if (ext == "paf" ) return SF_FORMAT_PAF;
if (ext == "svx" ) return SF_FORMAT_SVX;
if (ext == "nist" ) return SF_FORMAT_NIST;
if (ext == "voc" ) return SF_FORMAT_VOC;
if (ext == "sf" ) return SF_FORMAT_IRCAM;
if (ext == "w64" ) return SF_FORMAT_W64;
if (ext == "mat4" ) return SF_FORMAT_MAT4;
if (ext == "mat5" ) return SF_FORMAT_MAT5;
if (ext == "pvf" ) return SF_FORMAT_PVF;
if (ext == "xi" ) return SF_FORMAT_XI;
if (ext == "htk" ) return SF_FORMAT_HTK;
if (ext == "sds" ) return SF_FORMAT_SDS;
if (ext == "avr" ) return SF_FORMAT_AVR;
if (ext == "sd2" ) return SF_FORMAT_SD2;
if (ext == "flac" ) return SF_FORMAT_FLAC;
if (ext == "caf" ) return SF_FORMAT_CAF;
if (ext == "wve" ) return SF_FORMAT_WVE;
if (ext == "ogg" ) return SF_FORMAT_OGG;
if (ext == "mpc2k") return SF_FORMAT_MPC2K;
if (ext == "rf64" ) return SF_FORMAT_RF64;
return -1;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Memory::getLength(void* user)
{
Memory* memory = static_cast<Memory*>(user);
return memory->size;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user)
{
Memory* memory = static_cast<Memory*>(user);
sf_count_t position = tell(user);
if (position + count >= memory->size)
count = memory->size - position;
std::memcpy(ptr, memory->current, static_cast<std::size_t>(count));
memory->current += count;
return count;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
{
Memory* memory = static_cast<Memory*>(user);
sf_count_t position = 0;
switch (whence)
{
case SEEK_SET : position = offset; break;
case SEEK_CUR : position = memory->current - memory->begin + offset; break;
case SEEK_END : position = memory->size - offset; break;
default : position = 0; break;
}
if (position >= memory->size)
position = memory->size - 1;
else if (position < 0)
position = 0;
memory->current = memory->begin + position;
return position;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Memory::tell(void* user)
{
Memory* memory = static_cast<Memory*>(user);
return memory->current - memory->begin;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::getLength(void* userData)
{
Stream* stream = static_cast<Stream*>(userData);
return stream->size;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData)
{
Stream* stream = static_cast<Stream*>(userData);
Int64 position = stream->source->tell();
if (position != -1)
{
if (count > stream->size - position)
count = stream->size - position;
return stream->source->read(reinterpret_cast<char*>(ptr), count);
}
else
{
return -1;
}
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData)
{
Stream* stream = static_cast<Stream*>(userData);
switch (whence)
{
case SEEK_SET : return stream->source->seek(offset);
case SEEK_CUR : return stream->source->seek(stream->source->tell() + offset);
case SEEK_END : return stream->source->seek(stream->size - offset);
default : return stream->source->seek(0);
}
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::tell(void* userData)
{
Stream* stream = static_cast<Stream*>(userData);
return stream->source->tell();
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/SoundFile.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/ResourceStream.hpp>
#endif
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp>
#include <cstring>
#include <cctype>
namespace
{
// Convert a string to lower case
std::string toLower(std::string str)
{
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
*i = static_cast<char>(std::tolower(*i));
return str;
}
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
SoundFile::SoundFile() :
m_file (NULL),
m_sampleCount (0),
m_channelCount(0),
m_sampleRate (0)
{
#ifdef SFML_SYSTEM_ANDROID
m_resourceStream = NULL;
#endif
}
////////////////////////////////////////////////////////////
SoundFile::~SoundFile()
{
if (m_file)
sf_close(m_file);
#ifdef SFML_SYSTEM_ANDROID
if (m_resourceStream)
delete (priv::ResourceStream*)m_resourceStream;
#endif
}
////////////////////////////////////////////////////////////
std::size_t SoundFile::getSampleCount() const
{
return m_sampleCount;
}
////////////////////////////////////////////////////////////
unsigned int SoundFile::getChannelCount() const
{
return m_channelCount;
}
////////////////////////////////////////////////////////////
unsigned int SoundFile::getSampleRate() const
{
return m_sampleRate;
}
////////////////////////////////////////////////////////////
bool SoundFile::openRead(const std::string& filename)
{
#ifndef SFML_SYSTEM_ANDROID
// If the file is already opened, first close it
if (m_file)
sf_close(m_file);
// Open the sound file
SF_INFO fileInfo;
fileInfo.format = 0;
m_file = sf_open(filename.c_str(), SFM_READ, &fileInfo);
if (!m_file)
{
err() << "Failed to open sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
return false;
}
// Initialize the internal state from the loaded information
initialize(fileInfo);
return true;
#else
if (m_resourceStream)
delete (priv::ResourceStream*)m_resourceStream;
m_resourceStream = new priv::ResourceStream(filename);
return openRead(*(priv::ResourceStream*)m_resourceStream);
#endif
}
////////////////////////////////////////////////////////////
bool SoundFile::openRead(const void* data, std::size_t sizeInBytes)
{
// If the file is already opened, first close it
if (m_file)
sf_close(m_file);
// Prepare the memory I/O structure
SF_VIRTUAL_IO io;
io.get_filelen = &Memory::getLength;
io.read = &Memory::read;
io.seek = &Memory::seek;
io.tell = &Memory::tell;
// Initialize the memory data
m_memory.begin = static_cast<const char*>(data);
m_memory.current = m_memory.begin;
m_memory.size = sizeInBytes;
// Open the sound file
SF_INFO fileInfo;
fileInfo.format = 0;
m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_memory);
if (!m_file)
{
err() << "Failed to open sound file from memory (" << sf_strerror(m_file) << ")" << std::endl;
return false;
}
// Initialize the internal state from the loaded information
initialize(fileInfo);
return true;
}
////////////////////////////////////////////////////////////
bool SoundFile::openRead(InputStream& stream)
{
// If the file is already opened, first close it
if (m_file)
sf_close(m_file);
// Prepare the memory I/O structure
SF_VIRTUAL_IO io;
io.get_filelen = &Stream::getLength;
io.read = &Stream::read;
io.seek = &Stream::seek;
io.tell = &Stream::tell;
// Initialize the stream data
m_stream.source = &stream;
m_stream.size = stream.getSize();
// Make sure that the stream's reading position is at the beginning
stream.seek(0);
// Open the sound file
SF_INFO fileInfo;
fileInfo.format = 0;
m_file = sf_open_virtual(&io, SFM_READ, &fileInfo, &m_stream);
if (!m_file)
{
err() << "Failed to open sound file from stream (" << sf_strerror(m_file) << ")" << std::endl;
return false;
}
// Initialize the internal state from the loaded information
initialize(fileInfo);
return true;
}
////////////////////////////////////////////////////////////
bool SoundFile::openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate)
{
// If the file is already opened, first close it
if (m_file)
sf_close(m_file);
// Find the right format according to the file extension
int format = getFormatFromFilename(filename);
if (format == -1)
{
// Error: unrecognized extension
err() << "Failed to create sound file \"" << filename << "\" (unknown format)" << std::endl;
return false;
}
// Fill the sound infos with parameters
SF_INFO fileInfos;
fileInfos.channels = channelCount;
fileInfos.samplerate = sampleRate;
fileInfos.format = format | (format == SF_FORMAT_OGG ? SF_FORMAT_VORBIS : SF_FORMAT_PCM_16);
// Open the sound file for writing
m_file = sf_open(filename.c_str(), SFM_WRITE, &fileInfos);
if (!m_file)
{
err() << "Failed to create sound file \"" << filename << "\" (" << sf_strerror(m_file) << ")" << std::endl;
return false;
}
// Set the sound parameters
m_channelCount = channelCount;
m_sampleRate = sampleRate;
m_sampleCount = 0;
return true;
}
////////////////////////////////////////////////////////////
std::size_t SoundFile::read(Int16* data, std::size_t sampleCount)
{
if (m_file && data && sampleCount)
return static_cast<std::size_t>(sf_read_short(m_file, data, sampleCount));
else
return 0;
}
////////////////////////////////////////////////////////////
void SoundFile::write(const Int16* data, std::size_t sampleCount)
{
if (m_file && data && sampleCount)
{
// Write small chunks instead of everything at once,
// to avoid a stack overflow in libsndfile (happens only with OGG format)
while (sampleCount > 0)
{
std::size_t count = sampleCount > 10000 ? 10000 : sampleCount;
sf_write_short(m_file, data, count);
data += count;
sampleCount -= count;
}
}
}
////////////////////////////////////////////////////////////
void SoundFile::seek(Time timeOffset)
{
if (m_file)
{
sf_count_t frameOffset = static_cast<sf_count_t>(timeOffset.asSeconds() * m_sampleRate);
sf_seek(m_file, frameOffset, SEEK_SET);
}
}
////////////////////////////////////////////////////////////
void SoundFile::initialize(SF_INFO fileInfo)
{
// Save the sound properties
m_channelCount = fileInfo.channels;
m_sampleRate = fileInfo.samplerate;
m_sampleCount = static_cast<std::size_t>(fileInfo.frames) * fileInfo.channels;
// Enable scaling for Vorbis files (float samples)
// @todo enable when it's faster (it currently has to iterate over the *whole* music)
//if (fileInfo.format & SF_FORMAT_VORBIS)
// sf_command(m_file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE);
}
////////////////////////////////////////////////////////////
int SoundFile::getFormatFromFilename(const std::string& filename)
{
// Extract the extension
std::string ext = "wav";
std::string::size_type pos = filename.find_last_of(".");
if (pos != std::string::npos)
ext = toLower(filename.substr(pos + 1));
// Match every supported extension with its format constant
if (ext == "wav" ) return SF_FORMAT_WAV;
if (ext == "aif" ) return SF_FORMAT_AIFF;
if (ext == "aiff" ) return SF_FORMAT_AIFF;
if (ext == "au" ) return SF_FORMAT_AU;
if (ext == "raw" ) return SF_FORMAT_RAW;
if (ext == "paf" ) return SF_FORMAT_PAF;
if (ext == "svx" ) return SF_FORMAT_SVX;
if (ext == "nist" ) return SF_FORMAT_NIST;
if (ext == "voc" ) return SF_FORMAT_VOC;
if (ext == "sf" ) return SF_FORMAT_IRCAM;
if (ext == "w64" ) return SF_FORMAT_W64;
if (ext == "mat4" ) return SF_FORMAT_MAT4;
if (ext == "mat5" ) return SF_FORMAT_MAT5;
if (ext == "pvf" ) return SF_FORMAT_PVF;
if (ext == "xi" ) return SF_FORMAT_XI;
if (ext == "htk" ) return SF_FORMAT_HTK;
if (ext == "sds" ) return SF_FORMAT_SDS;
if (ext == "avr" ) return SF_FORMAT_AVR;
if (ext == "sd2" ) return SF_FORMAT_SD2;
if (ext == "flac" ) return SF_FORMAT_FLAC;
if (ext == "caf" ) return SF_FORMAT_CAF;
if (ext == "wve" ) return SF_FORMAT_WVE;
if (ext == "ogg" ) return SF_FORMAT_OGG;
if (ext == "mpc2k") return SF_FORMAT_MPC2K;
if (ext == "rf64" ) return SF_FORMAT_RF64;
return -1;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Memory::getLength(void* user)
{
Memory* memory = static_cast<Memory*>(user);
return memory->size;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Memory::read(void* ptr, sf_count_t count, void* user)
{
Memory* memory = static_cast<Memory*>(user);
sf_count_t position = tell(user);
if (position + count >= memory->size)
count = memory->size - position;
std::memcpy(ptr, memory->current, static_cast<std::size_t>(count));
memory->current += count;
return count;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Memory::seek(sf_count_t offset, int whence, void* user)
{
Memory* memory = static_cast<Memory*>(user);
sf_count_t position = 0;
switch (whence)
{
case SEEK_SET: position = offset; break;
case SEEK_CUR: position = memory->current - memory->begin + offset; break;
case SEEK_END: position = memory->size - offset; break;
default: position = 0; break;
}
if (position >= memory->size)
position = memory->size - 1;
else if (position < 0)
position = 0;
memory->current = memory->begin + position;
return position;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Memory::tell(void* user)
{
Memory* memory = static_cast<Memory*>(user);
return memory->current - memory->begin;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::getLength(void* userData)
{
Stream* stream = static_cast<Stream*>(userData);
return stream->size;
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::read(void* ptr, sf_count_t count, void* userData)
{
Stream* stream = static_cast<Stream*>(userData);
Int64 position = stream->source->tell();
if (position != -1)
{
if (count > stream->size - position)
count = stream->size - position;
return stream->source->read(reinterpret_cast<char*>(ptr), count);
}
else
{
return -1;
}
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::seek(sf_count_t offset, int whence, void* userData)
{
Stream* stream = static_cast<Stream*>(userData);
switch (whence)
{
case SEEK_SET: return stream->source->seek(offset);
case SEEK_CUR: return stream->source->seek(stream->source->tell() + offset);
case SEEK_END: return stream->source->seek(stream->size - offset);
default: return stream->source->seek(0);
}
}
////////////////////////////////////////////////////////////
sf_count_t SoundFile::Stream::tell(void* userData)
{
Stream* stream = static_cast<Stream*>(userData);
return stream->source->tell();
}
} // namespace priv
} // namespace sf

View file

@ -1,231 +1,231 @@
////////////////////////////////////////////////////////////
//
// 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_SOUNDFILE_HPP
#define SFML_SOUNDFILE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Time.hpp>
#include <sndfile.h>
#include <string>
namespace sf
{
class InputStream;
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Provide read and write access to sound files
///
////////////////////////////////////////////////////////////
class SoundFile : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
SoundFile();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SoundFile();
////////////////////////////////////////////////////////////
/// \brief Get the total number of audio samples in the file
///
/// \return Number of samples
///
////////////////////////////////////////////////////////////
std::size_t getSampleCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the number of channels used by the sound
///
/// \return Number of channels (1 = mono, 2 = stereo)
///
////////////////////////////////////////////////////////////
unsigned int getChannelCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the sample rate of the sound
///
/// \return Sample rate, in samples per second
///
////////////////////////////////////////////////////////////
unsigned int getSampleRate() const;
////////////////////////////////////////////////////////////
/// \brief Open a sound file for reading
///
/// \param filename Path of the sound file to load
///
/// \return True if the file was successfully opened
///
////////////////////////////////////////////////////////////
bool openRead(const std::string& filename);
////////////////////////////////////////////////////////////
/// \brief Open a sound file in memory for reading
///
/// \param data Pointer to the file data in memory
/// \param sizeInBytes Size of the data to load, in bytes
///
/// \return True if the file was successfully opened
///
////////////////////////////////////////////////////////////
bool openRead(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Open a sound file from a custom stream for reading
///
/// \param stream Source stream to read from
///
/// \return True if the file was successfully opened
///
////////////////////////////////////////////////////////////
bool openRead(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief a the sound file for writing
///
/// \param filename Path of the sound file to write
/// \param channelCount Number of channels in the sound
/// \param sampleRate Sample rate of the sound
///
/// \return True if the file was successfully opened
///
////////////////////////////////////////////////////////////
bool openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate);
////////////////////////////////////////////////////////////
/// \brief Read audio samples from the loaded sound
///
/// \param data Pointer to the sample array to fill
/// \param sampleCount Number of samples to read
///
/// \return Number of samples actually read (may be less than \a sampleCount)
///
////////////////////////////////////////////////////////////
std::size_t read(Int16* data, std::size_t sampleCount);
////////////////////////////////////////////////////////////
/// \brief Write audio samples to the file
///
/// \param data Pointer to the sample array to write
/// \param sampleCount Number of samples to write
///
////////////////////////////////////////////////////////////
void write(const Int16* data, std::size_t sampleCount);
////////////////////////////////////////////////////////////
/// \brief Change the current read position in the file
///
/// \param timeOffset New playing position, from the beginning of the file
///
////////////////////////////////////////////////////////////
void seek(Time timeOffset);
private :
////////////////////////////////////////////////////////////
/// \brief Initialize the internal state of the sound file
///
/// This function is called by all the openRead functions.
///
/// \param fileInfo Information about the loaded sound file
///
////////////////////////////////////////////////////////////
void initialize(SF_INFO fileInfo);
////////////////////////////////////////////////////////////
/// \brief Get the internal format of an audio file according to
/// its filename extension
///
/// \param filename Filename to check
///
/// \return Internal format matching the filename (-1 if no match)
///
////////////////////////////////////////////////////////////
static int getFormatFromFilename(const std::string& filename);
////////////////////////////////////////////////////////////
/// \brief Data and callbacks for opening from memory
///
////////////////////////////////////////////////////////////
struct Memory
{
const char* begin;
const char* current;
sf_count_t size;
static sf_count_t getLength(void* user);
static sf_count_t read(void* ptr, sf_count_t count, void* user);
static sf_count_t seek(sf_count_t offset, int whence, void* user);
static sf_count_t tell(void* user);
};
////////////////////////////////////////////////////////////
/// \brief Data and callbacks for opening from stream
///
////////////////////////////////////////////////////////////
struct Stream
{
InputStream* source;
Int64 size;
static sf_count_t getLength(void* user);
static sf_count_t read(void* ptr, sf_count_t count, void* user);
static sf_count_t seek(sf_count_t offset, int whence, void* user);
static sf_count_t tell(void* user);
};
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
SNDFILE* m_file; ///< File descriptor
Memory m_memory; ///< Memory reading info
Stream m_stream; ///< Stream reading info
std::size_t m_sampleCount; ///< Total number of samples in the file
unsigned int m_channelCount; ///< Number of channels used by the sound
unsigned int m_sampleRate; ///< Number of samples per second
#ifdef SFML_SYSTEM_ANDROID
void* m_resourceStream; ///< Asset file streamer (if loaded from file)
#endif
};
} // namespace priv
} // namespace sf
#endif // SFML_SOUNDFILE_HPP
////////////////////////////////////////////////////////////
//
// 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_SOUNDFILE_HPP
#define SFML_SOUNDFILE_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Time.hpp>
#include <sndfile.h>
#include <string>
namespace sf
{
class InputStream;
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Provide read and write access to sound files
///
////////////////////////////////////////////////////////////
class SoundFile : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
SoundFile();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~SoundFile();
////////////////////////////////////////////////////////////
/// \brief Get the total number of audio samples in the file
///
/// \return Number of samples
///
////////////////////////////////////////////////////////////
std::size_t getSampleCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the number of channels used by the sound
///
/// \return Number of channels (1 = mono, 2 = stereo)
///
////////////////////////////////////////////////////////////
unsigned int getChannelCount() const;
////////////////////////////////////////////////////////////
/// \brief Get the sample rate of the sound
///
/// \return Sample rate, in samples per second
///
////////////////////////////////////////////////////////////
unsigned int getSampleRate() const;
////////////////////////////////////////////////////////////
/// \brief Open a sound file for reading
///
/// \param filename Path of the sound file to load
///
/// \return True if the file was successfully opened
///
////////////////////////////////////////////////////////////
bool openRead(const std::string& filename);
////////////////////////////////////////////////////////////
/// \brief Open a sound file in memory for reading
///
/// \param data Pointer to the file data in memory
/// \param sizeInBytes Size of the data to load, in bytes
///
/// \return True if the file was successfully opened
///
////////////////////////////////////////////////////////////
bool openRead(const void* data, std::size_t sizeInBytes);
////////////////////////////////////////////////////////////
/// \brief Open a sound file from a custom stream for reading
///
/// \param stream Source stream to read from
///
/// \return True if the file was successfully opened
///
////////////////////////////////////////////////////////////
bool openRead(InputStream& stream);
////////////////////////////////////////////////////////////
/// \brief a the sound file for writing
///
/// \param filename Path of the sound file to write
/// \param channelCount Number of channels in the sound
/// \param sampleRate Sample rate of the sound
///
/// \return True if the file was successfully opened
///
////////////////////////////////////////////////////////////
bool openWrite(const std::string& filename, unsigned int channelCount, unsigned int sampleRate);
////////////////////////////////////////////////////////////
/// \brief Read audio samples from the loaded sound
///
/// \param data Pointer to the sample array to fill
/// \param sampleCount Number of samples to read
///
/// \return Number of samples actually read (may be less than \a sampleCount)
///
////////////////////////////////////////////////////////////
std::size_t read(Int16* data, std::size_t sampleCount);
////////////////////////////////////////////////////////////
/// \brief Write audio samples to the file
///
/// \param data Pointer to the sample array to write
/// \param sampleCount Number of samples to write
///
////////////////////////////////////////////////////////////
void write(const Int16* data, std::size_t sampleCount);
////////////////////////////////////////////////////////////
/// \brief Change the current read position in the file
///
/// \param timeOffset New playing position, from the beginning of the file
///
////////////////////////////////////////////////////////////
void seek(Time timeOffset);
private:
////////////////////////////////////////////////////////////
/// \brief Initialize the internal state of the sound file
///
/// This function is called by all the openRead functions.
///
/// \param fileInfo Information about the loaded sound file
///
////////////////////////////////////////////////////////////
void initialize(SF_INFO fileInfo);
////////////////////////////////////////////////////////////
/// \brief Get the internal format of an audio file according to
/// its filename extension
///
/// \param filename Filename to check
///
/// \return Internal format matching the filename (-1 if no match)
///
////////////////////////////////////////////////////////////
static int getFormatFromFilename(const std::string& filename);
////////////////////////////////////////////////////////////
/// \brief Data and callbacks for opening from memory
///
////////////////////////////////////////////////////////////
struct Memory
{
const char* begin;
const char* current;
sf_count_t size;
static sf_count_t getLength(void* user);
static sf_count_t read(void* ptr, sf_count_t count, void* user);
static sf_count_t seek(sf_count_t offset, int whence, void* user);
static sf_count_t tell(void* user);
};
////////////////////////////////////////////////////////////
/// \brief Data and callbacks for opening from stream
///
////////////////////////////////////////////////////////////
struct Stream
{
InputStream* source;
Int64 size;
static sf_count_t getLength(void* user);
static sf_count_t read(void* ptr, sf_count_t count, void* user);
static sf_count_t seek(sf_count_t offset, int whence, void* user);
static sf_count_t tell(void* user);
};
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
SNDFILE* m_file; ///< File descriptor
Memory m_memory; ///< Memory reading info
Stream m_stream; ///< Stream reading info
std::size_t m_sampleCount; ///< Total number of samples in the file
unsigned int m_channelCount; ///< Number of channels used by the sound
unsigned int m_sampleRate; ///< Number of samples per second
#ifdef SFML_SYSTEM_ANDROID
void* m_resourceStream; ///< Asset file streamer (if loaded from file)
#endif
};
} // namespace priv
} // namespace sf
#endif // SFML_SOUNDFILE_HPP

View file

@ -1,290 +1,290 @@
////////////////////////////////////////////////////////////
//
// 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/SoundRecorder.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Err.hpp>
#include <cstring>
#ifdef _MSC_VER
#pragma warning(disable : 4355) // 'this' used in base member initializer list
#endif
namespace
{
ALCdevice* captureDevice = NULL;
}
namespace sf
{
////////////////////////////////////////////////////////////
SoundRecorder::SoundRecorder() :
m_thread (&SoundRecorder::record, this),
m_sampleRate (0),
m_processingInterval(milliseconds(100)),
m_isCapturing (false)
{
priv::ensureALInit();
// Set the device name to the default device
m_deviceName = getDefaultDevice();
}
////////////////////////////////////////////////////////////
SoundRecorder::~SoundRecorder()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
bool SoundRecorder::start(unsigned int sampleRate)
{
// Check if the device can do audio capture
if (!isAvailable())
{
err() << "Failed to start capture : your system cannot capture audio data (call SoundRecorder::isAvailable to check it)" << std::endl;
return false;
}
// Check that another capture is not already running
if (captureDevice)
{
err() << "Trying to start audio capture, but another capture is already running" << std::endl;
return false;
}
// Open the capture device for capturing 16 bits mono samples
captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, AL_FORMAT_MONO16, sampleRate);
if (!captureDevice)
{
err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
return false;
}
// Clear the array of samples
m_samples.clear();
// Store the sample rate
m_sampleRate = sampleRate;
// Notify derived class
if (onStart())
{
// Start the capture
alcCaptureStart(captureDevice);
// Start the capture in a new thread, to avoid blocking the main thread
m_isCapturing = true;
m_thread.launch();
return true;
}
return false;
}
////////////////////////////////////////////////////////////
void SoundRecorder::stop()
{
// Stop the capturing thread
m_isCapturing = false;
m_thread.wait();
// Notify derived class
onStop();
}
////////////////////////////////////////////////////////////
unsigned int SoundRecorder::getSampleRate() const
{
return m_sampleRate;
}
////////////////////////////////////////////////////////////
std::vector<std::string> SoundRecorder::getAvailableDevices()
{
std::vector<std::string> deviceNameList;
const ALchar *deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
if (deviceList)
{
while (*deviceList)
{
deviceNameList.push_back(deviceList);
deviceList += std::strlen(deviceList) + 1;
}
}
return deviceNameList;
}
////////////////////////////////////////////////////////////
std::string SoundRecorder::getDefaultDevice()
{
return alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
}
////////////////////////////////////////////////////////////
bool SoundRecorder::setDevice(const std::string& name)
{
// Store the device name
if (name.empty())
m_deviceName = getDefaultDevice();
else
m_deviceName = name;
if (m_isCapturing)
{
// Stop the capturing thread
m_isCapturing = false;
m_thread.wait();
// Open the requested capture device for capturing 16 bits mono samples
captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, AL_FORMAT_MONO16, m_sampleRate);
if (!captureDevice)
{
// Notify derived class
onStop();
err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
return false;
}
// Start the capture
alcCaptureStart(captureDevice);
// Start the capture in a new thread, to avoid blocking the main thread
m_isCapturing = true;
m_thread.launch();
}
return true;
}
////////////////////////////////////////////////////////////
const std::string& SoundRecorder::getDevice() const
{
return m_deviceName;
}
////////////////////////////////////////////////////////////
bool SoundRecorder::isAvailable()
{
return (priv::AudioDevice::isExtensionSupported("ALC_EXT_CAPTURE") != AL_FALSE) ||
(priv::AudioDevice::isExtensionSupported("ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6
}
////////////////////////////////////////////////////////////
void SoundRecorder::setProcessingInterval(sf::Time interval)
{
m_processingInterval = interval;
}
////////////////////////////////////////////////////////////
bool SoundRecorder::onStart()
{
// Nothing to do
return true;
}
////////////////////////////////////////////////////////////
void SoundRecorder::onStop()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
void SoundRecorder::record()
{
while (m_isCapturing)
{
// Process available samples
processCapturedSamples();
// Don't bother the CPU while waiting for more captured data
sleep(m_processingInterval);
}
// Capture is finished : clean up everything
cleanup();
}
////////////////////////////////////////////////////////////
void SoundRecorder::processCapturedSamples()
{
// Get the number of samples available
ALCint samplesAvailable;
alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable);
if (samplesAvailable > 0)
{
// Get the recorded samples
m_samples.resize(samplesAvailable);
alcCaptureSamples(captureDevice, &m_samples[0], samplesAvailable);
// Forward them to the derived class
if (!onProcessSamples(&m_samples[0], m_samples.size()))
{
// The user wants to stop the capture
m_isCapturing = false;
}
}
}
////////////////////////////////////////////////////////////
void SoundRecorder::cleanup()
{
// Stop the capture
alcCaptureStop(captureDevice);
// Get the samples left in the buffer
processCapturedSamples();
// Close the device
alcCaptureCloseDevice(captureDevice);
captureDevice = NULL;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/SoundRecorder.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Err.hpp>
#include <cstring>
#ifdef _MSC_VER
#pragma warning(disable: 4355) // 'this' used in base member initializer list
#endif
namespace
{
ALCdevice* captureDevice = NULL;
}
namespace sf
{
////////////////////////////////////////////////////////////
SoundRecorder::SoundRecorder() :
m_thread (&SoundRecorder::record, this),
m_sampleRate (0),
m_processingInterval(milliseconds(100)),
m_isCapturing (false)
{
priv::ensureALInit();
// Set the device name to the default device
m_deviceName = getDefaultDevice();
}
////////////////////////////////////////////////////////////
SoundRecorder::~SoundRecorder()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
bool SoundRecorder::start(unsigned int sampleRate)
{
// Check if the device can do audio capture
if (!isAvailable())
{
err() << "Failed to start capture: your system cannot capture audio data (call SoundRecorder::isAvailable to check it)" << std::endl;
return false;
}
// Check that another capture is not already running
if (captureDevice)
{
err() << "Trying to start audio capture, but another capture is already running" << std::endl;
return false;
}
// Open the capture device for capturing 16 bits mono samples
captureDevice = alcCaptureOpenDevice(m_deviceName.c_str(), sampleRate, AL_FORMAT_MONO16, sampleRate);
if (!captureDevice)
{
err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
return false;
}
// Clear the array of samples
m_samples.clear();
// Store the sample rate
m_sampleRate = sampleRate;
// Notify derived class
if (onStart())
{
// Start the capture
alcCaptureStart(captureDevice);
// Start the capture in a new thread, to avoid blocking the main thread
m_isCapturing = true;
m_thread.launch();
return true;
}
return false;
}
////////////////////////////////////////////////////////////
void SoundRecorder::stop()
{
// Stop the capturing thread
m_isCapturing = false;
m_thread.wait();
// Notify derived class
onStop();
}
////////////////////////////////////////////////////////////
unsigned int SoundRecorder::getSampleRate() const
{
return m_sampleRate;
}
////////////////////////////////////////////////////////////
std::vector<std::string> SoundRecorder::getAvailableDevices()
{
std::vector<std::string> deviceNameList;
const ALchar *deviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER);
if (deviceList)
{
while (*deviceList)
{
deviceNameList.push_back(deviceList);
deviceList += std::strlen(deviceList) + 1;
}
}
return deviceNameList;
}
////////////////////////////////////////////////////////////
std::string SoundRecorder::getDefaultDevice()
{
return alcGetString(NULL, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER);
}
////////////////////////////////////////////////////////////
bool SoundRecorder::setDevice(const std::string& name)
{
// Store the device name
if (name.empty())
m_deviceName = getDefaultDevice();
else
m_deviceName = name;
if (m_isCapturing)
{
// Stop the capturing thread
m_isCapturing = false;
m_thread.wait();
// Open the requested capture device for capturing 16 bits mono samples
captureDevice = alcCaptureOpenDevice(name.c_str(), m_sampleRate, AL_FORMAT_MONO16, m_sampleRate);
if (!captureDevice)
{
// Notify derived class
onStop();
err() << "Failed to open the audio capture device with the name: " << m_deviceName << std::endl;
return false;
}
// Start the capture
alcCaptureStart(captureDevice);
// Start the capture in a new thread, to avoid blocking the main thread
m_isCapturing = true;
m_thread.launch();
}
return true;
}
////////////////////////////////////////////////////////////
const std::string& SoundRecorder::getDevice() const
{
return m_deviceName;
}
////////////////////////////////////////////////////////////
bool SoundRecorder::isAvailable()
{
return (priv::AudioDevice::isExtensionSupported("ALC_EXT_CAPTURE") != AL_FALSE) ||
(priv::AudioDevice::isExtensionSupported("ALC_EXT_capture") != AL_FALSE); // "bug" in Mac OS X 10.5 and 10.6
}
////////////////////////////////////////////////////////////
void SoundRecorder::setProcessingInterval(sf::Time interval)
{
m_processingInterval = interval;
}
////////////////////////////////////////////////////////////
bool SoundRecorder::onStart()
{
// Nothing to do
return true;
}
////////////////////////////////////////////////////////////
void SoundRecorder::onStop()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
void SoundRecorder::record()
{
while (m_isCapturing)
{
// Process available samples
processCapturedSamples();
// Don't bother the CPU while waiting for more captured data
sleep(m_processingInterval);
}
// Capture is finished: clean up everything
cleanup();
}
////////////////////////////////////////////////////////////
void SoundRecorder::processCapturedSamples()
{
// Get the number of samples available
ALCint samplesAvailable;
alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, 1, &samplesAvailable);
if (samplesAvailable > 0)
{
// Get the recorded samples
m_samples.resize(samplesAvailable);
alcCaptureSamples(captureDevice, &m_samples[0], samplesAvailable);
// Forward them to the derived class
if (!onProcessSamples(&m_samples[0], m_samples.size()))
{
// The user wants to stop the capture
m_isCapturing = false;
}
}
}
////////////////////////////////////////////////////////////
void SoundRecorder::cleanup()
{
// Stop the capture
alcCaptureStop(captureDevice);
// Get the samples left in the buffer
processCapturedSamples();
// Close the device
alcCaptureCloseDevice(captureDevice);
captureDevice = NULL;
}
} // namespace sf

View file

@ -1,194 +1,194 @@
////////////////////////////////////////////////////////////
//
// 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/SoundSource.hpp>
#include <SFML/Audio/ALCheck.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
SoundSource::SoundSource()
{
priv::ensureALInit();
alCheck(alGenSources(1, &m_source));
alCheck(alSourcei(m_source, AL_BUFFER, 0));
}
////////////////////////////////////////////////////////////
SoundSource::SoundSource(const SoundSource& copy)
{
priv::ensureALInit();
alCheck(alGenSources(1, &m_source));
alCheck(alSourcei(m_source, AL_BUFFER, 0));
setPitch(copy.getPitch());
setVolume(copy.getVolume());
setPosition(copy.getPosition());
setRelativeToListener(copy.isRelativeToListener());
setMinDistance(copy.getMinDistance());
setAttenuation(copy.getAttenuation());
}
////////////////////////////////////////////////////////////
SoundSource::~SoundSource()
{
alCheck(alSourcei(m_source, AL_BUFFER, 0));
alCheck(alDeleteSources(1, &m_source));
}
////////////////////////////////////////////////////////////
void SoundSource::setPitch(float pitch)
{
alCheck(alSourcef(m_source, AL_PITCH, pitch));
}
////////////////////////////////////////////////////////////
void SoundSource::setVolume(float volume)
{
alCheck(alSourcef(m_source, AL_GAIN, volume * 0.01f));
}
////////////////////////////////////////////////////////////
void SoundSource::setPosition(float x, float y, float z)
{
alCheck(alSource3f(m_source, AL_POSITION, x, y, z));
}
////////////////////////////////////////////////////////////
void SoundSource::setPosition(const Vector3f& position)
{
setPosition(position.x, position.y, position.z);
}
////////////////////////////////////////////////////////////
void SoundSource::setRelativeToListener(bool relative)
{
alCheck(alSourcei(m_source, AL_SOURCE_RELATIVE, relative));
}
////////////////////////////////////////////////////////////
void SoundSource::setMinDistance(float distance)
{
alCheck(alSourcef(m_source, AL_REFERENCE_DISTANCE, distance));
}
////////////////////////////////////////////////////////////
void SoundSource::setAttenuation(float attenuation)
{
alCheck(alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation));
}
////////////////////////////////////////////////////////////
float SoundSource::getPitch() const
{
ALfloat pitch;
alCheck(alGetSourcef(m_source, AL_PITCH, &pitch));
return pitch;
}
////////////////////////////////////////////////////////////
float SoundSource::getVolume() const
{
ALfloat gain;
alCheck(alGetSourcef(m_source, AL_GAIN, &gain));
return gain * 100.f;
}
////////////////////////////////////////////////////////////
Vector3f SoundSource::getPosition() const
{
Vector3f position;
alCheck(alGetSource3f(m_source, AL_POSITION, &position.x, &position.y, &position.z));
return position;
}
////////////////////////////////////////////////////////////
bool SoundSource::isRelativeToListener() const
{
ALint relative;
alCheck(alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative));
return relative != 0;
}
////////////////////////////////////////////////////////////
float SoundSource::getMinDistance() const
{
ALfloat distance;
alCheck(alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance));
return distance;
}
////////////////////////////////////////////////////////////
float SoundSource::getAttenuation() const
{
ALfloat attenuation;
alCheck(alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation));
return attenuation;
}
////////////////////////////////////////////////////////////
SoundSource::Status SoundSource::getStatus() const
{
ALint status;
alCheck(alGetSourcei(m_source, AL_SOURCE_STATE, &status));
switch (status)
{
case AL_INITIAL :
case AL_STOPPED : return Stopped;
case AL_PAUSED : return Paused;
case AL_PLAYING : return Playing;
}
return Stopped;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/SoundSource.hpp>
#include <SFML/Audio/ALCheck.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
SoundSource::SoundSource()
{
priv::ensureALInit();
alCheck(alGenSources(1, &m_source));
alCheck(alSourcei(m_source, AL_BUFFER, 0));
}
////////////////////////////////////////////////////////////
SoundSource::SoundSource(const SoundSource& copy)
{
priv::ensureALInit();
alCheck(alGenSources(1, &m_source));
alCheck(alSourcei(m_source, AL_BUFFER, 0));
setPitch(copy.getPitch());
setVolume(copy.getVolume());
setPosition(copy.getPosition());
setRelativeToListener(copy.isRelativeToListener());
setMinDistance(copy.getMinDistance());
setAttenuation(copy.getAttenuation());
}
////////////////////////////////////////////////////////////
SoundSource::~SoundSource()
{
alCheck(alSourcei(m_source, AL_BUFFER, 0));
alCheck(alDeleteSources(1, &m_source));
}
////////////////////////////////////////////////////////////
void SoundSource::setPitch(float pitch)
{
alCheck(alSourcef(m_source, AL_PITCH, pitch));
}
////////////////////////////////////////////////////////////
void SoundSource::setVolume(float volume)
{
alCheck(alSourcef(m_source, AL_GAIN, volume * 0.01f));
}
////////////////////////////////////////////////////////////
void SoundSource::setPosition(float x, float y, float z)
{
alCheck(alSource3f(m_source, AL_POSITION, x, y, z));
}
////////////////////////////////////////////////////////////
void SoundSource::setPosition(const Vector3f& position)
{
setPosition(position.x, position.y, position.z);
}
////////////////////////////////////////////////////////////
void SoundSource::setRelativeToListener(bool relative)
{
alCheck(alSourcei(m_source, AL_SOURCE_RELATIVE, relative));
}
////////////////////////////////////////////////////////////
void SoundSource::setMinDistance(float distance)
{
alCheck(alSourcef(m_source, AL_REFERENCE_DISTANCE, distance));
}
////////////////////////////////////////////////////////////
void SoundSource::setAttenuation(float attenuation)
{
alCheck(alSourcef(m_source, AL_ROLLOFF_FACTOR, attenuation));
}
////////////////////////////////////////////////////////////
float SoundSource::getPitch() const
{
ALfloat pitch;
alCheck(alGetSourcef(m_source, AL_PITCH, &pitch));
return pitch;
}
////////////////////////////////////////////////////////////
float SoundSource::getVolume() const
{
ALfloat gain;
alCheck(alGetSourcef(m_source, AL_GAIN, &gain));
return gain * 100.f;
}
////////////////////////////////////////////////////////////
Vector3f SoundSource::getPosition() const
{
Vector3f position;
alCheck(alGetSource3f(m_source, AL_POSITION, &position.x, &position.y, &position.z));
return position;
}
////////////////////////////////////////////////////////////
bool SoundSource::isRelativeToListener() const
{
ALint relative;
alCheck(alGetSourcei(m_source, AL_SOURCE_RELATIVE, &relative));
return relative != 0;
}
////////////////////////////////////////////////////////////
float SoundSource::getMinDistance() const
{
ALfloat distance;
alCheck(alGetSourcef(m_source, AL_REFERENCE_DISTANCE, &distance));
return distance;
}
////////////////////////////////////////////////////////////
float SoundSource::getAttenuation() const
{
ALfloat attenuation;
alCheck(alGetSourcef(m_source, AL_ROLLOFF_FACTOR, &attenuation));
return attenuation;
}
////////////////////////////////////////////////////////////
SoundSource::Status SoundSource::getStatus() const
{
ALint status;
alCheck(alGetSourcei(m_source, AL_SOURCE_STATE, &status));
switch (status)
{
case AL_INITIAL:
case AL_STOPPED: return Stopped;
case AL_PAUSED: return Paused;
case AL_PLAYING: return Playing;
}
return Stopped;
}
} // namespace sf

View file

@ -1,469 +1,469 @@
////////////////////////////////////////////////////////////
//
// 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/SoundStream.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Lock.hpp>
#ifdef _MSC_VER
#pragma warning(disable : 4355) // 'this' used in base member initializer list
#endif
namespace sf
{
////////////////////////////////////////////////////////////
SoundStream::SoundStream() :
m_thread (&SoundStream::streamData, this),
m_threadMutex (),
m_threadStartState(Stopped),
m_isStreaming (false),
m_channelCount (0),
m_sampleRate (0),
m_format (0),
m_loop (false),
m_samplesProcessed(0)
{
}
////////////////////////////////////////////////////////////
SoundStream::~SoundStream()
{
// Stop the sound if it was playing
// Request the thread to terminate
{
Lock lock(m_threadMutex);
m_isStreaming = false;
}
// Wait for the thread to terminate
m_thread.wait();
}
////////////////////////////////////////////////////////////
void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate)
{
m_channelCount = channelCount;
m_sampleRate = sampleRate;
// Deduce the format from the number of channels
m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
// Check if the format is valid
if (m_format == 0)
{
m_channelCount = 0;
m_sampleRate = 0;
err() << "Unsupported number of channels (" << m_channelCount << ")" << std::endl;
}
}
////////////////////////////////////////////////////////////
void SoundStream::play()
{
// Check if the sound parameters have been set
if (m_format == 0)
{
err() << "Failed to play audio stream: sound parameters have not been initialized (call initialize() first)" << std::endl;
return;
}
bool isStreaming = false;
Status threadStartState = Stopped;
{
Lock lock(m_threadMutex);
isStreaming = m_isStreaming;
threadStartState = m_threadStartState;
}
if (isStreaming && (threadStartState == Paused))
{
// If the sound is paused, resume it
Lock lock(m_threadMutex);
m_threadStartState = Playing;
alCheck(alSourcePlay(m_source));
return;
}
else if (isStreaming && (threadStartState == Playing))
{
// If the sound is playing, stop it and continue as if it was stopped
stop();
}
// Move to the beginning
onSeek(Time::Zero);
// Start updating the stream in a separate thread to avoid blocking the application
m_samplesProcessed = 0;
m_isStreaming = true;
m_threadStartState = Playing;
m_thread.launch();
}
////////////////////////////////////////////////////////////
void SoundStream::pause()
{
// Handle pause() being called before the thread has started
{
Lock lock(m_threadMutex);
if (!m_isStreaming)
return;
m_threadStartState = Paused;
}
alCheck(alSourcePause(m_source));
}
////////////////////////////////////////////////////////////
void SoundStream::stop()
{
// Request the thread to terminate
{
Lock lock(m_threadMutex);
m_isStreaming = false;
}
// Wait for the thread to terminate
m_thread.wait();
// Move to the beginning
onSeek(Time::Zero);
// Reset the playing position
m_samplesProcessed = 0;
}
////////////////////////////////////////////////////////////
unsigned int SoundStream::getChannelCount() const
{
return m_channelCount;
}
////////////////////////////////////////////////////////////
unsigned int SoundStream::getSampleRate() const
{
return m_sampleRate;
}
////////////////////////////////////////////////////////////
SoundStream::Status SoundStream::getStatus() const
{
Status status = SoundSource::getStatus();
// To compensate for the lag between play() and alSourceplay()
if (status == Stopped)
{
Lock lock(m_threadMutex);
if (m_isStreaming)
status = m_threadStartState;
}
return status;
}
////////////////////////////////////////////////////////////
void SoundStream::setPlayingOffset(Time timeOffset)
{
// Get old playing status
Status oldStatus = getStatus();
// Stop the stream
stop();
// Let the derived class update the current position
onSeek(timeOffset);
// Restart streaming
m_samplesProcessed = static_cast<Uint64>(timeOffset.asSeconds() * m_sampleRate * m_channelCount);
if (oldStatus == Stopped)
return;
m_isStreaming = true;
m_threadStartState = oldStatus;
m_thread.launch();
}
////////////////////////////////////////////////////////////
Time SoundStream::getPlayingOffset() const
{
if (m_sampleRate && m_channelCount)
{
ALfloat secs = 0.f;
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
return seconds(secs + static_cast<float>(m_samplesProcessed) / m_sampleRate / m_channelCount);
}
else
{
return Time::Zero;
}
}
////////////////////////////////////////////////////////////
void SoundStream::setLoop(bool loop)
{
m_loop = loop;
}
////////////////////////////////////////////////////////////
bool SoundStream::getLoop() const
{
return m_loop;
}
////////////////////////////////////////////////////////////
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
alCheck(alGenBuffers(BufferCount, m_buffers));
for (int i = 0; i < BufferCount; ++i)
m_endBuffers[i] = false;
// Fill the queue
requestStop = fillQueue();
// Play the sound
alCheck(alSourcePlay(m_source));
// 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!
if (SoundSource::getStatus() == Stopped)
{
if (!requestStop)
{
// Just continue
alCheck(alSourcePlay(m_source));
}
else
{
// End streaming
Lock lock(m_threadMutex);
m_isStreaming = false;
}
}
// Get the number of buffers that have been processed (ie. ready for reuse)
ALint nbProcessed = 0;
alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed));
while (nbProcessed--)
{
// Pop the first unused buffer from the queue
ALuint buffer;
alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
// Find its number
unsigned int bufferNum = 0;
for (int i = 0; i < BufferCount; ++i)
if (m_buffers[i] == buffer)
{
bufferNum = i;
break;
}
// Retrieve its size and add it to the samples count
if (m_endBuffers[bufferNum])
{
// This was the last buffer: reset the sample count
m_samplesProcessed = 0;
m_endBuffers[bufferNum] = false;
}
else
{
ALint size, bits;
alCheck(alGetBufferi(buffer, AL_SIZE, &size));
alCheck(alGetBufferi(buffer, AL_BITS, &bits));
// Bits can be 0 if the format or parameters are corrupt, avoid division by zero
if (bits == 0)
{
err() << "Bits in sound stream are 0: make sure that the audio format is not corrupt "
<< "and initialize() has been called correctly" << std::endl;
// Abort streaming (exit main loop)
Lock lock(m_threadMutex);
m_isStreaming = false;
requestStop = true;
break;
}
else
{
m_samplesProcessed += size / (bits / 8);
}
}
// Fill it and push it back into the playing queue
if (!requestStop)
{
if (fillAndPushBuffer(bufferNum))
requestStop = true;
}
}
// Leave some time for the other threads if the stream is still playing
if (SoundSource::getStatus() != Stopped)
sleep(milliseconds(10));
}
// Stop the playback
alCheck(alSourceStop(m_source));
// Unqueue any buffer left in the queue
clearQueue();
// Delete the buffers
alCheck(alSourcei(m_source, AL_BUFFER, 0));
alCheck(alDeleteBuffers(BufferCount, m_buffers));
}
////////////////////////////////////////////////////////////
bool SoundStream::fillAndPushBuffer(unsigned int bufferNum)
{
bool requestStop = false;
// Acquire audio data
Chunk data = {NULL, 0};
if (!onGetData(data))
{
// Mark the buffer as the last one (so that we know when to reset the playing position)
m_endBuffers[bufferNum] = true;
// Check if the stream must loop or stop
if (m_loop)
{
// Return to the beginning of the stream source
onSeek(Time::Zero);
// If we previously had no data, try to fill the buffer once again
if (!data.samples || (data.sampleCount == 0))
{
return fillAndPushBuffer(bufferNum);
}
}
else
{
// Not looping: request stop
requestStop = true;
}
}
// Fill the buffer if some data was returned
if (data.samples && data.sampleCount)
{
unsigned int buffer = m_buffers[bufferNum];
// Fill the buffer
ALsizei size = static_cast<ALsizei>(data.sampleCount) * sizeof(Int16);
alCheck(alBufferData(buffer, m_format, data.samples, size, m_sampleRate));
// Push it into the sound queue
alCheck(alSourceQueueBuffers(m_source, 1, &buffer));
}
return requestStop;
}
////////////////////////////////////////////////////////////
bool SoundStream::fillQueue()
{
// Fill and enqueue all the available buffers
bool requestStop = false;
for (int i = 0; (i < BufferCount) && !requestStop; ++i)
{
if (fillAndPushBuffer(i))
requestStop = true;
}
return requestStop;
}
////////////////////////////////////////////////////////////
void SoundStream::clearQueue()
{
// Get the number of buffers still in the queue
ALint nbQueued;
alCheck(alGetSourcei(m_source, AL_BUFFERS_QUEUED, &nbQueued));
// Unqueue them all
ALuint buffer;
for (ALint i = 0; i < nbQueued; ++i)
alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/SoundStream.hpp>
#include <SFML/Audio/AudioDevice.hpp>
#include <SFML/Audio/ALCheck.hpp>
#include <SFML/System/Sleep.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/System/Lock.hpp>
#ifdef _MSC_VER
#pragma warning(disable: 4355) // 'this' used in base member initializer list
#endif
namespace sf
{
////////////////////////////////////////////////////////////
SoundStream::SoundStream() :
m_thread (&SoundStream::streamData, this),
m_threadMutex (),
m_threadStartState(Stopped),
m_isStreaming (false),
m_channelCount (0),
m_sampleRate (0),
m_format (0),
m_loop (false),
m_samplesProcessed(0)
{
}
////////////////////////////////////////////////////////////
SoundStream::~SoundStream()
{
// Stop the sound if it was playing
// Request the thread to terminate
{
Lock lock(m_threadMutex);
m_isStreaming = false;
}
// Wait for the thread to terminate
m_thread.wait();
}
////////////////////////////////////////////////////////////
void SoundStream::initialize(unsigned int channelCount, unsigned int sampleRate)
{
m_channelCount = channelCount;
m_sampleRate = sampleRate;
// Deduce the format from the number of channels
m_format = priv::AudioDevice::getFormatFromChannelCount(channelCount);
// Check if the format is valid
if (m_format == 0)
{
m_channelCount = 0;
m_sampleRate = 0;
err() << "Unsupported number of channels (" << m_channelCount << ")" << std::endl;
}
}
////////////////////////////////////////////////////////////
void SoundStream::play()
{
// Check if the sound parameters have been set
if (m_format == 0)
{
err() << "Failed to play audio stream: sound parameters have not been initialized (call initialize() first)" << std::endl;
return;
}
bool isStreaming = false;
Status threadStartState = Stopped;
{
Lock lock(m_threadMutex);
isStreaming = m_isStreaming;
threadStartState = m_threadStartState;
}
if (isStreaming && (threadStartState == Paused))
{
// If the sound is paused, resume it
Lock lock(m_threadMutex);
m_threadStartState = Playing;
alCheck(alSourcePlay(m_source));
return;
}
else if (isStreaming && (threadStartState == Playing))
{
// If the sound is playing, stop it and continue as if it was stopped
stop();
}
// Move to the beginning
onSeek(Time::Zero);
// Start updating the stream in a separate thread to avoid blocking the application
m_samplesProcessed = 0;
m_isStreaming = true;
m_threadStartState = Playing;
m_thread.launch();
}
////////////////////////////////////////////////////////////
void SoundStream::pause()
{
// Handle pause() being called before the thread has started
{
Lock lock(m_threadMutex);
if (!m_isStreaming)
return;
m_threadStartState = Paused;
}
alCheck(alSourcePause(m_source));
}
////////////////////////////////////////////////////////////
void SoundStream::stop()
{
// Request the thread to terminate
{
Lock lock(m_threadMutex);
m_isStreaming = false;
}
// Wait for the thread to terminate
m_thread.wait();
// Move to the beginning
onSeek(Time::Zero);
// Reset the playing position
m_samplesProcessed = 0;
}
////////////////////////////////////////////////////////////
unsigned int SoundStream::getChannelCount() const
{
return m_channelCount;
}
////////////////////////////////////////////////////////////
unsigned int SoundStream::getSampleRate() const
{
return m_sampleRate;
}
////////////////////////////////////////////////////////////
SoundStream::Status SoundStream::getStatus() const
{
Status status = SoundSource::getStatus();
// To compensate for the lag between play() and alSourceplay()
if (status == Stopped)
{
Lock lock(m_threadMutex);
if (m_isStreaming)
status = m_threadStartState;
}
return status;
}
////////////////////////////////////////////////////////////
void SoundStream::setPlayingOffset(Time timeOffset)
{
// Get old playing status
Status oldStatus = getStatus();
// Stop the stream
stop();
// Let the derived class update the current position
onSeek(timeOffset);
// Restart streaming
m_samplesProcessed = static_cast<Uint64>(timeOffset.asSeconds() * m_sampleRate * m_channelCount);
if (oldStatus == Stopped)
return;
m_isStreaming = true;
m_threadStartState = oldStatus;
m_thread.launch();
}
////////////////////////////////////////////////////////////
Time SoundStream::getPlayingOffset() const
{
if (m_sampleRate && m_channelCount)
{
ALfloat secs = 0.f;
alCheck(alGetSourcef(m_source, AL_SEC_OFFSET, &secs));
return seconds(secs + static_cast<float>(m_samplesProcessed) / m_sampleRate / m_channelCount);
}
else
{
return Time::Zero;
}
}
////////////////////////////////////////////////////////////
void SoundStream::setLoop(bool loop)
{
m_loop = loop;
}
////////////////////////////////////////////////////////////
bool SoundStream::getLoop() const
{
return m_loop;
}
////////////////////////////////////////////////////////////
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
alCheck(alGenBuffers(BufferCount, m_buffers));
for (int i = 0; i < BufferCount; ++i)
m_endBuffers[i] = false;
// Fill the queue
requestStop = fillQueue();
// Play the sound
alCheck(alSourcePlay(m_source));
// 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!
if (SoundSource::getStatus() == Stopped)
{
if (!requestStop)
{
// Just continue
alCheck(alSourcePlay(m_source));
}
else
{
// End streaming
Lock lock(m_threadMutex);
m_isStreaming = false;
}
}
// Get the number of buffers that have been processed (ie. ready for reuse)
ALint nbProcessed = 0;
alCheck(alGetSourcei(m_source, AL_BUFFERS_PROCESSED, &nbProcessed));
while (nbProcessed--)
{
// Pop the first unused buffer from the queue
ALuint buffer;
alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
// Find its number
unsigned int bufferNum = 0;
for (int i = 0; i < BufferCount; ++i)
if (m_buffers[i] == buffer)
{
bufferNum = i;
break;
}
// Retrieve its size and add it to the samples count
if (m_endBuffers[bufferNum])
{
// This was the last buffer: reset the sample count
m_samplesProcessed = 0;
m_endBuffers[bufferNum] = false;
}
else
{
ALint size, bits;
alCheck(alGetBufferi(buffer, AL_SIZE, &size));
alCheck(alGetBufferi(buffer, AL_BITS, &bits));
// Bits can be 0 if the format or parameters are corrupt, avoid division by zero
if (bits == 0)
{
err() << "Bits in sound stream are 0: make sure that the audio format is not corrupt "
<< "and initialize() has been called correctly" << std::endl;
// Abort streaming (exit main loop)
Lock lock(m_threadMutex);
m_isStreaming = false;
requestStop = true;
break;
}
else
{
m_samplesProcessed += size / (bits / 8);
}
}
// Fill it and push it back into the playing queue
if (!requestStop)
{
if (fillAndPushBuffer(bufferNum))
requestStop = true;
}
}
// Leave some time for the other threads if the stream is still playing
if (SoundSource::getStatus() != Stopped)
sleep(milliseconds(10));
}
// Stop the playback
alCheck(alSourceStop(m_source));
// Unqueue any buffer left in the queue
clearQueue();
// Delete the buffers
alCheck(alSourcei(m_source, AL_BUFFER, 0));
alCheck(alDeleteBuffers(BufferCount, m_buffers));
}
////////////////////////////////////////////////////////////
bool SoundStream::fillAndPushBuffer(unsigned int bufferNum)
{
bool requestStop = false;
// Acquire audio data
Chunk data = {NULL, 0};
if (!onGetData(data))
{
// Mark the buffer as the last one (so that we know when to reset the playing position)
m_endBuffers[bufferNum] = true;
// Check if the stream must loop or stop
if (m_loop)
{
// Return to the beginning of the stream source
onSeek(Time::Zero);
// If we previously had no data, try to fill the buffer once again
if (!data.samples || (data.sampleCount == 0))
{
return fillAndPushBuffer(bufferNum);
}
}
else
{
// Not looping: request stop
requestStop = true;
}
}
// Fill the buffer if some data was returned
if (data.samples && data.sampleCount)
{
unsigned int buffer = m_buffers[bufferNum];
// Fill the buffer
ALsizei size = static_cast<ALsizei>(data.sampleCount) * sizeof(Int16);
alCheck(alBufferData(buffer, m_format, data.samples, size, m_sampleRate));
// Push it into the sound queue
alCheck(alSourceQueueBuffers(m_source, 1, &buffer));
}
return requestStop;
}
////////////////////////////////////////////////////////////
bool SoundStream::fillQueue()
{
// Fill and enqueue all the available buffers
bool requestStop = false;
for (int i = 0; (i < BufferCount) && !requestStop; ++i)
{
if (fillAndPushBuffer(i))
requestStop = true;
}
return requestStop;
}
////////////////////////////////////////////////////////////
void SoundStream::clearQueue()
{
// Get the number of buffers still in the queue
ALint nbQueued;
alCheck(alGetSourcei(m_source, AL_BUFFERS_QUEUED, &nbQueued));
// Unqueue them all
ALuint buffer;
for (ALint i = 0; i < nbQueued; ++i)
alCheck(alSourceUnqueueBuffers(m_source, 1, &buffer));
}
} // namespace sf

View file

@ -1,53 +1,53 @@
# include the SFML specific macros
include(${PROJECT_SOURCE_DIR}/cmake/Macros.cmake)
# let CMake know about our additional libraries paths
# include the SFML specific macros
include(${PROJECT_SOURCE_DIR}/cmake/Macros.cmake)
# let CMake know about our additional libraries paths
if (SFML_OS_WINDOWS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
if(SFML_COMPILER_GCC)
if(ARCH_32BITS)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x86")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x86")
elseif(ARCH_64BITS)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x64")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x64")
endif()
elseif(SFML_COMPILER_MSVC)
if(ARCH_32BITS)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x86")
elseif(ARCH_64BITS)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x64")
endif()
endif()
elseif(SFML_OS_MACOSX)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/lib/")
elseif(SFML_OS_IOS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-ios/")
elseif(SFML_OS_ANDROID)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-android/${ANDROID_ABI}")
endif()
# add the SFML sources path
include_directories(${PROJECT_SOURCE_DIR}/src)
# define the path of our additional CMake modules
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/")
# set the output directory for SFML libraries
set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib")
# add the modules subdirectories
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
if(SFML_COMPILER_GCC)
if(ARCH_32BITS)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x86")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x86")
elseif(ARCH_64BITS)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-mingw/x64")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/bin/x64")
endif()
elseif(SFML_COMPILER_MSVC)
if(ARCH_32BITS)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x86")
elseif(ARCH_64BITS)
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-msvc/x64")
endif()
endif()
elseif(SFML_OS_MACOSX)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/lib/")
elseif(SFML_OS_IOS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-ios/")
elseif(SFML_OS_ANDROID)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-android/${ANDROID_ABI}")
endif()
# add the SFML sources path
include_directories(${PROJECT_SOURCE_DIR}/src)
# define the path of our additional CMake modules
set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/")
# set the output directory for SFML libraries
set(LIBRARY_OUTPUT_PATH "${PROJECT_BINARY_DIR}/lib")
# add the modules subdirectories
add_subdirectory(System)
if(SFML_OS_WINDOWS OR SFML_OS_ANDROID OR SFML_OS_IOS)
add_subdirectory(Main)
endif()
add_subdirectory(Window)
if(SFML_OS_WINDOWS OR SFML_OS_ANDROID OR SFML_OS_IOS)
add_subdirectory(Main)
endif()
add_subdirectory(Window)
add_subdirectory(Network)
add_subdirectory(Graphics)
if(NOT SFML_OS_IOS)
add_subdirectory(Audio)
endif()
add_subdirectory(Audio)
endif()

View file

@ -1,168 +1,168 @@
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Graphics)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Graphics)
# all source files
set(SRC
${SRCROOT}/BlendMode.cpp
${INCROOT}/BlendMode.hpp
${SRCROOT}/Color.cpp
${INCROOT}/Color.hpp
${INCROOT}/Export.hpp
${SRCROOT}/Font.cpp
${INCROOT}/Font.hpp
${INCROOT}/Glyph.hpp
${SRCROOT}/GLCheck.cpp
${SRCROOT}/GLCheck.hpp
${SRCROOT}/GLExtensions.hpp
${SRCROOT}/GLExtensions.cpp
${SRCROOT}/Image.cpp
${INCROOT}/Image.hpp
${SRCROOT}/ImageLoader.cpp
${SRCROOT}/ImageLoader.hpp
${INCROOT}/PrimitiveType.hpp
${INCROOT}/Rect.hpp
${INCROOT}/Rect.inl
${SRCROOT}/RenderStates.cpp
${INCROOT}/RenderStates.hpp
${SRCROOT}/RenderTexture.cpp
${INCROOT}/RenderTexture.hpp
${SRCROOT}/RenderTarget.cpp
${INCROOT}/RenderTarget.hpp
${SRCROOT}/RenderWindow.cpp
${INCROOT}/RenderWindow.hpp
${SRCROOT}/Shader.cpp
${INCROOT}/Shader.hpp
${SRCROOT}/Texture.cpp
${INCROOT}/Texture.hpp
${SRCROOT}/TextureSaver.cpp
${SRCROOT}/TextureSaver.hpp
${SRCROOT}/Transform.cpp
${INCROOT}/Transform.hpp
${SRCROOT}/Transformable.cpp
${INCROOT}/Transformable.hpp
${SRCROOT}/View.cpp
${INCROOT}/View.hpp
${SRCROOT}/Vertex.cpp
${INCROOT}/Vertex.hpp
)
source_group("" FILES ${SRC})
# drawables sources
set(DRAWABLES_SRC
${INCROOT}/Drawable.hpp
${SRCROOT}/Shape.cpp
${INCROOT}/Shape.hpp
${SRCROOT}/CircleShape.cpp
${INCROOT}/CircleShape.hpp
${SRCROOT}/RectangleShape.cpp
${INCROOT}/RectangleShape.hpp
${SRCROOT}/ConvexShape.cpp
${INCROOT}/ConvexShape.hpp
${SRCROOT}/Sprite.cpp
${INCROOT}/Sprite.hpp
${SRCROOT}/Text.cpp
${INCROOT}/Text.hpp
${SRCROOT}/VertexArray.cpp
${INCROOT}/VertexArray.hpp
)
source_group("drawables" FILES ${DRAWABLES_SRC})
# render-texture sources
set(RENDER_TEXTURE_SRC
${SRCROOT}/RenderTextureImpl.cpp
${SRCROOT}/RenderTextureImpl.hpp
${SRCROOT}/RenderTextureImplFBO.cpp
${SRCROOT}/RenderTextureImplFBO.hpp
${SRCROOT}/RenderTextureImplDefault.cpp
${SRCROOT}/RenderTextureImplDefault.hpp
)
source_group("render texture" FILES ${RENDER_TEXTURE_SRC})
# stb_image sources
set(STB_SRC
${SRCROOT}/stb_image/stb_image.h
${SRCROOT}/stb_image/stb_image_write.h
)
source_group("stb_image" FILES ${STB_SRC})
# let CMake know about our additional graphics libraries paths (on Windows and OSX)
if(SFML_OS_WINDOWS OR SFML_OS_MACOSX)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Graphics)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Graphics)
# all source files
set(SRC
${SRCROOT}/BlendMode.cpp
${INCROOT}/BlendMode.hpp
${SRCROOT}/Color.cpp
${INCROOT}/Color.hpp
${INCROOT}/Export.hpp
${SRCROOT}/Font.cpp
${INCROOT}/Font.hpp
${INCROOT}/Glyph.hpp
${SRCROOT}/GLCheck.cpp
${SRCROOT}/GLCheck.hpp
${SRCROOT}/GLExtensions.hpp
${SRCROOT}/GLExtensions.cpp
${SRCROOT}/Image.cpp
${INCROOT}/Image.hpp
${SRCROOT}/ImageLoader.cpp
${SRCROOT}/ImageLoader.hpp
${INCROOT}/PrimitiveType.hpp
${INCROOT}/Rect.hpp
${INCROOT}/Rect.inl
${SRCROOT}/RenderStates.cpp
${INCROOT}/RenderStates.hpp
${SRCROOT}/RenderTexture.cpp
${INCROOT}/RenderTexture.hpp
${SRCROOT}/RenderTarget.cpp
${INCROOT}/RenderTarget.hpp
${SRCROOT}/RenderWindow.cpp
${INCROOT}/RenderWindow.hpp
${SRCROOT}/Shader.cpp
${INCROOT}/Shader.hpp
${SRCROOT}/Texture.cpp
${INCROOT}/Texture.hpp
${SRCROOT}/TextureSaver.cpp
${SRCROOT}/TextureSaver.hpp
${SRCROOT}/Transform.cpp
${INCROOT}/Transform.hpp
${SRCROOT}/Transformable.cpp
${INCROOT}/Transformable.hpp
${SRCROOT}/View.cpp
${INCROOT}/View.hpp
${SRCROOT}/Vertex.cpp
${INCROOT}/Vertex.hpp
)
source_group("" FILES ${SRC})
# drawables sources
set(DRAWABLES_SRC
${INCROOT}/Drawable.hpp
${SRCROOT}/Shape.cpp
${INCROOT}/Shape.hpp
${SRCROOT}/CircleShape.cpp
${INCROOT}/CircleShape.hpp
${SRCROOT}/RectangleShape.cpp
${INCROOT}/RectangleShape.hpp
${SRCROOT}/ConvexShape.cpp
${INCROOT}/ConvexShape.hpp
${SRCROOT}/Sprite.cpp
${INCROOT}/Sprite.hpp
${SRCROOT}/Text.cpp
${INCROOT}/Text.hpp
${SRCROOT}/VertexArray.cpp
${INCROOT}/VertexArray.hpp
)
source_group("drawables" FILES ${DRAWABLES_SRC})
# render-texture sources
set(RENDER_TEXTURE_SRC
${SRCROOT}/RenderTextureImpl.cpp
${SRCROOT}/RenderTextureImpl.hpp
${SRCROOT}/RenderTextureImplFBO.cpp
${SRCROOT}/RenderTextureImplFBO.hpp
${SRCROOT}/RenderTextureImplDefault.cpp
${SRCROOT}/RenderTextureImplDefault.hpp
)
source_group("render texture" FILES ${RENDER_TEXTURE_SRC})
# stb_image sources
set(STB_SRC
${SRCROOT}/stb_image/stb_image.h
${SRCROOT}/stb_image/stb_image_write.h
)
source_group("stb_image" FILES ${STB_SRC})
# let CMake know about our additional graphics libraries paths (on Windows and OSX)
if(SFML_OS_WINDOWS OR SFML_OS_MACOSX)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
endif()
# let CMake know about our additional graphics libraries paths
if(SFML_OS_WINDOWS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows/freetype")
# let CMake know about our additional graphics libraries paths
if(SFML_OS_WINDOWS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/windows/freetype")
elseif(SFML_OS_MACOSX)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx/freetype2")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
elseif(SFML_OS_IOS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios/freetype2")
elseif(SFML_OS_ANDROID)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android/freetype")
endif()
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/osx/freetype2")
set(CMAKE_LIBRARY_PATH ${CMAKE_LIBRARY_PATH} "${PROJECT_SOURCE_DIR}/extlibs/libs-osx/Frameworks")
elseif(SFML_OS_IOS)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/ios/freetype2")
elseif(SFML_OS_ANDROID)
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/jpeg")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android")
set(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "${PROJECT_SOURCE_DIR}/extlibs/headers/libfreetype/android/freetype")
endif()
# find external libraries
if(NOT SFML_OPENGL_ES)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
if(SFML_OS_LINUX)
find_package(X11 REQUIRED)
endif()
include_directories(${FREETYPE_INCLUDE_DIRS} ${GLEW_INCLUDE_PATH} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR})
endif()
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
find_package(EGL REQUIRED)
find_package(GLES REQUIRED)
include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
endif()
if(SFML_OS_ANDROID)
find_host_package(JPEG REQUIRED)
find_host_package(Freetype REQUIRED)
else()
find_package(JPEG REQUIRED)
find_package(Freetype REQUIRED)
endif()
include_directories(${FREETYPE_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR})
# build the list of external libraries to link
if(NOT SFML_OPENGL_ES)
list(APPEND GRAPHICS_EXT_LIBS ${GLEW_LIBRARY} ${OPENGL_gl_LIBRARY})
if(SFML_OS_LINUX)
list(APPEND GRAPHICS_EXT_LIBS ${X11_LIBRARIES})
endif()
endif()
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
list(APPEND GRAPHICS_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
endif()
# find external libraries
if(NOT SFML_OPENGL_ES)
find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
if(SFML_OS_LINUX)
find_package(X11 REQUIRED)
endif()
include_directories(${FREETYPE_INCLUDE_DIRS} ${GLEW_INCLUDE_PATH} ${JPEG_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR})
endif()
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
find_package(EGL REQUIRED)
find_package(GLES REQUIRED)
include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
endif()
if(SFML_OS_ANDROID)
find_host_package(JPEG REQUIRED)
find_host_package(Freetype REQUIRED)
else()
find_package(JPEG REQUIRED)
find_package(Freetype REQUIRED)
endif()
include_directories(${FREETYPE_INCLUDE_DIRS} ${JPEG_INCLUDE_DIR})
# build the list of external libraries to link
if(NOT SFML_OPENGL_ES)
list(APPEND GRAPHICS_EXT_LIBS ${GLEW_LIBRARY} ${OPENGL_gl_LIBRARY})
if(SFML_OS_LINUX)
list(APPEND GRAPHICS_EXT_LIBS ${X11_LIBRARIES})
endif()
endif()
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
list(APPEND GRAPHICS_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
endif()
if(SFML_OS_IOS)
list(APPEND GRAPHICS_EXT_LIBS "-framework OpenGLES")
elseif(SFML_OS_ANDROID)
list(APPEND GRAPHICS_EXT_LIBS "-framework OpenGLES")
elseif(SFML_OS_ANDROID)
list(APPEND GRAPHICS_EXT_LIBS -lz)
endif()
list(APPEND GRAPHICS_EXT_LIBS ${FREETYPE_LIBRARY} ${JPEG_LIBRARY})
# add preprocessor symbols
if(NOT SFML_OPENGL_ES)
add_definitions(-DGLEW_STATIC)
endif()
add_definitions(-DSTBI_FAILURE_USERMSG)
# ImageLoader.cpp must be compiled with the -fno-strict-aliasing
# when gcc is used; otherwise saving PNGs may crash in stb_image_write
if(SFML_COMPILER_GCC)
set_source_files_properties(${SRCROOT}/ImageLoader.cpp PROPERTIES COMPILE_FLAGS -fno-strict-aliasing)
endif()
# define the sfml-graphics target
sfml_add_library(sfml-graphics
SOURCES ${SRC} ${DRAWABLES_SRC} ${RENDER_TEXTURE_SRC} ${STB_SRC}
DEPENDS sfml-window sfml-system
EXTERNAL_LIBS ${GRAPHICS_EXT_LIBS})
endif()
list(APPEND GRAPHICS_EXT_LIBS ${FREETYPE_LIBRARY} ${JPEG_LIBRARY})
# add preprocessor symbols
if(NOT SFML_OPENGL_ES)
add_definitions(-DGLEW_STATIC)
endif()
add_definitions(-DSTBI_FAILURE_USERMSG)
# ImageLoader.cpp must be compiled with the -fno-strict-aliasing
# when gcc is used; otherwise saving PNGs may crash in stb_image_write
if(SFML_COMPILER_GCC)
set_source_files_properties(${SRCROOT}/ImageLoader.cpp PROPERTIES COMPILE_FLAGS -fno-strict-aliasing)
endif()
# define the sfml-graphics target
sfml_add_library(sfml-graphics
SOURCES ${SRC} ${DRAWABLES_SRC} ${RENDER_TEXTURE_SRC} ${STB_SRC}
DEPENDS sfml-window sfml-system
EXTERNAL_LIBS ${GRAPHICS_EXT_LIBS})

View file

@ -1,137 +1,137 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/Color.hpp>
#include <algorithm>
namespace sf
{
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
const Color Color::Black(0, 0, 0);
const Color Color::White(255, 255, 255);
const Color Color::Red(255, 0, 0);
const Color Color::Green(0, 255, 0);
const Color Color::Blue(0, 0, 255);
const Color Color::Yellow(255, 255, 0);
const Color Color::Magenta(255, 0, 255);
const Color Color::Cyan(0, 255, 255);
const Color Color::Transparent(0, 0, 0, 0);
////////////////////////////////////////////////////////////
Color::Color() :
r(0),
g(0),
b(0),
a(255)
{
}
////////////////////////////////////////////////////////////
Color::Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha) :
r(red),
g(green),
b(blue),
a(alpha)
{
}
////////////////////////////////////////////////////////////
bool operator ==(const Color& left, const Color& right)
{
return (left.r == right.r) &&
(left.g == right.g) &&
(left.b == right.b) &&
(left.a == right.a);
}
////////////////////////////////////////////////////////////
bool operator !=(const Color& left, const Color& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
Color operator +(const Color& left, const Color& right)
{
return Color(Uint8(std::min(int(left.r) + right.r, 255)),
Uint8(std::min(int(left.g) + right.g, 255)),
Uint8(std::min(int(left.b) + right.b, 255)),
Uint8(std::min(int(left.a) + right.a, 255)));
}
////////////////////////////////////////////////////////////
Color operator -(const Color& left, const Color& right)
{
return Color(Uint8(std::max(int(left.r) - right.r, 0)),
Uint8(std::max(int(left.g) - right.g, 0)),
Uint8(std::max(int(left.b) - right.b, 0)),
Uint8(std::max(int(left.a) - right.a, 0)));
}
////////////////////////////////////////////////////////////
Color operator *(const Color& left, const Color& right)
{
return Color(Uint8(int(left.r) * right.r / 255),
Uint8(int(left.g) * right.g / 255),
Uint8(int(left.b) * right.b / 255),
Uint8(int(left.a) * right.a / 255));
}
////////////////////////////////////////////////////////////
Color& operator +=(Color& left, const Color& right)
{
return left = left + right;
}
////////////////////////////////////////////////////////////
Color& operator -=(Color& left, const Color& right)
{
return left = left - right;
}
////////////////////////////////////////////////////////////
Color& operator *=(Color& left, const Color& right)
{
return left = left * right;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/Color.hpp>
#include <algorithm>
namespace sf
{
////////////////////////////////////////////////////////////
// Static member data
////////////////////////////////////////////////////////////
const Color Color::Black(0, 0, 0);
const Color Color::White(255, 255, 255);
const Color Color::Red(255, 0, 0);
const Color Color::Green(0, 255, 0);
const Color Color::Blue(0, 0, 255);
const Color Color::Yellow(255, 255, 0);
const Color Color::Magenta(255, 0, 255);
const Color Color::Cyan(0, 255, 255);
const Color Color::Transparent(0, 0, 0, 0);
////////////////////////////////////////////////////////////
Color::Color() :
r(0),
g(0),
b(0),
a(255)
{
}
////////////////////////////////////////////////////////////
Color::Color(Uint8 red, Uint8 green, Uint8 blue, Uint8 alpha) :
r(red),
g(green),
b(blue),
a(alpha)
{
}
////////////////////////////////////////////////////////////
bool operator ==(const Color& left, const Color& right)
{
return (left.r == right.r) &&
(left.g == right.g) &&
(left.b == right.b) &&
(left.a == right.a);
}
////////////////////////////////////////////////////////////
bool operator !=(const Color& left, const Color& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
Color operator +(const Color& left, const Color& right)
{
return Color(Uint8(std::min(int(left.r) + right.r, 255)),
Uint8(std::min(int(left.g) + right.g, 255)),
Uint8(std::min(int(left.b) + right.b, 255)),
Uint8(std::min(int(left.a) + right.a, 255)));
}
////////////////////////////////////////////////////////////
Color operator -(const Color& left, const Color& right)
{
return Color(Uint8(std::max(int(left.r) - right.r, 0)),
Uint8(std::max(int(left.g) - right.g, 0)),
Uint8(std::max(int(left.b) - right.b, 0)),
Uint8(std::max(int(left.a) - right.a, 0)));
}
////////////////////////////////////////////////////////////
Color operator *(const Color& left, const Color& right)
{
return Color(Uint8(int(left.r) * right.r / 255),
Uint8(int(left.g) * right.g / 255),
Uint8(int(left.b) * right.b / 255),
Uint8(int(left.a) * right.a / 255));
}
////////////////////////////////////////////////////////////
Color& operator +=(Color& left, const Color& right)
{
return left = left + right;
}
////////////////////////////////////////////////////////////
Color& operator -=(Color& left, const Color& right)
{
return left = left - right;
}
////////////////////////////////////////////////////////////
Color& operator *=(Color& left, const Color& right)
{
return left = left * right;
}
} // namespace sf

File diff suppressed because it is too large Load diff

View file

@ -1,112 +1,112 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/GLCheck.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void glCheckError(const char* file, unsigned int line)
{
// Get the last error
GLenum errorCode = glGetError();
if (errorCode != GL_NO_ERROR)
{
std::string fileString(file);
std::string error = "unknown error";
std::string description = "no description";
// Decode the error code
switch (errorCode)
{
case GL_INVALID_ENUM :
{
error = "GL_INVALID_ENUM";
description = "an unacceptable value has been specified for an enumerated argument";
break;
}
case GL_INVALID_VALUE :
{
error = "GL_INVALID_VALUE";
description = "a numeric argument is out of range";
break;
}
case GL_INVALID_OPERATION :
{
error = "GL_INVALID_OPERATION";
description = "the specified operation is not allowed in the current state";
break;
}
case GL_STACK_OVERFLOW :
{
error = "GL_STACK_OVERFLOW";
description = "this command would cause a stack overflow";
break;
}
case GL_STACK_UNDERFLOW :
{
error = "GL_STACK_UNDERFLOW";
description = "this command would cause a stack underflow";
break;
}
case GL_OUT_OF_MEMORY :
{
error = "GL_OUT_OF_MEMORY";
description = "there is not enough memory left to execute the command";
break;
}
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION :
{
error = "GL_INVALID_FRAMEBUFFER_OPERATION";
description = "the object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\"";
break;
}
}
// Log the error
err() << "An internal OpenGL call failed in "
<< fileString.substr(fileString.find_last_of("\\/") + 1) << " (" << line << ") : "
<< error << ", " << description
<< std::endl;
}
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/GLCheck.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void glCheckError(const char* file, unsigned int line)
{
// Get the last error
GLenum errorCode = glGetError();
if (errorCode != GL_NO_ERROR)
{
std::string fileString(file);
std::string error = "unknown error";
std::string description = "no description";
// Decode the error code
switch (errorCode)
{
case GL_INVALID_ENUM:
{
error = "GL_INVALID_ENUM";
description = "an unacceptable value has been specified for an enumerated argument";
break;
}
case GL_INVALID_VALUE:
{
error = "GL_INVALID_VALUE";
description = "a numeric argument is out of range";
break;
}
case GL_INVALID_OPERATION:
{
error = "GL_INVALID_OPERATION";
description = "the specified operation is not allowed in the current state";
break;
}
case GL_STACK_OVERFLOW:
{
error = "GL_STACK_OVERFLOW";
description = "this command would cause a stack overflow";
break;
}
case GL_STACK_UNDERFLOW:
{
error = "GL_STACK_UNDERFLOW";
description = "this command would cause a stack underflow";
break;
}
case GL_OUT_OF_MEMORY:
{
error = "GL_OUT_OF_MEMORY";
description = "there is not enough memory left to execute the command";
break;
}
case GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION:
{
error = "GL_INVALID_FRAMEBUFFER_OPERATION";
description = "the object bound to FRAMEBUFFER_BINDING is not \"framebuffer complete\"";
break;
}
}
// Log the error
err() << "An internal OpenGL call failed in "
<< fileString.substr(fileString.find_last_of("\\/") + 1) << " (" << line << ") : "
<< error << ", " << description
<< std::endl;
}
}
} // namespace priv
} // namespace sf

View file

@ -1,69 +1,69 @@
////////////////////////////////////////////////////////////
//
// 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_GLCHECK_HPP
#define SFML_GLCHECK_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/Graphics/GLExtensions.hpp>
#include <string>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// Let's define a macro to quickly check every OpenGL API calls
////////////////////////////////////////////////////////////
#ifdef SFML_DEBUG
// In debug mode, perform a test on every OpenGL call
#define glCheck(x) x; sf::priv::glCheckError(__FILE__, __LINE__);
#else
// Else, we don't add any overhead
#define glCheck(call) (call)
#endif
////////////////////////////////////////////////////////////
/// \brief Check the last OpenGL error
///
/// \param file Source file where the call is located
/// \param line Line number of the source file where the call is located
///
////////////////////////////////////////////////////////////
void glCheckError(const char* file, unsigned int line);
} // namespace priv
} // namespace sf
#endif // SFML_GLCHECK_HPP
////////////////////////////////////////////////////////////
//
// 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_GLCHECK_HPP
#define SFML_GLCHECK_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/Graphics/GLExtensions.hpp>
#include <string>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// Let's define a macro to quickly check every OpenGL API calls
////////////////////////////////////////////////////////////
#ifdef SFML_DEBUG
// In debug mode, perform a test on every OpenGL call
#define glCheck(x) x; sf::priv::glCheckError(__FILE__, __LINE__);
#else
// Else, we don't add any overhead
#define glCheck(call) (call)
#endif
////////////////////////////////////////////////////////////
/// \brief Check the last OpenGL error
///
/// \param file Source file where the call is located
/// \param line Line number of the source file where the call is located
///
////////////////////////////////////////////////////////////
void glCheckError(const char* file, unsigned int line);
} // namespace priv
} // namespace sf
#endif // SFML_GLCHECK_HPP

View file

@ -1,58 +1,58 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 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/Graphics/GLExtensions.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void ensureExtensionsInit()
{
#if !defined(SFML_OPENGL_ES)
static bool initialized = false;
if (!initialized)
{
GLenum status = glewInit();
if (status == GLEW_OK)
{
initialized = true;
}
else
{
err() << "Failed to initialize GLEW, " << glewGetErrorString(status) << std::endl;
}
}
#endif
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 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/Graphics/GLExtensions.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void ensureExtensionsInit()
{
#if !defined(SFML_OPENGL_ES)
static bool initialized = false;
if (!initialized)
{
GLenum status = glewInit();
if (status == GLEW_OK)
{
initialized = true;
}
else
{
err() << "Failed to initialize GLEW, " << glewGetErrorString(status) << std::endl;
}
}
#endif
}
} // namespace priv
} // namespace sf

View file

@ -1,130 +1,130 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 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_GLEXTENSIONS_HPP
#define SFML_GLEXTENSIONS_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#ifdef SFML_OPENGL_ES
#include <SFML/OpenGL.hpp>
#ifdef SFML_SYSTEM_ANDROID
// Hack to make transparency working on some Android devices
#define GLEXT_blend_func_separate false
#define GLEXT_blend_equation_separate false
#else
#define GLEXT_blend_func_separate GL_OES_blend_func_separate
#define GLEXT_blend_equation_separate GL_OES_blend_equation_separate
#endif
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateOES
#define GLEXT_glBlendEquationSeparate glBlendEquationSeparateOES
#define GLEXT_framebuffer_object GL_OES_framebuffer_object
#define GLEXT_glGenFramebuffers glGenFramebuffersOES
#define GLEXT_glGenRenderbuffers glGenRenderbuffersOES
#define GLEXT_glBindFramebuffer glBindFramebufferOES
#define GLEXT_glBindRenderbuffer glBindRenderbufferOES
#define GLEXT_glDeleteFramebuffers glDeleteFramebuffersOES
#define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersOES
#define GLEXT_glRenderbufferStorage glRenderbufferStorageOES
#define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferOES
#define GLEXT_glFramebufferTexture2D glFramebufferTexture2DOES
#define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusOES
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_OES
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
#define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT16_OES
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES
#define GLEXT_texture_non_power_of_two false
#define GLEXT_multitexture true
#define GLEXT_glClientActiveTexture glClientActiveTexture
#define GLEXT_glActiveTexture glActiveTexture
#define GLEXT_GL_TEXTURE0 GL_TEXTURE0
#define GLEXT_glBlendEquation glBlendEquationOES
#define GLEXT_GL_FUNC_ADD GL_FUNC_ADD_OES
#define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT_OES
#else
#include <GL/glew.h>
#include <SFML/OpenGL.hpp>
#define GLEXT_blend_func_separate GLEW_EXT_blend_func_separate
#define GLEXT_blend_equation_separate GLEW_EXT_blend_equation_separate
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateEXT
#define GLEXT_glBlendEquationSeparate glBlendEquationSeparateEXT
#define GLEXT_framebuffer_object GLEW_EXT_framebuffer_object
#define GLEXT_glGenFramebuffers glGenFramebuffersEXT
#define GLEXT_glGenRenderbuffers glGenRenderbuffersEXT
#define GLEXT_glBindFramebuffer glBindFramebufferEXT
#define GLEXT_glBindRenderbuffer glBindRenderbufferEXT
#define GLEXT_glDeleteFramebuffers glDeleteFramebuffersEXT
#define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersEXT
#define GLEXT_glRenderbufferStorage glRenderbufferStorageEXT
#define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferEXT
#define GLEXT_glFramebufferTexture2D glFramebufferTexture2DEXT
#define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusEXT
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_EXT
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
#define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
#define GLEXT_texture_non_power_of_two GLEW_ARB_texture_non_power_of_two
#define GLEXT_multitexture GLEW_ARB_multitexture
#define GLEXT_glClientActiveTexture glClientActiveTextureARB
#define GLEXT_glActiveTexture glActiveTextureARB
#define GLEXT_GL_TEXTURE0 GL_TEXTURE0_ARB
#define GLEXT_glBlendEquation glBlendEquation
#define GLEXT_GL_FUNC_ADD GL_FUNC_ADD
#define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT
#endif
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Make sure that extensions are initialized
///
////////////////////////////////////////////////////////////
void ensureExtensionsInit();
} // namespace priv
} // namespace sf
#endif // SFML_GLEXTENSIONS_HPP
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 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_GLEXTENSIONS_HPP
#define SFML_GLEXTENSIONS_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#ifdef SFML_OPENGL_ES
#include <SFML/OpenGL.hpp>
#ifdef SFML_SYSTEM_ANDROID
// Hack to make transparency working on some Android devices
#define GLEXT_blend_func_separate false
#define GLEXT_blend_equation_separate false
#else
#define GLEXT_blend_func_separate GL_OES_blend_func_separate
#define GLEXT_blend_equation_separate GL_OES_blend_equation_separate
#endif
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateOES
#define GLEXT_glBlendEquationSeparate glBlendEquationSeparateOES
#define GLEXT_framebuffer_object GL_OES_framebuffer_object
#define GLEXT_glGenFramebuffers glGenFramebuffersOES
#define GLEXT_glGenRenderbuffers glGenRenderbuffersOES
#define GLEXT_glBindFramebuffer glBindFramebufferOES
#define GLEXT_glBindRenderbuffer glBindRenderbufferOES
#define GLEXT_glDeleteFramebuffers glDeleteFramebuffersOES
#define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersOES
#define GLEXT_glRenderbufferStorage glRenderbufferStorageOES
#define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferOES
#define GLEXT_glFramebufferTexture2D glFramebufferTexture2DOES
#define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusOES
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_OES
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_OES
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_OES
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_OES
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_OES
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_OES
#define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT16_OES
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_OES
#define GLEXT_texture_non_power_of_two false
#define GLEXT_multitexture true
#define GLEXT_glClientActiveTexture glClientActiveTexture
#define GLEXT_glActiveTexture glActiveTexture
#define GLEXT_GL_TEXTURE0 GL_TEXTURE0
#define GLEXT_glBlendEquation glBlendEquationOES
#define GLEXT_GL_FUNC_ADD GL_FUNC_ADD_OES
#define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT_OES
#else
#include <GL/glew.h>
#include <SFML/OpenGL.hpp>
#define GLEXT_blend_func_separate GLEW_EXT_blend_func_separate
#define GLEXT_blend_equation_separate GLEW_EXT_blend_equation_separate
#define GLEXT_glBlendFuncSeparate glBlendFuncSeparateEXT
#define GLEXT_glBlendEquationSeparate glBlendEquationSeparateEXT
#define GLEXT_framebuffer_object GLEW_EXT_framebuffer_object
#define GLEXT_glGenFramebuffers glGenFramebuffersEXT
#define GLEXT_glGenRenderbuffers glGenRenderbuffersEXT
#define GLEXT_glBindFramebuffer glBindFramebufferEXT
#define GLEXT_glBindRenderbuffer glBindRenderbufferEXT
#define GLEXT_glDeleteFramebuffers glDeleteFramebuffersEXT
#define GLEXT_glDeleteRenderbuffers glDeleteRenderbuffersEXT
#define GLEXT_glRenderbufferStorage glRenderbufferStorageEXT
#define GLEXT_glFramebufferRenderbuffer glFramebufferRenderbufferEXT
#define GLEXT_glFramebufferTexture2D glFramebufferTexture2DEXT
#define GLEXT_glCheckFramebufferStatus glCheckFramebufferStatusEXT
#define GLEXT_GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
#define GLEXT_GL_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING_EXT
#define GLEXT_GL_RENDERBUFFER GL_RENDERBUFFER_EXT
#define GLEXT_GL_COLOR_ATTACHMENT0 GL_COLOR_ATTACHMENT0_EXT
#define GLEXT_GL_DEPTH_ATTACHMENT GL_DEPTH_ATTACHMENT_EXT
#define GLEXT_GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
#define GLEXT_GL_DEPTH_COMPONENT GL_DEPTH_COMPONENT
#define GLEXT_GL_INVALID_FRAMEBUFFER_OPERATION GL_INVALID_FRAMEBUFFER_OPERATION_EXT
#define GLEXT_texture_non_power_of_two GLEW_ARB_texture_non_power_of_two
#define GLEXT_multitexture GLEW_ARB_multitexture
#define GLEXT_glClientActiveTexture glClientActiveTextureARB
#define GLEXT_glActiveTexture glActiveTextureARB
#define GLEXT_GL_TEXTURE0 GL_TEXTURE0_ARB
#define GLEXT_glBlendEquation glBlendEquation
#define GLEXT_GL_FUNC_ADD GL_FUNC_ADD
#define GLEXT_GL_FUNC_SUBTRACT GL_FUNC_SUBTRACT
#endif
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Make sure that extensions are initialized
///
////////////////////////////////////////////////////////////
void ensureExtensionsInit();
} // namespace priv
} // namespace sf
#endif // SFML_GLEXTENSIONS_HPP

View file

@ -1,344 +1,344 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/Image.hpp>
#include <SFML/Graphics/ImageLoader.hpp>
#include <SFML/System/Err.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/ResourceStream.hpp>
#endif
#include <algorithm>
#include <cstring>
namespace sf
{
////////////////////////////////////////////////////////////
Image::Image() :
m_size(0, 0)
{
#ifdef SFML_SYSTEM_ANDROID
m_stream = NULL;
#endif
}
////////////////////////////////////////////////////////////
Image::~Image()
{
#ifdef SFML_SYSTEM_ANDROID
if (m_stream)
delete (priv::ResourceStream*)m_stream;
#endif
}
////////////////////////////////////////////////////////////
void Image::create(unsigned int width, unsigned int height, const Color& color)
{
if (width && height)
{
// Assign the new size
m_size.x = width;
m_size.y = height;
// Resize the pixel buffer
m_pixels.resize(width * height * 4);
// Fill it with the specified color
Uint8* ptr = &m_pixels[0];
Uint8* end = ptr + m_pixels.size();
while (ptr < end)
{
*ptr++ = color.r;
*ptr++ = color.g;
*ptr++ = color.b;
*ptr++ = color.a;
}
}
else
{
// Create an empty image
m_size.x = 0;
m_size.y = 0;
m_pixels.clear();
}
}
////////////////////////////////////////////////////////////
void Image::create(unsigned int width, unsigned int height, const Uint8* pixels)
{
if (pixels && width && height)
{
// Assign the new size
m_size.x = width;
m_size.y = height;
// Copy the pixels
std::size_t size = width * height * 4;
m_pixels.resize(size);
std::memcpy(&m_pixels[0], pixels, size); // faster than vector::assign
}
else
{
// Create an empty image
m_size.x = 0;
m_size.y = 0;
m_pixels.clear();
}
}
////////////////////////////////////////////////////////////
bool Image::loadFromFile(const std::string& filename)
{
#ifndef SFML_SYSTEM_ANDROID
return priv::ImageLoader::getInstance().loadImageFromFile(filename, m_pixels, m_size);
#else
if (m_stream)
delete (priv::ResourceStream*)m_stream;
m_stream = new priv::ResourceStream(filename);
return loadFromStream(*(priv::ResourceStream*)m_stream);
#endif
}
////////////////////////////////////////////////////////////
bool Image::loadFromMemory(const void* data, std::size_t size)
{
return priv::ImageLoader::getInstance().loadImageFromMemory(data, size, m_pixels, m_size);
}
////////////////////////////////////////////////////////////
bool Image::loadFromStream(InputStream& stream)
{
return priv::ImageLoader::getInstance().loadImageFromStream(stream, m_pixels, m_size);
}
////////////////////////////////////////////////////////////
bool Image::saveToFile(const std::string& filename) const
{
return priv::ImageLoader::getInstance().saveImageToFile(filename, m_pixels, m_size);
}
////////////////////////////////////////////////////////////
Vector2u Image::getSize() const
{
return m_size;
}
////////////////////////////////////////////////////////////
void Image::createMaskFromColor(const Color& color, Uint8 alpha)
{
// Make sure that the image is not empty
if (!m_pixels.empty())
{
// Replace the alpha of the pixels that match the transparent color
Uint8* ptr = &m_pixels[0];
Uint8* end = ptr + m_pixels.size();
while (ptr < end)
{
if ((ptr[0] == color.r) && (ptr[1] == color.g) && (ptr[2] == color.b) && (ptr[3] == color.a))
ptr[3] = alpha;
ptr += 4;
}
}
}
////////////////////////////////////////////////////////////
void Image::copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect, bool applyAlpha)
{
// Make sure that both images are valid
if ((source.m_size.x == 0) || (source.m_size.y == 0) || (m_size.x == 0) || (m_size.y == 0))
return;
// Adjust the source rectangle
IntRect srcRect = sourceRect;
if (srcRect.width == 0 || (srcRect.height == 0))
{
srcRect.left = 0;
srcRect.top = 0;
srcRect.width = source.m_size.x;
srcRect.height = source.m_size.y;
}
else
{
if (srcRect.left < 0) srcRect.left = 0;
if (srcRect.top < 0) srcRect.top = 0;
if (srcRect.width > static_cast<int>(source.m_size.x)) srcRect.width = source.m_size.x;
if (srcRect.height > static_cast<int>(source.m_size.y)) srcRect.height = source.m_size.y;
}
// Then find the valid bounds of the destination rectangle
int width = srcRect.width;
int height = srcRect.height;
if (destX + width > m_size.x) width = m_size.x - destX;
if (destY + height > m_size.y) height = m_size.y - destY;
// Make sure the destination area is valid
if ((width <= 0) || (height <= 0))
return;
// Precompute as much as possible
int pitch = width * 4;
int rows = height;
int srcStride = source.m_size.x * 4;
int dstStride = m_size.x * 4;
const Uint8* srcPixels = &source.m_pixels[0] + (srcRect.left + srcRect.top * source.m_size.x) * 4;
Uint8* dstPixels = &m_pixels[0] + (destX + destY * m_size.x) * 4;
// Copy the pixels
if (applyAlpha)
{
// Interpolation using alpha values, pixel by pixel (slower)
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < width; ++j)
{
// Get a direct pointer to the components of the current pixel
const Uint8* src = srcPixels + j * 4;
Uint8* dst = dstPixels + j * 4;
// Interpolate RGBA components using the alpha value of the source pixel
Uint8 alpha = src[3];
dst[0] = (src[0] * alpha + dst[0] * (255 - alpha)) / 255;
dst[1] = (src[1] * alpha + dst[1] * (255 - alpha)) / 255;
dst[2] = (src[2] * alpha + dst[2] * (255 - alpha)) / 255;
dst[3] = alpha + dst[3] * (255 - alpha) / 255;
}
srcPixels += srcStride;
dstPixels += dstStride;
}
}
else
{
// Optimized copy ignoring alpha values, row by row (faster)
for (int i = 0; i < rows; ++i)
{
std::memcpy(dstPixels, srcPixels, pitch);
srcPixels += srcStride;
dstPixels += dstStride;
}
}
}
////////////////////////////////////////////////////////////
void Image::setPixel(unsigned int x, unsigned int y, const Color& color)
{
Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4];
*pixel++ = color.r;
*pixel++ = color.g;
*pixel++ = color.b;
*pixel++ = color.a;
}
////////////////////////////////////////////////////////////
Color Image::getPixel(unsigned int x, unsigned int y) const
{
const Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4];
return Color(pixel[0], pixel[1], pixel[2], pixel[3]);
}
////////////////////////////////////////////////////////////
const Uint8* Image::getPixelsPtr() const
{
if (!m_pixels.empty())
{
return &m_pixels[0];
}
else
{
err() << "Trying to access the pixels of an empty image" << std::endl;
return NULL;
}
}
////////////////////////////////////////////////////////////
void Image::flipHorizontally()
{
if (!m_pixels.empty())
{
std::size_t rowSize = m_size.x * 4;
for (std::size_t y = 0; y < m_size.y; ++y)
{
std::vector<Uint8>::iterator left = m_pixels.begin() + y * rowSize;
std::vector<Uint8>::iterator right = m_pixels.begin() + (y + 1) * rowSize - 4;
for (std::size_t x = 0; x < m_size.x / 2; ++x)
{
std::swap_ranges(left, left + 4, right);
left += 4;
right -= 4;
}
}
}
}
////////////////////////////////////////////////////////////
void Image::flipVertically()
{
if (!m_pixels.empty())
{
std::size_t rowSize = m_size.x * 4;
std::vector<Uint8>::iterator top = m_pixels.begin();
std::vector<Uint8>::iterator bottom = m_pixels.end() - rowSize;
for (std::size_t y = 0; y < m_size.y / 2; ++y)
{
std::swap_ranges(top, top + rowSize, bottom);
top += rowSize;
bottom -= rowSize;
}
}
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/Image.hpp>
#include <SFML/Graphics/ImageLoader.hpp>
#include <SFML/System/Err.hpp>
#ifdef SFML_SYSTEM_ANDROID
#include <SFML/System/Android/ResourceStream.hpp>
#endif
#include <algorithm>
#include <cstring>
namespace sf
{
////////////////////////////////////////////////////////////
Image::Image() :
m_size(0, 0)
{
#ifdef SFML_SYSTEM_ANDROID
m_stream = NULL;
#endif
}
////////////////////////////////////////////////////////////
Image::~Image()
{
#ifdef SFML_SYSTEM_ANDROID
if (m_stream)
delete (priv::ResourceStream*)m_stream;
#endif
}
////////////////////////////////////////////////////////////
void Image::create(unsigned int width, unsigned int height, const Color& color)
{
if (width && height)
{
// Assign the new size
m_size.x = width;
m_size.y = height;
// Resize the pixel buffer
m_pixels.resize(width * height * 4);
// Fill it with the specified color
Uint8* ptr = &m_pixels[0];
Uint8* end = ptr + m_pixels.size();
while (ptr < end)
{
*ptr++ = color.r;
*ptr++ = color.g;
*ptr++ = color.b;
*ptr++ = color.a;
}
}
else
{
// Create an empty image
m_size.x = 0;
m_size.y = 0;
m_pixels.clear();
}
}
////////////////////////////////////////////////////////////
void Image::create(unsigned int width, unsigned int height, const Uint8* pixels)
{
if (pixels && width && height)
{
// Assign the new size
m_size.x = width;
m_size.y = height;
// Copy the pixels
std::size_t size = width * height * 4;
m_pixels.resize(size);
std::memcpy(&m_pixels[0], pixels, size); // faster than vector::assign
}
else
{
// Create an empty image
m_size.x = 0;
m_size.y = 0;
m_pixels.clear();
}
}
////////////////////////////////////////////////////////////
bool Image::loadFromFile(const std::string& filename)
{
#ifndef SFML_SYSTEM_ANDROID
return priv::ImageLoader::getInstance().loadImageFromFile(filename, m_pixels, m_size);
#else
if (m_stream)
delete (priv::ResourceStream*)m_stream;
m_stream = new priv::ResourceStream(filename);
return loadFromStream(*(priv::ResourceStream*)m_stream);
#endif
}
////////////////////////////////////////////////////////////
bool Image::loadFromMemory(const void* data, std::size_t size)
{
return priv::ImageLoader::getInstance().loadImageFromMemory(data, size, m_pixels, m_size);
}
////////////////////////////////////////////////////////////
bool Image::loadFromStream(InputStream& stream)
{
return priv::ImageLoader::getInstance().loadImageFromStream(stream, m_pixels, m_size);
}
////////////////////////////////////////////////////////////
bool Image::saveToFile(const std::string& filename) const
{
return priv::ImageLoader::getInstance().saveImageToFile(filename, m_pixels, m_size);
}
////////////////////////////////////////////////////////////
Vector2u Image::getSize() const
{
return m_size;
}
////////////////////////////////////////////////////////////
void Image::createMaskFromColor(const Color& color, Uint8 alpha)
{
// Make sure that the image is not empty
if (!m_pixels.empty())
{
// Replace the alpha of the pixels that match the transparent color
Uint8* ptr = &m_pixels[0];
Uint8* end = ptr + m_pixels.size();
while (ptr < end)
{
if ((ptr[0] == color.r) && (ptr[1] == color.g) && (ptr[2] == color.b) && (ptr[3] == color.a))
ptr[3] = alpha;
ptr += 4;
}
}
}
////////////////////////////////////////////////////////////
void Image::copy(const Image& source, unsigned int destX, unsigned int destY, const IntRect& sourceRect, bool applyAlpha)
{
// Make sure that both images are valid
if ((source.m_size.x == 0) || (source.m_size.y == 0) || (m_size.x == 0) || (m_size.y == 0))
return;
// Adjust the source rectangle
IntRect srcRect = sourceRect;
if (srcRect.width == 0 || (srcRect.height == 0))
{
srcRect.left = 0;
srcRect.top = 0;
srcRect.width = source.m_size.x;
srcRect.height = source.m_size.y;
}
else
{
if (srcRect.left < 0) srcRect.left = 0;
if (srcRect.top < 0) srcRect.top = 0;
if (srcRect.width > static_cast<int>(source.m_size.x)) srcRect.width = source.m_size.x;
if (srcRect.height > static_cast<int>(source.m_size.y)) srcRect.height = source.m_size.y;
}
// Then find the valid bounds of the destination rectangle
int width = srcRect.width;
int height = srcRect.height;
if (destX + width > m_size.x) width = m_size.x - destX;
if (destY + height > m_size.y) height = m_size.y - destY;
// Make sure the destination area is valid
if ((width <= 0) || (height <= 0))
return;
// Precompute as much as possible
int pitch = width * 4;
int rows = height;
int srcStride = source.m_size.x * 4;
int dstStride = m_size.x * 4;
const Uint8* srcPixels = &source.m_pixels[0] + (srcRect.left + srcRect.top * source.m_size.x) * 4;
Uint8* dstPixels = &m_pixels[0] + (destX + destY * m_size.x) * 4;
// Copy the pixels
if (applyAlpha)
{
// Interpolation using alpha values, pixel by pixel (slower)
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < width; ++j)
{
// Get a direct pointer to the components of the current pixel
const Uint8* src = srcPixels + j * 4;
Uint8* dst = dstPixels + j * 4;
// Interpolate RGBA components using the alpha value of the source pixel
Uint8 alpha = src[3];
dst[0] = (src[0] * alpha + dst[0] * (255 - alpha)) / 255;
dst[1] = (src[1] * alpha + dst[1] * (255 - alpha)) / 255;
dst[2] = (src[2] * alpha + dst[2] * (255 - alpha)) / 255;
dst[3] = alpha + dst[3] * (255 - alpha) / 255;
}
srcPixels += srcStride;
dstPixels += dstStride;
}
}
else
{
// Optimized copy ignoring alpha values, row by row (faster)
for (int i = 0; i < rows; ++i)
{
std::memcpy(dstPixels, srcPixels, pitch);
srcPixels += srcStride;
dstPixels += dstStride;
}
}
}
////////////////////////////////////////////////////////////
void Image::setPixel(unsigned int x, unsigned int y, const Color& color)
{
Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4];
*pixel++ = color.r;
*pixel++ = color.g;
*pixel++ = color.b;
*pixel++ = color.a;
}
////////////////////////////////////////////////////////////
Color Image::getPixel(unsigned int x, unsigned int y) const
{
const Uint8* pixel = &m_pixels[(x + y * m_size.x) * 4];
return Color(pixel[0], pixel[1], pixel[2], pixel[3]);
}
////////////////////////////////////////////////////////////
const Uint8* Image::getPixelsPtr() const
{
if (!m_pixels.empty())
{
return &m_pixels[0];
}
else
{
err() << "Trying to access the pixels of an empty image" << std::endl;
return NULL;
}
}
////////////////////////////////////////////////////////////
void Image::flipHorizontally()
{
if (!m_pixels.empty())
{
std::size_t rowSize = m_size.x * 4;
for (std::size_t y = 0; y < m_size.y; ++y)
{
std::vector<Uint8>::iterator left = m_pixels.begin() + y * rowSize;
std::vector<Uint8>::iterator right = m_pixels.begin() + (y + 1) * rowSize - 4;
for (std::size_t x = 0; x < m_size.x / 2; ++x)
{
std::swap_ranges(left, left + 4, right);
left += 4;
right -= 4;
}
}
}
}
////////////////////////////////////////////////////////////
void Image::flipVertically()
{
if (!m_pixels.empty())
{
std::size_t rowSize = m_size.x * 4;
std::vector<Uint8>::iterator top = m_pixels.begin();
std::vector<Uint8>::iterator bottom = m_pixels.end() - rowSize;
for (std::size_t y = 0; y < m_size.y / 2; ++y)
{
std::swap_ranges(top, top + rowSize, bottom);
top += rowSize;
bottom -= rowSize;
}
}
}
} // namespace sf

View file

@ -1,321 +1,321 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/ImageLoader.hpp>
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/Graphics/stb_image/stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <SFML/Graphics/stb_image/stb_image_write.h>
extern "C"
{
#include <jpeglib.h>
#include <jerror.h>
}
#include <cctype>
namespace
{
// Convert a string to lower case
std::string toLower(std::string str)
{
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
*i = static_cast<char>(std::tolower(*i));
return str;
}
// stb_image callbacks that operate on a sf::InputStream
int read(void* user, char* data, int size)
{
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
return static_cast<int>(stream->read(data, size));
}
void skip(void* user, unsigned int size)
{
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
stream->seek(stream->tell() + size);
}
int eof(void* user)
{
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
return stream->tell() >= stream->getSize();
}
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ImageLoader& ImageLoader::getInstance()
{
static ImageLoader Instance;
return Instance;
}
////////////////////////////////////////////////////////////
ImageLoader::ImageLoader()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
ImageLoader::~ImageLoader()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
bool ImageLoader::loadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, Vector2u& size)
{
// Clear the array (just in case)
pixels.clear();
// Load the image and get a pointer to the pixels in memory
int width, height, channels;
unsigned char* ptr = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha);
if (ptr && width && height)
{
// Assign the image properties
size.x = width;
size.y = height;
// Copy the loaded pixels to the pixel buffer
pixels.resize(width * height * 4);
memcpy(&pixels[0], ptr, pixels.size());
// Free the loaded pixels (they are now in our own pixel buffer)
stbi_image_free(ptr);
return true;
}
else
{
// Error, failed to load the image
err() << "Failed to load image \"" << filename << "\". Reason : " << stbi_failure_reason() << std::endl;
return false;
}
}
////////////////////////////////////////////////////////////
bool ImageLoader::loadImageFromMemory(const void* data, std::size_t dataSize, std::vector<Uint8>& pixels, Vector2u& size)
{
// Check input parameters
if (data && dataSize)
{
// Clear the array (just in case)
pixels.clear();
// Load the image and get a pointer to the pixels in memory
int width, height, channels;
const unsigned char* buffer = static_cast<const unsigned char*>(data);
unsigned char* ptr = stbi_load_from_memory(buffer, static_cast<int>(dataSize), &width, &height, &channels, STBI_rgb_alpha);
if (ptr && width && height)
{
// Assign the image properties
size.x = width;
size.y = height;
// Copy the loaded pixels to the pixel buffer
pixels.resize(width * height * 4);
memcpy(&pixels[0], ptr, pixels.size());
// Free the loaded pixels (they are now in our own pixel buffer)
stbi_image_free(ptr);
return true;
}
else
{
// Error, failed to load the image
err() << "Failed to load image from memory. Reason : " << stbi_failure_reason() << std::endl;
return false;
}
}
else
{
err() << "Failed to load image from memory, no data provided" << std::endl;
return false;
}
}
////////////////////////////////////////////////////////////
bool ImageLoader::loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, Vector2u& size)
{
// Clear the array (just in case)
pixels.clear();
// Make sure that the stream's reading position is at the beginning
stream.seek(0);
// Setup the stb_image callbacks
stbi_io_callbacks callbacks;
callbacks.read = &read;
callbacks.skip = &skip;
callbacks.eof = &eof;
// Load the image and get a pointer to the pixels in memory
int width, height, channels;
unsigned char* ptr = stbi_load_from_callbacks(&callbacks, &stream, &width, &height, &channels, STBI_rgb_alpha);
if (ptr && width && height)
{
// Assign the image properties
size.x = width;
size.y = height;
// Copy the loaded pixels to the pixel buffer
pixels.resize(width * height * 4);
memcpy(&pixels[0], ptr, pixels.size());
// Free the loaded pixels (they are now in our own pixel buffer)
stbi_image_free(ptr);
return true;
}
else
{
// Error, failed to load the image
err() << "Failed to load image from stream. Reason : " << stbi_failure_reason() << std::endl;
return false;
}
}
////////////////////////////////////////////////////////////
bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, const Vector2u& size)
{
// Make sure the image is not empty
if (!pixels.empty() && (size.x > 0) && (size.y > 0))
{
// Deduce the image type from its extension
if (filename.size() > 3)
{
// Extract the extension
std::string extension = toLower(filename.substr(filename.size() - 3));
if (extension == "bmp")
{
// BMP format
if (stbi_write_bmp(filename.c_str(), size.x, size.y, 4, &pixels[0]))
return true;
}
else if (extension == "tga")
{
// TGA format
if (stbi_write_tga(filename.c_str(), size.x, size.y, 4, &pixels[0]))
return true;
}
else if (extension == "png")
{
// PNG format
if (stbi_write_png(filename.c_str(), size.x, size.y, 4, &pixels[0], 0))
return true;
}
else if (extension == "jpg")
{
// JPG format
if (writeJpg(filename, pixels, size.x, size.y))
return true;
}
}
}
err() << "Failed to save image \"" << filename << "\"" << std::endl;
return false;
}
////////////////////////////////////////////////////////////
bool ImageLoader::writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
{
// Open the file to write in
FILE* file = fopen(filename.c_str(), "wb");
if (!file)
return false;
// Initialize the error handler
jpeg_compress_struct compressInfos;
jpeg_error_mgr errorManager;
compressInfos.err = jpeg_std_error(&errorManager);
// Initialize all the writing and compression infos
jpeg_create_compress(&compressInfos);
compressInfos.image_width = width;
compressInfos.image_height = height;
compressInfos.input_components = 3;
compressInfos.in_color_space = JCS_RGB;
jpeg_stdio_dest(&compressInfos, file);
jpeg_set_defaults(&compressInfos);
jpeg_set_quality(&compressInfos, 90, TRUE);
// Get rid of the aplha channel
std::vector<Uint8> buffer(width * height * 3);
for (std::size_t i = 0; i < width * height; ++i)
{
buffer[i * 3 + 0] = pixels[i * 4 + 0];
buffer[i * 3 + 1] = pixels[i * 4 + 1];
buffer[i * 3 + 2] = pixels[i * 4 + 2];
}
Uint8* ptr = &buffer[0];
// Start compression
jpeg_start_compress(&compressInfos, TRUE);
// Write each row of the image
while (compressInfos.next_scanline < compressInfos.image_height)
{
JSAMPROW rawPointer = ptr + (compressInfos.next_scanline * width * 3);
jpeg_write_scanlines(&compressInfos, &rawPointer, 1);
}
// Finish compression
jpeg_finish_compress(&compressInfos);
jpeg_destroy_compress(&compressInfos);
// Close the file
fclose(file);
return true;
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/ImageLoader.hpp>
#include <SFML/System/InputStream.hpp>
#include <SFML/System/Err.hpp>
#include <SFML/Graphics/stb_image/stb_image.h>
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <SFML/Graphics/stb_image/stb_image_write.h>
extern "C"
{
#include <jpeglib.h>
#include <jerror.h>
}
#include <cctype>
namespace
{
// Convert a string to lower case
std::string toLower(std::string str)
{
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
*i = static_cast<char>(std::tolower(*i));
return str;
}
// stb_image callbacks that operate on a sf::InputStream
int read(void* user, char* data, int size)
{
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
return static_cast<int>(stream->read(data, size));
}
void skip(void* user, unsigned int size)
{
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
stream->seek(stream->tell() + size);
}
int eof(void* user)
{
sf::InputStream* stream = static_cast<sf::InputStream*>(user);
return stream->tell() >= stream->getSize();
}
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ImageLoader& ImageLoader::getInstance()
{
static ImageLoader Instance;
return Instance;
}
////////////////////////////////////////////////////////////
ImageLoader::ImageLoader()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
ImageLoader::~ImageLoader()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
bool ImageLoader::loadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, Vector2u& size)
{
// Clear the array (just in case)
pixels.clear();
// Load the image and get a pointer to the pixels in memory
int width, height, channels;
unsigned char* ptr = stbi_load(filename.c_str(), &width, &height, &channels, STBI_rgb_alpha);
if (ptr && width && height)
{
// Assign the image properties
size.x = width;
size.y = height;
// Copy the loaded pixels to the pixel buffer
pixels.resize(width * height * 4);
memcpy(&pixels[0], ptr, pixels.size());
// Free the loaded pixels (they are now in our own pixel buffer)
stbi_image_free(ptr);
return true;
}
else
{
// Error, failed to load the image
err() << "Failed to load image \"" << filename << "\". Reason: " << stbi_failure_reason() << std::endl;
return false;
}
}
////////////////////////////////////////////////////////////
bool ImageLoader::loadImageFromMemory(const void* data, std::size_t dataSize, std::vector<Uint8>& pixels, Vector2u& size)
{
// Check input parameters
if (data && dataSize)
{
// Clear the array (just in case)
pixels.clear();
// Load the image and get a pointer to the pixels in memory
int width, height, channels;
const unsigned char* buffer = static_cast<const unsigned char*>(data);
unsigned char* ptr = stbi_load_from_memory(buffer, static_cast<int>(dataSize), &width, &height, &channels, STBI_rgb_alpha);
if (ptr && width && height)
{
// Assign the image properties
size.x = width;
size.y = height;
// Copy the loaded pixels to the pixel buffer
pixels.resize(width * height * 4);
memcpy(&pixels[0], ptr, pixels.size());
// Free the loaded pixels (they are now in our own pixel buffer)
stbi_image_free(ptr);
return true;
}
else
{
// Error, failed to load the image
err() << "Failed to load image from memory. Reason: " << stbi_failure_reason() << std::endl;
return false;
}
}
else
{
err() << "Failed to load image from memory, no data provided" << std::endl;
return false;
}
}
////////////////////////////////////////////////////////////
bool ImageLoader::loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, Vector2u& size)
{
// Clear the array (just in case)
pixels.clear();
// Make sure that the stream's reading position is at the beginning
stream.seek(0);
// Setup the stb_image callbacks
stbi_io_callbacks callbacks;
callbacks.read = &read;
callbacks.skip = &skip;
callbacks.eof = &eof;
// Load the image and get a pointer to the pixels in memory
int width, height, channels;
unsigned char* ptr = stbi_load_from_callbacks(&callbacks, &stream, &width, &height, &channels, STBI_rgb_alpha);
if (ptr && width && height)
{
// Assign the image properties
size.x = width;
size.y = height;
// Copy the loaded pixels to the pixel buffer
pixels.resize(width * height * 4);
memcpy(&pixels[0], ptr, pixels.size());
// Free the loaded pixels (they are now in our own pixel buffer)
stbi_image_free(ptr);
return true;
}
else
{
// Error, failed to load the image
err() << "Failed to load image from stream. Reason: " << stbi_failure_reason() << std::endl;
return false;
}
}
////////////////////////////////////////////////////////////
bool ImageLoader::saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, const Vector2u& size)
{
// Make sure the image is not empty
if (!pixels.empty() && (size.x > 0) && (size.y > 0))
{
// Deduce the image type from its extension
if (filename.size() > 3)
{
// Extract the extension
std::string extension = toLower(filename.substr(filename.size() - 3));
if (extension == "bmp")
{
// BMP format
if (stbi_write_bmp(filename.c_str(), size.x, size.y, 4, &pixels[0]))
return true;
}
else if (extension == "tga")
{
// TGA format
if (stbi_write_tga(filename.c_str(), size.x, size.y, 4, &pixels[0]))
return true;
}
else if (extension == "png")
{
// PNG format
if (stbi_write_png(filename.c_str(), size.x, size.y, 4, &pixels[0], 0))
return true;
}
else if (extension == "jpg")
{
// JPG format
if (writeJpg(filename, pixels, size.x, size.y))
return true;
}
}
}
err() << "Failed to save image \"" << filename << "\"" << std::endl;
return false;
}
////////////////////////////////////////////////////////////
bool ImageLoader::writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height)
{
// Open the file to write in
FILE* file = fopen(filename.c_str(), "wb");
if (!file)
return false;
// Initialize the error handler
jpeg_compress_struct compressInfos;
jpeg_error_mgr errorManager;
compressInfos.err = jpeg_std_error(&errorManager);
// Initialize all the writing and compression infos
jpeg_create_compress(&compressInfos);
compressInfos.image_width = width;
compressInfos.image_height = height;
compressInfos.input_components = 3;
compressInfos.in_color_space = JCS_RGB;
jpeg_stdio_dest(&compressInfos, file);
jpeg_set_defaults(&compressInfos);
jpeg_set_quality(&compressInfos, 90, TRUE);
// Get rid of the aplha channel
std::vector<Uint8> buffer(width * height * 3);
for (std::size_t i = 0; i < width * height; ++i)
{
buffer[i * 3 + 0] = pixels[i * 4 + 0];
buffer[i * 3 + 1] = pixels[i * 4 + 1];
buffer[i * 3 + 2] = pixels[i * 4 + 2];
}
Uint8* ptr = &buffer[0];
// Start compression
jpeg_start_compress(&compressInfos, TRUE);
// Write each row of the image
while (compressInfos.next_scanline < compressInfos.image_height)
{
JSAMPROW rawPointer = ptr + (compressInfos.next_scanline * width * 3);
jpeg_write_scanlines(&compressInfos, &rawPointer, 1);
}
// Finish compression
jpeg_finish_compress(&compressInfos);
jpeg_destroy_compress(&compressInfos);
// Close the file
fclose(file);
return true;
}
} // namespace priv
} // namespace sf

View file

@ -1,141 +1,141 @@
////////////////////////////////////////////////////////////
//
// 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_IMAGELOADER_HPP
#define SFML_IMAGELOADER_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Vector2.hpp>
#include <string>
#include <vector>
namespace sf
{
class InputStream;
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Load/save image files
///
////////////////////////////////////////////////////////////
class ImageLoader : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Get the unique instance of the class
///
/// \return Reference to the ImageLoader instance
///
////////////////////////////////////////////////////////////
static ImageLoader& getInstance();
////////////////////////////////////////////////////////////
/// \brief Load an image from a file on disk
///
/// \param filename Path of image file to load
/// \param pixels Array of pixels to fill with loaded image
/// \param size Size of loaded image, in pixels
///
/// \return True if loading was successful
///
////////////////////////////////////////////////////////////
bool loadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, Vector2u& size);
////////////////////////////////////////////////////////////
/// \brief Load an image from a file in memory
///
/// \param data Pointer to the file data in memory
/// \param dataSize Size of the data to load, in bytes
/// \param pixels Array of pixels to fill with loaded image
/// \param size Size of loaded image, in pixels
///
/// \return True if loading was successful
///
////////////////////////////////////////////////////////////
bool loadImageFromMemory(const void* data, std::size_t dataSize, std::vector<Uint8>& pixels, Vector2u& size);
////////////////////////////////////////////////////////////
/// \brief Load an image from a custom stream
///
/// \param stream Source stream to read from
/// \param pixels Array of pixels to fill with loaded image
/// \param size Size of loaded image, in pixels
///
/// \return True if loading was successful
///
////////////////////////////////////////////////////////////
bool loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, Vector2u& size);
////////////////////////////////////////////////////////////
/// \brief Save an array of pixels as an image file
///
/// \param filename Path of image file to save
/// \param pixels Array of pixels to save to image
/// \param size Size of image to save, in pixels
///
/// \return True if saving was successful
///
////////////////////////////////////////////////////////////
bool saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, const Vector2u& size);
private :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
ImageLoader();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~ImageLoader();
////////////////////////////////////////////////////////////
/// \brief Save an image file in JPEG format
///
/// \param filename Path of image file to save
/// \param pixels Array of pixels to save to image
/// \param width Width of image to save, in pixels
/// \param height Height of image to save, in pixels
///
/// \return True if saving was successful
///
////////////////////////////////////////////////////////////
bool writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height);
};
} // namespace priv
} // namespace sf
#endif // SFML_IMAGELOADER_HPP
////////////////////////////////////////////////////////////
//
// 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_IMAGELOADER_HPP
#define SFML_IMAGELOADER_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <SFML/System/Vector2.hpp>
#include <string>
#include <vector>
namespace sf
{
class InputStream;
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Load/save image files
///
////////////////////////////////////////////////////////////
class ImageLoader : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Get the unique instance of the class
///
/// \return Reference to the ImageLoader instance
///
////////////////////////////////////////////////////////////
static ImageLoader& getInstance();
////////////////////////////////////////////////////////////
/// \brief Load an image from a file on disk
///
/// \param filename Path of image file to load
/// \param pixels Array of pixels to fill with loaded image
/// \param size Size of loaded image, in pixels
///
/// \return True if loading was successful
///
////////////////////////////////////////////////////////////
bool loadImageFromFile(const std::string& filename, std::vector<Uint8>& pixels, Vector2u& size);
////////////////////////////////////////////////////////////
/// \brief Load an image from a file in memory
///
/// \param data Pointer to the file data in memory
/// \param dataSize Size of the data to load, in bytes
/// \param pixels Array of pixels to fill with loaded image
/// \param size Size of loaded image, in pixels
///
/// \return True if loading was successful
///
////////////////////////////////////////////////////////////
bool loadImageFromMemory(const void* data, std::size_t dataSize, std::vector<Uint8>& pixels, Vector2u& size);
////////////////////////////////////////////////////////////
/// \brief Load an image from a custom stream
///
/// \param stream Source stream to read from
/// \param pixels Array of pixels to fill with loaded image
/// \param size Size of loaded image, in pixels
///
/// \return True if loading was successful
///
////////////////////////////////////////////////////////////
bool loadImageFromStream(InputStream& stream, std::vector<Uint8>& pixels, Vector2u& size);
////////////////////////////////////////////////////////////
/// \brief Save an array of pixels as an image file
///
/// \param filename Path of image file to save
/// \param pixels Array of pixels to save to image
/// \param size Size of image to save, in pixels
///
/// \return True if saving was successful
///
////////////////////////////////////////////////////////////
bool saveImageToFile(const std::string& filename, const std::vector<Uint8>& pixels, const Vector2u& size);
private:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
ImageLoader();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~ImageLoader();
////////////////////////////////////////////////////////////
/// \brief Save an image file in JPEG format
///
/// \param filename Path of image file to save
/// \param pixels Array of pixels to save to image
/// \param width Width of image to save, in pixels
/// \param height Height of image to save, in pixels
///
/// \return True if saving was successful
///
////////////////////////////////////////////////////////////
bool writeJpg(const std::string& filename, const std::vector<Uint8>& pixels, unsigned int width, unsigned int height);
};
} // namespace priv
} // namespace sf
#endif // SFML_IMAGELOADER_HPP

File diff suppressed because it is too large Load diff

View file

@ -1,155 +1,155 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/RenderTexture.hpp>
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/RenderTextureImplDefault.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
RenderTexture::RenderTexture() :
m_impl(NULL)
{
}
////////////////////////////////////////////////////////////
RenderTexture::~RenderTexture()
{
delete m_impl;
}
////////////////////////////////////////////////////////////
bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer)
{
// Create the texture
if (!m_texture.create(width, height))
{
err() << "Impossible to create render texture (failed to create the target texture)" << std::endl;
return false;
}
// We disable smoothing by default for render textures
setSmooth(false);
// Create the implementation
delete m_impl;
if (priv::RenderTextureImplFBO::isAvailable())
{
// Use frame-buffer object (FBO)
m_impl = new priv::RenderTextureImplFBO;
}
else
{
// Use default implementation
m_impl = new priv::RenderTextureImplDefault;
}
// Initialize the render texture
if (!m_impl->create(width, height, m_texture.m_texture, depthBuffer))
return false;
// We can now initialize the render target part
RenderTarget::initialize();
return true;
}
////////////////////////////////////////////////////////////
void RenderTexture::setSmooth(bool smooth)
{
m_texture.setSmooth(smooth);
}
////////////////////////////////////////////////////////////
bool RenderTexture::isSmooth() const
{
return m_texture.isSmooth();
}
////////////////////////////////////////////////////////////
void RenderTexture::setRepeated(bool repeated)
{
m_texture.setRepeated(repeated);
}
////////////////////////////////////////////////////////////
bool RenderTexture::isRepeated() const
{
return m_texture.isRepeated();
}
////////////////////////////////////////////////////////////
bool RenderTexture::setActive(bool active)
{
return m_impl && m_impl->activate(active);
}
////////////////////////////////////////////////////////////
void RenderTexture::display()
{
// Update the target texture
if (setActive(true))
{
m_impl->updateTexture(m_texture.m_texture);
m_texture.m_pixelsFlipped = true;
}
}
////////////////////////////////////////////////////////////
Vector2u RenderTexture::getSize() const
{
return m_texture.getSize();
}
////////////////////////////////////////////////////////////
const Texture& RenderTexture::getTexture() const
{
return m_texture;
}
////////////////////////////////////////////////////////////
bool RenderTexture::activate(bool active)
{
return setActive(active);
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/RenderTexture.hpp>
#include <SFML/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/RenderTextureImplDefault.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
RenderTexture::RenderTexture() :
m_impl(NULL)
{
}
////////////////////////////////////////////////////////////
RenderTexture::~RenderTexture()
{
delete m_impl;
}
////////////////////////////////////////////////////////////
bool RenderTexture::create(unsigned int width, unsigned int height, bool depthBuffer)
{
// Create the texture
if (!m_texture.create(width, height))
{
err() << "Impossible to create render texture (failed to create the target texture)" << std::endl;
return false;
}
// We disable smoothing by default for render textures
setSmooth(false);
// Create the implementation
delete m_impl;
if (priv::RenderTextureImplFBO::isAvailable())
{
// Use frame-buffer object (FBO)
m_impl = new priv::RenderTextureImplFBO;
}
else
{
// Use default implementation
m_impl = new priv::RenderTextureImplDefault;
}
// Initialize the render texture
if (!m_impl->create(width, height, m_texture.m_texture, depthBuffer))
return false;
// We can now initialize the render target part
RenderTarget::initialize();
return true;
}
////////////////////////////////////////////////////////////
void RenderTexture::setSmooth(bool smooth)
{
m_texture.setSmooth(smooth);
}
////////////////////////////////////////////////////////////
bool RenderTexture::isSmooth() const
{
return m_texture.isSmooth();
}
////////////////////////////////////////////////////////////
void RenderTexture::setRepeated(bool repeated)
{
m_texture.setRepeated(repeated);
}
////////////////////////////////////////////////////////////
bool RenderTexture::isRepeated() const
{
return m_texture.isRepeated();
}
////////////////////////////////////////////////////////////
bool RenderTexture::setActive(bool active)
{
return m_impl && m_impl->activate(active);
}
////////////////////////////////////////////////////////////
void RenderTexture::display()
{
// Update the target texture
if (setActive(true))
{
m_impl->updateTexture(m_texture.m_texture);
m_texture.m_pixelsFlipped = true;
}
}
////////////////////////////////////////////////////////////
Vector2u RenderTexture::getSize() const
{
return m_texture.getSize();
}
////////////////////////////////////////////////////////////
const Texture& RenderTexture::getTexture() const
{
return m_texture;
}
////////////////////////////////////////////////////////////
bool RenderTexture::activate(bool active)
{
return setActive(active);
}
} // namespace sf

View file

@ -1,43 +1,43 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/RenderTextureImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
RenderTextureImpl::~RenderTextureImpl()
{
// Nothing to do
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/RenderTextureImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
RenderTextureImpl::~RenderTextureImpl()
{
// Nothing to do
}
} // namespace priv
} // namespace sf

View file

@ -1,89 +1,89 @@
////////////////////////////////////////////////////////////
//
// 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_RENDERTEXTUREIMPL_HPP
#define SFML_RENDERTEXTUREIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Abstract base class for render-texture implementations
///
////////////////////////////////////////////////////////////
class RenderTextureImpl : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
virtual ~RenderTextureImpl();
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0;
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering
///
/// \param active True to activate, false to deactivate
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
virtual bool activate(bool active) = 0;
////////////////////////////////////////////////////////////
/// \brief Update the pixels of the target texture
///
/// \param textureId OpenGL identifier of the target texture
///
////////////////////////////////////////////////////////////
virtual void updateTexture(unsigned int textureId) = 0;
};
} // namespace priv
} // namespace sf
#endif // SFML_RENDERTEXTUREIMPL_HPP
////////////////////////////////////////////////////////////
//
// 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_RENDERTEXTUREIMPL_HPP
#define SFML_RENDERTEXTUREIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Abstract base class for render-texture implementations
///
////////////////////////////////////////////////////////////
class RenderTextureImpl : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
virtual ~RenderTextureImpl();
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer) = 0;
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering
///
/// \param active True to activate, false to deactivate
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
virtual bool activate(bool active) = 0;
////////////////////////////////////////////////////////////
/// \brief Update the pixels of the target texture
///
/// \param textureId OpenGL identifier of the target texture
///
////////////////////////////////////////////////////////////
virtual void updateTexture(unsigned int textureId) = 0;
};
} // namespace priv
} // namespace sf
#endif // SFML_RENDERTEXTUREIMPL_HPP

View file

@ -44,7 +44,7 @@ namespace priv
////////////////////////////////////////////////////////////
class RenderTextureImplDefault : public RenderTextureImpl, GlResource
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
@ -58,7 +58,7 @@ public :
////////////////////////////////////////////////////////////
~RenderTextureImplDefault();
private :
private:
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation

View file

@ -1,147 +1,147 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
RenderTextureImplFBO::RenderTextureImplFBO() :
m_frameBuffer(0),
m_depthBuffer(0)
{
}
////////////////////////////////////////////////////////////
RenderTextureImplFBO::~RenderTextureImplFBO()
{
ensureGlContext();
// Destroy the depth buffer
if (m_depthBuffer)
{
GLuint depthBuffer = static_cast<GLuint>(m_depthBuffer);
glCheck(GLEXT_glDeleteRenderbuffers(1, &depthBuffer));
}
// Destroy the frame buffer
if (m_frameBuffer)
{
GLuint frameBuffer = static_cast<GLuint>(m_frameBuffer);
glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
}
// Delete the context
delete m_context;
}
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::isAvailable()
{
ensureGlContext();
// Make sure that extensions are initialized
priv::ensureExtensionsInit();
return GLEXT_framebuffer_object != 0;
}
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
{
// Create the context
m_context = new Context;
// Create the framebuffer object
GLuint frameBuffer = 0;
glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer));
m_frameBuffer = static_cast<unsigned int>(frameBuffer);
if (!m_frameBuffer)
{
err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl;
return false;
}
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer));
// Create the depth buffer if requested
if (depthBuffer)
{
GLuint depth = 0;
glCheck(GLEXT_glGenRenderbuffers(1, &depth));
m_depthBuffer = static_cast<unsigned int>(depth);
if (!m_depthBuffer)
{
err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl;
return false;
}
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthBuffer));
glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthBuffer));
}
// Link the texture to the frame buffer
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));
////////////////////////////////////////////////////////////
//
// 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/Graphics/RenderTextureImplFBO.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/GLCheck.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
RenderTextureImplFBO::RenderTextureImplFBO() :
m_frameBuffer(0),
m_depthBuffer(0)
{
}
////////////////////////////////////////////////////////////
RenderTextureImplFBO::~RenderTextureImplFBO()
{
ensureGlContext();
// Destroy the depth buffer
if (m_depthBuffer)
{
GLuint depthBuffer = static_cast<GLuint>(m_depthBuffer);
glCheck(GLEXT_glDeleteRenderbuffers(1, &depthBuffer));
}
// Destroy the frame buffer
if (m_frameBuffer)
{
GLuint frameBuffer = static_cast<GLuint>(m_frameBuffer);
glCheck(GLEXT_glDeleteFramebuffers(1, &frameBuffer));
}
// Delete the context
delete m_context;
}
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::isAvailable()
{
ensureGlContext();
// Make sure that extensions are initialized
priv::ensureExtensionsInit();
return GLEXT_framebuffer_object != 0;
}
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer)
{
// Create the context
m_context = new Context;
// Create the framebuffer object
GLuint frameBuffer = 0;
glCheck(GLEXT_glGenFramebuffers(1, &frameBuffer));
m_frameBuffer = static_cast<unsigned int>(frameBuffer);
if (!m_frameBuffer)
{
err() << "Impossible to create render texture (failed to create the frame buffer object)" << std::endl;
return false;
}
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, m_frameBuffer));
// Create the depth buffer if requested
if (depthBuffer)
{
GLuint depth = 0;
glCheck(GLEXT_glGenRenderbuffers(1, &depth));
m_depthBuffer = static_cast<unsigned int>(depth);
if (!m_depthBuffer)
{
err() << "Impossible to create render texture (failed to create the attached depth buffer)" << std::endl;
return false;
}
glCheck(GLEXT_glBindRenderbuffer(GLEXT_GL_RENDERBUFFER, m_depthBuffer));
glCheck(GLEXT_glRenderbufferStorage(GLEXT_GL_RENDERBUFFER, GLEXT_GL_DEPTH_COMPONENT, width, height));
glCheck(GLEXT_glFramebufferRenderbuffer(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_DEPTH_ATTACHMENT, GLEXT_GL_RENDERBUFFER, m_depthBuffer));
}
// Link the texture to the frame buffer
glCheck(GLEXT_glFramebufferTexture2D(GLEXT_GL_FRAMEBUFFER, GLEXT_GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0));
// A final check, just to be sure...
GLenum status = glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
GLenum status = glCheck(GLEXT_glCheckFramebufferStatus(GLEXT_GL_FRAMEBUFFER));
if (status != GLEXT_GL_FRAMEBUFFER_COMPLETE)
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
return false;
}
return true;
}
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::activate(bool active)
{
return m_context->setActive(active);
}
////////////////////////////////////////////////////////////
void RenderTextureImplFBO::updateTexture(unsigned int)
{
glCheck(glFlush());
}
} // namespace priv
} // namespace sf
{
glCheck(GLEXT_glBindFramebuffer(GLEXT_GL_FRAMEBUFFER, 0));
err() << "Impossible to create render texture (failed to link the target texture to the frame buffer)" << std::endl;
return false;
}
return true;
}
////////////////////////////////////////////////////////////
bool RenderTextureImplFBO::activate(bool active)
{
return m_context->setActive(active);
}
////////////////////////////////////////////////////////////
void RenderTextureImplFBO::updateTexture(unsigned int)
{
glCheck(glFlush());
}
} // namespace priv
} // namespace sf

View file

@ -1,115 +1,115 @@
////////////////////////////////////////////////////////////
//
// 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_RENDERTEXTUREIMPLFBO_HPP
#define SFML_RENDERTEXTUREIMPLFBO_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderTextureImpl.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/GlResource.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Specialization of RenderTextureImpl using the
/// FrameBuffer Object OpenGL extension
///
////////////////////////////////////////////////////////////
class RenderTextureImplFBO : public RenderTextureImpl, GlResource
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
RenderTextureImplFBO();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~RenderTextureImplFBO();
////////////////////////////////////////////////////////////
/// \brief Check whether the system supports FBOs or not
///
/// \return True if FBO render textures are supported
///
////////////////////////////////////////////////////////////
static bool isAvailable();
private :
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering
///
/// \param active True to activate, false to deactivate
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
virtual bool activate(bool active);
////////////////////////////////////////////////////////////
/// \brief Update the pixels of the target texture
///
/// \param textureId OpenGL identifier of the target texture
///
////////////////////////////////////////////////////////////
virtual void updateTexture(unsigned textureId);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Context* m_context; ///< Needs a separate OpenGL context for not messing up the other ones
unsigned int m_frameBuffer; ///< OpenGL frame buffer object
unsigned int m_depthBuffer; ///< Optional depth buffer attached to the frame buffer
};
} // namespace priv
} // namespace sf
#endif // SFML_RENDERTEXTUREIMPLFBO_HPP
////////////////////////////////////////////////////////////
//
// 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_RENDERTEXTUREIMPLFBO_HPP
#define SFML_RENDERTEXTUREIMPLFBO_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Graphics/RenderTextureImpl.hpp>
#include <SFML/Window/Context.hpp>
#include <SFML/Window/GlResource.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Specialization of RenderTextureImpl using the
/// FrameBuffer Object OpenGL extension
///
////////////////////////////////////////////////////////////
class RenderTextureImplFBO : public RenderTextureImpl, GlResource
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
RenderTextureImplFBO();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~RenderTextureImplFBO();
////////////////////////////////////////////////////////////
/// \brief Check whether the system supports FBOs or not
///
/// \return True if FBO render textures are supported
///
////////////////////////////////////////////////////////////
static bool isAvailable();
private:
////////////////////////////////////////////////////////////
/// \brief Create the render texture implementation
///
/// \param width Width of the texture to render to
/// \param height Height of the texture to render to
/// \param textureId OpenGL identifier of the target texture
/// \param depthBuffer Is a depth buffer requested?
///
/// \return True if creation has been successful
///
////////////////////////////////////////////////////////////
virtual bool create(unsigned int width, unsigned int height, unsigned int textureId, bool depthBuffer);
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the render texture for rendering
///
/// \param active True to activate, false to deactivate
///
/// \return True on success, false on failure
///
////////////////////////////////////////////////////////////
virtual bool activate(bool active);
////////////////////////////////////////////////////////////
/// \brief Update the pixels of the target texture
///
/// \param textureId OpenGL identifier of the target texture
///
////////////////////////////////////////////////////////////
virtual void updateTexture(unsigned textureId);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
Context* m_context; ///< Needs a separate OpenGL context for not messing up the other ones
unsigned int m_frameBuffer; ///< OpenGL frame buffer object
unsigned int m_depthBuffer; ///< Optional depth buffer attached to the frame buffer
};
} // namespace priv
} // namespace sf
#endif // SFML_RENDERTEXTUREIMPLFBO_HPP

View file

@ -1,117 +1,117 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/GLCheck.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
RenderWindow::RenderWindow()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
RenderWindow::RenderWindow(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings)
{
// Don't call the base class constructor because it contains virtual function calls
create(mode, title, style, settings);
}
////////////////////////////////////////////////////////////
RenderWindow::RenderWindow(WindowHandle handle, const ContextSettings& settings)
{
// Don't call the base class constructor because it contains virtual function calls
create(handle, settings);
}
////////////////////////////////////////////////////////////
RenderWindow::~RenderWindow()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
bool RenderWindow::activate(bool active)
{
return setActive(active);
}
////////////////////////////////////////////////////////////
Vector2u RenderWindow::getSize() const
{
return Window::getSize();
}
////////////////////////////////////////////////////////////
Image RenderWindow::capture() const
{
Image image;
if (setActive())
{
int width = static_cast<int>(getSize().x);
int height = static_cast<int>(getSize().y);
// copy rows one by one and flip them (OpenGL's origin is bottom while SFML's origin is top)
std::vector<Uint8> pixels(width * height * 4);
for (int i = 0; i < height; ++i)
{
Uint8* ptr = &pixels[i * width * 4];
glCheck(glReadPixels(0, height - i - 1, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr));
}
image.create(width, height, &pixels[0]);
}
return image;
}
////////////////////////////////////////////////////////////
void RenderWindow::onCreate()
{
// Just initialize the render target part
RenderTarget::initialize();
}
////////////////////////////////////////////////////////////
void RenderWindow::onResize()
{
// Update the current view (recompute the viewport, which is stored in relative coordinates)
setView(getView());
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/RenderWindow.hpp>
#include <SFML/Graphics/GLCheck.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
RenderWindow::RenderWindow()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
RenderWindow::RenderWindow(VideoMode mode, const String& title, Uint32 style, const ContextSettings& settings)
{
// Don't call the base class constructor because it contains virtual function calls
create(mode, title, style, settings);
}
////////////////////////////////////////////////////////////
RenderWindow::RenderWindow(WindowHandle handle, const ContextSettings& settings)
{
// Don't call the base class constructor because it contains virtual function calls
create(handle, settings);
}
////////////////////////////////////////////////////////////
RenderWindow::~RenderWindow()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
bool RenderWindow::activate(bool active)
{
return setActive(active);
}
////////////////////////////////////////////////////////////
Vector2u RenderWindow::getSize() const
{
return Window::getSize();
}
////////////////////////////////////////////////////////////
Image RenderWindow::capture() const
{
Image image;
if (setActive())
{
int width = static_cast<int>(getSize().x);
int height = static_cast<int>(getSize().y);
// copy rows one by one and flip them (OpenGL's origin is bottom while SFML's origin is top)
std::vector<Uint8> pixels(width * height * 4);
for (int i = 0; i < height; ++i)
{
Uint8* ptr = &pixels[i * width * 4];
glCheck(glReadPixels(0, height - i - 1, width, 1, GL_RGBA, GL_UNSIGNED_BYTE, ptr));
}
image.create(width, height, &pixels[0]);
}
return image;
}
////////////////////////////////////////////////////////////
void RenderWindow::onCreate()
{
// Just initialize the render target part
RenderTarget::initialize();
}
////////////////////////////////////////////////////////////
void RenderWindow::onResize()
{
// Update the current view (recompute the viewport, which is stored in relative coordinates)
setView(getView());
}
} // namespace sf

File diff suppressed because it is too large Load diff

View file

@ -1,305 +1,305 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/Shape.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/System/Err.hpp>
#include <cmath>
namespace
{
// Compute the normal of a segment
sf::Vector2f computeNormal(const sf::Vector2f& p1, const sf::Vector2f& p2)
{
sf::Vector2f normal(p1.y - p2.y, p2.x - p1.x);
float length = std::sqrt(normal.x * normal.x + normal.y * normal.y);
if (length != 0.f)
normal /= length;
return normal;
}
// Compute the dot product of two vectors
float dotProduct(const sf::Vector2f& p1, const sf::Vector2f& p2)
{
return p1.x * p2.x + p1.y * p2.y;
}
}
namespace sf
{
////////////////////////////////////////////////////////////
Shape::~Shape()
{
}
////////////////////////////////////////////////////////////
void Shape::setTexture(const Texture* texture, bool resetRect)
{
if (texture)
{
// Recompute the texture area if requested, or if there was no texture & rect before
if (resetRect || (!m_texture && (m_textureRect == sf::IntRect())))
setTextureRect(IntRect(0, 0, texture->getSize().x, texture->getSize().y));
}
// Assign the new texture
m_texture = texture;
}
////////////////////////////////////////////////////////////
const Texture* Shape::getTexture() const
{
return m_texture;
}
////////////////////////////////////////////////////////////
void Shape::setTextureRect(const IntRect& rect)
{
m_textureRect = rect;
updateTexCoords();
}
////////////////////////////////////////////////////////////
const IntRect& Shape::getTextureRect() const
{
return m_textureRect;
}
////////////////////////////////////////////////////////////
void Shape::setFillColor(const Color& color)
{
m_fillColor = color;
updateFillColors();
}
////////////////////////////////////////////////////////////
const Color& Shape::getFillColor() const
{
return m_fillColor;
}
////////////////////////////////////////////////////////////
void Shape::setOutlineColor(const Color& color)
{
m_outlineColor = color;
updateOutlineColors();
}
////////////////////////////////////////////////////////////
const Color& Shape::getOutlineColor() const
{
return m_outlineColor;
}
////////////////////////////////////////////////////////////
void Shape::setOutlineThickness(float thickness)
{
m_outlineThickness = thickness;
update(); // recompute everything because the whole shape must be offset
}
////////////////////////////////////////////////////////////
float Shape::getOutlineThickness() const
{
return m_outlineThickness;
}
////////////////////////////////////////////////////////////
FloatRect Shape::getLocalBounds() const
{
return m_bounds;
}
////////////////////////////////////////////////////////////
FloatRect Shape::getGlobalBounds() const
{
return getTransform().transformRect(getLocalBounds());
}
////////////////////////////////////////////////////////////
Shape::Shape() :
m_texture (NULL),
m_textureRect (),
m_fillColor (255, 255, 255),
m_outlineColor (255, 255, 255),
m_outlineThickness(0),
m_vertices (TrianglesFan),
m_outlineVertices (TrianglesStrip),
m_insideBounds (),
m_bounds ()
{
}
////////////////////////////////////////////////////////////
void Shape::update()
{
// Get the total number of points of the shape
unsigned int count = getPointCount();
if (count < 3)
{
m_vertices.resize(0);
m_outlineVertices.resize(0);
return;
}
m_vertices.resize(count + 2); // + 2 for center and repeated first point
// Position
for (unsigned int i = 0; i < count; ++i)
m_vertices[i + 1].position = getPoint(i);
m_vertices[count + 1].position = m_vertices[1].position;
// Update the bounding rectangle
m_vertices[0] = m_vertices[1]; // so that the result of getBounds() is correct
m_insideBounds = m_vertices.getBounds();
// Compute the center and make it the first vertex
m_vertices[0].position.x = m_insideBounds.left + m_insideBounds.width / 2;
m_vertices[0].position.y = m_insideBounds.top + m_insideBounds.height / 2;
// Color
updateFillColors();
// Texture coordinates
updateTexCoords();
// Outline
updateOutline();
}
////////////////////////////////////////////////////////////
void Shape::draw(RenderTarget& target, RenderStates states) const
{
states.transform *= getTransform();
// Render the inside
states.texture = m_texture;
target.draw(m_vertices, states);
// Render the outline
if (m_outlineThickness != 0)
{
states.texture = NULL;
target.draw(m_outlineVertices, states);
}
}
////////////////////////////////////////////////////////////
void Shape::updateFillColors()
{
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
m_vertices[i].color = m_fillColor;
}
////////////////////////////////////////////////////////////
void Shape::updateTexCoords()
{
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
{
float xratio = m_insideBounds.width > 0 ? (m_vertices[i].position.x - m_insideBounds.left) / m_insideBounds.width : 0;
float yratio = m_insideBounds.height > 0 ? (m_vertices[i].position.y - m_insideBounds.top) / m_insideBounds.height : 0;
m_vertices[i].texCoords.x = m_textureRect.left + m_textureRect.width * xratio;
m_vertices[i].texCoords.y = m_textureRect.top + m_textureRect.height * yratio;
}
}
////////////////////////////////////////////////////////////
void Shape::updateOutline()
{
unsigned int count = m_vertices.getVertexCount() - 2;
m_outlineVertices.resize((count + 1) * 2);
for (unsigned int i = 0; i < count; ++i)
{
unsigned int index = i + 1;
// Get the two segments shared by the current point
Vector2f p0 = (i == 0) ? m_vertices[count].position : m_vertices[index - 1].position;
Vector2f p1 = m_vertices[index].position;
Vector2f p2 = m_vertices[index + 1].position;
// Compute their normal
Vector2f n1 = computeNormal(p0, p1);
Vector2f n2 = computeNormal(p1, p2);
// Make sure that the normals point towards the outside of the shape
// (this depends on the order in which the points were defined)
if (dotProduct(n1, m_vertices[0].position - p1) > 0)
n1 = -n1;
if (dotProduct(n2, m_vertices[0].position - p1) > 0)
n2 = -n2;
// Combine them to get the extrusion direction
float factor = 1.f + (n1.x * n2.x + n1.y * n2.y);
Vector2f normal = (n1 + n2) / factor;
// Update the outline points
m_outlineVertices[i * 2 + 0].position = p1;
m_outlineVertices[i * 2 + 1].position = p1 + normal * m_outlineThickness;
}
// Duplicate the first point at the end, to close the outline
m_outlineVertices[count * 2 + 0].position = m_outlineVertices[0].position;
m_outlineVertices[count * 2 + 1].position = m_outlineVertices[1].position;
// Update outline colors
updateOutlineColors();
// Update the shape's bounds
m_bounds = m_outlineVertices.getBounds();
}
////////////////////////////////////////////////////////////
void Shape::updateOutlineColors()
{
for (unsigned int i = 0; i < m_outlineVertices.getVertexCount(); ++i)
m_outlineVertices[i].color = m_outlineColor;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/Shape.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/System/Err.hpp>
#include <cmath>
namespace
{
// Compute the normal of a segment
sf::Vector2f computeNormal(const sf::Vector2f& p1, const sf::Vector2f& p2)
{
sf::Vector2f normal(p1.y - p2.y, p2.x - p1.x);
float length = std::sqrt(normal.x * normal.x + normal.y * normal.y);
if (length != 0.f)
normal /= length;
return normal;
}
// Compute the dot product of two vectors
float dotProduct(const sf::Vector2f& p1, const sf::Vector2f& p2)
{
return p1.x * p2.x + p1.y * p2.y;
}
}
namespace sf
{
////////////////////////////////////////////////////////////
Shape::~Shape()
{
}
////////////////////////////////////////////////////////////
void Shape::setTexture(const Texture* texture, bool resetRect)
{
if (texture)
{
// Recompute the texture area if requested, or if there was no texture & rect before
if (resetRect || (!m_texture && (m_textureRect == sf::IntRect())))
setTextureRect(IntRect(0, 0, texture->getSize().x, texture->getSize().y));
}
// Assign the new texture
m_texture = texture;
}
////////////////////////////////////////////////////////////
const Texture* Shape::getTexture() const
{
return m_texture;
}
////////////////////////////////////////////////////////////
void Shape::setTextureRect(const IntRect& rect)
{
m_textureRect = rect;
updateTexCoords();
}
////////////////////////////////////////////////////////////
const IntRect& Shape::getTextureRect() const
{
return m_textureRect;
}
////////////////////////////////////////////////////////////
void Shape::setFillColor(const Color& color)
{
m_fillColor = color;
updateFillColors();
}
////////////////////////////////////////////////////////////
const Color& Shape::getFillColor() const
{
return m_fillColor;
}
////////////////////////////////////////////////////////////
void Shape::setOutlineColor(const Color& color)
{
m_outlineColor = color;
updateOutlineColors();
}
////////////////////////////////////////////////////////////
const Color& Shape::getOutlineColor() const
{
return m_outlineColor;
}
////////////////////////////////////////////////////////////
void Shape::setOutlineThickness(float thickness)
{
m_outlineThickness = thickness;
update(); // recompute everything because the whole shape must be offset
}
////////////////////////////////////////////////////////////
float Shape::getOutlineThickness() const
{
return m_outlineThickness;
}
////////////////////////////////////////////////////////////
FloatRect Shape::getLocalBounds() const
{
return m_bounds;
}
////////////////////////////////////////////////////////////
FloatRect Shape::getGlobalBounds() const
{
return getTransform().transformRect(getLocalBounds());
}
////////////////////////////////////////////////////////////
Shape::Shape() :
m_texture (NULL),
m_textureRect (),
m_fillColor (255, 255, 255),
m_outlineColor (255, 255, 255),
m_outlineThickness(0),
m_vertices (TrianglesFan),
m_outlineVertices (TrianglesStrip),
m_insideBounds (),
m_bounds ()
{
}
////////////////////////////////////////////////////////////
void Shape::update()
{
// Get the total number of points of the shape
unsigned int count = getPointCount();
if (count < 3)
{
m_vertices.resize(0);
m_outlineVertices.resize(0);
return;
}
m_vertices.resize(count + 2); // + 2 for center and repeated first point
// Position
for (unsigned int i = 0; i < count; ++i)
m_vertices[i + 1].position = getPoint(i);
m_vertices[count + 1].position = m_vertices[1].position;
// Update the bounding rectangle
m_vertices[0] = m_vertices[1]; // so that the result of getBounds() is correct
m_insideBounds = m_vertices.getBounds();
// Compute the center and make it the first vertex
m_vertices[0].position.x = m_insideBounds.left + m_insideBounds.width / 2;
m_vertices[0].position.y = m_insideBounds.top + m_insideBounds.height / 2;
// Color
updateFillColors();
// Texture coordinates
updateTexCoords();
// Outline
updateOutline();
}
////////////////////////////////////////////////////////////
void Shape::draw(RenderTarget& target, RenderStates states) const
{
states.transform *= getTransform();
// Render the inside
states.texture = m_texture;
target.draw(m_vertices, states);
// Render the outline
if (m_outlineThickness != 0)
{
states.texture = NULL;
target.draw(m_outlineVertices, states);
}
}
////////////////////////////////////////////////////////////
void Shape::updateFillColors()
{
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
m_vertices[i].color = m_fillColor;
}
////////////////////////////////////////////////////////////
void Shape::updateTexCoords()
{
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
{
float xratio = m_insideBounds.width > 0 ? (m_vertices[i].position.x - m_insideBounds.left) / m_insideBounds.width : 0;
float yratio = m_insideBounds.height > 0 ? (m_vertices[i].position.y - m_insideBounds.top) / m_insideBounds.height : 0;
m_vertices[i].texCoords.x = m_textureRect.left + m_textureRect.width * xratio;
m_vertices[i].texCoords.y = m_textureRect.top + m_textureRect.height * yratio;
}
}
////////////////////////////////////////////////////////////
void Shape::updateOutline()
{
unsigned int count = m_vertices.getVertexCount() - 2;
m_outlineVertices.resize((count + 1) * 2);
for (unsigned int i = 0; i < count; ++i)
{
unsigned int index = i + 1;
// Get the two segments shared by the current point
Vector2f p0 = (i == 0) ? m_vertices[count].position : m_vertices[index - 1].position;
Vector2f p1 = m_vertices[index].position;
Vector2f p2 = m_vertices[index + 1].position;
// Compute their normal
Vector2f n1 = computeNormal(p0, p1);
Vector2f n2 = computeNormal(p1, p2);
// Make sure that the normals point towards the outside of the shape
// (this depends on the order in which the points were defined)
if (dotProduct(n1, m_vertices[0].position - p1) > 0)
n1 = -n1;
if (dotProduct(n2, m_vertices[0].position - p1) > 0)
n2 = -n2;
// Combine them to get the extrusion direction
float factor = 1.f + (n1.x * n2.x + n1.y * n2.y);
Vector2f normal = (n1 + n2) / factor;
// Update the outline points
m_outlineVertices[i * 2 + 0].position = p1;
m_outlineVertices[i * 2 + 1].position = p1 + normal * m_outlineThickness;
}
// Duplicate the first point at the end, to close the outline
m_outlineVertices[count * 2 + 0].position = m_outlineVertices[0].position;
m_outlineVertices[count * 2 + 1].position = m_outlineVertices[1].position;
// Update outline colors
updateOutlineColors();
// Update the shape's bounds
m_bounds = m_outlineVertices.getBounds();
}
////////////////////////////////////////////////////////////
void Shape::updateOutlineColors()
{
for (unsigned int i = 0; i < m_outlineVertices.getVertexCount(); ++i)
m_outlineVertices[i].color = m_outlineColor;
}
} // namespace sf

View file

@ -1,174 +1,174 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/Sprite.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <cstdlib>
namespace sf
{
////////////////////////////////////////////////////////////
Sprite::Sprite() :
m_texture (NULL),
m_textureRect()
{
}
////////////////////////////////////////////////////////////
Sprite::Sprite(const Texture& texture) :
m_texture (NULL),
m_textureRect()
{
setTexture(texture);
}
////////////////////////////////////////////////////////////
Sprite::Sprite(const Texture& texture, const IntRect& rectangle) :
m_texture (NULL),
m_textureRect()
{
setTexture(texture);
setTextureRect(rectangle);
}
////////////////////////////////////////////////////////////
void Sprite::setTexture(const Texture& texture, bool resetRect)
{
// Recompute the texture area if requested, or if there was no valid texture & rect before
if (resetRect || (!m_texture && (m_textureRect == sf::IntRect())))
setTextureRect(IntRect(0, 0, texture.getSize().x, texture.getSize().y));
// Assign the new texture
m_texture = &texture;
}
////////////////////////////////////////////////////////////
void Sprite::setTextureRect(const IntRect& rectangle)
{
if (rectangle != m_textureRect)
{
m_textureRect = rectangle;
updatePositions();
updateTexCoords();
}
}
////////////////////////////////////////////////////////////
void Sprite::setColor(const Color& color)
{
// Update the vertices' color
m_vertices[0].color = color;
m_vertices[1].color = color;
m_vertices[2].color = color;
m_vertices[3].color = color;
}
////////////////////////////////////////////////////////////
const Texture* Sprite::getTexture() const
{
return m_texture;
}
////////////////////////////////////////////////////////////
const IntRect& Sprite::getTextureRect() const
{
return m_textureRect;
}
////////////////////////////////////////////////////////////
const Color& Sprite::getColor() const
{
return m_vertices[0].color;
}
////////////////////////////////////////////////////////////
FloatRect Sprite::getLocalBounds() const
{
float width = static_cast<float>(std::abs(m_textureRect.width));
float height = static_cast<float>(std::abs(m_textureRect.height));
return FloatRect(0.f, 0.f, width, height);
}
////////////////////////////////////////////////////////////
FloatRect Sprite::getGlobalBounds() const
{
return getTransform().transformRect(getLocalBounds());
}
////////////////////////////////////////////////////////////
void Sprite::draw(RenderTarget& target, RenderStates states) const
{
if (m_texture)
{
states.transform *= getTransform();
states.texture = m_texture;
target.draw(m_vertices, 4, TrianglesStrip, states);
}
}
////////////////////////////////////////////////////////////
void Sprite::updatePositions()
{
FloatRect bounds = getLocalBounds();
m_vertices[0].position = Vector2f(0, 0);
m_vertices[1].position = Vector2f(0, bounds.height);
m_vertices[2].position = Vector2f(bounds.width, 0);
m_vertices[3].position = Vector2f(bounds.width, bounds.height);
}
////////////////////////////////////////////////////////////
void Sprite::updateTexCoords()
{
float left = static_cast<float>(m_textureRect.left);
float right = left + m_textureRect.width;
float top = static_cast<float>(m_textureRect.top);
float bottom = top + m_textureRect.height;
m_vertices[0].texCoords = Vector2f(left, top);
m_vertices[1].texCoords = Vector2f(left, bottom);
m_vertices[2].texCoords = Vector2f(right, top);
m_vertices[3].texCoords = Vector2f(right, bottom);
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/Sprite.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <cstdlib>
namespace sf
{
////////////////////////////////////////////////////////////
Sprite::Sprite() :
m_texture (NULL),
m_textureRect()
{
}
////////////////////////////////////////////////////////////
Sprite::Sprite(const Texture& texture) :
m_texture (NULL),
m_textureRect()
{
setTexture(texture);
}
////////////////////////////////////////////////////////////
Sprite::Sprite(const Texture& texture, const IntRect& rectangle) :
m_texture (NULL),
m_textureRect()
{
setTexture(texture);
setTextureRect(rectangle);
}
////////////////////////////////////////////////////////////
void Sprite::setTexture(const Texture& texture, bool resetRect)
{
// Recompute the texture area if requested, or if there was no valid texture & rect before
if (resetRect || (!m_texture && (m_textureRect == sf::IntRect())))
setTextureRect(IntRect(0, 0, texture.getSize().x, texture.getSize().y));
// Assign the new texture
m_texture = &texture;
}
////////////////////////////////////////////////////////////
void Sprite::setTextureRect(const IntRect& rectangle)
{
if (rectangle != m_textureRect)
{
m_textureRect = rectangle;
updatePositions();
updateTexCoords();
}
}
////////////////////////////////////////////////////////////
void Sprite::setColor(const Color& color)
{
// Update the vertices' color
m_vertices[0].color = color;
m_vertices[1].color = color;
m_vertices[2].color = color;
m_vertices[3].color = color;
}
////////////////////////////////////////////////////////////
const Texture* Sprite::getTexture() const
{
return m_texture;
}
////////////////////////////////////////////////////////////
const IntRect& Sprite::getTextureRect() const
{
return m_textureRect;
}
////////////////////////////////////////////////////////////
const Color& Sprite::getColor() const
{
return m_vertices[0].color;
}
////////////////////////////////////////////////////////////
FloatRect Sprite::getLocalBounds() const
{
float width = static_cast<float>(std::abs(m_textureRect.width));
float height = static_cast<float>(std::abs(m_textureRect.height));
return FloatRect(0.f, 0.f, width, height);
}
////////////////////////////////////////////////////////////
FloatRect Sprite::getGlobalBounds() const
{
return getTransform().transformRect(getLocalBounds());
}
////////////////////////////////////////////////////////////
void Sprite::draw(RenderTarget& target, RenderStates states) const
{
if (m_texture)
{
states.transform *= getTransform();
states.texture = m_texture;
target.draw(m_vertices, 4, TrianglesStrip, states);
}
}
////////////////////////////////////////////////////////////
void Sprite::updatePositions()
{
FloatRect bounds = getLocalBounds();
m_vertices[0].position = Vector2f(0, 0);
m_vertices[1].position = Vector2f(0, bounds.height);
m_vertices[2].position = Vector2f(bounds.width, 0);
m_vertices[3].position = Vector2f(bounds.width, bounds.height);
}
////////////////////////////////////////////////////////////
void Sprite::updateTexCoords()
{
float left = static_cast<float>(m_textureRect.left);
float right = left + m_textureRect.width;
float top = static_cast<float>(m_textureRect.top);
float bottom = top + m_textureRect.height;
m_vertices[0].texCoords = Vector2f(left, top);
m_vertices[1].texCoords = Vector2f(left, bottom);
m_vertices[2].texCoords = Vector2f(right, top);
m_vertices[3].texCoords = Vector2f(right, bottom);
}
} // namespace sf

View file

@ -1,411 +1,411 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/Text.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <cmath>
namespace sf
{
////////////////////////////////////////////////////////////
Text::Text() :
m_string (),
m_font (NULL),
m_characterSize (30),
m_style (Regular),
m_color (255, 255, 255),
m_vertices (Triangles),
m_bounds (),
m_geometryNeedUpdate(false)
{
}
////////////////////////////////////////////////////////////
Text::Text(const String& string, const Font& font, unsigned int characterSize) :
m_string (string),
m_font (&font),
m_characterSize (characterSize),
m_style (Regular),
m_color (255, 255, 255),
m_vertices (Triangles),
m_bounds (),
m_geometryNeedUpdate(true)
{
}
////////////////////////////////////////////////////////////
void Text::setString(const String& string)
{
if (m_string != string)
{
m_string = string;
m_geometryNeedUpdate = true;
}
}
////////////////////////////////////////////////////////////
void Text::setFont(const Font& font)
{
if (m_font != &font)
{
m_font = &font;
m_geometryNeedUpdate = true;
}
}
////////////////////////////////////////////////////////////
void Text::setCharacterSize(unsigned int size)
{
if (m_characterSize != size)
{
m_characterSize = size;
m_geometryNeedUpdate = true;
}
}
////////////////////////////////////////////////////////////
void Text::setStyle(Uint32 style)
{
if (m_style != style)
{
m_style = style;
m_geometryNeedUpdate = true;
}
}
////////////////////////////////////////////////////////////
void Text::setColor(const Color& color)
{
if (color != m_color)
{
m_color = color;
// Change vertex colors directly, no need to update whole geometry
// (if geometry is updated anyway, we can skip this step)
if (!m_geometryNeedUpdate)
{
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
m_vertices[i].color = m_color;
}
}
}
////////////////////////////////////////////////////////////
const String& Text::getString() const
{
return m_string;
}
////////////////////////////////////////////////////////////
const Font* Text::getFont() const
{
return m_font;
}
////////////////////////////////////////////////////////////
unsigned int Text::getCharacterSize() const
{
return m_characterSize;
}
////////////////////////////////////////////////////////////
Uint32 Text::getStyle() const
{
return m_style;
}
////////////////////////////////////////////////////////////
const Color& Text::getColor() const
{
return m_color;
}
////////////////////////////////////////////////////////////
Vector2f Text::findCharacterPos(std::size_t index) const
{
// Make sure that we have a valid font
if (!m_font)
return Vector2f();
// Adjust the index if it's out of range
if (index > m_string.getSize())
index = m_string.getSize();
// Precompute the variables needed by the algorithm
bool bold = (m_style & Bold) != 0;
float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
// Compute the position
Vector2f position;
Uint32 prevChar = 0;
for (std::size_t i = 0; i < index; ++i)
{
Uint32 curChar = m_string[i];
// Apply the kerning offset
position.x += static_cast<float>(m_font->getKerning(prevChar, curChar, m_characterSize));
prevChar = curChar;
// Handle special characters
switch (curChar)
{
case ' ' : position.x += hspace; continue;
case '\t' : position.x += hspace * 4; continue;
case '\n' : position.y += vspace; position.x = 0; continue;
}
// For regular characters, add the advance offset of the glyph
position.x += static_cast<float>(m_font->getGlyph(curChar, m_characterSize, bold).advance);
}
// Transform the position to global coordinates
position = getTransform().transformPoint(position);
return position;
}
////////////////////////////////////////////////////////////
FloatRect Text::getLocalBounds() const
{
ensureGeometryUpdate();
return m_bounds;
}
////////////////////////////////////////////////////////////
FloatRect Text::getGlobalBounds() const
{
return getTransform().transformRect(getLocalBounds());
}
////////////////////////////////////////////////////////////
void Text::draw(RenderTarget& target, RenderStates states) const
{
if (m_font)
{
ensureGeometryUpdate();
states.transform *= getTransform();
states.texture = &m_font->getTexture(m_characterSize);
target.draw(m_vertices, states);
}
}
////////////////////////////////////////////////////////////
void Text::ensureGeometryUpdate() const
{
// Do nothing, if geometry has not changed
if (!m_geometryNeedUpdate)
return;
// Mark geometry as updated
m_geometryNeedUpdate = false;
// Clear the previous geometry
m_vertices.clear();
m_bounds = FloatRect();
// No font: nothing to draw
if (!m_font)
return;
// No text: nothing to draw
if (m_string.isEmpty())
return;
// Compute values related to the text style
bool bold = (m_style & Bold) != 0;
bool underlined = (m_style & Underlined) != 0;
bool strikeThrough = (m_style & StrikeThrough) != 0;
float italic = (m_style & Italic) ? 0.208f : 0.f; // 12 degrees
float underlineOffset = m_font->getUnderlinePosition(m_characterSize);
float underlineThickness = m_font->getUnderlineThickness(m_characterSize);
// Compute the location of the strike through dynamically
// We use the center point of the lowercase 'x' glyph as the reference
// We reuse the underline thickness as the thickness of the strike through as well
FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, bold).bounds;
float strikeThroughOffset = xBounds.top + xBounds.height / 2.f;
// Precompute the variables needed by the algorithm
float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
float x = 0.f;
float y = static_cast<float>(m_characterSize);
// Create one quad for each character
float minX = static_cast<float>(m_characterSize);
float minY = static_cast<float>(m_characterSize);
float maxX = 0.f;
float maxY = 0.f;
Uint32 prevChar = 0;
for (std::size_t i = 0; i < m_string.getSize(); ++i)
{
Uint32 curChar = m_string[i];
// Apply the kerning offset
x += static_cast<float>(m_font->getKerning(prevChar, curChar, m_characterSize));
prevChar = curChar;
// If we're using the underlined style and there's a new line, draw a line
if (underlined && (curChar == L'\n'))
{
float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f);
float bottom = top + std::floor(underlineThickness + 0.5f);
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
}
// If we're using the strike through style and there's a new line, draw a line across all characters
if (strikeThrough && (curChar == L'\n'))
{
float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f);
float bottom = top + std::floor(underlineThickness + 0.5f);
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
}
// Handle special characters
if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n'))
{
// Update the current bounds (min coordinates)
minX = std::min(minX, x);
minY = std::min(minY, y);
switch (curChar)
{
case ' ' : x += hspace; break;
case '\t' : x += hspace * 4; break;
case '\n' : y += vspace; x = 0; break;
}
// Update the current bounds (max coordinates)
maxX = std::max(maxX, x);
maxY = std::max(maxY, y);
// Next glyph, no need to create a quad for whitespace
continue;
}
// Extract the current glyph's description
const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, bold);
float left = glyph.bounds.left;
float top = glyph.bounds.top;
float right = glyph.bounds.left + glyph.bounds.width;
float bottom = glyph.bounds.top + glyph.bounds.height;
float u1 = static_cast<float>(glyph.textureRect.left);
float v1 = static_cast<float>(glyph.textureRect.top);
float u2 = static_cast<float>(glyph.textureRect.left + glyph.textureRect.width);
float v2 = static_cast<float>(glyph.textureRect.top + glyph.textureRect.height);
// Add a quad for the current character
m_vertices.append(Vertex(Vector2f(x + left - italic * top, y + top), m_color, Vector2f(u1, v1)));
m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1)));
m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2)));
m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2)));
m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1)));
m_vertices.append(Vertex(Vector2f(x + right - italic * bottom, y + bottom), m_color, Vector2f(u2, v2)));
// Update the current bounds
minX = std::min(minX, x + left - italic * bottom);
maxX = std::max(maxX, x + right - italic * top);
minY = std::min(minY, y + top);
maxY = std::max(maxY, y + bottom);
// Advance to the next character
x += glyph.advance;
}
// If we're using the underlined style, add the last line
if (underlined)
{
float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f);
float bottom = top + std::floor(underlineThickness + 0.5f);
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
}
// If we're using the strike through style, add the last line across all characters
if (strikeThrough)
{
float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f);
float bottom = top + std::floor(underlineThickness + 0.5f);
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
}
// Update the bounding rectangle
m_bounds.left = minX;
m_bounds.top = minY;
m_bounds.width = maxX - minX;
m_bounds.height = maxY - minY;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/Text.hpp>
#include <SFML/Graphics/Texture.hpp>
#include <SFML/Graphics/RenderTarget.hpp>
#include <cmath>
namespace sf
{
////////////////////////////////////////////////////////////
Text::Text() :
m_string (),
m_font (NULL),
m_characterSize (30),
m_style (Regular),
m_color (255, 255, 255),
m_vertices (Triangles),
m_bounds (),
m_geometryNeedUpdate(false)
{
}
////////////////////////////////////////////////////////////
Text::Text(const String& string, const Font& font, unsigned int characterSize) :
m_string (string),
m_font (&font),
m_characterSize (characterSize),
m_style (Regular),
m_color (255, 255, 255),
m_vertices (Triangles),
m_bounds (),
m_geometryNeedUpdate(true)
{
}
////////////////////////////////////////////////////////////
void Text::setString(const String& string)
{
if (m_string != string)
{
m_string = string;
m_geometryNeedUpdate = true;
}
}
////////////////////////////////////////////////////////////
void Text::setFont(const Font& font)
{
if (m_font != &font)
{
m_font = &font;
m_geometryNeedUpdate = true;
}
}
////////////////////////////////////////////////////////////
void Text::setCharacterSize(unsigned int size)
{
if (m_characterSize != size)
{
m_characterSize = size;
m_geometryNeedUpdate = true;
}
}
////////////////////////////////////////////////////////////
void Text::setStyle(Uint32 style)
{
if (m_style != style)
{
m_style = style;
m_geometryNeedUpdate = true;
}
}
////////////////////////////////////////////////////////////
void Text::setColor(const Color& color)
{
if (color != m_color)
{
m_color = color;
// Change vertex colors directly, no need to update whole geometry
// (if geometry is updated anyway, we can skip this step)
if (!m_geometryNeedUpdate)
{
for (unsigned int i = 0; i < m_vertices.getVertexCount(); ++i)
m_vertices[i].color = m_color;
}
}
}
////////////////////////////////////////////////////////////
const String& Text::getString() const
{
return m_string;
}
////////////////////////////////////////////////////////////
const Font* Text::getFont() const
{
return m_font;
}
////////////////////////////////////////////////////////////
unsigned int Text::getCharacterSize() const
{
return m_characterSize;
}
////////////////////////////////////////////////////////////
Uint32 Text::getStyle() const
{
return m_style;
}
////////////////////////////////////////////////////////////
const Color& Text::getColor() const
{
return m_color;
}
////////////////////////////////////////////////////////////
Vector2f Text::findCharacterPos(std::size_t index) const
{
// Make sure that we have a valid font
if (!m_font)
return Vector2f();
// Adjust the index if it's out of range
if (index > m_string.getSize())
index = m_string.getSize();
// Precompute the variables needed by the algorithm
bool bold = (m_style & Bold) != 0;
float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
// Compute the position
Vector2f position;
Uint32 prevChar = 0;
for (std::size_t i = 0; i < index; ++i)
{
Uint32 curChar = m_string[i];
// Apply the kerning offset
position.x += static_cast<float>(m_font->getKerning(prevChar, curChar, m_characterSize));
prevChar = curChar;
// Handle special characters
switch (curChar)
{
case ' ': position.x += hspace; continue;
case '\t': position.x += hspace * 4; continue;
case '\n': position.y += vspace; position.x = 0; continue;
}
// For regular characters, add the advance offset of the glyph
position.x += static_cast<float>(m_font->getGlyph(curChar, m_characterSize, bold).advance);
}
// Transform the position to global coordinates
position = getTransform().transformPoint(position);
return position;
}
////////////////////////////////////////////////////////////
FloatRect Text::getLocalBounds() const
{
ensureGeometryUpdate();
return m_bounds;
}
////////////////////////////////////////////////////////////
FloatRect Text::getGlobalBounds() const
{
return getTransform().transformRect(getLocalBounds());
}
////////////////////////////////////////////////////////////
void Text::draw(RenderTarget& target, RenderStates states) const
{
if (m_font)
{
ensureGeometryUpdate();
states.transform *= getTransform();
states.texture = &m_font->getTexture(m_characterSize);
target.draw(m_vertices, states);
}
}
////////////////////////////////////////////////////////////
void Text::ensureGeometryUpdate() const
{
// Do nothing, if geometry has not changed
if (!m_geometryNeedUpdate)
return;
// Mark geometry as updated
m_geometryNeedUpdate = false;
// Clear the previous geometry
m_vertices.clear();
m_bounds = FloatRect();
// No font: nothing to draw
if (!m_font)
return;
// No text: nothing to draw
if (m_string.isEmpty())
return;
// Compute values related to the text style
bool bold = (m_style & Bold) != 0;
bool underlined = (m_style & Underlined) != 0;
bool strikeThrough = (m_style & StrikeThrough) != 0;
float italic = (m_style & Italic) ? 0.208f : 0.f; // 12 degrees
float underlineOffset = m_font->getUnderlinePosition(m_characterSize);
float underlineThickness = m_font->getUnderlineThickness(m_characterSize);
// Compute the location of the strike through dynamically
// We use the center point of the lowercase 'x' glyph as the reference
// We reuse the underline thickness as the thickness of the strike through as well
FloatRect xBounds = m_font->getGlyph(L'x', m_characterSize, bold).bounds;
float strikeThroughOffset = xBounds.top + xBounds.height / 2.f;
// Precompute the variables needed by the algorithm
float hspace = static_cast<float>(m_font->getGlyph(L' ', m_characterSize, bold).advance);
float vspace = static_cast<float>(m_font->getLineSpacing(m_characterSize));
float x = 0.f;
float y = static_cast<float>(m_characterSize);
// Create one quad for each character
float minX = static_cast<float>(m_characterSize);
float minY = static_cast<float>(m_characterSize);
float maxX = 0.f;
float maxY = 0.f;
Uint32 prevChar = 0;
for (std::size_t i = 0; i < m_string.getSize(); ++i)
{
Uint32 curChar = m_string[i];
// Apply the kerning offset
x += static_cast<float>(m_font->getKerning(prevChar, curChar, m_characterSize));
prevChar = curChar;
// If we're using the underlined style and there's a new line, draw a line
if (underlined && (curChar == L'\n'))
{
float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f);
float bottom = top + std::floor(underlineThickness + 0.5f);
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
}
// If we're using the strike through style and there's a new line, draw a line across all characters
if (strikeThrough && (curChar == L'\n'))
{
float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f);
float bottom = top + std::floor(underlineThickness + 0.5f);
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
}
// Handle special characters
if ((curChar == ' ') || (curChar == '\t') || (curChar == '\n'))
{
// Update the current bounds (min coordinates)
minX = std::min(minX, x);
minY = std::min(minY, y);
switch (curChar)
{
case ' ': x += hspace; break;
case '\t': x += hspace * 4; break;
case '\n': y += vspace; x = 0; break;
}
// Update the current bounds (max coordinates)
maxX = std::max(maxX, x);
maxY = std::max(maxY, y);
// Next glyph, no need to create a quad for whitespace
continue;
}
// Extract the current glyph's description
const Glyph& glyph = m_font->getGlyph(curChar, m_characterSize, bold);
float left = glyph.bounds.left;
float top = glyph.bounds.top;
float right = glyph.bounds.left + glyph.bounds.width;
float bottom = glyph.bounds.top + glyph.bounds.height;
float u1 = static_cast<float>(glyph.textureRect.left);
float v1 = static_cast<float>(glyph.textureRect.top);
float u2 = static_cast<float>(glyph.textureRect.left + glyph.textureRect.width);
float v2 = static_cast<float>(glyph.textureRect.top + glyph.textureRect.height);
// Add a quad for the current character
m_vertices.append(Vertex(Vector2f(x + left - italic * top, y + top), m_color, Vector2f(u1, v1)));
m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1)));
m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2)));
m_vertices.append(Vertex(Vector2f(x + left - italic * bottom, y + bottom), m_color, Vector2f(u1, v2)));
m_vertices.append(Vertex(Vector2f(x + right - italic * top, y + top), m_color, Vector2f(u2, v1)));
m_vertices.append(Vertex(Vector2f(x + right - italic * bottom, y + bottom), m_color, Vector2f(u2, v2)));
// Update the current bounds
minX = std::min(minX, x + left - italic * bottom);
maxX = std::max(maxX, x + right - italic * top);
minY = std::min(minY, y + top);
maxY = std::max(maxY, y + bottom);
// Advance to the next character
x += glyph.advance;
}
// If we're using the underlined style, add the last line
if (underlined)
{
float top = std::floor(y + underlineOffset - (underlineThickness / 2) + 0.5f);
float bottom = top + std::floor(underlineThickness + 0.5f);
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
}
// If we're using the strike through style, add the last line across all characters
if (strikeThrough)
{
float top = std::floor(y + strikeThroughOffset - (underlineThickness / 2) + 0.5f);
float bottom = top + std::floor(underlineThickness + 0.5f);
m_vertices.append(Vertex(Vector2f(0, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(0, bottom), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, top), m_color, Vector2f(1, 1)));
m_vertices.append(Vertex(Vector2f(x, bottom), m_color, Vector2f(1, 1)));
}
// Update the bounding rectangle
m_bounds.left = minX;
m_bounds.top = minY;
m_bounds.width = maxX - minX;
m_bounds.height = maxY - minY;
}
} // namespace sf

View file

@ -41,7 +41,7 @@ namespace priv
////////////////////////////////////////////////////////////
class TextureSaver
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
@ -59,7 +59,7 @@ public :
////////////////////////////////////////////////////////////
~TextureSaver();
private :
private:
////////////////////////////////////////////////////////////
// Member data

View file

@ -1,240 +1,240 @@
////////////////////////////////////////////////////////////
//
// 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/Graphics/View.hpp>
#include <cmath>
namespace sf
{
////////////////////////////////////////////////////////////
View::View() :
m_center (),
m_size (),
m_rotation (0),
m_viewport (0, 0, 1, 1),
m_transformUpdated (false),
m_invTransformUpdated(false)
{
reset(FloatRect(0, 0, 1000, 1000));
}
////////////////////////////////////////////////////////////
View::View(const FloatRect& rectangle) :
m_center (),
m_size (),
m_rotation (0),
m_viewport (0, 0, 1, 1),
m_transformUpdated (false),
m_invTransformUpdated(false)
{
reset(rectangle);
}
////////////////////////////////////////////////////////////
View::View(const Vector2f& center, const Vector2f& size) :
m_center (center),
m_size (size),
m_rotation (0),
m_viewport (0, 0, 1, 1),
m_transformUpdated (false),
m_invTransformUpdated(false)
{
}
////////////////////////////////////////////////////////////
void View::setCenter(float x, float y)
{
m_center.x = x;
m_center.y = y;
m_transformUpdated = false;
m_invTransformUpdated = false;
}
////////////////////////////////////////////////////////////
void View::setCenter(const Vector2f& center)
{
setCenter(center.x, center.y);
}
////////////////////////////////////////////////////////////
void View::setSize(float width, float height)
{
m_size.x = width;
m_size.y = height;
m_transformUpdated = false;
m_invTransformUpdated = false;
}
////////////////////////////////////////////////////////////
void View::setSize(const Vector2f& size)
{
setSize(size.x, size.y);
}
////////////////////////////////////////////////////////////
void View::setRotation(float angle)
{
m_rotation = static_cast<float>(fmod(angle, 360));
if (m_rotation < 0)
m_rotation += 360.f;
m_transformUpdated = false;
m_invTransformUpdated = false;
}
////////////////////////////////////////////////////////////
void View::setViewport(const FloatRect& viewport)
{
m_viewport = viewport;
}
////////////////////////////////////////////////////////////
void View::reset(const FloatRect& rectangle)
{
m_center.x = rectangle.left + rectangle.width / 2.f;
m_center.y = rectangle.top + rectangle.height / 2.f;
m_size.x = rectangle.width;
m_size.y = rectangle.height;
m_rotation = 0;
m_transformUpdated = false;
m_invTransformUpdated = false;
}
////////////////////////////////////////////////////////////
const Vector2f& View::getCenter() const
{
return m_center;
}
////////////////////////////////////////////////////////////
const Vector2f& View::getSize() const
{
return m_size;
}
////////////////////////////////////////////////////////////
float View::getRotation() const
{
return m_rotation;
}
////////////////////////////////////////////////////////////
const FloatRect& View::getViewport() const
{
return m_viewport;
}
////////////////////////////////////////////////////////////
void View::move(float offsetX, float offsetY)
{
setCenter(m_center.x + offsetX, m_center.y + offsetY);
}
////////////////////////////////////////////////////////////
void View::move(const Vector2f& offset)
{
setCenter(m_center + offset);
}
////////////////////////////////////////////////////////////
void View::rotate(float angle)
{
setRotation(m_rotation + angle);
}
////////////////////////////////////////////////////////////
void View::zoom(float factor)
{
setSize(m_size.x * factor, m_size.y * factor);
}
////////////////////////////////////////////////////////////
const Transform& View::getTransform() const
{
// Recompute the matrix if needed
if (!m_transformUpdated)
{
// Rotation components
float angle = m_rotation * 3.141592654f / 180.f;
float cosine = static_cast<float>(std::cos(angle));
float sine = static_cast<float>(std::sin(angle));
float tx = -m_center.x * cosine - m_center.y * sine + m_center.x;
float ty = m_center.x * sine - m_center.y * cosine + m_center.y;
// Projection components
float a = 2.f / m_size.x;
float b = -2.f / m_size.y;
float c = -a * m_center.x;
float d = -b * m_center.y;
// Rebuild the projection matrix
m_transform = Transform( a * cosine, a * sine, a * tx + c,
-b * sine, b * cosine, b * ty + d,
0.f, 0.f, 1.f);
m_transformUpdated = true;
}
return m_transform;
}
////////////////////////////////////////////////////////////
const Transform& View::getInverseTransform() const
{
// Recompute the matrix if needed
if (!m_invTransformUpdated)
{
m_inverseTransform = getTransform().getInverse();
m_invTransformUpdated = true;
}
return m_inverseTransform;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Graphics/View.hpp>
#include <cmath>
namespace sf
{
////////////////////////////////////////////////////////////
View::View() :
m_center (),
m_size (),
m_rotation (0),
m_viewport (0, 0, 1, 1),
m_transformUpdated (false),
m_invTransformUpdated(false)
{
reset(FloatRect(0, 0, 1000, 1000));
}
////////////////////////////////////////////////////////////
View::View(const FloatRect& rectangle) :
m_center (),
m_size (),
m_rotation (0),
m_viewport (0, 0, 1, 1),
m_transformUpdated (false),
m_invTransformUpdated(false)
{
reset(rectangle);
}
////////////////////////////////////////////////////////////
View::View(const Vector2f& center, const Vector2f& size) :
m_center (center),
m_size (size),
m_rotation (0),
m_viewport (0, 0, 1, 1),
m_transformUpdated (false),
m_invTransformUpdated(false)
{
}
////////////////////////////////////////////////////////////
void View::setCenter(float x, float y)
{
m_center.x = x;
m_center.y = y;
m_transformUpdated = false;
m_invTransformUpdated = false;
}
////////////////////////////////////////////////////////////
void View::setCenter(const Vector2f& center)
{
setCenter(center.x, center.y);
}
////////////////////////////////////////////////////////////
void View::setSize(float width, float height)
{
m_size.x = width;
m_size.y = height;
m_transformUpdated = false;
m_invTransformUpdated = false;
}
////////////////////////////////////////////////////////////
void View::setSize(const Vector2f& size)
{
setSize(size.x, size.y);
}
////////////////////////////////////////////////////////////
void View::setRotation(float angle)
{
m_rotation = static_cast<float>(fmod(angle, 360));
if (m_rotation < 0)
m_rotation += 360.f;
m_transformUpdated = false;
m_invTransformUpdated = false;
}
////////////////////////////////////////////////////////////
void View::setViewport(const FloatRect& viewport)
{
m_viewport = viewport;
}
////////////////////////////////////////////////////////////
void View::reset(const FloatRect& rectangle)
{
m_center.x = rectangle.left + rectangle.width / 2.f;
m_center.y = rectangle.top + rectangle.height / 2.f;
m_size.x = rectangle.width;
m_size.y = rectangle.height;
m_rotation = 0;
m_transformUpdated = false;
m_invTransformUpdated = false;
}
////////////////////////////////////////////////////////////
const Vector2f& View::getCenter() const
{
return m_center;
}
////////////////////////////////////////////////////////////
const Vector2f& View::getSize() const
{
return m_size;
}
////////////////////////////////////////////////////////////
float View::getRotation() const
{
return m_rotation;
}
////////////////////////////////////////////////////////////
const FloatRect& View::getViewport() const
{
return m_viewport;
}
////////////////////////////////////////////////////////////
void View::move(float offsetX, float offsetY)
{
setCenter(m_center.x + offsetX, m_center.y + offsetY);
}
////////////////////////////////////////////////////////////
void View::move(const Vector2f& offset)
{
setCenter(m_center + offset);
}
////////////////////////////////////////////////////////////
void View::rotate(float angle)
{
setRotation(m_rotation + angle);
}
////////////////////////////////////////////////////////////
void View::zoom(float factor)
{
setSize(m_size.x * factor, m_size.y * factor);
}
////////////////////////////////////////////////////////////
const Transform& View::getTransform() const
{
// Recompute the matrix if needed
if (!m_transformUpdated)
{
// Rotation components
float angle = m_rotation * 3.141592654f / 180.f;
float cosine = static_cast<float>(std::cos(angle));
float sine = static_cast<float>(std::sin(angle));
float tx = -m_center.x * cosine - m_center.y * sine + m_center.x;
float ty = m_center.x * sine - m_center.y * cosine + m_center.y;
// Projection components
float a = 2.f / m_size.x;
float b = -2.f / m_size.y;
float c = -a * m_center.x;
float d = -b * m_center.y;
// Rebuild the projection matrix
m_transform = Transform( a * cosine, a * sine, a * tx + c,
-b * sine, b * cosine, b * ty + d,
0.f, 0.f, 1.f);
m_transformUpdated = true;
}
return m_transform;
}
////////////////////////////////////////////////////////////
const Transform& View::getInverseTransform() const
{
// Recompute the matrix if needed
if (!m_invTransformUpdated)
{
m_inverseTransform = getTransform().getInverse();
m_invTransformUpdated = true;
}
return m_inverseTransform;
}
} // namespace sf

View file

@ -1,37 +1,37 @@
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Main)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Main)
# sources
if(SFML_OS_WINDOWS)
set(SRC ${SRC} ${SRCROOT}/MainWin32.cpp)
elseif(SFML_OS_IOS)
set(SRC ${SRC} ${SRCROOT}/MainiOS.mm)
elseif(SFML_OS_ANDROID)
set(SRC ${SRC} ${SRCROOT}/MainAndroid.cpp)
else()
return()
endif()
source_group("" FILES ${SRC})
# define the sfml-main target
add_library(sfml-main STATIC ${SRC})
# set the debug suffix
set_target_properties(sfml-main PROPERTIES DEBUG_POSTFIX -d)
# insert the major version number in the output filename
set_target_properties(sfml-main PROPERTIES OUTPUT_NAME "sfml-main")
# set the target's folder (for IDEs that support it, e.g. Visual Studio)
set_target_properties(sfml-main PROPERTIES FOLDER "SFML")
# setup the install rule
install(TARGETS sfml-main ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel)
# because of a current limitation on Android (which prevents one library
# from depending on shared libraries), we need a boostrap activity which
# will load our shared libraries manually
if(SFML_OS_ANDROID)
sfml_add_library(sfml-activity SOURCES ${PROJECT_SOURCE_DIR}/src/SFML/Main/SFMLActivity.cpp)
endif()
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Main)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Main)
# sources
if(SFML_OS_WINDOWS)
set(SRC ${SRC} ${SRCROOT}/MainWin32.cpp)
elseif(SFML_OS_IOS)
set(SRC ${SRC} ${SRCROOT}/MainiOS.mm)
elseif(SFML_OS_ANDROID)
set(SRC ${SRC} ${SRCROOT}/MainAndroid.cpp)
else()
return()
endif()
source_group("" FILES ${SRC})
# define the sfml-main target
add_library(sfml-main STATIC ${SRC})
# set the debug suffix
set_target_properties(sfml-main PROPERTIES DEBUG_POSTFIX -d)
# insert the major version number in the output filename
set_target_properties(sfml-main PROPERTIES OUTPUT_NAME "sfml-main")
# set the target's folder (for IDEs that support it, e.g. Visual Studio)
set_target_properties(sfml-main PROPERTIES FOLDER "SFML")
# setup the install rule
install(TARGETS sfml-main ARCHIVE DESTINATION lib${LIB_SUFFIX} COMPONENT devel)
# because of a current limitation on Android (which prevents one library
# from depending on shared libraries), we need a boostrap activity which
# will load our shared libraries manually
if(SFML_OS_ANDROID)
sfml_add_library(sfml-activity SOURCES ${PROJECT_SOURCE_DIR}/src/SFML/Main/SFMLActivity.cpp)
endif()

File diff suppressed because it is too large Load diff

View file

@ -1,54 +1,54 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@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.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Windows specific: we define the WinMain entry point,
// so that developers can use the standard main function
// even in a Win32 Application project, and thus keep a
// portable code
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#ifdef SFML_SYSTEM_WINDOWS
#include <windows.h>
extern int main(int argc, char* argv[]);
////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
return main(__argc, __argv);
}
#endif // SFML_SYSTEM_WINDOWS
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@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.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Windows specific: we define the WinMain entry point,
// so that developers can use the standard main function
// even in a Win32 Application project, and thus keep a
// portable code
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#ifdef SFML_SYSTEM_WINDOWS
#include <windows.h>
extern int main(int argc, char* argv[]);
////////////////////////////////////////////////////////////
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
return main(__argc, __argv);
}
#endif // SFML_SYSTEM_WINDOWS

View file

@ -1,63 +1,63 @@
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@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.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// iOS specific: SFML needs to hook the main function, to
// launch the iOS application (event loop), and then call the
// user main from inside it.
//
// Our strategy is to rename the user main to 'sfmlMain' with
// a macro (see Main.hpp), and call this modified main ourselves.
//
// Note that half of this trick (the sfmlMain placeholders and
// the application delegate) is defined sfml-window; see there
// for the full implementation.
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#ifdef SFML_SYSTEM_IOS
#include <UIKit/UIKit.h>
////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
// Note: we intentionally drop command line arguments,
// there's no such thing as a command line on an iOS device :)
// Important: "SFAppDelegate" must always match the name of the
// application delegate class defined in sfml-window
return UIApplicationMain(argc, argv, nil, @"SFAppDelegate");
}
#endif // SFML_SYSTEM_IOS
////////////////////////////////////////////////////////////
//
// SFML - Simple and Fast Multimedia Library
// Copyright (C) 2007-2013 Laurent Gomila (laurent.gom@gmail.com)
// Copyright (C) 2013 Jonathan De Wachter (dewachter.jonathan@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.
//
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// iOS specific: SFML needs to hook the main function, to
// launch the iOS application (event loop), and then call the
// user main from inside it.
//
// Our strategy is to rename the user main to 'sfmlMain' with
// a macro (see Main.hpp), and call this modified main ourselves.
//
// Note that half of this trick (the sfmlMain placeholders and
// the application delegate) is defined sfml-window; see there
// for the full implementation.
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#ifdef SFML_SYSTEM_IOS
#include <UIKit/UIKit.h>
////////////////////////////////////////////////////////////
int main(int argc, char** argv)
{
// Note: we intentionally drop command line arguments,
// there's no such thing as a command line on an iOS device :)
// Important: "SFAppDelegate" must always match the name of the
// application delegate class defined in sfml-window
return UIApplicationMain(argc, argv, nil, @"SFAppDelegate");
}
#endif // SFML_SYSTEM_IOS

View file

@ -1,57 +1,57 @@
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Network)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Network)
# all source files
set(SRC
${INCROOT}/Export.hpp
${SRCROOT}/Ftp.cpp
${INCROOT}/Ftp.hpp
${SRCROOT}/Http.cpp
${INCROOT}/Http.hpp
${SRCROOT}/IpAddress.cpp
${INCROOT}/IpAddress.hpp
${SRCROOT}/Packet.cpp
${INCROOT}/Packet.hpp
${SRCROOT}/Socket.cpp
${INCROOT}/Socket.hpp
${SRCROOT}/SocketImpl.hpp
${INCROOT}/SocketHandle.hpp
${SRCROOT}/SocketSelector.cpp
${INCROOT}/SocketSelector.hpp
${SRCROOT}/TcpListener.cpp
${INCROOT}/TcpListener.hpp
${SRCROOT}/TcpSocket.cpp
${INCROOT}/TcpSocket.hpp
${SRCROOT}/UdpSocket.cpp
${INCROOT}/UdpSocket.hpp
)
# add platform specific sources
if(SFML_OS_WINDOWS)
set(SRC
${SRC}
${SRCROOT}/Win32/SocketImpl.cpp
${SRCROOT}/Win32/SocketImpl.hpp
)
else()
set(SRC
${SRC}
${SRCROOT}/Unix/SocketImpl.cpp
${SRCROOT}/Unix/SocketImpl.hpp
)
endif()
source_group("" FILES ${SRC})
# build the list of external libraries to link
set(NETWORK_EXT_LIBS)
if(SFML_OS_WINDOWS)
set(NETWORK_EXT_LIBS ${NETWORK_EXT_LIBS} ws2_32)
endif()
# define the sfml-network target
sfml_add_library(sfml-network
SOURCES ${SRC}
DEPENDS sfml-system
EXTERNAL_LIBS ${NETWORK_EXT_LIBS})
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Network)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Network)
# all source files
set(SRC
${INCROOT}/Export.hpp
${SRCROOT}/Ftp.cpp
${INCROOT}/Ftp.hpp
${SRCROOT}/Http.cpp
${INCROOT}/Http.hpp
${SRCROOT}/IpAddress.cpp
${INCROOT}/IpAddress.hpp
${SRCROOT}/Packet.cpp
${INCROOT}/Packet.hpp
${SRCROOT}/Socket.cpp
${INCROOT}/Socket.hpp
${SRCROOT}/SocketImpl.hpp
${INCROOT}/SocketHandle.hpp
${SRCROOT}/SocketSelector.cpp
${INCROOT}/SocketSelector.hpp
${SRCROOT}/TcpListener.cpp
${INCROOT}/TcpListener.hpp
${SRCROOT}/TcpSocket.cpp
${INCROOT}/TcpSocket.hpp
${SRCROOT}/UdpSocket.cpp
${INCROOT}/UdpSocket.hpp
)
# add platform specific sources
if(SFML_OS_WINDOWS)
set(SRC
${SRC}
${SRCROOT}/Win32/SocketImpl.cpp
${SRCROOT}/Win32/SocketImpl.hpp
)
else()
set(SRC
${SRC}
${SRCROOT}/Unix/SocketImpl.cpp
${SRCROOT}/Unix/SocketImpl.hpp
)
endif()
source_group("" FILES ${SRC})
# build the list of external libraries to link
set(NETWORK_EXT_LIBS)
if(SFML_OS_WINDOWS)
set(NETWORK_EXT_LIBS ${NETWORK_EXT_LIBS} ws2_32)
endif()
# define the sfml-network target
sfml_add_library(sfml-network
SOURCES ${SRC}
DEPENDS sfml-system
EXTERNAL_LIBS ${NETWORK_EXT_LIBS})

File diff suppressed because it is too large Load diff

View file

@ -1,415 +1,415 @@
////////////////////////////////////////////////////////////
//
// 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/Network/Http.hpp>
#include <SFML/System/Err.hpp>
#include <cctype>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <limits>
namespace
{
// Convert a string to lower case
std::string toLower(std::string str)
{
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
*i = static_cast<char>(std::tolower(*i));
return str;
}
}
namespace sf
{
////////////////////////////////////////////////////////////
Http::Request::Request(const std::string& uri, Method method, const std::string& body)
{
setMethod(method);
setUri(uri);
setHttpVersion(1, 0);
setBody(body);
}
////////////////////////////////////////////////////////////
void Http::Request::setField(const std::string& field, const std::string& value)
{
m_fields[toLower(field)] = value;
}
////////////////////////////////////////////////////////////
void Http::Request::setMethod(Http::Request::Method method)
{
m_method = method;
}
////////////////////////////////////////////////////////////
void Http::Request::setUri(const std::string& uri)
{
m_uri = uri;
// Make sure it starts with a '/'
if (m_uri.empty() || (m_uri[0] != '/'))
m_uri.insert(0, "/");
}
////////////////////////////////////////////////////////////
void Http::Request::setHttpVersion(unsigned int major, unsigned int minor)
{
m_majorVersion = major;
m_minorVersion = minor;
}
////////////////////////////////////////////////////////////
void Http::Request::setBody(const std::string& body)
{
m_body = body;
}
////////////////////////////////////////////////////////////
std::string Http::Request::prepare() const
{
std::ostringstream out;
// Convert the method to its string representation
std::string method;
switch (m_method)
{
default :
case Get : method = "GET"; break;
case Post : method = "POST"; break;
case Head : method = "HEAD"; break;
case Put : method = "PUT"; break;
case Delete : method = "DELETE"; break;
}
// Write the first line containing the request type
out << method << " " << m_uri << " ";
out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n";
// Write fields
for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i)
{
out << i->first << ": " << i->second << "\r\n";
}
// Use an extra \r\n to separate the header from the body
out << "\r\n";
// Add the body
out << m_body;
return out.str();
}
////////////////////////////////////////////////////////////
bool Http::Request::hasField(const std::string& field) const
{
return m_fields.find(toLower(field)) != m_fields.end();
}
////////////////////////////////////////////////////////////
Http::Response::Response() :
m_status (ConnectionFailed),
m_majorVersion(0),
m_minorVersion(0)
{
}
////////////////////////////////////////////////////////////
const std::string& Http::Response::getField(const std::string& field) const
{
FieldTable::const_iterator it = m_fields.find(toLower(field));
if (it != m_fields.end())
{
return it->second;
}
else
{
static const std::string empty = "";
return empty;
}
}
////////////////////////////////////////////////////////////
Http::Response::Status Http::Response::getStatus() const
{
return m_status;
}
////////////////////////////////////////////////////////////
unsigned int Http::Response::getMajorHttpVersion() const
{
return m_majorVersion;
}
////////////////////////////////////////////////////////////
unsigned int Http::Response::getMinorHttpVersion() const
{
return m_minorVersion;
}
////////////////////////////////////////////////////////////
const std::string& Http::Response::getBody() const
{
return m_body;
}
////////////////////////////////////////////////////////////
void Http::Response::parse(const std::string& data)
{
std::istringstream in(data);
// Extract the HTTP version from the first line
std::string version;
if (in >> version)
{
if ((version.size() >= 8) && (version[6] == '.') &&
(toLower(version.substr(0, 5)) == "http/") &&
isdigit(version[5]) && isdigit(version[7]))
{
m_majorVersion = version[5] - '0';
m_minorVersion = version[7] - '0';
}
else
{
// Invalid HTTP version
m_status = InvalidResponse;
return;
}
}
// Extract the status code from the first line
int status;
if (in >> status)
{
m_status = static_cast<Status>(status);
}
else
{
// Invalid status code
m_status = InvalidResponse;
return;
}
// Ignore the end of the first line
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Parse the other lines, which contain fields, one by one
parseFields(in);
m_body.clear();
// Determine whether the transfer is chunked
if (toLower(getField("transfer-encoding")) != "chunked")
{
// Not chunked - just read everything at once
std::copy(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::back_inserter(m_body));
}
else
{
// Chunked - have to read chunk by chunk
std::size_t length;
// Read all chunks, identified by a chunk-size not being 0
while (in >> std::hex >> length)
{
// Drop the rest of the line (chunk-extension)
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Copy the actual content data
std::istreambuf_iterator<char> it(in);
for (std::size_t i = 0; i < length; i++)
m_body.push_back(*it++);
}
// Drop the rest of the line (chunk-extension)
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Read all trailers (if present)
parseFields(in);
}
}
////////////////////////////////////////////////////////////
void Http::Response::parseFields(std::istream &in)
{
std::string line;
while (std::getline(in, line) && (line.size() > 2))
{
std::string::size_type pos = line.find(": ");
if (pos != std::string::npos)
{
// Extract the field name and its value
std::string field = line.substr(0, pos);
std::string value = line.substr(pos + 2);
// Remove any trailing \r
if (!value.empty() && (*value.rbegin() == '\r'))
value.erase(value.size() - 1);
// Add the field
m_fields[toLower(field)] = value;
}
}
}
////////////////////////////////////////////////////////////
Http::Http() :
m_host(),
m_port(0)
{
}
////////////////////////////////////////////////////////////
Http::Http(const std::string& host, unsigned short port)
{
setHost(host, port);
}
////////////////////////////////////////////////////////////
void Http::setHost(const std::string& host, unsigned short port)
{
// Check the protocol
if (toLower(host.substr(0, 7)) == "http://")
{
// HTTP protocol
m_hostName = host.substr(7);
m_port = (port != 0 ? port : 80);
}
else if (toLower(host.substr(0, 8)) == "https://")
{
// HTTPS protocol -- unsupported (requires encryption and certificates and stuff...)
err() << "HTTPS protocol is not supported by sf::Http" << std::endl;
m_hostName = "";
m_port = 0;
}
else
{
// Undefined protocol - use HTTP
m_hostName = host;
m_port = (port != 0 ? port : 80);
}
// Remove any trailing '/' from the host name
if (!m_hostName.empty() && (*m_hostName.rbegin() == '/'))
m_hostName.erase(m_hostName.size() - 1);
m_host = IpAddress(m_hostName);
}
////////////////////////////////////////////////////////////
Http::Response Http::sendRequest(const Http::Request& request, Time timeout)
{
// First make sure that the request is valid -- add missing mandatory fields
Request toSend(request);
if (!toSend.hasField("From"))
{
toSend.setField("From", "user@sfml-dev.org");
}
if (!toSend.hasField("User-Agent"))
{
toSend.setField("User-Agent", "libsfml-network/2.x");
}
if (!toSend.hasField("Host"))
{
toSend.setField("Host", m_hostName);
}
if (!toSend.hasField("Content-Length"))
{
std::ostringstream out;
out << toSend.m_body.size();
toSend.setField("Content-Length", out.str());
}
if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type"))
{
toSend.setField("Content-Type", "application/x-www-form-urlencoded");
}
if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection"))
{
toSend.setField("Connection", "close");
}
// Prepare the response
Response received;
// Connect the socket to the host
if (m_connection.connect(m_host, m_port, timeout) == Socket::Done)
{
// Convert the request to string and send it through the connected socket
std::string requestStr = toSend.prepare();
if (!requestStr.empty())
{
// Send it through the socket
if (m_connection.send(requestStr.c_str(), requestStr.size()) == Socket::Done)
{
// Wait for the server's response
std::string receivedStr;
std::size_t size = 0;
char buffer[1024];
while (m_connection.receive(buffer, sizeof(buffer), size) == Socket::Done)
{
receivedStr.append(buffer, buffer + size);
}
// Build the Response object from the received data
received.parse(receivedStr);
}
}
// Close the connection
m_connection.disconnect();
}
return received;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Network/Http.hpp>
#include <SFML/System/Err.hpp>
#include <cctype>
#include <algorithm>
#include <iterator>
#include <sstream>
#include <limits>
namespace
{
// Convert a string to lower case
std::string toLower(std::string str)
{
for (std::string::iterator i = str.begin(); i != str.end(); ++i)
*i = static_cast<char>(std::tolower(*i));
return str;
}
}
namespace sf
{
////////////////////////////////////////////////////////////
Http::Request::Request(const std::string& uri, Method method, const std::string& body)
{
setMethod(method);
setUri(uri);
setHttpVersion(1, 0);
setBody(body);
}
////////////////////////////////////////////////////////////
void Http::Request::setField(const std::string& field, const std::string& value)
{
m_fields[toLower(field)] = value;
}
////////////////////////////////////////////////////////////
void Http::Request::setMethod(Http::Request::Method method)
{
m_method = method;
}
////////////////////////////////////////////////////////////
void Http::Request::setUri(const std::string& uri)
{
m_uri = uri;
// Make sure it starts with a '/'
if (m_uri.empty() || (m_uri[0] != '/'))
m_uri.insert(0, "/");
}
////////////////////////////////////////////////////////////
void Http::Request::setHttpVersion(unsigned int major, unsigned int minor)
{
m_majorVersion = major;
m_minorVersion = minor;
}
////////////////////////////////////////////////////////////
void Http::Request::setBody(const std::string& body)
{
m_body = body;
}
////////////////////////////////////////////////////////////
std::string Http::Request::prepare() const
{
std::ostringstream out;
// Convert the method to its string representation
std::string method;
switch (m_method)
{
default:
case Get: method = "GET"; break;
case Post: method = "POST"; break;
case Head: method = "HEAD"; break;
case Put: method = "PUT"; break;
case Delete: method = "DELETE"; break;
}
// Write the first line containing the request type
out << method << " " << m_uri << " ";
out << "HTTP/" << m_majorVersion << "." << m_minorVersion << "\r\n";
// Write fields
for (FieldTable::const_iterator i = m_fields.begin(); i != m_fields.end(); ++i)
{
out << i->first << ": " << i->second << "\r\n";
}
// Use an extra \r\n to separate the header from the body
out << "\r\n";
// Add the body
out << m_body;
return out.str();
}
////////////////////////////////////////////////////////////
bool Http::Request::hasField(const std::string& field) const
{
return m_fields.find(toLower(field)) != m_fields.end();
}
////////////////////////////////////////////////////////////
Http::Response::Response() :
m_status (ConnectionFailed),
m_majorVersion(0),
m_minorVersion(0)
{
}
////////////////////////////////////////////////////////////
const std::string& Http::Response::getField(const std::string& field) const
{
FieldTable::const_iterator it = m_fields.find(toLower(field));
if (it != m_fields.end())
{
return it->second;
}
else
{
static const std::string empty = "";
return empty;
}
}
////////////////////////////////////////////////////////////
Http::Response::Status Http::Response::getStatus() const
{
return m_status;
}
////////////////////////////////////////////////////////////
unsigned int Http::Response::getMajorHttpVersion() const
{
return m_majorVersion;
}
////////////////////////////////////////////////////////////
unsigned int Http::Response::getMinorHttpVersion() const
{
return m_minorVersion;
}
////////////////////////////////////////////////////////////
const std::string& Http::Response::getBody() const
{
return m_body;
}
////////////////////////////////////////////////////////////
void Http::Response::parse(const std::string& data)
{
std::istringstream in(data);
// Extract the HTTP version from the first line
std::string version;
if (in >> version)
{
if ((version.size() >= 8) && (version[6] == '.') &&
(toLower(version.substr(0, 5)) == "http/") &&
isdigit(version[5]) && isdigit(version[7]))
{
m_majorVersion = version[5] - '0';
m_minorVersion = version[7] - '0';
}
else
{
// Invalid HTTP version
m_status = InvalidResponse;
return;
}
}
// Extract the status code from the first line
int status;
if (in >> status)
{
m_status = static_cast<Status>(status);
}
else
{
// Invalid status code
m_status = InvalidResponse;
return;
}
// Ignore the end of the first line
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Parse the other lines, which contain fields, one by one
parseFields(in);
m_body.clear();
// Determine whether the transfer is chunked
if (toLower(getField("transfer-encoding")) != "chunked")
{
// Not chunked - just read everything at once
std::copy(std::istreambuf_iterator<char>(in), std::istreambuf_iterator<char>(), std::back_inserter(m_body));
}
else
{
// Chunked - have to read chunk by chunk
std::size_t length;
// Read all chunks, identified by a chunk-size not being 0
while (in >> std::hex >> length)
{
// Drop the rest of the line (chunk-extension)
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Copy the actual content data
std::istreambuf_iterator<char> it(in);
for (std::size_t i = 0; i < length; i++)
m_body.push_back(*it++);
}
// Drop the rest of the line (chunk-extension)
in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Read all trailers (if present)
parseFields(in);
}
}
////////////////////////////////////////////////////////////
void Http::Response::parseFields(std::istream &in)
{
std::string line;
while (std::getline(in, line) && (line.size() > 2))
{
std::string::size_type pos = line.find(": ");
if (pos != std::string::npos)
{
// Extract the field name and its value
std::string field = line.substr(0, pos);
std::string value = line.substr(pos + 2);
// Remove any trailing \r
if (!value.empty() && (*value.rbegin() == '\r'))
value.erase(value.size() - 1);
// Add the field
m_fields[toLower(field)] = value;
}
}
}
////////////////////////////////////////////////////////////
Http::Http() :
m_host(),
m_port(0)
{
}
////////////////////////////////////////////////////////////
Http::Http(const std::string& host, unsigned short port)
{
setHost(host, port);
}
////////////////////////////////////////////////////////////
void Http::setHost(const std::string& host, unsigned short port)
{
// Check the protocol
if (toLower(host.substr(0, 7)) == "http://")
{
// HTTP protocol
m_hostName = host.substr(7);
m_port = (port != 0 ? port : 80);
}
else if (toLower(host.substr(0, 8)) == "https://")
{
// HTTPS protocol -- unsupported (requires encryption and certificates and stuff...)
err() << "HTTPS protocol is not supported by sf::Http" << std::endl;
m_hostName = "";
m_port = 0;
}
else
{
// Undefined protocol - use HTTP
m_hostName = host;
m_port = (port != 0 ? port : 80);
}
// Remove any trailing '/' from the host name
if (!m_hostName.empty() && (*m_hostName.rbegin() == '/'))
m_hostName.erase(m_hostName.size() - 1);
m_host = IpAddress(m_hostName);
}
////////////////////////////////////////////////////////////
Http::Response Http::sendRequest(const Http::Request& request, Time timeout)
{
// First make sure that the request is valid -- add missing mandatory fields
Request toSend(request);
if (!toSend.hasField("From"))
{
toSend.setField("From", "user@sfml-dev.org");
}
if (!toSend.hasField("User-Agent"))
{
toSend.setField("User-Agent", "libsfml-network/2.x");
}
if (!toSend.hasField("Host"))
{
toSend.setField("Host", m_hostName);
}
if (!toSend.hasField("Content-Length"))
{
std::ostringstream out;
out << toSend.m_body.size();
toSend.setField("Content-Length", out.str());
}
if ((toSend.m_method == Request::Post) && !toSend.hasField("Content-Type"))
{
toSend.setField("Content-Type", "application/x-www-form-urlencoded");
}
if ((toSend.m_majorVersion * 10 + toSend.m_minorVersion >= 11) && !toSend.hasField("Connection"))
{
toSend.setField("Connection", "close");
}
// Prepare the response
Response received;
// Connect the socket to the host
if (m_connection.connect(m_host, m_port, timeout) == Socket::Done)
{
// Convert the request to string and send it through the connected socket
std::string requestStr = toSend.prepare();
if (!requestStr.empty())
{
// Send it through the socket
if (m_connection.send(requestStr.c_str(), requestStr.size()) == Socket::Done)
{
// Wait for the server's response
std::string receivedStr;
std::size_t size = 0;
char buffer[1024];
while (m_connection.receive(buffer, sizeof(buffer), size) == Socket::Done)
{
receivedStr.append(buffer, buffer + size);
}
// Build the Response object from the received data
received.parse(receivedStr);
}
}
// Close the connection
m_connection.disconnect();
}
return received;
}
} // namespace sf

View file

@ -1,255 +1,255 @@
////////////////////////////////////////////////////////////
//
// 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/Network/IpAddress.hpp>
#include <SFML/Network/Http.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <cstring>
namespace
{
sf::Uint32 resolve(const std::string& address)
{
if (address == "255.255.255.255")
{
// The broadcast address needs to be handled explicitely,
// because it is also the value returned by inet_addr on error
return INADDR_BROADCAST;
}
else
{
// Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx")
sf::Uint32 ip = inet_addr(address.c_str());
if (ip != INADDR_NONE)
return ip;
// Not a valid address, try to convert it as a host name
addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
addrinfo* result = NULL;
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
{
if (result)
{
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
return ip;
}
}
// Not a valid address nor a host name
return 0;
}
}
}
namespace sf
{
////////////////////////////////////////////////////////////
const IpAddress IpAddress::None;
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
////////////////////////////////////////////////////////////
IpAddress::IpAddress() :
m_address(0)
{
// We're using 0 (INADDR_ANY) instead of INADDR_NONE to represent the invalid address,
// because the latter is also the broadcast address (255.255.255.255); it's ok because
// SFML doesn't publicly use INADDR_ANY (it is always used implicitely)
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(const std::string& address) :
m_address(resolve(address))
{
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(const char* address) :
m_address(resolve(address))
{
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3))
{
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(Uint32 address) :
m_address(htonl(address))
{
}
////////////////////////////////////////////////////////////
std::string IpAddress::toString() const
{
in_addr address;
address.s_addr = m_address;
return inet_ntoa(address);
}
////////////////////////////////////////////////////////////
Uint32 IpAddress::toInteger() const
{
return ntohl(m_address);
}
////////////////////////////////////////////////////////////
IpAddress IpAddress::getLocalAddress()
{
// The method here is to connect a UDP socket to anyone (here to localhost),
// and get the local socket address with the getsockname function.
// UDP connection will not send anything to the network, so this function won't cause any overhead.
IpAddress localAddress;
// Create the socket
SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == priv::SocketImpl::invalidSocket())
return localAddress;
// Connect the socket to localhost on any port
sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9);
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
{
priv::SocketImpl::close(sock);
return localAddress;
}
// Get the local address of the socket connection
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
{
priv::SocketImpl::close(sock);
return localAddress;
}
// Close the socket
priv::SocketImpl::close(sock);
// Finally build the IP address
localAddress = IpAddress(ntohl(address.sin_addr.s_addr));
return localAddress;
}
////////////////////////////////////////////////////////////
IpAddress IpAddress::getPublicAddress(Time timeout)
{
// The trick here is more complicated, because the only way
// to get our public IP address is to get it from a distant computer.
// Here we get the web page from http://www.sfml-dev.org/ip-provider.php
// and parse the result to extract our IP address
// (not very hard: the web page contains only our IP address).
Http server("www.sfml-dev.org");
Http::Request request("/ip-provider.php", Http::Request::Get);
Http::Response page = server.sendRequest(request, timeout);
if (page.getStatus() == Http::Response::Ok)
return IpAddress(page.getBody());
// Something failed: return an invalid address
return IpAddress();
}
////////////////////////////////////////////////////////////
bool operator ==(const IpAddress& left, const IpAddress& right)
{
return left.toInteger() == right.toInteger();
}
////////////////////////////////////////////////////////////
bool operator !=(const IpAddress& left, const IpAddress& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
bool operator <(const IpAddress& left, const IpAddress& right)
{
return left.toInteger() < right.toInteger();
}
////////////////////////////////////////////////////////////
bool operator >(const IpAddress& left, const IpAddress& right)
{
return right < left;
}
////////////////////////////////////////////////////////////
bool operator <=(const IpAddress& left, const IpAddress& right)
{
return !(right < left);
}
////////////////////////////////////////////////////////////
bool operator >=(const IpAddress& left, const IpAddress& right)
{
return !(left < right);
}
////////////////////////////////////////////////////////////
std::istream& operator >>(std::istream& stream, IpAddress& address)
{
std::string str;
stream >> str;
address = IpAddress(str);
return stream;
}
////////////////////////////////////////////////////////////
std::ostream& operator <<(std::ostream& stream, const IpAddress& address)
{
return stream << address.toString();
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Network/IpAddress.hpp>
#include <SFML/Network/Http.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <cstring>
namespace
{
sf::Uint32 resolve(const std::string& address)
{
if (address == "255.255.255.255")
{
// The broadcast address needs to be handled explicitely,
// because it is also the value returned by inet_addr on error
return INADDR_BROADCAST;
}
else
{
// Try to convert the address as a byte representation ("xxx.xxx.xxx.xxx")
sf::Uint32 ip = inet_addr(address.c_str());
if (ip != INADDR_NONE)
return ip;
// Not a valid address, try to convert it as a host name
addrinfo hints;
std::memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
addrinfo* result = NULL;
if (getaddrinfo(address.c_str(), NULL, &hints, &result) == 0)
{
if (result)
{
ip = reinterpret_cast<sockaddr_in*>(result->ai_addr)->sin_addr.s_addr;
freeaddrinfo(result);
return ip;
}
}
// Not a valid address nor a host name
return 0;
}
}
}
namespace sf
{
////////////////////////////////////////////////////////////
const IpAddress IpAddress::None;
const IpAddress IpAddress::LocalHost(127, 0, 0, 1);
const IpAddress IpAddress::Broadcast(255, 255, 255, 255);
////////////////////////////////////////////////////////////
IpAddress::IpAddress() :
m_address(0)
{
// We're using 0 (INADDR_ANY) instead of INADDR_NONE to represent the invalid address,
// because the latter is also the broadcast address (255.255.255.255); it's ok because
// SFML doesn't publicly use INADDR_ANY (it is always used implicitely)
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(const std::string& address) :
m_address(resolve(address))
{
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(const char* address) :
m_address(resolve(address))
{
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(Uint8 byte0, Uint8 byte1, Uint8 byte2, Uint8 byte3) :
m_address(htonl((byte0 << 24) | (byte1 << 16) | (byte2 << 8) | byte3))
{
}
////////////////////////////////////////////////////////////
IpAddress::IpAddress(Uint32 address) :
m_address(htonl(address))
{
}
////////////////////////////////////////////////////////////
std::string IpAddress::toString() const
{
in_addr address;
address.s_addr = m_address;
return inet_ntoa(address);
}
////////////////////////////////////////////////////////////
Uint32 IpAddress::toInteger() const
{
return ntohl(m_address);
}
////////////////////////////////////////////////////////////
IpAddress IpAddress::getLocalAddress()
{
// The method here is to connect a UDP socket to anyone (here to localhost),
// and get the local socket address with the getsockname function.
// UDP connection will not send anything to the network, so this function won't cause any overhead.
IpAddress localAddress;
// Create the socket
SocketHandle sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == priv::SocketImpl::invalidSocket())
return localAddress;
// Connect the socket to localhost on any port
sockaddr_in address = priv::SocketImpl::createAddress(ntohl(INADDR_LOOPBACK), 9);
if (connect(sock, reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
{
priv::SocketImpl::close(sock);
return localAddress;
}
// Get the local address of the socket connection
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(sock, reinterpret_cast<sockaddr*>(&address), &size) == -1)
{
priv::SocketImpl::close(sock);
return localAddress;
}
// Close the socket
priv::SocketImpl::close(sock);
// Finally build the IP address
localAddress = IpAddress(ntohl(address.sin_addr.s_addr));
return localAddress;
}
////////////////////////////////////////////////////////////
IpAddress IpAddress::getPublicAddress(Time timeout)
{
// The trick here is more complicated, because the only way
// to get our public IP address is to get it from a distant computer.
// Here we get the web page from http://www.sfml-dev.org/ip-provider.php
// and parse the result to extract our IP address
// (not very hard: the web page contains only our IP address).
Http server("www.sfml-dev.org");
Http::Request request("/ip-provider.php", Http::Request::Get);
Http::Response page = server.sendRequest(request, timeout);
if (page.getStatus() == Http::Response::Ok)
return IpAddress(page.getBody());
// Something failed: return an invalid address
return IpAddress();
}
////////////////////////////////////////////////////////////
bool operator ==(const IpAddress& left, const IpAddress& right)
{
return left.toInteger() == right.toInteger();
}
////////////////////////////////////////////////////////////
bool operator !=(const IpAddress& left, const IpAddress& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
bool operator <(const IpAddress& left, const IpAddress& right)
{
return left.toInteger() < right.toInteger();
}
////////////////////////////////////////////////////////////
bool operator >(const IpAddress& left, const IpAddress& right)
{
return right < left;
}
////////////////////////////////////////////////////////////
bool operator <=(const IpAddress& left, const IpAddress& right)
{
return !(right < left);
}
////////////////////////////////////////////////////////////
bool operator >=(const IpAddress& left, const IpAddress& right)
{
return !(left < right);
}
////////////////////////////////////////////////////////////
std::istream& operator >>(std::istream& stream, IpAddress& address)
{
std::string str;
stream >> str;
address = IpAddress(str);
return stream;
}
////////////////////////////////////////////////////////////
std::ostream& operator <<(std::ostream& stream, const IpAddress& address)
{
return stream << address.toString();
}
} // namespace sf

File diff suppressed because it is too large Load diff

View file

@ -1,144 +1,144 @@
////////////////////////////////////////////////////////////
//
// 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/Network/Socket.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Socket::Socket(Type type) :
m_type (type),
m_socket (priv::SocketImpl::invalidSocket()),
m_isBlocking(true)
{
}
////////////////////////////////////////////////////////////
Socket::~Socket()
{
// Close the socket before it gets destructed
close();
}
////////////////////////////////////////////////////////////
void Socket::setBlocking(bool blocking)
{
// Apply if the socket is already created
if (m_socket != priv::SocketImpl::invalidSocket())
priv::SocketImpl::setBlocking(m_socket, blocking);
m_isBlocking = blocking;
}
////////////////////////////////////////////////////////////
bool Socket::isBlocking() const
{
return m_isBlocking;
}
////////////////////////////////////////////////////////////
SocketHandle Socket::getHandle() const
{
return m_socket;
}
////////////////////////////////////////////////////////////
void Socket::create()
{
// Don't create the socket if it already exists
if (m_socket == priv::SocketImpl::invalidSocket())
{
SocketHandle handle = socket(PF_INET, m_type == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
create(handle);
}
}
////////////////////////////////////////////////////////////
void Socket::create(SocketHandle handle)
{
// Don't create the socket if it already exists
if (m_socket == priv::SocketImpl::invalidSocket())
{
// Assign the new handle
m_socket = handle;
// Set the current blocking state
setBlocking(m_isBlocking);
if (m_type == Tcp)
{
// Disable the Nagle algorithm (ie. removes buffering of TCP packets)
int yes = 1;
if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
{
err() << "Failed to set socket option \"TCP_NODELAY\" ; "
<< "all your TCP packets will be buffered" << std::endl;
}
// On Mac OS X, disable the SIGPIPE signal on disconnection
#ifdef SFML_SYSTEM_MACOS
if (setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
{
err() << "Failed to set socket option \"SO_NOSIGPIPE\"" << std::endl;
}
#endif
}
else
{
// Enable broadcast by default for UDP sockets
int yes = 1;
if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
{
err() << "Failed to enable broadcast on UDP socket" << std::endl;
}
}
}
}
////////////////////////////////////////////////////////////
void Socket::close()
{
// Close the socket
if (m_socket != priv::SocketImpl::invalidSocket())
{
priv::SocketImpl::close(m_socket);
m_socket = priv::SocketImpl::invalidSocket();
}
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Network/Socket.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Socket::Socket(Type type) :
m_type (type),
m_socket (priv::SocketImpl::invalidSocket()),
m_isBlocking(true)
{
}
////////////////////////////////////////////////////////////
Socket::~Socket()
{
// Close the socket before it gets destructed
close();
}
////////////////////////////////////////////////////////////
void Socket::setBlocking(bool blocking)
{
// Apply if the socket is already created
if (m_socket != priv::SocketImpl::invalidSocket())
priv::SocketImpl::setBlocking(m_socket, blocking);
m_isBlocking = blocking;
}
////////////////////////////////////////////////////////////
bool Socket::isBlocking() const
{
return m_isBlocking;
}
////////////////////////////////////////////////////////////
SocketHandle Socket::getHandle() const
{
return m_socket;
}
////////////////////////////////////////////////////////////
void Socket::create()
{
// Don't create the socket if it already exists
if (m_socket == priv::SocketImpl::invalidSocket())
{
SocketHandle handle = socket(PF_INET, m_type == Tcp ? SOCK_STREAM : SOCK_DGRAM, 0);
create(handle);
}
}
////////////////////////////////////////////////////////////
void Socket::create(SocketHandle handle)
{
// Don't create the socket if it already exists
if (m_socket == priv::SocketImpl::invalidSocket())
{
// Assign the new handle
m_socket = handle;
// Set the current blocking state
setBlocking(m_isBlocking);
if (m_type == Tcp)
{
// Disable the Nagle algorithm (ie. removes buffering of TCP packets)
int yes = 1;
if (setsockopt(m_socket, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
{
err() << "Failed to set socket option \"TCP_NODELAY\" ; "
<< "all your TCP packets will be buffered" << std::endl;
}
// On Mac OS X, disable the SIGPIPE signal on disconnection
#ifdef SFML_SYSTEM_MACOS
if (setsockopt(m_socket, SOL_SOCKET, SO_NOSIGPIPE, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
{
err() << "Failed to set socket option \"SO_NOSIGPIPE\"" << std::endl;
}
#endif
}
else
{
// Enable broadcast by default for UDP sockets
int yes = 1;
if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char*>(&yes), sizeof(yes)) == -1)
{
err() << "Failed to enable broadcast on UDP socket" << std::endl;
}
}
}
}
////////////////////////////////////////////////////////////
void Socket::close()
{
// Close the socket
if (m_socket != priv::SocketImpl::invalidSocket())
{
priv::SocketImpl::close(m_socket);
m_socket = priv::SocketImpl::invalidSocket();
}
}
} // namespace sf

View file

@ -1,39 +1,39 @@
////////////////////////////////////////////////////////////
//
// 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/Config.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Network/Win32/SocketImpl.hpp>
#else
#include <SFML/Network/Unix/SocketImpl.hpp>
#endif
////////////////////////////////////////////////////////////
//
// 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/Config.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Network/Win32/SocketImpl.hpp>
#else
#include <SFML/Network/Unix/SocketImpl.hpp>
#endif

View file

@ -1,205 +1,205 @@
////////////////////////////////////////////////////////////
//
// 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/Network/SocketSelector.hpp>
#include <SFML/Network/Socket.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
#include <utility>
#ifdef _MSC_VER
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
#endif
namespace sf
{
////////////////////////////////////////////////////////////
struct SocketSelector::SocketSelectorImpl
{
fd_set allSockets; ///< Set containing all the sockets handles
fd_set socketsReady; ///< Set containing handles of the sockets that are ready
int maxSocket; ///< Maximum socket handle
int socketCount; ///< Number of socket handles
};
////////////////////////////////////////////////////////////
SocketSelector::SocketSelector() :
m_impl(new SocketSelectorImpl)
{
clear();
}
////////////////////////////////////////////////////////////
SocketSelector::SocketSelector(const SocketSelector& copy) :
m_impl(new SocketSelectorImpl(*copy.m_impl))
{
}
////////////////////////////////////////////////////////////
SocketSelector::~SocketSelector()
{
delete m_impl;
}
////////////////////////////////////////////////////////////
void SocketSelector::add(Socket& socket)
{
SocketHandle handle = socket.getHandle();
if (handle != priv::SocketImpl::invalidSocket())
{
#if defined(SFML_SYSTEM_WINDOWS)
if (m_impl->socketCount >= FD_SETSIZE)
{
err() << "The socket can't be added to the selector because the "
<< "selector is full. This is a limitation of your operating "
<< "system's FD_SETSIZE setting.";
return;
}
if (FD_ISSET(handle, &m_impl->allSockets))
return;
m_impl->socketCount++;
#else
if (handle >= FD_SETSIZE)
{
err() << "The socket can't be added to the selector because its "
<< "ID is too high. This is a limitation of your operating "
<< "system's FD_SETSIZE setting.";
return;
}
// SocketHandle is an int in POSIX
m_impl->maxSocket = std::max(m_impl->maxSocket, handle);
#endif
FD_SET(handle, &m_impl->allSockets);
}
}
////////////////////////////////////////////////////////////
void SocketSelector::remove(Socket& socket)
{
SocketHandle handle = socket.getHandle();
if (handle != priv::SocketImpl::invalidSocket())
{
#if defined(SFML_SYSTEM_WINDOWS)
if (!FD_ISSET(handle, &m_impl->allSockets))
return;
m_impl->socketCount--;
#else
if (handle >= FD_SETSIZE)
return;
#endif
FD_CLR(handle, &m_impl->allSockets);
FD_CLR(handle, &m_impl->socketsReady);
}
}
////////////////////////////////////////////////////////////
void SocketSelector::clear()
{
FD_ZERO(&m_impl->allSockets);
FD_ZERO(&m_impl->socketsReady);
m_impl->maxSocket = 0;
m_impl->socketCount = 0;
}
////////////////////////////////////////////////////////////
bool SocketSelector::wait(Time timeout)
{
// Setup the timeout
timeval time;
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
// Initialize the set that will contain the sockets that are ready
m_impl->socketsReady = m_impl->allSockets;
// Wait until one of the sockets is ready for reading, or timeout is reached
// The first parameter is ignored on Windows
int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL);
return count > 0;
}
////////////////////////////////////////////////////////////
bool SocketSelector::isReady(Socket& socket) const
{
SocketHandle handle = socket.getHandle();
if (handle != priv::SocketImpl::invalidSocket())
{
#if !defined(SFML_SYSTEM_WINDOWS)
if (handle >= FD_SETSIZE)
return false;
#endif
return FD_ISSET(handle, &m_impl->socketsReady) != 0;
}
return false;
}
////////////////////////////////////////////////////////////
SocketSelector& SocketSelector::operator =(const SocketSelector& right)
{
SocketSelector temp(right);
std::swap(m_impl, temp.m_impl);
return *this;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Network/SocketSelector.hpp>
#include <SFML/Network/Socket.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
#include <utility>
#ifdef _MSC_VER
#pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro
#endif
namespace sf
{
////////////////////////////////////////////////////////////
struct SocketSelector::SocketSelectorImpl
{
fd_set allSockets; ///< Set containing all the sockets handles
fd_set socketsReady; ///< Set containing handles of the sockets that are ready
int maxSocket; ///< Maximum socket handle
int socketCount; ///< Number of socket handles
};
////////////////////////////////////////////////////////////
SocketSelector::SocketSelector() :
m_impl(new SocketSelectorImpl)
{
clear();
}
////////////////////////////////////////////////////////////
SocketSelector::SocketSelector(const SocketSelector& copy) :
m_impl(new SocketSelectorImpl(*copy.m_impl))
{
}
////////////////////////////////////////////////////////////
SocketSelector::~SocketSelector()
{
delete m_impl;
}
////////////////////////////////////////////////////////////
void SocketSelector::add(Socket& socket)
{
SocketHandle handle = socket.getHandle();
if (handle != priv::SocketImpl::invalidSocket())
{
#if defined(SFML_SYSTEM_WINDOWS)
if (m_impl->socketCount >= FD_SETSIZE)
{
err() << "The socket can't be added to the selector because the "
<< "selector is full. This is a limitation of your operating "
<< "system's FD_SETSIZE setting.";
return;
}
if (FD_ISSET(handle, &m_impl->allSockets))
return;
m_impl->socketCount++;
#else
if (handle >= FD_SETSIZE)
{
err() << "The socket can't be added to the selector because its "
<< "ID is too high. This is a limitation of your operating "
<< "system's FD_SETSIZE setting.";
return;
}
// SocketHandle is an int in POSIX
m_impl->maxSocket = std::max(m_impl->maxSocket, handle);
#endif
FD_SET(handle, &m_impl->allSockets);
}
}
////////////////////////////////////////////////////////////
void SocketSelector::remove(Socket& socket)
{
SocketHandle handle = socket.getHandle();
if (handle != priv::SocketImpl::invalidSocket())
{
#if defined(SFML_SYSTEM_WINDOWS)
if (!FD_ISSET(handle, &m_impl->allSockets))
return;
m_impl->socketCount--;
#else
if (handle >= FD_SETSIZE)
return;
#endif
FD_CLR(handle, &m_impl->allSockets);
FD_CLR(handle, &m_impl->socketsReady);
}
}
////////////////////////////////////////////////////////////
void SocketSelector::clear()
{
FD_ZERO(&m_impl->allSockets);
FD_ZERO(&m_impl->socketsReady);
m_impl->maxSocket = 0;
m_impl->socketCount = 0;
}
////////////////////////////////////////////////////////////
bool SocketSelector::wait(Time timeout)
{
// Setup the timeout
timeval time;
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
// Initialize the set that will contain the sockets that are ready
m_impl->socketsReady = m_impl->allSockets;
// Wait until one of the sockets is ready for reading, or timeout is reached
// The first parameter is ignored on Windows
int count = select(m_impl->maxSocket + 1, &m_impl->socketsReady, NULL, NULL, timeout != Time::Zero ? &time : NULL);
return count > 0;
}
////////////////////////////////////////////////////////////
bool SocketSelector::isReady(Socket& socket) const
{
SocketHandle handle = socket.getHandle();
if (handle != priv::SocketImpl::invalidSocket())
{
#if !defined(SFML_SYSTEM_WINDOWS)
if (handle >= FD_SETSIZE)
return false;
#endif
return FD_ISSET(handle, &m_impl->socketsReady) != 0;
}
return false;
}
////////////////////////////////////////////////////////////
SocketSelector& SocketSelector::operator =(const SocketSelector& right)
{
SocketSelector temp(right);
std::swap(m_impl, temp.m_impl);
return *this;
}
} // namespace sf

View file

@ -1,124 +1,124 @@
////////////////////////////////////////////////////////////
//
// 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/Network/TcpListener.hpp>
#include <SFML/Network/TcpSocket.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
TcpListener::TcpListener() :
Socket(Tcp)
{
}
////////////////////////////////////////////////////////////
unsigned short TcpListener::getLocalPort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the local end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
Socket::Status TcpListener::listen(unsigned short port)
{
// Create the internal socket if it doesn't exist
create();
// Bind the socket to the specified port
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
if (bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
{
// Not likely to happen, but...
err() << "Failed to bind listener socket to port " << port << std::endl;
return Error;
}
// Listen to the bound port
if (::listen(getHandle(), 0) == -1)
{
// Oops, socket is deaf
err() << "Failed to listen to port " << port << std::endl;
return Error;
}
return Done;
}
////////////////////////////////////////////////////////////
void TcpListener::close()
{
// Simply close the socket
Socket::close();
}
////////////////////////////////////////////////////////////
Socket::Status TcpListener::accept(TcpSocket& socket)
{
// Make sure that we're listening
if (getHandle() == priv::SocketImpl::invalidSocket())
{
err() << "Failed to accept a new connection, the socket is not listening" << std::endl;
return Error;
}
// Accept a new connection
sockaddr_in address;
priv::SocketImpl::AddrLength length = sizeof(address);
SocketHandle remote = ::accept(getHandle(), reinterpret_cast<sockaddr*>(&address), &length);
// Check for errors
if (remote == priv::SocketImpl::invalidSocket())
return priv::SocketImpl::getErrorStatus();
// Initialize the new connected socket
socket.close();
socket.create(remote);
return Done;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Network/TcpListener.hpp>
#include <SFML/Network/TcpSocket.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
TcpListener::TcpListener() :
Socket(Tcp)
{
}
////////////////////////////////////////////////////////////
unsigned short TcpListener::getLocalPort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the local end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
Socket::Status TcpListener::listen(unsigned short port)
{
// Create the internal socket if it doesn't exist
create();
// Bind the socket to the specified port
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
if (bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
{
// Not likely to happen, but...
err() << "Failed to bind listener socket to port " << port << std::endl;
return Error;
}
// Listen to the bound port
if (::listen(getHandle(), 0) == -1)
{
// Oops, socket is deaf
err() << "Failed to listen to port " << port << std::endl;
return Error;
}
return Done;
}
////////////////////////////////////////////////////////////
void TcpListener::close()
{
// Simply close the socket
Socket::close();
}
////////////////////////////////////////////////////////////
Socket::Status TcpListener::accept(TcpSocket& socket)
{
// Make sure that we're listening
if (getHandle() == priv::SocketImpl::invalidSocket())
{
err() << "Failed to accept a new connection, the socket is not listening" << std::endl;
return Error;
}
// Accept a new connection
sockaddr_in address;
priv::SocketImpl::AddrLength length = sizeof(address);
SocketHandle remote = ::accept(getHandle(), reinterpret_cast<sockaddr*>(&address), &length);
// Check for errors
if (remote == priv::SocketImpl::invalidSocket())
return priv::SocketImpl::getErrorStatus();
// Initialize the new connected socket
socket.close();
socket.create(remote);
return Done;
}
} // namespace sf

View file

@ -1,382 +1,382 @@
////////////////////////////////////////////////////////////
//
// 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/Network/TcpSocket.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <SFML/Network/Packet.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
#include <cstring>
#ifdef _MSC_VER
#pragma warning(disable : 4127) // "conditional expression is constant" generated by the FD_SET macro
#endif
namespace
{
// Define the low-level send/receive flags, which depend on the OS
#ifdef SFML_SYSTEM_LINUX
const int flags = MSG_NOSIGNAL;
#else
const int flags = 0;
#endif
}
namespace sf
{
////////////////////////////////////////////////////////////
TcpSocket::TcpSocket() :
Socket(Tcp)
{
}
////////////////////////////////////////////////////////////
unsigned short TcpSocket::getLocalPort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the local end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
IpAddress TcpSocket::getRemoteAddress() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the remote end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return IpAddress(ntohl(address.sin_addr.s_addr));
}
}
// We failed to retrieve the address
return IpAddress::None;
}
////////////////////////////////////////////////////////////
unsigned short TcpSocket::getRemotePort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the remote end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout)
{
// Create the internal socket if it doesn't exist
create();
// Create the remote address
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
if (timeout <= Time::Zero)
{
// ----- We're not using a timeout: just try to connect -----
// Connect the socket
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
return priv::SocketImpl::getErrorStatus();
// Connection succeeded
return Done;
}
else
{
// ----- We're using a timeout: we'll need a few tricks to make it work -----
// Save the previous blocking state
bool blocking = isBlocking();
// Switch to non-blocking to enable our connection timeout
if (blocking)
setBlocking(false);
// Try to connect to the remote address
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0)
{
// We got instantly connected! (it may no happen a lot...)
setBlocking(blocking);
return Done;
}
// Get the error status
Status status = priv::SocketImpl::getErrorStatus();
// If we were in non-blocking mode, return immediatly
if (!blocking)
return status;
// Otherwise, wait until something happens to our socket (success, timeout or error)
if (status == Socket::NotReady)
{
// Setup the selector
fd_set selector;
FD_ZERO(&selector);
FD_SET(getHandle(), &selector);
// Setup the timeout
timeval time;
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
// Wait for something to write on our socket (which means that the connection request has returned)
if (select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time) > 0)
{
// At this point the connection may have been either accepted or refused.
// To know whether it's a success or a failure, we must check the address of the connected peer
if (getRemoteAddress() != sf::IpAddress::None)
{
// Connection accepted
status = Done;
}
else
{
// Connection refused
status = priv::SocketImpl::getErrorStatus();
}
}
else
{
// Failed to connect before timeout is over
status = priv::SocketImpl::getErrorStatus();
}
}
// Switch back to blocking mode
setBlocking(true);
return status;
}
}
////////////////////////////////////////////////////////////
void TcpSocket::disconnect()
{
// Close the socket
close();
// Reset the pending packet data
m_pendingPacket = PendingPacket();
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::send(const void* data, std::size_t size)
{
// Check the parameters
if (!data || (size == 0))
{
err() << "Cannot send data over the network (no data to send)" << std::endl;
return Error;
}
// Loop until every byte has been sent
int sent = 0;
int sizeToSend = static_cast<int>(size);
for (int length = 0; length < sizeToSend; length += sent)
{
// Send a chunk of data
sent = ::send(getHandle(), static_cast<const char*>(data) + length, sizeToSend - length, flags);
// Check for errors
if (sent < 0)
return priv::SocketImpl::getErrorStatus();
}
return Done;
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received)
{
// First clear the variables to fill
received = 0;
// Check the destination buffer
if (!data)
{
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
return Error;
}
// Receive a chunk of bytes
int sizeReceived = recv(getHandle(), static_cast<char*>(data), static_cast<int>(size), flags);
// Check the number of bytes received
if (sizeReceived > 0)
{
received = static_cast<std::size_t>(sizeReceived);
return Done;
}
else if (sizeReceived == 0)
{
return Socket::Disconnected;
}
else
{
return priv::SocketImpl::getErrorStatus();
}
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::send(Packet& packet)
{
// TCP is a stream protocol, it doesn't preserve messages boundaries.
// This means that we have to send the packet size first, so that the
// receiver knows the actual end of the packet in the data stream.
// We allocate an extra memory block so that the size can be sent
// together with the data in a single call. This may seem inefficient,
// but it is actually required to avoid partial send, which could cause
// data corruption on the receiving end.
// Get the data to send from the packet
std::size_t size = 0;
const void* data = packet.onSend(size);
// First convert the packet size to network byte order
Uint32 packetSize = htonl(static_cast<Uint32>(size));
// Allocate memory for the data block to send
std::vector<char> blockToSend(sizeof(packetSize) + size);
// Copy the packet size and data into the block to send
std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
if (size > 0)
std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
// Send the data block
return send(&blockToSend[0], blockToSend.size());
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::receive(Packet& packet)
{
// First clear the variables to fill
packet.clear();
// We start by getting the size of the incoming packet
Uint32 packetSize = 0;
std::size_t received = 0;
if (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
{
// Loop until we've received the entire size of the packet
// (even a 4 byte variable may be received in more than one call)
while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
{
char* data = reinterpret_cast<char*>(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived;
Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received);
m_pendingPacket.SizeReceived += received;
if (status != Done)
return status;
}
// The packet size has been fully received
packetSize = ntohl(m_pendingPacket.Size);
}
else
{
// The packet size has already been received in a previous call
packetSize = ntohl(m_pendingPacket.Size);
}
// Loop until we receive all the packet data
char buffer[1024];
while (m_pendingPacket.Data.size() < packetSize)
{
// Receive a chunk of data
std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - m_pendingPacket.Data.size()), sizeof(buffer));
Status status = receive(buffer, sizeToGet, received);
if (status != Done)
return status;
// Append it into the packet
if (received > 0)
{
m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received);
char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received;
std::memcpy(begin, buffer, received);
}
}
// We have received all the packet data: we can copy it to the user packet
if (!m_pendingPacket.Data.empty())
packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size());
// Clear the pending packet data
m_pendingPacket = PendingPacket();
return Done;
}
////////////////////////////////////////////////////////////
TcpSocket::PendingPacket::PendingPacket() :
Size (0),
SizeReceived(0),
Data ()
{
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Network/TcpSocket.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <SFML/Network/Packet.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
#include <cstring>
#ifdef _MSC_VER
#pragma warning(disable: 4127) // "conditional expression is constant" generated by the FD_SET macro
#endif
namespace
{
// Define the low-level send/receive flags, which depend on the OS
#ifdef SFML_SYSTEM_LINUX
const int flags = MSG_NOSIGNAL;
#else
const int flags = 0;
#endif
}
namespace sf
{
////////////////////////////////////////////////////////////
TcpSocket::TcpSocket() :
Socket(Tcp)
{
}
////////////////////////////////////////////////////////////
unsigned short TcpSocket::getLocalPort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the local end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
IpAddress TcpSocket::getRemoteAddress() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the remote end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return IpAddress(ntohl(address.sin_addr.s_addr));
}
}
// We failed to retrieve the address
return IpAddress::None;
}
////////////////////////////////////////////////////////////
unsigned short TcpSocket::getRemotePort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the remote end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getpeername(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::connect(const IpAddress& remoteAddress, unsigned short remotePort, Time timeout)
{
// Create the internal socket if it doesn't exist
create();
// Create the remote address
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
if (timeout <= Time::Zero)
{
// ----- We're not using a timeout: just try to connect -----
// Connect the socket
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
return priv::SocketImpl::getErrorStatus();
// Connection succeeded
return Done;
}
else
{
// ----- We're using a timeout: we'll need a few tricks to make it work -----
// Save the previous blocking state
bool blocking = isBlocking();
// Switch to non-blocking to enable our connection timeout
if (blocking)
setBlocking(false);
// Try to connect to the remote address
if (::connect(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) >= 0)
{
// We got instantly connected! (it may no happen a lot...)
setBlocking(blocking);
return Done;
}
// Get the error status
Status status = priv::SocketImpl::getErrorStatus();
// If we were in non-blocking mode, return immediatly
if (!blocking)
return status;
// Otherwise, wait until something happens to our socket (success, timeout or error)
if (status == Socket::NotReady)
{
// Setup the selector
fd_set selector;
FD_ZERO(&selector);
FD_SET(getHandle(), &selector);
// Setup the timeout
timeval time;
time.tv_sec = static_cast<long>(timeout.asMicroseconds() / 1000000);
time.tv_usec = static_cast<long>(timeout.asMicroseconds() % 1000000);
// Wait for something to write on our socket (which means that the connection request has returned)
if (select(static_cast<int>(getHandle() + 1), NULL, &selector, NULL, &time) > 0)
{
// At this point the connection may have been either accepted or refused.
// To know whether it's a success or a failure, we must check the address of the connected peer
if (getRemoteAddress() != sf::IpAddress::None)
{
// Connection accepted
status = Done;
}
else
{
// Connection refused
status = priv::SocketImpl::getErrorStatus();
}
}
else
{
// Failed to connect before timeout is over
status = priv::SocketImpl::getErrorStatus();
}
}
// Switch back to blocking mode
setBlocking(true);
return status;
}
}
////////////////////////////////////////////////////////////
void TcpSocket::disconnect()
{
// Close the socket
close();
// Reset the pending packet data
m_pendingPacket = PendingPacket();
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::send(const void* data, std::size_t size)
{
// Check the parameters
if (!data || (size == 0))
{
err() << "Cannot send data over the network (no data to send)" << std::endl;
return Error;
}
// Loop until every byte has been sent
int sent = 0;
int sizeToSend = static_cast<int>(size);
for (int length = 0; length < sizeToSend; length += sent)
{
// Send a chunk of data
sent = ::send(getHandle(), static_cast<const char*>(data) + length, sizeToSend - length, flags);
// Check for errors
if (sent < 0)
return priv::SocketImpl::getErrorStatus();
}
return Done;
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::receive(void* data, std::size_t size, std::size_t& received)
{
// First clear the variables to fill
received = 0;
// Check the destination buffer
if (!data)
{
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
return Error;
}
// Receive a chunk of bytes
int sizeReceived = recv(getHandle(), static_cast<char*>(data), static_cast<int>(size), flags);
// Check the number of bytes received
if (sizeReceived > 0)
{
received = static_cast<std::size_t>(sizeReceived);
return Done;
}
else if (sizeReceived == 0)
{
return Socket::Disconnected;
}
else
{
return priv::SocketImpl::getErrorStatus();
}
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::send(Packet& packet)
{
// TCP is a stream protocol, it doesn't preserve messages boundaries.
// This means that we have to send the packet size first, so that the
// receiver knows the actual end of the packet in the data stream.
// We allocate an extra memory block so that the size can be sent
// together with the data in a single call. This may seem inefficient,
// but it is actually required to avoid partial send, which could cause
// data corruption on the receiving end.
// Get the data to send from the packet
std::size_t size = 0;
const void* data = packet.onSend(size);
// First convert the packet size to network byte order
Uint32 packetSize = htonl(static_cast<Uint32>(size));
// Allocate memory for the data block to send
std::vector<char> blockToSend(sizeof(packetSize) + size);
// Copy the packet size and data into the block to send
std::memcpy(&blockToSend[0], &packetSize, sizeof(packetSize));
if (size > 0)
std::memcpy(&blockToSend[0] + sizeof(packetSize), data, size);
// Send the data block
return send(&blockToSend[0], blockToSend.size());
}
////////////////////////////////////////////////////////////
Socket::Status TcpSocket::receive(Packet& packet)
{
// First clear the variables to fill
packet.clear();
// We start by getting the size of the incoming packet
Uint32 packetSize = 0;
std::size_t received = 0;
if (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
{
// Loop until we've received the entire size of the packet
// (even a 4 byte variable may be received in more than one call)
while (m_pendingPacket.SizeReceived < sizeof(m_pendingPacket.Size))
{
char* data = reinterpret_cast<char*>(&m_pendingPacket.Size) + m_pendingPacket.SizeReceived;
Status status = receive(data, sizeof(m_pendingPacket.Size) - m_pendingPacket.SizeReceived, received);
m_pendingPacket.SizeReceived += received;
if (status != Done)
return status;
}
// The packet size has been fully received
packetSize = ntohl(m_pendingPacket.Size);
}
else
{
// The packet size has already been received in a previous call
packetSize = ntohl(m_pendingPacket.Size);
}
// Loop until we receive all the packet data
char buffer[1024];
while (m_pendingPacket.Data.size() < packetSize)
{
// Receive a chunk of data
std::size_t sizeToGet = std::min(static_cast<std::size_t>(packetSize - m_pendingPacket.Data.size()), sizeof(buffer));
Status status = receive(buffer, sizeToGet, received);
if (status != Done)
return status;
// Append it into the packet
if (received > 0)
{
m_pendingPacket.Data.resize(m_pendingPacket.Data.size() + received);
char* begin = &m_pendingPacket.Data[0] + m_pendingPacket.Data.size() - received;
std::memcpy(begin, buffer, received);
}
}
// We have received all the packet data: we can copy it to the user packet
if (!m_pendingPacket.Data.empty())
packet.onReceive(&m_pendingPacket.Data[0], m_pendingPacket.Data.size());
// Clear the pending packet data
m_pendingPacket = PendingPacket();
return Done;
}
////////////////////////////////////////////////////////////
TcpSocket::PendingPacket::PendingPacket() :
Size (0),
SizeReceived(0),
Data ()
{
}
} // namespace sf

View file

@ -1,193 +1,193 @@
////////////////////////////////////////////////////////////
//
// 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/Network/UdpSocket.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <SFML/Network/Packet.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
namespace sf
{
////////////////////////////////////////////////////////////
UdpSocket::UdpSocket() :
Socket (Udp),
m_buffer(MaxDatagramSize)
{
}
////////////////////////////////////////////////////////////
unsigned short UdpSocket::getLocalPort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the local end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::bind(unsigned short port)
{
// Create the internal socket if it doesn't exist
create();
// Bind the socket
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
if (::bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
{
err() << "Failed to bind socket to port " << port << std::endl;
return Error;
}
return Done;
}
////////////////////////////////////////////////////////////
void UdpSocket::unbind()
{
// Simply close the socket
close();
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort)
{
// Create the internal socket if it doesn't exist
create();
// Make sure that all the data will fit in one datagram
if (size > MaxDatagramSize)
{
err() << "Cannot send data over the network "
<< "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl;
return Error;
}
// Build the target address
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
// Send the data (unlike TCP, all the data is always sent in one call)
int sent = sendto(getHandle(), static_cast<const char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), sizeof(address));
// Check for errors
if (sent < 0)
return priv::SocketImpl::getErrorStatus();
return Done;
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort)
{
// First clear the variables to fill
received = 0;
remoteAddress = IpAddress();
remotePort = 0;
// Check the destination buffer
if (!data)
{
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
return Error;
}
// Data that will be filled with the other computer's address
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, 0);
// Receive a chunk of bytes
priv::SocketImpl::AddrLength addressSize = sizeof(address);
int sizeReceived = recvfrom(getHandle(), static_cast<char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), &addressSize);
// Check for errors
if (sizeReceived < 0)
return priv::SocketImpl::getErrorStatus();
// Fill the sender informations
received = static_cast<std::size_t>(sizeReceived);
remoteAddress = IpAddress(ntohl(address.sin_addr.s_addr));
remotePort = ntohs(address.sin_port);
return Done;
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort)
{
// UDP is a datagram-oriented protocol (as opposed to TCP which is a stream protocol).
// Sending one datagram is almost safe: it may be lost but if it's received, then its data
// is guaranteed to be ok. However, splitting a packet into multiple datagrams would be highly
// unreliable, since datagrams may be reordered, dropped or mixed between different sources.
// That's why SFML imposes a limit on packet size so that they can be sent in a single datagram.
// This also removes the overhead associated to packets -- there's no size to send in addition
// to the packet's data.
// Get the data to send from the packet
std::size_t size = 0;
const void* data = packet.onSend(size);
// Send it
return send(data, size, remoteAddress, remotePort);
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort)
{
// See the detailed comment in send(Packet) above.
// Receive the datagram
std::size_t received = 0;
Status status = receive(&m_buffer[0], m_buffer.size(), received, remoteAddress, remotePort);
// If we received valid data, we can copy it to the user packet
packet.clear();
if ((status == Done) && (received > 0))
packet.onReceive(&m_buffer[0], received);
return status;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Network/UdpSocket.hpp>
#include <SFML/Network/IpAddress.hpp>
#include <SFML/Network/Packet.hpp>
#include <SFML/Network/SocketImpl.hpp>
#include <SFML/System/Err.hpp>
#include <algorithm>
namespace sf
{
////////////////////////////////////////////////////////////
UdpSocket::UdpSocket() :
Socket (Udp),
m_buffer(MaxDatagramSize)
{
}
////////////////////////////////////////////////////////////
unsigned short UdpSocket::getLocalPort() const
{
if (getHandle() != priv::SocketImpl::invalidSocket())
{
// Retrieve informations about the local end of the socket
sockaddr_in address;
priv::SocketImpl::AddrLength size = sizeof(address);
if (getsockname(getHandle(), reinterpret_cast<sockaddr*>(&address), &size) != -1)
{
return ntohs(address.sin_port);
}
}
// We failed to retrieve the port
return 0;
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::bind(unsigned short port)
{
// Create the internal socket if it doesn't exist
create();
// Bind the socket
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, port);
if (::bind(getHandle(), reinterpret_cast<sockaddr*>(&address), sizeof(address)) == -1)
{
err() << "Failed to bind socket to port " << port << std::endl;
return Error;
}
return Done;
}
////////////////////////////////////////////////////////////
void UdpSocket::unbind()
{
// Simply close the socket
close();
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::send(const void* data, std::size_t size, const IpAddress& remoteAddress, unsigned short remotePort)
{
// Create the internal socket if it doesn't exist
create();
// Make sure that all the data will fit in one datagram
if (size > MaxDatagramSize)
{
err() << "Cannot send data over the network "
<< "(the number of bytes to send is greater than sf::UdpSocket::MaxDatagramSize)" << std::endl;
return Error;
}
// Build the target address
sockaddr_in address = priv::SocketImpl::createAddress(remoteAddress.toInteger(), remotePort);
// Send the data (unlike TCP, all the data is always sent in one call)
int sent = sendto(getHandle(), static_cast<const char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), sizeof(address));
// Check for errors
if (sent < 0)
return priv::SocketImpl::getErrorStatus();
return Done;
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::receive(void* data, std::size_t size, std::size_t& received, IpAddress& remoteAddress, unsigned short& remotePort)
{
// First clear the variables to fill
received = 0;
remoteAddress = IpAddress();
remotePort = 0;
// Check the destination buffer
if (!data)
{
err() << "Cannot receive data from the network (the destination buffer is invalid)" << std::endl;
return Error;
}
// Data that will be filled with the other computer's address
sockaddr_in address = priv::SocketImpl::createAddress(INADDR_ANY, 0);
// Receive a chunk of bytes
priv::SocketImpl::AddrLength addressSize = sizeof(address);
int sizeReceived = recvfrom(getHandle(), static_cast<char*>(data), static_cast<int>(size), 0, reinterpret_cast<sockaddr*>(&address), &addressSize);
// Check for errors
if (sizeReceived < 0)
return priv::SocketImpl::getErrorStatus();
// Fill the sender informations
received = static_cast<std::size_t>(sizeReceived);
remoteAddress = IpAddress(ntohl(address.sin_addr.s_addr));
remotePort = ntohs(address.sin_port);
return Done;
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::send(Packet& packet, const IpAddress& remoteAddress, unsigned short remotePort)
{
// UDP is a datagram-oriented protocol (as opposed to TCP which is a stream protocol).
// Sending one datagram is almost safe: it may be lost but if it's received, then its data
// is guaranteed to be ok. However, splitting a packet into multiple datagrams would be highly
// unreliable, since datagrams may be reordered, dropped or mixed between different sources.
// That's why SFML imposes a limit on packet size so that they can be sent in a single datagram.
// This also removes the overhead associated to packets -- there's no size to send in addition
// to the packet's data.
// Get the data to send from the packet
std::size_t size = 0;
const void* data = packet.onSend(size);
// Send it
return send(data, size, remoteAddress, remotePort);
}
////////////////////////////////////////////////////////////
Socket::Status UdpSocket::receive(Packet& packet, IpAddress& remoteAddress, unsigned short& remotePort)
{
// See the detailed comment in send(Packet) above.
// Receive the datagram
std::size_t received = 0;
Status status = receive(&m_buffer[0], m_buffer.size(), received, remoteAddress, remotePort);
// If we received valid data, we can copy it to the user packet
packet.clear();
if ((status == Done) && (received > 0))
packet.onReceive(&m_buffer[0], received);
return status;
}
} // namespace sf

View file

@ -1,104 +1,104 @@
////////////////////////////////////////////////////////////
//
// 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/Network/Unix/SocketImpl.hpp>
#include <errno.h>
#include <fcntl.h>
#include <cstring>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
{
sockaddr_in addr;
std::memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = htonl(address);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
#if defined(SFML_SYSTEM_MACOS)
addr.sin_len = sizeof(addr);
#endif
return addr;
}
////////////////////////////////////////////////////////////
SocketHandle SocketImpl::invalidSocket()
{
return -1;
}
////////////////////////////////////////////////////////////
void SocketImpl::close(SocketHandle sock)
{
::close(sock);
}
////////////////////////////////////////////////////////////
void SocketImpl::setBlocking(SocketHandle sock, bool block)
{
int status = fcntl(sock, F_GETFL);
if (block)
fcntl(sock, F_SETFL, status & ~O_NONBLOCK);
else
fcntl(sock, F_SETFL, status | O_NONBLOCK);
}
////////////////////////////////////////////////////////////
Socket::Status SocketImpl::getErrorStatus()
{
// The followings are sometimes equal to EWOULDBLOCK,
// so we have to make a special case for them in order
// to avoid having double values in the switch case
if ((errno == EAGAIN) || (errno == EINPROGRESS))
return Socket::NotReady;
switch (errno)
{
case EWOULDBLOCK : return Socket::NotReady;
case ECONNABORTED : return Socket::Disconnected;
case ECONNRESET : return Socket::Disconnected;
case ETIMEDOUT : return Socket::Disconnected;
case ENETRESET : return Socket::Disconnected;
case ENOTCONN : return Socket::Disconnected;
case EPIPE : return Socket::Disconnected;
default : return Socket::Error;
}
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Network/Unix/SocketImpl.hpp>
#include <errno.h>
#include <fcntl.h>
#include <cstring>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
{
sockaddr_in addr;
std::memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = htonl(address);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
#if defined(SFML_SYSTEM_MACOS)
addr.sin_len = sizeof(addr);
#endif
return addr;
}
////////////////////////////////////////////////////////////
SocketHandle SocketImpl::invalidSocket()
{
return -1;
}
////////////////////////////////////////////////////////////
void SocketImpl::close(SocketHandle sock)
{
::close(sock);
}
////////////////////////////////////////////////////////////
void SocketImpl::setBlocking(SocketHandle sock, bool block)
{
int status = fcntl(sock, F_GETFL);
if (block)
fcntl(sock, F_SETFL, status & ~O_NONBLOCK);
else
fcntl(sock, F_SETFL, status | O_NONBLOCK);
}
////////////////////////////////////////////////////////////
Socket::Status SocketImpl::getErrorStatus()
{
// The followings are sometimes equal to EWOULDBLOCK,
// so we have to make a special case for them in order
// to avoid having double values in the switch case
if ((errno == EAGAIN) || (errno == EINPROGRESS))
return Socket::NotReady;
switch (errno)
{
case EWOULDBLOCK: return Socket::NotReady;
case ECONNABORTED: return Socket::Disconnected;
case ECONNRESET: return Socket::Disconnected;
case ETIMEDOUT: return Socket::Disconnected;
case ENETRESET: return Socket::Disconnected;
case ENOTCONN: return Socket::Disconnected;
case EPIPE: return Socket::Disconnected;
default: return Socket::Error;
}
}
} // namespace priv
} // namespace sf

View file

@ -1,109 +1,109 @@
////////////////////////////////////////////////////////////
//
// 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_SOCKETIMPL_HPP
#define SFML_SOCKETIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Socket.hpp>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Helper class implementing all the non-portable
/// socket stuff; this is the Unix version
///
////////////////////////////////////////////////////////////
class SocketImpl
{
public :
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef socklen_t AddrLength;
////////////////////////////////////////////////////////////
/// \brief Create an internal sockaddr_in address
///
/// \param address Target address
/// \param port Target port
///
/// \return sockaddr_in ready to be used by socket functions
///
////////////////////////////////////////////////////////////
static sockaddr_in createAddress(Uint32 address, unsigned short port);
////////////////////////////////////////////////////////////
/// \brief Return the value of the invalid socket
///
/// \return Special value of the invalid socket
///
////////////////////////////////////////////////////////////
static SocketHandle invalidSocket();
////////////////////////////////////////////////////////////
/// \brief Close and destroy a socket
///
/// \param sock Handle of the socket to close
///
////////////////////////////////////////////////////////////
static void close(SocketHandle sock);
////////////////////////////////////////////////////////////
/// \brief Set a socket as blocking or non-blocking
///
/// \param sock Handle of the socket
/// \param block New blocking state of the socket
///
////////////////////////////////////////////////////////////
static void setBlocking(SocketHandle sock, bool block);
////////////////////////////////////////////////////////////
/// Get the last socket error status
///
/// \return Status corresponding to the last socket error
///
////////////////////////////////////////////////////////////
static Socket::Status getErrorStatus();
};
} // namespace priv
} // namespace sf
#endif // SFML_SOCKETIMPL_HPP
////////////////////////////////////////////////////////////
//
// 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_SOCKETIMPL_HPP
#define SFML_SOCKETIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Network/Socket.hpp>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Helper class implementing all the non-portable
/// socket stuff; this is the Unix version
///
////////////////////////////////////////////////////////////
class SocketImpl
{
public:
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef socklen_t AddrLength;
////////////////////////////////////////////////////////////
/// \brief Create an internal sockaddr_in address
///
/// \param address Target address
/// \param port Target port
///
/// \return sockaddr_in ready to be used by socket functions
///
////////////////////////////////////////////////////////////
static sockaddr_in createAddress(Uint32 address, unsigned short port);
////////////////////////////////////////////////////////////
/// \brief Return the value of the invalid socket
///
/// \return Special value of the invalid socket
///
////////////////////////////////////////////////////////////
static SocketHandle invalidSocket();
////////////////////////////////////////////////////////////
/// \brief Close and destroy a socket
///
/// \param sock Handle of the socket to close
///
////////////////////////////////////////////////////////////
static void close(SocketHandle sock);
////////////////////////////////////////////////////////////
/// \brief Set a socket as blocking or non-blocking
///
/// \param sock Handle of the socket
/// \param block New blocking state of the socket
///
////////////////////////////////////////////////////////////
static void setBlocking(SocketHandle sock, bool block);
////////////////////////////////////////////////////////////
/// Get the last socket error status
///
/// \return Status corresponding to the last socket error
///
////////////////////////////////////////////////////////////
static Socket::Status getErrorStatus();
};
} // namespace priv
} // namespace sf
#endif // SFML_SOCKETIMPL_HPP

View file

@ -1,112 +1,112 @@
////////////////////////////////////////////////////////////
//
// 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/Network/Win32/SocketImpl.hpp>
#include <cstring>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
{
sockaddr_in addr;
std::memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = htonl(address);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
return addr;
}
////////////////////////////////////////////////////////////
SocketHandle SocketImpl::invalidSocket()
{
return INVALID_SOCKET;
}
////////////////////////////////////////////////////////////
void SocketImpl::close(SocketHandle sock)
{
closesocket(sock);
}
////////////////////////////////////////////////////////////
void SocketImpl::setBlocking(SocketHandle sock, bool block)
{
u_long blocking = block ? 0 : 1;
ioctlsocket(sock, FIONBIO, &blocking);
}
////////////////////////////////////////////////////////////
Socket::Status SocketImpl::getErrorStatus()
{
switch (WSAGetLastError())
{
case WSAEWOULDBLOCK : return Socket::NotReady;
case WSAEALREADY : return Socket::NotReady;
case WSAECONNABORTED : return Socket::Disconnected;
case WSAECONNRESET : return Socket::Disconnected;
case WSAETIMEDOUT : return Socket::Disconnected;
case WSAENETRESET : return Socket::Disconnected;
case WSAENOTCONN : return Socket::Disconnected;
case WSAEISCONN : return Socket::Done; // when connecting a non-blocking socket
default : return Socket::Error;
}
}
////////////////////////////////////////////////////////////
// Windows needs some initialization and cleanup to get
// sockets working properly... so let's create a class that will
// do it automatically
////////////////////////////////////////////////////////////
struct SocketInitializer
{
SocketInitializer()
{
WSADATA init;
WSAStartup(MAKEWORD(2, 2), &init);
}
~SocketInitializer()
{
WSACleanup();
}
};
SocketInitializer globalInitializer;
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Network/Win32/SocketImpl.hpp>
#include <cstring>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
sockaddr_in SocketImpl::createAddress(Uint32 address, unsigned short port)
{
sockaddr_in addr;
std::memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = htonl(address);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
return addr;
}
////////////////////////////////////////////////////////////
SocketHandle SocketImpl::invalidSocket()
{
return INVALID_SOCKET;
}
////////////////////////////////////////////////////////////
void SocketImpl::close(SocketHandle sock)
{
closesocket(sock);
}
////////////////////////////////////////////////////////////
void SocketImpl::setBlocking(SocketHandle sock, bool block)
{
u_long blocking = block ? 0 : 1;
ioctlsocket(sock, FIONBIO, &blocking);
}
////////////////////////////////////////////////////////////
Socket::Status SocketImpl::getErrorStatus()
{
switch (WSAGetLastError())
{
case WSAEWOULDBLOCK: return Socket::NotReady;
case WSAEALREADY: return Socket::NotReady;
case WSAECONNABORTED: return Socket::Disconnected;
case WSAECONNRESET: return Socket::Disconnected;
case WSAETIMEDOUT: return Socket::Disconnected;
case WSAENETRESET: return Socket::Disconnected;
case WSAENOTCONN: return Socket::Disconnected;
case WSAEISCONN: return Socket::Done; // when connecting a non-blocking socket
default: return Socket::Error;
}
}
////////////////////////////////////////////////////////////
// Windows needs some initialization and cleanup to get
// sockets working properly... so let's create a class that will
// do it automatically
////////////////////////////////////////////////////////////
struct SocketInitializer
{
SocketInitializer()
{
WSADATA init;
WSAStartup(MAKEWORD(2, 2), &init);
}
~SocketInitializer()
{
WSACleanup();
}
};
SocketInitializer globalInitializer;
} // namespace priv
} // namespace sf

View file

@ -1,112 +1,112 @@
////////////////////////////////////////////////////////////
//
// 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_SOCKETIMPL_HPP
#define SFML_SOCKETIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#ifdef _WIN32_WINDOWS
#undef _WIN32_WINDOWS
#endif
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINDOWS 0x0501
#define _WIN32_WINNT 0x0501
#include <SFML/Network/Socket.hpp>
#include <winsock2.h>
#include <ws2tcpip.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Helper class implementing all the non-portable
/// socket stuff; this is the Windows version
///
////////////////////////////////////////////////////////////
class SocketImpl
{
public :
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef int AddrLength;
////////////////////////////////////////////////////////////
/// \brief Create an internal sockaddr_in address
///
/// \param address Target address
/// \param port Target port
///
/// \return sockaddr_in ready to be used by socket functions
///
////////////////////////////////////////////////////////////
static sockaddr_in createAddress(Uint32 address, unsigned short port);
////////////////////////////////////////////////////////////
/// \brief Return the value of the invalid socket
///
/// \return Special value of the invalid socket
///
////////////////////////////////////////////////////////////
static SocketHandle invalidSocket();
////////////////////////////////////////////////////////////
/// \brief Close and destroy a socket
///
/// \param sock Handle of the socket to close
///
////////////////////////////////////////////////////////////
static void close(SocketHandle sock);
////////////////////////////////////////////////////////////
/// \brief Set a socket as blocking or non-blocking
///
/// \param sock Handle of the socket
/// \param block New blocking state of the socket
///
////////////////////////////////////////////////////////////
static void setBlocking(SocketHandle sock, bool block);
////////////////////////////////////////////////////////////
/// Get the last socket error status
///
/// \return Status corresponding to the last socket error
///
////////////////////////////////////////////////////////////
static Socket::Status getErrorStatus();
};
} // namespace priv
} // namespace sf
#endif // SFML_SOCKETIMPL_HPP
////////////////////////////////////////////////////////////
//
// 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_SOCKETIMPL_HPP
#define SFML_SOCKETIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#ifdef _WIN32_WINDOWS
#undef _WIN32_WINDOWS
#endif
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINDOWS 0x0501
#define _WIN32_WINNT 0x0501
#include <SFML/Network/Socket.hpp>
#include <winsock2.h>
#include <ws2tcpip.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Helper class implementing all the non-portable
/// socket stuff; this is the Windows version
///
////////////////////////////////////////////////////////////
class SocketImpl
{
public:
////////////////////////////////////////////////////////////
// Types
////////////////////////////////////////////////////////////
typedef int AddrLength;
////////////////////////////////////////////////////////////
/// \brief Create an internal sockaddr_in address
///
/// \param address Target address
/// \param port Target port
///
/// \return sockaddr_in ready to be used by socket functions
///
////////////////////////////////////////////////////////////
static sockaddr_in createAddress(Uint32 address, unsigned short port);
////////////////////////////////////////////////////////////
/// \brief Return the value of the invalid socket
///
/// \return Special value of the invalid socket
///
////////////////////////////////////////////////////////////
static SocketHandle invalidSocket();
////////////////////////////////////////////////////////////
/// \brief Close and destroy a socket
///
/// \param sock Handle of the socket to close
///
////////////////////////////////////////////////////////////
static void close(SocketHandle sock);
////////////////////////////////////////////////////////////
/// \brief Set a socket as blocking or non-blocking
///
/// \param sock Handle of the socket
/// \param block New blocking state of the socket
///
////////////////////////////////////////////////////////////
static void setBlocking(SocketHandle sock, bool block);
////////////////////////////////////////////////////////////
/// Get the last socket error status
///
/// \return Status corresponding to the last socket error
///
////////////////////////////////////////////////////////////
static Socket::Status getErrorStatus();
};
} // namespace priv
} // namespace sf
#endif // SFML_SOCKETIMPL_HPP

View file

@ -44,7 +44,7 @@ namespace priv
////////////////////////////////////////////////////////////
class SFML_SYSTEM_API ResourceStream : public InputStream
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
@ -97,7 +97,7 @@ public :
////////////////////////////////////////////////////////////
Int64 getSize();
private :
private:
////////////////////////////////////////////////////////////
// Member data

View file

@ -1,99 +1,99 @@
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/System)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/System)
# all source files
set(SRC
${SRCROOT}/Clock.cpp
${INCROOT}/Clock.hpp
${SRCROOT}/Err.cpp
${INCROOT}/Err.hpp
${INCROOT}/Export.hpp
${INCROOT}/InputStream.hpp
${SRCROOT}/Lock.cpp
${INCROOT}/Lock.hpp
${SRCROOT}/Mutex.cpp
${INCROOT}/Mutex.hpp
${INCROOT}/NonCopyable.hpp
${SRCROOT}/Sleep.cpp
${INCROOT}/Sleep.hpp
${SRCROOT}/String.cpp
${INCROOT}/String.hpp
${INCROOT}/String.inl
${SRCROOT}/Thread.cpp
${INCROOT}/Thread.hpp
${INCROOT}/Thread.inl
${SRCROOT}/ThreadLocal.cpp
${INCROOT}/ThreadLocal.hpp
${INCROOT}/ThreadLocalPtr.hpp
${INCROOT}/ThreadLocalPtr.inl
${SRCROOT}/Time.cpp
${INCROOT}/Time.hpp
${INCROOT}/Utf.hpp
${INCROOT}/Utf.inl
${INCROOT}/Vector2.hpp
${INCROOT}/Vector2.inl
${INCROOT}/Vector3.hpp
${INCROOT}/Vector3.inl
)
source_group("" FILES ${SRC})
# add platform specific sources
if(SFML_OS_WINDOWS)
set(PLATFORM_SRC
${SRCROOT}/Win32/ClockImpl.cpp
${SRCROOT}/Win32/ClockImpl.hpp
${SRCROOT}/Win32/MutexImpl.cpp
${SRCROOT}/Win32/MutexImpl.hpp
${SRCROOT}/Win32/SleepImpl.cpp
${SRCROOT}/Win32/SleepImpl.hpp
${SRCROOT}/Win32/ThreadImpl.cpp
${SRCROOT}/Win32/ThreadImpl.hpp
${SRCROOT}/Win32/ThreadLocalImpl.cpp
${SRCROOT}/Win32/ThreadLocalImpl.hpp
)
source_group("windows" FILES ${PLATFORM_SRC})
else()
set(PLATFORM_SRC
${SRCROOT}/Unix/ClockImpl.cpp
${SRCROOT}/Unix/ClockImpl.hpp
${SRCROOT}/Unix/MutexImpl.cpp
${SRCROOT}/Unix/MutexImpl.hpp
${SRCROOT}/Unix/SleepImpl.cpp
${SRCROOT}/Unix/SleepImpl.hpp
${SRCROOT}/Unix/ThreadImpl.cpp
${SRCROOT}/Unix/ThreadImpl.hpp
${SRCROOT}/Unix/ThreadLocalImpl.cpp
${SRCROOT}/Unix/ThreadLocalImpl.hpp
)
if(SFML_OS_ANDROID)
set(PLATFORM_SRC ${PLATFORM_SRC}
${SRCROOT}/Android/Activity.hpp
${SRCROOT}/Android/Activity.cpp
${SRCROOT}/Android/ResourceStream.cpp
${SRCROOT}/Android/ResourceStream.cpp
)
endif()
source_group("unix" FILES ${PLATFORM_SRC})
endif()
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/System)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/System)
# all source files
set(SRC
${SRCROOT}/Clock.cpp
${INCROOT}/Clock.hpp
${SRCROOT}/Err.cpp
${INCROOT}/Err.hpp
${INCROOT}/Export.hpp
${INCROOT}/InputStream.hpp
${SRCROOT}/Lock.cpp
${INCROOT}/Lock.hpp
${SRCROOT}/Mutex.cpp
${INCROOT}/Mutex.hpp
${INCROOT}/NonCopyable.hpp
${SRCROOT}/Sleep.cpp
${INCROOT}/Sleep.hpp
${SRCROOT}/String.cpp
${INCROOT}/String.hpp
${INCROOT}/String.inl
${SRCROOT}/Thread.cpp
${INCROOT}/Thread.hpp
${INCROOT}/Thread.inl
${SRCROOT}/ThreadLocal.cpp
${INCROOT}/ThreadLocal.hpp
${INCROOT}/ThreadLocalPtr.hpp
${INCROOT}/ThreadLocalPtr.inl
${SRCROOT}/Time.cpp
${INCROOT}/Time.hpp
${INCROOT}/Utf.hpp
${INCROOT}/Utf.inl
${INCROOT}/Vector2.hpp
${INCROOT}/Vector2.inl
${INCROOT}/Vector3.hpp
${INCROOT}/Vector3.inl
)
source_group("" FILES ${SRC})
# add platform specific sources
if(SFML_OS_WINDOWS)
set(PLATFORM_SRC
${SRCROOT}/Win32/ClockImpl.cpp
${SRCROOT}/Win32/ClockImpl.hpp
${SRCROOT}/Win32/MutexImpl.cpp
${SRCROOT}/Win32/MutexImpl.hpp
${SRCROOT}/Win32/SleepImpl.cpp
${SRCROOT}/Win32/SleepImpl.hpp
${SRCROOT}/Win32/ThreadImpl.cpp
${SRCROOT}/Win32/ThreadImpl.hpp
${SRCROOT}/Win32/ThreadLocalImpl.cpp
${SRCROOT}/Win32/ThreadLocalImpl.hpp
)
source_group("windows" FILES ${PLATFORM_SRC})
else()
set(PLATFORM_SRC
${SRCROOT}/Unix/ClockImpl.cpp
${SRCROOT}/Unix/ClockImpl.hpp
${SRCROOT}/Unix/MutexImpl.cpp
${SRCROOT}/Unix/MutexImpl.hpp
${SRCROOT}/Unix/SleepImpl.cpp
${SRCROOT}/Unix/SleepImpl.hpp
${SRCROOT}/Unix/ThreadImpl.cpp
${SRCROOT}/Unix/ThreadImpl.hpp
${SRCROOT}/Unix/ThreadLocalImpl.cpp
${SRCROOT}/Unix/ThreadLocalImpl.hpp
)
if(SFML_OS_ANDROID)
set(PLATFORM_SRC ${PLATFORM_SRC}
${SRCROOT}/Android/Activity.hpp
${SRCROOT}/Android/Activity.cpp
${SRCROOT}/Android/ResourceStream.cpp
${SRCROOT}/Android/ResourceStream.cpp
)
endif()
source_group("unix" FILES ${PLATFORM_SRC})
endif()
# build the list of external libraries to link
if(SFML_OS_LINUX OR SFML_OS_FREEBSD OR SFML_OS_MACOSX)
list(APPEND SYSTEM_EXT_LIBS pthread)
endif()
if(SFML_OS_LINUX)
list(APPEND SYSTEM_EXT_LIBS rt)
endif()
if(SFML_OS_WINDOWS)
list(APPEND SYSTEM_EXT_LIBS winmm)
endif()
if(SFML_OS_ANDROID)
list(APPEND SYSTEM_EXT_LIBS android log)
endif()
# define the sfml-system target
sfml_add_library(sfml-system
SOURCES ${SRC} ${PLATFORM_SRC}
EXTERNAL_LIBS ${SYSTEM_EXT_LIBS})
list(APPEND SYSTEM_EXT_LIBS pthread)
endif()
if(SFML_OS_LINUX)
list(APPEND SYSTEM_EXT_LIBS rt)
endif()
if(SFML_OS_WINDOWS)
list(APPEND SYSTEM_EXT_LIBS winmm)
endif()
if(SFML_OS_ANDROID)
list(APPEND SYSTEM_EXT_LIBS android log)
endif()
# define the sfml-system target
sfml_add_library(sfml-system
SOURCES ${SRC} ${PLATFORM_SRC}
EXTERNAL_LIBS ${SYSTEM_EXT_LIBS})

View file

@ -1,63 +1,63 @@
////////////////////////////////////////////////////////////
//
// 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/System/Clock.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/ClockImpl.hpp>
#else
#include <SFML/System/Unix/ClockImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
Clock::Clock() :
m_startTime(priv::ClockImpl::getCurrentTime())
{
}
////////////////////////////////////////////////////////////
Time Clock::getElapsedTime() const
{
return priv::ClockImpl::getCurrentTime() - m_startTime;
}
////////////////////////////////////////////////////////////
Time Clock::restart()
{
Time now = priv::ClockImpl::getCurrentTime();
Time elapsed = now - m_startTime;
m_startTime = now;
return elapsed;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Clock.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/ClockImpl.hpp>
#else
#include <SFML/System/Unix/ClockImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
Clock::Clock() :
m_startTime(priv::ClockImpl::getCurrentTime())
{
}
////////////////////////////////////////////////////////////
Time Clock::getElapsedTime() const
{
return priv::ClockImpl::getCurrentTime() - m_startTime;
}
////////////////////////////////////////////////////////////
Time Clock::restart()
{
Time now = priv::ClockImpl::getCurrentTime();
Time elapsed = now - m_startTime;
m_startTime = now;
return elapsed;
}
} // namespace sf

View file

@ -1,110 +1,110 @@
////////////////////////////////////////////////////////////
//
// 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/System/Err.hpp>
#include <streambuf>
#include <cstdio>
namespace
{
// This class will be used as the default streambuf of sf::Err,
// it outputs to stderr by default (to keep the default behaviour)
class DefaultErrStreamBuf : public std::streambuf
{
public :
DefaultErrStreamBuf()
{
// Allocate the write buffer
static const int size = 64;
char* buffer = new char[size];
setp(buffer, buffer + size);
}
~DefaultErrStreamBuf()
{
// Synchronize
sync();
// Delete the write buffer
delete[] pbase();
}
private :
virtual int overflow(int character)
{
if ((character != EOF) && (pptr() != epptr()))
{
// Valid character
return sputc(static_cast<char>(character));
}
else if (character != EOF)
{
// Not enough space in the buffer: synchronize output and try again
sync();
return overflow(character);
}
else
{
// Invalid character: synchronize output
return sync();
}
}
virtual int sync()
{
// Check if there is something into the write buffer
if (pbase() != pptr())
{
// Print the contents of the write buffer into the standard error output
std::size_t size = static_cast<int>(pptr() - pbase());
fwrite(pbase(), 1, size, stderr);
// Reset the pointer position to the beginning of the write buffer
setp(pbase(), epptr());
}
return 0;
}
};
}
namespace sf
{
////////////////////////////////////////////////////////////
std::ostream& err()
{
static DefaultErrStreamBuf buffer;
static std::ostream stream(&buffer);
return stream;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Err.hpp>
#include <streambuf>
#include <cstdio>
namespace
{
// This class will be used as the default streambuf of sf::Err,
// it outputs to stderr by default (to keep the default behaviour)
class DefaultErrStreamBuf : public std::streambuf
{
public:
DefaultErrStreamBuf()
{
// Allocate the write buffer
static const int size = 64;
char* buffer = new char[size];
setp(buffer, buffer + size);
}
~DefaultErrStreamBuf()
{
// Synchronize
sync();
// Delete the write buffer
delete[] pbase();
}
private:
virtual int overflow(int character)
{
if ((character != EOF) && (pptr() != epptr()))
{
// Valid character
return sputc(static_cast<char>(character));
}
else if (character != EOF)
{
// Not enough space in the buffer: synchronize output and try again
sync();
return overflow(character);
}
else
{
// Invalid character: synchronize output
return sync();
}
}
virtual int sync()
{
// Check if there is something into the write buffer
if (pbase() != pptr())
{
// Print the contents of the write buffer into the standard error output
std::size_t size = static_cast<int>(pptr() - pbase());
fwrite(pbase(), 1, size, stderr);
// Reset the pointer position to the beginning of the write buffer
setp(pbase(), epptr());
}
return 0;
}
};
}
namespace sf
{
////////////////////////////////////////////////////////////
std::ostream& err()
{
static DefaultErrStreamBuf buffer;
static std::ostream stream(&buffer);
return stream;
}
} // namespace sf

View file

@ -1,48 +1,48 @@
////////////////////////////////////////////////////////////
//
// 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/System/Lock.hpp>
#include <SFML/System/Mutex.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Lock::Lock(Mutex& mutex) :
m_mutex(mutex)
{
m_mutex.lock();
}
////////////////////////////////////////////////////////////
Lock::~Lock()
{
m_mutex.unlock();
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Lock.hpp>
#include <SFML/System/Mutex.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Lock::Lock(Mutex& mutex) :
m_mutex(mutex)
{
m_mutex.lock();
}
////////////////////////////////////////////////////////////
Lock::~Lock()
{
m_mutex.unlock();
}
} // namespace sf

View file

@ -1,66 +1,66 @@
////////////////////////////////////////////////////////////
//
// 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/System/Mutex.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/MutexImpl.hpp>
#else
#include <SFML/System/Unix/MutexImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
Mutex::Mutex()
{
m_mutexImpl = new priv::MutexImpl;
}
////////////////////////////////////////////////////////////
Mutex::~Mutex()
{
delete m_mutexImpl;
}
////////////////////////////////////////////////////////////
void Mutex::lock()
{
m_mutexImpl->lock();
}
////////////////////////////////////////////////////////////
void Mutex::unlock()
{
m_mutexImpl->unlock();
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Mutex.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/MutexImpl.hpp>
#else
#include <SFML/System/Unix/MutexImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
Mutex::Mutex()
{
m_mutexImpl = new priv::MutexImpl;
}
////////////////////////////////////////////////////////////
Mutex::~Mutex()
{
delete m_mutexImpl;
}
////////////////////////////////////////////////////////////
void Mutex::lock()
{
m_mutexImpl->lock();
}
////////////////////////////////////////////////////////////
void Mutex::unlock()
{
m_mutexImpl->unlock();
}
} // namespace sf

View file

@ -1,46 +1,46 @@
////////////////////////////////////////////////////////////
//
// 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/System/Sleep.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/SleepImpl.hpp>
#else
#include <SFML/System/Unix/SleepImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
void sleep(Time duration)
{
if (duration >= Time::Zero)
priv::sleepImpl(duration);
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Sleep.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/SleepImpl.hpp>
#else
#include <SFML/System/Unix/SleepImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
void sleep(Time duration)
{
if (duration >= Time::Zero)
priv::sleepImpl(duration);
}
} // namespace sf

View file

@ -1,400 +1,400 @@
////////////////////////////////////////////////////////////
//
// 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/System/String.hpp>
#include <SFML/System/Utf.hpp>
#include <iterator>
#include <cstring>
namespace sf
{
////////////////////////////////////////////////////////////
const std::size_t String::InvalidPos = std::basic_string<Uint32>::npos;
////////////////////////////////////////////////////////////
String::String()
{
}
////////////////////////////////////////////////////////////
String::String(char ansiChar, const std::locale& locale)
{
m_string += Utf32::decodeAnsi(ansiChar, locale);
}
////////////////////////////////////////////////////////////
String::String(wchar_t wideChar)
{
m_string += Utf32::decodeWide(wideChar);
}
////////////////////////////////////////////////////////////
String::String(Uint32 utf32Char)
{
m_string += utf32Char;
}
////////////////////////////////////////////////////////////
String::String(const char* ansiString, const std::locale& locale)
{
if (ansiString)
{
std::size_t length = strlen(ansiString);
if (length > 0)
{
m_string.reserve(length + 1);
Utf32::fromAnsi(ansiString, ansiString + length, std::back_inserter(m_string), locale);
}
}
}
////////////////////////////////////////////////////////////
String::String(const std::string& ansiString, const std::locale& locale)
{
m_string.reserve(ansiString.length() + 1);
Utf32::fromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_string), locale);
}
////////////////////////////////////////////////////////////
String::String(const wchar_t* wideString)
{
if (wideString)
{
std::size_t length = std::wcslen(wideString);
if (length > 0)
{
m_string.reserve(length + 1);
Utf32::fromWide(wideString, wideString + length, std::back_inserter(m_string));
}
}
}
////////////////////////////////////////////////////////////
String::String(const std::wstring& wideString)
{
m_string.reserve(wideString.length() + 1);
Utf32::fromWide(wideString.begin(), wideString.end(), std::back_inserter(m_string));
}
////////////////////////////////////////////////////////////
String::String(const Uint32* utf32String)
{
if (utf32String)
m_string = utf32String;
}
////////////////////////////////////////////////////////////
String::String(const std::basic_string<Uint32>& utf32String) :
m_string(utf32String)
{
}
////////////////////////////////////////////////////////////
String::String(const String& copy) :
m_string(copy.m_string)
{
}
////////////////////////////////////////////////////////////
String::operator std::string() const
{
return toAnsiString();
}
////////////////////////////////////////////////////////////
String::operator std::wstring() const
{
return toWideString();
}
////////////////////////////////////////////////////////////
std::string String::toAnsiString(const std::locale& locale) const
{
// Prepare the output string
std::string output;
output.reserve(m_string.length() + 1);
// Convert
Utf32::toAnsi(m_string.begin(), m_string.end(), std::back_inserter(output), 0, locale);
return output;
}
////////////////////////////////////////////////////////////
std::wstring String::toWideString() const
{
// Prepare the output string
std::wstring output;
output.reserve(m_string.length() + 1);
// Convert
Utf32::toWide(m_string.begin(), m_string.end(), std::back_inserter(output), 0);
return output;
}
////////////////////////////////////////////////////////////
std::basic_string<Uint8> String::toUtf8() const
{
// Prepare the output string
std::basic_string<Uint8> output;
output.reserve(m_string.length());
// Convert
Utf32::toUtf8(m_string.begin(), m_string.end(), std::back_inserter(output));
return output;
}
////////////////////////////////////////////////////////////
std::basic_string<Uint16> String::toUtf16() const
{
// Prepare the output string
std::basic_string<Uint16> output;
output.reserve(m_string.length());
// Convert
Utf32::toUtf16(m_string.begin(), m_string.end(), std::back_inserter(output));
return output;
}
////////////////////////////////////////////////////////////
std::basic_string<Uint32> String::toUtf32() const
{
return m_string;
}
////////////////////////////////////////////////////////////
String& String::operator =(const String& right)
{
m_string = right.m_string;
return *this;
}
////////////////////////////////////////////////////////////
String& String::operator +=(const String& right)
{
m_string += right.m_string;
return *this;
}
////////////////////////////////////////////////////////////
Uint32 String::operator [](std::size_t index) const
{
return m_string[index];
}
////////////////////////////////////////////////////////////
Uint32& String::operator [](std::size_t index)
{
return m_string[index];
}
////////////////////////////////////////////////////////////
void String::clear()
{
m_string.clear();
}
////////////////////////////////////////////////////////////
std::size_t String::getSize() const
{
return m_string.size();
}
////////////////////////////////////////////////////////////
bool String::isEmpty() const
{
return m_string.empty();
}
////////////////////////////////////////////////////////////
void String::erase(std::size_t position, std::size_t count)
{
m_string.erase(position, count);
}
////////////////////////////////////////////////////////////
void String::insert(std::size_t position, const String& str)
{
m_string.insert(position, str.m_string);
}
////////////////////////////////////////////////////////////
std::size_t String::find(const String& str, std::size_t start) const
{
return m_string.find(str.m_string, start);
}
////////////////////////////////////////////////////////////
void String::replace(std::size_t position, std::size_t length, const String& replaceWith)
{
m_string.replace(position, length, replaceWith.m_string);
}
////////////////////////////////////////////////////////////
void String::replace(const String& searchFor, const String& replaceWith)
{
std::size_t step = replaceWith.getSize();
std::size_t len = searchFor.getSize();
std::size_t pos = find(searchFor);
// Replace each occurence of search
while (pos != InvalidPos)
{
replace(pos, len, replaceWith);
pos = find(searchFor, pos + step);
}
}
////////////////////////////////////////////////////////////
String String::substring(std::size_t position, std::size_t length) const
{
return m_string.substr(position, length);
}
////////////////////////////////////////////////////////////
const Uint32* String::getData() const
{
return m_string.c_str();
}
////////////////////////////////////////////////////////////
String::Iterator String::begin()
{
return m_string.begin();
}
////////////////////////////////////////////////////////////
String::ConstIterator String::begin() const
{
return m_string.begin();
}
////////////////////////////////////////////////////////////
String::Iterator String::end()
{
return m_string.end();
}
////////////////////////////////////////////////////////////
String::ConstIterator String::end() const
{
return m_string.end();
}
////////////////////////////////////////////////////////////
bool operator ==(const String& left, const String& right)
{
return left.m_string == right.m_string;
}
////////////////////////////////////////////////////////////
bool operator !=(const String& left, const String& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
bool operator <(const String& left, const String& right)
{
return left.m_string < right.m_string;
}
////////////////////////////////////////////////////////////
bool operator >(const String& left, const String& right)
{
return right < left;
}
////////////////////////////////////////////////////////////
bool operator <=(const String& left, const String& right)
{
return !(right < left);
}
////////////////////////////////////////////////////////////
bool operator >=(const String& left, const String& right)
{
return !(left < right);
}
////////////////////////////////////////////////////////////
String operator +(const String& left, const String& right)
{
String string = left;
string += right;
return string;
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/String.hpp>
#include <SFML/System/Utf.hpp>
#include <iterator>
#include <cstring>
namespace sf
{
////////////////////////////////////////////////////////////
const std::size_t String::InvalidPos = std::basic_string<Uint32>::npos;
////////////////////////////////////////////////////////////
String::String()
{
}
////////////////////////////////////////////////////////////
String::String(char ansiChar, const std::locale& locale)
{
m_string += Utf32::decodeAnsi(ansiChar, locale);
}
////////////////////////////////////////////////////////////
String::String(wchar_t wideChar)
{
m_string += Utf32::decodeWide(wideChar);
}
////////////////////////////////////////////////////////////
String::String(Uint32 utf32Char)
{
m_string += utf32Char;
}
////////////////////////////////////////////////////////////
String::String(const char* ansiString, const std::locale& locale)
{
if (ansiString)
{
std::size_t length = strlen(ansiString);
if (length > 0)
{
m_string.reserve(length + 1);
Utf32::fromAnsi(ansiString, ansiString + length, std::back_inserter(m_string), locale);
}
}
}
////////////////////////////////////////////////////////////
String::String(const std::string& ansiString, const std::locale& locale)
{
m_string.reserve(ansiString.length() + 1);
Utf32::fromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(m_string), locale);
}
////////////////////////////////////////////////////////////
String::String(const wchar_t* wideString)
{
if (wideString)
{
std::size_t length = std::wcslen(wideString);
if (length > 0)
{
m_string.reserve(length + 1);
Utf32::fromWide(wideString, wideString + length, std::back_inserter(m_string));
}
}
}
////////////////////////////////////////////////////////////
String::String(const std::wstring& wideString)
{
m_string.reserve(wideString.length() + 1);
Utf32::fromWide(wideString.begin(), wideString.end(), std::back_inserter(m_string));
}
////////////////////////////////////////////////////////////
String::String(const Uint32* utf32String)
{
if (utf32String)
m_string = utf32String;
}
////////////////////////////////////////////////////////////
String::String(const std::basic_string<Uint32>& utf32String) :
m_string(utf32String)
{
}
////////////////////////////////////////////////////////////
String::String(const String& copy) :
m_string(copy.m_string)
{
}
////////////////////////////////////////////////////////////
String::operator std::string() const
{
return toAnsiString();
}
////////////////////////////////////////////////////////////
String::operator std::wstring() const
{
return toWideString();
}
////////////////////////////////////////////////////////////
std::string String::toAnsiString(const std::locale& locale) const
{
// Prepare the output string
std::string output;
output.reserve(m_string.length() + 1);
// Convert
Utf32::toAnsi(m_string.begin(), m_string.end(), std::back_inserter(output), 0, locale);
return output;
}
////////////////////////////////////////////////////////////
std::wstring String::toWideString() const
{
// Prepare the output string
std::wstring output;
output.reserve(m_string.length() + 1);
// Convert
Utf32::toWide(m_string.begin(), m_string.end(), std::back_inserter(output), 0);
return output;
}
////////////////////////////////////////////////////////////
std::basic_string<Uint8> String::toUtf8() const
{
// Prepare the output string
std::basic_string<Uint8> output;
output.reserve(m_string.length());
// Convert
Utf32::toUtf8(m_string.begin(), m_string.end(), std::back_inserter(output));
return output;
}
////////////////////////////////////////////////////////////
std::basic_string<Uint16> String::toUtf16() const
{
// Prepare the output string
std::basic_string<Uint16> output;
output.reserve(m_string.length());
// Convert
Utf32::toUtf16(m_string.begin(), m_string.end(), std::back_inserter(output));
return output;
}
////////////////////////////////////////////////////////////
std::basic_string<Uint32> String::toUtf32() const
{
return m_string;
}
////////////////////////////////////////////////////////////
String& String::operator =(const String& right)
{
m_string = right.m_string;
return *this;
}
////////////////////////////////////////////////////////////
String& String::operator +=(const String& right)
{
m_string += right.m_string;
return *this;
}
////////////////////////////////////////////////////////////
Uint32 String::operator [](std::size_t index) const
{
return m_string[index];
}
////////////////////////////////////////////////////////////
Uint32& String::operator [](std::size_t index)
{
return m_string[index];
}
////////////////////////////////////////////////////////////
void String::clear()
{
m_string.clear();
}
////////////////////////////////////////////////////////////
std::size_t String::getSize() const
{
return m_string.size();
}
////////////////////////////////////////////////////////////
bool String::isEmpty() const
{
return m_string.empty();
}
////////////////////////////////////////////////////////////
void String::erase(std::size_t position, std::size_t count)
{
m_string.erase(position, count);
}
////////////////////////////////////////////////////////////
void String::insert(std::size_t position, const String& str)
{
m_string.insert(position, str.m_string);
}
////////////////////////////////////////////////////////////
std::size_t String::find(const String& str, std::size_t start) const
{
return m_string.find(str.m_string, start);
}
////////////////////////////////////////////////////////////
void String::replace(std::size_t position, std::size_t length, const String& replaceWith)
{
m_string.replace(position, length, replaceWith.m_string);
}
////////////////////////////////////////////////////////////
void String::replace(const String& searchFor, const String& replaceWith)
{
std::size_t step = replaceWith.getSize();
std::size_t len = searchFor.getSize();
std::size_t pos = find(searchFor);
// Replace each occurence of search
while (pos != InvalidPos)
{
replace(pos, len, replaceWith);
pos = find(searchFor, pos + step);
}
}
////////////////////////////////////////////////////////////
String String::substring(std::size_t position, std::size_t length) const
{
return m_string.substr(position, length);
}
////////////////////////////////////////////////////////////
const Uint32* String::getData() const
{
return m_string.c_str();
}
////////////////////////////////////////////////////////////
String::Iterator String::begin()
{
return m_string.begin();
}
////////////////////////////////////////////////////////////
String::ConstIterator String::begin() const
{
return m_string.begin();
}
////////////////////////////////////////////////////////////
String::Iterator String::end()
{
return m_string.end();
}
////////////////////////////////////////////////////////////
String::ConstIterator String::end() const
{
return m_string.end();
}
////////////////////////////////////////////////////////////
bool operator ==(const String& left, const String& right)
{
return left.m_string == right.m_string;
}
////////////////////////////////////////////////////////////
bool operator !=(const String& left, const String& right)
{
return !(left == right);
}
////////////////////////////////////////////////////////////
bool operator <(const String& left, const String& right)
{
return left.m_string < right.m_string;
}
////////////////////////////////////////////////////////////
bool operator >(const String& left, const String& right)
{
return right < left;
}
////////////////////////////////////////////////////////////
bool operator <=(const String& left, const String& right)
{
return !(right < left);
}
////////////////////////////////////////////////////////////
bool operator >=(const String& left, const String& right)
{
return !(left < right);
}
////////////////////////////////////////////////////////////
String operator +(const String& left, const String& right)
{
String string = left;
string += right;
return string;
}
} // namespace sf

View file

@ -1,86 +1,86 @@
////////////////////////////////////////////////////////////
//
// 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/System/Thread.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/ThreadImpl.hpp>
#else
#include <SFML/System/Unix/ThreadImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
Thread::~Thread()
{
wait();
delete m_entryPoint;
}
////////////////////////////////////////////////////////////
void Thread::launch()
{
wait();
m_impl = new priv::ThreadImpl(this);
}
////////////////////////////////////////////////////////////
void Thread::wait()
{
if (m_impl)
{
m_impl->wait();
delete m_impl;
m_impl = NULL;
}
}
////////////////////////////////////////////////////////////
void Thread::terminate()
{
if (m_impl)
{
m_impl->terminate();
delete m_impl;
m_impl = NULL;
}
}
////////////////////////////////////////////////////////////
void Thread::run()
{
m_entryPoint->run();
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Thread.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/ThreadImpl.hpp>
#else
#include <SFML/System/Unix/ThreadImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
Thread::~Thread()
{
wait();
delete m_entryPoint;
}
////////////////////////////////////////////////////////////
void Thread::launch()
{
wait();
m_impl = new priv::ThreadImpl(this);
}
////////////////////////////////////////////////////////////
void Thread::wait()
{
if (m_impl)
{
m_impl->wait();
delete m_impl;
m_impl = NULL;
}
}
////////////////////////////////////////////////////////////
void Thread::terminate()
{
if (m_impl)
{
m_impl->terminate();
delete m_impl;
m_impl = NULL;
}
}
////////////////////////////////////////////////////////////
void Thread::run()
{
m_entryPoint->run();
}
} // namespace sf

View file

@ -1,67 +1,67 @@
////////////////////////////////////////////////////////////
//
// 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/System/ThreadLocal.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/ThreadLocalImpl.hpp>
#else
#include <SFML/System/Unix/ThreadLocalImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
ThreadLocal::ThreadLocal(void* value)
{
m_impl = new priv::ThreadLocalImpl;
setValue(value);
}
////////////////////////////////////////////////////////////
ThreadLocal::~ThreadLocal()
{
delete m_impl;
}
////////////////////////////////////////////////////////////
void ThreadLocal::setValue(void* value)
{
m_impl->setValue(value);
}
////////////////////////////////////////////////////////////
void* ThreadLocal::getValue() const
{
return m_impl->getValue();
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/ThreadLocal.hpp>
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/System/Win32/ThreadLocalImpl.hpp>
#else
#include <SFML/System/Unix/ThreadLocalImpl.hpp>
#endif
namespace sf
{
////////////////////////////////////////////////////////////
ThreadLocal::ThreadLocal(void* value)
{
m_impl = new priv::ThreadLocalImpl;
setValue(value);
}
////////////////////////////////////////////////////////////
ThreadLocal::~ThreadLocal()
{
delete m_impl;
}
////////////////////////////////////////////////////////////
void ThreadLocal::setValue(void* value)
{
m_impl->setValue(value);
}
////////////////////////////////////////////////////////////
void* ThreadLocal::getValue() const
{
return m_impl->getValue();
}
} // namespace sf

View file

@ -42,7 +42,7 @@ namespace priv
////////////////////////////////////////////////////////////
class ClockImpl
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Get the current time

View file

@ -1,69 +1,69 @@
////////////////////////////////////////////////////////////
//
// 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/System/Unix/MutexImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
MutexImpl::MutexImpl()
{
// Make it recursive to follow the expected behaviour
pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes);
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attributes);
}
////////////////////////////////////////////////////////////
MutexImpl::~MutexImpl()
{
pthread_mutex_destroy(&m_mutex);
}
////////////////////////////////////////////////////////////
void MutexImpl::lock()
{
pthread_mutex_lock(&m_mutex);
}
////////////////////////////////////////////////////////////
void MutexImpl::unlock()
{
pthread_mutex_unlock(&m_mutex);
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Unix/MutexImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
MutexImpl::MutexImpl()
{
// Make it recursive to follow the expected behaviour
pthread_mutexattr_t attributes;
pthread_mutexattr_init(&attributes);
pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_mutex, &attributes);
}
////////////////////////////////////////////////////////////
MutexImpl::~MutexImpl()
{
pthread_mutex_destroy(&m_mutex);
}
////////////////////////////////////////////////////////////
void MutexImpl::lock()
{
pthread_mutex_lock(&m_mutex);
}
////////////////////////////////////////////////////////////
void MutexImpl::unlock()
{
pthread_mutex_unlock(&m_mutex);
}
} // namespace priv
} // namespace sf

View file

@ -1,83 +1,83 @@
////////////////////////////////////////////////////////////
//
// 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_MUTEXIMPL_HPP
#define SFML_MUTEXIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <pthread.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Unix implementation of mutexes
////////////////////////////////////////////////////////////
class MutexImpl : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
MutexImpl();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~MutexImpl();
////////////////////////////////////////////////////////////
/// \brief Lock the mutex
///
////////////////////////////////////////////////////////////
void lock();
////////////////////////////////////////////////////////////
/// \brief Unlock the mutex
///
////////////////////////////////////////////////////////////
void unlock();
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
pthread_mutex_t m_mutex; ///< pthread handle of the mutex
};
} // namespace priv
} // namespace sf
#endif // SFML_MUTEXIMPL_HPP
////////////////////////////////////////////////////////////
//
// 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_MUTEXIMPL_HPP
#define SFML_MUTEXIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <pthread.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Unix implementation of mutexes
////////////////////////////////////////////////////////////
class MutexImpl : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
MutexImpl();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~MutexImpl();
////////////////////////////////////////////////////////////
/// \brief Lock the mutex
///
////////////////////////////////////////////////////////////
void lock();
////////////////////////////////////////////////////////////
/// \brief Unlock the mutex
///
////////////////////////////////////////////////////////////
void unlock();
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
pthread_mutex_t m_mutex; ///< pthread handle of the mutex
};
} // namespace priv
} // namespace sf
#endif // SFML_MUTEXIMPL_HPP

View file

@ -1,94 +1,94 @@
////////////////////////////////////////////////////////////
//
// 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/System/Unix/ThreadImpl.hpp>
#include <SFML/System/Thread.hpp>
#include <iostream>
#include <cassert>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ThreadImpl::ThreadImpl(Thread* owner) :
m_isActive(true)
{
m_isActive = pthread_create(&m_thread, NULL, &ThreadImpl::entryPoint, owner) == 0;
if (!m_isActive)
std::cerr << "Failed to create thread" << std::endl;
}
////////////////////////////////////////////////////////////
void ThreadImpl::wait()
{
if (m_isActive)
{
assert(pthread_equal(pthread_self(), m_thread) == 0); // A thread cannot wait for itself!
pthread_join(m_thread, NULL);
}
}
////////////////////////////////////////////////////////////
void ThreadImpl::terminate()
{
if (m_isActive)
{
#ifndef SFML_SYSTEM_ANDROID
pthread_cancel(m_thread);
#else
// See http://stackoverflow.com/questions/4610086/pthread-cancel-al
pthread_kill(m_thread, SIGUSR1);
#endif
}
}
////////////////////////////////////////////////////////////
void* ThreadImpl::entryPoint(void* userData)
{
// The Thread instance is stored in the user data
Thread* owner = static_cast<Thread*>(userData);
#ifndef SFML_SYSTEM_ANDROID
// Tell the thread to handle cancel requests immediatly
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
#endif
// Forward to the owner
owner->run();
return NULL;
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Unix/ThreadImpl.hpp>
#include <SFML/System/Thread.hpp>
#include <iostream>
#include <cassert>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ThreadImpl::ThreadImpl(Thread* owner) :
m_isActive(true)
{
m_isActive = pthread_create(&m_thread, NULL, &ThreadImpl::entryPoint, owner) == 0;
if (!m_isActive)
std::cerr << "Failed to create thread" << std::endl;
}
////////////////////////////////////////////////////////////
void ThreadImpl::wait()
{
if (m_isActive)
{
assert(pthread_equal(pthread_self(), m_thread) == 0); // A thread cannot wait for itself!
pthread_join(m_thread, NULL);
}
}
////////////////////////////////////////////////////////////
void ThreadImpl::terminate()
{
if (m_isActive)
{
#ifndef SFML_SYSTEM_ANDROID
pthread_cancel(m_thread);
#else
// See http://stackoverflow.com/questions/4610086/pthread-cancel-al
pthread_kill(m_thread, SIGUSR1);
#endif
}
}
////////////////////////////////////////////////////////////
void* ThreadImpl::entryPoint(void* userData)
{
// The Thread instance is stored in the user data
Thread* owner = static_cast<Thread*>(userData);
#ifndef SFML_SYSTEM_ANDROID
// Tell the thread to handle cancel requests immediatly
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
#endif
// Forward to the owner
owner->run();
return NULL;
}
} // namespace priv
} // namespace sf

View file

@ -1,93 +1,93 @@
////////////////////////////////////////////////////////////
//
// 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_THREADIMPL_HPP
#define SFML_THREADIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <pthread.h>
namespace sf
{
class Thread;
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Unix implementation of threads
////////////////////////////////////////////////////////////
class ThreadImpl : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor, launch the thread
///
/// \param owner The Thread instance to run
///
////////////////////////////////////////////////////////////
ThreadImpl(Thread* owner);
////////////////////////////////////////////////////////////
/// \brief Wait until the thread finishes
///
////////////////////////////////////////////////////////////
void wait();
////////////////////////////////////////////////////////////
/// \brief Terminate the thread
///
////////////////////////////////////////////////////////////
void terminate();
private :
////////////////////////////////////////////////////////////
/// \brief Global entry point for all threads
///
/// \param userData User-defined data (contains the Thread instance)
///
/// \return Os specific error code
///
////////////////////////////////////////////////////////////
static void* entryPoint(void* userData);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
pthread_t m_thread; ///< pthread thread instance
bool m_isActive; ///< Thread state (active or inactive)
};
} // namespace priv
} // namespace sf
#endif // SFML_THREADIMPL_HPP
////////////////////////////////////////////////////////////
//
// 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_THREADIMPL_HPP
#define SFML_THREADIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/System/NonCopyable.hpp>
#include <pthread.h>
namespace sf
{
class Thread;
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Unix implementation of threads
////////////////////////////////////////////////////////////
class ThreadImpl : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor, launch the thread
///
/// \param owner The Thread instance to run
///
////////////////////////////////////////////////////////////
ThreadImpl(Thread* owner);
////////////////////////////////////////////////////////////
/// \brief Wait until the thread finishes
///
////////////////////////////////////////////////////////////
void wait();
////////////////////////////////////////////////////////////
/// \brief Terminate the thread
///
////////////////////////////////////////////////////////////
void terminate();
private:
////////////////////////////////////////////////////////////
/// \brief Global entry point for all threads
///
/// \param userData User-defined data (contains the Thread instance)
///
/// \return Os specific error code
///
////////////////////////////////////////////////////////////
static void* entryPoint(void* userData);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
pthread_t m_thread; ///< pthread thread instance
bool m_isActive; ///< Thread state (active or inactive)
};
} // namespace priv
} // namespace sf
#endif // SFML_THREADIMPL_HPP

View file

@ -1,64 +1,64 @@
////////////////////////////////////////////////////////////
//
// 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/System/Unix/ThreadLocalImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ThreadLocalImpl::ThreadLocalImpl()
{
pthread_key_create(&m_key, NULL);
}
////////////////////////////////////////////////////////////
ThreadLocalImpl::~ThreadLocalImpl()
{
pthread_key_delete(m_key);
}
////////////////////////////////////////////////////////////
void ThreadLocalImpl::setValue(void* value)
{
pthread_setspecific(m_key, value);
}
////////////////////////////////////////////////////////////
void* ThreadLocalImpl::getValue() const
{
return pthread_getspecific(m_key);
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Unix/ThreadLocalImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ThreadLocalImpl::ThreadLocalImpl()
{
pthread_key_create(&m_key, NULL);
}
////////////////////////////////////////////////////////////
ThreadLocalImpl::~ThreadLocalImpl()
{
pthread_key_delete(m_key);
}
////////////////////////////////////////////////////////////
void ThreadLocalImpl::setValue(void* value)
{
pthread_setspecific(m_key, value);
}
////////////////////////////////////////////////////////////
void* ThreadLocalImpl::getValue() const
{
return pthread_getspecific(m_key);
}
} // namespace priv
} // namespace sf

View file

@ -1,87 +1,87 @@
////////////////////////////////////////////////////////////
//
// 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_THREADLOCALIMPL_HPP
#define SFML_THREADLOCALIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <pthread.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Unix implementation of thread-local storage
////////////////////////////////////////////////////////////
class ThreadLocalImpl : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor -- allocate the storage
///
////////////////////////////////////////////////////////////
ThreadLocalImpl();
////////////////////////////////////////////////////////////
/// \brief Destructor -- free the storage
///
////////////////////////////////////////////////////////////
~ThreadLocalImpl();
////////////////////////////////////////////////////////////
/// \brief Set the thread-specific value of the variable
///
/// \param value Value of the variable for this thread
///
////////////////////////////////////////////////////////////
void setValue(void* value);
////////////////////////////////////////////////////////////
/// \brief Retrieve the thread-specific value of the variable
///
/// \return Value of the variable for this thread
///
////////////////////////////////////////////////////////////
void* getValue() const;
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
pthread_key_t m_key; ///< Index of our thread-local storage slot
};
} // namespace priv
} // namespace sf
#endif // SFML_THREADLOCALIMPL_HPP
////////////////////////////////////////////////////////////
//
// 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_THREADLOCALIMPL_HPP
#define SFML_THREADLOCALIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <pthread.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Unix implementation of thread-local storage
////////////////////////////////////////////////////////////
class ThreadLocalImpl : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor -- allocate the storage
///
////////////////////////////////////////////////////////////
ThreadLocalImpl();
////////////////////////////////////////////////////////////
/// \brief Destructor -- free the storage
///
////////////////////////////////////////////////////////////
~ThreadLocalImpl();
////////////////////////////////////////////////////////////
/// \brief Set the thread-specific value of the variable
///
/// \param value Value of the variable for this thread
///
////////////////////////////////////////////////////////////
void setValue(void* value);
////////////////////////////////////////////////////////////
/// \brief Retrieve the thread-specific value of the variable
///
/// \return Value of the variable for this thread
///
////////////////////////////////////////////////////////////
void* getValue() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
pthread_key_t m_key; ///< Index of our thread-local storage slot
};
} // namespace priv
} // namespace sf
#endif // SFML_THREADLOCALIMPL_HPP

View file

@ -42,7 +42,7 @@ namespace priv
////////////////////////////////////////////////////////////
class ClockImpl
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Get the current time

View file

@ -1,64 +1,64 @@
////////////////////////////////////////////////////////////
//
// 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/System/Win32/MutexImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
MutexImpl::MutexImpl()
{
InitializeCriticalSection(&m_mutex);
}
////////////////////////////////////////////////////////////
MutexImpl::~MutexImpl()
{
DeleteCriticalSection(&m_mutex);
}
////////////////////////////////////////////////////////////
void MutexImpl::lock()
{
EnterCriticalSection(&m_mutex);
}
////////////////////////////////////////////////////////////
void MutexImpl::unlock()
{
LeaveCriticalSection(&m_mutex);
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Win32/MutexImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
MutexImpl::MutexImpl()
{
InitializeCriticalSection(&m_mutex);
}
////////////////////////////////////////////////////////////
MutexImpl::~MutexImpl()
{
DeleteCriticalSection(&m_mutex);
}
////////////////////////////////////////////////////////////
void MutexImpl::lock()
{
EnterCriticalSection(&m_mutex);
}
////////////////////////////////////////////////////////////
void MutexImpl::unlock()
{
LeaveCriticalSection(&m_mutex);
}
} // namespace priv
} // namespace sf

View file

@ -1,83 +1,83 @@
////////////////////////////////////////////////////////////
//
// 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_MUTEXIMPL_HPP
#define SFML_MUTEXIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <windows.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Windows implementation of mutexes
////////////////////////////////////////////////////////////
class MutexImpl : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
MutexImpl();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~MutexImpl();
////////////////////////////////////////////////////////////
/// \brief Lock the mutex
///
////////////////////////////////////////////////////////////
void lock();
////////////////////////////////////////////////////////////
/// \brief Unlock the mutex
///
////////////////////////////////////////////////////////////
void unlock();
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
CRITICAL_SECTION m_mutex; ///< Win32 handle of the mutex
};
} // namespace priv
} // namespace sf
#endif // SFML_MUTEXIMPL_HPP
////////////////////////////////////////////////////////////
//
// 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_MUTEXIMPL_HPP
#define SFML_MUTEXIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <windows.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Windows implementation of mutexes
////////////////////////////////////////////////////////////
class MutexImpl : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
////////////////////////////////////////////////////////////
MutexImpl();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~MutexImpl();
////////////////////////////////////////////////////////////
/// \brief Lock the mutex
///
////////////////////////////////////////////////////////////
void lock();
////////////////////////////////////////////////////////////
/// \brief Unlock the mutex
///
////////////////////////////////////////////////////////////
void unlock();
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
CRITICAL_SECTION m_mutex; ///< Win32 handle of the mutex
};
} // namespace priv
} // namespace sf
#endif // SFML_MUTEXIMPL_HPP

View file

@ -1,93 +1,93 @@
////////////////////////////////////////////////////////////
//
// 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/System/Win32/ThreadImpl.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
#include <process.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ThreadImpl::ThreadImpl(Thread* owner)
{
m_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &ThreadImpl::entryPoint, owner, 0, &m_threadId));
if (!m_thread)
err() << "Failed to create thread" << std::endl;
}
////////////////////////////////////////////////////////////
ThreadImpl::~ThreadImpl()
{
if (m_thread)
CloseHandle(m_thread);
}
////////////////////////////////////////////////////////////
void ThreadImpl::wait()
{
if (m_thread)
{
assert(m_threadId != GetCurrentThreadId()); // A thread cannot wait for itself!
WaitForSingleObject(m_thread, INFINITE);
}
}
////////////////////////////////////////////////////////////
void ThreadImpl::terminate()
{
if (m_thread)
TerminateThread(m_thread, 0);
}
////////////////////////////////////////////////////////////
unsigned int __stdcall ThreadImpl::entryPoint(void* userData)
{
// The Thread instance is stored in the user data
Thread* owner = static_cast<Thread*>(userData);
// Forward to the owner
owner->run();
// Optional, but it is cleaner
_endthreadex(0);
return 0;
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Win32/ThreadImpl.hpp>
#include <SFML/System/Thread.hpp>
#include <SFML/System/Err.hpp>
#include <cassert>
#include <process.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ThreadImpl::ThreadImpl(Thread* owner)
{
m_thread = reinterpret_cast<HANDLE>(_beginthreadex(NULL, 0, &ThreadImpl::entryPoint, owner, 0, &m_threadId));
if (!m_thread)
err() << "Failed to create thread" << std::endl;
}
////////////////////////////////////////////////////////////
ThreadImpl::~ThreadImpl()
{
if (m_thread)
CloseHandle(m_thread);
}
////////////////////////////////////////////////////////////
void ThreadImpl::wait()
{
if (m_thread)
{
assert(m_threadId != GetCurrentThreadId()); // A thread cannot wait for itself!
WaitForSingleObject(m_thread, INFINITE);
}
}
////////////////////////////////////////////////////////////
void ThreadImpl::terminate()
{
if (m_thread)
TerminateThread(m_thread, 0);
}
////////////////////////////////////////////////////////////
unsigned int __stdcall ThreadImpl::entryPoint(void* userData)
{
// The Thread instance is stored in the user data
Thread* owner = static_cast<Thread*>(userData);
// Forward to the owner
owner->run();
// Optional, but it is cleaner
_endthreadex(0);
return 0;
}
} // namespace priv
} // namespace sf

View file

@ -1,109 +1,109 @@
////////////////////////////////////////////////////////////
//
// 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_THREADIMPL_HPP
#define SFML_THREADIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <windows.h>
// Fix for unaligned stack with clang and GCC on Windows XP 32-bit
#if defined(SFML_SYSTEM_WINDOWS) && (defined(__clang__) || defined(__GNUC__))
#define ALIGN_STACK __attribute__((__force_align_arg_pointer__))
#else
#define ALIGN_STACK
#endif
namespace sf
{
class Thread;
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Windows implementation of threads
////////////////////////////////////////////////////////////
class ThreadImpl : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor, launch the thread
///
/// \param owner The Thread instance to run
///
////////////////////////////////////////////////////////////
ThreadImpl(Thread* owner);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~ThreadImpl();
////////////////////////////////////////////////////////////
/// \brief Wait until the thread finishes
///
////////////////////////////////////////////////////////////
void wait();
////////////////////////////////////////////////////////////
/// \brief Terminate the thread
///
////////////////////////////////////////////////////////////
void terminate();
private :
////////////////////////////////////////////////////////////
/// \brief Global entry point for all threads
///
/// \param userData User-defined data (contains the Thread instance)
///
/// \return OS specific error code
///
////////////////////////////////////////////////////////////
ALIGN_STACK static unsigned int __stdcall entryPoint(void* userData);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
HANDLE m_thread; ///< Win32 thread handle
unsigned int m_threadId; ///< Win32 thread identifier
};
} // namespace priv
} // namespace sf
#endif // SFML_THREADIMPL_HPP
////////////////////////////////////////////////////////////
//
// 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_THREADIMPL_HPP
#define SFML_THREADIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <windows.h>
// Fix for unaligned stack with clang and GCC on Windows XP 32-bit
#if defined(SFML_SYSTEM_WINDOWS) && (defined(__clang__) || defined(__GNUC__))
#define ALIGN_STACK __attribute__((__force_align_arg_pointer__))
#else
#define ALIGN_STACK
#endif
namespace sf
{
class Thread;
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Windows implementation of threads
////////////////////////////////////////////////////////////
class ThreadImpl : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor, launch the thread
///
/// \param owner The Thread instance to run
///
////////////////////////////////////////////////////////////
ThreadImpl(Thread* owner);
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
~ThreadImpl();
////////////////////////////////////////////////////////////
/// \brief Wait until the thread finishes
///
////////////////////////////////////////////////////////////
void wait();
////////////////////////////////////////////////////////////
/// \brief Terminate the thread
///
////////////////////////////////////////////////////////////
void terminate();
private:
////////////////////////////////////////////////////////////
/// \brief Global entry point for all threads
///
/// \param userData User-defined data (contains the Thread instance)
///
/// \return OS specific error code
///
////////////////////////////////////////////////////////////
ALIGN_STACK static unsigned int __stdcall entryPoint(void* userData);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
HANDLE m_thread; ///< Win32 thread handle
unsigned int m_threadId; ///< Win32 thread identifier
};
} // namespace priv
} // namespace sf
#endif // SFML_THREADIMPL_HPP

View file

@ -1,64 +1,64 @@
////////////////////////////////////////////////////////////
//
// 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/System/Win32/ThreadLocalImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ThreadLocalImpl::ThreadLocalImpl()
{
m_index = TlsAlloc();
}
////////////////////////////////////////////////////////////
ThreadLocalImpl::~ThreadLocalImpl()
{
TlsFree(m_index);
}
////////////////////////////////////////////////////////////
void ThreadLocalImpl::setValue(void* value)
{
TlsSetValue(m_index, value);
}
////////////////////////////////////////////////////////////
void* ThreadLocalImpl::getValue() const
{
return TlsGetValue(m_index);
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/System/Win32/ThreadLocalImpl.hpp>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
ThreadLocalImpl::ThreadLocalImpl()
{
m_index = TlsAlloc();
}
////////////////////////////////////////////////////////////
ThreadLocalImpl::~ThreadLocalImpl()
{
TlsFree(m_index);
}
////////////////////////////////////////////////////////////
void ThreadLocalImpl::setValue(void* value)
{
TlsSetValue(m_index, value);
}
////////////////////////////////////////////////////////////
void* ThreadLocalImpl::getValue() const
{
return TlsGetValue(m_index);
}
} // namespace priv
} // namespace sf

View file

@ -1,87 +1,87 @@
////////////////////////////////////////////////////////////
//
// 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_THREADLOCALIMPL_HPP
#define SFML_THREADLOCALIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <windows.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Windows implementation of thread-local storage
////////////////////////////////////////////////////////////
class ThreadLocalImpl : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Default constructor -- allocate the storage
///
////////////////////////////////////////////////////////////
ThreadLocalImpl();
////////////////////////////////////////////////////////////
/// \brief Destructor -- free the storage
///
////////////////////////////////////////////////////////////
~ThreadLocalImpl();
////////////////////////////////////////////////////////////
/// \brief Set the thread-specific value of the variable
///
/// \param value Value of the variable for this thread
///
////////////////////////////////////////////////////////////
void setValue(void* value);
////////////////////////////////////////////////////////////
/// \brief Retrieve the thread-specific value of the variable
///
/// \return Value of the variable for this thread
///
////////////////////////////////////////////////////////////
void* getValue() const;
private :
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
DWORD m_index; ///< Index of our thread-local storage slot
};
} // namespace priv
} // namespace sf
#endif // SFML_THREADLOCALIMPL_HPP
////////////////////////////////////////////////////////////
//
// 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_THREADLOCALIMPL_HPP
#define SFML_THREADLOCALIMPL_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/System/NonCopyable.hpp>
#include <windows.h>
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
/// \brief Windows implementation of thread-local storage
////////////////////////////////////////////////////////////
class ThreadLocalImpl : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor -- allocate the storage
///
////////////////////////////////////////////////////////////
ThreadLocalImpl();
////////////////////////////////////////////////////////////
/// \brief Destructor -- free the storage
///
////////////////////////////////////////////////////////////
~ThreadLocalImpl();
////////////////////////////////////////////////////////////
/// \brief Set the thread-specific value of the variable
///
/// \param value Value of the variable for this thread
///
////////////////////////////////////////////////////////////
void setValue(void* value);
////////////////////////////////////////////////////////////
/// \brief Retrieve the thread-specific value of the variable
///
/// \return Value of the variable for this thread
///
////////////////////////////////////////////////////////////
void* getValue() const;
private:
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
DWORD m_index; ///< Index of our thread-local storage slot
};
} // namespace priv
} // namespace sf
#endif // SFML_THREADLOCALIMPL_HPP

View file

@ -42,7 +42,7 @@ namespace priv
////////////////////////////////////////////////////////////
class InputImpl
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Check if a key is pressed

View file

@ -36,7 +36,7 @@ namespace priv
////////////////////////////////////////////////////////////
class JoystickImpl
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Perform the global initialization of the joystick module
@ -100,7 +100,7 @@ public :
////////////////////////////////////////////////////////////
JoystickState update();
private :
private:
////////////////////////////////////////////////////////////
// Member data

View file

@ -42,7 +42,7 @@ namespace priv
////////////////////////////////////////////////////////////
class SensorImpl
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Perform the global initialization of the sensor module
@ -98,7 +98,7 @@ public :
////////////////////////////////////////////////////////////
void setEnabled(bool enabled);
private :
private:
////////////////////////////////////////////////////////////
/// \brief Get the default Android sensor matching the sensor type

View file

@ -515,117 +515,117 @@ Keyboard::Key WindowImplAndroid::androidKeyToSF(int32_t key)
{
switch (key)
{
case AKEYCODE_UNKNOWN :
case AKEYCODE_SOFT_LEFT :
case AKEYCODE_SOFT_RIGHT :
case AKEYCODE_HOME : return Keyboard::Unknown;
case AKEYCODE_BACK : return Keyboard::Escape;
case AKEYCODE_CALL :
case AKEYCODE_ENDCALL : return Keyboard::Unknown;
case AKEYCODE_0 : return Keyboard::Num0;
case AKEYCODE_1 : return Keyboard::Num1;
case AKEYCODE_2 : return Keyboard::Num2;
case AKEYCODE_3 : return Keyboard::Num3;
case AKEYCODE_4 : return Keyboard::Num4;
case AKEYCODE_5 : return Keyboard::Num5;
case AKEYCODE_6 : return Keyboard::Num6;
case AKEYCODE_7 : return Keyboard::Num7;
case AKEYCODE_8 : return Keyboard::Num8;
case AKEYCODE_9 : return Keyboard::Num9;
case AKEYCODE_STAR :
case AKEYCODE_POUND :
case AKEYCODE_DPAD_UP :
case AKEYCODE_DPAD_DOWN :
case AKEYCODE_DPAD_LEFT :
case AKEYCODE_DPAD_RIGHT :
case AKEYCODE_DPAD_CENTER :
case AKEYCODE_VOLUME_UP :
case AKEYCODE_VOLUME_DOWN :
case AKEYCODE_POWER :
case AKEYCODE_CAMERA :
case AKEYCODE_CLEAR : return Keyboard::Unknown;
case AKEYCODE_A : return Keyboard::A;
case AKEYCODE_B : return Keyboard::B;
case AKEYCODE_C : return Keyboard::C;
case AKEYCODE_D : return Keyboard::D;
case AKEYCODE_E : return Keyboard::E;
case AKEYCODE_F : return Keyboard::F;
case AKEYCODE_G : return Keyboard::G;
case AKEYCODE_H : return Keyboard::H;
case AKEYCODE_I : return Keyboard::I;
case AKEYCODE_J : return Keyboard::J;
case AKEYCODE_K : return Keyboard::K;
case AKEYCODE_L : return Keyboard::L;
case AKEYCODE_M : return Keyboard::M;
case AKEYCODE_N : return Keyboard::N;
case AKEYCODE_O : return Keyboard::O;
case AKEYCODE_P : return Keyboard::P;
case AKEYCODE_Q : return Keyboard::Q;
case AKEYCODE_R : return Keyboard::R;
case AKEYCODE_S : return Keyboard::S;
case AKEYCODE_T : return Keyboard::T;
case AKEYCODE_U : return Keyboard::U;
case AKEYCODE_V : return Keyboard::V;
case AKEYCODE_W : return Keyboard::W;
case AKEYCODE_X : return Keyboard::X;
case AKEYCODE_Y : return Keyboard::Y;
case AKEYCODE_Z : return Keyboard::Z;
case AKEYCODE_COMMA : return Keyboard::Comma;
case AKEYCODE_PERIOD : return Keyboard::Period;
case AKEYCODE_ALT_LEFT : return Keyboard::LAlt;
case AKEYCODE_ALT_RIGHT : return Keyboard::RAlt;
case AKEYCODE_SHIFT_LEFT : return Keyboard::LShift;
case AKEYCODE_SHIFT_RIGHT : return Keyboard::RShift;
case AKEYCODE_TAB : return Keyboard::Tab;
case AKEYCODE_SPACE : return Keyboard::Space;
case AKEYCODE_SYM :
case AKEYCODE_EXPLORER :
case AKEYCODE_ENVELOPE : return Keyboard::Unknown;
case AKEYCODE_ENTER : return Keyboard::Return;
case AKEYCODE_DEL : return Keyboard::Delete;
case AKEYCODE_GRAVE : return Keyboard::Tilde;
case AKEYCODE_MINUS : return Keyboard::Subtract;
case AKEYCODE_EQUALS : return Keyboard::Equal;
case AKEYCODE_LEFT_BRACKET : return Keyboard::LBracket;
case AKEYCODE_RIGHT_BRACKET : return Keyboard::RBracket;
case AKEYCODE_BACKSLASH : return Keyboard::BackSlash;
case AKEYCODE_SEMICOLON : return Keyboard::SemiColon;
case AKEYCODE_APOSTROPHE : return Keyboard::Quote;
case AKEYCODE_SLASH : return Keyboard::Slash;
case AKEYCODE_AT :
case AKEYCODE_NUM :
case AKEYCODE_HEADSETHOOK :
case AKEYCODE_FOCUS : // *Camera* focus
case AKEYCODE_PLUS :
case AKEYCODE_MENU :
case AKEYCODE_NOTIFICATION :
case AKEYCODE_SEARCH :
case AKEYCODE_MEDIA_PLAY_PAUSE :
case AKEYCODE_MEDIA_STOP :
case AKEYCODE_MEDIA_NEXT :
case AKEYCODE_MEDIA_PREVIOUS :
case AKEYCODE_MEDIA_REWIND :
case AKEYCODE_MEDIA_FAST_FORWARD :
case AKEYCODE_MUTE : return Keyboard::Unknown;
case AKEYCODE_PAGE_UP : return Keyboard::PageUp;
case AKEYCODE_PAGE_DOWN : return Keyboard::PageDown;
case AKEYCODE_PICTSYMBOLS :
case AKEYCODE_SWITCH_CHARSET :
case AKEYCODE_BUTTON_A :
case AKEYCODE_BUTTON_B :
case AKEYCODE_BUTTON_C :
case AKEYCODE_BUTTON_X :
case AKEYCODE_BUTTON_Y :
case AKEYCODE_BUTTON_Z :
case AKEYCODE_BUTTON_L1 :
case AKEYCODE_BUTTON_R1 :
case AKEYCODE_BUTTON_L2 :
case AKEYCODE_BUTTON_R2 :
case AKEYCODE_BUTTON_THUMBL :
case AKEYCODE_BUTTON_THUMBR :
case AKEYCODE_BUTTON_START :
case AKEYCODE_BUTTON_SELECT :
case AKEYCODE_BUTTON_MODE : return Keyboard::Unknown;
case AKEYCODE_UNKNOWN:
case AKEYCODE_SOFT_LEFT:
case AKEYCODE_SOFT_RIGHT:
case AKEYCODE_HOME: return Keyboard::Unknown;
case AKEYCODE_BACK: return Keyboard::Escape;
case AKEYCODE_CALL:
case AKEYCODE_ENDCALL: return Keyboard::Unknown;
case AKEYCODE_0: return Keyboard::Num0;
case AKEYCODE_1: return Keyboard::Num1;
case AKEYCODE_2: return Keyboard::Num2;
case AKEYCODE_3: return Keyboard::Num3;
case AKEYCODE_4: return Keyboard::Num4;
case AKEYCODE_5: return Keyboard::Num5;
case AKEYCODE_6: return Keyboard::Num6;
case AKEYCODE_7: return Keyboard::Num7;
case AKEYCODE_8: return Keyboard::Num8;
case AKEYCODE_9: return Keyboard::Num9;
case AKEYCODE_STAR:
case AKEYCODE_POUND:
case AKEYCODE_DPAD_UP:
case AKEYCODE_DPAD_DOWN:
case AKEYCODE_DPAD_LEFT:
case AKEYCODE_DPAD_RIGHT:
case AKEYCODE_DPAD_CENTER:
case AKEYCODE_VOLUME_UP:
case AKEYCODE_VOLUME_DOWN:
case AKEYCODE_POWER:
case AKEYCODE_CAMERA:
case AKEYCODE_CLEAR: return Keyboard::Unknown;
case AKEYCODE_A: return Keyboard::A;
case AKEYCODE_B: return Keyboard::B;
case AKEYCODE_C: return Keyboard::C;
case AKEYCODE_D: return Keyboard::D;
case AKEYCODE_E: return Keyboard::E;
case AKEYCODE_F: return Keyboard::F;
case AKEYCODE_G: return Keyboard::G;
case AKEYCODE_H: return Keyboard::H;
case AKEYCODE_I: return Keyboard::I;
case AKEYCODE_J: return Keyboard::J;
case AKEYCODE_K: return Keyboard::K;
case AKEYCODE_L: return Keyboard::L;
case AKEYCODE_M: return Keyboard::M;
case AKEYCODE_N: return Keyboard::N;
case AKEYCODE_O: return Keyboard::O;
case AKEYCODE_P: return Keyboard::P;
case AKEYCODE_Q: return Keyboard::Q;
case AKEYCODE_R: return Keyboard::R;
case AKEYCODE_S: return Keyboard::S;
case AKEYCODE_T: return Keyboard::T;
case AKEYCODE_U: return Keyboard::U;
case AKEYCODE_V: return Keyboard::V;
case AKEYCODE_W: return Keyboard::W;
case AKEYCODE_X: return Keyboard::X;
case AKEYCODE_Y: return Keyboard::Y;
case AKEYCODE_Z: return Keyboard::Z;
case AKEYCODE_COMMA: return Keyboard::Comma;
case AKEYCODE_PERIOD: return Keyboard::Period;
case AKEYCODE_ALT_LEFT: return Keyboard::LAlt;
case AKEYCODE_ALT_RIGHT: return Keyboard::RAlt;
case AKEYCODE_SHIFT_LEFT: return Keyboard::LShift;
case AKEYCODE_SHIFT_RIGHT: return Keyboard::RShift;
case AKEYCODE_TAB: return Keyboard::Tab;
case AKEYCODE_SPACE: return Keyboard::Space;
case AKEYCODE_SYM:
case AKEYCODE_EXPLORER:
case AKEYCODE_ENVELOPE: return Keyboard::Unknown;
case AKEYCODE_ENTER: return Keyboard::Return;
case AKEYCODE_DEL: return Keyboard::Delete;
case AKEYCODE_GRAVE: return Keyboard::Tilde;
case AKEYCODE_MINUS: return Keyboard::Subtract;
case AKEYCODE_EQUALS: return Keyboard::Equal;
case AKEYCODE_LEFT_BRACKET: return Keyboard::LBracket;
case AKEYCODE_RIGHT_BRACKET: return Keyboard::RBracket;
case AKEYCODE_BACKSLASH: return Keyboard::BackSlash;
case AKEYCODE_SEMICOLON: return Keyboard::SemiColon;
case AKEYCODE_APOSTROPHE: return Keyboard::Quote;
case AKEYCODE_SLASH: return Keyboard::Slash;
case AKEYCODE_AT:
case AKEYCODE_NUM:
case AKEYCODE_HEADSETHOOK:
case AKEYCODE_FOCUS: // *Camera* focus
case AKEYCODE_PLUS:
case AKEYCODE_MENU:
case AKEYCODE_NOTIFICATION:
case AKEYCODE_SEARCH:
case AKEYCODE_MEDIA_PLAY_PAUSE:
case AKEYCODE_MEDIA_STOP:
case AKEYCODE_MEDIA_NEXT:
case AKEYCODE_MEDIA_PREVIOUS:
case AKEYCODE_MEDIA_REWIND:
case AKEYCODE_MEDIA_FAST_FORWARD:
case AKEYCODE_MUTE: return Keyboard::Unknown;
case AKEYCODE_PAGE_UP: return Keyboard::PageUp;
case AKEYCODE_PAGE_DOWN: return Keyboard::PageDown;
case AKEYCODE_PICTSYMBOLS:
case AKEYCODE_SWITCH_CHARSET:
case AKEYCODE_BUTTON_A:
case AKEYCODE_BUTTON_B:
case AKEYCODE_BUTTON_C:
case AKEYCODE_BUTTON_X:
case AKEYCODE_BUTTON_Y:
case AKEYCODE_BUTTON_Z:
case AKEYCODE_BUTTON_L1:
case AKEYCODE_BUTTON_R1:
case AKEYCODE_BUTTON_L2:
case AKEYCODE_BUTTON_R2:
case AKEYCODE_BUTTON_THUMBL:
case AKEYCODE_BUTTON_THUMBR:
case AKEYCODE_BUTTON_START:
case AKEYCODE_BUTTON_SELECT:
case AKEYCODE_BUTTON_MODE: return Keyboard::Unknown;
}
}

View file

@ -45,7 +45,7 @@ namespace priv
////////////////////////////////////////////////////////////
class WindowImplAndroid : public WindowImpl
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Construct the window implementation from an existing control
@ -157,7 +157,7 @@ public :
static void forwardEvent(const Event& event);
static WindowImplAndroid* singleInstance;
protected :
protected:
////////////////////////////////////////////////////////////
/// \brief Process incoming events from the operating system

View file

@ -1,246 +1,246 @@
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Window)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Window)
# all source files
set(SRC
${SRCROOT}/Context.cpp
${INCROOT}/Context.hpp
${INCROOT}/Export.hpp
${SRCROOT}/GlContext.cpp
${SRCROOT}/GlContext.hpp
${SRCROOT}/GlResource.cpp
${INCROOT}/GlResource.hpp
${INCROOT}/ContextSettings.hpp
${INCROOT}/Event.hpp
${SRCROOT}/InputImpl.hpp
${INCROOT}/Joystick.hpp
${SRCROOT}/Joystick.cpp
${SRCROOT}/JoystickImpl.hpp
${SRCROOT}/JoystickManager.cpp
${SRCROOT}/JoystickManager.hpp
${INCROOT}/Keyboard.hpp
${SRCROOT}/Keyboard.cpp
${INCROOT}/Mouse.hpp
${SRCROOT}/Mouse.cpp
${INCROOT}/Touch.hpp
${SRCROOT}/Touch.cpp
${INCROOT}/Sensor.hpp
${SRCROOT}/Sensor.cpp
${SRCROOT}/SensorImpl.hpp
${SRCROOT}/SensorManager.cpp
${SRCROOT}/SensorManager.hpp
${SRCROOT}/VideoMode.cpp
${INCROOT}/VideoMode.hpp
${SRCROOT}/VideoModeImpl.hpp
${SRCROOT}/Window.cpp
${INCROOT}/Window.hpp
${INCROOT}/WindowHandle.hpp
${SRCROOT}/WindowImpl.cpp
${SRCROOT}/WindowImpl.hpp
${INCROOT}/WindowStyle.hpp
)
if(SFML_OPENGL_ES AND NOT SFML_OS_IOS)
list(APPEND SRC ${SRCROOT}/EGLCheck.cpp)
list(APPEND SRC ${SRCROOT}/EGLCheck.hpp)
list(APPEND SRC ${SRCROOT}/EglContext.cpp)
list(APPEND SRC ${SRCROOT}/EglContext.hpp)
endif()
source_group("" FILES ${SRC})
# add platform specific sources
if(SFML_OS_WINDOWS)
set(PLATFORM_SRC
${SRCROOT}/Win32/WglContext.cpp
${SRCROOT}/Win32/WglContext.hpp
${SRCROOT}/Win32/InputImpl.cpp
${SRCROOT}/Win32/InputImpl.hpp
${SRCROOT}/Win32/JoystickImpl.cpp
${SRCROOT}/Win32/JoystickImpl.hpp
${SRCROOT}/Win32/SensorImpl.hpp
${SRCROOT}/Win32/SensorImpl.cpp
${SRCROOT}/Win32/VideoModeImpl.cpp
${SRCROOT}/Win32/WindowImplWin32.cpp
${SRCROOT}/Win32/WindowImplWin32.hpp
)
source_group("windows" FILES ${PLATFORM_SRC})
# make sure that we use the Unicode version of the Win API functions
add_definitions(-DUNICODE -D_UNICODE)
elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
set(PLATFORM_SRC
${SRCROOT}/Unix/Display.cpp
${SRCROOT}/Unix/Display.hpp
${SRCROOT}/Unix/InputImpl.cpp
${SRCROOT}/Unix/InputImpl.hpp
${SRCROOT}/Unix/SensorImpl.cpp
${SRCROOT}/Unix/SensorImpl.hpp
${SRCROOT}/Unix/VideoModeImpl.cpp
${SRCROOT}/Unix/WindowImplX11.cpp
${SRCROOT}/Unix/WindowImplX11.hpp
)
if(NOT SFML_OPENGL_ES)
set(PLATFORM_SRC
${PLATFORM_SRC}
${SRCROOT}/Unix/GlxContext.cpp
${SRCROOT}/Unix/GlxContext.hpp
)
endif()
if(SFML_OS_LINUX)
set(PLATFORM_SRC
${PLATFORM_SRC}
${SRCROOT}/Unix/JoystickImpl.cpp
${SRCROOT}/Unix/JoystickImpl.hpp
)
elseif(SFML_OS_FREEBSD)
set(PLATFORM_SRC
${PLATFORM_SRC}
${SRCROOT}/FreeBSD/JoystickImpl.cpp
${SRCROOT}/FreeBSD/JoystickImpl.hpp
)
endif()
source_group("unix" FILES ${PLATFORM_SRC})
elseif(SFML_OS_MACOSX)
set(PLATFORM_SRC
${SRCROOT}/OSX/cpp_objc_conversion.h
${SRCROOT}/OSX/cpp_objc_conversion.mm
${SRCROOT}/OSX/cg_sf_conversion.hpp
${SRCROOT}/OSX/cg_sf_conversion.cpp
${SRCROOT}/OSX/InputImpl.mm
${SRCROOT}/OSX/InputImpl.hpp
${SRCROOT}/OSX/HIDInputManager.hpp
${SRCROOT}/OSX/HIDInputManager.mm
${SRCROOT}/OSX/HIDJoystickManager.hpp
${SRCROOT}/OSX/HIDJoystickManager.cpp
${SRCROOT}/OSX/JoystickImpl.cpp
${SRCROOT}/OSX/JoystickImpl.hpp
${SRCROOT}/OSX/SensorImpl.cpp
${SRCROOT}/OSX/SensorImpl.hpp
${SRCROOT}/OSX/SFApplication.h
${SRCROOT}/OSX/SFApplication.m
${SRCROOT}/OSX/SFApplicationDelegate.h
${SRCROOT}/OSX/SFApplicationDelegate.m
${SRCROOT}/OSX/SFContext.hpp
${SRCROOT}/OSX/SFContext.mm
${SRCROOT}/OSX/SFKeyboardModifiersHelper.h
${SRCROOT}/OSX/SFKeyboardModifiersHelper.mm
${SRCROOT}/OSX/SFOpenGLView.h
${SRCROOT}/OSX/SFOpenGLView.mm
${SRCROOT}/OSX/SFSilentResponder.h
${SRCROOT}/OSX/SFSilentResponder.m
${SRCROOT}/OSX/SFWindow.h
${SRCROOT}/OSX/SFWindow.m
${SRCROOT}/OSX/SFWindowController.h
${SRCROOT}/OSX/SFWindowController.mm
${SRCROOT}/OSX/SFViewController.h
${SRCROOT}/OSX/SFViewController.mm
${SRCROOT}/OSX/VideoModeImpl.cpp
${SRCROOT}/OSX/WindowImplCocoa.hpp
${SRCROOT}/OSX/WindowImplCocoa.mm
${SRCROOT}/OSX/WindowImplDelegateProtocol.h
${SRCROOT}/OSX/AutoreleasePoolWrapper.h
${SRCROOT}/OSX/AutoreleasePoolWrapper.mm
)
source_group("mac" FILES ${PLATFORM_SRC})
elseif(SFML_OS_IOS)
set(PLATFORM_SRC
${SRCROOT}/iOS/EaglContext.mm
${SRCROOT}/iOS/EaglContext.hpp
${SRCROOT}/iOS/InputImpl.mm
${SRCROOT}/iOS/InputImpl.hpp
${SRCROOT}/iOS/JoystickImpl.mm
${SRCROOT}/iOS/JoystickImpl.hpp
${SRCROOT}/iOS/SensorImpl.mm
${SRCROOT}/iOS/SensorImpl.hpp
${SRCROOT}/iOS/VideoModeImpl.mm
${SRCROOT}/iOS/WindowImplUIKit.hpp
${SRCROOT}/iOS/WindowImplUIKit.mm
${SRCROOT}/iOS/ObjCType.hpp
${SRCROOT}/iOS/SFAppDelegate.hpp
${SRCROOT}/iOS/SFAppDelegate.mm
${SRCROOT}/iOS/SFView.hpp
${SRCROOT}/iOS/SFView.mm
${SRCROOT}/iOS/SFViewController.hpp
${SRCROOT}/iOS/SFViewController.mm
${SRCROOT}/iOS/SFMain.hpp
${SRCROOT}/iOS/SFMain.mm
)
source_group("ios" FILES ${PLATFORM_SRC})
elseif(SFML_OS_ANDROID)
set(PLATFORM_SRC
${SRCROOT}/Android/WindowImplAndroid.hpp
${SRCROOT}/Android/WindowImplAndroid.cpp
${SRCROOT}/Android/VideoModeImpl.cpp
${SRCROOT}/Android/InputImpl.hpp
${SRCROOT}/Android/InputImpl.cpp
${SRCROOT}/Android/JoystickImpl.hpp
${SRCROOT}/Android/JoystickImpl.cpp
${SRCROOT}/Android/SensorImpl.hpp
${SRCROOT}/Android/SensorImpl.cpp
)
source_group("android" FILES ${PLATFORM_SRC})
endif()
# find external libraries
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
find_package(X11 REQUIRED)
if(NOT X11_Xrandr_FOUND)
message(FATAL_ERROR "Xrandr library not found")
endif()
include_directories(${X11_INCLUDE_DIR})
set(INCROOT ${PROJECT_SOURCE_DIR}/include/SFML/Window)
set(SRCROOT ${PROJECT_SOURCE_DIR}/src/SFML/Window)
# all source files
set(SRC
${SRCROOT}/Context.cpp
${INCROOT}/Context.hpp
${INCROOT}/Export.hpp
${SRCROOT}/GlContext.cpp
${SRCROOT}/GlContext.hpp
${SRCROOT}/GlResource.cpp
${INCROOT}/GlResource.hpp
${INCROOT}/ContextSettings.hpp
${INCROOT}/Event.hpp
${SRCROOT}/InputImpl.hpp
${INCROOT}/Joystick.hpp
${SRCROOT}/Joystick.cpp
${SRCROOT}/JoystickImpl.hpp
${SRCROOT}/JoystickManager.cpp
${SRCROOT}/JoystickManager.hpp
${INCROOT}/Keyboard.hpp
${SRCROOT}/Keyboard.cpp
${INCROOT}/Mouse.hpp
${SRCROOT}/Mouse.cpp
${INCROOT}/Touch.hpp
${SRCROOT}/Touch.cpp
${INCROOT}/Sensor.hpp
${SRCROOT}/Sensor.cpp
${SRCROOT}/SensorImpl.hpp
${SRCROOT}/SensorManager.cpp
${SRCROOT}/SensorManager.hpp
${SRCROOT}/VideoMode.cpp
${INCROOT}/VideoMode.hpp
${SRCROOT}/VideoModeImpl.hpp
${SRCROOT}/Window.cpp
${INCROOT}/Window.hpp
${INCROOT}/WindowHandle.hpp
${SRCROOT}/WindowImpl.cpp
${SRCROOT}/WindowImpl.hpp
${INCROOT}/WindowStyle.hpp
)
if(SFML_OPENGL_ES AND NOT SFML_OS_IOS)
list(APPEND SRC ${SRCROOT}/EGLCheck.cpp)
list(APPEND SRC ${SRCROOT}/EGLCheck.hpp)
list(APPEND SRC ${SRCROOT}/EglContext.cpp)
list(APPEND SRC ${SRCROOT}/EglContext.hpp)
endif()
source_group("" FILES ${SRC})
# add platform specific sources
if(SFML_OS_WINDOWS)
set(PLATFORM_SRC
${SRCROOT}/Win32/WglContext.cpp
${SRCROOT}/Win32/WglContext.hpp
${SRCROOT}/Win32/InputImpl.cpp
${SRCROOT}/Win32/InputImpl.hpp
${SRCROOT}/Win32/JoystickImpl.cpp
${SRCROOT}/Win32/JoystickImpl.hpp
${SRCROOT}/Win32/SensorImpl.hpp
${SRCROOT}/Win32/SensorImpl.cpp
${SRCROOT}/Win32/VideoModeImpl.cpp
${SRCROOT}/Win32/WindowImplWin32.cpp
${SRCROOT}/Win32/WindowImplWin32.hpp
)
source_group("windows" FILES ${PLATFORM_SRC})
# make sure that we use the Unicode version of the Win API functions
add_definitions(-DUNICODE -D_UNICODE)
elseif(SFML_OS_LINUX OR SFML_OS_FREEBSD)
set(PLATFORM_SRC
${SRCROOT}/Unix/Display.cpp
${SRCROOT}/Unix/Display.hpp
${SRCROOT}/Unix/InputImpl.cpp
${SRCROOT}/Unix/InputImpl.hpp
${SRCROOT}/Unix/SensorImpl.cpp
${SRCROOT}/Unix/SensorImpl.hpp
${SRCROOT}/Unix/VideoModeImpl.cpp
${SRCROOT}/Unix/WindowImplX11.cpp
${SRCROOT}/Unix/WindowImplX11.hpp
)
if(NOT SFML_OPENGL_ES)
set(PLATFORM_SRC
${PLATFORM_SRC}
${SRCROOT}/Unix/GlxContext.cpp
${SRCROOT}/Unix/GlxContext.hpp
)
endif()
if(SFML_OS_LINUX)
set(PLATFORM_SRC
${PLATFORM_SRC}
${SRCROOT}/Unix/JoystickImpl.cpp
${SRCROOT}/Unix/JoystickImpl.hpp
)
elseif(SFML_OS_FREEBSD)
set(PLATFORM_SRC
${PLATFORM_SRC}
${SRCROOT}/FreeBSD/JoystickImpl.cpp
${SRCROOT}/FreeBSD/JoystickImpl.hpp
)
endif()
source_group("unix" FILES ${PLATFORM_SRC})
elseif(SFML_OS_MACOSX)
set(PLATFORM_SRC
${SRCROOT}/OSX/cpp_objc_conversion.h
${SRCROOT}/OSX/cpp_objc_conversion.mm
${SRCROOT}/OSX/cg_sf_conversion.hpp
${SRCROOT}/OSX/cg_sf_conversion.cpp
${SRCROOT}/OSX/InputImpl.mm
${SRCROOT}/OSX/InputImpl.hpp
${SRCROOT}/OSX/HIDInputManager.hpp
${SRCROOT}/OSX/HIDInputManager.mm
${SRCROOT}/OSX/HIDJoystickManager.hpp
${SRCROOT}/OSX/HIDJoystickManager.cpp
${SRCROOT}/OSX/JoystickImpl.cpp
${SRCROOT}/OSX/JoystickImpl.hpp
${SRCROOT}/OSX/SensorImpl.cpp
${SRCROOT}/OSX/SensorImpl.hpp
${SRCROOT}/OSX/SFApplication.h
${SRCROOT}/OSX/SFApplication.m
${SRCROOT}/OSX/SFApplicationDelegate.h
${SRCROOT}/OSX/SFApplicationDelegate.m
${SRCROOT}/OSX/SFContext.hpp
${SRCROOT}/OSX/SFContext.mm
${SRCROOT}/OSX/SFKeyboardModifiersHelper.h
${SRCROOT}/OSX/SFKeyboardModifiersHelper.mm
${SRCROOT}/OSX/SFOpenGLView.h
${SRCROOT}/OSX/SFOpenGLView.mm
${SRCROOT}/OSX/SFSilentResponder.h
${SRCROOT}/OSX/SFSilentResponder.m
${SRCROOT}/OSX/SFWindow.h
${SRCROOT}/OSX/SFWindow.m
${SRCROOT}/OSX/SFWindowController.h
${SRCROOT}/OSX/SFWindowController.mm
${SRCROOT}/OSX/SFViewController.h
${SRCROOT}/OSX/SFViewController.mm
${SRCROOT}/OSX/VideoModeImpl.cpp
${SRCROOT}/OSX/WindowImplCocoa.hpp
${SRCROOT}/OSX/WindowImplCocoa.mm
${SRCROOT}/OSX/WindowImplDelegateProtocol.h
${SRCROOT}/OSX/AutoreleasePoolWrapper.h
${SRCROOT}/OSX/AutoreleasePoolWrapper.mm
)
source_group("mac" FILES ${PLATFORM_SRC})
elseif(SFML_OS_IOS)
set(PLATFORM_SRC
${SRCROOT}/iOS/EaglContext.mm
${SRCROOT}/iOS/EaglContext.hpp
${SRCROOT}/iOS/InputImpl.mm
${SRCROOT}/iOS/InputImpl.hpp
${SRCROOT}/iOS/JoystickImpl.mm
${SRCROOT}/iOS/JoystickImpl.hpp
${SRCROOT}/iOS/SensorImpl.mm
${SRCROOT}/iOS/SensorImpl.hpp
${SRCROOT}/iOS/VideoModeImpl.mm
${SRCROOT}/iOS/WindowImplUIKit.hpp
${SRCROOT}/iOS/WindowImplUIKit.mm
${SRCROOT}/iOS/ObjCType.hpp
${SRCROOT}/iOS/SFAppDelegate.hpp
${SRCROOT}/iOS/SFAppDelegate.mm
${SRCROOT}/iOS/SFView.hpp
${SRCROOT}/iOS/SFView.mm
${SRCROOT}/iOS/SFViewController.hpp
${SRCROOT}/iOS/SFViewController.mm
${SRCROOT}/iOS/SFMain.hpp
${SRCROOT}/iOS/SFMain.mm
)
source_group("ios" FILES ${PLATFORM_SRC})
elseif(SFML_OS_ANDROID)
set(PLATFORM_SRC
${SRCROOT}/Android/WindowImplAndroid.hpp
${SRCROOT}/Android/WindowImplAndroid.cpp
${SRCROOT}/Android/VideoModeImpl.cpp
${SRCROOT}/Android/InputImpl.hpp
${SRCROOT}/Android/InputImpl.cpp
${SRCROOT}/Android/JoystickImpl.hpp
${SRCROOT}/Android/JoystickImpl.cpp
${SRCROOT}/Android/SensorImpl.hpp
${SRCROOT}/Android/SensorImpl.cpp
)
source_group("android" FILES ${PLATFORM_SRC})
endif()
# find external libraries
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
find_package(X11 REQUIRED)
if(NOT X11_Xrandr_FOUND)
message(FATAL_ERROR "Xrandr library not found")
endif()
include_directories(${X11_INCLUDE_DIR})
endif()
if(NOT SFML_OPENGL_ES)
find_package(OpenGL REQUIRED)
include_directories(${OPENGL_INCLUDE_DIR})
if(SFML_OS_LINUX OR SFML_OS_FREEBSD)
find_package(X11 REQUIRED)
if(NOT X11_Xrandr_FOUND)
message(FATAL_ERROR "Xrandr library not found")
endif()
include_directories(${X11_INCLUDE_DIR})
find_package(X11 REQUIRED)
if(NOT X11_Xrandr_FOUND)
message(FATAL_ERROR "Xrandr library not found")
endif()
include_directories(${X11_INCLUDE_DIR})
endif()
if(SFML_OS_LINUX)
find_package(UDev REQUIRED)
if(NOT UDEV_FOUND)
message(FATAL_ERROR "udev library not found")
endif()
find_package(UDev REQUIRED)
if(NOT UDEV_FOUND)
message(FATAL_ERROR "udev library not found")
endif()
include_directories(${UDEV_INCLUDE_DIR})
endif()
endif()
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
find_package(EGL REQUIRED)
find_package(GLES REQUIRED)
include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
endif()
endif()
if(SFML_OPENGL_ES AND SFML_OS_LINUX)
find_package(EGL REQUIRED)
find_package(GLES REQUIRED)
include_directories(${EGL_INCLUDE_DIR} ${GLES_INCLUDE_DIR})
endif()
# build the list of external libraries to link
# build the list of external libraries to link
if(SFML_OS_WINDOWS)
list(APPEND WINDOW_EXT_LIBS winmm gdi32)
elseif(SFML_OS_LINUX)
list(APPEND WINDOW_EXT_LIBS winmm gdi32)
elseif(SFML_OS_LINUX)
list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} ${UDEV_LIBRARIES})
elseif(SFML_OS_FREEBSD)
elseif(SFML_OS_FREEBSD)
list(APPEND WINDOW_EXT_LIBS ${X11_X11_LIB} ${X11_Xrandr_LIB} usbhid)
elseif(SFML_OS_MACOSX)
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
elseif(SFML_OS_IOS)
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework UIKit -framework CoreGraphics -framework QuartzCore -framework CoreMotion")
elseif(SFML_OS_ANDROID)
list(APPEND WINDOW_EXT_LIBS "-landroid")
endif()
if(SFML_OPENGL_ES)
if(SFML_OS_LINUX)
list(APPEND WINDOW_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
elseif(SFML_OS_IOS)
list(APPEND WINDOW_EXT_LIBS "-framework OpenGLES")
elseif(SFML_OS_ANDROID)
list(APPEND WINDOW_EXT_LIBS "-lEGL -lGLESv1_CM")
endif()
else()
list(APPEND WINDOW_EXT_LIBS ${OPENGL_gl_LIBRARY})
endif()
# define the sfml-window target
sfml_add_library(sfml-window
SOURCES ${SRC} ${PLATFORM_SRC}
DEPENDS sfml-system
EXTERNAL_LIBS ${WINDOW_EXT_LIBS})
elseif(SFML_OS_MACOSX)
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework AppKit -framework IOKit -framework Carbon")
elseif(SFML_OS_IOS)
list(APPEND WINDOW_EXT_LIBS "-framework Foundation -framework UIKit -framework CoreGraphics -framework QuartzCore -framework CoreMotion")
elseif(SFML_OS_ANDROID)
list(APPEND WINDOW_EXT_LIBS "-landroid")
endif()
if(SFML_OPENGL_ES)
if(SFML_OS_LINUX)
list(APPEND WINDOW_EXT_LIBS ${EGL_LIBRARY} ${GLES_LIBRARY})
elseif(SFML_OS_IOS)
list(APPEND WINDOW_EXT_LIBS "-framework OpenGLES")
elseif(SFML_OS_ANDROID)
list(APPEND WINDOW_EXT_LIBS "-lEGL -lGLESv1_CM")
endif()
else()
list(APPEND WINDOW_EXT_LIBS ${OPENGL_gl_LIBRARY})
endif()
# define the sfml-window target
sfml_add_library(sfml-window
SOURCES ${SRC} ${PLATFORM_SRC}
DEPENDS sfml-system
EXTERNAL_LIBS ${WINDOW_EXT_LIBS})

View file

@ -1,63 +1,63 @@
////////////////////////////////////////////////////////////
//
// 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/Window/Context.hpp>
#include <SFML/Window/GlContext.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Context::Context()
{
m_context = priv::GlContext::create();
setActive(true);
}
////////////////////////////////////////////////////////////
Context::~Context()
{
delete m_context;
}
////////////////////////////////////////////////////////////
bool Context::setActive(bool active)
{
return m_context->setActive(active);
}
////////////////////////////////////////////////////////////
Context::Context(const ContextSettings& settings, unsigned int width, unsigned int height)
{
m_context = priv::GlContext::create(settings, width, height);
setActive(true);
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Window/Context.hpp>
#include <SFML/Window/GlContext.hpp>
namespace sf
{
////////////////////////////////////////////////////////////
Context::Context()
{
m_context = priv::GlContext::create();
setActive(true);
}
////////////////////////////////////////////////////////////
Context::~Context()
{
delete m_context;
}
////////////////////////////////////////////////////////////
bool Context::setActive(bool active)
{
return m_context->setActive(active);
}
////////////////////////////////////////////////////////////
Context::Context(const ContextSettings& settings, unsigned int width, unsigned int height)
{
m_context = priv::GlContext::create(settings, width, height);
setActive(true);
}
} // namespace sf

View file

@ -50,55 +50,55 @@ void eglCheckError(const char* file, unsigned int line)
// Decode the error code returned
switch (errorCode)
{
case EGL_NOT_INITIALIZED :
case EGL_NOT_INITIALIZED:
{
error = "EGL_NOT_INITIALIZED";
description = "EGL is not initialized, or could not be initialized, for the specified display";
break;
}
case EGL_BAD_ACCESS :
case EGL_BAD_ACCESS:
{
error = "EGL_BAD_ACCESS";
description = "EGL cannot access a requested resource (for example, a context is bound in another thread)";
break;
}
case EGL_BAD_ALLOC :
case EGL_BAD_ALLOC:
{
error = "EGL_BAD_ALLOC";
description = "EGL failed to allocate resources for the requested operation";
break;
}
case EGL_BAD_ATTRIBUTE :
case EGL_BAD_ATTRIBUTE:
{
error = "EGL_BAD_ATTRIBUTE";
description = "an unrecognized attribute or attribute value was passed in an attribute list";
break;
}
case EGL_BAD_CONTEXT :
case EGL_BAD_CONTEXT:
{
error = "EGL_BAD_CONTEXT";
description = "an EGLContext argument does not name a valid EGLContext";
break;
}
case EGL_BAD_CONFIG :
case EGL_BAD_CONFIG:
{
error = "EGL_BAD_CONFIG";
description = "an EGLConfig argument does not name a valid EGLConfig";
break;
}
case EGL_BAD_CURRENT_SURFACE :
case EGL_BAD_CURRENT_SURFACE:
{
error = "EGL_BAD_CURRENT_SURFACE";
description = "the current surface of the calling thread is a window, pbuffer, or pixmap that is no longer valid";
break;
}
case EGL_BAD_DISPLAY :
case EGL_BAD_DISPLAY:
{
error = "EGL_BAD_DISPLAY";
description = "an EGLDisplay argument does not name a valid EGLDisplay; or, EGL is not initialized on the specified EGLDisplay";
@ -106,42 +106,42 @@ void eglCheckError(const char* file, unsigned int line)
}
case EGL_BAD_SURFACE :
case EGL_BAD_SURFACE:
{
error = "EGL_BAD_SURFACE";
description = "an EGLSurface argument does not name a valid surface (window, pbuffer, or pixmap) configured for rendering";
break;
}
case EGL_BAD_MATCH :
case EGL_BAD_MATCH:
{
error = "EGL_BAD_MATCH";
description = "arguments are inconsistent; for example, an otherwise valid context requires buffers (e.g. depth or stencil) not allocated by an otherwise valid surface";
break;
}
case EGL_BAD_PARAMETER :
case EGL_BAD_PARAMETER:
{
error = "EGL_BAD_PARAMETER";
description = "one or more argument values are invalid";
break;
}
case EGL_BAD_NATIVE_PIXMAP :
case EGL_BAD_NATIVE_PIXMAP:
{
error = "EGL_BAD_NATIVE_PIXMAP";
description = "an EGLNativePixmapType argument does not refer to a valid native pixmap";
break;
}
case EGL_BAD_NATIVE_WINDOW :
case EGL_BAD_NATIVE_WINDOW:
{
error = "EGL_BAD_NATIVE_WINDOW";
description = "an EGLNativeWindowType argument does not refer to a valid native window";
break;
}
case EGL_CONTEXT_LOST :
case EGL_CONTEXT_LOST:
{
error = "EGL_CONTEXT_LOST";
description = "a power management event has occured. The application must destroy all contexts and reinitialise client API state and objects to continue rendering";

View file

@ -41,7 +41,7 @@ namespace priv
{
class EglContext : public GlContext
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Create a new context, not associated to a window
@ -102,7 +102,7 @@ public :
/// This can avoid some visual artifacts, and limit the framerate
/// to a good value (but not constant across different computers).
///
/// \param enabled : True to enable v-sync, false to deactivate
/// \param enabled: True to enable v-sync, false to deactivate
///
////////////////////////////////////////////////////////////
virtual void setVerticalSyncEnabled(bool enabled);
@ -123,7 +123,7 @@ public :
/// This function must be called when the activity (re)start, or
/// when the orientation change.
///
/// \param window : The native window type
/// \param window: The native window type
///
////////////////////////////////////////////////////////////
void createSurface(EGLNativeWindowType window);
@ -163,7 +163,7 @@ public :
static XVisualInfo selectBestVisual(::Display* display, unsigned int bitsPerPixel, const ContextSettings& settings);
#endif
private :
private:
////////////////////////////////////////////////////////////
// Member data

View file

@ -43,7 +43,7 @@ namespace priv
////////////////////////////////////////////////////////////
class JoystickImpl
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Perform the global initialization of the joystick module
@ -107,7 +107,7 @@ public :
////////////////////////////////////////////////////////////
JoystickState update();
private :
private:
////////////////////////////////////////////////////////////
// Member data

View file

@ -1,300 +1,300 @@
////////////////////////////////////////////////////////////
//
// 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/Window/GlContext.hpp>
#include <SFML/System/ThreadLocalPtr.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/OpenGL.hpp>
#include <set>
#include <cstdlib>
#ifdef SFML_SYSTEM_IOS
#include <OpenGLES/ES1/gl.h>
#else
#include <SFML/Window/glext/glext.h>
#endif
#if !defined(SFML_OPENGL_ES)
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Window/Win32/WglContext.hpp>
typedef sf::priv::WglContext ContextType;
#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
#include <SFML/Window/Unix/GlxContext.hpp>
typedef sf::priv::GlxContext ContextType;
#elif defined(SFML_SYSTEM_MACOS)
#include <SFML/Window/OSX/SFContext.hpp>
typedef sf::priv::SFContext ContextType;
#endif
#else
#if defined(SFML_SYSTEM_IOS)
#include <SFML/Window/iOS/EaglContext.hpp>
typedef sf::priv::EaglContext ContextType;
#else
#include <SFML/Window/EglContext.hpp>
typedef sf::priv::EglContext ContextType;
#endif
#endif
namespace
{
// This per-thread variable holds the current context for each thread
sf::ThreadLocalPtr<sf::priv::GlContext> currentContext(NULL);
// The hidden, inactive context that will be shared with all other contexts
ContextType* sharedContext = NULL;
// Internal contexts
sf::ThreadLocalPtr<sf::priv::GlContext> internalContext(NULL);
std::set<sf::priv::GlContext*> internalContexts;
sf::Mutex internalContextsMutex;
// Check if the internal context of the current thread is valid
bool hasInternalContext()
{
// The internal context can be null...
if (!internalContext)
return false;
// ... or non-null but deleted from the list of internal contexts
sf::Lock lock(internalContextsMutex);
return internalContexts.find(internalContext) != internalContexts.end();
}
// Retrieve the internal context for the current thread
sf::priv::GlContext* getInternalContext()
{
if (!hasInternalContext())
{
internalContext = sf::priv::GlContext::create();
sf::Lock lock(internalContextsMutex);
internalContexts.insert(internalContext);
}
return internalContext;
}
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void GlContext::globalInit()
{
// Create the shared context
sharedContext = new ContextType(NULL);
sharedContext->initialize();
// This call makes sure that:
// - the shared context is inactive (it must never be)
// - another valid context is activated in the current thread
sharedContext->setActive(false);
}
////////////////////////////////////////////////////////////
void GlContext::globalCleanup()
{
// Destroy the shared context
delete sharedContext;
sharedContext = NULL;
// Destroy the internal contexts
sf::Lock lock(internalContextsMutex);
for (std::set<GlContext*>::iterator it = internalContexts.begin(); it != internalContexts.end(); ++it)
delete *it;
internalContexts.clear();
}
////////////////////////////////////////////////////////////
void GlContext::ensureContext()
{
// If there's no active context on the current thread, activate an internal one
if (!currentContext)
getInternalContext()->setActive(true);
}
////////////////////////////////////////////////////////////
GlContext* GlContext::create()
{
GlContext* context = new ContextType(sharedContext);
context->initialize();
return context;
}
////////////////////////////////////////////////////////////
GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel)
{
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
ensureContext();
// Create the context
GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
context->initialize();
return context;
}
////////////////////////////////////////////////////////////
GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height)
{
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
ensureContext();
// Create the context
GlContext* context = new ContextType(sharedContext, settings, width, height);
context->initialize();
return context;
}
////////////////////////////////////////////////////////////
GlContext::~GlContext()
{
// Deactivate the context before killing it, unless we're inside Cleanup()
if (sharedContext)
setActive(false);
}
////////////////////////////////////////////////////////////
const ContextSettings& GlContext::getSettings() const
{
return m_settings;
}
////////////////////////////////////////////////////////////
bool GlContext::setActive(bool active)
{
if (active)
{
if (this != currentContext)
{
// Activate the context
if (makeCurrent())
{
// Set it as the new current context for this thread
currentContext = this;
return true;
}
else
{
return false;
}
}
else
{
// This context is already the active one on this thread, don't do anything
return true;
}
}
else
{
if (this == currentContext)
{
// To deactivate the context, we actually activate another one so that we make
// sure that there is always an active context for subsequent graphics operations
return getInternalContext()->setActive(true);
}
else
{
// This context is not the active one on this thread, don't do anything
return true;
}
}
}
////////////////////////////////////////////////////////////
GlContext::GlContext()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing)
{
return std::abs(static_cast<int>(bitsPerPixel - colorBits)) +
std::abs(static_cast<int>(settings.depthBits - depthBits)) +
std::abs(static_cast<int>(settings.stencilBits - stencilBits)) +
std::abs(static_cast<int>(settings.antialiasingLevel - antialiasing));
}
////////////////////////////////////////////////////////////
void GlContext::initialize()
{
// Activate the context
setActive(true);
// Retrieve the context version number
const GLubyte* version = glGetString(GL_VERSION);
if (version)
{
// The beginning of the returned string is "major.minor" (this is standard)
m_settings.majorVersion = version[0] - '0';
m_settings.minorVersion = version[2] - '0';
}
else
{
// Can't get the version number, assume 2.0
m_settings.majorVersion = 2;
m_settings.minorVersion = 0;
}
// Enable antialiasing if needed
if (m_settings.antialiasingLevel > 0)
glEnable(GL_MULTISAMPLE);
}
} // namespace priv
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Window/GlContext.hpp>
#include <SFML/System/ThreadLocalPtr.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
#include <SFML/OpenGL.hpp>
#include <set>
#include <cstdlib>
#ifdef SFML_SYSTEM_IOS
#include <OpenGLES/ES1/gl.h>
#else
#include <SFML/Window/glext/glext.h>
#endif
#if !defined(SFML_OPENGL_ES)
#if defined(SFML_SYSTEM_WINDOWS)
#include <SFML/Window/Win32/WglContext.hpp>
typedef sf::priv::WglContext ContextType;
#elif defined(SFML_SYSTEM_LINUX) || defined(SFML_SYSTEM_FREEBSD)
#include <SFML/Window/Unix/GlxContext.hpp>
typedef sf::priv::GlxContext ContextType;
#elif defined(SFML_SYSTEM_MACOS)
#include <SFML/Window/OSX/SFContext.hpp>
typedef sf::priv::SFContext ContextType;
#endif
#else
#if defined(SFML_SYSTEM_IOS)
#include <SFML/Window/iOS/EaglContext.hpp>
typedef sf::priv::EaglContext ContextType;
#else
#include <SFML/Window/EglContext.hpp>
typedef sf::priv::EglContext ContextType;
#endif
#endif
namespace
{
// This per-thread variable holds the current context for each thread
sf::ThreadLocalPtr<sf::priv::GlContext> currentContext(NULL);
// The hidden, inactive context that will be shared with all other contexts
ContextType* sharedContext = NULL;
// Internal contexts
sf::ThreadLocalPtr<sf::priv::GlContext> internalContext(NULL);
std::set<sf::priv::GlContext*> internalContexts;
sf::Mutex internalContextsMutex;
// Check if the internal context of the current thread is valid
bool hasInternalContext()
{
// The internal context can be null...
if (!internalContext)
return false;
// ... or non-null but deleted from the list of internal contexts
sf::Lock lock(internalContextsMutex);
return internalContexts.find(internalContext) != internalContexts.end();
}
// Retrieve the internal context for the current thread
sf::priv::GlContext* getInternalContext()
{
if (!hasInternalContext())
{
internalContext = sf::priv::GlContext::create();
sf::Lock lock(internalContextsMutex);
internalContexts.insert(internalContext);
}
return internalContext;
}
}
namespace sf
{
namespace priv
{
////////////////////////////////////////////////////////////
void GlContext::globalInit()
{
// Create the shared context
sharedContext = new ContextType(NULL);
sharedContext->initialize();
// This call makes sure that:
// - the shared context is inactive (it must never be)
// - another valid context is activated in the current thread
sharedContext->setActive(false);
}
////////////////////////////////////////////////////////////
void GlContext::globalCleanup()
{
// Destroy the shared context
delete sharedContext;
sharedContext = NULL;
// Destroy the internal contexts
sf::Lock lock(internalContextsMutex);
for (std::set<GlContext*>::iterator it = internalContexts.begin(); it != internalContexts.end(); ++it)
delete *it;
internalContexts.clear();
}
////////////////////////////////////////////////////////////
void GlContext::ensureContext()
{
// If there's no active context on the current thread, activate an internal one
if (!currentContext)
getInternalContext()->setActive(true);
}
////////////////////////////////////////////////////////////
GlContext* GlContext::create()
{
GlContext* context = new ContextType(sharedContext);
context->initialize();
return context;
}
////////////////////////////////////////////////////////////
GlContext* GlContext::create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel)
{
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
ensureContext();
// Create the context
GlContext* context = new ContextType(sharedContext, settings, owner, bitsPerPixel);
context->initialize();
return context;
}
////////////////////////////////////////////////////////////
GlContext* GlContext::create(const ContextSettings& settings, unsigned int width, unsigned int height)
{
// Make sure that there's an active context (context creation may need extensions, and thus a valid context)
ensureContext();
// Create the context
GlContext* context = new ContextType(sharedContext, settings, width, height);
context->initialize();
return context;
}
////////////////////////////////////////////////////////////
GlContext::~GlContext()
{
// Deactivate the context before killing it, unless we're inside Cleanup()
if (sharedContext)
setActive(false);
}
////////////////////////////////////////////////////////////
const ContextSettings& GlContext::getSettings() const
{
return m_settings;
}
////////////////////////////////////////////////////////////
bool GlContext::setActive(bool active)
{
if (active)
{
if (this != currentContext)
{
// Activate the context
if (makeCurrent())
{
// Set it as the new current context for this thread
currentContext = this;
return true;
}
else
{
return false;
}
}
else
{
// This context is already the active one on this thread, don't do anything
return true;
}
}
else
{
if (this == currentContext)
{
// To deactivate the context, we actually activate another one so that we make
// sure that there is always an active context for subsequent graphics operations
return getInternalContext()->setActive(true);
}
else
{
// This context is not the active one on this thread, don't do anything
return true;
}
}
}
////////////////////////////////////////////////////////////
GlContext::GlContext()
{
// Nothing to do
}
////////////////////////////////////////////////////////////
int GlContext::evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing)
{
return std::abs(static_cast<int>(bitsPerPixel - colorBits)) +
std::abs(static_cast<int>(settings.depthBits - depthBits)) +
std::abs(static_cast<int>(settings.stencilBits - stencilBits)) +
std::abs(static_cast<int>(settings.antialiasingLevel - antialiasing));
}
////////////////////////////////////////////////////////////
void GlContext::initialize()
{
// Activate the context
setActive(true);
// Retrieve the context version number
const GLubyte* version = glGetString(GL_VERSION);
if (version)
{
// The beginning of the returned string is "major.minor" (this is standard)
m_settings.majorVersion = version[0] - '0';
m_settings.minorVersion = version[2] - '0';
}
else
{
// Can't get the version number, assume 2.0
m_settings.majorVersion = 2;
m_settings.minorVersion = 0;
}
// Enable antialiasing if needed
if (m_settings.antialiasingLevel > 0)
glEnable(GL_MULTISAMPLE);
}
} // namespace priv
} // namespace sf

View file

@ -1,234 +1,234 @@
////////////////////////////////////////////////////////////
//
// 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_GLCONTEXT_HPP
#define SFML_GLCONTEXT_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/Window/ContextSettings.hpp>
#include <SFML/System/NonCopyable.hpp>
namespace sf
{
namespace priv
{
class WindowImpl;
////////////////////////////////////////////////////////////
/// \brief Abstract class representing an OpenGL context
///
////////////////////////////////////////////////////////////
class GlContext : NonCopyable
{
public :
////////////////////////////////////////////////////////////
/// \brief Perform the global initialization
///
/// This function is called once, before the very first OpenGL
/// resource is created. It makes sure that everything is ready
/// for contexts to work properly.
/// Note: this function doesn't need to be thread-safe, as it
/// can be called only once.
///
////////////////////////////////////////////////////////////
static void globalInit();
////////////////////////////////////////////////////////////
/// \brief Perform the global cleanup
///
/// This function is called after the very last OpenGL resource
/// is destroyed. It makes sure that everything that was
/// created by initialize() is properly released.
/// Note: this function doesn't need to be thread-safe, as it
/// can be called only once.
///
////////////////////////////////////////////////////////////
static void globalCleanup();
////////////////////////////////////////////////////////////
/// \brief Ensures that an OpenGL context is active in the current thread
///
////////////////////////////////////////////////////////////
static void ensureContext();
////////////////////////////////////////////////////////////
/// \brief Create a new context, not associated to a window
///
/// This function automatically chooses the specialized class
/// to use according to the OS.
///
/// \return Pointer to the created context (don't forget to delete it)
///
////////////////////////////////////////////////////////////
static GlContext* create();
////////////////////////////////////////////////////////////
/// \brief Create a new context attached to a window
///
/// This function automatically chooses the specialized class
/// to use according to the OS.
///
/// \param settings Creation parameters
/// \param owner Pointer to the owner window
/// \param bitsPerPixel Pixel depth (in bits per pixel)
///
/// \return Pointer to the created context
///
////////////////////////////////////////////////////////////
static GlContext* create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel);
////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target
///
/// This function automatically chooses the specialized class
/// to use according to the OS.
///
/// \param settings Creation parameters
/// \param width Back buffer width
/// \param height Back buffer height
///
/// \return Pointer to the created context
///
////////////////////////////////////////////////////////////
static GlContext* create(const ContextSettings& settings, unsigned int width, unsigned int height);
public :
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
virtual ~GlContext();
////////////////////////////////////////////////////////////
/// \brief Get the settings of the context
///
/// Note that these settings may be different than the ones
/// passed to the constructor; they are indeed adjusted if the
/// original settings are not directly supported by the system.
///
/// \return Structure containing the settings
///
////////////////////////////////////////////////////////////
const ContextSettings& getSettings() const;
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the context as the current target for rendering
///
/// A context is active only on the current thread, if you want to
/// make it active on another thread you have to deactivate it
/// on the previous thread first if it was active.
/// Only one context can be active on a thread at a time, thus
/// the context previously active (if any) automatically gets deactivated.
///
/// \param active True to activate, false to deactivate
///
/// \return True if operation was successful, false otherwise
///
////////////////////////////////////////////////////////////
bool setActive(bool active);
////////////////////////////////////////////////////////////
/// \brief Display what has been rendered to the context so far
///
////////////////////////////////////////////////////////////
virtual void display() = 0;
////////////////////////////////////////////////////////////
/// \brief Enable or disable vertical synchronization
///
/// Activating vertical synchronization will limit the number
/// of frames displayed to the refresh rate of the monitor.
/// This can avoid some visual artifacts, and limit the framerate
/// to a good value (but not constant across different computers).
///
/// \param enabled True to enable v-sync, false to deactivate
///
////////////////////////////////////////////////////////////
virtual void setVerticalSyncEnabled(bool enabled) = 0;
protected :
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor is meant for derived classes only.
///
////////////////////////////////////////////////////////////
GlContext();
////////////////////////////////////////////////////////////
/// \brief Activate the context as the current target
/// for rendering
///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
virtual bool makeCurrent() = 0;
////////////////////////////////////////////////////////////
/// \brief Evaluate a pixel format configuration
///
/// This functions can be used by implementations that have
/// several valid formats and want to get the best one.
/// A score is returned for the given configuration: the
/// lower the score is, the better the configuration is.
///
/// \param bitsPerPixel Requested pixel depth (bits per pixel)
/// \param settings Requested additionnal settings
/// \param colorBits Color bits of the configuration to evaluate
/// \param depthBits Depth bits of the configuration to evaluate
/// \param stencilBits Stencil bits of the configuration to evaluate
/// \param antialiasing Antialiasing level of the configuration to evaluate
///
/// \return Score of the configuration
///
////////////////////////////////////////////////////////////
static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
ContextSettings m_settings; ///< Creation settings of the context
private:
////////////////////////////////////////////////////////////
/// \brief Perform various initializations after the context construction
///
////////////////////////////////////////////////////////////
void initialize();
};
} // namespace priv
} // namespace sf
#endif // SFML_GLCONTEXT_HPP
////////////////////////////////////////////////////////////
//
// 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_GLCONTEXT_HPP
#define SFML_GLCONTEXT_HPP
////////////////////////////////////////////////////////////
// Headers
////////////////////////////////////////////////////////////
#include <SFML/Config.hpp>
#include <SFML/Window/ContextSettings.hpp>
#include <SFML/System/NonCopyable.hpp>
namespace sf
{
namespace priv
{
class WindowImpl;
////////////////////////////////////////////////////////////
/// \brief Abstract class representing an OpenGL context
///
////////////////////////////////////////////////////////////
class GlContext : NonCopyable
{
public:
////////////////////////////////////////////////////////////
/// \brief Perform the global initialization
///
/// This function is called once, before the very first OpenGL
/// resource is created. It makes sure that everything is ready
/// for contexts to work properly.
/// Note: this function doesn't need to be thread-safe, as it
/// can be called only once.
///
////////////////////////////////////////////////////////////
static void globalInit();
////////////////////////////////////////////////////////////
/// \brief Perform the global cleanup
///
/// This function is called after the very last OpenGL resource
/// is destroyed. It makes sure that everything that was
/// created by initialize() is properly released.
/// Note: this function doesn't need to be thread-safe, as it
/// can be called only once.
///
////////////////////////////////////////////////////////////
static void globalCleanup();
////////////////////////////////////////////////////////////
/// \brief Ensures that an OpenGL context is active in the current thread
///
////////////////////////////////////////////////////////////
static void ensureContext();
////////////////////////////////////////////////////////////
/// \brief Create a new context, not associated to a window
///
/// This function automatically chooses the specialized class
/// to use according to the OS.
///
/// \return Pointer to the created context (don't forget to delete it)
///
////////////////////////////////////////////////////////////
static GlContext* create();
////////////////////////////////////////////////////////////
/// \brief Create a new context attached to a window
///
/// This function automatically chooses the specialized class
/// to use according to the OS.
///
/// \param settings Creation parameters
/// \param owner Pointer to the owner window
/// \param bitsPerPixel Pixel depth (in bits per pixel)
///
/// \return Pointer to the created context
///
////////////////////////////////////////////////////////////
static GlContext* create(const ContextSettings& settings, const WindowImpl* owner, unsigned int bitsPerPixel);
////////////////////////////////////////////////////////////
/// \brief Create a new context that embeds its own rendering target
///
/// This function automatically chooses the specialized class
/// to use according to the OS.
///
/// \param settings Creation parameters
/// \param width Back buffer width
/// \param height Back buffer height
///
/// \return Pointer to the created context
///
////////////////////////////////////////////////////////////
static GlContext* create(const ContextSettings& settings, unsigned int width, unsigned int height);
public:
////////////////////////////////////////////////////////////
/// \brief Destructor
///
////////////////////////////////////////////////////////////
virtual ~GlContext();
////////////////////////////////////////////////////////////
/// \brief Get the settings of the context
///
/// Note that these settings may be different than the ones
/// passed to the constructor; they are indeed adjusted if the
/// original settings are not directly supported by the system.
///
/// \return Structure containing the settings
///
////////////////////////////////////////////////////////////
const ContextSettings& getSettings() const;
////////////////////////////////////////////////////////////
/// \brief Activate or deactivate the context as the current target for rendering
///
/// A context is active only on the current thread, if you want to
/// make it active on another thread you have to deactivate it
/// on the previous thread first if it was active.
/// Only one context can be active on a thread at a time, thus
/// the context previously active (if any) automatically gets deactivated.
///
/// \param active True to activate, false to deactivate
///
/// \return True if operation was successful, false otherwise
///
////////////////////////////////////////////////////////////
bool setActive(bool active);
////////////////////////////////////////////////////////////
/// \brief Display what has been rendered to the context so far
///
////////////////////////////////////////////////////////////
virtual void display() = 0;
////////////////////////////////////////////////////////////
/// \brief Enable or disable vertical synchronization
///
/// Activating vertical synchronization will limit the number
/// of frames displayed to the refresh rate of the monitor.
/// This can avoid some visual artifacts, and limit the framerate
/// to a good value (but not constant across different computers).
///
/// \param enabled True to enable v-sync, false to deactivate
///
////////////////////////////////////////////////////////////
virtual void setVerticalSyncEnabled(bool enabled) = 0;
protected:
////////////////////////////////////////////////////////////
/// \brief Default constructor
///
/// This constructor is meant for derived classes only.
///
////////////////////////////////////////////////////////////
GlContext();
////////////////////////////////////////////////////////////
/// \brief Activate the context as the current target
/// for rendering
///
/// \return True on success, false if any error happened
///
////////////////////////////////////////////////////////////
virtual bool makeCurrent() = 0;
////////////////////////////////////////////////////////////
/// \brief Evaluate a pixel format configuration
///
/// This functions can be used by implementations that have
/// several valid formats and want to get the best one.
/// A score is returned for the given configuration: the
/// lower the score is, the better the configuration is.
///
/// \param bitsPerPixel Requested pixel depth (bits per pixel)
/// \param settings Requested additionnal settings
/// \param colorBits Color bits of the configuration to evaluate
/// \param depthBits Depth bits of the configuration to evaluate
/// \param stencilBits Stencil bits of the configuration to evaluate
/// \param antialiasing Antialiasing level of the configuration to evaluate
///
/// \return Score of the configuration
///
////////////////////////////////////////////////////////////
static int evaluateFormat(unsigned int bitsPerPixel, const ContextSettings& settings, int colorBits, int depthBits, int stencilBits, int antialiasing);
////////////////////////////////////////////////////////////
// Member data
////////////////////////////////////////////////////////////
ContextSettings m_settings; ///< Creation settings of the context
private:
////////////////////////////////////////////////////////////
/// \brief Perform various initializations after the context construction
///
////////////////////////////////////////////////////////////
void initialize();
};
} // namespace priv
} // namespace sf
#endif // SFML_GLCONTEXT_HPP

View file

@ -1,85 +1,85 @@
////////////////////////////////////////////////////////////
//
// 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/Window/GlResource.hpp>
#include <SFML/Window/GlContext.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
namespace
{
// OpenGL resources counter and its mutex
unsigned int count = 0;
sf::Mutex mutex;
}
namespace sf
{
////////////////////////////////////////////////////////////
GlResource::GlResource()
{
{
// Protect from concurrent access
Lock lock(mutex);
// If this is the very first resource, trigger the global context initialization
if (count == 0)
priv::GlContext::globalInit();
// Increment the resources counter
count++;
}
// Now make sure that there is an active OpenGL context in the current thread
priv::GlContext::ensureContext();
}
////////////////////////////////////////////////////////////
GlResource::~GlResource()
{
// Protect from concurrent access
Lock lock(mutex);
// Decrement the resources counter
count--;
// If there's no more resource alive, we can trigger the global context cleanup
if (count == 0)
priv::GlContext::globalCleanup();
}
////////////////////////////////////////////////////////////
void GlResource::ensureGlContext()
{
priv::GlContext::ensureContext();
}
} // namespace sf
////////////////////////////////////////////////////////////
//
// 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/Window/GlResource.hpp>
#include <SFML/Window/GlContext.hpp>
#include <SFML/System/Mutex.hpp>
#include <SFML/System/Lock.hpp>
namespace
{
// OpenGL resources counter and its mutex
unsigned int count = 0;
sf::Mutex mutex;
}
namespace sf
{
////////////////////////////////////////////////////////////
GlResource::GlResource()
{
{
// Protect from concurrent access
Lock lock(mutex);
// If this is the very first resource, trigger the global context initialization
if (count == 0)
priv::GlContext::globalInit();
// Increment the resources counter
count++;
}
// Now make sure that there is an active OpenGL context in the current thread
priv::GlContext::ensureContext();
}
////////////////////////////////////////////////////////////
GlResource::~GlResource()
{
// Protect from concurrent access
Lock lock(mutex);
// Decrement the resources counter
count--;
// If there's no more resource alive, we can trigger the global context cleanup
if (count == 0)
priv::GlContext::globalCleanup();
}
////////////////////////////////////////////////////////////
void GlResource::ensureGlContext()
{
priv::GlContext::ensureContext();
}
} // namespace sf

View file

@ -43,7 +43,7 @@ namespace priv
////////////////////////////////////////////////////////////
class JoystickManager : NonCopyable
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Get the global unique instance of the manager

View file

@ -61,7 +61,7 @@ namespace priv
////////////////////////////////////////////////////////////
class PoolWrapper : NonCopyable
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Default constructor

View file

@ -54,7 +54,7 @@ typedef std::vector<IOHIDElementRef> IOHIDElements;
////////////////////////////////////////////////////////////
class HIDInputManager : NonCopyable
{
public :
public:
////////////////////////////////////////////////////////////
/// \brief Get the unique instance of the class
@ -86,7 +86,7 @@ public :
////////////////////////////////////////////////////////////
bool isMouseButtonPressed(Mouse::Button button);
public :
public:
////////////////////////////////////////////////////////////
/// \brief Get the usb location ID of a given device
@ -130,7 +130,7 @@ public :
////////////////////////////////////////////////////////////
static Keyboard::Key nonLocalizedKeys(UniChar virtualKeycode);
private :
private:
////////////////////////////////////////////////////////////
/// \brief Default constructor
@ -247,7 +247,7 @@ private :
////////////////////////////////////////////////////////////
static UInt8 usageToVirtualCode(UInt32 usage);
private :
private:
////////////////////////////////////////////////////////////
// Member data

View file

@ -367,7 +367,7 @@ void HIDInputManager::loadKey(IOHIDElementRef key)
}
////////////////////////////////////////////////////////////
// These are known to be unbound :
// These are known to be unbound:
// Supposed Virtual | HID | Supposed Key
// ===============================================
// 0x1b | 0x2d | Hyphen
@ -390,7 +390,7 @@ void HIDInputManager::loadKey(IOHIDElementRef key)
} /* if (error == noErr) */
else
{
sf::err() << "Cannot translate the virtual key code, error : "
sf::err() << "Cannot translate the virtual key code, error: "
<< error
<< std::endl;
}

Some files were not shown because too many files have changed in this diff Show more