using System.Runtime.InteropServices; using ReactiveUI; namespace RedBookPlayer.Models.Hardware { 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 } }