Make OpticalDisc have events

This commit is contained in:
Matt Nadareski
2021-07-04 23:36:09 -07:00
parent be2c704654
commit cd3ccbc8eb
3 changed files with 171 additions and 88 deletions

View File

@@ -6,11 +6,12 @@ using Aaru.CommonTypes.Interfaces;
using Aaru.CommonTypes.Structs; using Aaru.CommonTypes.Structs;
using Aaru.Decoders.CD; using Aaru.Decoders.CD;
using Aaru.Helpers; using Aaru.Helpers;
using ReactiveUI;
using static Aaru.Decoders.CD.FullTOC; using static Aaru.Decoders.CD.FullTOC;
namespace RedBookPlayer.Discs namespace RedBookPlayer.Discs
{ {
public class CompactDisc : OpticalDisc public class CompactDisc : OpticalDisc, IReactiveObject
{ {
#region Public Fields #region Public Fields
@@ -26,7 +27,7 @@ namespace RedBookPlayer.Discs
// Cache the value and the current track number // Cache the value and the current track number
int cachedValue = value; int cachedValue = value;
int cachedTrackNumber = _currentTrackNumber; int cachedTrackNumber;
// Check if we're incrementing or decrementing the track // Check if we're incrementing or decrementing the track
bool increment = cachedValue >= _currentTrackNumber; bool increment = cachedValue >= _currentTrackNumber;
@@ -39,10 +40,10 @@ namespace RedBookPlayer.Discs
else if(cachedValue < 0) else if(cachedValue < 0)
cachedValue = _image.Tracks.Count - 1; cachedValue = _image.Tracks.Count - 1;
_currentTrackNumber = cachedValue; cachedTrackNumber = cachedValue;
// Cache the current track for easy access // 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 // Set track flags from subchannel data, if possible
SetTrackFlags(track); SetTrackFlags(track);
@@ -52,7 +53,7 @@ namespace RedBookPlayer.Discs
// If the track is playable, just return // If the track is playable, just return
if(TrackType == TrackType.Audio || App.Settings.PlayDataTracks) if(TrackType == TrackType.Audio || App.Settings.PlayDataTracks)
return; break;
// If we're not playing the track, skip // If we're not playing the track, skip
if(increment) if(increment)
@@ -60,7 +61,9 @@ namespace RedBookPlayer.Discs
else else
cachedValue--; cachedValue--;
} }
while(cachedValue != cachedTrackNumber); while(cachedValue != _currentTrackNumber);
this.RaiseAndSetIfChanged(ref _currentTrackNumber, cachedTrackNumber);
} }
} }
@@ -78,12 +81,13 @@ namespace RedBookPlayer.Discs
Track track = _image.Tracks[CurrentTrackNumber]; Track track = _image.Tracks[CurrentTrackNumber];
// Ensure that the value is valid, wrapping around if necessary // Ensure that the value is valid, wrapping around if necessary
ushort fixedValue = value;
if(value > track.Indexes.Keys.Max()) if(value > track.Indexes.Keys.Max())
_currentTrackIndex = track.Indexes.Keys.Min(); fixedValue = track.Indexes.Keys.Min();
else if(value < track.Indexes.Keys.Min()) else if(value < track.Indexes.Keys.Min())
_currentTrackIndex = track.Indexes.Keys.Max(); fixedValue = track.Indexes.Keys.Max();
else
_currentTrackIndex = value; this.RaiseAndSetIfChanged(ref _currentTrackIndex, fixedValue);
// Set new index-specific data // Set new index-specific data
SectionStartSector = (ulong)track.Indexes[CurrentTrackIndex]; SectionStartSector = (ulong)track.Indexes[CurrentTrackIndex];
@@ -104,7 +108,7 @@ namespace RedBookPlayer.Discs
// Cache the current track for easy access // Cache the current track for easy access
Track track = _image.Tracks[CurrentTrackNumber]; Track track = _image.Tracks[CurrentTrackNumber];
_currentSector = value; this.RaiseAndSetIfChanged(ref _currentSector, value);
if((CurrentTrackNumber < _image.Tracks.Count - 1 && CurrentSector >= _image.Tracks[CurrentTrackNumber + 1].TrackStartSector) if((CurrentTrackNumber < _image.Tracks.Count - 1 && CurrentSector >= _image.Tracks[CurrentTrackNumber + 1].TrackStartSector)
|| (CurrentTrackNumber > 0 && CurrentSector < track.TrackStartSector)) || (CurrentTrackNumber > 0 && CurrentSector < track.TrackStartSector))
@@ -135,22 +139,43 @@ namespace RedBookPlayer.Discs
/// <summary> /// <summary>
/// Represents the 4CH flag /// Represents the 4CH flag
/// </summary> /// </summary>
public bool QuadChannel { get; private set; } = false; public bool QuadChannel
{
get => _quadChannel;
private set => this.RaiseAndSetIfChanged(ref _quadChannel, value);
}
/// <summary> /// <summary>
/// Represents the DATA flag /// Represents the DATA flag
/// </summary> /// </summary>
public bool IsDataTrack => TrackType != TrackType.Audio; public bool IsDataTrack
{
get => _isDataTrack;
private set => this.RaiseAndSetIfChanged(ref _isDataTrack, value);
}
/// <summary> /// <summary>
/// Represents the DCP flag /// Represents the DCP flag
/// </summary> /// </summary>
public bool CopyAllowed { get; private set; } = false; public bool CopyAllowed
{
get => _copyAllowed;
private set => this.RaiseAndSetIfChanged(ref _copyAllowed, value);
}
/// <summary> /// <summary>
/// Represents the PRE flag /// Represents the PRE flag
/// </summary> /// </summary>
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 #endregion
@@ -369,8 +394,9 @@ namespace RedBookPlayer.Discs
/// <param name="track">Track object to read from</param> /// <param name="track">Track object to read from</param>
private void SetDefaultTrackFlags(Track track) private void SetDefaultTrackFlags(Track track)
{ {
QuadChannel = false;
TrackType = track.TrackType; TrackType = track.TrackType;
QuadChannel = false;
IsDataTrack = track.TrackType != TrackType.Audio;
CopyAllowed = false; CopyAllowed = false;
TrackHasEmphasis = false; TrackHasEmphasis = false;
} }
@@ -390,9 +416,11 @@ namespace RedBookPlayer.Discs
byte flags = (byte)(descriptor.CONTROL & 0x0D); byte flags = (byte)(descriptor.CONTROL & 0x0D);
TrackHasEmphasis = (flags & (byte)TocControl.TwoChanPreEmph) == (byte)TocControl.TwoChanPreEmph; TrackHasEmphasis = (flags & (byte)TocControl.TwoChanPreEmph) == (byte)TocControl.TwoChanPreEmph;
CopyAllowed = (flags & (byte)TocControl.CopyPermissionMask) == (byte)TocControl.CopyPermissionMask; 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; QuadChannel = (flags & (byte)TocControl.FourChanNoPreEmph) == (byte)TocControl.FourChanNoPreEmph;
TrackType = IsDataTrack ? TrackType.Data : TrackType.Audio;
return; return;
} }
catch(Exception) catch(Exception)

