diff options
author | TrueDoctor <d-kobert@web.de> | 2018-04-11 14:19:57 +0200 |
---|---|---|
committer | TrueDoctor <d-kobert@web.de> | 2018-04-11 14:19:57 +0200 |
commit | 351067a5203307fc0c1a14ae2be84eae71246af9 (patch) | |
tree | a17b63d94b41c87215a03fd2a19edab9f4d53c30 /DiscoBot/Audio | |
parent | aa236f67bf1829e2a7c6e9a5f82d109b39147b11 (diff) |
Added possibillity for service based soundplaying
Diffstat (limited to 'DiscoBot/Audio')
-rw-r--r-- | DiscoBot/Audio/AudioModule.cs | 72 | ||||
-rw-r--r-- | DiscoBot/Audio/AudioService.cs | 101 |
2 files changed, 173 insertions, 0 deletions
diff --git a/DiscoBot/Audio/AudioModule.cs b/DiscoBot/Audio/AudioModule.cs new file mode 100644 index 0000000..0c3814f --- /dev/null +++ b/DiscoBot/Audio/AudioModule.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Threading.Tasks; + +using DiscoBot; +using DiscoBot.Audio; +using DiscoBot.Auxiliary; +using DiscoBot.Commands; + +using Discord; +using Discord.Commands; + +public class AudioModule : ModuleBase +{ + // Scroll down further for the AudioService. + // Like, way down + private readonly AudioService _service; + + // Remember to add an instance of the AudioService + // to your IServiceCollection when you initialize your bot + public AudioModule(AudioService service) + { + _service = service; + Dsa.Service = service; + } + + // You *MUST* mark these commands with 'RunMode.Async' + // otherwise the bot will not respond until the Task times out. + [Command("_join", RunMode = RunMode.Async)] + public async Task JoinCmd() + { + await _service.JoinAudio(Context.Guild, (Context.User as IVoiceState).VoiceChannel); + } + + // Remember to add preconditions to your commands, + // this is merely the minimal amount necessary. + // Adding more commands of your own is also encouraged. + [Command("_leave", RunMode = RunMode.Async)] + public async Task LeaveCmd() + { + await _service.LeaveAudio(Context.Guild); + } + + [Command("_play", RunMode = RunMode.Async)] + public async Task PlayCmd([Remainder] string song) + { + if (Dsa.GeneralContext == null) + { + Dsa.GeneralContext = this.Context; + } + + var sounds = Enum.GetValues(typeof(Sound)); + var soundList = new List<Sound>(); + foreach (var sound in sounds) + { + soundList.Add((Sound)sound); + } + + var sc = new SpellCorrect(); + + var tSound = soundList.OrderBy(x => sc.Compare(song, x.ToString())).First(); + + if (sc.Compare(song, tSound.ToString()) > SpellCorrect.ErrorThreshold) + { + await _service.SendAudioAsync(Context.Guild, Context.Channel, song); + } + + await SoundEffects.Play(tSound); + } +}
\ No newline at end of file diff --git a/DiscoBot/Audio/AudioService.cs b/DiscoBot/Audio/AudioService.cs new file mode 100644 index 0000000..25beed0 --- /dev/null +++ b/DiscoBot/Audio/AudioService.cs @@ -0,0 +1,101 @@ +namespace DiscoBot.Audio +{ + using System.Collections.Concurrent; + using System.Diagnostics; + using System.IO; + using System.Threading.Tasks; + + using Discord; + using Discord.Audio; + + public class AudioService + { + private readonly ConcurrentDictionary<ulong, IAudioClient> connectedChannels = new ConcurrentDictionary<ulong, IAudioClient>(); + + public async Task JoinAudio(IGuild guild, IVoiceChannel target) + { + IAudioClient client; + if (this.connectedChannels.TryGetValue(guild.Id, out client)) + { + return; + } + + if (target.Guild.Id != guild.Id) + { + return; + } + + var audioClient = await target.ConnectAsync(); + + if (this.connectedChannels.TryAdd(guild.Id, audioClient)) + { + // If you add a method to log happenings from this service, + // you can uncomment these commented lines to make use of that. + //await Log(LogSeverity.Info, $"Connected to voice on {guild.Name}."); + } + } + + public async Task LeaveAudio(IGuild guild) + { + IAudioClient client; + if (this.connectedChannels.TryRemove(guild.Id, out client)) + { + await client.StopAsync(); + //await Log(LogSeverity.Info, $"Disconnected from voice on {guild.Name}."); + } + } + + public async Task SendAudioAsync(IGuild guild, IMessageChannel channel, string path) + { + // Your task: Get a full path to the file if the value of 'path' is only a filename. + if (!File.Exists(path) && false) + { + await channel.SendMessageAsync("File does not exist."); + return; + } + IAudioClient client; + if (this.connectedChannels.TryGetValue(guild.Id, out client)) + { + //await Log(LogSeverity.Debug, $"Starting playback of {path} in {guild.Name}"); + using (var ffmpeg = this.CreateStream(path)) + using (var stream = client.CreatePCMStream(AudioApplication.Music)) + { + try { await ffmpeg.StandardOutput.BaseStream.CopyToAsync(stream); } + finally { await stream.FlushAsync(); } + } + } + } + + public async Task SendAudioAsync(string path, int Volume) + { + // Your task: Get a full path to the file if the value of 'path' is only a filename. + if (!File.Exists(path) && false) + { + //await channel.SendMessageAsync("File does not exist."); + return; + } + + if (this.connectedChannels.TryGetValue(Dsa.GeneralContext.Guild.Id, out var client)) + { + //await Log(LogSeverity.Debug, $"Starting playback of {path} in {guild.Name}"); + using (var ffmpeg = this.CreateStream(path)) + using (var stream = client.CreatePCMStream(AudioApplication.Voice)) + { + try { await ffmpeg.StandardOutput.BaseStream.CopyToAsync(stream); } + finally { await stream.FlushAsync(); } + } + } + } + + private Process CreateStream(string path) + { + return Process.Start(new ProcessStartInfo + { + FileName = "ffmpeg.exe", + Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1", + UseShellExecute = false, + RedirectStandardOutput = true + }); + } + } +} |