public StreamTask(DiscordClient client, StreamRequest streamRequest, Stream bufferingStream) { this.streamRequest = streamRequest; this.bufferingStream = bufferingStream; this.client = client; State = StreamTaskState.Queued; }
public void CancelStreaming() { if (State != StreamTaskState.Queued && State != StreamTaskState.Playing) { return; } tokenSource?.Cancel(false); audioTask?.Wait(); State = StreamTaskState.Completed; }
public void StartStreaming() { if (State != StreamTaskState.Queued) { return; } State = StreamTaskState.Playing; tokenSource = new CancellationTokenSource(); audioTask = Task.Run(StreamFunc, tokenSource.Token); }
async Task StreamFunc() { CancellationToken cancellationToken = tokenSource.Token; IAudioClient voiceClient = null; TranscodingTask streamer = null; try { uint byteCounter = 0; // Download and read audio from the url streamer = new TranscodingTask(streamRequest, bufferingStream); streamer.Start(); // Wait until we have at least a few kb transcoded or network stream done while (true) { if (streamRequest.NetworkDone) { await Task.Delay(600); break; } if (streamer.ReadyBytesLeft > 5 * 1024) { break; } await Task.Delay(200); } if (cancellationToken.IsCancellationRequested) { return; } // Start streaming to voice await streamRequest.Channel.SendMessage($"Playing **{streamRequest.Title}** [{streamRequest.Length}]"); var audioService = client.Audio(); voiceClient = await audioService.Join(streamRequest.VoiceChannel); int blockSize = 1920 * audioService.Config.Channels; byte[] voiceBuffer = new byte[blockSize]; var ringBuffer = streamer.PCMOutput; Stopwatch timeout = Stopwatch.StartNew(); while (true) { var readCount = ringBuffer.Read(voiceBuffer, 0, voiceBuffer.Length); if (readCount == 0) { if (timeout.ElapsedMilliseconds > 1500) { Console.WriteLine("Audio stream timed out. Disconnecting."); break; } await Task.Delay(200); continue; } if (cancellationToken.IsCancellationRequested) { return; } timeout.Restart(); byteCounter += (uint)voiceBuffer.Length; voiceClient.Send(voiceBuffer, 0, voiceBuffer.Length); } streamer.Cancel(); voiceClient.Wait(); } catch (Exception ex) { await streamRequest.Channel.SendMessage($":musical_note: {streamRequest.User.Mention} Something went wrong, please report this. :angry: :anger:"); Console.WriteLine("Exception while playing music: " + ex); } finally { if (voiceClient != null) { await streamRequest.Channel.SendMessage($"Finished playing **{streamRequest.Title}**"); State = StreamTaskState.Completed; streamer?.Cancel(); await voiceClient.Disconnect(); await Task.Delay(500); } } }