Files
RedBookPlayer/RedBookPlayer.Models/Audio/SoundOutput.cs

183 lines
4.9 KiB
C#
Raw Normal View History

2021-10-05 09:54:02 -07:00
using System.Runtime.InteropServices;
2021-07-04 23:17:30 -07:00
using ReactiveUI;
2021-03-19 17:07:27 -03:00
2021-10-06 20:52:16 -07:00
namespace RedBookPlayer.Models.Audio
2021-03-19 17:07:27 -03:00
{
2021-07-04 23:17:30 -07:00
public class SoundOutput : ReactiveObject
2021-03-19 17:07:27 -03:00
{
#region Public Fields
2021-04-14 20:36:34 -03:00
/// <summary>
2021-06-29 21:16:43 -07:00
/// Indicate if the output is ready to be used
/// </summary>
2021-08-05 21:05:20 -07:00
public bool Initialized
{
get => _initialized;
private set => this.RaiseAndSetIfChanged(ref _initialized, value);
}
2021-06-06 20:28:36 +01:00
/// <summary>
2021-08-05 21:05:20 -07:00
/// Indicates the current player state
/// </summary>
2021-08-05 21:05:20 -07:00
public PlayerState PlayerState
2021-07-04 23:17:30 -07:00
{
2021-08-05 21:05:20 -07:00
get => _playerState;
private set => this.RaiseAndSetIfChanged(ref _playerState, value);
2021-07-04 23:17:30 -07:00
}
/// <summary>
/// Current playback volume
/// </summary>
public int Volume
{
get => _volume;
2021-07-05 16:23:50 -07:00
private set
{
2021-07-04 23:17:30 -07:00
int tempVolume = value;
if(value > 100)
2021-07-04 23:17:30 -07:00
tempVolume = 100;
else if(value < 0)
2021-07-04 23:17:30 -07:00
tempVolume = 0;
this.RaiseAndSetIfChanged(ref _volume, tempVolume);
}
}
2021-08-05 21:05:20 -07:00
private bool _initialized;
private PlayerState _playerState;
2021-07-04 23:17:30 -07:00
private int _volume;
#endregion
#region Private State Variables
/// <summary>
/// Data provider for sound output
/// </summary>
private PlayerSource _source;
/// <summary>
/// Sound output instance
/// </summary>
2021-10-04 21:50:44 -07:00
private IAudioBackend _soundOut;
#endregion
2021-08-05 21:05:20 -07:00
/// <summary>
/// Constructor
/// </summary>
/// <param name="defaultVolume">Default volume between 0 and 100 to use when starting playback</param>
public SoundOutput(int defaultVolume = 100) => Volume = defaultVolume;
2021-08-05 21:05:20 -07:00
/// <summary>
/// Initialize the output with a given image
/// </summary>
/// <param name="read">ReadFunction to use during decoding</param>
/// <param name="autoPlay">True if playback should begin immediately, false otherwise</param>
public void Init(PlayerSource.ReadFunction read, bool autoPlay)
2021-03-19 17:07:27 -03:00
{
// Reset initialization
Initialized = false;
// Setup the audio output
SetupAudio(read);
2021-08-24 22:11:25 -07:00
// Initialize playback, if necessary
2021-06-06 20:28:36 +01:00
if(autoPlay)
_soundOut.Play();
2021-04-15 19:16:34 -03:00
// Mark the output as ready
2021-03-19 17:07:27 -03:00
Initialized = true;
2021-08-05 21:05:20 -07:00
PlayerState = PlayerState.Stopped;
2021-03-19 17:07:27 -03:00
// Begin loading data
_source.Start();
2021-03-19 17:07:27 -03:00
}
2021-08-24 22:11:25 -07:00
/// <summary>
/// Reset the current internal state
/// </summary>
public void Reset()
{
_soundOut.Stop();
Initialized = false;
PlayerState = PlayerState.NoDisc;
}
#region Playback
2021-03-19 17:07:27 -03:00
/// <summary>
/// Start audio playback
/// </summary>
2021-07-04 23:17:30 -07:00
public void Play()
{
2021-10-04 21:50:44 -07:00
if(_soundOut.GetPlayerState() != PlayerState.Playing)
2021-07-04 23:17:30 -07:00
_soundOut.Play();
2021-08-05 21:05:20 -07:00
PlayerState = PlayerState.Playing;
2021-07-04 23:17:30 -07:00
}
/// <summary>
/// Pause audio playback
/// </summary>
public void Pause()
{
2021-10-04 21:50:44 -07:00
if(_soundOut.GetPlayerState() != PlayerState.Paused)
2021-07-04 23:17:30 -07:00
_soundOut.Pause();
2021-08-05 21:05:20 -07:00
PlayerState = PlayerState.Paused;
2021-07-04 23:17:30 -07:00
}
/// <summary>
/// Stop audio playback
/// </summary>
2021-07-04 23:17:30 -07:00
public void Stop()
{
2021-10-04 21:50:44 -07:00
if(_soundOut.GetPlayerState() != PlayerState.Stopped)
2021-07-04 23:17:30 -07:00
_soundOut.Stop();
2021-08-05 21:05:20 -07:00
PlayerState = PlayerState.Stopped;
2021-07-04 23:17:30 -07:00
}
2021-03-19 17:07:27 -03:00
2021-08-24 22:11:25 -07:00
/// <summary>
/// Eject the currently loaded disc
/// </summary>
public void Eject() => Reset();
#endregion
2021-03-19 17:07:27 -03:00
#region Helpers
/// <summary>
/// Set the value for the volume
/// </summary>
/// <param name="volume">New volume value</param>
public void SetVolume(int volume)
2021-08-05 21:05:20 -07:00
{
Volume = volume;
2021-10-08 23:02:36 -07:00
_soundOut?.SetVolume((float)Volume / 100);
2021-08-05 21:05:20 -07:00
}
/// <summary>
/// Sets or resets the audio playback objects
/// </summary>
/// <param name="read">ReadFunction to use during decoding</param>
private void SetupAudio(PlayerSource.ReadFunction read)
{
if(_source == null)
{
_source = new PlayerSource(read);
2021-10-05 09:54:02 -07:00
if(RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
_soundOut = new Linux.AudioBackend(_source);
else if(RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
_soundOut = new Windows.AudioBackend(_source);
}
else
{
_soundOut.Stop();
}
}
2021-06-06 20:28:36 +01:00
#endregion
2021-03-19 17:07:27 -03:00
}
2021-08-05 21:05:20 -07:00
}