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); if (ALHelper.Efx.IsInitialized) { ALHelper.Efx.DeleteFilter(alFilterId); } ALHelper.Check(); Logger.Log(LogEventSingle.MemoryUsage, () => GC.GetTotalMemory(true)); }
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(); } } Logger.Log(LogEvent.Empty, this); }
public void Resume() { if (AL.GetSourceState(alSourceId) != ALSourceState.Paused) { return; } OggStreamer.Instance.AddStream(this); Logger.Log(LogEvent.Resume, this); AL.SourcePlay(alSourceId); ALHelper.Check(); }
public void Pause() { if (AL.GetSourceState(alSourceId) != ALSourceState.Playing) { return; } OggStreamer.Instance.RemoveStream(this); Logger.Log(LogEvent.Pause, this); AL.SourcePause(alSourceId); ALHelper.Check(); }
public void Play() { var state = AL.GetSourceState(alSourceId); switch (state) { case ALSourceState.Playing: return; case ALSourceState.Paused: Resume(); return; } Prepare(); Logger.Log(LogEvent.Play, this); AL.SourcePlay(alSourceId); ALHelper.Check(); Preparing = false; OggStreamer.Instance.AddStream(this); }
void StopPlayback() { AL.SourceStop(alSourceId); ALHelper.Check(); }
public void EnsureBuffersFilled() { do { 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(); } int bufIdx = 0; for (; bufIdx < tempBuffers.Length; bufIdx++) { finished |= FillBuffer(stream, tempBuffers[bufIdx]); if (finished) { if (stream.IsLooped) { stream.Reader.DecodedTime = TimeSpan.Zero; if (bufIdx == 0) { // we didn't have any buffers left over, so let's start from the beginning on the next cycle... continue; } } else { lock (stream.stopMutex) { stream.NotifyFinished(); } streams.Remove(stream); break; } } } AL.SourceQueueBuffers(stream.alSourceId, bufIdx, 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) { Logger.Log(LogEvent.BufferUnderrun, stream); AL.SourcePlay(stream.alSourceId); ALHelper.Check(); } } } if (UpdateRate > 0) { Thread.Sleep((int)(1000 / UpdateRate)); } }while (underlyingThread != null && !cancelled); }