View File

@@ -1,9 +1,10 @@
using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Interfaces;
using ReactiveUI;
namespace RedBookPlayer.Discs namespace RedBookPlayer.Discs
{ {
public abstract class OpticalDisc public abstract class OpticalDisc : ReactiveObject
{ {
#region Public Fields #region Public Fields
@@ -55,7 +56,7 @@ namespace RedBookPlayer.Discs
/// <summary> /// <summary>
/// Total sectors in the image /// Total sectors in the image
/// </summary> /// </summary>
public ulong TotalSectors => _image.Info.Sectors; public ulong TotalSectors => _image?.Info.Sectors ?? 0;
/// <summary> /// <summary>
/// Represents the time adjustment offset for the disc /// Represents the time adjustment offset for the disc

View File

@@ -19,6 +19,119 @@ namespace RedBookPlayer.GUI
#region Player Passthrough #region Player Passthrough
#region OpticalDisc Passthrough
/// <summary>
/// Current track number
/// </summary>
public int CurrentTrackNumber
{
get => _currentTrackNumber;
private set => this.RaiseAndSetIfChanged(ref _currentTrackNumber, value);
}
/// <summary>
/// Current track index
/// </summary>
public ushort CurrentTrackIndex
{
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 => _player.TotalTracks;
/// <summary>
/// Represents the total indices on the disc
/// </summary>
public int TotalIndexes => _player.TotalIndexes;
/// <summary>
/// Total sectors in the image
/// </summary>
public ulong TotalSectors => _player.TotalSectors;
/// <summary>
/// Represents the time adjustment offset for the disc
/// </summary>
public ulong TimeOffset => _player.TimeOffset;
/// <summary>
/// Represents the total playing time for the disc
/// </summary>
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
/// <summary> /// <summary>
/// Indicate if the model is ready to be used /// Indicate if the model is ready to be used
/// </summary> /// </summary>
@@ -57,69 +170,6 @@ namespace RedBookPlayer.GUI
#endregion #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 #endregion
/// <summary> /// <summary>
@@ -199,6 +249,9 @@ namespace RedBookPlayer.GUI
/// Generate the digit string to be interpreted by the frontend /// Generate the digit string to be interpreted by the frontend
/// </summary> /// </summary>
/// <returns>String representing the digits for the frontend</returns> /// <returns>String representing the digits for the frontend</returns>
/// <remarks>
/// TODO: The model shouldn't care about this
/// </remarks>
public string GenerateDigitString() public string GenerateDigitString()
{ {
// If the disc isn't initialized, return all '-' characters // If the disc isn't initialized, return all '-' characters
@@ -259,12 +312,9 @@ namespace RedBookPlayer.GUI
if(_player?.Initialized != true) if(_player?.Initialized != true)
return; return;
Playing = _player.Playing; CurrentTrackNumber = _player.CurrentTrackNumber;
ApplyDeEmphasis = _player.ApplyDeEmphasis; CurrentTrackIndex = _player.CurrentTrackIndex;
Volume = _player.Volume; CurrentSector = _player.CurrentSector;
CurrentSector = _player.GetCurrentSectorTime();
TotalSectors = _player.TotalTime;
HiddenTrack = _player.HiddenTrack; HiddenTrack = _player.HiddenTrack;
@@ -272,6 +322,10 @@ namespace RedBookPlayer.GUI
IsDataTrack = _player.IsDataTrack; IsDataTrack = _player.IsDataTrack;
CopyAllowed = _player.CopyAllowed; CopyAllowed = _player.CopyAllowed;
TrackHasEmphasis = _player.TrackHasEmphasis; TrackHasEmphasis = _player.TrackHasEmphasis;
Playing = _player.Playing;
ApplyDeEmphasis = _player.ApplyDeEmphasis;
Volume = _player.Volume;
} }
#endregion #endregion