diff --git a/BUILDS/net6.0/MusicCommands.deps.json b/BUILDS/net6.0/Music Commands.deps.json similarity index 99% rename from BUILDS/net6.0/MusicCommands.deps.json rename to BUILDS/net6.0/Music Commands.deps.json index 1c91428..2834772 100644 --- a/BUILDS/net6.0/MusicCommands.deps.json +++ b/BUILDS/net6.0/Music Commands.deps.json @@ -6,13 +6,13 @@ "compilationOptions": {}, "targets": { ".NETCoreApp,Version=v6.0": { - "MusicCommands/1.0.0": { + "Music Commands/1.0.0": { "dependencies": { "PluginManager": "1.0.0", "YoutubeExplode": "6.2.0" }, "runtime": { - "MusicCommands.dll": {} + "Music Commands.dll": {} } }, "AngleSharp/0.17.0": { @@ -187,7 +187,7 @@ } }, "libraries": { - "MusicCommands/1.0.0": { + "Music Commands/1.0.0": { "type": "project", "serviceable": false, "sha512": "" diff --git a/BUILDS/net6.0/Music Commands.dll b/BUILDS/net6.0/Music Commands.dll new file mode 100644 index 0000000..dc82fef Binary files /dev/null and b/BUILDS/net6.0/Music Commands.dll differ diff --git a/BUILDS/net6.0/MusicCommands.dll b/BUILDS/net6.0/MusicCommands.dll deleted file mode 100644 index 2349924..0000000 Binary files a/BUILDS/net6.0/MusicCommands.dll and /dev/null differ diff --git a/EVE_LevelingSystem/EVE_LevelingSystem.csproj b/EVE_LevelingSystem/EVE_LevelingSystem.csproj index b8dd406..cf07d6d 100644 --- a/EVE_LevelingSystem/EVE_LevelingSystem.csproj +++ b/EVE_LevelingSystem/EVE_LevelingSystem.csproj @@ -4,7 +4,7 @@ net6.0 enable enable - bin\ + diff --git a/MusicCommands/AudioFile.cs b/MusicCommands/AudioFile.cs new file mode 100644 index 0000000..76daa24 --- /dev/null +++ b/MusicCommands/AudioFile.cs @@ -0,0 +1,34 @@ +using AngleSharp.Dom; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MusicCommands +{ + internal class AudioFile + { + internal string Name { get; set; } + internal string Url { get; set; } + + internal AudioFile(string name, string url) + { + Name = name; + Url = url; + } + + internal async Task DownloadAudioFile() + { + Process proc = new Process(); + proc.StartInfo.FileName = "MusicDownloader.exe"; + proc.StartInfo.Arguments = $"{Url},{Name}"; + proc.StartInfo.UseShellExecute = false; + proc.StartInfo.RedirectStandardOutput = true; + + proc.Start(); + await proc.WaitForExitAsync(); + } + } +} diff --git a/MusicCommands/Data.cs b/MusicCommands/Data.cs index 066af23..ac61ac7 100644 --- a/MusicCommands/Data.cs +++ b/MusicCommands/Data.cs @@ -8,5 +8,6 @@ internal static class Data internal static IAudioClient audioClient = null; internal static IVoiceChannel voiceChannel = null; - internal static MusicPlayer CurrentlyRunning = null; + internal static MusicPlayer MusicPlayer = null; + internal static MusicPlaylist Playlist = new(); } diff --git a/MusicCommands/Leave.cs b/MusicCommands/Leave.cs index 3171489..98af079 100644 --- a/MusicCommands/Leave.cs +++ b/MusicCommands/Leave.cs @@ -22,8 +22,8 @@ internal class Leave : DBCommand { if (Data.audioClient is not null && Data.voiceChannel is not null) { - Data.CurrentlyRunning.Stop(); - Data.CurrentlyRunning = null; + Data.Playlist.ClearQueue(); + Data.MusicPlayer.isPlaying = false; await Data.audioClient.StopAsync(); await Data.voiceChannel.DisconnectAsync(); } diff --git a/MusicCommands/MusicCommands.csproj b/MusicCommands/MusicCommands.csproj index 7ebcc0e..037f43c 100644 --- a/MusicCommands/MusicCommands.csproj +++ b/MusicCommands/MusicCommands.csproj @@ -4,6 +4,7 @@ net6.0 warnings bin\ + Music Commands diff --git a/MusicCommands/MusicPlayer.cs b/MusicCommands/MusicPlayer.cs index 6d8e8f6..536f6d7 100644 --- a/MusicCommands/MusicPlayer.cs +++ b/MusicCommands/MusicPlayer.cs @@ -9,110 +9,93 @@ namespace MusicCommands; internal class MusicPlayer { - public MusicPlayer(Stream input, Stream output) + private Stream outputStream { get; } + + internal bool isPlaying, isPaused; + + public MusicPlayer(Stream outputChannel) { - inputStream = input; - outputStream = output; + outputStream = outputChannel; } - public MusicPlayer(Stream output) + public async Task Play(Stream source, int byteSize) { - inputStream = null; - outputStream = output; - } - - public Stream inputStream { get; } // from FFMPEG - public Stream outputStream { get; } // to Voice Channel - - public bool Paused { get; set; } - private bool _stop { get; set; } - - public void Stop() - { - _stop = true; - } - - public async Task StartSendAudioFromLink(string URL) - { - /* using (HttpClient client = new HttpClient()) - using (HttpResponseMessage response = await client.GetAsync(URL)) - using (var content = response.Content) - { - await (await content.ReadAsStreamAsync()).CopyToAsync(outputStream); - }*/ - - - Stream ms = new MemoryStream(); - var bsize = 512; - new Thread(async delegate(object o) - { - var response = await new HttpClient().GetAsync(URL); - using (var stream = await response.Content.ReadAsStreamAsync()) - { - var buffer = new byte[bsize]; - int read; - while ((read = stream.Read(buffer, 0, buffer.Length)) > 0) - { - var pos = ms.Position; - ms.Position = ms.Length; - ms.Write(buffer, 0, read); - ms.Position = pos; - } - } - } - ).Start(); - Console.Write("Reading data: "); - while (ms.Length < bsize * 10) + isPlaying = true; + while (isPlaying) { - await Task.Delay(1000); - Console.Title = "Reading data: " + ms.Length + " bytes read of " + bsize * 10; - Console.Write("."); - } + if (isPaused) + continue; - Console.WriteLine("\nDone"); - ms.Position = 0; - - _stop = false; - Paused = false; - - while (!_stop) - { - if (Paused) continue; - var buffer = new byte[bsize]; - var read = await ms.ReadAsync(buffer, 0, buffer.Length); - if (read > 0) - await outputStream.WriteAsync(buffer, 0, read); - else + var bits = new byte[byteSize]; + var read = await source.ReadAsync(bits, 0, byteSize); + if (read == 0) break; - } - } - - public async Task StartSendAudio() - { - Paused = false; - _stop = false; - while (!_stop) - { - if (Paused) continue; - var bsize = 512; - var buffer = new byte[bsize]; - var bcount = await inputStream.ReadAsync(buffer, 0, bsize); - if (bcount <= 0) - { - Stop(); - Data.CurrentlyRunning = null; - break; - } - try { - await outputStream.WriteAsync(buffer, 0, bcount); + await outputStream.WriteAsync(bits, 0, read); } - catch (Exception ex) + catch { - await outputStream.FlushAsync(); - Functions.WriteLogFile(ex.ToString()); + break; } } + + + await source.FlushAsync(); + await source.DisposeAsync(); + source.Close(); + await outputStream.FlushAsync(); + isPlaying = false; } + + + /* + public MusicPlayer(Stream input, Stream output) + { + inputStream = input; + outputStream = output; + } + + + + + + public Stream inputStream { get; } // from FFMPEG + public Stream outputStream { get; } // to Voice Channel + + public bool Paused { get; set; } + private bool _stop { get; set; } + + public void Stop() + { + _stop = true; + } + + public async Task StartSendAudio(int bsize) + { + Paused = false; + _stop = false; + while (!_stop) + { + if (Paused) continue; + var buffer = new byte[bsize]; + var bcount = await inputStream.ReadAsync(buffer, 0, bsize); + if (bcount <= 0) + { + Stop(); + Data.CurrentlyRunning = null; + break; + } + + try + { + await outputStream.WriteAsync(buffer, 0, bcount); + } + catch (Exception ex) + { + await outputStream.FlushAsync(); + Functions.WriteLogFile(ex.ToString()); + } + } + }*/ } diff --git a/MusicCommands/MusicPlaylist.cs b/MusicCommands/MusicPlaylist.cs new file mode 100644 index 0000000..f514fb1 --- /dev/null +++ b/MusicCommands/MusicPlaylist.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MusicCommands +{ + internal class MusicPlaylist + { + internal MusicPlaylist() + { + Console.WriteLine("Initialized playlist."); + } + + public Queue QueueList = new(); + + public void Enqueue(AudioFile query) => QueueList.Enqueue(query); + public void ClearQueue() => QueueList.Clear(); + + public int Count => QueueList.Count; + public AudioFile GetNextSong => QueueList.Dequeue(); + public AudioFile WhatIsNext => QueueList.Peek(); + } +} diff --git a/MusicCommands/Pause.cs b/MusicCommands/Pause.cs index 8a86430..5b16b37 100644 --- a/MusicCommands/Pause.cs +++ b/MusicCommands/Pause.cs @@ -8,7 +8,7 @@ internal class Pause : DBCommand { public string Command => "pause"; - public string Description => "Pause the music"; + public string Description => "Pause/Unpause the music that is currently running"; public string Usage => "pause"; @@ -20,6 +20,6 @@ internal class Pause : DBCommand public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) { - Data.CurrentlyRunning.Paused = true; + Data.MusicPlayer.isPaused = !Data.MusicPlayer.isPaused; } } diff --git a/MusicCommands/Play.cs b/MusicCommands/Play.cs index bf98e28..b1ab2ae 100644 --- a/MusicCommands/Play.cs +++ b/MusicCommands/Play.cs @@ -1,7 +1,6 @@ using System; using System.Diagnostics; using System.IO; -using System.Threading.Tasks; using Discord; using Discord.Audio; using Discord.Commands; @@ -42,28 +41,47 @@ internal class Play : DBCommand return; } - string url = splitted[1]; + var url = splitted[1]; path += $"{Functions.CreateMD5(url)}"; if (File.Exists(path)) - break; - //await context.Channel.SendMessageAsync("Searching for " + url); - await GetMusicAudio(url, path); - //await context.Channel.SendMessageAsync("Playing: " + url); + { + Data.Playlist.Enqueue(new AudioFile(path, null)); + } + else + { + var file = new AudioFile(path, url); + await file.DownloadAudioFile(); + Data.Playlist.Enqueue(file); + } } else { - string searchString = Functions.MergeStrings(splitted, 1); + var searchString = splitted.MergeStrings(1); path += $"{Functions.CreateMD5(searchString)}"; - if (File.Exists(path)) - break; - await context.Channel.SendMessageAsync("Searching for " + searchString); - await GetMusicAudio(searchString, path); - await context.Channel.SendMessageAsync("Playing: " + searchString); + { + Data.Playlist.Enqueue(new AudioFile(path, null)); + } + else + { + await context.Channel.SendMessageAsync("Searching for " + searchString); + var file = new AudioFile(path, searchString); + await file.DownloadAudioFile(); + Data.Playlist.Enqueue(file); + if (Data.MusicPlayer is null) + await context.Channel.SendMessageAsync("Playing: " + searchString); + } + } + + if (Data.MusicPlayer is not null) + { + await context.Channel.SendMessageAsync("Enqueued your request"); + return; } } while (false); + Data.voiceChannel = (context.User as IGuildUser)?.VoiceChannel; if (Data.voiceChannel == null) @@ -72,16 +90,29 @@ internal class Play : DBCommand return; } - Data.audioClient = await Data.voiceChannel.ConnectAsync(true); - - - using (var ffmpeg = CreateStream(path)) - using (var output = ffmpeg.StandardOutput.BaseStream) - using (var discord = Data.audioClient.CreatePCMStream(AudioApplication.Mixed)) + if (Data.audioClient is null) { - if (Data.CurrentlyRunning != null) Data.CurrentlyRunning.Stop(); - Data.CurrentlyRunning = new MusicPlayer(output, discord); - await Data.CurrentlyRunning.StartSendAudio(); + Data.audioClient = await Data.voiceChannel.ConnectAsync(true); + Data.MusicPlayer = null; + } + + + using (var discordChanneAudioOutStream = Data.audioClient.CreatePCMStream(AudioApplication.Mixed)) + { + if (Data.MusicPlayer is null) + Data.MusicPlayer = new MusicPlayer(discordChanneAudioOutStream); + while (Data.Playlist.Count > 0) + { + var nowPlaying = Data.Playlist.GetNextSong; + using (var ffmpeg = CreateStream(nowPlaying.Name)) + using (var ffmpegOutputBaseStream = ffmpeg.StandardOutput.BaseStream) + { + await Data.MusicPlayer.Play(ffmpegOutputBaseStream, 1024); + Console.WriteLine("Finished playing from" + nowPlaying.Name); + } + } + + Data.MusicPlayer = null; } } @@ -89,16 +120,4 @@ internal class Play : DBCommand { return Process.Start(new ProcessStartInfo { FileName = "ffmpeg", Arguments = $"-hide_banner -loglevel panic -i \"{path}\" -ac 2 -f s16le -ar 48000 pipe:1", UseShellExecute = false, RedirectStandardOutput = true }); } - - private async Task GetMusicAudio(string url, string location) - { - Process proc = new Process(); - proc.StartInfo.FileName = "MusicDownloader.exe"; - proc.StartInfo.Arguments = $"{url},{location}"; - proc.StartInfo.UseShellExecute = false; - proc.StartInfo.RedirectStandardOutput = true; - - proc.Start(); - await proc.WaitForExitAsync(); - } } diff --git a/MusicCommands/Skip.cs b/MusicCommands/Skip.cs new file mode 100644 index 0000000..583363c --- /dev/null +++ b/MusicCommands/Skip.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Discord.Commands; +using Discord.WebSocket; +using PluginManager.Interfaces; + +namespace MusicCommands +{ + public class Skip : DBCommand + { + public string Command => "skip"; + + public string Description => "skip the music that is currently running"; + + public string Usage => "skip"; + + public bool canUseDM => false; + + public bool canUseServer => true; + + public bool requireAdmin => false; + + public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) + { + Data.MusicPlayer.isPlaying = false; + } + } +} diff --git a/MusicCommands/Unpause.cs b/MusicCommands/Unpause.cs deleted file mode 100644 index cfe2040..0000000 --- a/MusicCommands/Unpause.cs +++ /dev/null @@ -1,25 +0,0 @@ -using Discord.Commands; -using Discord.WebSocket; -using PluginManager.Interfaces; - -namespace MusicCommands; - -internal class Unpause : DBCommand -{ - public string Command => "unpause"; - - public string Description => "Unpause the music"; - - public string Usage => "unpause"; - - public bool canUseDM => false; - - public bool canUseServer => true; - - public bool requireAdmin => false; - - public void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) - { - Data.CurrentlyRunning.Paused = false; - } -} diff --git a/MusicCommands/queue.cs b/MusicCommands/queue.cs new file mode 100644 index 0000000..a6c762d --- /dev/null +++ b/MusicCommands/queue.cs @@ -0,0 +1,31 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Discord.Commands; +using Discord.WebSocket; +using PluginManager.Interfaces; + +namespace MusicCommands +{ + public class queue : DBCommand + { + public string Command => "queue"; + + public string Description => "check queue"; + + public string Usage => "queue"; + + public bool canUseDM => false; + + public bool canUseServer => true; + + public bool requireAdmin => false; + + public async void Execute(SocketCommandContext context, SocketMessage message, DiscordSocketClient client, bool isDM) + { + await context.Channel.SendMessageAsync($"You have {Data.Playlist.Count} items in queue"); + } + } +}