+ void stop()
+ {
+ alSourceStop(mSource);
+ mIsPlaying = false;
+
+ mStreamTimer.invalidate();
+ }
+
+ void pause()
+ {
+ alSourcePause(mSource);
+ mIsPlaying = false;
+
+ mStreamTimer.invalidate();
+ }
+
+
+ void setSample(const std::string& name)
+ {
+ stop();
+ alSourcei(mSource, AL_BUFFER, AL_NONE);
+
+ mQueue.clear();
+ mIsLoaded = false;
+
+ enqueue(name);
+
+ while (!mBuffers.empty())
+ {
+ alDeleteBuffers(1, &mBuffers.back());
+ mBuffers.pop_back();
+ }
+ }
+
+ void enqueue(const std::string& name)
+ {
+ BufferP buffer = Buffer::getInstance(name);
+ mQueue.push_back(buffer);
+ }
+
+
+ bool isPlaying() const
+ {
+ if (mIsPlaying) return true;
+
+ ALenum state;
+ alGetSourcei(mSource, AL_SOURCE_STATE, &state);
+
+ return state == AL_PLAYING;
+ }
+
+
+ void setLooping(bool looping)
+ {
+ mIsLooping = looping;
+
+ ALenum type;
+ alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
+
+ if (type != AL_STREAMING)
+ {
+ alSourcei(mSource, AL_LOOPING, mIsLooping);
+ }
+ }
+
+
+ void streamUpdate(Timer& timer, Scalar t)
+ {
+ // 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
+ }
+
+ 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;
+
+ bool mIsLoaded;
+ bool mIsPlaying;
+ bool mIsLooping;
+
+ std::deque<BufferP> mQueue;
+
+ Timer mStreamTimer;
+
+ static unsigned gRetainCount;
+ static ALCdevice* gAlDevice;
+ static ALCcontext* gAlContext;