diff --git a/README.md b/README.md
index 22a22c2..a8c710e 100644
--- a/README.md
+++ b/README.md
@@ -12,8 +12,10 @@
| --- | ------ |
| **F1** | Open Settings Window |
| **F2** | Load New Image |
+| **S** | Save Track(s) |
| **Space** | Toggle Play / Pause |
| **Esc** | Stop Playback |
+| **~** | Eject |
| **→** | Next Track |
| **←** | Previous Track |
| **]** | Next Index |
@@ -25,6 +27,10 @@
| **M** | Mute |
| **E** | Toggle Emphasis |
+For Save Track(s):
+- Holding no modifying keys will prompt to save the current track
+- Holding **Shift** will prompt to save all tracks (including hidden)
+
For both Volume Up and Volume Down:
- Holding **Ctrl** will move in increments of 2
- Holding **Shift** will move in increments of 5
diff --git a/RedBookPlayer.GUI/ViewModels/MainViewModel.cs b/RedBookPlayer.GUI/ViewModels/MainViewModel.cs
index 9faa1f5..c3a2a0e 100644
--- a/RedBookPlayer.GUI/ViewModels/MainViewModel.cs
+++ b/RedBookPlayer.GUI/ViewModels/MainViewModel.cs
@@ -40,6 +40,23 @@ namespace RedBookPlayer.GUI.ViewModels
PlayerView?.ViewModel?.ExecuteLoad();
}
+ // Save track(s)
+ else if(e.Key == App.Settings.SaveTrackKey)
+ {
+ if(PlayerView?.ViewModel == null || !PlayerView.ViewModel.Initialized)
+ return;
+
+ var dialog = new OpenFolderDialog();
+ string path = await dialog.ShowAsync(App.MainWindow);
+ if(string.IsNullOrWhiteSpace(path))
+ return;
+
+ if(e.KeyModifiers.HasFlag(KeyModifiers.Shift))
+ PlayerView.ViewModel.ExtractAllTracksToWav(path);
+ else
+ PlayerView.ViewModel.ExtractSingleTrackToWav((uint)PlayerView.ViewModel.CurrentTrackNumber, path);
+ }
+
// Toggle playback
else if(e.Key == App.Settings.TogglePlaybackKey || e.Key == Key.MediaPlayPause)
{
@@ -52,6 +69,12 @@ namespace RedBookPlayer.GUI.ViewModels
PlayerView?.ViewModel?.ExecuteStop();
}
+ // Eject
+ else if(e.Key == App.Settings.EjectKey)
+ {
+ PlayerView?.ViewModel?.ExecuteEject();
+ }
+
// Next Track
else if(e.Key == App.Settings.NextTrackKey || e.Key == Key.MediaNextTrack)
{
diff --git a/RedBookPlayer.GUI/ViewModels/PlayerViewModel.cs b/RedBookPlayer.GUI/ViewModels/PlayerViewModel.cs
index 00f92d5..5c25eac 100644
--- a/RedBookPlayer.GUI/ViewModels/PlayerViewModel.cs
+++ b/RedBookPlayer.GUI/ViewModels/PlayerViewModel.cs
@@ -6,11 +6,9 @@ using System.Linq;
using System.Reactive;
using System.Threading.Tasks;
using System.Xml;
-using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;
-using Avalonia.Platform;
using Avalonia.Threading;
using ReactiveUI;
using RedBookPlayer.Models;
@@ -193,6 +191,15 @@ namespace RedBookPlayer.GUI.ViewModels
private set => this.RaiseAndSetIfChanged(ref _dataPlayback, value);
}
+ ///
+ /// Indicates the repeat mode
+ ///
+ public RepeatMode RepeatMode
+ {
+ get => _repeatMode;
+ private set => this.RaiseAndSetIfChanged(ref _repeatMode, value);
+ }
+
///
/// Indicates if de-emphasis should be applied
///
@@ -214,6 +221,7 @@ namespace RedBookPlayer.GUI.ViewModels
private bool _initialized;
private PlayerState _playerState;
private DataPlayback _dataPlayback;
+ private RepeatMode _repeatMode;
private bool _applyDeEmphasis;
private int _volume;
@@ -250,6 +258,11 @@ namespace RedBookPlayer.GUI.ViewModels
///
public ReactiveCommand StopCommand { get; }
+ ///
+ /// Command for ejecting the current disc
+ ///
+ public ReactiveCommand EjectCommand { get; }
+
///
/// Command for moving to the next track
///
@@ -334,6 +347,7 @@ namespace RedBookPlayer.GUI.ViewModels
PauseCommand = ReactiveCommand.Create(ExecutePause);
TogglePlayPauseCommand = ReactiveCommand.Create(ExecuteTogglePlayPause);
StopCommand = ReactiveCommand.Create(ExecuteStop);
+ EjectCommand = ReactiveCommand.Create(ExecuteEject);
NextTrackCommand = ReactiveCommand.Create(ExecuteNextTrack);
PreviousTrackCommand = ReactiveCommand.Create(ExecutePreviousTrack);
NextIndexCommand = ReactiveCommand.Create(ExecuteNextIndex);
@@ -359,15 +373,16 @@ namespace RedBookPlayer.GUI.ViewModels
///
/// Path to the disc image
/// Options to pass to the optical disc factory
+ /// RepeatMode for sound output
/// True if playback should begin immediately, false otherwise
- public void Init(string path, OpticalDiscOptions options, bool autoPlay)
+ public void Init(string path, OpticalDiscOptions options, RepeatMode repeatMode, bool autoPlay)
{
// Stop current playback, if necessary
if(PlayerState != PlayerState.NoDisc)
ExecuteStop();
// Attempt to initialize Player
- _player.Init(path, options, autoPlay);
+ _player.Init(path, options, repeatMode, autoPlay);
if(_player.Initialized)
{
_player.PropertyChanged += PlayerStateChanged;
@@ -397,6 +412,11 @@ namespace RedBookPlayer.GUI.ViewModels
///
public void ExecuteStop() => _player?.Stop();
+ ///
+ /// Eject the currently loaded disc
+ ///
+ public void ExecuteEject() => _player?.Eject();
+
///
/// Move to the next playable track
///
@@ -578,13 +598,14 @@ namespace RedBookPlayer.GUI.ViewModels
DataPlayback = App.Settings.DataPlayback,
GenerateMissingToc = App.Settings.GenerateMissingTOC,
LoadHiddenTracks = App.Settings.PlayHiddenTracks,
+ SessionHandling = App.Settings.SessionHandling,
};
// Ensure the context and view model are set
App.PlayerView.DataContext = this;
App.PlayerView.ViewModel = this;
- Init(path, options, App.Settings.AutoPlay);
+ Init(path, options, App.Settings.RepeatMode, App.Settings.AutoPlay);
if(Initialized)
App.MainWindow.Title = "RedBookPlayer - " + path.Split('/').Last().Split('\\').Last();
@@ -599,8 +620,23 @@ namespace RedBookPlayer.GUI.ViewModels
{
SetDataPlayback(App.Settings.DataPlayback);
SetLoadHiddenTracks(App.Settings.PlayHiddenTracks);
+ SetRepeatMode(App.Settings.RepeatMode);
+ SetSessionHandling(App.Settings.SessionHandling);
}
+ ///
+ /// Extract a single track from the image to WAV
+ ///
+ ///
+ /// Output path to write data to _player?.ExtractSingleTrackToWav(trackNumber, outputDirectory);
+
+ ///
+ /// Extract all tracks from the image to WAV
+ ///
+ /// Output path to write data to _player?.ExtractAllTracksToWav(outputDirectory);
+
///
/// Set data playback method [CompactDisc only]
///
@@ -613,6 +649,18 @@ namespace RedBookPlayer.GUI.ViewModels
/// True to enable loading hidden tracks, false otherwise
public void SetLoadHiddenTracks(bool load) => _player?.SetLoadHiddenTracks(load);
+ ///
+ /// Set repeat mode
+ ///
+ /// New repeat mode value
+ public void SetRepeatMode(RepeatMode repeatMode) => _player?.SetRepeatMode(repeatMode);
+
+ ///
+ /// Set session handling
+ ///
+ /// New session handling value
+ public void SetSessionHandling(SessionHandling sessionHandling) => _player?.SetSessionHandling(sessionHandling);
+
///
/// Generate the digit string to be interpreted by the frontend
///
@@ -754,6 +802,7 @@ namespace RedBookPlayer.GUI.ViewModels
CurrentTrackNumber = _player.CurrentTrackNumber;
CurrentTrackIndex = _player.CurrentTrackIndex;
+ CurrentTrackSession = _player.CurrentTrackSession;
CurrentSector = _player.CurrentSector;
SectionStartSector = _player.SectionStartSector;
@@ -766,6 +815,7 @@ namespace RedBookPlayer.GUI.ViewModels
PlayerState = _player.PlayerState;
DataPlayback = _player.DataPlayback;
+ RepeatMode = _player.RepeatMode;
ApplyDeEmphasis = _player.ApplyDeEmphasis;
Volume = _player.Volume;
diff --git a/RedBookPlayer.GUI/ViewModels/SettingsViewModel.cs b/RedBookPlayer.GUI/ViewModels/SettingsViewModel.cs
index c57e33d..6473f7c 100644
--- a/RedBookPlayer.GUI/ViewModels/SettingsViewModel.cs
+++ b/RedBookPlayer.GUI/ViewModels/SettingsViewModel.cs
@@ -21,6 +21,18 @@ namespace RedBookPlayer.GUI.ViewModels
[JsonIgnore]
public List DataPlaybackValues => GenerateDataPlaybackList();
+ ///
+ /// List of all repeat mode values
+ ///
+ [JsonIgnore]
+ public List RepeatModeValues => GenerateRepeatModeList();
+
+ ///
+ /// List of all session handling values
+ ///
+ [JsonIgnore]
+ public List SessionHandlingValues => GenerateSessionHandlingList();
+
///
/// List of all themes
///
@@ -57,6 +69,16 @@ namespace RedBookPlayer.GUI.ViewModels
///
public DataPlayback DataPlayback { get; set; } = DataPlayback.Skip;
+ ///
+ /// Indicates how to repeat tracks
+ ///
+ public RepeatMode RepeatMode { get; set; } = RepeatMode.All;
+
+ ///
+ /// Indicates how to handle tracks on different sessions
+ ///
+ public SessionHandling SessionHandling { get; set; } = SessionHandling.FirstSessionOnly;
+
///
/// Indicates the default playback volume
///
@@ -102,6 +124,11 @@ namespace RedBookPlayer.GUI.ViewModels
///
public Key LoadImageKey { get; set; } = Key.F2;
+ ///
+ /// Key assigned to save the current track or all tracks
+ ///
+ public Key SaveTrackKey { get; set; } = Key.S;
+
///
/// Key assigned to toggle play and pause
///
@@ -253,6 +280,16 @@ namespace RedBookPlayer.GUI.ViewModels
///
private List GenerateKeyList() => Enum.GetValues(typeof(Key)).Cast().ToList();
+ ///
+ /// Generate the list of RepeatMode values
+ ///
+ private List GenerateRepeatModeList() => Enum.GetValues(typeof(RepeatMode)).Cast().ToList();
+
+ ///
+ /// Generate the list of SessionHandling values
+ ///
+ private List GenerateSessionHandlingList() => Enum.GetValues(typeof(SessionHandling)).Cast().ToList();
+
///
/// Generate the list of valid themes
///
diff --git a/RedBookPlayer.GUI/Views/SettingsWindow.xaml b/RedBookPlayer.GUI/Views/SettingsWindow.xaml
index ab0a8c3..4000a8a 100644
--- a/RedBookPlayer.GUI/Views/SettingsWindow.xaml
+++ b/RedBookPlayer.GUI/Views/SettingsWindow.xaml
@@ -30,6 +30,16 @@
+
+ Session Handling
+
+
+
+ Repeat Mode
+
+
Generate a TOC if the disc is missing one
@@ -78,6 +88,12 @@
Items="{Binding KeyboardList}" SelectedItem="{Binding LoadImageKey, Mode=TwoWay}"
HorizontalAlignment="Right" Margin="8,0,0,0" Width="120"/>
+
+ Save Track(s)
+
+
Toggle Play/Pause
+ public override ushort CurrentTrackSession
+ {
+ get => _currentTrackSession;
+ protected set => this.RaiseAndSetIfChanged(ref _currentTrackSession, value);
+ }
+
///
public override ulong CurrentSector
{
@@ -229,6 +240,11 @@ namespace RedBookPlayer.Models.Discs
///
public bool LoadHiddenTracks { get; set; } = false;
+ ///
+ /// Indicates how tracks on different session should be handled
+ ///
+ public SessionHandling SessionHandling { get; set; } = SessionHandling.AllSessions;
+
private bool _quadChannel;
private bool _isDataTrack;
private bool _copyAllowed;
@@ -248,6 +264,11 @@ namespace RedBookPlayer.Models.Discs
///
private ushort _currentTrackIndex = 0;
+ ///
+ /// Current track session
+ ///
+ private ushort _currentTrackSession = 0;
+
///
/// Current sector number
///
@@ -274,6 +295,7 @@ namespace RedBookPlayer.Models.Discs
DataPlayback = options.DataPlayback;
_generateMissingToc = options.GenerateMissingToc;
LoadHiddenTracks = options.LoadHiddenTracks;
+ SessionHandling = options.SessionHandling;
}
///
@@ -417,6 +439,44 @@ namespace RedBookPlayer.Models.Discs
#region Helpers
+ ///
+ public override void ExtractTrackToWav(uint trackNumber, string outputDirectory)
+ {
+ if(_image == null)
+ return;
+
+ // Get the track with that value, if possible
+ Track track = _image.Tracks.FirstOrDefault(t => t.TrackSequence == trackNumber);
+
+ // If the track isn't valid, we can't do anything
+ if(track == null || track.TrackType != TrackType.Audio)
+ return;
+
+ // Read in the track data to a buffer
+ uint length = (uint)(track.TrackEndSector - track.TrackStartSector);
+ byte[] buffer = _image.ReadSectors(track.TrackStartSector, length);
+
+ // Build the WAV output
+ string filename = Path.Combine(outputDirectory, $"Track {trackNumber.ToString().PadLeft(2, '0')}.wav");
+ using(WaveWriter waveWriter = new WaveWriter(filename, new CSCore.WaveFormat()))
+ {
+ // Write out to the file
+ waveWriter.Write(buffer, 0, buffer.Length);
+ }
+ }
+
+ ///
+ public override void ExtractAllTracksToWav(string outputDirectory)
+ {
+ if(_image == null)
+ return;
+
+ foreach(Track track in _image.Tracks)
+ {
+ ExtractTrackToWav(track.TrackSequence, outputDirectory);
+ }
+ }
+
///
public override void LoadTrack(int trackNumber)
{
diff --git a/RedBookPlayer.Models/Discs/OpticalDiscBase.cs b/RedBookPlayer.Models/Discs/OpticalDiscBase.cs
index e496901..9b041d3 100644
--- a/RedBookPlayer.Models/Discs/OpticalDiscBase.cs
+++ b/RedBookPlayer.Models/Discs/OpticalDiscBase.cs
@@ -23,6 +23,11 @@ namespace RedBookPlayer.Models.Discs
///
public abstract ushort CurrentTrackIndex { get; protected set; }
+ ///
+ /// Current track session
+ ///
+ public abstract ushort CurrentTrackSession { get; protected set; }
+
///
/// Current sector number
///
@@ -122,6 +127,19 @@ namespace RedBookPlayer.Models.Discs
#region Helpers
+ ///
+ /// Extract a track to WAV
+ ///
+ /// Track number to extract
+ /// Output path to write data to
+ /// Extract all tracks to WAV
+ ///
+ /// Output path to write data to
/// Load the desired track, if possible
///
diff --git a/RedBookPlayer.Models/Discs/OpticalDiscOptions.cs b/RedBookPlayer.Models/Discs/OpticalDiscOptions.cs
index 89b1d35..a636c39 100644
--- a/RedBookPlayer.Models/Discs/OpticalDiscOptions.cs
+++ b/RedBookPlayer.Models/Discs/OpticalDiscOptions.cs
@@ -19,6 +19,11 @@ namespace RedBookPlayer.Models.Discs
///
public bool LoadHiddenTracks { get; set; } = false;
+ ///
+ /// Indicates how tracks on different session should be handled
+ ///
+ public SessionHandling SessionHandling { get; set; } = SessionHandling.AllSessions;
+
#endregion
}
}
\ No newline at end of file
diff --git a/RedBookPlayer.Models/Enums.cs b/RedBookPlayer.Models/Enums.cs
index 7063312..4066c37 100644
--- a/RedBookPlayer.Models/Enums.cs
+++ b/RedBookPlayer.Models/Enums.cs
@@ -46,4 +46,41 @@ namespace RedBookPlayer.Models
///
Playing,
}
+
+ ///
+ /// Playback repeat mode
+ ///
+ public enum RepeatMode
+ {
+ ///
+ /// No repeat
+ ///
+ None,
+
+ ///
+ /// Repeat a single track
+ ///
+ Single,
+
+ ///
+ /// Repeat all tracks
+ ///
+ All,
+ }
+
+ ///
+ /// Determine how to handle different sessions
+ ///
+ public enum SessionHandling
+ {
+ ///
+ /// Allow playing tracks from all sessions
+ ///
+ AllSessions = 0,
+
+ ///
+ /// Only play tracks from the first session
+ ///
+ FirstSessionOnly = 1,
+ }
}
\ No newline at end of file
diff --git a/RedBookPlayer.Models/Hardware/Player.cs b/RedBookPlayer.Models/Hardware/Player.cs
index 4f172ab..c22c23e 100644
--- a/RedBookPlayer.Models/Hardware/Player.cs
+++ b/RedBookPlayer.Models/Hardware/Player.cs
@@ -39,6 +39,15 @@ namespace RedBookPlayer.Models.Hardware
private set => this.RaiseAndSetIfChanged(ref _currentTrackIndex, value);
}
+ ///
+ /// Current track session
+ ///
+ public ushort CurrentTrackSession
+ {
+ get => _currentTrackSession;
+ private set => this.RaiseAndSetIfChanged(ref _currentTrackSession, value);
+ }
+
///
/// Current sector number
///
@@ -129,6 +138,7 @@ namespace RedBookPlayer.Models.Hardware
private int _currentTrackNumber;
private ushort _currentTrackIndex;
+ private ushort _currentTrackSession;
private ulong _currentSector;
private ulong _sectionStartSector;
@@ -160,6 +170,15 @@ namespace RedBookPlayer.Models.Hardware
private set => this.RaiseAndSetIfChanged(ref _dataPlayback, value);
}
+ ///
+ /// Indicates the repeat mode
+ ///
+ public RepeatMode RepeatMode
+ {
+ get => _repeatMode;
+ private set => this.RaiseAndSetIfChanged(ref _repeatMode, value);
+ }
+
///
/// Indicates if de-emphasis should be applied
///
@@ -180,6 +199,7 @@ namespace RedBookPlayer.Models.Hardware
private PlayerState _playerState;
private DataPlayback _dataPlayback;
+ private RepeatMode _repeatMode;
private bool _applyDeEmphasis;
private int _volume;
@@ -220,8 +240,9 @@ namespace RedBookPlayer.Models.Hardware
///
/// Path to the disc image
/// Options to pass to the optical disc factory
+ /// RepeatMode for sound output
/// True if playback should begin immediately, false otherwise
- public void Init(string path, OpticalDiscOptions options, bool autoPlay)
+ public void Init(string path, OpticalDiscOptions options, RepeatMode repeatMode, bool autoPlay)
{
// Reset initialization
Initialized = false;
@@ -235,7 +256,7 @@ namespace RedBookPlayer.Models.Hardware
_opticalDisc.PropertyChanged += OpticalDiscStateChanged;
// Initialize the sound output
- _soundOutput.Init(_opticalDisc, autoPlay);
+ _soundOutput.Init(_opticalDisc, repeatMode, autoPlay);
if(_soundOutput == null || !_soundOutput.Initialized)
return;
@@ -323,6 +344,23 @@ namespace RedBookPlayer.Models.Hardware
PlayerState = PlayerState.Stopped;
}
+ ///
+ /// Eject the currently loaded disc
+ ///
+ public void Eject()
+ {
+ if(_opticalDisc == null || !_opticalDisc.Initialized)
+ return;
+ else if(_soundOutput == null)
+ return;
+
+ Stop();
+ _soundOutput.Eject();
+ _opticalDisc = null;
+ PlayerState = PlayerState.NoDisc;
+ Initialized = false;
+ }
+
///
/// Move to the next playable track
///
@@ -493,6 +531,18 @@ namespace RedBookPlayer.Models.Hardware
#region Helpers
+ ///
+ /// Extract a single track from the image to WAV
+ ///
+ ///
+ /// Output path to write data to _opticalDisc?.ExtractTrackToWav(trackNumber, outputDirectory);
+
+ ///
+ /// Extract all tracks from the image to WAV
+ /// Output path to write data to _opticalDisc?.ExtractAllTracksToWav(outputDirectory);
+
///
/// Set data playback method [CompactDisc only]
///
@@ -513,6 +563,22 @@ namespace RedBookPlayer.Models.Hardware
compactDisc.LoadHiddenTracks = load;
}
+ ///
+ /// Set repeat mode
+ ///
+ /// New repeat mode value
+ public void SetRepeatMode(RepeatMode repeatMode) => _soundOutput?.SetRepeatMode(repeatMode);
+
+ ///
+ /// Set the value for session handling [CompactDisc only]
+ ///
+ /// New session handling value
+ public void SetSessionHandling(SessionHandling sessionHandling)
+ {
+ if(_opticalDisc is CompactDisc compactDisc)
+ compactDisc.SessionHandling = sessionHandling;
+ }
+
///
/// Update the player from the current OpticalDisc
///
@@ -547,6 +613,7 @@ namespace RedBookPlayer.Models.Hardware
private void SoundOutputStateChanged(object sender, PropertyChangedEventArgs e)
{
PlayerState = _soundOutput.PlayerState;
+ RepeatMode = _soundOutput.RepeatMode;
ApplyDeEmphasis = _soundOutput.ApplyDeEmphasis;
Volume = _soundOutput.Volume;
}
diff --git a/RedBookPlayer.Models/Hardware/SoundOutput.cs b/RedBookPlayer.Models/Hardware/SoundOutput.cs
index 663e7c9..94b2935 100644
--- a/RedBookPlayer.Models/Hardware/SoundOutput.cs
+++ b/RedBookPlayer.Models/Hardware/SoundOutput.cs
@@ -31,6 +31,15 @@ namespace RedBookPlayer.Models.Hardware
private set => this.RaiseAndSetIfChanged(ref _playerState, value);
}
+ ///
+ /// Indicates the repeat mode
+ ///
+ public RepeatMode RepeatMode
+ {
+ get => _repeatMode;
+ private set => this.RaiseAndSetIfChanged(ref _repeatMode, value);
+ }
+
///
/// Indicates if de-emphasis should be applied
///
@@ -60,6 +69,7 @@ namespace RedBookPlayer.Models.Hardware
private bool _initialized;
private PlayerState _playerState;
+ private RepeatMode _repeatMode;
private bool _applyDeEmphasis;
private int _volume;
@@ -117,8 +127,9 @@ namespace RedBookPlayer.Models.Hardware
/// Initialize the output with a given image
///
/// OpticalDisc to load from
+ /// RepeatMode for sound output
/// True if playback should begin immediately, false otherwise
- public void Init(OpticalDiscBase opticalDisc, bool autoPlay)
+ public void Init(OpticalDiscBase opticalDisc, RepeatMode repeatMode, bool autoPlay)
{
// If we have an unusable disc, just return
if(opticalDisc == null || !opticalDisc.Initialized)
@@ -137,6 +148,9 @@ namespace RedBookPlayer.Models.Hardware
// Setup the audio output
SetupAudio();
+ // Setup the repeat mode
+ RepeatMode = repeatMode;
+
// Initialize playback, if necessary
if(autoPlay)
_soundOut.Play();
@@ -149,6 +163,17 @@ namespace RedBookPlayer.Models.Hardware
_source.Start();
}
+ ///
+ /// Reset the current internal state
+ ///
+ public void Reset()
+ {
+ _soundOut.Stop();
+ _opticalDisc = null;
+ Initialized = false;
+ PlayerState = PlayerState.NoDisc;
+ }
+
///
/// Fill the current byte buffer with playable data
///
@@ -189,6 +214,11 @@ namespace RedBookPlayer.Models.Hardware
int currentTrack = _opticalDisc.CurrentTrackNumber;
_opticalDisc.SetCurrentSector(_opticalDisc.CurrentSector + (ulong)(_currentSectorReadPosition / _opticalDisc.BytesPerSector));
_currentSectorReadPosition %= _opticalDisc.BytesPerSector;
+
+ if(RepeatMode == RepeatMode.None && _opticalDisc.CurrentTrackNumber < currentTrack)
+ Stop();
+ else if(RepeatMode == RepeatMode.Single && _opticalDisc.CurrentTrackNumber != currentTrack)
+ _opticalDisc.LoadTrack(currentTrack);
}
return count;
@@ -229,6 +259,11 @@ namespace RedBookPlayer.Models.Hardware
PlayerState = PlayerState.Stopped;
}
+ ///
+ /// Eject the currently loaded disc
+ ///
+ public void Eject() => Reset();
+
#endregion
#region Helpers
@@ -239,6 +274,12 @@ namespace RedBookPlayer.Models.Hardware
/// New de-emphasis status
public void SetDeEmphasis(bool apply) => ApplyDeEmphasis = apply;
+ ///
+ /// Set repeat mode
+ ///
+ /// New repeat mode value
+ public void SetRepeatMode(RepeatMode repeatMode) => RepeatMode = repeatMode;
+
///
/// Set the value for the volume
///
@@ -253,8 +294,8 @@ namespace RedBookPlayer.Models.Hardware
/// Number of zeroed sectors to concatenate
private void DetermineReadAmount(int count, out ulong sectorsToRead, out ulong zeroSectorsAmount)
{
- // Attempt to read 5 more sectors than requested
- sectorsToRead = ((ulong)count / (ulong)_opticalDisc.BytesPerSector) + 5;
+ // Attempt to read 10 more sectors than requested
+ sectorsToRead = ((ulong)count / (ulong)_opticalDisc.BytesPerSector) + 10;
zeroSectorsAmount = 0;
// Avoid overreads by padding with 0-byte data at the end