コード例 #1
0
        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
            }
        }
コード例 #2
0
        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);
        }
コード例 #3
0
        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);
        }
コード例 #4
0
        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);
        }
コード例 #5
0
        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);
        }
コード例 #6
0
        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);
        }
コード例 #7
0
        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);
        }