#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 "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 = Sound::getPath(name);
+ int result = ov_fopen((char*)path.c_str(), &mOggStream);
if (result < 0)
{
- logWarning << "error while loading sound "
- << getName() << std::endl;
- throw Error(Error::UNKNOWN_AUDIO_FORMAT, getName());
+ logWarning << "couldn't load sound: " << path << std::endl;
+ throw Error(Error::UNKNOWN_AUDIO_FORMAT, path);
}
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()
{
+ retainBackend();
+
mIsLoaded = false;
mIsPlaying = false;
mIsLooping = false;
alDeleteBuffers(1, &mBuffers.back());
mBuffers.pop_back();
}
+
+ releaseBackend();
}
// 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);
+ }
+ }
+
ALuint mSource;
std::list<ALuint> mBuffers;
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
std::string Sound::getPath(const std::string& name)
{
- std::string path = Resource::getPath("sounds/" + name + ".ogg");
- return path;
+ if (boost::find_last(name, ".ogg"))
+ {
+ return Resource::getPath(name);
+ }
+ else
+ {
+ std::string path("sounds/");
+ path += name;
+ path += ".ogg";
+ return Resource::getPath(path);
+ }
}