using Aaru.CommonTypes.Enums;
using Aaru.CommonTypes.Interfaces;
using ReactiveUI;
namespace RedBookPlayer.Common.Discs
{
public abstract class OpticalDisc : ReactiveObject
{
#region Public Fields
///
/// Indicate if the disc is ready to be used
///
public bool Initialized { get; protected set; } = false;
///
/// Current track number
///
public abstract int CurrentTrackNumber { get; protected set; }
///
/// Current track index
///
public abstract ushort CurrentTrackIndex { get; protected set; }
///
/// Current sector number
///
public abstract ulong CurrentSector { get; set; }
///
/// Represents the sector starting the section
///
public ulong SectionStartSector
{
get => _sectionStartSector;
protected set => this.RaiseAndSetIfChanged(ref _sectionStartSector, value);
}
///
/// Number of bytes per sector for the current track
///
public int BytesPerSector => _image.Tracks[CurrentTrackNumber].TrackRawBytesPerSector;
///
/// Represents the track type
///
public TrackType TrackType { get; protected set; }
///
/// Represents the total tracks on the disc
///
public int TotalTracks { get; protected set; } = 0;
///
/// Represents the total indices on the disc
///
public int TotalIndexes { get; protected set; } = 0;
///
/// Total sectors in the image
///
public ulong TotalSectors => _image?.Info.Sectors ?? 0;
///
/// Represents the time adjustment offset for the disc
///
public ulong TimeOffset { get; protected set; } = 0;
///
/// Represents the total playing time for the disc
///
public ulong TotalTime { get; protected set; } = 0;
private ulong _sectionStartSector;
#endregion
#region Protected State Variables
///
/// Currently loaded disc image
///
protected IOpticalMediaImage _image;
#endregion
///
/// Initialize the disc with a given image
///
/// Aaruformat image to load
/// True if playback should begin immediately, false otherwise
public abstract void Init(IOpticalMediaImage image, bool autoPlay);
#region Seeking
///
/// Try to move to the next track, wrapping around if necessary
///
public void NextTrack()
{
if(_image == null)
return;
CurrentTrackNumber++;
LoadTrack(CurrentTrackNumber);
}
///
/// Try to move to the previous track, wrapping around if necessary
///
/// True to play the hidden track, if it exists
public void PreviousTrack(bool playHiddenTrack)
{
if(_image == null)
return;
if(CurrentSector < (ulong)_image.Tracks[CurrentTrackNumber].Indexes[1] + 75)
{
if(playHiddenTrack && CurrentTrackNumber == 0 && CurrentSector >= 75)
CurrentSector = 0;
else
CurrentTrackNumber--;
}
else
CurrentTrackNumber--;
LoadTrack(CurrentTrackNumber);
}
///
/// Try to move to the next track index
///
/// True if index changes can trigger a track change, false otherwise
/// True if the track was changed, false otherwise
public abstract bool NextIndex(bool changeTrack);
///
/// Try to move to the previous track index
///
/// True if index changes can trigger a track change, false otherwise
/// True to play the hidden track, if it exists
/// True if the track was changed, false otherwise
public abstract bool PreviousIndex(bool changeTrack, bool playHiddenTrack);
#endregion
#region Helpers
///
/// Load the first valid track in the image
///
public abstract void LoadFirstTrack();
///
/// Read sector data from the base image starting from the current sector
///
/// Current number of sectors to read
/// Byte array representing the read sectors, if possible
public byte[] ReadSectors(uint sectorsToRead) => _image.ReadSectors(CurrentSector, sectorsToRead);
///
/// Set the total indexes from the current track
///
public abstract void SetTotalIndexes();
///
/// Load the desired track, if possible
///
/// Track number to load
protected abstract void LoadTrack(int track);
#endregion
}
}