108 lines
2.4 KiB
C#
108 lines
2.4 KiB
C#
using System.Collections.Concurrent;
|
|
using Discord.Audio;
|
|
using NAudio.Wave;
|
|
using NLog;
|
|
using Exception = System.Exception;
|
|
|
|
namespace Elementary.Audio;
|
|
|
|
public enum JobType
|
|
{
|
|
Audio,
|
|
Text,
|
|
// Sozai
|
|
}
|
|
|
|
public class PlaybackJob
|
|
{
|
|
public JobType Type;
|
|
public string Text;
|
|
public float Volume = 1.0f;
|
|
}
|
|
|
|
public class PlaybackQueue : IPlaybackQueue
|
|
{
|
|
// any type of job ConcurrentQueue
|
|
|
|
private ConcurrentQueue<PlaybackJob> _queue;
|
|
|
|
private AudioManager _audioManager;
|
|
|
|
private object _lock;
|
|
|
|
private bool _isPlaying;
|
|
|
|
private ILogger _logger;
|
|
|
|
public PlaybackQueue(AudioManager audioManager)
|
|
{
|
|
_queue = new();
|
|
_isPlaying = false;
|
|
_lock = new();
|
|
_audioManager = audioManager;
|
|
_logger = LogManager.GetCurrentClassLogger();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enqueue audio stream and play it
|
|
/// </summary>
|
|
/// <param name="job"></param>
|
|
public async Task Enqueue(PlaybackJob job)
|
|
{
|
|
_queue.Enqueue(job);
|
|
_logger.Info("Enqueued");
|
|
if (!_isPlaying)
|
|
{
|
|
lock (_lock)
|
|
{
|
|
if (!_isPlaying)
|
|
{
|
|
_logger.Info("Start Playing due to empty queue");
|
|
PlayNext();
|
|
}
|
|
}
|
|
}
|
|
|
|
await Task.CompletedTask;
|
|
}
|
|
|
|
public void Flush()
|
|
{
|
|
_queue.Clear();
|
|
_logger.Info("Queue Flushed");
|
|
}
|
|
|
|
private async void PlayNext()
|
|
{
|
|
try
|
|
{
|
|
if (_queue.TryDequeue(out var currentStream))
|
|
{
|
|
_logger.Info("Start Playing");
|
|
|
|
_isPlaying = true;
|
|
await (currentStream.Type switch
|
|
{
|
|
JobType.Audio => _audioManager.PlayAudio(currentStream.Text),
|
|
JobType.Text => _audioManager.PlayText(currentStream.Text),
|
|
_ => throw new ArgumentOutOfRangeException()
|
|
});
|
|
_logger.Info("Finished Playing");
|
|
await Task.Delay(200);
|
|
_isPlaying = false;
|
|
PlayNext();
|
|
}
|
|
else if (_queue.IsEmpty)
|
|
{
|
|
_logger.Info("Queue is empty");
|
|
_isPlaying = false;
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
_logger.Error(e);
|
|
_isPlaying = false;
|
|
PlayNext();
|
|
}
|
|
}
|
|
} |