Fixed 100% cpu usage on single threaded systems. Totally my bad.
This commit is contained in:
parent
568cdfbd3c
commit
72e7b04319
@ -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
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user