private async Task CheckPrebufferingAsync(SongBuffer inStream, CancellationToken cancelToken, long size) { while (!inStream.BufferingCompleted && inStream.Length < size) { await Task.Delay(100, cancelToken); } _log.Debug("Buffering successfull"); }
public async Task Play(IAudioClient voiceClient, CancellationToken cancelToken) { var filename = Path.Combine(Music.MusicDataPath, DateTime.Now.UnixTimestamp().ToString()); SongBuffer inStream = new SongBuffer(MusicPlayer, filename, SongInfo, skipTo, frameBytes * 100); var bufferTask = inStream.BufferSong(cancelToken).ConfigureAwait(false); bytesSent = 0; try { var attempt = 0; var prebufferingTask = CheckPrebufferingAsync(inStream, cancelToken, 1.MiB()); //Fast connection can do this easy var finished = false; var count = 0; var sw = new Stopwatch(); var slowconnection = false; sw.Start(); while (!finished) { var t = await Task.WhenAny(prebufferingTask, Task.Delay(2000, cancelToken)); if (t != prebufferingTask) { count++; if (count == 10) { slowconnection = true; prebufferingTask = CheckPrebufferingAsync(inStream, cancelToken, 20.MiB()); _log.Warn("Slow connection buffering more to ensure no disruption, consider hosting in cloud"); continue; } if (inStream.BufferingCompleted && count == 1) { _log.Debug("Prebuffering canceled. Cannot get any data from the stream."); return; } else { continue; } } else if (prebufferingTask.IsCanceled) { _log.Debug("Prebuffering canceled. Cannot get any data from the stream."); return; } finished = true; } sw.Stop(); _log.Debug("Prebuffering successfully completed in " + sw.Elapsed); var outStream = voiceClient.CreatePCMStream(960); int nextTime = Environment.TickCount + milliseconds; byte[] buffer = new byte[frameBytes]; while (!cancelToken.IsCancellationRequested) { //Console.WriteLine($"Read: {songBuffer.ReadPosition}\nWrite: {songBuffer.WritePosition}\nContentLength:{songBuffer.ContentLength}\n---------"); var read = await inStream.ReadAsync(buffer, 0, buffer.Length).ConfigureAwait(false); //await inStream.CopyToAsync(voiceClient.OutputStream); if (read < frameBytes) { _log.Debug("read {0}", read); } unchecked { bytesSent += (ulong)read; } if (read < frameBytes) { if (read == 0) { if (inStream.BufferingCompleted) { break; } if (attempt++ == 20) { MusicPlayer.SongCancelSource.Cancel(); break; } if (slowconnection) { _log.Warn("Slow connection has disrupted music, waiting a bit for buffer"); await Task.Delay(1000, cancelToken).ConfigureAwait(false); } else { await Task.Delay(100, cancelToken).ConfigureAwait(false); } } else { attempt = 0; } } else { attempt = 0; } while (this.MusicPlayer.Paused) { await Task.Delay(200, cancelToken).ConfigureAwait(false); } buffer = AdjustVolume(buffer, MusicPlayer.Volume); if (read != frameBytes) { continue; } nextTime = unchecked (nextTime + milliseconds); int delayMillis = unchecked (nextTime - Environment.TickCount); if (delayMillis > 0) { await Task.Delay(delayMillis, cancelToken).ConfigureAwait(false); } await outStream.WriteAsync(buffer, 0, read).ConfigureAwait(false); } } finally { await bufferTask; if (inStream != null) { inStream.Dispose(); } } }