public async Task AdvanceQueue(ulong guildId) { DeleteCancelToken(guildId); if (Queue.Count(guildId) > 0) { VoiceConnection voiceConn = ServerVoiceConnections.GetValue(guildId); AudioInfo nextAudioInfo = Queue.Pop(guildId); if (nextAudioInfo.AudioStream != null) { var outStream = voiceConn.AudioStream; await(nextAudioInfo.AudioStream).CopyToAsync(outStream, 81920, voiceConn.CancelToken.Token).ContinueWith(task => { if (!task.IsCanceled && task.IsFaulted) { Console.WriteLine(task.Exception); } }); await outStream.FlushAsync(); } else #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed { Task.Run(async() => await PlayUrl(nextAudioInfo.DownloadUrl, guildId)); } #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } }
private void DeleteCancelToken(ulong guildId) { if (!IsInVoiceChannel(guildId)) { return; } VoiceConnection voiceConn = ServerVoiceConnections.GetValue(guildId); if (voiceConn.CancelToken != null && !voiceConn.CancelToken.IsCancellationRequested) { voiceConn.CancelToken.Cancel(); voiceConn.CancelToken.Dispose(); voiceConn.CancelToken = null; } ServerVoiceConnections.TryUpdate(guildId, voiceConn); }
public async Task <bool> LeaveVoice(ulong guildId) { if (!IsInVoiceChannel(guildId)) { return(false); } AudioQueue.Clear(guildId); DeleteCancelToken(guildId); VoiceConnection voiceConn = ServerVoiceConnections.GetValue(guildId); ServerVoiceConnections.TryRemove(guildId, out _); await voiceConn.AudioClient.StopAsync(); voiceConn.AudioStream.Dispose(); return(true); }
public async Task <bool> Record(SocketGuildUser guildUser, ulong guildId, int seconds) { if (!IsInVoiceChannel(guildId)) { return(false); } if (!InStreamExists(guildUser.Id)) { return(false); } CancellationTokenSource cancelSource = new CancellationTokenSource(); VoiceConnection voiceConn = ServerVoiceConnections.GetValue(guildId); ConsoleEx.WriteColoredLine(LogSeverity.Info, ConsoleTextFormat.TimeAndText, $"Recording User: {guildUser.Username}"); MemoryStream byteStream = new MemoryStream(await BufferIncomingStream(GetInStream(guildUser.Id), seconds)); if (IsAudioStreaming(guildId)) { ConsoleEx.WriteColoredLine(LogSeverity.Info, ConsoleTextFormat.TimeAndText, $"Recording Queued: Length = {byteStream.Length.ToString()}"); AudioQueue.Push(guildId, new AudioInfo(AudioSource.Recording, $"{seconds.ToString().Bold()} Recording of {guildUser.Username.Bold()}", "", byteStream)); return(false); } voiceConn.CancelToken = cancelSource; ServerVoiceConnections.TryUpdate(guildId, voiceConn); ConsoleEx.WriteColoredLine(LogSeverity.Info, ConsoleTextFormat.TimeAndText, $"Recording Playing: Length = {byteStream.Length.ToString()}"); await byteStream.CopyToAsync(voiceConn.AudioStream, 81920, voiceConn.CancelToken.Token).ContinueWith(task => { if (!task.IsCanceled && task.IsFaulted) { Console.WriteLine(task.Exception); } }); await AdvanceQueue(guildId); await voiceConn.AudioStream.FlushAsync(); return(true); }
public bool StopAudio(ulong guildId) { if (!IsInVoiceChannel(guildId)) { return(false); } if (!IsAudioStreaming(guildId)) { return(false); } VoiceConnection voiceConn = ServerVoiceConnections.GetValue(guildId); AudioQueue.Clear(guildId); DeleteCancelToken(guildId); return(true); }
public async Task <bool> JoinVoice(ulong guildId, IVoiceChannel voiceChannel) { if (IsInVoiceChannel(guildId)) { AudioQueue.Clear(guildId); DeleteCancelToken(guildId); VoiceConnection voiceConn = ServerVoiceConnections.GetValue(guildId); ServerVoiceConnections.TryRemove(guildId, out _); await voiceConn.AudioClient.StopAsync(); voiceConn.AudioClient.Dispose(); } IAudioClient audioClient = await voiceChannel.ConnectAsync(); ServerVoiceConnections.TryAdd(guildId, new VoiceConnection(voiceChannel, audioClient)); audioClient.StreamCreated += async(id, stream) => { SocketGuildUser user = Provider.GetService <DiscordSocketClient>().GetGuild(guildId).GetUser(id); AddInStream(id, stream); ConsoleEx.WriteColoredLine(LogSeverity.Verbose, ConsoleTextFormat.TimeAndText, $"AudioStream created for {user.Username}."); await Task.CompletedTask; }; audioClient.StreamDestroyed += async(id) => { SocketGuildUser user = Provider.GetService <DiscordSocketClient>().GetGuild(guildId).GetUser(id); RemoveInStream(id); ConsoleEx.WriteColoredLine(LogSeverity.Verbose, ConsoleTextFormat.TimeAndText, $"AudioStream destroyed for {user.Username}."); await Task.CompletedTask; }; foreach (SocketGuildUser user in Provider.GetService <DiscordSocketClient>().GetGuild(guildId).Users) { if (user.VoiceChannel != null && !InStreamExists(user.Id) && user.AudioStream != null) { AddInStream(user.Id, user.AudioStream); ConsoleEx.WriteColoredLine(LogSeverity.Verbose, ConsoleTextFormat.TimeAndText, $"Added {user.Username}'s AudioStream."); } } return(true); }
public async Task <bool> PlayUrl(string url, ulong guildId) { if (!IsInVoiceChannel(guildId)) { return(false); } StaticMethods.FireAndForget(async() => { CancellationTokenSource cancelSource = new CancellationTokenSource(); VoiceConnection voiceConn = ServerVoiceConnections.GetValue(guildId); var stream = voiceConn.AudioStream; var process = Process.Start(new ProcessStartInfo { FileName = "ffmpeg", Arguments = $"-i \"{url}\" -f s16le -ar 48000 -ac 2 pipe:1 -loglevel quiet -reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 2", UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }); voiceConn.CancelToken = cancelSource; ServerVoiceConnections.TryUpdate(guildId, voiceConn); await process.StandardOutput.BaseStream.CopyToAsync(stream, 81920, cancelSource.Token).ContinueWith(task => { if (!task.IsCanceled && task.IsFaulted) { Console.WriteLine(task.Exception); } }); process.WaitForExit(); await AdvanceQueue(guildId); await stream.FlushAsync(); process.Dispose(); }); return(true); }