Use MEF2 to load audio backends

This commit is contained in:
Declan Hoare 2020-08-20 17:14:12 +10:00
parent 650d9593d2
commit 2b6559b333
No known key found for this signature in database
GPG key ID: 4638791F582C04ED
5 changed files with 71 additions and 11 deletions

View file

@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Composition;
namespace FRESHMusicPlayer.Backends
{
class AudioBackendFactory
{
[ImportMany]
private IEnumerable<Lazy<IAudioBackend>> backends { get; set; }
///<summary>
/// The exceptions that were raised by rejected backends.
///</summary>
public IEnumerable<Exception> Exceptions { get; private set; } = null;
public IAudioBackend CreateBackend(string filename)
{
var exlist = new List<Exception>();
Exceptions = exlist;
foreach (var lazybackend in backends)
{
IAudioBackend backend = null;
try
{
backend = lazybackend.Value;
backend.LoadSong(filename);
return backend;
}
catch (Exception ex)
{
try
{
backend?.Dispose();
}
catch
{
}
exlist.Add(ex);
}
}
throw new Exception($"No backend could be found to play {filename}.\n\n{String.Join("\n\n", Exceptions)}\n");
}
}
}

View file

@ -8,6 +8,7 @@ namespace FRESHMusicPlayer.Backends
{
public interface IAudioBackend : IDisposable
{
void LoadSong(string file);
void Play();
void Pause();

View file

@ -1,12 +1,14 @@
using NAudio.Wave;
using System;
using System.Collections.Generic;
using System.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FRESHMusicPlayer.Backends
{
[Export(typeof(IAudioBackend))]
class NAudioBackend : IAudioBackend
{
private readonly WaveOutEvent outputDevice;
@ -27,7 +29,7 @@ namespace FRESHMusicPlayer.Backends
}
public TimeSpan TotalTime => AudioFile.TotalTime;
public NAudioBackend(string file)
public NAudioBackend()
{
if (outputDevice is null)
{
@ -37,12 +39,16 @@ namespace FRESHMusicPlayer.Backends
OnPlaybackStopped(this, new EventArgs());
};
}
}
if (AudioFile is null)
public void LoadSong(string file)
{
if (AudioFile != null)
{
AudioFile = new AudioFileReader(file);
outputDevice.Init(AudioFile);
AudioFile.Dispose();
}
AudioFile = new AudioFileReader(file);
outputDevice.Init(AudioFile);
}
public void Play()

View file

@ -14,6 +14,7 @@
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="NAudio" Version="1.10.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.Composition" Version="1.4.1" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
<PackageReference Include="z440.atl.core" Version="3.7.0" />
</ItemGroup>

View file

@ -1,6 +1,11 @@
using DiscordRPC;
using System;
using System.Collections.Generic;
using System.Composition;
using System.Composition.Hosting;
using System.IO;
using System.Linq;
using System.Reflection;
using FRESHMusicPlayer.Handlers;
using FRESHMusicPlayer.Utilities;
using FRESHMusicPlayer.Backends;
@ -39,6 +44,11 @@ namespace FRESHMusicPlayer
public event EventHandler SongStopped;
public event EventHandler<PlaybackExceptionEventArgs> SongException;
private CompositionHost container = new ContainerConfiguration()
.WithAssemblies(Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "*.dll")
.Select(n => { try { return Assembly.LoadFile(n); } catch (Exception ex) { Console.WriteLine(ex); return null; } })
.Where(a => a != null))
.CreateContainer();
#region CoreFMP
@ -120,13 +130,9 @@ namespace FRESHMusicPlayer
void PMusic()
{
//TODO: Check if FilePath is a file
//maybe we can use cd://2 for CD track 2, and anything else we can use the NAudio backend?
if (true)
{
currentBackend = new NAudioBackend(FilePath);
}
var factory = new AudioBackendFactory();
container.SatisfyImports(factory);
currentBackend = factory.CreateBackend(FilePath);
currentBackend.Play();
currentBackend.Volume = CurrentVolume;