public void Dispose() { var state = AL.GetSourceState(alSourceId); if (state == ALSourceState.Playing || state == ALSourceState.Paused) { StopPlayback(); } lock (prepareMutex) { OggStreamer.Instance.RemoveStream(this); if (state != ALSourceState.Initial) { Empty(); } Close(); underlyingStream.Dispose(); } AL.DeleteSource(alSourceId); AL.DeleteBuffers(alBufferIds); ALHelper.Check(); #if TRACE ALHelper.TraceMemoryUsage(LogHandler); #endif }
public void Play() { var state = AL.GetSourceState(alSourceId); switch (state) { case ALSourceState.Playing: return; case ALSourceState.Paused: Resume(); return; } Prepare(); #if TRACE LogHandler("{", logX++, logY); #endif AL.SourcePlay(alSourceId); ALHelper.Check(); Preparing = false; OggStreamer.Instance.AddStream(this); }
public void Resume() { if (AL.GetSourceState(alSourceId) != ALSourceState.Paused) { return; } OggStreamer.Instance.AddStream(this); #if TRACE LogHandler("[", logX++, logY); #endif AL.SourcePlay(alSourceId); ALHelper.Check(); }
public void Pause() { if (AL.GetSourceState(alSourceId) != ALSourceState.Playing) { return; } OggStreamer.Instance.RemoveStream(this); #if TRACE LogHandler("]", logX++, logY); #endif AL.SourcePause(alSourceId); ALHelper.Check(); }
internal void Open(bool precache = false) { underlyingStream.Seek(0, SeekOrigin.Begin); Reader = new VorbisReader(underlyingStream, false); if (precache) { // Fill first buffer synchronously OggStreamer.Instance.FillBuffer(this, alBufferIds[0]); AL.SourceQueueBuffer(alSourceId, alBufferIds[0]); ALHelper.Check(); // Schedule the others asynchronously OggStreamer.Instance.AddStream(this); } Ready = true; }
public bool FillBuffer(OggStream stream, int bufferId) { int readSamples; lock (readMutex) { readSamples = stream.Reader.ReadSamples(readSampleBuffer, 0, BufferSize); CastBuffer(readSampleBuffer, castBuffer, readSamples); } AL.BufferData(bufferId, stream.Reader.Channels == 1 ? ALFormat.Mono16 : ALFormat.Stereo16, castBuffer, readSamples * sizeof(short), stream.Reader.SampleRate); ALHelper.Check(); #if TRACE stream.LogHandler(readSamples == BufferSize ? "." : "|", stream.logX++, stream.logY); ALHelper.TraceMemoryUsage(stream.LogHandler); #endif return(readSamples != BufferSize); }
void Empty() { int queued; AL.GetSource(alSourceId, ALGetSourcei.BuffersQueued, out queued); if (queued > 0) { try { AL.SourceUnqueueBuffers(alSourceId, queued); ALHelper.Check(); } catch (InvalidOperationException) { // This is a bug in the OpenAL implementation // Salvage what we can int processed; AL.GetSource(alSourceId, ALGetSourcei.BuffersProcessed, out processed); var salvaged = new int[processed]; if (processed > 0) { AL.SourceUnqueueBuffers(alSourceId, processed, salvaged); ALHelper.Check(); } // Try turning it off again? AL.SourceStop(alSourceId); ALHelper.Check(); Empty(); } } #if TRACE logX = 7; LogHandler(new string(Enumerable.Repeat(' ', 20).ToArray()), logX, logY); #endif }
void EnsureBuffersFilled() { while (!cancelled) { Thread.Sleep((int)(1000 / UpdateRate)); if (cancelled) { break; } threadLocalStreams.Clear(); lock (iterationMutex) threadLocalStreams.AddRange(streams); foreach (var stream in threadLocalStreams) { lock (stream.prepareMutex) { lock (iterationMutex) if (!streams.Contains(stream)) { continue; } bool finished = false; int queued; AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersQueued, out queued); ALHelper.Check(); int processed; AL.GetSource(stream.alSourceId, ALGetSourcei.BuffersProcessed, out processed); ALHelper.Check(); if (processed == 0 && queued == stream.BufferCount) { continue; } int[] tempBuffers; if (processed > 0) { tempBuffers = AL.SourceUnqueueBuffers(stream.alSourceId, processed); } else { tempBuffers = stream.alBufferIds.Skip(queued).ToArray(); } for (int i = 0; i < tempBuffers.Length; i++) { finished |= FillBuffer(stream, tempBuffers[i]); if (finished) { if (stream.IsLooped) { stream.Close(); stream.Open(); } else { streams.Remove(stream); i = tempBuffers.Length; } } } AL.SourceQueueBuffers(stream.alSourceId, tempBuffers.Length, tempBuffers); ALHelper.Check(); if (finished && !stream.IsLooped) { continue; } } lock (stream.stopMutex) { if (stream.Preparing) { continue; } lock (iterationMutex) if (!streams.Contains(stream)) { continue; } var state = AL.GetSourceState(stream.alSourceId); if (state == ALSourceState.Stopped) { #if TRACE stream.LogHandler("!", stream.logX++, stream.logY); #endif AL.SourcePlay(stream.alSourceId); ALHelper.Check(); } } } } }
void StopPlayback() { AL.SourceStop(alSourceId); ALHelper.Check(); }