Files
TechMedia/TechMedia.Core/TechMediaCore.cs
2022-03-05 00:43:36 -07:00

158 lines
4.9 KiB
C#

using TechMedia.Core.Backend;
using TechMedia.Core.Model;
namespace TechMedia.Core
{
public class TechMediaCore : ITechMediaCore
{
private readonly IAudioBackend _backend;
private List<Track> _currentPlaylist = new();
private Queue<Track> _requestQueue = new();
private IProgress<Track>? _trackReporter;
private IProgress<float>? _progressReporter;
private IProgress<List<Track>>? _playlistWatcher;
private int _playbackIndex = 0;
public TechMediaCore(IAudioBackend backend)
{
_backend = backend;
_backend.RegisterTrackEndHandler(TrackEndHandler);
}
public void StartPlaylistPlayback(IProgress<Track>? trackReporter = null, IProgress<float>? progressReporter = null)
{
if (trackReporter != null)
_trackReporter = trackReporter;
if (progressReporter != null)
{
if (_progressReporter != null)
{
_backend.RemoveProgressWatcher(_progressReporter);
}
_progressReporter = progressReporter;
_backend.RegisterProgressWatcher(progressReporter);
}
var firstTrack = _currentPlaylist[_playbackIndex++];
_backend.PlayFile(firstTrack.Filename);
_trackReporter?.Report(firstTrack);
}
private void QueueFilePlayback(string filename)
{
// LibVLC has a famous bug when calling LibVLC from a LibVLC callback (which is what this method is) that results in a deadlock.
// Workaround is to queue the action on another thread.
ThreadPool.QueueUserWorkItem(_ => _backend.PlayFile(filename));
}
public void TrackEndHandler(object? sender, EventArgs args)
{
if (_requestQueue.Count > 0)
{
var requestTrack = _requestQueue.Dequeue();
_trackReporter?.Report(requestTrack);
QueueFilePlayback(requestTrack.Filename);
}
else if (_playbackIndex < _currentPlaylist.Count)
{
var nextTrack = _currentPlaylist[_playbackIndex++];
_trackReporter?.Report(nextTrack);
QueueFilePlayback(nextTrack.Filename);
}
else
{
ThreadPool.QueueUserWorkItem(state =>
{
ShuffleCurrentPlaylist();
StartPlaylistPlayback();
});
}
}
public void Stop()
{
_backend.StopPlayback();
_playbackIndex = 0;
}
public void Play()
{
throw new NotImplementedException();
}
public void Pause()
{
throw new NotImplementedException();
}
public void NextTrack()
{
throw new NotImplementedException();
}
public void PreviousTrack()
{
throw new NotImplementedException();
}
public void GetNextTrackInfo()
{
throw new NotImplementedException();
}
public void GetCurrentTrackInfo()
{
throw new NotImplementedException();
}
public void OpenMediaFile(string filename)
{
_backend.PlayFile(filename);
}
public void OpenPlaylistFile()
{
throw new NotImplementedException();
}
public async Task<int> LoadFiles(List<string> files, IProgress<int>? progress = null)
{
_currentPlaylist = new List<Track>();
foreach (var (file, index) in files.Select((filename, index) => (filename, index)))
{
var track = await _backend.GetFileMetadata(file);
progress?.Report(index);
if (track != null)
_currentPlaylist.Add(track);
}
return _currentPlaylist.Count;
}
public List<Track> ShuffleCurrentPlaylist()
{
_backend.StopPlayback();
_playbackIndex = 0;
var random = new Random();
_currentPlaylist = _currentPlaylist.OrderBy(t => random.Next()).ToList();
_playlistWatcher?.Report(_currentPlaylist);
return _currentPlaylist;
}
public List<Track> GetCurrentPlaylist() => _currentPlaylist;
public void RegisterPlaylistChangeListener(IProgress<List<Track>> playlistWatcher)
{
_playlistWatcher = playlistWatcher;
}
public Track? SubmitRequest(string filename)
{
var requestedTrack = _currentPlaylist.FirstOrDefault(t => t.Filename.Equals(filename, StringComparison.OrdinalIgnoreCase));
if (requestedTrack != null)
_requestQueue.Enqueue(requestedTrack);
return requestedTrack;
}
}
}