+ void stop()
+ {
+ alSourceStop(mSource);
+ mIsPlaying = false;
+
+ mStreamTimer.invalidate();
+ }
+
+ void pause()
+ {
+ alSourcePause(mSource);
+ mIsPlaying = false;
+
+ mStreamTimer.invalidate();
+ }
+
+ void resume()
+ {
+ alSourcePlay(mSource);
+ mIsPlaying = true;
+
+ ALenum type;
+ alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
+
+ if (type == AL_STREAMING)
+ {
+ mStreamTimer.init(boost::bind(&Impl::streamUpdate, this, _1, _2),
+ 1.0, Timer::REPEAT);
+ }
+ }
+
+
+ void setSample(const std::string& name)
+ {
+ bool playing = isPlaying();
+ ALenum type;
+ alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
+
+ stop();
+ mQueue.clear();
+
+ //alSourcei(mSource, AL_BUFFER, AL_NONE);
+ enqueue(name);
+
+ if (playing)
+ {
+ if (type == AL_STREAMING) stream();
+ else play();
+ }
+ }
+
+ 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
+ }
+
+
+ ALuint mSource;
+ std::vector<ALuint> mBufferObjects;
+
+ bool mIsPlaying;
+ bool mIsLooping;
+
+ std::deque<BufferP> mQueue;
+
+ Timer mStreamTimer;