-/*******************************************************************************
-
- Copyright (c) 2009, Charles McGarvey
- All rights reserved.
-
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
-
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-*******************************************************************************/
+/*] Copyright (c) 2009-2010, Charles McGarvey [**************************
+**] All rights reserved.
+*
+* vi:ts=4 sw=4 tw=75
+*
+* Distributable under the terms and conditions of the 2-clause BSD license;
+* see the file COPYING for a complete text of the license.
+*
+**************************************************************************/
#include <cstdio>
#include <deque>
#include <list>
#include <string>
+#include <boost/algorithm/string.hpp>
+
#include <AL/al.h>
+#include <AL/alc.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>
-#include "Engine.hh"
-#include "Exception.hh"
-#include "Library.hh"
+#include "Error.hh"
+#include "Manager.hh"
#include "Log.hh"
#include "Sound.hh"
#include "Timer.hh"
class Buffer;
typedef boost::shared_ptr<Buffer> BufferP;
- class Buffer : public Library<Buffer>
+ class Buffer : public Manager<Buffer>
{
public:
- Buffer(const std::string& name) :
- Library<Buffer>(name),
+ Buffer() :
mBuffer(-1)
{
mOggStream.datasource = 0;
- openFile();
}
~Buffer()
}
- void openFile()
+ void init(const std::string& name)
{
if (mOggStream.datasource)
{
mOggStream.datasource = 0;
}
- std::string filePath = Sound::getPath(getName());
- int result = ov_fopen((char*)filePath.c_str(), &mOggStream);
+ std::string path(name);
+ if (!Sound::getPath(path))
+ {
+ Error(Error::RESOURCE_NOT_FOUND, path).raise();
+ }
- if (result < 0)
+ if (ov_fopen((char*)path.c_str(), &mOggStream) < 0)
{
- logWarning << "error while loading sound "
- << getName() << std::endl;
- throw Exception(ErrorCode::UNKNOWN_AUDIO_FORMAT, getName());
+ Error(Error::UNKNOWN_AUDIO_FORMAT, path).raise();
}
vorbis_info* vorbisInfo = ov_info(&mOggStream, -1);
void loadAll(ALuint source)
{
- if (!mOggStream.datasource) openFile();
+ if (!mOggStream.datasource) init(getName());
if (!mOggStream.datasource) return;
char data[BUFFER_SIZE];
void rewind()
{
- if (!mOggStream.datasource) openFile();
+ if (!mOggStream.datasource) init(getName());
else ov_raw_seek(&mOggStream, 0);
}
void init()
{
- // make sure the engine is initialized
- Engine::getInstance();
+ retainBackend();
mIsLoaded = false;
mIsPlaying = false;
alDeleteBuffers(1, &mBuffers.back());
mBuffers.pop_back();
}
+
+ releaseBackend();
}
{
// nothing more to play, stopping...
mIsPlaying = false;
- std::remove(mBuffers.begin(), mBuffers.end(), bufferObj);
+ std::remove(mBuffers.begin(), mBuffers.end(),
+ bufferObj);
}
}
}
ALenum state;
alGetSourcei(mSource, AL_SOURCE_STATE, &state);
- // restart playing if we're stopped but supposed to be playing... this
- // means we didn't queue enough and the audio skipped :-(
+ // restart playing if we're stopped but supposed to be playing...
+ // this means we didn't queue enough and the audio skipped :-(
if (mIsPlaying && state != AL_PLAYING)
{
alSourcePlay(mSource);
{
// don't let the music die!
update();
- // TODO - might be nice to also allow using threads for streaming rather
- // than a timer, probably as a compile-time option
+ // TODO - might be nice to also allow using threads for streaming
+ // rather than a timer, probably as a compile-time option
+ }
+
+ static void retainBackend()
+ {
+ if (gRetainCount++ == 0)
+ {
+ gAlDevice = alcOpenDevice(0);
+ gAlContext = alcCreateContext(gAlDevice, 0);
+ if (!gAlDevice || !gAlContext)
+ {
+ const char* error = alcGetString(gAlDevice,
+ alcGetError(gAlDevice));
+ logError << "audio subsystem initialization failure: "
+ << error << std::endl;
+ }
+ else
+ {
+ alcMakeContextCurrent(gAlContext);
+ logInfo << "opened sound device `"
+ << alcGetString(gAlDevice,
+ ALC_DEFAULT_DEVICE_SPECIFIER)
+ << "'" << std::endl;
+ }
+ }
+ }
+
+ static void releaseBackend()
+ {
+ if (--gRetainCount == 0)
+ {
+ alcMakeContextCurrent(0);
+ alcDestroyContext(gAlContext);
+ alcCloseDevice(gAlDevice);
+ }
}
std::deque<BufferP> mQueue;
Timer mStreamTimer;
+
+ static unsigned gRetainCount;
+ static ALCdevice* gAlDevice;
+ static ALCcontext* gAlContext;
};
+unsigned Sound::Impl::gRetainCount = 0;
+ALCdevice* Sound::Impl::gAlDevice = 0;
+ALCcontext* Sound::Impl::gAlContext = 0;
+
Sound::Sound() :
// pass through
void Sound::setListenerPosition(const Vector3& position)
{
- //alListener3f(AL_POSITION, float(position[0]), float(position[1]),
- //float(position[2]));
float vec[] = {position[0], position[1], position[2]};
alListenerfv(AL_POSITION, vec);
}
void Sound::setListenerVelocity(const Vector3& velocity)
{
- //alListener3f(AL_VELOCITY, float(velocity[0]), float(velocity[1]),
- //float(velocity[2]));
float vec[] = {velocity[0], velocity[1], velocity[2]};
alListenerfv(AL_VELOCITY, vec);
}
-void Sound::setListenerOrientation(const Vector3& forward, const Vector3& up)
+void Sound::setListenerOrientation(const Vector3& forward,
+ const Vector3& up)
{
float vec[6];
vec[0] = float(forward[0]);
}
-std::string Sound::getPath(const std::string& name)
+bool Sound::getPath(std::string& name)
{
- std::string path = Resource::getPath("sounds/" + name + ".ogg");
- return path;
+ return Resource::getPath(name, "sounds/", "ogg");
}
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void SoundStream::enqueue(const std::string& name)
} // namespace Mf
-/** vim: set ts=4 sw=4 tw=80: *************************************************/
-