Beispiel #1
0
        public async Task <bool> JoinAudioAsync(IVoiceChannel voiceChannel)
        {
            bool joinedAudio = false;

            var currentUser = await voiceChannel.Guild.GetCurrentUserAsync();

            if (!audioInstances.TryGetValue(voiceChannel.GuildId, out AudioInstance audioInstance) || currentUser.VoiceChannel == null)
            {
                audioInstance = new AudioInstance
                {
                    GuildId     = voiceChannel.GuildId,
                    AudioClient = await voiceChannel.ConnectAsync().ConfigureAwait(false)
                };

                audioInstances[voiceChannel.GuildId] = audioInstance;
                audioInstance.Stream = audioInstance.AudioClient.CreatePCMStream(Discord.Audio.AudioApplication.Voice, null, 250);

                joinedAudio = true;
            }
            else
            {
                Log.Information($"{{Indicator}} Already in a voice channel for {voiceChannel.GuildId}", "[audio]");
            }

            if (audioInstance.AudioClient.ConnectionState == ConnectionState.Connected && audioInstance.Stream.CanWrite)
            {
                await this.SendAudioAsync(audioInstance, PhrasesConfig.Instance.GetVoiceFileNames(VoicePhraseType.BotJoin).Random());
            }
            else
            {
                audioInstance.AudioClient.Connected += async() =>
                {
                    await this.SendAudioAsync(audioInstance, PhrasesConfig.Instance.GetVoiceFileNames(VoicePhraseType.BotJoin).Random());
                };
                audioInstance.AudioClient.Disconnected += (Exception ex) =>
                {
                    Log.Error(ex, "{{Indicator}} Disconnected from audio", "[audio]");
                    return(Task.CompletedTask);
                };
            }

            return(joinedAudio);
        }
Beispiel #2
0
        public async Task JoinAudioAsync(IVoiceChannel voiceChannel)
        {
            var currentUser = await voiceChannel.Guild.GetCurrentUserAsync();

            if (!audioInstances.TryGetValue(voiceChannel.GuildId, out AudioInstance audioInstance) || currentUser.VoiceChannel == null)
            {
                audioInstance = new AudioInstance
                {
                    GuildId     = voiceChannel.GuildId,
                    AudioClient = await voiceChannel.ConnectAsync().ConfigureAwait(false)
                };

                audioInstances[voiceChannel.GuildId] = audioInstance;
                audioInstance.Stream = audioInstance.AudioClient.CreatePCMStream(Discord.Audio.AudioApplication.Voice, null, 250);
            }
            else
            {
                Console.WriteLine($"Already in a voice channel for {voiceChannel.GuildId}");
            }

            if (audioInstance.AudioClient.ConnectionState == ConnectionState.Connected && audioInstance.Stream.CanWrite)
            {
                await this.SendAudioAsync(audioInstance, PhrasesConfig.Instance.GetVoiceFileNames(VoicePhraseType.BotJoin).Random());
            }
            else
            {
                audioInstance.AudioClient.Connected += async() =>
                {
                    await this.SendAudioAsync(audioInstance, PhrasesConfig.Instance.GetVoiceFileNames(VoicePhraseType.BotJoin).Random());
                };
                audioInstance.AudioClient.Disconnected += async(Exception ex) =>
                {
                    await this.LeaveAudioAsync(voiceChannel.GuildId);

                    Console.WriteLine(ex);
                };
            }
        }
Beispiel #3
0
        private async Task SendAudioAsyncInternalAsync(AudioInstance audioInstance, string filePath)
        {
            var filename = Path.GetFileName(filePath);

            Process p = null;

            if (!audioBytes.ContainsKey(filename))
            {
                Console.WriteLine($"[audio] [{filename}] reading data");
                p = Process.Start(new ProcessStartInfo
                {
                    FileName               = "c:\\audio\\ffmpeg",
                    Arguments              = $"-i {filePath} -f s16le -ar 48000 -ac 2 pipe:1 -loglevel error",
                    UseShellExecute        = false,
                    RedirectStandardOutput = true,
                    RedirectStandardInput  = true,
                });
            }
            else
            {
                Console.WriteLine($"[audio] [{filename}] using cached bytes");
            }

            await audioInstance.streamLock.WaitAsync();

            Console.WriteLine($"[audio] [{filename}] lock obtained");

            try
            {
                if (audioInstance.Stream != null)
                {
                    Console.WriteLine($"[audio] [{filename}] stream copy");

                    if (p != null)
                    {
                        using (var memoryStream = new MemoryStream())
                        {
                            await p.StandardOutput.BaseStream.CopyToAsync(memoryStream);

                            byte[] data;
                            using (var binaryReader = new BinaryReader(memoryStream))
                            {
                                binaryReader.BaseStream.Position = 0;
                                data = binaryReader.ReadBytes((int)memoryStream.Length);
                            }

                            if (!audioBytes.ContainsKey(filename))
                            {
                                audioBytes[filename] = AdjustVolume(data, .8f);
                            }
                        }
                    }

                    using (var memoryStream = new MemoryStream(audioBytes[filename]))
                    {
                        await memoryStream.CopyToAsync(audioInstance.Stream);
                    }

                    p?.WaitForExit(8000);
                    var flushTask   = audioInstance.Stream.FlushAsync();
                    var timeoutTask = Task.Delay(8000);

                    if (await Task.WhenAny(flushTask, timeoutTask) == timeoutTask)
                    {
                        Console.WriteLine($"[audio] [{filename}] timeout occurred");
                        throw new TimeoutException();
                    }
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                p?.Dispose();
            }
            finally
            {
                if (audioInstance != null && !audioInstance.isDisposed)
                {
                    audioInstance?.streamLock?.Release();
                }
            }
        }
Beispiel #4
0
 public async Task SendAudioAsync(AudioInstance audioInstance, string filename)
 {
     await this.SendAudioAsyncInternalAsync(audioInstance, filename);
 }