void OpenALAudioObject::play()
	{
		careOfSource();

		ALint sourceState;
		alGetSourcei(mSourceId, AL_SOURCE_STATE, &sourceState);
		alErrorHandler("OpenALAudioObject::play", "Error occured calling alGetSourcei");

		switch (sourceState)
		{
			case AL_PLAYING:
				return;

			case AL_PAUSED:
				break;

			case AL_INITIAL:
			{
				boost::function<void(void)> onFinishedCallback = boost::bind
				(
					&OpenALAudioObject::onStreamFinished,
					this
				);
				
				boost::shared_ptr<Stream> stream
				(
					new OpenALStream
					(
						createFile(mAudioName),
						onFinishedCallback, 
						mSourceId
					)
				);
				
				mStreamHandle = mStreamLoop->driveMyStream(stream);
				
				break;
			}

			default:
				return;
		}
		
		alSourcef(mSourceId, AL_GAIN, mGain);
		alErrorHandler("OpenALAudioObject::play", "Error occured setting gain");

		alSourcePlay(mSourceId);
		alErrorHandler("OpenALAudioObject::play", "Error occured calling alSourcePlay.");
	}
	void OpenALAudioObject::stop()
	{
		if (mSourceId)
		{
			alSourceStop(mSourceId);
			alErrorHandler("OpenALAudioObject::stop", "Error occured calling alSourceStop.");

			mStreamLoop->removeMyStream(mStreamHandle);
			mStreamHandle = 0;
			
			alDeleteSources(1, &mSourceId);
			alErrorHandler("OpenALAudioObject::stop", "Error occured calling alDeleteSources.");
			mSourceId = 0;
		}
	}
	void OpenALAudioObject::pause()
	{
		if (mSourceId)
		{
			alSourcePause(mSourceId);
			alErrorHandler("OpenALAudioObject::pause", "Error occured calling alSourcePause.");

		}
	}
	void OpenALStream::preload()
	{
 		for (s32 i = 0; i < mNUM_BUFFER; ++i)
		{
			mAudioFile->read(mBufferIds[i]);
		}

		alSourceQueueBuffers(mSourceId, mNUM_BUFFER, mBufferIds.get());
		alErrorHandler("OpenALStream::preload", "Error occured calling alSourceQueueBuffers.");
    }
	void OpenALStream::nextStreamStep()
	{
		if (mFinished)
			return;

		ALint processedBuffers = 0;
		ALuint tempBufferId;

		// Get the numbers of buffers that are already processed.
		alGetSourcei(mSourceId, AL_BUFFERS_PROCESSED, &processedBuffers);
		alErrorHandler("OpenALStream::nextStreamStep", "Error occured calling alGetSourcei.");


		// If all buffers are processed the stream is finished.
		if (processedBuffers >= mNUM_BUFFER)
		{
			dbglog << "Stream '"+mAudioFile->toString()+"' finished.";
			alSourceUnqueueBuffers(mSourceId, mNUM_BUFFER, mBufferIds.get());
			alErrorHandler("OpenALStream::nextStreamStep", "Error occured calling alSourceUnqueueBuffers.");

			// Calling callback.
			mOnStreamFinished();
			mFinished = true;
			
			return;
		}

		// Filling the processed buffers with fresh audio data.
		while (processedBuffers > 0)
		{
			alSourceUnqueueBuffers(mSourceId, 1, &tempBufferId);
			alErrorHandler("OpenALStream::nextStreamStep", "Error occured calling alSourceUnqueueBuffers.");

			mAudioFile->read(tempBufferId);
			
			alSourceQueueBuffers(mSourceId, 1, &tempBufferId);
			alErrorHandler("OpenALStream::nextStreamStep", "Error occured calling alSourceQueueBuffers.");
			
			alGetSourcei(mSourceId, AL_BUFFERS_PROCESSED, &processedBuffers);
			alErrorHandler("OpenALStream::nextStreamStep", "Error occured calling alGetSourcei.");
		}
	}
	void OpenALAudioObject::careOfSource()
	{
		if (!mSourceId)
		{
			alGenSources(1, &mSourceId);
			alErrorHandler("OpenALAudioObject::careOfSource", "Error occured calling alGenSources.");
			
			if (!alIsSource(mSourceId))
				throw std::logic_error("Not a valid source ID at OpenALAudioObject::careOfSource().");
		}
	}
	OpenALStream::OpenALStream(boost::shared_ptr<AudioFile> file,
		                       boost::function<void (void)> onStreamFinished,
	                           ALuint sourceId):
		Stream(file, onStreamFinished),
		mNUM_BUFFER(6),
		mSourceId(sourceId),
		mFinished(false)
    {
		mBufferIds.reset(new ALuint[mNUM_BUFFER]);
		alGenBuffers(mNUM_BUFFER, mBufferIds.get());
		alErrorHandler("OpenALStream::OpenALStream", "Error occured calling alGenBuffers.");
	
		preload();
    }
	OpenALStream::~OpenALStream()
	{
		alDeleteBuffers(mNUM_BUFFER, mBufferIds.get());
		alErrorHandler("OpenALStream::~OpenALStream", "Error occured calling alDeleteBuffers.");
	}