using System.Runtime.InteropServices;
using ReactiveUI;
namespace RedBookPlayer.Models.Audio
{
public class SoundOutput : ReactiveObject
{
#region Public Fields
///
/// Indicate if the output is ready to be used
///
public bool Initialized
{
get => _initialized;
private set => this.RaiseAndSetIfChanged(ref _initialized, value);
}
///
/// Indicates the current player state
///
public PlayerState PlayerState
{
get => _playerState;
private set => this.RaiseAndSetIfChanged(ref _playerState, value);
}
///
/// Current playback volume
///
public int Volume
{
get => _volume;
private set
{
int tempVolume = value;
if(value > 100)
tempVolume = 100;
else if(value < 0)
tempVolume = 0;
this.RaiseAndSetIfChanged(ref _volume, tempVolume);
}
}
private bool _initialized;
private PlayerState _playerState;
private int _volume;
#endregion
#region Private State Variables
///
/// Data provider for sound output
///
private PlayerSource _source;
///
/// Sound output instance
///
private IAudioBackend _soundOut;
#endregion
///
/// Constructor
///
/// Default volume between 0 and 100 to use when starting playback
public SoundOutput(int defaultVolume = 100) => Volume = defaultVolume;
///
/// Initialize the output with a given image
///
/// ReadFunction to use during decoding
/// True if playback should begin immediately, false otherwise
public void Init(PlayerSource.ReadFunction read, bool autoPlay)
{
// Reset initialization
Initialized = false;
// Setup the audio output
SetupAudio(read);
// Initialize playback, if necessary
if(autoPlay)
_soundOut.Play();
// Mark the output as ready
Initialized = true;
PlayerState = PlayerState.Stopped;
// Begin loading data
_source.Start();
}
///
/// Reset the current internal state
///
public void Reset()
{
_soundOut.Stop();
Initialized = false;
PlayerState = PlayerState.NoDisc;
}
#region Playback
///
/// Start audio playback
///
public void Play()
{
if(_soundOut.GetPlayerState() != PlayerState.Playing)
_soundOut.Play();
PlayerState = PlayerState.Playing;
}
///
/// Pause audio playback
///
public void Pause()
{
if(_soundOut.GetPlayerState() != PlayerState.Paused)
_soundOut.Pause();
PlayerState = PlayerState.Paused;
}
///
/// Stop audio playback
///
public void Stop()
{
if(_soundOut.GetPlayerState() != PlayerState.Stopped)
_soundOut.Stop();
PlayerState = PlayerState.Stopped;
}
///
/// Eject the currently loaded disc
///
public void Eject() => Reset();
#endregion
#region Helpers
///
/// Set the value for the volume
///
/// New volume value
public void SetVolume(int volume)
{
Volume = volume;
_soundOut?.SetVolume((float)Volume / 100);
}
///
/// Sets or resets the audio playback objects
///
/// ReadFunction to use during decoding
private void SetupAudio(PlayerSource.ReadFunction read)
{
if(_source == null)
{
_source = new PlayerSource(read);
if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
_soundOut = new Linux.AudioBackend(_source);
else if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
_soundOut = new Windows.AudioBackend(_source);
}
else
{
_soundOut.Stop();
}
}
#endregion
}
}