added rcs and rpl (repeat current song, playlist), improved !m lq, closes #108

This commit is contained in:
Master Kwoth 2016-04-01 18:40:45 +02:00
parent 488b897690
commit b74aaec173
2 changed files with 123 additions and 39 deletions

View File

@ -5,15 +5,18 @@ using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace NadekoBot.Classes.Music {
namespace NadekoBot.Classes.Music
{
public enum MusicType {
public enum MusicType
{
Radio,
Normal,
Local
}
public enum StreamState {
public enum StreamState
{
Resolving,
Queued,
Buffering, //not using it atm
@ -21,7 +24,8 @@ namespace NadekoBot.Classes.Music {
Completed
}
public class MusicPlayer {
public class MusicPlayer
{
public static int MaximumPlaylistSize => 50;
private IAudioClient audioClient { get; set; }
@ -44,8 +48,11 @@ namespace NadekoBot.Classes.Music {
public Channel PlaybackVoiceChannel { get; private set; }
private bool Destroyed { get; set; } = false;
public bool RepeatSong { get; private set; } = false;
public bool RepeatPlaylist { get; private set; } = false;
public MusicPlayer(Channel startingVoiceChannel, float? defaultVolume) {
public MusicPlayer(Channel startingVoiceChannel, float? defaultVolume)
{
if (startingVoiceChannel == null)
throw new ArgumentNullException(nameof(startingVoiceChannel));
if (startingVoiceChannel.Type != ChannelType.Voice)
@ -56,27 +63,42 @@ namespace NadekoBot.Classes.Music {
SongCancelSource = new CancellationTokenSource();
cancelToken = SongCancelSource.Token;
Task.Run(async () => {
while (!Destroyed) {
try {
if(audioClient?.State != ConnectionState.Connected)
Task.Run(async () =>
{
while (!Destroyed)
{
try
{
if (audioClient?.State != ConnectionState.Connected)
audioClient = await PlaybackVoiceChannel.JoinAudio();
} catch {
}
catch
{
await Task.Delay(1000);
continue;
}
CurrentSong = GetNextSong();
var curSong = CurrentSong;
if (curSong != null) {
try {
if (curSong != null)
{
try
{
OnStarted(this, curSong);
await curSong.Play(audioClient, cancelToken);
} catch (OperationCanceledException) {
}
catch (OperationCanceledException)
{
Console.WriteLine("Song canceled");
} catch (Exception ex) {
}
catch (Exception ex)
{
Console.WriteLine($"Exception in PlaySong: {ex}");
}
OnCompleted(this, curSong);
if (RepeatSong)
playlist.Insert(0, curSong);
else if (RepeatPlaylist)
playlist.Insert(playlist.Count, curSong);
SongCancelSource = new CancellationTokenSource();
cancelToken = SongCancelSource.Token;
}
@ -85,17 +107,22 @@ namespace NadekoBot.Classes.Music {
});
}
public void Next() {
lock (playlistLock) {
if (!SongCancelSource.IsCancellationRequested) {
public void Next()
{
lock (playlistLock)
{
if (!SongCancelSource.IsCancellationRequested)
{
Paused = false;
SongCancelSource.Cancel();
}
}
}
public void Stop() {
lock (playlistLock) {
public void Stop()
{
lock (playlistLock)
{
playlist.Clear();
CurrentSong = null;
if (!SongCancelSource.IsCancellationRequested)
@ -105,13 +132,16 @@ namespace NadekoBot.Classes.Music {
public void TogglePause() => Paused = !Paused;
public void Shuffle() {
lock (playlistLock) {
public void Shuffle()
{
lock (playlistLock)
{
playlist.Shuffle();
}
}
public int SetVolume(int volume) {
public int SetVolume(int volume)
{
if (volume < 0)
volume = 0;
if (volume > 150)
@ -121,8 +151,10 @@ namespace NadekoBot.Classes.Music {
return volume;
}
private Song GetNextSong() {
lock (playlistLock) {
private Song GetNextSong()
{
lock (playlistLock)
{
if (playlist.Count == 0)
return null;
var toReturn = playlist[0];
@ -131,45 +163,56 @@ namespace NadekoBot.Classes.Music {
}
}
public void AddSong(Song s) {
public void AddSong(Song s)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
lock (playlistLock) {
lock (playlistLock)
{
playlist.Add(s);
}
}
public void RemoveSong(Song s) {
public void RemoveSong(Song s)
{
if (s == null)
throw new ArgumentNullException(nameof(s));
lock (playlistLock) {
lock (playlistLock)
{
playlist.Remove(s);
}
}
public void RemoveSongAt(int index) {
lock (playlistLock) {
public void RemoveSongAt(int index)
{
lock (playlistLock)
{
if (index < 0 || index >= playlist.Count)
throw new ArgumentException("Invalid index");
playlist.RemoveAt(index);
}
}
internal Task MoveToVoiceChannel(Channel voiceChannel) {
internal Task MoveToVoiceChannel(Channel voiceChannel)
{
if (audioClient?.State != ConnectionState.Connected)
throw new InvalidOperationException("Can't move while bot is not connected to voice channel.");
PlaybackVoiceChannel = voiceChannel;
return PlaybackVoiceChannel.JoinAudio();
}
internal void ClearQueue() {
lock (playlistLock) {
internal void ClearQueue()
{
lock (playlistLock)
{
playlist.Clear();
}
}
public void Destroy() {
lock (playlistLock) {
public void Destroy()
{
lock (playlistLock)
{
playlist.Clear();
Destroyed = true;
CurrentSong = null;
@ -178,5 +221,9 @@ namespace NadekoBot.Classes.Music {
audioClient.Disconnect();
}
}
internal bool ToggleRepeatSong() => this.RepeatSong = !this.RepeatSong;
internal bool ToggleRepeatPlaylist() => this.RepeatPlaylist = !this.RepeatPlaylist;
}
}

View File

@ -139,7 +139,15 @@ namespace NadekoBot.Modules
await e.Channel.SendMessage("🎵 No active music player.");
return;
}
var toSend = "🎵 **" + musicPlayer.Playlist.Count + "** `tracks currently queued.` ";
var currentSong = musicPlayer.CurrentSong;
if (currentSong == null)
return;
var toSend = $"🎵`Now Playing` {currentSong.PrettyName} " + $"{currentSong.PrettyCurrentTime()}\n";
if (musicPlayer.RepeatSong)
toSend += "🔁 `Repeating current song.`\n";
else if (musicPlayer.RepeatPlaylist)
toSend += "🔁 `Repeating playlist.`\n";
toSend += $"🎵 **{musicPlayer.Playlist.Count}** `tracks currently queued.` ";
if (musicPlayer.Playlist.Count >= MusicPlayer.MaximumPlaylistSize)
toSend += "**Song queue is full!**\n";
else
@ -157,7 +165,8 @@ namespace NadekoBot.Modules
if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer))
return;
var currentSong = musicPlayer.CurrentSong;
if (currentSong != null)
if (currentSong == null)
return;
await e.Channel.SendMessage($"🎵`Now Playing` {currentSong.PrettyName} " +
$"{currentSong.PrettyCurrentTime()}");
});
@ -386,6 +395,34 @@ namespace NadekoBot.Modules
}
});
cgb.CreateCommand("rcs")
.Alias("repeatcurrentsong")
.Description("Toggles repeat of current song.")
.Do(async e =>
{
MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer))
return;
var currentSong = musicPlayer.CurrentSong;
if (currentSong == null)
return;
var currentValue = musicPlayer.ToggleRepeatSong();
await e.Channel.SendMessage(currentValue ?
$"🎵 `Repeating track:`{currentSong.PrettyName}" :
$"🎵 `Current track repeat stopped.`");
});
cgb.CreateCommand("rpl")
.Alias("repeatplaylist")
.Description("Toggles repeat of all songs in the queue (every song that finishes is added to the end of the queue).")
.Do(async e =>
{
MusicPlayer musicPlayer;
if (!MusicPlayers.TryGetValue(e.Server, out musicPlayer))
return;
var currentValue = musicPlayer.ToggleRepeatPlaylist();
await e.Channel.SendMessage($"🎵🔁`Repeat playlist {(currentValue ? "enabled" : "disabled")}`");
});
//cgb.CreateCommand("debug")
// .Description("Does something magical. **BOT OWNER ONLY**")
// .AddCheck(Classes.Permissions.SimpleCheckers.OwnerOnly())