From be2c704654a043218fbeb7959abf101a0ab8f61a Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Sun, 4 Jul 2021 23:17:30 -0700 Subject: [PATCH] Make SoundOutput have events --- RedBookPlayer/GUI/PlayerView.xaml.cs | 22 +- RedBookPlayer/GUI/PlayerViewModel.cs | 119 +++++---- RedBookPlayer/Hardware/Player.cs | 361 ++++++++++++++++++++------ RedBookPlayer/Hardware/SoundOutput.cs | 84 ++++-- 4 files changed, 412 insertions(+), 174 deletions(-) diff --git a/RedBookPlayer/GUI/PlayerView.xaml.cs b/RedBookPlayer/GUI/PlayerView.xaml.cs index 7dabeae..bdb1ecc 100644 --- a/RedBookPlayer/GUI/PlayerView.xaml.cs +++ b/RedBookPlayer/GUI/PlayerView.xaml.cs @@ -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 } diff --git a/RedBookPlayer/GUI/PlayerViewModel.cs b/RedBookPlayer/GUI/PlayerViewModel.cs index 4030ba5..4162012 100644 --- a/RedBookPlayer/GUI/PlayerViewModel.cs +++ b/RedBookPlayer/GUI/PlayerViewModel.cs @@ -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 /// private int? _lastVolume = null; - #region Player Status + #region Player Passthrough /// /// Indicate if the model is ready to be used @@ -26,29 +25,12 @@ namespace RedBookPlayer.GUI public bool Initialized => _player?.Initialized ?? false; /// - /// Indicate the player state + /// Indicate if the output is playing /// public bool? Playing { - get => _player?.Playing ?? false; - set - { - if(_player != null) - _player.Playing = value; - } - } - - /// - /// Indicate the current playback volume - /// - public int Volume - { - get => _player?.Volume ?? 100; - set - { - if(_player != null) - _player.Volume = value; - } + get => _playing; + private set => this.RaiseAndSetIfChanged(ref _playing, value); } /// @@ -56,14 +38,23 @@ namespace RedBookPlayer.GUI /// public bool ApplyDeEmphasis { - get => _player?.ApplyDeEmphasis ?? false; - set - { - if(_player != null) - _player.ApplyDeEmphasis = value; - } + get => _applyDeEmphasis; + private set => this.RaiseAndSetIfChanged(ref _applyDeEmphasis, value); } + /// + /// Current playback volume + /// + 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 + /// + /// Begin playback + /// + public void Play() => _player.Play(); + + /// + /// Pause current playback + /// + public void Pause() => _player.Pause(); + + /// + /// Stop current playback + /// + public void Stop() => _player.Stop(); + /// /// Move to the next playable track /// @@ -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))); } + /// + /// Set de-emphasis status + /// + /// + public void SetDeEmphasis(bool apply) => _player?.SetDeEmphasis(apply); + /// /// Temporarily mute playback /// @@ -239,30 +254,24 @@ namespace RedBookPlayer.GUI /// /// Update the UI from the internal player /// - 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 diff --git a/RedBookPlayer/Hardware/Player.cs b/RedBookPlayer/Hardware/Player.cs index 2850f89..3c72fa6 100644 --- a/RedBookPlayer/Hardware/Player.cs +++ b/RedBookPlayer/Hardware/Player.cs @@ -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 - /// /// Indicate if the player is ready to be used /// public bool Initialized { get; private set; } = false; - /// - /// OpticalDisc object - /// - public OpticalDisc OpticalDisc { get; private set; } + #region OpticalDisc Passthrough /// - /// Indicate if the disc is playing + /// Current track number /// - 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); } /// - /// Indicate the current playback volume + /// Current track index /// - 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); + } + + /// + /// Current sector number + /// + public ulong CurrentSector + { + get => _currentSector; + private set => this.RaiseAndSetIfChanged(ref _currentSector, value); + } + + /// + /// Represents if the disc has a hidden track + /// + public bool HiddenTrack + { + get => _hasHiddenTrack; + private set => this.RaiseAndSetIfChanged(ref _hasHiddenTrack, value); + } + + /// + /// Represents the 4CH flag [CompactDisc only] + /// + public bool QuadChannel + { + get => _quadChannel; + private set => this.RaiseAndSetIfChanged(ref _quadChannel, value); + } + + /// + /// Represents the DATA flag [CompactDisc only] + /// + public bool IsDataTrack + { + get => _isDataTrack; + private set => this.RaiseAndSetIfChanged(ref _isDataTrack, value); + } + + /// + /// Represents the DCP flag [CompactDisc only] + /// + public bool CopyAllowed + { + get => _copyAllowed; + private set => this.RaiseAndSetIfChanged(ref _copyAllowed, value); + } + + /// + /// Represents the PRE flag [CompactDisc only] + /// + public bool TrackHasEmphasis + { + get => _trackHasEmphasis; + private set => this.RaiseAndSetIfChanged(ref _trackHasEmphasis, value); + } + + /// + /// Represents the total tracks on the disc + /// + public int TotalTracks => _opticalDisc.TotalTracks; + + /// + /// Represents the total indices on the disc + /// + public int TotalIndexes => _opticalDisc.TotalIndexes; + + /// + /// Total sectors in the image + /// + public ulong TotalSectors => _opticalDisc.TotalSectors; + + /// + /// Represents the time adjustment offset for the disc + /// + public ulong TimeOffset => _opticalDisc.TimeOffset; + + /// + /// Represents the total playing time for the disc + /// + 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 + + /// + /// Indicate if the output is playing + /// + public bool? Playing + { + get => _playing; + private set => this.RaiseAndSetIfChanged(ref _playing, value); } /// @@ -70,10 +143,23 @@ namespace RedBookPlayer.Hardware /// public bool ApplyDeEmphasis { - get => _soundOutput?.ApplyDeEmphasis ?? false; - set => _soundOutput?.SetDeEmphasis(value); + get => _applyDeEmphasis; + private set => this.RaiseAndSetIfChanged(ref _applyDeEmphasis, value); } + /// + /// Current playback volume + /// + 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 /// /// Sound output handling class /// - public SoundOutput _soundOutput; + private readonly SoundOutput _soundOutput; + + /// + /// OpticalDisc object + /// + 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 + /// + /// Begin playback + /// + 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; + } + + /// + /// Pause current playback + /// + public void Pause() + { + if(_opticalDisc == null || !_opticalDisc.Initialized) + return; + else if(_soundOutput == null) + return; + else if(!_soundOutput.Playing) + return; + + _soundOutput?.Stop(); + Playing = false; + } + + /// + /// Stop current playback + /// + 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; + } + /// /// Move to the next playable track /// 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(); } /// @@ -154,17 +301,19 @@ namespace RedBookPlayer.Hardware /// 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(); } /// @@ -173,17 +322,19 @@ namespace RedBookPlayer.Hardware /// True if index changes can trigger a track change, false otherwise 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(); } /// @@ -192,17 +343,19 @@ namespace RedBookPlayer.Hardware /// True if index changes can trigger a track change, false otherwise 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(); } /// @@ -210,10 +363,11 @@ namespace RedBookPlayer.Hardware /// 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(); } /// @@ -221,11 +375,13 @@ namespace RedBookPlayer.Hardware /// 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 /// ulong representing the current sector time 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; } /// - /// Set if de-emphasis should be applied + /// Set de-emphasis status /// - /// True to enable, false to disable + /// public void SetDeEmphasis(bool apply) => _soundOutput?.SetDeEmphasis(apply); + /// + /// Update the player from the current SoundOutput + /// + private void SoundOutputStateChanged(object sender, PropertyChangedEventArgs e) + { + Playing = _soundOutput.Playing; + ApplyDeEmphasis = _soundOutput.ApplyDeEmphasis; + //Volume = _soundOutput.Volume; + } + + /// + /// Set all current disc information + /// + 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 } } \ No newline at end of file diff --git a/RedBookPlayer/Hardware/SoundOutput.cs b/RedBookPlayer/Hardware/SoundOutput.cs index d31b68c..d97466e 100644 --- a/RedBookPlayer/Hardware/SoundOutput.cs +++ b/RedBookPlayer/Hardware/SoundOutput.cs @@ -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 /// public bool Initialized { get; private set; } = false; - /// - /// Indicates if de-emphasis should be applied - /// - public bool ApplyDeEmphasis { get; set; } = false; - /// /// Indicate if the output is playing /// - public bool Playing => _soundOut.PlaybackState == PlaybackState.Playing; + public bool Playing + { + get => _playing; + private set => this.RaiseAndSetIfChanged(ref _playing, value); + } + + /// + /// Indicates if de-emphasis should be applied + /// + public bool ApplyDeEmphasis + { + get => _applyDeEmphasis; + private set => this.RaiseAndSetIfChanged(ref _applyDeEmphasis, value); + } /// /// 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 - /// - /// Current position in the sector - /// - private int _currentSectorReadPosition = 0; - /// /// OpticalDisc from the parent player for easy access /// @@ -61,11 +70,6 @@ namespace RedBookPlayer.Hardware /// private OpticalDisc _opticalDisc; - /// - /// Internal value for the volume - /// - private int _volume; - /// /// Data provider for sound output /// @@ -86,6 +90,11 @@ namespace RedBookPlayer.Hardware /// private BiQuadFilter _deEmphasisFilterRight; + /// + /// Current position in the sector + /// + private int _currentSectorReadPosition = 0; + /// /// Lock object for reading track data /// @@ -254,22 +263,45 @@ namespace RedBookPlayer.Hardware /// /// Start audio playback /// - public void Play() => _soundOut.Play(); + public void Play() + { + if (_soundOut.PlaybackState != PlaybackState.Playing) + _soundOut.Play(); + + Playing = _soundOut.PlaybackState == PlaybackState.Playing; + } + + /// + /// Pause audio playback + /// + public void Pause() + { + if(_soundOut.PlaybackState != PlaybackState.Paused) + _soundOut.Pause(); + + Playing = _soundOut.PlaybackState == PlaybackState.Playing; + } /// /// Stop audio playback /// - public void Stop() => _soundOut.Stop(); + public void Stop() + { + if(_soundOut.PlaybackState != PlaybackState.Stopped) + _soundOut.Stop(); + + Playing = _soundOut.PlaybackState == PlaybackState.Playing; + } #endregion #region Helpers /// - /// Toggle de-emphasis processing + /// Set de-emphasis status /// - /// True to apply de-emphasis, false otherwise - public void SetDeEmphasis(bool enable) => ApplyDeEmphasis = enable; + /// + public void SetDeEmphasis(bool apply) => ApplyDeEmphasis = apply; /// /// Sets or resets the de-emphasis filters