View-model and model shouldn't know about settings

This commit is contained in:
Matt Nadareski
2021-07-05 11:55:36 -07:00
parent 8c9f10dd8e
commit d8635594ec
7 changed files with 129 additions and 59 deletions

View File

@@ -52,7 +52,7 @@ namespace RedBookPlayer.Discs
CurrentTrackIndex = track.Indexes.Keys.Min(); CurrentTrackIndex = track.Indexes.Keys.Min();
// If the track is playable, just return // If the track is playable, just return
if(TrackType == TrackType.Audio || App.Settings.PlayDataTracks) if(TrackType == TrackType.Audio || _loadDataTracks)
break; break;
// If we're not playing the track, skip // If we're not playing the track, skip
@@ -196,6 +196,16 @@ namespace RedBookPlayer.Discs
/// </summary> /// </summary>
private ulong _currentSector = 0; private ulong _currentSector = 0;
/// <summary>
/// Indicate if a TOC should be generated if missing
/// </summary>
private readonly bool _generateMissingToc = false;
/// <summary>
/// Indicate if data tracks should be loaded
/// </summary>
private bool _loadDataTracks = false;
/// <summary> /// <summary>
/// Current disc table of contents /// Current disc table of contents
/// </summary> /// </summary>
@@ -203,8 +213,19 @@ namespace RedBookPlayer.Discs
#endregion #endregion
/// <summary>
/// Constructor
/// </summary>
/// <param name="generateMissingToc">Generate a TOC if the disc is missing one</param>
/// <param name="loadDataTracks">Load data tracks for playback</param>
public CompactDisc(bool generateMissingToc, bool loadDataTracks)
{
_generateMissingToc = generateMissingToc;
_loadDataTracks = loadDataTracks;
}
/// <inheritdoc/> /// <inheritdoc/>
public override void Init(IOpticalMediaImage image, bool autoPlay = false) public override void Init(IOpticalMediaImage image, bool autoPlay)
{ {
// If the image is null, we can't do anything // If the image is null, we can't do anything
if(image == null) if(image == null)
@@ -260,7 +281,7 @@ namespace RedBookPlayer.Discs
} }
/// <inheritdoc/> /// <inheritdoc/>
public override bool PreviousIndex(bool changeTrack) public override bool PreviousIndex(bool changeTrack, bool playHiddenTrack)
{ {
if(_image == null) if(_image == null)
return false; return false;
@@ -269,7 +290,7 @@ namespace RedBookPlayer.Discs
{ {
if(changeTrack) if(changeTrack)
{ {
PreviousTrack(); PreviousTrack(playHiddenTrack);
CurrentSector = (ulong)_image.Tracks[CurrentTrackNumber].Indexes.Values.Max(); CurrentSector = (ulong)_image.Tracks[CurrentTrackNumber].Indexes.Values.Max();
return true; return true;
} }
@@ -293,6 +314,12 @@ namespace RedBookPlayer.Discs
LoadTrack(CurrentTrackNumber); LoadTrack(CurrentTrackNumber);
} }
/// <summary>
/// Set the value for loading data tracks
/// </summary>
/// <param name="load">True to enable loading data tracks, false otherwise</param>
public void SetLoadDataTracks(bool load) => _loadDataTracks = load;
/// <inheritdoc/> /// <inheritdoc/>
public override void SetTotalIndexes() public override void SetTotalIndexes()
{ {
@@ -329,7 +356,7 @@ namespace RedBookPlayer.Discs
if(_image.Info.ReadableMediaTags?.Contains(MediaTagType.CD_FullTOC) != true) if(_image.Info.ReadableMediaTags?.Contains(MediaTagType.CD_FullTOC) != true)
{ {
// Only generate the TOC if we have it set // Only generate the TOC if we have it set
if(!App.Settings.GenerateMissingTOC) if(!_generateMissingToc)
{ {
Console.WriteLine("Full TOC not found"); Console.WriteLine("Full TOC not found");
return false; return false;

View File

@@ -90,7 +90,7 @@ namespace RedBookPlayer.Discs
/// </summary> /// </summary>
/// <param name="image">Aaruformat image to load</param> /// <param name="image">Aaruformat image to load</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>
public abstract void Init(IOpticalMediaImage image, bool autoPlay = false); public abstract void Init(IOpticalMediaImage image, bool autoPlay);
#region Seeking #region Seeking
@@ -109,14 +109,15 @@ namespace RedBookPlayer.Discs
/// <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>
public void PreviousTrack() /// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
public void PreviousTrack(bool playHiddenTrack)
{ {
if(_image == null) if(_image == null)
return; return;
if(CurrentSector < (ulong)_image.Tracks[CurrentTrackNumber].Indexes[1] + 75) if(CurrentSector < (ulong)_image.Tracks[CurrentTrackNumber].Indexes[1] + 75)
{ {
if(App.Settings.AllowSkipHiddenTrack && CurrentTrackNumber == 0 && CurrentSector >= 75) if(playHiddenTrack && CurrentTrackNumber == 0 && CurrentSector >= 75)
CurrentSector = 0; CurrentSector = 0;
else else
CurrentTrackNumber--; CurrentTrackNumber--;
@@ -138,8 +139,9 @@ namespace RedBookPlayer.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); public abstract bool PreviousIndex(bool changeTrack, bool playHiddenTrack);
#endregion #endregion

View File

@@ -12,9 +12,11 @@ namespace RedBookPlayer.Discs
/// Generate an OpticalDisc from an input path /// Generate an OpticalDisc from an input path
/// </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="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 autoPlay) public static OpticalDisc GenerateFromPath(string path, bool generateMissingToc, bool loadDataTracks, bool autoPlay)
{ {
try try
{ {
@@ -30,7 +32,7 @@ namespace RedBookPlayer.Discs
image.Open(filter); image.Open(filter);
// Generate and instantiate the disc // Generate and instantiate the disc
return GenerateFromImage(image, autoPlay); return GenerateFromImage(image, generateMissingToc, loadDataTracks, autoPlay);
} }
catch catch
{ {
@@ -43,9 +45,11 @@ namespace RedBookPlayer.Discs
/// Generate an OpticalDisc from an input IOpticalMediaImage /// Generate an OpticalDisc from an input IOpticalMediaImage
/// </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="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 autoPlay) public static OpticalDisc GenerateFromImage(IOpticalMediaImage image, bool generateMissingToc, 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))
@@ -59,7 +63,7 @@ namespace RedBookPlayer.Discs
{ {
case "Compact Disc": case "Compact Disc":
case "GD": case "GD":
opticalDisc = new CompactDisc(); opticalDisc = new CompactDisc(generateMissingToc, loadDataTracks);
break; break;
default: default:
opticalDisc = null; opticalDisc = null;

View File

@@ -121,6 +121,7 @@ namespace RedBookPlayer.GUI
if(e.Key == App.Settings.OpenSettingsKey) if(e.Key == App.Settings.OpenSettingsKey)
{ {
settingsWindow = new SettingsWindow(App.Settings); settingsWindow = new SettingsWindow(App.Settings);
settingsWindow.Closed += OnSettingsClosed;
settingsWindow.Show(); settingsWindow.Show();
} }
@@ -217,6 +218,12 @@ namespace RedBookPlayer.GUI
} }
} }
public void OnSettingsClosed(object sender, EventArgs e)
{
PlayerView playerView = ContentControl.Content as PlayerView;
playerView?.UpdateViewModel();
}
#endregion #endregion
} }
} }

View File

@@ -26,11 +26,16 @@ namespace RedBookPlayer.GUI
/// </summary> /// </summary>
private Image[] _digits; private Image[] _digits;
/// <summary>
/// Initialize the UI based on the default theme
/// </summary>
public PlayerView() : this(null) { }
/// <summary> /// <summary>
/// Initialize the UI based on the currently selected theme /// Initialize the UI based on the currently selected theme
/// </summary> /// </summary>
/// <param name="xaml">XAML data representing the theme, null for default</param> /// <param name="xaml">XAML data representing the theme, null for default</param>
public PlayerView(string xaml = null) public PlayerView(string xaml)
{ {
DataContext = new PlayerViewModel(); DataContext = new PlayerViewModel();
PlayerViewModel.PropertyChanged += PlayerViewModelStateChanged; PlayerViewModel.PropertyChanged += PlayerViewModelStateChanged;
@@ -41,23 +46,6 @@ namespace RedBookPlayer.GUI
#region Helpers #region Helpers
/// <summary>
/// Generate a path selection dialog box
/// </summary>
/// <returns>User-selected path, if possible</returns>
public async Task<string> GetPath()
{
var dialog = new OpenFileDialog { AllowMultiple = false };
List<string> knownExtensions = new Aaru.DiscImages.AaruFormat().KnownExtensions.ToList();
dialog.Filters.Add(new FileDialogFilter()
{
Name = "Aaru Image Format (*" + string.Join(", *", knownExtensions) + ")",
Extensions = knownExtensions.ConvertAll(e => e.TrimStart('.'))
});
return (await dialog.ShowAsync((Window)Parent.Parent))?.FirstOrDefault();
}
/// <summary> /// <summary>
/// Load an image from the path /// Load an image from the path
/// </summary> /// </summary>
@@ -66,7 +54,7 @@ namespace RedBookPlayer.GUI
{ {
return await Dispatcher.UIThread.InvokeAsync(() => return await Dispatcher.UIThread.InvokeAsync(() =>
{ {
PlayerViewModel.Init(path, App.Settings.AutoPlay, App.Settings.Volume); PlayerViewModel.Init(path, App.Settings.GenerateMissingTOC, 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();
@@ -74,6 +62,11 @@ namespace RedBookPlayer.GUI
}); });
} }
/// <summary>
/// Update the view model with new settings
/// </summary>
public void UpdateViewModel() => PlayerViewModel.SetLoadDataTracks(App.Settings.PlayDataTracks);
/// <summary> /// <summary>
/// Generate the digit string to be interpreted by the frontend /// Generate the digit string to be interpreted by the frontend
/// </summary> /// </summary>
@@ -107,21 +100,6 @@ namespace RedBookPlayer.GUI
return string.Join("", numbers.Select(i => i.ToString().PadLeft(2, '0').Substring(0, 2))); return string.Join("", numbers.Select(i => i.ToString().PadLeft(2, '0').Substring(0, 2)));
} }
/// <summary>
/// Get current sector time, accounting for offsets
/// </summary>
/// <returns>ulong representing the current sector time</returns>
private ulong GetCurrentSectorTime()
{
ulong sectorTime = PlayerViewModel.CurrentSector;
if(PlayerViewModel.SectionStartSector != 0)
sectorTime -= PlayerViewModel.SectionStartSector;
else
sectorTime += PlayerViewModel.TimeOffset;
return sectorTime;
}
/// <summary> /// <summary>
/// Load the png image for a given character based on the theme /// Load the png image for a given character based on the theme
/// </summary> /// </summary>
@@ -150,6 +128,38 @@ namespace RedBookPlayer.GUI
} }
} }
/// <summary>
/// Get current sector time, accounting for offsets
/// </summary>
/// <returns>ulong representing the current sector time</returns>
private ulong GetCurrentSectorTime()
{
ulong sectorTime = PlayerViewModel.CurrentSector;
if(PlayerViewModel.SectionStartSector != 0)
sectorTime -= PlayerViewModel.SectionStartSector;
else
sectorTime += PlayerViewModel.TimeOffset;
return sectorTime;
}
/// <summary>
/// Generate a path selection dialog box
/// </summary>
/// <returns>User-selected path, if possible</returns>
private async Task<string> GetPath()
{
var dialog = new OpenFileDialog { AllowMultiple = false };
List<string> knownExtensions = new Aaru.DiscImages.AaruFormat().KnownExtensions.ToList();
dialog.Filters.Add(new FileDialogFilter()
{
Name = "Aaru Image Format (*" + string.Join(", *", knownExtensions) + ")",
Extensions = knownExtensions.ConvertAll(e => e.TrimStart('.'))
});
return (await dialog.ShowAsync((Window)Parent.Parent))?.FirstOrDefault();
}
/// <summary> /// <summary>
/// Initialize the displayed digits array /// Initialize the displayed digits array
/// </summary> /// </summary>
@@ -250,11 +260,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(); public void PreviousTrackButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.PreviousTrack(App.Settings.AllowSkipHiddenTrack);
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); public void PreviousIndexButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.PreviousIndex(App.Settings.IndexButtonChangeTrack, App.Settings.AllowSkipHiddenTrack);
public void FastForwardButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.FastForward(); public void FastForwardButton_Click(object sender, RoutedEventArgs e) => PlayerViewModel.FastForward();

View File

@@ -185,15 +185,17 @@ namespace RedBookPlayer.GUI
/// Initialize the view model with a given image path /// Initialize the view model with a given image path
/// </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="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 autoPlay, int defaultVolume) public void Init(string path, bool generateMissingToc, 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, autoPlay, defaultVolume); _player = new Player(path, generateMissingToc, loadDataTracks, autoPlay, defaultVolume);
if(Initialized) if(Initialized)
{ {
_player.PropertyChanged += PlayerStateChanged; _player.PropertyChanged += PlayerStateChanged;
@@ -226,7 +228,8 @@ namespace RedBookPlayer.GUI
/// <summary> /// <summary>
/// Move to the previous playable track /// Move to the previous playable track
/// </summary> /// </summary>
public void PreviousTrack() => _player?.PreviousTrack(); /// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
public void PreviousTrack(bool playHiddenTrack) => _player?.PreviousTrack(playHiddenTrack);
/// <summary> /// <summary>
/// Move to the next index /// Move to the next index
@@ -238,7 +241,8 @@ namespace RedBookPlayer.GUI
/// 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>
public void PreviousIndex(bool changeTrack) => _player?.PreviousIndex(changeTrack); /// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
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
@@ -260,6 +264,12 @@ namespace RedBookPlayer.GUI
/// <param name="apply"></param> /// <param name="apply"></param>
public void SetDeEmphasis(bool apply) => _player?.SetDeEmphasis(apply); public void SetDeEmphasis(bool apply) => _player?.SetDeEmphasis(apply);
/// <summary>
/// Set the value for loading data tracks [CompactDisc only]
/// </summary>
/// <param name="load">True to enable loading data tracks, false otherwise</param>
public void SetLoadDataTracks(bool load) => _player?.SetLoadDataTracks(load);
/// <summary> /// <summary>
/// Temporarily mute playback /// Temporarily mute playback
/// </summary> /// </summary>

View File

@@ -187,9 +187,11 @@ namespace RedBookPlayer.Hardware
/// Create a new Player from a given image path /// Create a new Player from a given image path
/// </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="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 autoPlay = false, int defaultVolume = 100) public Player(string path, bool generateMissingToc, bool loadDataTracks, bool autoPlay, int defaultVolume)
{ {
// Set the internal state for initialization // Set the internal state for initialization
Initialized = false; Initialized = false;
@@ -197,7 +199,7 @@ namespace RedBookPlayer.Hardware
_soundOutput.SetDeEmphasis(false); _soundOutput.SetDeEmphasis(false);
// Initalize the disc // Initalize the disc
_opticalDisc = OpticalDiscFactory.GenerateFromPath(path, autoPlay); _opticalDisc = OpticalDiscFactory.GenerateFromPath(path, generateMissingToc, loadDataTracks, autoPlay);
if(_opticalDisc == null || !_opticalDisc.Initialized) if(_opticalDisc == null || !_opticalDisc.Initialized)
return; return;
@@ -292,7 +294,8 @@ namespace RedBookPlayer.Hardware
/// <summary> /// <summary>
/// Move to the previous playable track /// Move to the previous playable track
/// </summary> /// </summary>
public void PreviousTrack() /// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
public void PreviousTrack(bool playHiddenTrack)
{ {
if(_opticalDisc == null || !_opticalDisc.Initialized) if(_opticalDisc == null || !_opticalDisc.Initialized)
return; return;
@@ -300,7 +303,7 @@ namespace RedBookPlayer.Hardware
bool? wasPlaying = Playing; bool? wasPlaying = Playing;
if(wasPlaying == true) Pause(); if(wasPlaying == true) Pause();
_opticalDisc.PreviousTrack(); _opticalDisc.PreviousTrack(playHiddenTrack);
if(_opticalDisc is CompactDisc compactDisc) if(_opticalDisc is CompactDisc compactDisc)
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis); _soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
@@ -334,7 +337,8 @@ namespace RedBookPlayer.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>
public void PreviousIndex(bool changeTrack) /// <param name="playHiddenTrack">True to play the hidden track, if it exists</param>
public void PreviousIndex(bool changeTrack, bool playHiddenTrack)
{ {
if(_opticalDisc == null || !_opticalDisc.Initialized) if(_opticalDisc == null || !_opticalDisc.Initialized)
return; return;
@@ -342,7 +346,7 @@ namespace RedBookPlayer.Hardware
bool? wasPlaying = Playing; bool? wasPlaying = Playing;
if(wasPlaying == true) Pause(); if(wasPlaying == true) Pause();
_opticalDisc.PreviousIndex(changeTrack); _opticalDisc.PreviousIndex(changeTrack, playHiddenTrack);
if(_opticalDisc is CompactDisc compactDisc) if(_opticalDisc is CompactDisc compactDisc)
_soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis); _soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis);
@@ -387,6 +391,12 @@ namespace RedBookPlayer.Hardware
/// <param name="apply"></param> /// <param name="apply"></param>
public void SetDeEmphasis(bool apply) => _soundOutput?.SetDeEmphasis(apply); public void SetDeEmphasis(bool apply) => _soundOutput?.SetDeEmphasis(apply);
/// <summary>
/// Set the value for loading data tracks [CompactDisc only]
/// </summary>
/// <param name="load">True to enable loading data tracks, false otherwise</param>
public void SetLoadDataTracks(bool load) => (_opticalDisc as CompactDisc)?.SetLoadDataTracks(load);
/// <summary> /// <summary>
/// Update the player from the current OpticalDisc /// Update the player from the current OpticalDisc
/// </summary> /// </summary>