Fixed a bug where spamming .n would crash the music player, closes #1372
This commit is contained in:
parent
70f0f6af44
commit
9a744172a9
@ -163,83 +163,86 @@ namespace NadekoBot.Services.Music
|
|||||||
if (data.Song != null)
|
if (data.Song != null)
|
||||||
{
|
{
|
||||||
_log.Info("Starting");
|
_log.Info("Starting");
|
||||||
using (var b = new SongBuffer(await data.Song.Uri(), "", data.Song.ProviderType == Database.Models.MusicType.Local))
|
AudioOutStream pcm = null;
|
||||||
|
SongBuffer b = null;
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_log.Info("Created buffer, buffering...");
|
b = new SongBuffer(await data.Song.Uri(), "", data.Song.ProviderType == Database.Models.MusicType.Local);
|
||||||
AudioOutStream pcm = null;
|
//_log.Info("Created buffer, buffering...");
|
||||||
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)
|
||||||
{
|
{
|
||||||
var bufferTask = b.StartBuffering(cancelToken);
|
_log.Info("Can't join");
|
||||||
var timeout = Task.Delay(10000);
|
await Task.Delay(900, cancelToken);
|
||||||
if (Task.WhenAny(bufferTask, timeout) == timeout)
|
// just wait some time, maybe bot doesn't even have perms to join that voice channel,
|
||||||
{
|
// i don't want to spam connection attempts
|
||||||
_log.Info("Buffering failed due to a timeout.");
|
continue;
|
||||||
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)
|
pcm = ac.CreatePCMStream(AudioApplication.Music, bufferMillis: 500);
|
||||||
{
|
_log.Info("Created pcm stream");
|
||||||
_log.Info("Song Canceled");
|
OnStarted?.Invoke(this, data);
|
||||||
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);
|
byte[] buffer = new byte[3840];
|
||||||
|
int bytesRead = 0;
|
||||||
|
|
||||||
if (_bytesSent == 0 && !cancel)
|
while ((bytesRead = b.Read(buffer, 0, buffer.Length)) > 0
|
||||||
{
|
&& (MaxPlaytimeSeconds <= 0 || MaxPlaytimeSeconds >= CurrentTime.TotalSeconds))
|
||||||
lock (locker)
|
{
|
||||||
Queue.RemoveSong(data.Song);
|
AdjustVolume(buffer, Volume);
|
||||||
_log.Info("Song removed because it can't play");
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b != null)
|
||||||
|
b.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
|
try
|
||||||
|
@ -26,6 +26,34 @@ namespace NadekoBot.Services.Music
|
|||||||
//_log.Warn(songUri);
|
//_log.Warn(songUri);
|
||||||
this.SongUri = songUri;
|
this.SongUri = songUri;
|
||||||
this._isLocal = isLocal;
|
this._isLocal = isLocal;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.p = StartFFmpegProcess(SongUri, 0);
|
||||||
|
var t = Task.Run(() =>
|
||||||
|
{
|
||||||
|
this.p.BeginErrorReadLine();
|
||||||
|
this.p.ErrorDataReceived += P_ErrorDataReceived;
|
||||||
|
this.p.WaitForExit();
|
||||||
|
});
|
||||||
|
|
||||||
|
this._outStream = this.p.StandardOutput.BaseStream;
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (System.ComponentModel.Win32Exception)
|
||||||
|
{
|
||||||
|
_log.Error(@"You have not properly installed or configured FFMPEG.
|
||||||
|
Please install and configure FFMPEG to play music.
|
||||||
|
Check the guides for your platform on how to setup ffmpeg correctly:
|
||||||
|
Windows Guide: https://goo.gl/OjKk8F
|
||||||
|
Linux Guide: https://goo.gl/ShjCUo");
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) { }
|
||||||
|
catch (InvalidOperationException) { } // when ffmpeg is disposed
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_log.Info(ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Process StartFFmpegProcess(string songUri, float skipTo = 0)
|
private Process StartFFmpegProcess(string songUri, float skipTo = 0)
|
||||||
@ -65,16 +93,8 @@ namespace NadekoBot.Services.Music
|
|||||||
var toReturn = new TaskCompletionSource<bool>();
|
var toReturn = new TaskCompletionSource<bool>();
|
||||||
var _ = Task.Run(() =>
|
var _ = Task.Run(() =>
|
||||||
{
|
{
|
||||||
try {
|
try
|
||||||
this.p = StartFFmpegProcess(SongUri, 0);
|
|
||||||
var t = Task.Run(() =>
|
|
||||||
{
|
{
|
||||||
this.p.BeginErrorReadLine();
|
|
||||||
this.p.ErrorDataReceived += P_ErrorDataReceived;
|
|
||||||
this.p.WaitForExit();
|
|
||||||
});
|
|
||||||
|
|
||||||
this._outStream = this.p.StandardOutput.BaseStream;
|
|
||||||
|
|
||||||
////int maxLoopsPerSec = 25;
|
////int maxLoopsPerSec = 25;
|
||||||
//var sw = Stopwatch.StartNew();
|
//var sw = Stopwatch.StartNew();
|
||||||
|
Loading…
Reference in New Issue
Block a user