mirror of
https://github.com/aaru-dps/RedBookPlayer.git
synced 2025-12-16 19:24:41 +00:00
Fix rendering of hidden tracks
This commit is contained in:
@@ -34,16 +34,30 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
// Ensure that the value is valid, wrapping around if necessary
|
// If we're over the last track, wrap around
|
||||||
if(cachedValue >= _image.Tracks.Count)
|
if(cachedValue > _image.Tracks.Max(t => t.TrackSequence))
|
||||||
cachedValue = 0;
|
{
|
||||||
else if(cachedValue < 0)
|
cachedValue = (int)_image.Tracks.Min(t => t.TrackSequence);
|
||||||
cachedValue = _image.Tracks.Count - 1;
|
if(cachedValue == 0 && !_loadHiddenTracks)
|
||||||
|
cachedValue++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're under the first track and we're not loading hidden tracks, wrap around
|
||||||
|
else if(cachedValue < 1 && !_loadHiddenTracks)
|
||||||
|
{
|
||||||
|
cachedValue = (int)_image.Tracks.Max(t => t.TrackSequence);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're under the first valid track, wrap around
|
||||||
|
else if(cachedValue < _image.Tracks.Min(t => t.TrackSequence))
|
||||||
|
{
|
||||||
|
cachedValue = (int)_image.Tracks.Max(t => t.TrackSequence);
|
||||||
|
}
|
||||||
|
|
||||||
cachedTrackNumber = cachedValue;
|
cachedTrackNumber = cachedValue;
|
||||||
|
|
||||||
// Cache the current track for easy access
|
// Cache the current track for easy access
|
||||||
Track track = _image.Tracks[cachedTrackNumber];
|
Track track = GetTrack(cachedTrackNumber);
|
||||||
|
|
||||||
// Set track flags from subchannel data, if possible
|
// Set track flags from subchannel data, if possible
|
||||||
SetTrackFlags(track);
|
SetTrackFlags(track);
|
||||||
@@ -78,7 +92,7 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Cache the current track for easy access
|
// Cache the current track for easy access
|
||||||
Track track = _image.Tracks[CurrentTrackNumber];
|
Track track = GetTrack(CurrentTrackNumber);
|
||||||
|
|
||||||
// Ensure that the value is valid, wrapping around if necessary
|
// Ensure that the value is valid, wrapping around if necessary
|
||||||
ushort fixedValue = value;
|
ushort fixedValue = value;
|
||||||
@@ -106,18 +120,18 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Cache the current track for easy access
|
// Cache the current track for easy access
|
||||||
Track track = _image.Tracks[CurrentTrackNumber];
|
Track track = GetTrack(CurrentTrackNumber);
|
||||||
|
|
||||||
this.RaiseAndSetIfChanged(ref _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 >= GetTrack(CurrentTrackNumber + 1).TrackStartSector)
|
||||||
|| (CurrentTrackNumber > 0 && CurrentSector < track.TrackStartSector))
|
|| (CurrentTrackNumber > 0 && CurrentSector < track.TrackStartSector))
|
||||||
{
|
{
|
||||||
foreach(Track trackData in _image.Tracks.ToArray().Reverse())
|
foreach(Track trackData in _image.Tracks.ToArray().Reverse())
|
||||||
{
|
{
|
||||||
if(CurrentSector >= trackData.TrackStartSector)
|
if(CurrentSector >= trackData.TrackStartSector)
|
||||||
{
|
{
|
||||||
CurrentTrackNumber = (int)trackData.TrackSequence - 1;
|
CurrentTrackNumber = (int)trackData.TrackSequence;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,6 +150,9 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override int BytesPerSector => GetTrack(CurrentTrackNumber).TrackRawBytesPerSector;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the 4CH flag
|
/// Represents the 4CH flag
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -206,6 +223,11 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private bool _loadDataTracks = false;
|
private bool _loadDataTracks = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicate if hidden tracks should be loaded
|
||||||
|
/// </summary>
|
||||||
|
private bool _loadHiddenTracks = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Current disc table of contents
|
/// Current disc table of contents
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -217,10 +239,12 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
/// Constructor
|
/// Constructor
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one</param>
|
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one</param>
|
||||||
|
/// <param name="loadHiddenTracks">Load hidden tracks for playback</param>
|
||||||
/// <param name="loadDataTracks">Load data tracks for playback</param>
|
/// <param name="loadDataTracks">Load data tracks for playback</param>
|
||||||
public CompactDisc(bool generateMissingToc, bool loadDataTracks)
|
public CompactDisc(bool generateMissingToc, bool loadHiddenTracks, bool loadDataTracks)
|
||||||
{
|
{
|
||||||
_generateMissingToc = generateMissingToc;
|
_generateMissingToc = generateMissingToc;
|
||||||
|
_loadHiddenTracks = loadHiddenTracks;
|
||||||
_loadDataTracks = loadDataTracks;
|
_loadDataTracks = loadDataTracks;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,47 +281,101 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
|
|
||||||
#region Seeking
|
#region Seeking
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void NextTrack()
|
||||||
|
{
|
||||||
|
if(_image == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CurrentTrackNumber++;
|
||||||
|
LoadTrack(CurrentTrackNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void PreviousTrack()
|
||||||
|
{
|
||||||
|
if(_image == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
CurrentTrackNumber--;
|
||||||
|
LoadTrack(CurrentTrackNumber);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override bool NextIndex(bool changeTrack)
|
public override bool NextIndex(bool changeTrack)
|
||||||
{
|
{
|
||||||
if(_image == null)
|
if(_image == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(CurrentTrackIndex + 1 > _image.Tracks[CurrentTrackNumber].Indexes.Keys.Max())
|
// Cache the current track for easy access
|
||||||
|
Track track = GetTrack(CurrentTrackNumber);
|
||||||
|
|
||||||
|
// If the index is greater than the highest index, change tracks if needed
|
||||||
|
if(CurrentTrackIndex + 1 > track.Indexes.Keys.Max())
|
||||||
{
|
{
|
||||||
if(changeTrack)
|
if(changeTrack)
|
||||||
{
|
{
|
||||||
NextTrack();
|
NextTrack();
|
||||||
CurrentSector = (ulong)_image.Tracks[CurrentTrackNumber].Indexes.Values.Min();
|
CurrentSector = (ulong)GetTrack(CurrentTrackNumber).Indexes.Values.Min();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the next index has an invalid offset, change tracks if needed
|
||||||
|
else if(track.Indexes[(ushort)(CurrentTrackIndex + 1)] < 0)
|
||||||
|
{
|
||||||
|
if(changeTrack)
|
||||||
|
{
|
||||||
|
NextTrack();
|
||||||
|
CurrentSector = (ulong)GetTrack(CurrentTrackNumber).Indexes.Values.Min();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, just move to the next index
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentSector = (ulong)_image.Tracks[CurrentTrackNumber].Indexes[++CurrentTrackIndex];
|
CurrentSector = (ulong)track.Indexes[++CurrentTrackIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override bool PreviousIndex(bool changeTrack, bool playHiddenTrack)
|
public override bool PreviousIndex(bool changeTrack)
|
||||||
{
|
{
|
||||||
if(_image == null)
|
if(_image == null)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(CurrentTrackIndex - 1 < _image.Tracks[CurrentTrackNumber].Indexes.Keys.Min())
|
// Cache the current track for easy access
|
||||||
|
Track track = GetTrack(CurrentTrackNumber);
|
||||||
|
|
||||||
|
// If the index is less than the lowest index, change tracks if needed
|
||||||
|
if(CurrentTrackIndex - 1 < track.Indexes.Keys.Min())
|
||||||
{
|
{
|
||||||
if(changeTrack)
|
if(changeTrack)
|
||||||
{
|
{
|
||||||
PreviousTrack(playHiddenTrack);
|
PreviousTrack();
|
||||||
CurrentSector = (ulong)_image.Tracks[CurrentTrackNumber].Indexes.Values.Max();
|
CurrentSector = (ulong)GetTrack(CurrentTrackNumber).Indexes.Values.Max();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the previous index has an invalid offset, change tracks if needed
|
||||||
|
else if (track.Indexes[(ushort)(CurrentTrackIndex - 1)] < 0)
|
||||||
|
{
|
||||||
|
if(changeTrack)
|
||||||
|
{
|
||||||
|
PreviousTrack();
|
||||||
|
CurrentSector = (ulong)GetTrack(CurrentTrackNumber).Indexes.Values.Max();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, just move to the previous index
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CurrentSector = (ulong)_image.Tracks[CurrentTrackNumber].Indexes[--CurrentTrackIndex];
|
CurrentSector = (ulong)track.Indexes[--CurrentTrackIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -310,7 +388,7 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void LoadFirstTrack()
|
public override void LoadFirstTrack()
|
||||||
{
|
{
|
||||||
CurrentTrackNumber = 0;
|
CurrentTrackNumber = 1;
|
||||||
LoadTrack(CurrentTrackNumber);
|
LoadTrack(CurrentTrackNumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +398,12 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
/// <param name="load">True to enable loading data tracks, false otherwise</param>
|
/// <param name="load">True to enable loading data tracks, false otherwise</param>
|
||||||
public void SetLoadDataTracks(bool load) => _loadDataTracks = load;
|
public void SetLoadDataTracks(bool load) => _loadDataTracks = load;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the value for loading hidden tracks
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="load">True to enable loading hidden tracks, false otherwise</param>
|
||||||
|
public void SetLoadHiddenTracks(bool load) => _loadHiddenTracks = load;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void SetTotalIndexes()
|
public override void SetTotalIndexes()
|
||||||
{
|
{
|
||||||
@@ -330,17 +414,37 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
protected override void LoadTrack(int track)
|
protected override void LoadTrack(int trackNumber)
|
||||||
{
|
{
|
||||||
if(_image == null)
|
if(_image == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(track < 0 || track >= _image.Tracks.Count)
|
// If the track number is invalid, just return
|
||||||
|
if(trackNumber < _image.Tracks.Min(t => t.TrackSequence) || trackNumber > _image.Tracks.Max(t => t.TrackSequence))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ushort firstIndex = _image.Tracks[track].Indexes.Keys.Min();
|
// Cache the current track for easy access
|
||||||
int firstSector = _image.Tracks[track].Indexes[firstIndex];
|
Track track = GetTrack(trackNumber);
|
||||||
CurrentSector = (ulong)(firstSector >= 0 ? firstSector : _image.Tracks[track].Indexes[1]);
|
|
||||||
|
// Select the first index that has a sector offset greater than or equal to 0
|
||||||
|
CurrentSector = (ulong)(track?.Indexes.OrderBy(kvp => kvp.Key).First(kvp => kvp.Value >= 0).Value ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the track with the given sequence value, if possible
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="trackNumber">Track number to retrieve</param>
|
||||||
|
/// <returns>Track object for the requested sequence, null on error</returns>
|
||||||
|
private Track GetTrack(int trackNumber)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return _image.Tracks.FirstOrDefault(t => t.TrackSequence == trackNumber);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Number of bytes per sector for the current track
|
/// Number of bytes per sector for the current track
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int BytesPerSector => _image.Tracks[CurrentTrackNumber].TrackRawBytesPerSector;
|
public abstract int BytesPerSector { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents the track type
|
/// Represents the track type
|
||||||
@@ -97,36 +97,12 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try to move to the next track, wrapping around if necessary
|
/// Try to move to the next track, wrapping around if necessary
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void NextTrack()
|
public abstract void NextTrack();
|
||||||
{
|
|
||||||
if(_image == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
CurrentTrackNumber++;
|
|
||||||
LoadTrack(CurrentTrackNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try to move to the previous track, wrapping around if necessary
|
/// Try to move to the previous track, wrapping around if necessary
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
|
public abstract void PreviousTrack();
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try to move to the next track index
|
/// Try to move to the next track index
|
||||||
@@ -139,9 +115,8 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
/// Try to move to the previous track index
|
/// Try to move to the previous track index
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="changeTrack">True if index changes can trigger a track change, false otherwise</param>
|
/// <param name="changeTrack">True if index changes can trigger a track change, false otherwise</param>
|
||||||
/// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
|
|
||||||
/// <returns>True if the track was changed, false otherwise</returns>
|
/// <returns>True if the track was changed, false otherwise</returns>
|
||||||
public abstract bool PreviousIndex(bool changeTrack, bool playHiddenTrack);
|
public abstract bool PreviousIndex(bool changeTrack);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">Path to load the image from</param>
|
/// <param name="path">Path to load the image from</param>
|
||||||
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one [CompactDisc only]</param>
|
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one [CompactDisc only]</param>
|
||||||
|
/// <param name="loadHiddenTracks">Load hidden tracks for playback [CompactDisc only]</param>
|
||||||
/// <param name="loadDataTracks">Load data tracks for playback [CompactDisc only]</param>
|
/// <param name="loadDataTracks">Load data tracks for playback [CompactDisc only]</param>
|
||||||
/// <param name="autoPlay">True if the image should be playable immediately, false otherwise</param>
|
/// <param name="autoPlay">True if the image should be playable immediately, false otherwise</param>
|
||||||
/// <returns>Instantiated OpticalDisc, if possible</returns>
|
/// <returns>Instantiated OpticalDisc, if possible</returns>
|
||||||
public static OpticalDisc GenerateFromPath(string path, bool generateMissingToc, bool loadDataTracks, bool autoPlay)
|
public static OpticalDisc GenerateFromPath(string path, bool generateMissingToc, bool loadHiddenTracks, bool loadDataTracks, bool autoPlay)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -32,7 +33,7 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
image.Open(filter);
|
image.Open(filter);
|
||||||
|
|
||||||
// Generate and instantiate the disc
|
// Generate and instantiate the disc
|
||||||
return GenerateFromImage(image, generateMissingToc, loadDataTracks, autoPlay);
|
return GenerateFromImage(image, generateMissingToc, loadHiddenTracks, loadDataTracks, autoPlay);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -46,10 +47,11 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="image">IOpticalMediaImage to create from</param>
|
/// <param name="image">IOpticalMediaImage to create from</param>
|
||||||
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one [CompactDisc only]</param>
|
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one [CompactDisc only]</param>
|
||||||
|
/// <param name="loadHiddenTracks">Load hidden tracks for playback [CompactDisc only]</param>
|
||||||
/// <param name="loadDataTracks">Load data tracks for playback [CompactDisc only]</param>
|
/// <param name="loadDataTracks">Load data tracks for playback [CompactDisc only]</param>
|
||||||
/// <param name="autoPlay">True if the image should be playable immediately, false otherwise</param>
|
/// <param name="autoPlay">True if the image should be playable immediately, false otherwise</param>
|
||||||
/// <returns>Instantiated OpticalDisc, if possible</returns>
|
/// <returns>Instantiated OpticalDisc, if possible</returns>
|
||||||
public static OpticalDisc GenerateFromImage(IOpticalMediaImage image, bool generateMissingToc, bool loadDataTracks, bool autoPlay)
|
public static OpticalDisc GenerateFromImage(IOpticalMediaImage image, bool generateMissingToc, bool loadHiddenTracks, bool loadDataTracks, bool autoPlay)
|
||||||
{
|
{
|
||||||
// If the image is not usable, we don't do anything
|
// If the image is not usable, we don't do anything
|
||||||
if(!IsUsableImage(image))
|
if(!IsUsableImage(image))
|
||||||
@@ -63,7 +65,7 @@ namespace RedBookPlayer.Common.Discs
|
|||||||
{
|
{
|
||||||
case "Compact Disc":
|
case "Compact Disc":
|
||||||
case "GD":
|
case "GD":
|
||||||
opticalDisc = new CompactDisc(generateMissingToc, loadDataTracks);
|
opticalDisc = new CompactDisc(generateMissingToc, loadHiddenTracks, loadDataTracks);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
opticalDisc = null;
|
opticalDisc = null;
|
||||||
|
|||||||
@@ -188,10 +188,11 @@ namespace RedBookPlayer.Common.Hardware
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">Path to the disc image</param>
|
/// <param name="path">Path to the disc image</param>
|
||||||
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one [CompactDisc only]</param>
|
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one [CompactDisc only]</param>
|
||||||
|
/// <param name="loadHiddenTracks">Load hidden tracks for playback [CompactDisc only]</param>
|
||||||
/// <param name="loadDataTracks">Load data tracks for playback [CompactDisc only]</param>
|
/// <param name="loadDataTracks">Load data tracks for playback [CompactDisc only]</param>
|
||||||
/// <param name="autoPlay">True if playback should begin immediately, false otherwise</param>
|
/// <param name="autoPlay">True if playback should begin immediately, false otherwise</param>
|
||||||
/// <param name="defaultVolume">Default volume between 0 and 100 to use when starting playback</param>
|
/// <param name="defaultVolume">Default volume between 0 and 100 to use when starting playback</param>
|
||||||
public Player(string path, bool generateMissingToc, bool loadDataTracks, bool autoPlay, int defaultVolume)
|
public Player(string path, bool generateMissingToc, bool loadHiddenTracks, bool loadDataTracks, bool autoPlay, int defaultVolume)
|
||||||
{
|
{
|
||||||
// Set the internal state for initialization
|
// Set the internal state for initialization
|
||||||
Initialized = false;
|
Initialized = false;
|
||||||
@@ -199,7 +200,7 @@ namespace RedBookPlayer.Common.Hardware
|
|||||||
_soundOutput.SetDeEmphasis(false);
|
_soundOutput.SetDeEmphasis(false);
|
||||||
|
|
||||||
// Initalize the disc
|
// Initalize the disc
|
||||||
_opticalDisc = OpticalDiscFactory.GenerateFromPath(path, generateMissingToc, loadDataTracks, autoPlay);
|
_opticalDisc = OpticalDiscFactory.GenerateFromPath(path, generateMissingToc, loadHiddenTracks, loadDataTracks, autoPlay);
|
||||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -295,8 +296,7 @@ namespace RedBookPlayer.Common.Hardware
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Move to the previous playable track
|
/// Move to the previous playable track
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
|
public void PreviousTrack()
|
||||||
public void PreviousTrack(bool playHiddenTrack)
|
|
||||||
{
|
{
|
||||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||||
return;
|
return;
|
||||||
@@ -304,7 +304,7 @@ namespace RedBookPlayer.Common.Hardware
|
|||||||
bool? wasPlaying = Playing;
|
bool? wasPlaying = Playing;
|
||||||
if(wasPlaying == true) Pause();
|
if(wasPlaying == true) Pause();
|
||||||
|
|
||||||
_opticalDisc.PreviousTrack(playHiddenTrack);
|
_opticalDisc.PreviousTrack();
|
||||||
if(_opticalDisc is CompactDisc compactDisc)
|
if(_opticalDisc is CompactDisc compactDisc)
|
||||||
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
|
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
|
||||||
|
|
||||||
@@ -334,8 +334,7 @@ namespace RedBookPlayer.Common.Hardware
|
|||||||
/// Move to the previous index
|
/// Move to the previous index
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="changeTrack">True if index changes can trigger a track change, false otherwise</param>
|
/// <param name="changeTrack">True if index changes can trigger a track change, false otherwise</param>
|
||||||
/// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
|
public void PreviousIndex(bool changeTrack)
|
||||||
public void PreviousIndex(bool changeTrack, bool playHiddenTrack)
|
|
||||||
{
|
{
|
||||||
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
if(_opticalDisc == null || !_opticalDisc.Initialized)
|
||||||
return;
|
return;
|
||||||
@@ -343,7 +342,7 @@ namespace RedBookPlayer.Common.Hardware
|
|||||||
bool? wasPlaying = Playing;
|
bool? wasPlaying = Playing;
|
||||||
if(wasPlaying == true) Pause();
|
if(wasPlaying == true) Pause();
|
||||||
|
|
||||||
_opticalDisc.PreviousIndex(changeTrack, playHiddenTrack);
|
_opticalDisc.PreviousIndex(changeTrack);
|
||||||
if(_opticalDisc is CompactDisc compactDisc)
|
if(_opticalDisc is CompactDisc compactDisc)
|
||||||
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
|
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
|
||||||
|
|
||||||
@@ -389,6 +388,12 @@ namespace RedBookPlayer.Common.Hardware
|
|||||||
/// <param name="load">True to enable loading data tracks, false otherwise</param>
|
/// <param name="load">True to enable loading data tracks, false otherwise</param>
|
||||||
public void SetLoadDataTracks(bool load) => (_opticalDisc as CompactDisc)?.SetLoadDataTracks(load);
|
public void SetLoadDataTracks(bool load) => (_opticalDisc as CompactDisc)?.SetLoadDataTracks(load);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the value for loading hidden tracks [CompactDisc only]
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="load">True to enable loading hidden tracks, false otherwise</param>
|
||||||
|
public void SetLoadHiddenTracks(bool load) => (_opticalDisc as CompactDisc)?.SetLoadHiddenTracks(load);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the value for the volume
|
/// Set the value for the volume
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -186,16 +186,17 @@ namespace RedBookPlayer.Common
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">Path to the disc image</param>
|
/// <param name="path">Path to the disc image</param>
|
||||||
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one [CompactDisc only]</param>
|
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one [CompactDisc only]</param>
|
||||||
|
/// <param name="loadHiddenTracks">Load hidden tracks for playback [CompactDisc only]</param>
|
||||||
/// <param name="loadDataTracks">Load data tracks for playback [CompactDisc only]</param>
|
/// <param name="loadDataTracks">Load data tracks for playback [CompactDisc only]</param>
|
||||||
/// <param name="autoPlay">True if playback should begin immediately, false otherwise</param>
|
/// <param name="autoPlay">True if playback should begin immediately, false otherwise</param>
|
||||||
/// <param name="defaultVolume">Default volume between 0 and 100 to use when starting playback</param>
|
/// <param name="defaultVolume">Default volume between 0 and 100 to use when starting playback</param>
|
||||||
public void Init(string path, bool generateMissingToc, bool loadDataTracks, bool autoPlay, int defaultVolume)
|
public void Init(string path, bool generateMissingToc, bool loadHiddenTracks, bool loadDataTracks, bool autoPlay, int defaultVolume)
|
||||||
{
|
{
|
||||||
// Stop current playback, if necessary
|
// Stop current playback, if necessary
|
||||||
if(Playing != null) Playing = null;
|
if(Playing != null) Playing = null;
|
||||||
|
|
||||||
// Create and attempt to initialize new Player
|
// Create and attempt to initialize new Player
|
||||||
_player = new Player(path, generateMissingToc, loadDataTracks, autoPlay, defaultVolume);
|
_player = new Player(path, generateMissingToc, loadHiddenTracks, loadDataTracks, autoPlay, defaultVolume);
|
||||||
if(Initialized)
|
if(Initialized)
|
||||||
{
|
{
|
||||||
_player.PropertyChanged += PlayerStateChanged;
|
_player.PropertyChanged += PlayerStateChanged;
|
||||||
@@ -228,8 +229,7 @@ namespace RedBookPlayer.Common
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Move to the previous playable track
|
/// Move to the previous playable track
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
|
public void PreviousTrack() => _player?.PreviousTrack();
|
||||||
public void PreviousTrack(bool playHiddenTrack) => _player?.PreviousTrack(playHiddenTrack);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Move to the next index
|
/// Move to the next index
|
||||||
@@ -241,8 +241,7 @@ namespace RedBookPlayer.Common
|
|||||||
/// Move to the previous index
|
/// Move to the previous index
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="changeTrack">True if index changes can trigger a track change, false otherwise</param>
|
/// <param name="changeTrack">True if index changes can trigger a track change, false otherwise</param>
|
||||||
/// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
|
public void PreviousIndex(bool changeTrack) => _player?.PreviousIndex(changeTrack);
|
||||||
public void PreviousIndex(bool changeTrack, bool playHiddenTrack) => _player?.PreviousIndex(changeTrack, playHiddenTrack);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fast-forward playback by 75 sectors, if possible
|
/// Fast-forward playback by 75 sectors, if possible
|
||||||
@@ -270,6 +269,12 @@ namespace RedBookPlayer.Common
|
|||||||
/// <param name="load">True to enable loading data tracks, false otherwise</param>
|
/// <param name="load">True to enable loading data tracks, false otherwise</param>
|
||||||
public void SetLoadDataTracks(bool load) => _player?.SetLoadDataTracks(load);
|
public void SetLoadDataTracks(bool load) => _player?.SetLoadDataTracks(load);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the value for loading hidden tracks [CompactDisc only]
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="load">True to enable loading hidden tracks, false otherwise</param>
|
||||||
|
public void SetLoadHiddenTracks(bool load) => _player?.SetLoadHiddenTracks(load);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the value for the volume
|
/// Set the value for the volume
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ namespace RedBookPlayer.GUI
|
|||||||
{
|
{
|
||||||
return await Dispatcher.UIThread.InvokeAsync(() =>
|
return await Dispatcher.UIThread.InvokeAsync(() =>
|
||||||
{
|
{
|
||||||
PlayerViewModel.Init(path, App.Settings.GenerateMissingTOC, App.Settings.PlayDataTracks, App.Settings.AutoPlay, App.Settings.Volume);
|
PlayerViewModel.Init(path, App.Settings.GenerateMissingTOC, App.Settings.PlayHiddenTracks, App.Settings.PlayDataTracks, App.Settings.AutoPlay, App.Settings.Volume);
|
||||||
if (PlayerViewModel.Initialized)
|
if (PlayerViewModel.Initialized)
|
||||||
MainWindow.Instance.Title = "RedBookPlayer - " + path.Split('/').Last().Split('\\').Last();
|
MainWindow.Instance.Title = "RedBookPlayer - " + path.Split('/').Last().Split('\\').Last();
|
||||||
|
|
||||||
@@ -66,7 +66,11 @@ namespace RedBookPlayer.GUI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update the view model with new settings
|
/// Update the view model with new settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void UpdateViewModel() => PlayerViewModel.SetLoadDataTracks(App.Settings.PlayDataTracks);
|
public void UpdateViewModel()
|
||||||
|
{
|
||||||
|
PlayerViewModel.SetLoadDataTracks(App.Settings.PlayDataTracks);
|
||||||
|
PlayerViewModel.SetLoadHiddenTracks(App.Settings.PlayHiddenTracks);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate the digit string to be interpreted by the frontend
|
/// Generate the digit string to be interpreted by the frontend
|
||||||
@@ -83,7 +87,7 @@ namespace RedBookPlayer.GUI
|
|||||||
|
|
||||||
int[] numbers = new int[]
|
int[] numbers = new int[]
|
||||||
{
|
{
|
||||||
PlayerViewModel.CurrentTrackNumber + 1,
|
PlayerViewModel.CurrentTrackNumber,
|
||||||
PlayerViewModel.CurrentTrackIndex,
|
PlayerViewModel.CurrentTrackIndex,
|
||||||
|
|
||||||
(int)(sectorTime / (75 * 60)),
|
(int)(sectorTime / (75 * 60)),
|
||||||
@@ -138,7 +142,7 @@ namespace RedBookPlayer.GUI
|
|||||||
ulong sectorTime = PlayerViewModel.CurrentSector;
|
ulong sectorTime = PlayerViewModel.CurrentSector;
|
||||||
if(PlayerViewModel.SectionStartSector != 0)
|
if(PlayerViewModel.SectionStartSector != 0)
|
||||||
sectorTime -= PlayerViewModel.SectionStartSector;
|
sectorTime -= PlayerViewModel.SectionStartSector;
|
||||||
else
|
else if (PlayerViewModel.CurrentTrackNumber > 0)
|
||||||
sectorTime += PlayerViewModel.TimeOffset;
|
sectorTime += PlayerViewModel.TimeOffset;
|
||||||
|
|
||||||
return sectorTime;
|
return sectorTime;
|
||||||
@@ -261,11 +265,11 @@ namespace RedBookPlayer.GUI
|
|||||||
|
|
||||||
public void NextTrackButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.NextTrack();
|
public void NextTrackButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.NextTrack();
|
||||||
|
|
||||||
public void PreviousTrackButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.PreviousTrack(App.Settings.AllowSkipHiddenTrack);
|
public void PreviousTrackButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.PreviousTrack();
|
||||||
|
|
||||||
public void NextIndexButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.NextIndex(App.Settings.IndexButtonChangeTrack);
|
public void NextIndexButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.NextIndex(App.Settings.IndexButtonChangeTrack);
|
||||||
|
|
||||||
public void PreviousIndexButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.PreviousIndex(App.Settings.IndexButtonChangeTrack, App.Settings.AllowSkipHiddenTrack);
|
public void PreviousIndexButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.PreviousIndex(App.Settings.IndexButtonChangeTrack);
|
||||||
|
|
||||||
public void FastForwardButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.FastForward();
|
public void FastForwardButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.FastForward();
|
||||||
|
|
||||||
|
|||||||
@@ -21,9 +21,14 @@ namespace RedBookPlayer.GUI
|
|||||||
public bool IndexButtonChangeTrack { get; set; } = false;
|
public bool IndexButtonChangeTrack { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if the index 0 of track 1 is treated like a hidden track
|
/// Indicates if hidden tracks should be played
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AllowSkipHiddenTrack { get; set; } = false;
|
/// <remarks>
|
||||||
|
/// Hidden tracks can be one of the following:
|
||||||
|
/// - TrackSequence == 0
|
||||||
|
/// - Larget pregap of track 1 (> 150 sectors)
|
||||||
|
/// </remarks>
|
||||||
|
public bool PlayHiddenTracks { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Indicates if data tracks should be played like old, non-compliant players
|
/// Indicates if data tracks should be played like old, non-compliant players
|
||||||
|
|||||||
@@ -17,8 +17,8 @@
|
|||||||
<TextBlock VerticalAlignment="Center">Index navigation can change track</TextBlock>
|
<TextBlock VerticalAlignment="Center">Index navigation can change track</TextBlock>
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
<WrapPanel Margin="0,0,0,16">
|
<WrapPanel Margin="0,0,0,16">
|
||||||
<CheckBox IsChecked="{Binding AllowSkipHiddenTrack}" Margin="0,0,8,0" />
|
<CheckBox IsChecked="{Binding PlayHiddenTracks}" Margin="0,0,8,0" />
|
||||||
<TextBlock VerticalAlignment="Center">Treat index 0 of track 1 as track 0 (hidden track)</TextBlock>
|
<TextBlock VerticalAlignment="Center">Play hidden tracks</TextBlock>
|
||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
<WrapPanel Margin="0,0,0,16">
|
<WrapPanel Margin="0,0,0,16">
|
||||||
<CheckBox IsChecked="{Binding PlayDataTracks}" Margin="0,0,8,0"/>
|
<CheckBox IsChecked="{Binding PlayDataTracks}" Margin="0,0,8,0"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user