+ void stream()
+ {
+ ALenum type;
+ alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
+
+ alSourcei(mSource, AL_BUFFER, AL_NONE);
+ mBuffer->rewind();
+ mBuffer->beginStream(mSource);
+
+ alSourcei(mSource, AL_LOOPING, AL_FALSE);
+ alSourcePlay(mSource);
+ mIsPlaying = true;
+
+ mStreamTimer.init(boost::bind(&Impl::streamUpdate, this, _1, _2), 1.0,
+ Timer::REPEAT);
+ }
+
+ inline void update()
+ {
+ ALint finished = 0;
+
+ alGetSourcei(mSource, AL_BUFFERS_PROCESSED, &finished);
+
+ while (finished-- > 0)
+ {
+ ALuint buffer;
+
+ alSourceUnqueueBuffers(mSource, 1, &buffer);
+
+ Buffer::StreamStatus status = mBuffer->stream(buffer);
+
+ if (status == Buffer::STREAM_OK)
+ {
+ alSourceQueueBuffers(mSource, 1, &buffer);
+ }
+ else if (status == Buffer::STREAM_EOF)
+ {
+ if (!mQueue.empty())
+ {
+ // begin the next buffer in the queue
+ mExpired.push_back(mBuffer);
+ mBuffer = mQueue.front();
+ mQueue.pop();
+ mBuffer->beginStream(mSource, 1);
+ }
+ else if (mIsLooping)
+ {
+ // restart from the beginning
+ mBuffer->rewind();
+ mBuffer->stream(buffer);
+ alSourceQueueBuffers(mSource, 1, &buffer);
+ }
+ }
+ else if (status == Buffer::STREAM_WRONG)
+ {
+ clear();
+ mBuffer->beginStream(mSource, 1);
+ }
+ }
+
+ 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
+ if (mIsPlaying && state != AL_PLAYING)
+ {
+ alSourcePlay(mSource);
+ }
+ }
+
+ inline void clear()
+ {
+ // try to remove expired buffers
+ std::vector<BufferP>::iterator it;
+ for (it = mExpired.end() - 1; it >= mExpired.begin(); --it)
+ {
+ if ((*it)->clear()) mExpired.erase(it);
+ }
+ }
+
+
+ void stop()
+ {
+ alSourceStop(mSource);
+ mIsPlaying = false;
+ }
+
+ inline void pause()
+ {
+ alSourcePause(mSource);
+ mIsPlaying = false;
+ }
+
+ inline void resume()
+ {
+ alSourcePlay(mSource);
+ mIsPlaying = true;
+ }
+
+
+ inline void setSample(const std::string& name)
+ {
+ bool playing = isPlaying();
+ ALenum type;
+ alGetSourcei(mSource, AL_SOURCE_TYPE, &type);
+
+ stop();
+
+ //alSourcei(mSource, AL_BUFFER, AL_NONE);
+ mBuffer = Buffer::getInstance(name);
+
+ if (type == AL_STREAMING)
+ {
+ if (playing) stream();
+ }
+ else
+ {
+ if (playing) play();
+ }
+ }
+
+ inline void enqueue(const std::string& name)
+ {
+ BufferP buffer = Buffer::getInstance(name);
+ mQueue.push(buffer);
+ }