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; protected 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 abstract int BytesPerSector { get; } /// /// 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 abstract void NextTrack(); /// /// Try to move to the previous track, wrapping around if necessary /// public abstract void PreviousTrack(); /// /// 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 if the track was changed, false otherwise public abstract bool PreviousIndex(bool changeTrack); #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(); /// /// Set the current sector /// /// New sector number to use public void SetCurrentSector(ulong sector) => CurrentSector = sector; /// /// Load the desired track, if possible /// /// Track number to load protected abstract void LoadTrack(int track); #endregion } }