158 lines
4.9 KiB
C#
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;
|
|
}
|
|
}
|
|
} |