From 72e7b04319b6f66979b9ce929d80c16ed88ff249 Mon Sep 17 00:00:00 2001 From: Master Kwoth Date: Sat, 8 Jul 2017 13:42:16 +0200 Subject: [PATCH] Fixed 100% cpu usage on single threaded systems. Totally my bad. --- src/NadekoBot/Services/Music/MusicPlayer.cs | 304 ++++++++++---------- 1 file changed, 152 insertions(+), 152 deletions(-) diff --git a/src/NadekoBot/Services/Music/MusicPlayer.cs b/src/NadekoBot/Services/Music/MusicPlayer.cs index 49f2c99d..fbb1a56d 100644 --- a/src/NadekoBot/Services/Music/MusicPlayer.cs +++ b/src/NadekoBot/Services/Music/MusicPlayer.cs @@ -160,173 +160,173 @@ namespace NadekoBot.Services.Music manualSkip = false; manualIndex = false; } - if (data.Song == null) - continue; - - _log.Info("Starting"); - using (var b = new SongBuffer(await data.Song.Uri(), "", data.Song.ProviderType == Database.Models.MusicType.Local)) + if (data.Song != null) { - _log.Info("Created buffer, buffering..."); - AudioOutStream pcm = null; + _log.Info("Starting"); + using (var b = new SongBuffer(await data.Song.Uri(), "", data.Song.ProviderType == Database.Models.MusicType.Local)) + { + _log.Info("Created buffer, buffering..."); + AudioOutStream pcm = null; + try + { + var bufferTask = b.StartBuffering(cancelToken); + var timeout = Task.Delay(10000); + if (Task.WhenAny(bufferTask, timeout) == timeout) + { + _log.Info("Buffering failed due to a timeout."); + continue; + } + else if (!bufferTask.Result) + { + _log.Info("Buffering failed due to a cancel or error."); + continue; + } + _log.Info("Buffered. Getting audio client..."); + var ac = await GetAudioClient(); + _log.Info("Got Audio client"); + if (ac == null) + { + _log.Info("Can't join"); + await Task.Delay(900, cancelToken); + // just wait some time, maybe bot doesn't even have perms to join that voice channel, + // i don't want to spam connection attempts + continue; + } + pcm = ac.CreatePCMStream(AudioApplication.Music, bufferMillis: 500); + _log.Info("Created pcm stream"); + OnStarted?.Invoke(this, data); + + byte[] buffer = new byte[3840]; + int bytesRead = 0; + + while ((bytesRead = b.Read(buffer, 0, buffer.Length)) > 0 + && (MaxPlaytimeSeconds <= 0 || MaxPlaytimeSeconds >= CurrentTime.TotalSeconds)) + { + AdjustVolume(buffer, Volume); + await pcm.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false); + unchecked { _bytesSent += bytesRead; } + + await (pauseTaskSource?.Task ?? Task.CompletedTask); + } + } + catch (OperationCanceledException) + { + _log.Info("Song Canceled"); + cancel = true; + } + catch (Exception ex) + { + _log.Warn(ex); + } + finally + { + if (pcm != null) + { + // flush is known to get stuck from time to time, + // just skip flushing 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(); + pcm.Dispose(); + } + + OnCompleted?.Invoke(this, data.Song); + + if (_bytesSent == 0 && !cancel) + { + lock (locker) + Queue.RemoveSong(data.Song); + _log.Info("Song removed because it can't play"); + } + } + } try { - var bufferTask = b.StartBuffering(cancelToken); - var timeout = Task.Delay(10000); - if (Task.WhenAny(bufferTask, timeout) == timeout) - { - _log.Info("Buffering failed due to a timeout."); - continue; - } - else if (!bufferTask.Result) - { - _log.Info("Buffering failed due to a cancel or error."); - continue; - } - _log.Info("Buffered. Getting audio client..."); - var ac = await GetAudioClient(); - _log.Info("Got Audio client"); - if (ac == null) - { - _log.Info("Can't join"); - await Task.Delay(900, cancelToken); - // just wait some time, maybe bot doesn't even have perms to join that voice channel, - // i don't want to spam connection attempts - continue; - } - pcm = ac.CreatePCMStream(AudioApplication.Music, bufferMillis: 500); - _log.Info("Created pcm stream"); - OnStarted?.Invoke(this, data); + //if repeating current song, just ignore other settings, + // and play this song again (don't change the index) + // ignore rcs if song is manually skipped - byte[] buffer = new byte[3840]; - int bytesRead = 0; + int queueCount; + lock (locker) + queueCount = Queue.Count; - while ((bytesRead = b.Read(buffer, 0, buffer.Length)) > 0 - && (MaxPlaytimeSeconds <= 0 || MaxPlaytimeSeconds >= CurrentTime.TotalSeconds)) + if (!manualIndex && (!RepeatCurrentSong || manualSkip)) { - AdjustVolume(buffer, Volume); - await pcm.WriteAsync(buffer, 0, bytesRead, cancelToken).ConfigureAwait(false); - unchecked { _bytesSent += bytesRead; } - - await (pauseTaskSource?.Task ?? Task.CompletedTask); - } - } - catch (OperationCanceledException) - { - _log.Info("Song Canceled"); - cancel = true; - } - catch (Exception ex) - { - _log.Warn(ex); - } - finally - { - if (pcm != null) - { - // flush is known to get stuck from time to time, - // just skip flushing 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(); - pcm.Dispose(); - } - - OnCompleted?.Invoke(this, data.Song); - - if (_bytesSent == 0 && !cancel) - { - lock (locker) - Queue.RemoveSong(data.Song); - _log.Info("Song removed because it can't play"); - } - } - } - try - { - //if repeating current song, just ignore other settings, - // and play this song again (don't change the index) - // ignore rcs if song is manually skipped - - int queueCount; - lock (locker) - queueCount = Queue.Count; - - if (!manualIndex && (!RepeatCurrentSong || manualSkip)) - { - if (Shuffle) - { - _log.Info("Random song"); - 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 (queueCount - 1 == data.Index && Autoplay && data.Song?.ProviderType == Database.Models.MusicType.YouTube) + if (Shuffle) { - try - { - _log.Info("Loading related song"); - await _musicService.TryQueueRelatedSongAsync(data.Song.Query, OutputTextChannel, VoiceChannel); - Queue.Next(); - } - catch - { - _log.Info("Loading related song failed."); - } - } - else if (FairPlay) - { - lock (locker) - { - _log.Info("Next fair song"); - var q = Queue.ToArray().Songs.Shuffle().ToArray(); - - bool found = false; - for (var i = 0; i < q.Length; i++) //first try to find a queuer who didn't have their song played recently - { - var item = q[i]; - if (RecentlyPlayedUsers.Add(item.QueuerName)) // if it's found, set current song to that index - { - Queue.CurrentIndex = i; - found = true; - break; - } - } - if (!found) //if it's not - { - RecentlyPlayedUsers.Clear(); //clear all recently played users (that means everyone from the playlist has had their song played) - Queue.Random(); //go to a random song (to prevent looping on the first few songs) - var cur = Current; - if (cur.Current != null) // add newely scheduled song's queuer to the recently played list - RecentlyPlayedUsers.Add(cur.Current.QueuerName); - } - } - } - else if (queueCount - 1 == data.Index && !RepeatPlaylist && !manualSkip) - { - _log.Info("Stopping because repeatplaylist is disabled"); - lock (locker) - { - Stop(); - } + _log.Info("Random song"); + Queue.Random(); //if shuffle is set, set current song index to a random number } else { - _log.Info("Next song"); - lock (locker) + //if last song, and autoplay is enabled, and if it's a youtube song + // do autplay magix + if (queueCount - 1 == data.Index && Autoplay && data.Song?.ProviderType == Database.Models.MusicType.YouTube) { - Queue.Next(); + try + { + _log.Info("Loading related song"); + await _musicService.TryQueueRelatedSongAsync(data.Song.Query, OutputTextChannel, VoiceChannel); + Queue.Next(); + } + catch + { + _log.Info("Loading related song failed."); + } + } + else if (FairPlay) + { + lock (locker) + { + _log.Info("Next fair song"); + var q = Queue.ToArray().Songs.Shuffle().ToArray(); + + bool found = false; + for (var i = 0; i < q.Length; i++) //first try to find a queuer who didn't have their song played recently + { + var item = q[i]; + if (RecentlyPlayedUsers.Add(item.QueuerName)) // if it's found, set current song to that index + { + Queue.CurrentIndex = i; + found = true; + break; + } + } + if (!found) //if it's not + { + RecentlyPlayedUsers.Clear(); //clear all recently played users (that means everyone from the playlist has had their song played) + Queue.Random(); //go to a random song (to prevent looping on the first few songs) + var cur = Current; + if (cur.Current != null) // add newely scheduled song's queuer to the recently played list + RecentlyPlayedUsers.Add(cur.Current.QueuerName); + } + } + } + else if (queueCount - 1 == data.Index && !RepeatPlaylist && !manualSkip) + { + _log.Info("Stopping because repeatplaylist is disabled"); + lock (locker) + { + Stop(); + } + } + else + { + _log.Info("Next song"); + lock (locker) + { + Queue.Next(); + } } } } } - } - catch (Exception ex) - { - _log.Error(ex); + catch (Exception ex) + { + _log.Error(ex); + } } do {