diff --git a/RedBookPlayer/Discs/CompactDisc.cs b/RedBookPlayer/Discs/CompactDisc.cs index 21e8fc8..62d8728 100644 --- a/RedBookPlayer/Discs/CompactDisc.cs +++ b/RedBookPlayer/Discs/CompactDisc.cs @@ -6,11 +6,12 @@ using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; using Aaru.Decoders.CD; using Aaru.Helpers; +using ReactiveUI; using static Aaru.Decoders.CD.FullTOC; namespace RedBookPlayer.Discs { - public class CompactDisc : OpticalDisc + public class CompactDisc : OpticalDisc, IReactiveObject { #region Public Fields @@ -26,7 +27,7 @@ namespace RedBookPlayer.Discs // Cache the value and the current track number int cachedValue = value; - int cachedTrackNumber = _currentTrackNumber; + int cachedTrackNumber; // Check if we're incrementing or decrementing the track bool increment = cachedValue >= _currentTrackNumber; @@ -39,10 +40,10 @@ namespace RedBookPlayer.Discs else if(cachedValue < 0) cachedValue = _image.Tracks.Count - 1; - _currentTrackNumber = cachedValue; + cachedTrackNumber = cachedValue; // Cache the current track for easy access - Track track = _image.Tracks[_currentTrackNumber]; + Track track = _image.Tracks[cachedTrackNumber]; // Set track flags from subchannel data, if possible SetTrackFlags(track); @@ -52,7 +53,7 @@ namespace RedBookPlayer.Discs // If the track is playable, just return if(TrackType == TrackType.Audio || App.Settings.PlayDataTracks) - return; + break; // If we're not playing the track, skip if(increment) @@ -60,7 +61,9 @@ namespace RedBookPlayer.Discs else cachedValue--; } - while(cachedValue != cachedTrackNumber); + while(cachedValue != _currentTrackNumber); + + this.RaiseAndSetIfChanged(ref _currentTrackNumber, cachedTrackNumber); } } @@ -78,12 +81,13 @@ namespace RedBookPlayer.Discs Track track = _image.Tracks[CurrentTrackNumber]; // Ensure that the value is valid, wrapping around if necessary + ushort fixedValue = value; if(value > track.Indexes.Keys.Max()) - _currentTrackIndex = track.Indexes.Keys.Min(); + fixedValue = track.Indexes.Keys.Min(); else if(value < track.Indexes.Keys.Min()) - _currentTrackIndex = track.Indexes.Keys.Max(); - else - _currentTrackIndex = value; + fixedValue = track.Indexes.Keys.Max(); + + this.RaiseAndSetIfChanged(ref _currentTrackIndex, fixedValue); // Set new index-specific data SectionStartSector = (ulong)track.Indexes[CurrentTrackIndex]; @@ -104,7 +108,7 @@ namespace RedBookPlayer.Discs // Cache the current track for easy access Track track = _image.Tracks[CurrentTrackNumber]; - _currentSector = value; + this.RaiseAndSetIfChanged(ref _currentSector, value); if((CurrentTrackNumber < _image.Tracks.Count - 1 && CurrentSector >= _image.Tracks[CurrentTrackNumber + 1].TrackStartSector) || (CurrentTrackNumber > 0 && CurrentSector < track.TrackStartSector)) @@ -135,22 +139,43 @@ namespace RedBookPlayer.Discs /// /// Represents the 4CH flag /// - public bool QuadChannel { get; private set; } = false; + public bool QuadChannel + { + get => _quadChannel; + private set => this.RaiseAndSetIfChanged(ref _quadChannel, value); + } /// /// Represents the DATA flag /// - public bool IsDataTrack => TrackType != TrackType.Audio; + public bool IsDataTrack + { + get => _isDataTrack; + private set => this.RaiseAndSetIfChanged(ref _isDataTrack, value); + } /// /// Represents the DCP flag /// - public bool CopyAllowed { get; private set; } = false; + public bool CopyAllowed + { + get => _copyAllowed; + private set => this.RaiseAndSetIfChanged(ref _copyAllowed, value); + } /// /// Represents the PRE flag /// - public bool TrackHasEmphasis { get; private set; } = false; + public bool TrackHasEmphasis + { + get => _trackHasEmphasis; + private set => this.RaiseAndSetIfChanged(ref _trackHasEmphasis, value); + } + + private bool _quadChannel; + private bool _isDataTrack; + private bool _copyAllowed; + private bool _trackHasEmphasis; #endregion @@ -369,8 +394,9 @@ namespace RedBookPlayer.Discs /// Track object to read from private void SetDefaultTrackFlags(Track track) { - QuadChannel = false; TrackType = track.TrackType; + QuadChannel = false; + IsDataTrack = track.TrackType != TrackType.Audio; CopyAllowed = false; TrackHasEmphasis = false; } @@ -390,9 +416,11 @@ namespace RedBookPlayer.Discs byte flags = (byte)(descriptor.CONTROL & 0x0D); TrackHasEmphasis = (flags & (byte)TocControl.TwoChanPreEmph) == (byte)TocControl.TwoChanPreEmph; CopyAllowed = (flags & (byte)TocControl.CopyPermissionMask) == (byte)TocControl.CopyPermissionMask; - TrackType = (flags & (byte)TocControl.DataTrack) == (byte)TocControl.DataTrack ? TrackType.Data : TrackType.Audio; + IsDataTrack = (flags & (byte)TocControl.DataTrack) == (byte)TocControl.DataTrack; QuadChannel = (flags & (byte)TocControl.FourChanNoPreEmph) == (byte)TocControl.FourChanNoPreEmph; + TrackType = IsDataTrack ? TrackType.Data : TrackType.Audio; + return; } catch(Exception) diff --git a/RedBookPlayer/Discs/OpticalDisc.cs b/RedBookPlayer/Discs/OpticalDisc.cs index 817c626..831deed 100644 --- a/RedBookPlayer/Discs/OpticalDisc.cs +++ b/RedBookPlayer/Discs/OpticalDisc.cs @@ -1,9 +1,10 @@ using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Interfaces; +using ReactiveUI; namespace RedBookPlayer.Discs { - public abstract class OpticalDisc + public abstract class OpticalDisc : ReactiveObject { #region Public Fields @@ -55,7 +56,7 @@ namespace RedBookPlayer.Discs /// /// Total sectors in the image /// - public ulong TotalSectors => _image.Info.Sectors; + public ulong TotalSectors => _image?.Info.Sectors ?? 0; /// /// Represents the time adjustment offset for the disc diff --git a/RedBookPlayer/GUI/PlayerViewModel.cs b/RedBookPlayer/GUI/PlayerViewModel.cs index 4162012..8714d48 100644 --- a/RedBookPlayer/GUI/PlayerViewModel.cs +++ b/RedBookPlayer/GUI/PlayerViewModel.cs @@ -19,6 +19,119 @@ namespace RedBookPlayer.GUI #region Player Passthrough + #region OpticalDisc Passthrough + + /// + /// Current track number + /// + public int CurrentTrackNumber + { + get => _currentTrackNumber; + private set => this.RaiseAndSetIfChanged(ref _currentTrackNumber, value); + } + + /// + /// Current track index + /// + public ushort CurrentTrackIndex + { + 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 => _player.TotalTracks; + + /// + /// Represents the total indices on the disc + /// + public int TotalIndexes => _player.TotalIndexes; + + /// + /// Total sectors in the image + /// + public ulong TotalSectors => _player.TotalSectors; + + /// + /// Represents the time adjustment offset for the disc + /// + public ulong TimeOffset => _player.TimeOffset; + + /// + /// Represents the total playing time for the disc + /// + public ulong TotalTime => _player.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 model is ready to be used /// @@ -57,69 +170,6 @@ namespace RedBookPlayer.GUI #endregion - #region Model-Provided Playback Information - - private ulong _currentSector; - public ulong CurrentSector - { - get => _currentSector; - set => this.RaiseAndSetIfChanged(ref _currentSector, value); - } - - public int CurrentFrame => (int)(_currentSector / (75 * 60)); - public int CurrentSecond => (int)(_currentSector / 75 % 60); - public int CurrentMinute => (int)(_currentSector % 75); - - private ulong _totalSectors; - public ulong TotalSectors - { - get => _totalSectors; - set => this.RaiseAndSetIfChanged(ref _totalSectors, value); - } - - public int TotalFrames => (int)(_totalSectors / (75 * 60)); - public int TotalSeconds => (int)(_totalSectors / 75 % 60); - public int TotalMinutes => (int)(_totalSectors % 75); - - #endregion - - #region Disc Flags - - private bool _quadChannel; - public bool QuadChannel - { - get => _quadChannel; - set => this.RaiseAndSetIfChanged(ref _quadChannel, value); - } - - private bool _isDataTrack; - public bool IsDataTrack - { - get => _isDataTrack; - set => this.RaiseAndSetIfChanged(ref _isDataTrack, value); - } - - private bool _copyAllowed; - public bool CopyAllowed - { - get => _copyAllowed; - set => this.RaiseAndSetIfChanged(ref _copyAllowed, value); - } - - private bool _trackHasEmphasis; - public bool TrackHasEmphasis - { - get => _trackHasEmphasis; - set => this.RaiseAndSetIfChanged(ref _trackHasEmphasis, value); - } - - private bool _hiddenTrack; - public bool HiddenTrack - { - get => _hiddenTrack; - set => this.RaiseAndSetIfChanged(ref _hiddenTrack, value); - } - #endregion /// @@ -199,6 +249,9 @@ namespace RedBookPlayer.GUI /// Generate the digit string to be interpreted by the frontend /// /// String representing the digits for the frontend + /// + /// TODO: The model shouldn't care about this + /// public string GenerateDigitString() { // If the disc isn't initialized, return all '-' characters @@ -259,12 +312,9 @@ namespace RedBookPlayer.GUI if(_player?.Initialized != true) return; - Playing = _player.Playing; - ApplyDeEmphasis = _player.ApplyDeEmphasis; - Volume = _player.Volume; - - CurrentSector = _player.GetCurrentSectorTime(); - TotalSectors = _player.TotalTime; + CurrentTrackNumber = _player.CurrentTrackNumber; + CurrentTrackIndex = _player.CurrentTrackIndex; + CurrentSector = _player.CurrentSector; HiddenTrack = _player.HiddenTrack; @@ -272,6 +322,10 @@ namespace RedBookPlayer.GUI IsDataTrack = _player.IsDataTrack; CopyAllowed = _player.CopyAllowed; TrackHasEmphasis = _player.TrackHasEmphasis; + + Playing = _player.Playing; + ApplyDeEmphasis = _player.ApplyDeEmphasis; + Volume = _player.Volume; } #endregion