Lot more work, fixes, addition, untested new implementations...
This commit is contained in:
		@@ -48,7 +48,7 @@ namespace NadekoBot.DataStructures
 | 
			
		||||
 | 
			
		||||
        private readonly SemaphoreSlim _locker = new SemaphoreSlim(1, 1);
 | 
			
		||||
 | 
			
		||||
        public PoopyRingBuffer(int capacity = 38400)
 | 
			
		||||
        public PoopyRingBuffer(int capacity = 3640 * 200)
 | 
			
		||||
        {
 | 
			
		||||
            this.Capacity = capacity + 1;
 | 
			
		||||
            this.buffer = new byte[this.Capacity];
 | 
			
		||||
 
 | 
			
		||||
@@ -111,11 +111,15 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        //todo  add play command. .play = .n, .play whatever = .q whatever
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Queue([Remainder] string query)
 | 
			
		||||
        {
 | 
			
		||||
            //todo add a notice that player is stopped if user queues a song while it is
 | 
			
		||||
            var mp = await _music.GetOrCreatePlayer(Context);
 | 
			
		||||
            var songInfo = await _music.ResolveSong(query, Context.User.ToString());
 | 
			
		||||
            await InternalQueue(mp, songInfo, false);
 | 
			
		||||
@@ -209,11 +213,9 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
                if (mp.RepeatCurrentSong)
 | 
			
		||||
                    desc = "🔂 " + GetText("repeating_cur_song") + "\n\n" + desc;
 | 
			
		||||
                //else if (musicPlayer.RepeatPlaylist)
 | 
			
		||||
                //    desc = "🔁 " + GetText("repeating_playlist") + "\n\n" + desc;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                else if (mp.Shuffle)
 | 
			
		||||
                    desc = "🔀 " + GetText("shuffling_playlist") + "\n\n" + desc;
 | 
			
		||||
                
 | 
			
		||||
                var embed = new EmbedBuilder()
 | 
			
		||||
                    .WithAuthor(eab => eab.WithName(GetText("player_queue", curPage + 1, lastPage + 1))
 | 
			
		||||
                        .WithMusicIcon())
 | 
			
		||||
@@ -307,7 +309,7 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
            {
 | 
			
		||||
                var song = mp.RemoveAt(index - 1);
 | 
			
		||||
                var embed = new EmbedBuilder()
 | 
			
		||||
                            .WithAuthor(eab => eab.WithName(GetText("removed_song") + " #" + (index + 1)).WithMusicIcon())
 | 
			
		||||
                            .WithAuthor(eab => eab.WithName(GetText("removed_song") + " #" + (index)).WithMusicIcon())
 | 
			
		||||
                            .WithDescription(song.PrettyName)
 | 
			
		||||
                            .WithFooter(ef => ef.WithText(song.PrettyInfo))
 | 
			
		||||
                            .WithErrorColor();
 | 
			
		||||
@@ -519,22 +521,18 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
            await Context.Channel.EmbedAsync(embed).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //[NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task ShufflePlaylist()
 | 
			
		||||
        //{
 | 
			
		||||
        //    MusicPlayer musicPlayer;
 | 
			
		||||
        //    if ((musicPlayer = _music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    if (((IGuildUser)Context.User).VoiceChannel != musicPlayer.PlaybackVoiceChannel)
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    if (musicPlayer.Playlist.Count < 2)
 | 
			
		||||
        //        return;
 | 
			
		||||
 | 
			
		||||
        //    musicPlayer.Shuffle();
 | 
			
		||||
        //    await ReplyConfirmLocalized("songs_shuffled").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
        //todo test shuffle
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task ShufflePlaylist()
 | 
			
		||||
        {
 | 
			
		||||
            var mp = await _music.GetOrCreatePlayer(Context);
 | 
			
		||||
            var val = mp.ToggleShuffle();
 | 
			
		||||
            if(val)
 | 
			
		||||
                await ReplyConfirmLocalized("songs_shuffle_enable").ConfigureAwait(false);
 | 
			
		||||
            else
 | 
			
		||||
                await ReplyConfirmLocalized("songs_shuffle_disable").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //[NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
@@ -687,17 +685,22 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        //[NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Move()
 | 
			
		||||
        //{
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Move()
 | 
			
		||||
        {
 | 
			
		||||
            var vch = ((IGuildUser)Context.User).VoiceChannel;
 | 
			
		||||
 | 
			
		||||
        //    MusicPlayer musicPlayer;
 | 
			
		||||
        //    var voiceChannel = ((IGuildUser)Context.User).VoiceChannel;
 | 
			
		||||
        //    if (voiceChannel == null || voiceChannel.Guild != Context.Guild || !MusicPlayers.TryGetValue(Context.Guild.Id, out musicPlayer))
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    await musicPlayer.MoveToVoiceChannel(voiceChannel);
 | 
			
		||||
        //}
 | 
			
		||||
            if (vch == null)
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var mp = _music.GetPlayerOrDefault(Context.Guild.Id);
 | 
			
		||||
 | 
			
		||||
            if (mp == null)
 | 
			
		||||
                return;
 | 
			
		||||
            //todo test move
 | 
			
		||||
            mp.SetVoiceChannel(vch);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //[NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
@@ -745,21 +748,21 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        //[NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task SetMaxQueue(uint size = 0)
 | 
			
		||||
        //{
 | 
			
		||||
        //    MusicPlayer musicPlayer;
 | 
			
		||||
        //    if ((musicPlayer = _music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
        //        return;
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task SetMaxQueue(uint size = 0)
 | 
			
		||||
        {
 | 
			
		||||
            if (size < 0)
 | 
			
		||||
                return;
 | 
			
		||||
            var mp = await _music.GetOrCreatePlayer(Context);
 | 
			
		||||
 | 
			
		||||
        //    musicPlayer.MaxQueueSize = size;
 | 
			
		||||
            mp.SetMaxQueueSize(size);
 | 
			
		||||
 | 
			
		||||
        //    if(size == 0)
 | 
			
		||||
        //        await ReplyConfirmLocalized("max_queue_unlimited").ConfigureAwait(false);
 | 
			
		||||
        //    else
 | 
			
		||||
        //        await ReplyConfirmLocalized("max_queue_x", size).ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
            if (size == 0)
 | 
			
		||||
                await ReplyConfirmLocalized("max_queue_unlimited").ConfigureAwait(false);
 | 
			
		||||
            else
 | 
			
		||||
                await ReplyConfirmLocalized("max_queue_x", size).ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //[NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
@@ -800,19 +803,17 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
                                            .ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //[NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task RepeatPl()
 | 
			
		||||
        //{
 | 
			
		||||
        //    MusicPlayer musicPlayer;
 | 
			
		||||
        //    if ((musicPlayer = _music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
        //        return;
 | 
			
		||||
        //    var currentValue = musicPlayer.ToggleRepeatPlaylist();
 | 
			
		||||
        //    if(currentValue)
 | 
			
		||||
        //        await ReplyConfirmLocalized("rpl_enabled").ConfigureAwait(false);
 | 
			
		||||
        //    else
 | 
			
		||||
        //        await ReplyConfirmLocalized("rpl_disabled").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task RepeatPl()
 | 
			
		||||
        {
 | 
			
		||||
            var mp = await _music.GetOrCreatePlayer(Context);
 | 
			
		||||
            var currentValue = mp.ToggleRepeatPlaylist();
 | 
			
		||||
            if (currentValue)
 | 
			
		||||
                await ReplyConfirmLocalized("rpl_enabled").ConfigureAwait(false);
 | 
			
		||||
            else
 | 
			
		||||
                await ReplyConfirmLocalized("rpl_disabled").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //[NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
@@ -849,19 +850,17 @@ namespace NadekoBot.Modules.Music
 | 
			
		||||
        //    await ReplyConfirmLocalized("skipped_to", minutes, seconds).ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
        //[NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        //[RequireContext(ContextType.Guild)]
 | 
			
		||||
        //public async Task Autoplay()
 | 
			
		||||
        //{
 | 
			
		||||
        //    MusicPlayer musicPlayer;
 | 
			
		||||
        //    if ((musicPlayer = _music.GetPlayer(Context.Guild.Id)) == null)
 | 
			
		||||
        //        return;
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
        public async Task Autoplay()
 | 
			
		||||
        {
 | 
			
		||||
            var mp = await _music.GetOrCreatePlayer(Context);
 | 
			
		||||
 | 
			
		||||
        //    if (!musicPlayer.ToggleAutoplay())
 | 
			
		||||
        //        await ReplyConfirmLocalized("autoplay_disabled").ConfigureAwait(false);
 | 
			
		||||
        //    else
 | 
			
		||||
        //        await ReplyConfirmLocalized("autoplay_enabled").ConfigureAwait(false);
 | 
			
		||||
        //}
 | 
			
		||||
            if (!mp.ToggleAutoplay())
 | 
			
		||||
                await ReplyConfirmLocalized("autoplay_disabled").ConfigureAwait(false);
 | 
			
		||||
            else
 | 
			
		||||
                await ReplyConfirmLocalized("autoplay_enabled").ConfigureAwait(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        [NadekoCommand, Usage, Description, Aliases]
 | 
			
		||||
        [RequireContext(ContextType.Guild)]
 | 
			
		||||
 
 | 
			
		||||
@@ -183,7 +183,7 @@ namespace NadekoBot
 | 
			
		||||
                #endregion
 | 
			
		||||
 | 
			
		||||
                var clashService = new ClashOfClansService(Client, Db, Localization, Strings, uow, startingGuildIdList);
 | 
			
		||||
                var musicService = new MusicService(GoogleApi, Strings, Localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
 | 
			
		||||
                var musicService = new MusicService(Client, GoogleApi, Strings, Localization, Db, soundcloudApiService, Credentials, AllGuildConfigs);
 | 
			
		||||
                var crService = new CustomReactionsService(permissionsService, Db, Strings, Client, CommandHandler, BotConfig, uow);
 | 
			
		||||
 | 
			
		||||
                #region Games
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
    public class MusicPlayer
 | 
			
		||||
    {
 | 
			
		||||
        private readonly Task _player;
 | 
			
		||||
        private readonly IVoiceChannel VoiceChannel;
 | 
			
		||||
        private IVoiceChannel VoiceChannel { get; set; }
 | 
			
		||||
        private readonly Logger _log;
 | 
			
		||||
 | 
			
		||||
        private MusicQueue Queue { get; } = new MusicQueue();
 | 
			
		||||
@@ -42,9 +42,13 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool RepeatCurrentSong { get; private set; }
 | 
			
		||||
        public bool Shuffle { get; private set; }
 | 
			
		||||
        public bool Autoplay { get; private set; }
 | 
			
		||||
        public bool RepeatPlaylist { get; private set; } = true;
 | 
			
		||||
 | 
			
		||||
        private IAudioClient _audioClient;
 | 
			
		||||
        private readonly object locker = new object();
 | 
			
		||||
        private MusicService _musicService;
 | 
			
		||||
 | 
			
		||||
        #region events
 | 
			
		||||
        public event Action<MusicPlayer, SongInfo> OnStarted;
 | 
			
		||||
@@ -59,6 +63,7 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
            this.VoiceChannel = vch;
 | 
			
		||||
            this.SongCancelSource = new CancellationTokenSource();
 | 
			
		||||
            this.OutputTextChannel = output;
 | 
			
		||||
            this._musicService = musicService;
 | 
			
		||||
 | 
			
		||||
            _player = Task.Run(async () =>
 | 
			
		||||
             {
 | 
			
		||||
@@ -96,42 +101,43 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
                                 // i don't want to spam connection attempts
 | 
			
		||||
                                 continue;
 | 
			
		||||
                             }
 | 
			
		||||
                             var pcm = ac.CreatePCMStream(AudioApplication.Music);
 | 
			
		||||
 | 
			
		||||
                             OnStarted?.Invoke(this, data.Song);
 | 
			
		||||
 | 
			
		||||
                             byte[] buffer = new byte[3840];
 | 
			
		||||
                             int bytesRead = 0;
 | 
			
		||||
                             try
 | 
			
		||||
                             using (var pcm = ac.CreatePCMStream(AudioApplication.Music))
 | 
			
		||||
                             {
 | 
			
		||||
                                 while ((bytesRead = await b.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false)) > 0)
 | 
			
		||||
                                 OnStarted?.Invoke(this, data.Song);
 | 
			
		||||
 | 
			
		||||
                                 byte[] buffer = new byte[3840];
 | 
			
		||||
                                 int bytesRead = 0;
 | 
			
		||||
                                 try
 | 
			
		||||
                                 {
 | 
			
		||||
                                     var vol = Volume;
 | 
			
		||||
                                     if (vol != 1)
 | 
			
		||||
                                         AdjustVolume(buffer, vol);
 | 
			
		||||
                                     await Task.WhenAll(Task.Delay(10), pcm.WriteAsync(buffer, 0, bytesRead, cancelToken)).ConfigureAwait(false);
 | 
			
		||||
                                     while ((bytesRead = await b.ReadAsync(buffer, 0, buffer.Length, cancelToken).ConfigureAwait(false)) > 0)
 | 
			
		||||
                                     {
 | 
			
		||||
                                         var vol = Volume;
 | 
			
		||||
                                         if (vol != 1)
 | 
			
		||||
                                             AdjustVolume(buffer, vol);
 | 
			
		||||
                                         await Task.WhenAll(Task.Delay(10), pcm.WriteAsync(buffer, 0, bytesRead, cancelToken)).ConfigureAwait(false);
 | 
			
		||||
 | 
			
		||||
                                     await (pauseTaskSource?.Task ?? Task.CompletedTask);
 | 
			
		||||
                                         await (pauseTaskSource?.Task ?? Task.CompletedTask);
 | 
			
		||||
                                     }
 | 
			
		||||
                                 }
 | 
			
		||||
                             }
 | 
			
		||||
                             catch (OperationCanceledException)
 | 
			
		||||
                             {
 | 
			
		||||
                                 _log.Info("Song Canceled");
 | 
			
		||||
                             }
 | 
			
		||||
                             catch (Exception ex)
 | 
			
		||||
                             {
 | 
			
		||||
                                 _log.Warn(ex);
 | 
			
		||||
                             }
 | 
			
		||||
                             finally
 | 
			
		||||
                             {
 | 
			
		||||
                                 //flush is known to get stuck from time to time, just cancel it if it takes more than 1 second
 | 
			
		||||
                                var flushCancel = new CancellationTokenSource();
 | 
			
		||||
                                var flushToken = flushCancel.Token;
 | 
			
		||||
                                var flushDelay = Task.Delay(1000, flushToken);
 | 
			
		||||
                                await Task.WhenAny(flushDelay, pcm.FlushAsync(flushToken));
 | 
			
		||||
                                flushCancel.Cancel();
 | 
			
		||||
                                 catch (OperationCanceledException)
 | 
			
		||||
                                 {
 | 
			
		||||
                                     _log.Info("Song Canceled");
 | 
			
		||||
                                 }
 | 
			
		||||
                                 catch (Exception ex)
 | 
			
		||||
                                 {
 | 
			
		||||
                                     _log.Warn(ex);
 | 
			
		||||
                                 }
 | 
			
		||||
                                 finally
 | 
			
		||||
                                 {
 | 
			
		||||
                                     //flush is known to get stuck from time to time, just cancel it if it takes more than 1 second
 | 
			
		||||
                                     var flushCancel = new CancellationTokenSource();
 | 
			
		||||
                                     var flushToken = flushCancel.Token;
 | 
			
		||||
                                     var flushDelay = Task.Delay(1000, flushToken);
 | 
			
		||||
                                     await Task.WhenAny(flushDelay, pcm.FlushAsync(flushToken));
 | 
			
		||||
                                     flushCancel.Cancel();
 | 
			
		||||
 | 
			
		||||
                                 OnCompleted?.Invoke(this, data.Song);
 | 
			
		||||
                                     OnCompleted?.Invoke(this, data.Song);
 | 
			
		||||
                                 }
 | 
			
		||||
                             }
 | 
			
		||||
                         }
 | 
			
		||||
                     }
 | 
			
		||||
@@ -143,8 +149,35 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
                             await Task.Delay(500);
 | 
			
		||||
                         }
 | 
			
		||||
                         while (Stopped && !Exited);
 | 
			
		||||
                         if(!RepeatCurrentSong)
 | 
			
		||||
                            Queue.Next();
 | 
			
		||||
                         if (!RepeatCurrentSong) //if repeating current song, just ignore other settings, and play this song again (don't change the index)
 | 
			
		||||
                         {
 | 
			
		||||
                             if (Shuffle)
 | 
			
		||||
                                 Queue.Random(); //if shuffle is set, set current song index to a random number
 | 
			
		||||
                             else
 | 
			
		||||
                             {
 | 
			
		||||
                                 //if last song, and autoplay is enabled, and if it's a youtube song
 | 
			
		||||
                                 // do autplay magix
 | 
			
		||||
                                 if (Queue.Count == data.Index && Autoplay && data.Song?.Provider == "YouTube")
 | 
			
		||||
                                 {
 | 
			
		||||
                                     try
 | 
			
		||||
                                     {
 | 
			
		||||
                                         //todo test autoplay
 | 
			
		||||
                                         await _musicService.TryQueueRelatedSongAsync(data.Song.Query, OutputTextChannel, VoiceChannel);
 | 
			
		||||
                                         Queue.Next();
 | 
			
		||||
                                     }
 | 
			
		||||
                                     catch { }
 | 
			
		||||
                                 }
 | 
			
		||||
                                 else if (Queue.Count == data.Index && !RepeatPlaylist)
 | 
			
		||||
                                 {
 | 
			
		||||
                                     //todo test repeatplaylist
 | 
			
		||||
                                     Stop();
 | 
			
		||||
                                 }
 | 
			
		||||
                                 else
 | 
			
		||||
                                 {
 | 
			
		||||
                                     Queue.Next();
 | 
			
		||||
                                 }
 | 
			
		||||
                             }
 | 
			
		||||
                         }
 | 
			
		||||
                     }
 | 
			
		||||
                 }
 | 
			
		||||
             }, SongCancelSource.Token);
 | 
			
		||||
@@ -313,6 +346,41 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
                await ac.StopAsync();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool ToggleShuffle()
 | 
			
		||||
        {
 | 
			
		||||
            lock (locker)
 | 
			
		||||
            {
 | 
			
		||||
                return Shuffle = !Shuffle;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool ToggleAutoplay()
 | 
			
		||||
        {
 | 
			
		||||
            lock (locker)
 | 
			
		||||
            {
 | 
			
		||||
                return Autoplay = !Autoplay;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public bool ToggleRepeatPlaylist()
 | 
			
		||||
        {
 | 
			
		||||
            lock (locker)
 | 
			
		||||
            {
 | 
			
		||||
                return RepeatPlaylist = !RepeatPlaylist;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void SetMaxQueueSize(uint size)
 | 
			
		||||
        {
 | 
			
		||||
            Queue.SetMaxQueueSize(size);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void SetVoiceChannel(IVoiceChannel vch)
 | 
			
		||||
        {
 | 
			
		||||
            VoiceChannel = vch;
 | 
			
		||||
            Next();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        //private IAudioClient AudioClient { get; set; }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
using System;
 | 
			
		||||
using NadekoBot.Extensions;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
@@ -49,17 +50,23 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public uint maxQueueSize { get; private set; }
 | 
			
		||||
 | 
			
		||||
        public void Add(SongInfo song)
 | 
			
		||||
        {
 | 
			
		||||
            song.ThrowIfNull(nameof(song));
 | 
			
		||||
            lock (locker)
 | 
			
		||||
            {
 | 
			
		||||
                if(CurrentIndex >= maxQueueSize)
 | 
			
		||||
                    throw new PlaylistFullException();
 | 
			
		||||
                Songs.AddLast(song);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Next()
 | 
			
		||||
        {
 | 
			
		||||
            CurrentIndex++;
 | 
			
		||||
            lock(locker)
 | 
			
		||||
                CurrentIndex++;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Dispose()
 | 
			
		||||
@@ -118,5 +125,24 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
                CurrentIndex = 0;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void Random()
 | 
			
		||||
        {
 | 
			
		||||
            lock (locker)
 | 
			
		||||
            {
 | 
			
		||||
                CurrentIndex = new NadekoRandom().Next(Songs.Count);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public void SetMaxQueueSize(uint size)
 | 
			
		||||
        {
 | 
			
		||||
            if (size < 0)
 | 
			
		||||
                throw new ArgumentOutOfRangeException(nameof(size));
 | 
			
		||||
 | 
			
		||||
            lock (locker)
 | 
			
		||||
            {
 | 
			
		||||
                maxQueueSize = size;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ using System.IO;
 | 
			
		||||
using VideoLibrary;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using Discord.Commands;
 | 
			
		||||
using Discord.WebSocket;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Music
 | 
			
		||||
{
 | 
			
		||||
@@ -25,13 +26,15 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
        private readonly SoundCloudApiService _sc;
 | 
			
		||||
        private readonly IBotCredentials _creds;
 | 
			
		||||
        private readonly ConcurrentDictionary<ulong, float> _defaultVolumes;
 | 
			
		||||
        private readonly DiscordSocketClient _client;
 | 
			
		||||
 | 
			
		||||
        public ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>();
 | 
			
		||||
 | 
			
		||||
        public MusicService(IGoogleApiService google,
 | 
			
		||||
        public MusicService(DiscordSocketClient client, IGoogleApiService google,
 | 
			
		||||
            NadekoStrings strings, ILocalization localization, DbService db,
 | 
			
		||||
            SoundCloudApiService sc, IBotCredentials creds, IEnumerable<GuildConfig> gcs)
 | 
			
		||||
        {
 | 
			
		||||
            _client = client;
 | 
			
		||||
            _google = google;
 | 
			
		||||
            _strings = strings;
 | 
			
		||||
            _localization = localization;
 | 
			
		||||
@@ -187,6 +190,25 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public MusicPlayer GetPlayerOrDefault(ulong guildId)
 | 
			
		||||
        {
 | 
			
		||||
            if (MusicPlayers.TryGetValue(guildId, out var mp))
 | 
			
		||||
                return mp;
 | 
			
		||||
            else
 | 
			
		||||
                return null;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task TryQueueRelatedSongAsync(string query, ITextChannel txtCh, IVoiceChannel vch)
 | 
			
		||||
        {
 | 
			
		||||
            var related = (await _google.GetRelatedVideosAsync(query, 4)).ToArray();
 | 
			
		||||
            if (!related.Any())
 | 
			
		||||
                return;
 | 
			
		||||
 | 
			
		||||
            var si = await ResolveSong(related[new NadekoRandom().Next(related.Length)], _client.CurrentUser.ToString(), MusicType.Normal);
 | 
			
		||||
            var mp = await GetOrCreatePlayer(txtCh.GuildId, vch, txtCh);
 | 
			
		||||
            mp.Enqueue(si);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public async Task<SongInfo> ResolveSong(string query, string queuerName, MusicType musicType = MusicType.Normal)
 | 
			
		||||
        {
 | 
			
		||||
            query.ThrowIfNull(nameof(query));
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ namespace NadekoBot.Services.Music
 | 
			
		||||
            this.p = Process.Start(new ProcessStartInfo
 | 
			
		||||
            {
 | 
			
		||||
                FileName = "ffmpeg",
 | 
			
		||||
                Arguments = $"-i {songUri} -f s16le -ar 48000 -vn -ac 2 pipe:1 -loglevel quiet",
 | 
			
		||||
                Arguments = $"-i {songUri} -f s16le -ar 48000 -vn -b:a 128k -ac 2 pipe:1 -loglevel quiet -nostdin",
 | 
			
		||||
                UseShellExecute = false,
 | 
			
		||||
                RedirectStandardOutput = true,
 | 
			
		||||
                RedirectStandardError = false,
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ using NadekoBot.Services.Database.Models;
 | 
			
		||||
using System;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Text.RegularExpressions;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
 | 
			
		||||
namespace NadekoBot.Services.Music
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
@@ -442,12 +442,14 @@
 | 
			
		||||
  "music_repeating_playlist": "Repeating playlist",
 | 
			
		||||
  "music_repeating_track": "Repeating track",
 | 
			
		||||
  "music_repeating_track_stopped": "Current track repeat stopped.",
 | 
			
		||||
  "music_shuffling_playlist": "Shuffling songs",
 | 
			
		||||
  "music_resumed": "Music playback resumed.",
 | 
			
		||||
  "music_rpl_disabled": "Repeat playlist disabled.",
 | 
			
		||||
  "music_rpl_enabled": "Repeat playlist enabled.",
 | 
			
		||||
  "music_set_music_channel": "I will now output playing, finished, paused and removed songs in this channel.",
 | 
			
		||||
  "music_skipped_to": "Skipped to `{0}:{1}`",
 | 
			
		||||
  "music_songs_shuffled": "Songs shuffled",
 | 
			
		||||
  "music_songs_shuffle_enable": "Songs will shuffle from now on.",
 | 
			
		||||
  "music_songs_shuffle_disable": "Songs will no longer shuffle.",
 | 
			
		||||
  "music_song_moved": "Song moved",
 | 
			
		||||
  "music_song_not_found": "No song found.",
 | 
			
		||||
  "music_time_format": "{0}h {1}m {2}s",
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user