diff --git a/RedBookPlayer/PlayableDisc.cs b/RedBookPlayer/PlayableDisc.cs index 7feaa8d..f030fa9 100644 --- a/RedBookPlayer/PlayableDisc.cs +++ b/RedBookPlayer/PlayableDisc.cs @@ -4,6 +4,7 @@ using System.Linq; using Aaru.CommonTypes.Enums; using Aaru.CommonTypes.Interfaces; using Aaru.CommonTypes.Structs; +using Aaru.Decoders.CD; using Aaru.Helpers; using static Aaru.Decoders.CD.FullTOC; @@ -30,36 +31,45 @@ namespace RedBookPlayer if(_image == null) return; + // Cache the value and the current track number + int cachedValue = value; + int cachedTrackNumber = _currentTrackNumber; + // Check if we're incrementing or decrementing the track - bool increment = value >= _currentTrackNumber; + bool increment = cachedValue >= _currentTrackNumber; - // Ensure that the value is valid, wrapping around if necessary - if(value >= _image.Tracks.Count) - _currentTrackNumber = 0; - else if(value < 0) - _currentTrackNumber = _image.Tracks.Count - 1; - else - _currentTrackNumber = value; - - // Cache the current track for easy access - Track track = _image.Tracks[CurrentTrackNumber]; - - // Set track flags from subchannel data, if possible - SetTrackFlags(track); - - ApplyDeEmphasis = TrackHasEmphasis; - - TotalIndexes = track.Indexes.Keys.Max(); - CurrentTrackIndex = track.Indexes.Keys.Min(); - - // If we're not playing data tracks, skip - if(!App.Settings.PlayDataTracks && TrackType != TrackType.Audio) + do { + // Ensure that the value is valid, wrapping around if necessary + if(cachedValue >= _image.Tracks.Count) + cachedValue = 0; + else if(cachedValue < 0) + cachedValue = _image.Tracks.Count - 1; + + _currentTrackNumber = cachedValue; + + // Cache the current track for easy access + Track track = _image.Tracks[_currentTrackNumber]; + + // Set track flags from subchannel data, if possible + SetTrackFlags(track); + + ApplyDeEmphasis = TrackHasEmphasis; + + TotalIndexes = track.Indexes.Keys.Max(); + CurrentTrackIndex = track.Indexes.Keys.Min(); + + // If the track is playable, just return + if(TrackType == TrackType.Audio || App.Settings.PlayDataTracks) + return; + + // If we're not playing the track, skip if(increment) - NextTrack(); + cachedValue++; else - PreviousTrack(); + cachedValue--; } + while(cachedValue != cachedTrackNumber); } } @@ -110,7 +120,7 @@ namespace RedBookPlayer _currentSector = value; if((CurrentTrackNumber < _image.Tracks.Count - 1 && CurrentSector >= _image.Tracks[CurrentTrackNumber + 1].TrackStartSector) - || (CurrentTrackNumber > 0 && CurrentSector < track.TrackStartSector)) + || (CurrentTrackNumber > 0 && CurrentSector < track.TrackStartSector)) { foreach(Track trackData in _image.Tracks.ToArray().Reverse()) { @@ -666,62 +676,17 @@ namespace RedBookPlayer { try { - ulong currentSector = track.TrackStartSector; - for (int i = 0; i < 16; i++) - { - // Try to read the subchannel - byte[] subBuf = _image.ReadSectorTag(track.TrackStartSector, SectorTagType.CdSectorSubchannel); - if(subBuf == null || subBuf.Length < 4) - return; + // Get the track descriptor from the TOC + TrackDataDescriptor descriptor = _toc.TrackDescriptors.First(d => d.POINT == track.TrackSequence); - // Check the expected track, if possible - int adr = subBuf[0] & 0x0F; - if(adr == 1) - { - if(subBuf[1] > track.TrackSequence) - { - currentSector--; - continue; - } - else if(subBuf[1] < track.TrackSequence) - { - currentSector++; - continue; - } - } + // Set the track flags from TOC data + 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; + QuadChannel = (flags & (byte)TocControl.FourChanNoPreEmph) == (byte)TocControl.FourChanNoPreEmph; - // Set the track flags from subchannel data - int control = (subBuf[0] & 0xF0) / 16; - switch((control & 0xC) / 4) - { - case 0: - QuadChannel = false; - TrackType = TrackType.Audio; - TrackHasEmphasis = (control & 0x01) == 1; - break; - case 1: - QuadChannel = false; - TrackType = TrackType.Data; - TrackHasEmphasis = false; - break; - case 2: - QuadChannel = true; - TrackType = TrackType.Audio; - TrackHasEmphasis = (control & 0x01) == 1; - break; - default: - QuadChannel = false; - TrackType = track.TrackType; - TrackHasEmphasis = false; - break; - } - - CopyAllowed = (control & 0x02) > 0; - return; - } - - // If we didn't find subchannel data, assume defaults - SetDefaultTrackFlags(track); + return; } catch(Exception) { diff --git a/RedBookPlayer/Player.cs b/RedBookPlayer/Player.cs index 443e459..6ef92d4 100644 --- a/RedBookPlayer/Player.cs +++ b/RedBookPlayer/Player.cs @@ -16,6 +16,11 @@ namespace RedBookPlayer /// public bool Initialized { get; private set; } = false; + /// + /// Indicate if the disc is playing + /// + public bool Playing => _soundOut.PlaybackState == PlaybackState.Playing; + #endregion #region Private State Variables diff --git a/RedBookPlayer/PlayerView.xaml.cs b/RedBookPlayer/PlayerView.xaml.cs index 095e332..72dc4b3 100644 --- a/RedBookPlayer/PlayerView.xaml.cs +++ b/RedBookPlayer/PlayerView.xaml.cs @@ -301,13 +301,37 @@ namespace RedBookPlayer public void StopButton_Click(object sender, RoutedEventArgs e) => Player.Stop(); - public void NextTrackButton_Click(object sender, RoutedEventArgs e) => PlayableDisc.NextTrack(); + public void NextTrackButton_Click(object sender, RoutedEventArgs e) + { + bool wasPlaying = Player.Playing; + if(wasPlaying) Player.Pause(); + PlayableDisc.NextTrack(); + if(wasPlaying) Player.Play(); + } - public void PreviousTrackButton_Click(object sender, RoutedEventArgs e) => PlayableDisc.PreviousTrack(); + public void PreviousTrackButton_Click(object sender, RoutedEventArgs e) + { + bool wasPlaying = Player.Playing; + if(wasPlaying) Player.Pause(); + PlayableDisc.PreviousTrack(); + if(wasPlaying) Player.Play(); + } - public void NextIndexButton_Click(object sender, RoutedEventArgs e) => PlayableDisc.NextIndex(App.Settings.IndexButtonChangeTrack); + public void NextIndexButton_Click(object sender, RoutedEventArgs e) + { + bool wasPlaying = Player.Playing; + if(wasPlaying) Player.Pause(); + PlayableDisc.NextIndex(App.Settings.IndexButtonChangeTrack); + if(wasPlaying) Player.Play(); + } - public void PreviousIndexButton_Click(object sender, RoutedEventArgs e) => PlayableDisc.PreviousIndex(App.Settings.IndexButtonChangeTrack); + public void PreviousIndexButton_Click(object sender, RoutedEventArgs e) + { + bool wasPlaying = Player.Playing; + if(wasPlaying) Player.Pause(); + PlayableDisc.PreviousIndex(App.Settings.IndexButtonChangeTrack); + if(wasPlaying) Player.Play(); + } public void FastForwardButton_Click(object sender, RoutedEventArgs e) => PlayableDisc.FastForward();