rewrite started
This commit is contained in:
parent
0240a62337
commit
ba7fb089d2
@ -5,6 +5,9 @@ using System.Collections.Generic;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Discord.Commands;
|
using Discord.Commands;
|
||||||
using MusicModule = NadekoBot.Modules.Music;
|
using MusicModule = NadekoBot.Modules.Music;
|
||||||
|
using System.Collections;
|
||||||
|
using NadekoBot.Extensions;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
namespace NadekoBot.Classes.Music {
|
namespace NadekoBot.Classes.Music {
|
||||||
|
|
||||||
@ -13,8 +16,130 @@ namespace NadekoBot.Classes.Music {
|
|||||||
Normal,
|
Normal,
|
||||||
Local
|
Local
|
||||||
}
|
}
|
||||||
|
public class Song {
|
||||||
|
public StreamState State { get; internal set; }
|
||||||
|
|
||||||
public class MusicControls {
|
private Song() { }
|
||||||
|
|
||||||
|
internal Task Play(CancellationToken cancelToken) {
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class MusicPlayer {
|
||||||
|
private IAudioClient _client { get; set; }
|
||||||
|
|
||||||
|
private List<Song> _playlist = new List<Song>();
|
||||||
|
public IReadOnlyCollection<Song> Playlist => _playlist;
|
||||||
|
private object playlistLock = new object();
|
||||||
|
|
||||||
|
public Song CurrentSong { get; set; } = default(Song);
|
||||||
|
private CancellationTokenSource SongCancelSource { get; set; }
|
||||||
|
private CancellationToken cancelToken { get; set; }
|
||||||
|
|
||||||
|
public bool Paused { get; set; }
|
||||||
|
|
||||||
|
public float Volume { get; private set; }
|
||||||
|
|
||||||
|
public MusicPlayer(IAudioClient client) {
|
||||||
|
if (client == null)
|
||||||
|
throw new ArgumentNullException(nameof(client));
|
||||||
|
_client = client;
|
||||||
|
SongCancelSource = new CancellationTokenSource();
|
||||||
|
cancelToken = SongCancelSource.Token;
|
||||||
|
Task.Run(async () => {
|
||||||
|
while (_client?.State == ConnectionState.Connected) {
|
||||||
|
CurrentSong = GetNextSong();
|
||||||
|
if (CurrentSong != null) {
|
||||||
|
try {
|
||||||
|
await CurrentSong.Play(cancelToken);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) {
|
||||||
|
Console.WriteLine("Song canceled");
|
||||||
|
}
|
||||||
|
catch (Exception ex) {
|
||||||
|
Console.WriteLine($"Exception in PlaySong: {ex}");
|
||||||
|
}
|
||||||
|
SongCancelSource = new CancellationTokenSource();
|
||||||
|
cancelToken = SongCancelSource.Token;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await Stop();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Next() {
|
||||||
|
if(!SongCancelSource.IsCancellationRequested)
|
||||||
|
SongCancelSource.Cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Stop() {
|
||||||
|
|
||||||
|
lock (_playlist) {
|
||||||
|
_playlist.Clear();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (!SongCancelSource.IsCancellationRequested)
|
||||||
|
SongCancelSource.Cancel();
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Console.WriteLine("This shouldn't happen");
|
||||||
|
}
|
||||||
|
await _client?.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Shuffle() {
|
||||||
|
lock (_playlist) {
|
||||||
|
_playlist.Shuffle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetVolume(float volume) {
|
||||||
|
if (volume < 0)
|
||||||
|
volume = 0;
|
||||||
|
if (volume > 150)
|
||||||
|
volume = 150;
|
||||||
|
|
||||||
|
Volume = volume / 100.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Song GetNextSong() {
|
||||||
|
lock (playlistLock) {
|
||||||
|
if (_playlist.Count == 0)
|
||||||
|
return null;
|
||||||
|
var toReturn = _playlist[0];
|
||||||
|
_playlist.RemoveAt(0);
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddSong(Song s) {
|
||||||
|
if (s == null)
|
||||||
|
throw new ArgumentNullException(nameof(s));
|
||||||
|
lock (playlistLock) {
|
||||||
|
_playlist.Add(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveSong(Song s) {
|
||||||
|
if (s == null)
|
||||||
|
throw new ArgumentNullException(nameof(s));
|
||||||
|
lock (playlistLock) {
|
||||||
|
_playlist.Remove(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveSongAt(int index) {
|
||||||
|
lock (playlistLock) {
|
||||||
|
if (index < 0 || index >= _playlist.Count)
|
||||||
|
throw new ArgumentException("Invalid index");
|
||||||
|
_playlist.RemoveAt(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
private CommandEventArgs _e;
|
private CommandEventArgs _e;
|
||||||
public bool NextSong { get; set; } = false;
|
public bool NextSong { get; set; } = false;
|
||||||
public IAudioClient Voice { get; set; }
|
public IAudioClient Voice { get; set; }
|
||||||
@ -33,7 +158,7 @@ namespace NadekoBot.Classes.Music {
|
|||||||
|
|
||||||
private readonly object _voiceLock = new object();
|
private readonly object _voiceLock = new object();
|
||||||
|
|
||||||
public MusicControls() {
|
public MusicPlayer() {
|
||||||
Task.Run(async () => {
|
Task.Run(async () => {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!Stopped) {
|
if (!Stopped) {
|
||||||
@ -61,7 +186,7 @@ namespace NadekoBot.Classes.Music {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicControls(Channel voiceChannel, CommandEventArgs e, float? vol) : this() {
|
public MusicPlayer(Channel voiceChannel, CommandEventArgs e, float? vol) : this() {
|
||||||
if (voiceChannel == null)
|
if (voiceChannel == null)
|
||||||
throw new ArgumentNullException(nameof(voiceChannel));
|
throw new ArgumentNullException(nameof(voiceChannel));
|
||||||
if (vol != null)
|
if (vol != null)
|
||||||
@ -96,7 +221,6 @@ namespace NadekoBot.Classes.Music {
|
|||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
Console.WriteLine($"Starting failed: {ex}");
|
Console.WriteLine($"Starting failed: {ex}");
|
||||||
CurrentSong?.Stop();
|
CurrentSong?.Stop();
|
||||||
CurrentSong = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,7 +236,7 @@ namespace NadekoBot.Classes.Music {
|
|||||||
VoiceClient?.Disconnect();
|
VoiceClient?.Disconnect();
|
||||||
VoiceClient = null;
|
VoiceClient = null;
|
||||||
|
|
||||||
MusicControls throwAwayValue;
|
MusicPlayer throwAwayValue;
|
||||||
MusicModule.musicPlayers.TryRemove(_e.Server, out throwAwayValue);
|
MusicModule.musicPlayers.TryRemove(_e.Server, out throwAwayValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,5 +251,6 @@ namespace NadekoBot.Classes.Music {
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal bool TogglePause() => IsPaused = !IsPaused;
|
internal bool TogglePause() => IsPaused = !IsPaused;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -38,9 +38,9 @@ namespace NadekoBot.Classes.Music {
|
|||||||
|
|
||||||
public MusicType LinkType { get; }
|
public MusicType LinkType { get; }
|
||||||
|
|
||||||
public MusicControls MusicControls;
|
public MusicPlayer MusicControls;
|
||||||
|
|
||||||
public StreamRequest(CommandEventArgs e, string query, MusicControls mc, MusicType musicType = MusicType.Normal) {
|
public StreamRequest(CommandEventArgs e, string query, MusicPlayer mc, MusicType musicType = MusicType.Normal) {
|
||||||
if (e == null)
|
if (e == null)
|
||||||
throw new ArgumentNullException(nameof(e));
|
throw new ArgumentNullException(nameof(e));
|
||||||
if (query == null)
|
if (query == null)
|
||||||
|
@ -15,7 +15,7 @@ using Timer = System.Timers.Timer;
|
|||||||
namespace NadekoBot.Modules {
|
namespace NadekoBot.Modules {
|
||||||
class Music : DiscordModule {
|
class Music : DiscordModule {
|
||||||
|
|
||||||
public static ConcurrentDictionary<Server, MusicControls> musicPlayers = new ConcurrentDictionary<Server, MusicControls>();
|
public static ConcurrentDictionary<Server, MusicPlayer> musicPlayers = new ConcurrentDictionary<Server, MusicPlayer>();
|
||||||
public static ConcurrentDictionary<ulong, float> musicVolumes = new ConcurrentDictionary<ulong, float>();
|
public static ConcurrentDictionary<ulong, float> musicVolumes = new ConcurrentDictionary<ulong, float>();
|
||||||
|
|
||||||
internal static string GetMusicStats() {
|
internal static string GetMusicStats() {
|
||||||
@ -24,7 +24,21 @@ namespace NadekoBot.Modules {
|
|||||||
return $"Playing {cnt = stats.Count()} songs".SnPl(cnt) + $", {stats.Sum(kvp => kvp.Value?.SongQueue?.Count ?? 0)} queued.";
|
return $"Playing {cnt = stats.Count()} songs".SnPl(cnt) + $", {stats.Sum(kvp => kvp.Value?.SongQueue?.Count ?? 0)} queued.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Timer setgameTimer => new Timer();
|
||||||
|
|
||||||
|
bool setgameEnabled = false;
|
||||||
|
|
||||||
public Music() : base() {
|
public Music() : base() {
|
||||||
|
|
||||||
|
setgameTimer.Interval = 20000;
|
||||||
|
setgameTimer.Elapsed += (s, e) => {
|
||||||
|
try {
|
||||||
|
int num = musicPlayers.Where(kvp => kvp.Value.CurrentSong != null).Count();
|
||||||
|
NadekoBot.client.SetGame($"{num} songs".SnPl(num) + $", {musicPlayers.Sum(kvp => kvp.Value.SongQueue.Count())} queued");
|
||||||
|
}
|
||||||
|
catch { }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Install(ModuleManager manager) {
|
public override void Install(ModuleManager manager) {
|
||||||
@ -164,17 +178,6 @@ namespace NadekoBot.Modules {
|
|||||||
player.SongQueue.Shuffle();
|
player.SongQueue.Shuffle();
|
||||||
await e.Channel.SendMessage("🎵 `Songs shuffled.`");
|
await e.Channel.SendMessage("🎵 `Songs shuffled.`");
|
||||||
});
|
});
|
||||||
|
|
||||||
bool setgameEnabled = false;
|
|
||||||
Timer setgameTimer = new Timer();
|
|
||||||
setgameTimer.Interval = 20000;
|
|
||||||
setgameTimer.Elapsed += (s, e) => {
|
|
||||||
try {
|
|
||||||
int num = musicPlayers.Where(kvp => kvp.Value.CurrentSong != null).Count();
|
|
||||||
NadekoBot.client.SetGame($"{num} songs".SnPl(num) + $", {musicPlayers.Sum(kvp => kvp.Value.SongQueue.Count())} queued");
|
|
||||||
}
|
|
||||||
catch { }
|
|
||||||
};
|
|
||||||
cgb.CreateCommand("setgame")
|
cgb.CreateCommand("setgame")
|
||||||
.Description("Sets the game of the bot to the number of songs playing.**Owner only**")
|
.Description("Sets the game of the bot to the number of songs playing.**Owner only**")
|
||||||
.Do(async e => {
|
.Do(async e => {
|
||||||
@ -201,7 +204,7 @@ namespace NadekoBot.Modules {
|
|||||||
//todo TEMPORARY SOLUTION, USE RESOLVE QUEUE IN THE FUTURE
|
//todo TEMPORARY SOLUTION, USE RESOLVE QUEUE IN THE FUTURE
|
||||||
var msg = await e.Channel.SendMessage($"🎵 `Attempting to queue {ids.Count} songs".SnPl(ids.Count) + "...`");
|
var msg = await e.Channel.SendMessage($"🎵 `Attempting to queue {ids.Count} songs".SnPl(ids.Count) + "...`");
|
||||||
foreach (var id in ids) {
|
foreach (var id in ids) {
|
||||||
Task.Run(async () => await QueueSong(e, id, true)).ConfigureAwait(false);
|
Task.Run(async () => await QueueSong(e, id, true));
|
||||||
await Task.Delay(150);
|
await Task.Delay(150);
|
||||||
}
|
}
|
||||||
msg?.Edit("🎵 `Playlist queue complete.`");
|
msg?.Edit("🎵 `Playlist queue complete.`");
|
||||||
@ -250,7 +253,7 @@ namespace NadekoBot.Modules {
|
|||||||
cgb.CreateCommand("mv")
|
cgb.CreateCommand("mv")
|
||||||
.Description("Moves the bot to your voice channel. (works only if music is already playing)")
|
.Description("Moves the bot to your voice channel. (works only if music is already playing)")
|
||||||
.Do(async e => {
|
.Do(async e => {
|
||||||
MusicControls mc;
|
MusicPlayer mc;
|
||||||
if (e.User.VoiceChannel == null || e.User.VoiceChannel.Server != e.Server || !musicPlayers.TryGetValue(e.Server, out mc))
|
if (e.User.VoiceChannel == null || e.User.VoiceChannel.Server != e.Server || !musicPlayers.TryGetValue(e.Server, out mc))
|
||||||
return;
|
return;
|
||||||
mc.VoiceChannel = e.User.VoiceChannel;
|
mc.VoiceChannel = e.User.VoiceChannel;
|
||||||
@ -262,7 +265,7 @@ namespace NadekoBot.Modules {
|
|||||||
.Parameter("num", ParameterType.Required)
|
.Parameter("num", ParameterType.Required)
|
||||||
.Do(async e => {
|
.Do(async e => {
|
||||||
var arg = e.GetArg("num");
|
var arg = e.GetArg("num");
|
||||||
MusicControls mc;
|
MusicPlayer mc;
|
||||||
if (!musicPlayers.TryGetValue(e.Server, out mc)) {
|
if (!musicPlayers.TryGetValue(e.Server, out mc)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -316,7 +319,7 @@ namespace NadekoBot.Modules {
|
|||||||
if (musicVolumes.TryGetValue(e.Server.Id, out throwAway))
|
if (musicVolumes.TryGetValue(e.Server.Id, out throwAway))
|
||||||
vol = throwAway;
|
vol = throwAway;
|
||||||
|
|
||||||
if (!musicPlayers.TryAdd(e.Server, new MusicControls(e.User.VoiceChannel, e, vol))) {
|
if (!musicPlayers.TryAdd(e.Server, new MusicPlayer(e.User.VoiceChannel, e, vol))) {
|
||||||
await e.Channel.SendMessage("Failed to create a music player for this server.");
|
await e.Channel.SendMessage("Failed to create a music player for this server.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -339,13 +342,15 @@ namespace NadekoBot.Modules {
|
|||||||
qmsg = await e.Channel.SendMessage("🎵 `Searching / Resolving...`");
|
qmsg = await e.Channel.SendMessage("🎵 `Searching / Resolving...`");
|
||||||
sr.OnResolvingFailed += async (err) => {
|
sr.OnResolvingFailed += async (err) => {
|
||||||
try {
|
try {
|
||||||
await qmsg.Edit($"💢 🎵 `Resolving failed` for **{query}**");
|
await qmsg.Delete();
|
||||||
|
await e.Channel.Send($"💢 🎵 `Resolving failed` for **{query}**");
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
};
|
};
|
||||||
sr.OnQueued += async () => {
|
sr.OnQueued += async () => {
|
||||||
try {
|
try {
|
||||||
await qmsg.Edit($"🎵`Queued`{sr.FullPrettyName}");
|
await qmsg.Delete();
|
||||||
|
await e.Channel.Send($"🎵`Queued`{sr.FullPrettyName}");
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
};
|
};
|
||||||
@ -354,7 +359,7 @@ namespace NadekoBot.Modules {
|
|||||||
}
|
}
|
||||||
sr.OnCompleted += async () => {
|
sr.OnCompleted += async () => {
|
||||||
try {
|
try {
|
||||||
MusicControls mc;
|
MusicPlayer mc;
|
||||||
if (musicPlayers.TryGetValue(e.Server, out mc)) {
|
if (musicPlayers.TryGetValue(e.Server, out mc)) {
|
||||||
if (mc.SongQueue.Count == 0)
|
if (mc.SongQueue.Count == 0)
|
||||||
mc.Stop();
|
mc.Stop();
|
||||||
@ -363,12 +368,12 @@ namespace NadekoBot.Modules {
|
|||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
};
|
};
|
||||||
|
|
||||||
sr.OnStarted += async () => {
|
sr.OnStarted += async () => {
|
||||||
try {
|
try {
|
||||||
var msgTxt = $"🎵`Playing`{sr.FullPrettyName} `Vol: {(int)(player.Volume * 100)}%`";
|
var msgTxt = $"🎵`Playing`{sr.FullPrettyName} `Vol: {(int)(player.Volume * 100)}%`";
|
||||||
if (qmsg != null)
|
if (qmsg != null)
|
||||||
await qmsg.Edit(msgTxt);
|
await qmsg.Delete();
|
||||||
else
|
|
||||||
await e.Channel.SendMessage(msgTxt);
|
await e.Channel.SendMessage(msgTxt);
|
||||||
}
|
}
|
||||||
catch { }
|
catch { }
|
||||||
|
Loading…
Reference in New Issue
Block a user