Add wrapper for large part of SDL2 audio functionality

This commit is contained in:
Dmitry Marakasov 2014-11-29 22:58:27 +03:00
parent bb1c4bf168
commit 2be68a9ebb
9 changed files with 330 additions and 0 deletions

View File

@ -5,6 +5,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
# there are functions present on wiki, but not yet in stable SDL2 releases;
# we hide these under following options
OPTION(SDL2PP_NEW_2_0_4 "Enable new SDL2 functions present since SDL2 2.0.4" OFF)
IF(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
OPTION(SDL2PP_WITH_IMAGE "Enable SDL2_image support" ON)
ELSE(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR)
@ -45,6 +49,9 @@ INCLUDE_DIRECTORIES(BEFORE ${PROJECT_BINARY_DIR})
# sources
SET(LIBRARY_SOURCES
SDL2pp/AudioDevice.cc
SDL2pp/AudioLock.cc
SDL2pp/AudioSpec.cc
SDL2pp/Exception.cc
SDL2pp/Point.cc
SDL2pp/RWops.cc
@ -57,6 +64,7 @@ SET(LIBRARY_SOURCES
)
SET(LIBRARY_HEADERS
SDL2pp/Audio.hh
SDL2pp/Exception.hh
SDL2pp/ExtraRWops.hh
SDL2pp/Point.hh

108
SDL2pp/Audio.hh Normal file
View File

@ -0,0 +1,108 @@
/*
libSDL2pp - C++ wrapper for libSDL2
Copyright (C) 2014 Dmitry Marakasov <amdmi3@amdmi3.ru>
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 SDL2PP_AUDIO_HH
#define SDL2PP_AUDIO_HH
#include <functional>
#include <string>
#include <SDL2/SDL_audio.h>
#include <SDL2pp/Config.hh>
namespace SDL2pp {
class AudioSpec : public SDL_AudioSpec {
public:
typedef std::function<void(Uint8* stream, int len)> AudioCallback;
private:
AudioCallback callback_;
private:
static void SDLCallback(void *userdata, Uint8* stream, int len);
public:
AudioSpec(int freq, SDL_AudioFormat format, Uint8 channels, Uint16 samples, AudioCallback&& callback);
~AudioSpec();
AudioSpec(AudioSpec&& other) noexcept;
AudioSpec& operator=(AudioSpec&& other) noexcept;
AudioSpec(const AudioSpec& other) = delete;
AudioSpec& operator=(const AudioSpec& other) = delete;
void ChangeCallback(AudioCallback&& callback); // should be called with audio device using this spec locked!
void MergeChanges(const SDL_AudioSpec& obtained);
const SDL_AudioSpec* Get() const;
};
class AudioDevice {
private:
SDL_AudioDeviceID device_id_;
public:
class LockHandle {
friend class AudioDevice;
private:
AudioDevice* device_;
private:
LockHandle(AudioDevice* device);
public:
~LockHandle();
LockHandle(LockHandle&& other) noexcept;
LockHandle& operator=(LockHandle&& other) noexcept;
LockHandle(const LockHandle& other) = delete;
LockHandle& operator=(const LockHandle& other) = delete;
};
public:
AudioDevice(const std::string& device, bool iscapture, const AudioSpec& spec);
AudioDevice(const std::string& device, bool iscapture, AudioSpec& spec, int allowed_changes);
virtual ~AudioDevice();
AudioDevice(const AudioDevice& other) = delete;
AudioDevice(AudioDevice&& other) noexcept;
AudioDevice& operator=(const AudioDevice& other) = delete;
AudioDevice& operator=(AudioDevice&& other) noexcept;
SDL_AudioDeviceID Get() const;
void Pause(bool pause_on);
SDL_AudioStatus GetStatus() const;
LockHandle Lock();
#ifdef SDL2PP_NEW_2_0_4
void QueueAudio(const void* data, Uint32 len);
void ClearQueuedAudio();
Uint32 GetQueuedAudioSize() const;
#endif
};
}
#endif

94
SDL2pp/AudioDevice.cc Normal file
View File

@ -0,0 +1,94 @@
/*
libSDL2pp - C++ wrapper for libSDL2
Copyright (C) 2014 Dmitry Marakasov <amdmi3@amdmi3.ru>
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.
*/
#include <SDL2pp/Exception.hh>
#include <SDL2pp/Audio.hh>
namespace SDL2pp {
AudioDevice::AudioDevice(const std::string& device, bool iscapture, const AudioSpec& spec) {
SDL_AudioSpec obtained;
if ((device_id_ = SDL_OpenAudioDevice(device.empty() ? nullptr : device.c_str(), iscapture ? 1 : 0, &spec, &obtained, 0)) == 0)
throw Exception("SDL_OpenAudioDevice failed");
}
AudioDevice::AudioDevice(const std::string& device, bool iscapture, AudioSpec& spec, int allowed_changes) {
SDL_AudioSpec obtained;
if ((device_id_ = SDL_OpenAudioDevice(device.empty() ? nullptr : device.c_str(), iscapture ? 1 : 0, &spec, &obtained, allowed_changes)) == 0)
throw Exception("SDL_OpenAudioDevice failed");
spec.MergeChanges(obtained);
}
AudioDevice::~AudioDevice() {
if (device_id_ != 0)
SDL_CloseAudioDevice(device_id_);
}
AudioDevice::AudioDevice(AudioDevice&& other) noexcept : device_id_(other.device_id_) {
other.device_id_ = 0;
}
AudioDevice& AudioDevice::operator=(AudioDevice&& other) noexcept {
if (device_id_)
SDL_CloseAudioDevice(device_id_);
device_id_ = other.device_id_;
other.device_id_ = 0;
return *this;
}
SDL_AudioDeviceID AudioDevice::Get() const {
return device_id_;
}
void AudioDevice::Pause(bool pause_on) {
SDL_PauseAudioDevice(device_id_, pause_on ? 1 : 0);
}
SDL_AudioStatus AudioDevice::GetStatus() const {
return SDL_GetAudioDeviceStatus(device_id_);
}
AudioDevice::LockHandle AudioDevice::Lock() {
return LockHandle(this);
}
#ifdef SDL2PP_NEW_2_0_4
void AudioDevice::QueueAudio(const void* data, Uint32 len) {
if (SDL_QueueAudio(device_id_, data, len) == 0)
throw Exception("SDL_QueueAudio failed");
}
void AudioDevice::ClearQueuedAudio() {
SDL_ClearQueuedAudio(device_id_);
}
Uint32 GetQueuedAudioSize() const {
return SDL_GetQueuedAudioSize(device_id_);
}
#endif
}

47
SDL2pp/AudioLock.cc Normal file
View File

@ -0,0 +1,47 @@
/*
libSDL2pp - C++ wrapper for libSDL2
Copyright (C) 2014 Dmitry Marakasov <amdmi3@amdmi3.ru>
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.
*/
#include <SDL2pp/Audio.hh>
namespace SDL2pp {
AudioDevice::LockHandle::LockHandle(AudioDevice* device) : device_(device) {
SDL_LockAudioDevice(device_->device_id_);
}
AudioDevice::LockHandle::~LockHandle() {
if (device_ != nullptr)
SDL_UnlockAudioDevice(device_->device_id_);
}
AudioDevice::LockHandle::LockHandle(AudioDevice::LockHandle&& other) noexcept : device_(other.device_) {
other.device_ = nullptr;
}
AudioDevice::LockHandle& AudioDevice::LockHandle::operator=(AudioDevice::LockHandle&& other) noexcept {
device_ = other.device_;
other.device_ = nullptr;
return *this;
}
}

65
SDL2pp/AudioSpec.cc Normal file
View File

@ -0,0 +1,65 @@
/*
libSDL2pp - C++ wrapper for libSDL2
Copyright (C) 2014 Dmitry Marakasov <amdmi3@amdmi3.ru>
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.
*/
#include <algorithm>
#include <SDL2pp/Audio.hh>
namespace SDL2pp {
void AudioSpec::SDLCallback(void *userdata, Uint8* stream, int len) {
AudioSpec* audiospec = static_cast<AudioSpec*>(userdata);
audiospec->callback_(stream, len);
}
AudioSpec::AudioSpec(int freq, SDL_AudioFormat format, Uint8 channels, Uint16 samples, AudioCallback&& callback)
: callback_(std::move(callback)) {
std::fill((char*)this, (char*)this + sizeof(SDL_AudioSpec), 0);
SDL_AudioSpec::freq = freq;
SDL_AudioSpec::format = format;
SDL_AudioSpec::channels = channels;
SDL_AudioSpec::samples = samples;
SDL_AudioSpec::callback = SDLCallback;
SDL_AudioSpec::userdata = static_cast<void*>(this);
}
AudioSpec::~AudioSpec() {
}
AudioSpec::AudioSpec(AudioSpec&&) noexcept = default;
AudioSpec& AudioSpec::operator=(AudioSpec&&) noexcept = default;
void AudioSpec::ChangeCallback(AudioCallback&& callback) {
callback_ = callback;
}
void AudioSpec::MergeChanges(const SDL_AudioSpec& obtained) {
freq = obtained.freq;
format = obtained.format;
channels = obtained.channels;
samples = obtained.samples;
}
const SDL_AudioSpec* AudioSpec::Get() const {
return static_cast<const SDL_AudioSpec*>(this);
}
}

View File

@ -23,5 +23,6 @@
#define SDL2PP_CONFIG_HH
#cmakedefine SDL2PP_WITH_IMAGE
#cmakedefine SDL2PP_NEW_2_0_4
#endif

View File

@ -26,6 +26,7 @@
#include <SDL2pp/Config.hh>
#include <SDL2pp/SDL.hh>
#include <SDL2pp/Audio.hh>
#include <SDL2pp/Window.hh>
#include <SDL2pp/Renderer.hh>
#include <SDL2pp/Texture.hh>

View File

@ -2,6 +2,7 @@
# they are compilable (e.g., includes and forward declarations are
# complete and do not require extra includes)
SET(HEADER_TESTS
header_audio
header_exception
header_point
header_rect

5
tests/header_audio.cc Normal file
View File

@ -0,0 +1,5 @@
#include <SDL2pp/Audio.hh>
int main() {
return 0;
}