From d8635594ec8b8b0a427f32757a3150a40816b1c7 Mon Sep 17 00:00:00 2001 From: Matt Nadareski Date: Mon, 5 Jul 2021 11:55:36 -0700 Subject: [PATCH] View-model and model shouldn't know about settings --- RedBookPlayer/Discs/CompactDisc.cs | 37 ++++++++-- RedBookPlayer/Discs/OpticalDisc.cs | 10 +-- RedBookPlayer/Discs/OpticalDiscFactory.cs | 12 ++-- RedBookPlayer/GUI/MainWindow.xaml.cs | 7 ++ RedBookPlayer/GUI/PlayerView.xaml.cs | 82 +++++++++++++---------- RedBookPlayer/GUI/PlayerViewModel.cs | 18 +++-- RedBookPlayer/Hardware/Player.cs | 22 ++++-- 7 files changed, 129 insertions(+), 59 deletions(-) diff --git a/RedBookPlayer/Discs/CompactDisc.cs b/RedBookPlayer/Discs/CompactDisc.cs index 62d8728..f25a7ec 100644 --- a/RedBookPlayer/Discs/CompactDisc.cs +++ b/RedBookPlayer/Discs/CompactDisc.cs @@ -52,7 +52,7 @@ namespace RedBookPlayer.Discs CurrentTrackIndex = track.Indexes.Keys.Min(); // If the track is playable, just return - if(TrackType == TrackType.Audio || App.Settings.PlayDataTracks) + if(TrackType == TrackType.Audio || _loadDataTracks) break; // If we're not playing the track, skip @@ -196,6 +196,16 @@ namespace RedBookPlayer.Discs /// private ulong _currentSector = 0; + /// + /// Indicate if a TOC should be generated if missing + /// + private readonly bool _generateMissingToc = false; + + /// + /// Indicate if data tracks should be loaded + /// + private bool _loadDataTracks = false; + /// /// Current disc table of contents /// @@ -203,8 +213,19 @@ namespace RedBookPlayer.Discs #endregion + /// + /// Constructor + /// + /// Generate a TOC if the disc is missing one + /// Load data tracks for playback + public CompactDisc(bool generateMissingToc, bool loadDataTracks) + { + _generateMissingToc = generateMissingToc; + _loadDataTracks = loadDataTracks; + } + /// - 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(image == null) @@ -260,7 +281,7 @@ namespace RedBookPlayer.Discs } /// - public override bool PreviousIndex(bool changeTrack) + public override bool PreviousIndex(bool changeTrack, bool playHiddenTrack) { if(_image == null) return false; @@ -269,7 +290,7 @@ namespace RedBookPlayer.Discs { if(changeTrack) { - PreviousTrack(); + PreviousTrack(playHiddenTrack); CurrentSector = (ulong)_image.Tracks[CurrentTrackNumber].Indexes.Values.Max(); return true; } @@ -293,6 +314,12 @@ namespace RedBookPlayer.Discs LoadTrack(CurrentTrackNumber); } + /// + /// Set the value for loading data tracks + /// + /// True to enable loading data tracks, false otherwise + public void SetLoadDataTracks(bool load) => _loadDataTracks = load; + /// public override void SetTotalIndexes() { @@ -329,7 +356,7 @@ namespace RedBookPlayer.Discs if(_image.Info.ReadableMediaTags?.Contains(MediaTagType.CD_FullTOC) != true) { // Only generate the TOC if we have it set - if(!App.Settings.GenerateMissingTOC) + if(!_generateMissingToc) { Console.WriteLine("Full TOC not found"); return false; diff --git a/RedBookPlayer/Discs/OpticalDisc.cs b/RedBookPlayer/Discs/OpticalDisc.cs index 701660a..3bc2443 100644 --- a/RedBookPlayer/Discs/OpticalDisc.cs +++ b/RedBookPlayer/Discs/OpticalDisc.cs @@ -90,7 +90,7 @@ namespace RedBookPlayer.Discs /// /// Aaruformat image to load /// True if playback should begin immediately, false otherwise - public abstract void Init(IOpticalMediaImage image, bool autoPlay = false); + public abstract void Init(IOpticalMediaImage image, bool autoPlay); #region Seeking @@ -109,14 +109,15 @@ namespace RedBookPlayer.Discs /// /// Try to move to the previous track, wrapping around if necessary /// - public void PreviousTrack() + /// True to play the hidden track, if it exists + public void PreviousTrack(bool playHiddenTrack) { if(_image == null) return; 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; else CurrentTrackNumber--; @@ -138,8 +139,9 @@ namespace RedBookPlayer.Discs /// Try to move to the previous track index /// /// True if index changes can trigger a track change, false otherwise + /// True to play the hidden track, if it exists /// True if the track was changed, false otherwise - public abstract bool PreviousIndex(bool changeTrack); + public abstract bool PreviousIndex(bool changeTrack, bool playHiddenTrack); #endregion diff --git a/RedBookPlayer/Discs/OpticalDiscFactory.cs b/RedBookPlayer/Discs/OpticalDiscFactory.cs index 178a87a..76ab981 100644 --- a/RedBookPlayer/Discs/OpticalDiscFactory.cs +++ b/RedBookPlayer/Discs/OpticalDiscFactory.cs @@ -12,9 +12,11 @@ namespace RedBookPlayer.Discs /// Generate an OpticalDisc from an input path /// /// Path to load the image from + /// Generate a TOC if the disc is missing one [CompactDisc only] + /// Load data tracks for playback [CompactDisc only] /// True if the image should be playable immediately, false otherwise /// Instantiated OpticalDisc, if possible - public static OpticalDisc GenerateFromPath(string path, bool autoPlay) + public static OpticalDisc GenerateFromPath(string path, bool generateMissingToc, bool loadDataTracks, bool autoPlay) { try { @@ -30,7 +32,7 @@ namespace RedBookPlayer.Discs image.Open(filter); // Generate and instantiate the disc - return GenerateFromImage(image, autoPlay); + return GenerateFromImage(image, generateMissingToc, loadDataTracks, autoPlay); } catch { @@ -43,9 +45,11 @@ namespace RedBookPlayer.Discs /// Generate an OpticalDisc from an input IOpticalMediaImage /// /// IOpticalMediaImage to create from + /// Generate a TOC if the disc is missing one [CompactDisc only] + /// Load data tracks for playback [CompactDisc only] /// True if the image should be playable immediately, false otherwise /// Instantiated OpticalDisc, if possible - 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(!IsUsableImage(image)) @@ -59,7 +63,7 @@ namespace RedBookPlayer.Discs { case "Compact Disc": case "GD": - opticalDisc = new CompactDisc(); + opticalDisc = new CompactDisc(generateMissingToc, loadDataTracks); break; default: opticalDisc = null; diff --git a/RedBookPlayer/GUI/MainWindow.xaml.cs b/RedBookPlayer/GUI/MainWindow.xaml.cs index 9c46297..d95bb98 100644 --- a/RedBookPlayer/GUI/MainWindow.xaml.cs +++ b/RedBookPlayer/GUI/MainWindow.xaml.cs @@ -121,6 +121,7 @@ namespace RedBookPlayer.GUI if(e.Key == App.Settings.OpenSettingsKey) { settingsWindow = new SettingsWindow(App.Settings); + settingsWindow.Closed += OnSettingsClosed; 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 } } \ No newline at end of file diff --git a/RedBookPlayer/GUI/PlayerView.xaml.cs b/RedBookPlayer/GUI/PlayerView.xaml.cs index 2319c97..1a31981 100644 --- a/RedBookPlayer/GUI/PlayerView.xaml.cs +++ b/RedBookPlayer/GUI/PlayerView.xaml.cs @@ -26,11 +26,16 @@ namespace RedBookPlayer.GUI /// private Image[] _digits; + /// + /// Initialize the UI based on the default theme + /// + public PlayerView() : this(null) { } + /// /// Initialize the UI based on the currently selected theme /// /// XAML data representing the theme, null for default - public PlayerView(string xaml = null) + public PlayerView(string xaml) { DataContext = new PlayerViewModel(); PlayerViewModel.PropertyChanged += PlayerViewModelStateChanged; @@ -41,23 +46,6 @@ namespace RedBookPlayer.GUI #region Helpers - /// - /// Generate a path selection dialog box - /// - /// User-selected path, if possible - public async Task GetPath() - { - var dialog = new OpenFileDialog { AllowMultiple = false }; - List 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(); - } - /// /// Load an image from the path /// @@ -66,7 +54,7 @@ namespace RedBookPlayer.GUI { 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) MainWindow.Instance.Title = "RedBookPlayer - " + path.Split('/').Last().Split('\\').Last(); @@ -74,6 +62,11 @@ namespace RedBookPlayer.GUI }); } + /// + /// Update the view model with new settings + /// + public void UpdateViewModel() => PlayerViewModel.SetLoadDataTracks(App.Settings.PlayDataTracks); + /// /// Generate the digit string to be interpreted by the frontend /// @@ -107,21 +100,6 @@ namespace RedBookPlayer.GUI return string.Join("", numbers.Select(i => i.ToString().PadLeft(2, '0').Substring(0, 2))); } - /// - /// Get current sector time, accounting for offsets - /// - /// ulong representing the current sector time - private ulong GetCurrentSectorTime() - { - ulong sectorTime = PlayerViewModel.CurrentSector; - if(PlayerViewModel.SectionStartSector != 0) - sectorTime -= PlayerViewModel.SectionStartSector; - else - sectorTime += PlayerViewModel.TimeOffset; - - return sectorTime; - } - /// /// Load the png image for a given character based on the theme /// @@ -150,6 +128,38 @@ namespace RedBookPlayer.GUI } } + /// + /// Get current sector time, accounting for offsets + /// + /// ulong representing the current sector time + private ulong GetCurrentSectorTime() + { + ulong sectorTime = PlayerViewModel.CurrentSector; + if(PlayerViewModel.SectionStartSector != 0) + sectorTime -= PlayerViewModel.SectionStartSector; + else + sectorTime += PlayerViewModel.TimeOffset; + + return sectorTime; + } + + /// + /// Generate a path selection dialog box + /// + /// User-selected path, if possible + private async Task GetPath() + { + var dialog = new OpenFileDialog { AllowMultiple = false }; + List 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(); + } + /// /// Initialize the displayed digits array /// @@ -250,11 +260,11 @@ namespace RedBookPlayer.GUI 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 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(); diff --git a/RedBookPlayer/GUI/PlayerViewModel.cs b/RedBookPlayer/GUI/PlayerViewModel.cs index 654d3cd..87ebbb4 100644 --- a/RedBookPlayer/GUI/PlayerViewModel.cs +++ b/RedBookPlayer/GUI/PlayerViewModel.cs @@ -185,15 +185,17 @@ namespace RedBookPlayer.GUI /// Initialize the view model with a given image path /// /// Path to the disc image + /// Generate a TOC if the disc is missing one [CompactDisc only] + /// Load data tracks for playback [CompactDisc only] /// True if playback should begin immediately, false otherwise /// Default volume between 0 and 100 to use when starting playback - 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 if(Playing != null) Playing = null; // Create and attempt to initialize new Player - _player = new Player(path, autoPlay, defaultVolume); + _player = new Player(path, generateMissingToc, loadDataTracks, autoPlay, defaultVolume); if(Initialized) { _player.PropertyChanged += PlayerStateChanged; @@ -226,7 +228,8 @@ namespace RedBookPlayer.GUI /// /// Move to the previous playable track /// - public void PreviousTrack() => _player?.PreviousTrack(); + /// True to play the hidden track, if it exists + public void PreviousTrack(bool playHiddenTrack) => _player?.PreviousTrack(playHiddenTrack); /// /// Move to the next index @@ -238,7 +241,8 @@ namespace RedBookPlayer.GUI /// Move to the previous index /// /// True if index changes can trigger a track change, false otherwise - public void PreviousIndex(bool changeTrack) => _player?.PreviousIndex(changeTrack); + /// True to play the hidden track, if it exists + public void PreviousIndex(bool changeTrack, bool playHiddenTrack) => _player?.PreviousIndex(changeTrack, playHiddenTrack); /// /// Fast-forward playback by 75 sectors, if possible @@ -260,6 +264,12 @@ namespace RedBookPlayer.GUI /// public void SetDeEmphasis(bool apply) => _player?.SetDeEmphasis(apply); + /// + /// Set the value for loading data tracks [CompactDisc only] + /// + /// True to enable loading data tracks, false otherwise + public void SetLoadDataTracks(bool load) => _player?.SetLoadDataTracks(load); + /// /// Temporarily mute playback /// diff --git a/RedBookPlayer/Hardware/Player.cs b/RedBookPlayer/Hardware/Player.cs index 870200e..85c2263 100644 --- a/RedBookPlayer/Hardware/Player.cs +++ b/RedBookPlayer/Hardware/Player.cs @@ -187,9 +187,11 @@ namespace RedBookPlayer.Hardware /// Create a new Player from a given image path /// /// Path to the disc image + /// Generate a TOC if the disc is missing one [CompactDisc only] + /// Load data tracks for playback [CompactDisc only] /// True if playback should begin immediately, false otherwise /// Default volume between 0 and 100 to use when starting playback - 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 Initialized = false; @@ -197,7 +199,7 @@ namespace RedBookPlayer.Hardware _soundOutput.SetDeEmphasis(false); // Initalize the disc - _opticalDisc = OpticalDiscFactory.GenerateFromPath(path, autoPlay); + _opticalDisc = OpticalDiscFactory.GenerateFromPath(path, generateMissingToc, loadDataTracks, autoPlay); if(_opticalDisc == null || !_opticalDisc.Initialized) return; @@ -292,7 +294,8 @@ namespace RedBookPlayer.Hardware /// /// Move to the previous playable track /// - public void PreviousTrack() + /// True to play the hidden track, if it exists + public void PreviousTrack(bool playHiddenTrack) { if(_opticalDisc == null || !_opticalDisc.Initialized) return; @@ -300,7 +303,7 @@ namespace RedBookPlayer.Hardware bool? wasPlaying = Playing; if(wasPlaying == true) Pause(); - _opticalDisc.PreviousTrack(); + _opticalDisc.PreviousTrack(playHiddenTrack); if(_opticalDisc is CompactDisc compactDisc) _soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis); @@ -334,7 +337,8 @@ namespace RedBookPlayer.Hardware /// Move to the previous index /// /// True if index changes can trigger a track change, false otherwise - public void PreviousIndex(bool changeTrack) + /// True to play the hidden track, if it exists + public void PreviousIndex(bool changeTrack, bool playHiddenTrack) { if(_opticalDisc == null || !_opticalDisc.Initialized) return; @@ -342,7 +346,7 @@ namespace RedBookPlayer.Hardware bool? wasPlaying = Playing; if(wasPlaying == true) Pause(); - _opticalDisc.PreviousIndex(changeTrack); + _opticalDisc.PreviousIndex(changeTrack, playHiddenTrack); if(_opticalDisc is CompactDisc compactDisc) _soundOutput.SetDeEmphasis(compactDisc.TrackHasEmphasis); @@ -387,6 +391,12 @@ namespace RedBookPlayer.Hardware /// public void SetDeEmphasis(bool apply) => _soundOutput?.SetDeEmphasis(apply); + /// + /// Set the value for loading data tracks [CompactDisc only] + /// + /// True to enable loading data tracks, false otherwise + public void SetLoadDataTracks(bool load) => (_opticalDisc as CompactDisc)?.SetLoadDataTracks(load); + /// /// Update the player from the current OpticalDisc ///