mirror of
https://github.com/aaru-dps/RedBookPlayer.git
synced 2025-12-16 19:24:41 +00:00
Make SoundOutput have events
This commit is contained in:
@@ -193,8 +193,6 @@ namespace RedBookPlayer.GUI
|
||||
if (_digits[i] != null)
|
||||
_digits[i].Source = GetBitmap(digitString[i]);
|
||||
}
|
||||
|
||||
PlayerViewModel?.UpdateView();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -211,13 +209,19 @@ namespace RedBookPlayer.GUI
|
||||
await LoadImage(path);
|
||||
}
|
||||
|
||||
public void PlayButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.Playing = true;
|
||||
public void PlayButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.Play();
|
||||
|
||||
public void PauseButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.Playing = false;
|
||||
public void PauseButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.Pause();
|
||||
|
||||
public void PlayPauseButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.Playing = !(PlayerViewModel.Playing ?? false);
|
||||
public void PlayPauseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if(PlayerViewModel.Playing == true)
|
||||
PlayerViewModel.Pause();
|
||||
else
|
||||
PlayerViewModel.Play();
|
||||
}
|
||||
|
||||
public void StopButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.Playing = null;
|
||||
public void StopButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.Stop();
|
||||
|
||||
public void NextTrackButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.NextTrack();
|
||||
|
||||
@@ -237,11 +241,11 @@ namespace RedBookPlayer.GUI
|
||||
|
||||
public void MuteToggleButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.ToggleMute();
|
||||
|
||||
public void EnableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.ApplyDeEmphasis = true;
|
||||
public void EnableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.SetDeEmphasis(true);
|
||||
|
||||
public void DisableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.ApplyDeEmphasis = false;
|
||||
public void DisableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.SetDeEmphasis(false);
|
||||
|
||||
public void EnableDisableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.ApplyDeEmphasis = !PlayerViewModel.ApplyDeEmphasis;
|
||||
public void EnableDisableDeEmphasisButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.SetDeEmphasis(!PlayerViewModel.ApplyDeEmphasis);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using ReactiveUI;
|
||||
using RedBookPlayer.Discs;
|
||||
using RedBookPlayer.Hardware;
|
||||
|
||||
namespace RedBookPlayer.GUI
|
||||
@@ -18,7 +17,7 @@ namespace RedBookPlayer.GUI
|
||||
/// </summary>
|
||||
private int? _lastVolume = null;
|
||||
|
||||
#region Player Status
|
||||
#region Player Passthrough
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the model is ready to be used
|
||||
@@ -26,29 +25,12 @@ namespace RedBookPlayer.GUI
|
||||
public bool Initialized => _player?.Initialized ?? false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicate the player state
|
||||
/// Indicate if the output is playing
|
||||
/// </summary>
|
||||
public bool? Playing
|
||||
{
|
||||
get => _player?.Playing ?? false;
|
||||
set
|
||||
{
|
||||
if(_player != null)
|
||||
_player.Playing = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicate the current playback volume
|
||||
/// </summary>
|
||||
public int Volume
|
||||
{
|
||||
get => _player?.Volume ?? 100;
|
||||
set
|
||||
{
|
||||
if(_player != null)
|
||||
_player.Volume = value;
|
||||
}
|
||||
get => _playing;
|
||||
private set => this.RaiseAndSetIfChanged(ref _playing, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -56,14 +38,23 @@ namespace RedBookPlayer.GUI
|
||||
/// </summary>
|
||||
public bool ApplyDeEmphasis
|
||||
{
|
||||
get => _player?.ApplyDeEmphasis ?? false;
|
||||
set
|
||||
{
|
||||
if(_player != null)
|
||||
_player.ApplyDeEmphasis = value;
|
||||
}
|
||||
get => _applyDeEmphasis;
|
||||
private set => this.RaiseAndSetIfChanged(ref _applyDeEmphasis, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current playback volume
|
||||
/// </summary>
|
||||
public int Volume
|
||||
{
|
||||
get => _volume;
|
||||
set => this.RaiseAndSetIfChanged(ref _volume, value);
|
||||
}
|
||||
|
||||
private bool? _playing;
|
||||
private bool _applyDeEmphasis;
|
||||
private int _volume;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Model-Provided Playback Information
|
||||
@@ -145,11 +136,29 @@ namespace RedBookPlayer.GUI
|
||||
// Create and attempt to initialize new Player
|
||||
_player = new Player(path, autoPlay, defaultVolume);
|
||||
if(Initialized)
|
||||
UpdateView();
|
||||
{
|
||||
_player.PropertyChanged += PlayerStateChanged;
|
||||
PlayerStateChanged(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
#region Playback
|
||||
|
||||
/// <summary>
|
||||
/// Begin playback
|
||||
/// </summary>
|
||||
public void Play() => _player.Play();
|
||||
|
||||
/// <summary>
|
||||
/// Pause current playback
|
||||
/// </summary>
|
||||
public void Pause() => _player.Pause();
|
||||
|
||||
/// <summary>
|
||||
/// Stop current playback
|
||||
/// </summary>
|
||||
public void Stop() => _player.Stop();
|
||||
|
||||
/// <summary>
|
||||
/// Move to the next playable track
|
||||
/// </summary>
|
||||
@@ -193,7 +202,7 @@ namespace RedBookPlayer.GUI
|
||||
public string GenerateDigitString()
|
||||
{
|
||||
// If the disc isn't initialized, return all '-' characters
|
||||
if(_player?.OpticalDisc == null || !_player.OpticalDisc.Initialized)
|
||||
if(_player?.Initialized != true)
|
||||
return string.Empty.PadLeft(20, '-');
|
||||
|
||||
// Otherwise, take the current time into account
|
||||
@@ -201,24 +210,30 @@ namespace RedBookPlayer.GUI
|
||||
|
||||
int[] numbers = new int[]
|
||||
{
|
||||
_player.OpticalDisc.CurrentTrackNumber + 1,
|
||||
_player.OpticalDisc.CurrentTrackIndex,
|
||||
_player.CurrentTrackNumber + 1,
|
||||
_player.CurrentTrackIndex,
|
||||
|
||||
(int)(sectorTime / (75 * 60)),
|
||||
(int)(sectorTime / 75 % 60),
|
||||
(int)(sectorTime % 75),
|
||||
|
||||
_player.OpticalDisc.TotalTracks,
|
||||
_player.OpticalDisc.TotalIndexes,
|
||||
_player.TotalTracks,
|
||||
_player.TotalIndexes,
|
||||
|
||||
(int)(_player.OpticalDisc.TotalTime / (75 * 60)),
|
||||
(int)(_player.OpticalDisc.TotalTime / 75 % 60),
|
||||
(int)(_player.OpticalDisc.TotalTime % 75),
|
||||
(int)(_player.TotalTime / (75 * 60)),
|
||||
(int)(_player.TotalTime / 75 % 60),
|
||||
(int)(_player.TotalTime % 75),
|
||||
};
|
||||
|
||||
return string.Join("", numbers.Select(i => i.ToString().PadLeft(2, '0').Substring(0, 2)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set de-emphasis status
|
||||
/// </summary>
|
||||
/// <param name="apply"></param>
|
||||
public void SetDeEmphasis(bool apply) => _player?.SetDeEmphasis(apply);
|
||||
|
||||
/// <summary>
|
||||
/// Temporarily mute playback
|
||||
/// </summary>
|
||||
@@ -239,30 +254,24 @@ namespace RedBookPlayer.GUI
|
||||
/// <summary>
|
||||
/// Update the UI from the internal player
|
||||
/// </summary>
|
||||
public void UpdateView()
|
||||
private void PlayerStateChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
if(_player?.Initialized != true)
|
||||
return;
|
||||
|
||||
Playing = _player.Playing;
|
||||
ApplyDeEmphasis = _player.ApplyDeEmphasis;
|
||||
Volume = _player.Volume;
|
||||
|
||||
CurrentSector = _player.GetCurrentSectorTime();
|
||||
TotalSectors = _player.OpticalDisc.TotalTime;
|
||||
TotalSectors = _player.TotalTime;
|
||||
|
||||
HiddenTrack = _player.OpticalDisc.TimeOffset > 150;
|
||||
HiddenTrack = _player.HiddenTrack;
|
||||
|
||||
if(_player.OpticalDisc is CompactDisc compactDisc)
|
||||
{
|
||||
QuadChannel = compactDisc.QuadChannel;
|
||||
IsDataTrack = compactDisc.IsDataTrack;
|
||||
CopyAllowed = compactDisc.CopyAllowed;
|
||||
TrackHasEmphasis = compactDisc.TrackHasEmphasis;
|
||||
}
|
||||
else
|
||||
{
|
||||
QuadChannel = false;
|
||||
IsDataTrack = _player.OpticalDisc.TrackType != TrackType.Audio;
|
||||
CopyAllowed = false;
|
||||
TrackHasEmphasis = false;
|
||||
}
|
||||
QuadChannel = _player.QuadChannel;
|
||||
IsDataTrack = _player.IsDataTrack;
|
||||
CopyAllowed = _player.CopyAllowed;
|
||||
TrackHasEmphasis = _player.TrackHasEmphasis;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,68 +1,141 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using Aaru.CommonTypes.Enums;
|
||||
using Aaru.DiscImages;
|
||||
using Aaru.Filters;
|
||||
using ReactiveUI;
|
||||
using RedBookPlayer.Discs;
|
||||
|
||||
namespace RedBookPlayer.Hardware
|
||||
{
|
||||
public class Player
|
||||
public class Player : ReactiveObject
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the player is ready to be used
|
||||
/// </summary>
|
||||
public bool Initialized { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// OpticalDisc object
|
||||
/// </summary>
|
||||
public OpticalDisc OpticalDisc { get; private set; }
|
||||
#region OpticalDisc Passthrough
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the disc is playing
|
||||
/// Current track number
|
||||
/// </summary>
|
||||
public bool? Playing
|
||||
public int CurrentTrackNumber
|
||||
{
|
||||
get => _soundOutput?.Playing;
|
||||
set
|
||||
{
|
||||
if(OpticalDisc == null || !OpticalDisc.Initialized)
|
||||
return;
|
||||
|
||||
// If the playing state has not changed, do nothing
|
||||
if(value == _soundOutput?.Playing)
|
||||
return;
|
||||
|
||||
if(value == true)
|
||||
{
|
||||
_soundOutput.Play();
|
||||
OpticalDisc.SetTotalIndexes();
|
||||
}
|
||||
else if(value == false)
|
||||
{
|
||||
_soundOutput.Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
_soundOutput.Stop();
|
||||
OpticalDisc.LoadFirstTrack();
|
||||
}
|
||||
}
|
||||
get => _currentTrackNumber;
|
||||
private set => this.RaiseAndSetIfChanged(ref _currentTrackNumber, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicate the current playback volume
|
||||
/// Current track index
|
||||
/// </summary>
|
||||
public int Volume
|
||||
public ushort CurrentTrackIndex
|
||||
{
|
||||
get => _soundOutput?.Volume ?? 100;
|
||||
set
|
||||
{
|
||||
if(_soundOutput != null)
|
||||
_soundOutput.Volume = value;
|
||||
}
|
||||
get => _currentTrackIndex;
|
||||
private set => this.RaiseAndSetIfChanged(ref _currentTrackIndex, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current sector number
|
||||
/// </summary>
|
||||
public ulong CurrentSector
|
||||
{
|
||||
get => _currentSector;
|
||||
private set => this.RaiseAndSetIfChanged(ref _currentSector, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents if the disc has a hidden track
|
||||
/// </summary>
|
||||
public bool HiddenTrack
|
||||
{
|
||||
get => _hasHiddenTrack;
|
||||
private set => this.RaiseAndSetIfChanged(ref _hasHiddenTrack, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the 4CH flag [CompactDisc only]
|
||||
/// </summary>
|
||||
public bool QuadChannel
|
||||
{
|
||||
get => _quadChannel;
|
||||
private set => this.RaiseAndSetIfChanged(ref _quadChannel, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the DATA flag [CompactDisc only]
|
||||
/// </summary>
|
||||
public bool IsDataTrack
|
||||
{
|
||||
get => _isDataTrack;
|
||||
private set => this.RaiseAndSetIfChanged(ref _isDataTrack, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the DCP flag [CompactDisc only]
|
||||
/// </summary>
|
||||
public bool CopyAllowed
|
||||
{
|
||||
get => _copyAllowed;
|
||||
private set => this.RaiseAndSetIfChanged(ref _copyAllowed, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the PRE flag [CompactDisc only]
|
||||
/// </summary>
|
||||
public bool TrackHasEmphasis
|
||||
{
|
||||
get => _trackHasEmphasis;
|
||||
private set => this.RaiseAndSetIfChanged(ref _trackHasEmphasis, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents the total tracks on the disc
|
||||
/// </summary>
|
||||
public int TotalTracks => _opticalDisc.TotalTracks;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the total indices on the disc
|
||||
/// </summary>
|
||||
public int TotalIndexes => _opticalDisc.TotalIndexes;
|
||||
|
||||
/// <summary>
|
||||
/// Total sectors in the image
|
||||
/// </summary>
|
||||
public ulong TotalSectors => _opticalDisc.TotalSectors;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the time adjustment offset for the disc
|
||||
/// </summary>
|
||||
public ulong TimeOffset => _opticalDisc.TimeOffset;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the total playing time for the disc
|
||||
/// </summary>
|
||||
public ulong TotalTime => _opticalDisc.TotalTime;
|
||||
|
||||
private int _currentTrackNumber;
|
||||
private ushort _currentTrackIndex;
|
||||
private ulong _currentSector;
|
||||
|
||||
private bool _hasHiddenTrack;
|
||||
private bool _quadChannel;
|
||||
private bool _isDataTrack;
|
||||
private bool _copyAllowed;
|
||||
private bool _trackHasEmphasis;
|
||||
|
||||
#endregion
|
||||
|
||||
#region SoundOutput Passthrough
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the output is playing
|
||||
/// </summary>
|
||||
public bool? Playing
|
||||
{
|
||||
get => _playing;
|
||||
private set => this.RaiseAndSetIfChanged(ref _playing, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -70,10 +143,23 @@ namespace RedBookPlayer.Hardware
|
||||
/// </summary>
|
||||
public bool ApplyDeEmphasis
|
||||
{
|
||||
get => _soundOutput?.ApplyDeEmphasis ?? false;
|
||||
set => _soundOutput?.SetDeEmphasis(value);
|
||||
get => _applyDeEmphasis;
|
||||
private set => this.RaiseAndSetIfChanged(ref _applyDeEmphasis, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current playback volume
|
||||
/// </summary>
|
||||
public int Volume
|
||||
{
|
||||
get => _volume;
|
||||
set => this.RaiseAndSetIfChanged(ref _volume, value);
|
||||
}
|
||||
|
||||
private bool? _playing;
|
||||
private bool _applyDeEmphasis;
|
||||
private int _volume;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private State Variables
|
||||
@@ -81,7 +167,12 @@ namespace RedBookPlayer.Hardware
|
||||
/// <summary>
|
||||
/// Sound output handling class
|
||||
/// </summary>
|
||||
public SoundOutput _soundOutput;
|
||||
private readonly SoundOutput _soundOutput;
|
||||
|
||||
/// <summary>
|
||||
/// OpticalDisc object
|
||||
/// </summary>
|
||||
private readonly OpticalDisc _opticalDisc;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -96,8 +187,8 @@ namespace RedBookPlayer.Hardware
|
||||
// Set the internal state for initialization
|
||||
Initialized = false;
|
||||
_soundOutput = new SoundOutput();
|
||||
_soundOutput.ApplyDeEmphasis = false;
|
||||
OpticalDisc = null;
|
||||
_soundOutput.SetDeEmphasis(false);
|
||||
_opticalDisc = null;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -112,7 +203,7 @@ namespace RedBookPlayer.Hardware
|
||||
image.Open(filter);
|
||||
|
||||
// Generate and instantiate the disc
|
||||
OpticalDisc = OpticalDiscFactory.GenerateFromImage(image, autoPlay);
|
||||
_opticalDisc = OpticalDiscFactory.GenerateFromImage(image, autoPlay);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -121,32 +212,88 @@ namespace RedBookPlayer.Hardware
|
||||
}
|
||||
|
||||
// Initialize the sound output
|
||||
_soundOutput.Init(OpticalDisc, autoPlay, defaultVolume);
|
||||
_soundOutput.Init(_opticalDisc, autoPlay, defaultVolume);
|
||||
if(_soundOutput == null || !_soundOutput.Initialized)
|
||||
return;
|
||||
|
||||
// Add event handling for the sound output
|
||||
_soundOutput.PropertyChanged += SoundOutputStateChanged;
|
||||
|
||||
// Mark the player as ready
|
||||
Initialized = true;
|
||||
SetDiscInformation();
|
||||
}
|
||||
|
||||
#region Playback
|
||||
|
||||
/// <summary>
|
||||
/// Begin playback
|
||||
/// </summary>
|
||||
public void Play()
|
||||
{
|
||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||
return;
|
||||
else if(_soundOutput == null)
|
||||
return;
|
||||
else if(_soundOutput.Playing)
|
||||
return;
|
||||
|
||||
_soundOutput.Play();
|
||||
_opticalDisc.SetTotalIndexes();
|
||||
Playing = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause current playback
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||
return;
|
||||
else if(_soundOutput == null)
|
||||
return;
|
||||
else if(!_soundOutput.Playing)
|
||||
return;
|
||||
|
||||
_soundOutput?.Stop();
|
||||
Playing = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop current playback
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||
return;
|
||||
else if(_soundOutput == null)
|
||||
return;
|
||||
else if(!_soundOutput.Playing)
|
||||
return;
|
||||
|
||||
_soundOutput?.Stop();
|
||||
_opticalDisc.LoadFirstTrack();
|
||||
Playing = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Move to the next playable track
|
||||
/// </summary>
|
||||
public void NextTrack()
|
||||
{
|
||||
if(OpticalDisc == null || !OpticalDisc.Initialized)
|
||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||
return;
|
||||
|
||||
bool? wasPlaying = Playing;
|
||||
if(wasPlaying == true) Playing = false;
|
||||
if(wasPlaying == true) Pause();
|
||||
|
||||
OpticalDisc.NextTrack();
|
||||
if(OpticalDisc is CompactDisc compactDisc)
|
||||
_soundOutput.ApplyDeEmphasis = compactDisc.TrackHasEmphasis;
|
||||
_opticalDisc.NextTrack();
|
||||
if(_opticalDisc is CompactDisc compactDisc)
|
||||
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
|
||||
|
||||
if(wasPlaying == true) Playing = true;
|
||||
SetDiscInformation();
|
||||
|
||||
if(wasPlaying == true) Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -154,17 +301,19 @@ namespace RedBookPlayer.Hardware
|
||||
/// </summary>
|
||||
public void PreviousTrack()
|
||||
{
|
||||
if(OpticalDisc == null || !OpticalDisc.Initialized)
|
||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||
return;
|
||||
|
||||
bool? wasPlaying = Playing;
|
||||
if(wasPlaying == true) Playing = false;
|
||||
if(wasPlaying == true) Pause();
|
||||
|
||||
OpticalDisc.PreviousTrack();
|
||||
if(OpticalDisc is CompactDisc compactDisc)
|
||||
_soundOutput.ApplyDeEmphasis = compactDisc.TrackHasEmphasis;
|
||||
_opticalDisc.PreviousTrack();
|
||||
if(_opticalDisc is CompactDisc compactDisc)
|
||||
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
|
||||
|
||||
if(wasPlaying == true) Playing = true;
|
||||
SetDiscInformation();
|
||||
|
||||
if(wasPlaying == true) Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -173,17 +322,19 @@ namespace RedBookPlayer.Hardware
|
||||
/// <param name="changeTrack">True if index changes can trigger a track change, false otherwise</param>
|
||||
public void NextIndex(bool changeTrack)
|
||||
{
|
||||
if(OpticalDisc == null || !OpticalDisc.Initialized)
|
||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||
return;
|
||||
|
||||
bool? wasPlaying = Playing;
|
||||
if(wasPlaying == true) Playing = false;
|
||||
if(wasPlaying == true) Pause();
|
||||
|
||||
OpticalDisc.NextIndex(changeTrack);
|
||||
if(OpticalDisc is CompactDisc compactDisc)
|
||||
_soundOutput.ApplyDeEmphasis = compactDisc.TrackHasEmphasis;
|
||||
_opticalDisc.NextIndex(changeTrack);
|
||||
if(_opticalDisc is CompactDisc compactDisc)
|
||||
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
|
||||
|
||||
if(wasPlaying == true) Playing = true;
|
||||
SetDiscInformation();
|
||||
|
||||
if(wasPlaying == true) Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -192,17 +343,19 @@ namespace RedBookPlayer.Hardware
|
||||
/// <param name="changeTrack">True if index changes can trigger a track change, false otherwise</param>
|
||||
public void PreviousIndex(bool changeTrack)
|
||||
{
|
||||
if(OpticalDisc == null || !OpticalDisc.Initialized)
|
||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||
return;
|
||||
|
||||
bool? wasPlaying = Playing;
|
||||
if(wasPlaying == true) Playing = false;
|
||||
if(wasPlaying == true) Pause();
|
||||
|
||||
OpticalDisc.PreviousIndex(changeTrack);
|
||||
if(OpticalDisc is CompactDisc compactDisc)
|
||||
_soundOutput.ApplyDeEmphasis = compactDisc.TrackHasEmphasis;
|
||||
_opticalDisc.PreviousIndex(changeTrack);
|
||||
if(_opticalDisc is CompactDisc compactDisc)
|
||||
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
|
||||
|
||||
if(wasPlaying == true) Playing = true;
|
||||
SetDiscInformation();
|
||||
|
||||
if(wasPlaying == true) Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -210,10 +363,11 @@ namespace RedBookPlayer.Hardware
|
||||
/// </summary>
|
||||
public void FastForward()
|
||||
{
|
||||
if(OpticalDisc == null || !OpticalDisc.Initialized)
|
||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||
return;
|
||||
|
||||
OpticalDisc.CurrentSector = Math.Min(OpticalDisc.TotalSectors, OpticalDisc.CurrentSector + 75);
|
||||
_opticalDisc.CurrentSector = Math.Min(_opticalDisc.TotalSectors, _opticalDisc.CurrentSector + 75);
|
||||
SetDiscInformation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -221,11 +375,13 @@ namespace RedBookPlayer.Hardware
|
||||
/// </summary>
|
||||
public void Rewind()
|
||||
{
|
||||
if(OpticalDisc == null || !OpticalDisc.Initialized)
|
||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||
return;
|
||||
|
||||
if(OpticalDisc.CurrentSector >= 75)
|
||||
OpticalDisc.CurrentSector -= 75;
|
||||
if(_opticalDisc.CurrentSector >= 75)
|
||||
_opticalDisc.CurrentSector -= 75;
|
||||
|
||||
SetDiscInformation();
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -238,21 +394,58 @@ namespace RedBookPlayer.Hardware
|
||||
/// <returns>ulong representing the current sector time</returns>
|
||||
public ulong GetCurrentSectorTime()
|
||||
{
|
||||
ulong sectorTime = OpticalDisc.CurrentSector;
|
||||
if (OpticalDisc.SectionStartSector != 0)
|
||||
sectorTime -= OpticalDisc.SectionStartSector;
|
||||
ulong sectorTime = _opticalDisc.CurrentSector;
|
||||
if (_opticalDisc.SectionStartSector != 0)
|
||||
sectorTime -= _opticalDisc.SectionStartSector;
|
||||
else
|
||||
sectorTime += OpticalDisc.TimeOffset;
|
||||
sectorTime += _opticalDisc.TimeOffset;
|
||||
|
||||
return sectorTime;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set if de-emphasis should be applied
|
||||
/// Set de-emphasis status
|
||||
/// </summary>
|
||||
/// <param name="apply">True to enable, false to disable</param>
|
||||
/// <param name="apply"></param>
|
||||
public void SetDeEmphasis(bool apply) => _soundOutput?.SetDeEmphasis(apply);
|
||||
|
||||
/// <summary>
|
||||
/// Update the player from the current SoundOutput
|
||||
/// </summary>
|
||||
private void SoundOutputStateChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
Playing = _soundOutput.Playing;
|
||||
ApplyDeEmphasis = _soundOutput.ApplyDeEmphasis;
|
||||
//Volume = _soundOutput.Volume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set all current disc information
|
||||
/// </summary>
|
||||
private void SetDiscInformation()
|
||||
{
|
||||
CurrentTrackNumber = _opticalDisc.CurrentTrackNumber;
|
||||
CurrentTrackIndex = _opticalDisc.CurrentTrackIndex;
|
||||
CurrentSector = _opticalDisc.CurrentSector;
|
||||
|
||||
HiddenTrack = TimeOffset > 150;
|
||||
|
||||
if(_opticalDisc is CompactDisc compactDisc)
|
||||
{
|
||||
QuadChannel = compactDisc.QuadChannel;
|
||||
IsDataTrack = compactDisc.IsDataTrack;
|
||||
CopyAllowed = compactDisc.CopyAllowed;
|
||||
TrackHasEmphasis = compactDisc.TrackHasEmphasis;
|
||||
}
|
||||
else
|
||||
{
|
||||
QuadChannel = false;
|
||||
IsDataTrack = _opticalDisc.TrackType != TrackType.Audio;
|
||||
CopyAllowed = false;
|
||||
TrackHasEmphasis = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -4,11 +4,12 @@ using System.Threading.Tasks;
|
||||
using CSCore.SoundOut;
|
||||
using NWaves.Audio;
|
||||
using NWaves.Filters.BiQuad;
|
||||
using ReactiveUI;
|
||||
using RedBookPlayer.Discs;
|
||||
|
||||
namespace RedBookPlayer.Hardware
|
||||
{
|
||||
public class SoundOutput
|
||||
public class SoundOutput : ReactiveObject
|
||||
{
|
||||
#region Public Fields
|
||||
|
||||
@@ -17,15 +18,23 @@ namespace RedBookPlayer.Hardware
|
||||
/// </summary>
|
||||
public bool Initialized { get; private set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if de-emphasis should be applied
|
||||
/// </summary>
|
||||
public bool ApplyDeEmphasis { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// Indicate if the output is playing
|
||||
/// </summary>
|
||||
public bool Playing => _soundOut.PlaybackState == PlaybackState.Playing;
|
||||
public bool Playing
|
||||
{
|
||||
get => _playing;
|
||||
private set => this.RaiseAndSetIfChanged(ref _playing, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates if de-emphasis should be applied
|
||||
/// </summary>
|
||||
public bool ApplyDeEmphasis
|
||||
{
|
||||
get => _applyDeEmphasis;
|
||||
private set => this.RaiseAndSetIfChanged(ref _applyDeEmphasis, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Current playback volume
|
||||
@@ -35,24 +44,24 @@ namespace RedBookPlayer.Hardware
|
||||
get => _volume;
|
||||
set
|
||||
{
|
||||
int tempVolume = value;
|
||||
if(value > 100)
|
||||
_volume = 100;
|
||||
tempVolume = 100;
|
||||
else if(value < 0)
|
||||
_volume = 0;
|
||||
else
|
||||
_volume = value;
|
||||
tempVolume = 0;
|
||||
|
||||
this.RaiseAndSetIfChanged(ref _volume, tempVolume);
|
||||
}
|
||||
}
|
||||
|
||||
private bool _playing;
|
||||
private bool _applyDeEmphasis;
|
||||
private int _volume;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private State Variables
|
||||
|
||||
/// <summary>
|
||||
/// Current position in the sector
|
||||
/// </summary>
|
||||
private int _currentSectorReadPosition = 0;
|
||||
|
||||
/// <summary>
|
||||
/// OpticalDisc from the parent player for easy access
|
||||
/// </summary>
|
||||
@@ -61,11 +70,6 @@ namespace RedBookPlayer.Hardware
|
||||
/// </remarks>
|
||||
private OpticalDisc _opticalDisc;
|
||||
|
||||
/// <summary>
|
||||
/// Internal value for the volume
|
||||
/// </summary>
|
||||
private int _volume;
|
||||
|
||||
/// <summary>
|
||||
/// Data provider for sound output
|
||||
/// </summary>
|
||||
@@ -86,6 +90,11 @@ namespace RedBookPlayer.Hardware
|
||||
/// </summary>
|
||||
private BiQuadFilter _deEmphasisFilterRight;
|
||||
|
||||
/// <summary>
|
||||
/// Current position in the sector
|
||||
/// </summary>
|
||||
private int _currentSectorReadPosition = 0;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object for reading track data
|
||||
/// </summary>
|
||||
@@ -254,22 +263,45 @@ namespace RedBookPlayer.Hardware
|
||||
/// <summary>
|
||||
/// Start audio playback
|
||||
/// </summary>
|
||||
public void Play() => _soundOut.Play();
|
||||
public void Play()
|
||||
{
|
||||
if (_soundOut.PlaybackState != PlaybackState.Playing)
|
||||
_soundOut.Play();
|
||||
|
||||
Playing = _soundOut.PlaybackState == PlaybackState.Playing;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pause audio playback
|
||||
/// </summary>
|
||||
public void Pause()
|
||||
{
|
||||
if(_soundOut.PlaybackState != PlaybackState.Paused)
|
||||
_soundOut.Pause();
|
||||
|
||||
Playing = _soundOut.PlaybackState == PlaybackState.Playing;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop audio playback
|
||||
/// </summary>
|
||||
public void Stop() => _soundOut.Stop();
|
||||
public void Stop()
|
||||
{
|
||||
if(_soundOut.PlaybackState != PlaybackState.Stopped)
|
||||
_soundOut.Stop();
|
||||
|
||||
Playing = _soundOut.PlaybackState == PlaybackState.Playing;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Helpers
|
||||
|
||||
/// <summary>
|
||||
/// Toggle de-emphasis processing
|
||||
/// Set de-emphasis status
|
||||
/// </summary>
|
||||
/// <param name="enable">True to apply de-emphasis, false otherwise</param>
|
||||
public void SetDeEmphasis(bool enable) => ApplyDeEmphasis = enable;
|
||||
/// <param name="apply"></param>
|
||||
public void SetDeEmphasis(bool apply) => ApplyDeEmphasis = apply;
|
||||
|
||||
/// <summary>
|
||||
/// Sets or resets the de-emphasis filters
|
||||
|
||||
Reference in New Issue
Block a user