From bc8fd4de31f298d42bb95e2a71e903c1cce11974 Mon Sep 17 00:00:00 2001 From: Zhe Fang Date: Fri, 20 Jun 2025 21:03:43 -0400 Subject: [PATCH] fix: add title and artist as the first line lyrics --- .../BetterLyrics.WinUI3.csproj | 1 + .../Helper/LyricsParser.cs | 12 ++++---- .../Services/IMusicSearchService.cs | 13 ++------ .../Services/MusicSearchService.cs | 30 +++++++++++++++++++ .../Services/PlaybackService.cs | 7 +++++ .../ViewModels/LyricsRendererViewModel.cs | 16 ++++++---- 6 files changed, 56 insertions(+), 23 deletions(-) diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj index f0a0c9e..279a271 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/BetterLyrics.WinUI3.csproj @@ -28,6 +28,7 @@ + diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs index 8470ac8..0209c51 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Helper/LyricsParser.cs @@ -24,7 +24,7 @@ namespace BetterLyrics.WinUI3.Helper switch (lyricsFormat) { case LyricsFormat.Lrc: - ParseLyricsFromLrc(raw); + ParseLyricsFromLrc(raw, durationMs); break; case LyricsFormat.DecryptedQrc: ParseLyricsFromQrc(raw, durationMs); @@ -34,9 +34,7 @@ namespace BetterLyrics.WinUI3.Helper } if ( - title != null - && artist != null - && _lyricsLines != null + _lyricsLines != null && _lyricsLines.Count > 0 && _lyricsLines[0].StartTimestampMs > 0 ) @@ -47,7 +45,7 @@ namespace BetterLyrics.WinUI3.Helper { StartTimestampMs = 0, EndTimestampMs = _lyricsLines[0].StartTimestampMs, - Texts = [$"{artist} - {title}"], + Texts = [artist != null && title != null ? $"{artist} - {title}" : ""], } ); } @@ -59,7 +57,7 @@ namespace BetterLyrics.WinUI3.Helper /// /// /// - private void ParseLyricsFromLrc(string raw) + private void ParseLyricsFromLrc(string raw, int durationMs) { Track track = new() { Lyrics = new() }; track.Lyrics.ParseLRC(raw); @@ -81,7 +79,7 @@ namespace BetterLyrics.WinUI3.Helper } else { - endTimestampMs = (int)track.DurationMs; + endTimestampMs = durationMs; } lyricsLine ??= new LyricsLine { StartTimestampMs = startTimestampMs }; diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IMusicSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IMusicSearchService.cs index 58fc3b5..84f5be3 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IMusicSearchService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/IMusicSearchService.cs @@ -6,17 +6,6 @@ namespace BetterLyrics.WinUI3.Services { public interface IMusicSearchService { - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Return a tuple (raw lyrics, lyrics format, album art) Task<(string?, LyricsFormat?)> SearchLyricsAsync( string title, string artist, @@ -24,5 +13,7 @@ namespace BetterLyrics.WinUI3.Services double durationMs = 0.0, MusicSearchMatchMode matchMode = MusicSearchMatchMode.TitleAndArtist ); + + byte[]? SearchAlbumArtAsync(string title, string artist); } } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MusicSearchService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MusicSearchService.cs index 90c9e37..7b14c50 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MusicSearchService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/MusicSearchService.cs @@ -30,6 +30,36 @@ namespace BetterLyrics.WinUI3.Services ); } + public byte[]? SearchAlbumArtAsync(string title, string artist) + { + foreach (var path in _settingsService.MusicLibraries) + { + if (Directory.Exists(path)) + { + foreach ( + var file in Directory.GetFiles(path, $"*.*", SearchOption.AllDirectories) + ) + { + if (file.Contains(title) && file.Contains(artist)) + { + Track track = new(file); + if (track.Lyrics.SynchronizedLyrics.Count > 0) + { + // Get synchronized lyrics from the track (metadata) + var bytes = track.EmbeddedPictures.FirstOrDefault()?.PictureData; + if (bytes != null) + { + return bytes; + } + } + } + } + } + } + + return null; + } + public async Task<(string?, LyricsFormat?)> SearchLyricsAsync( string title, string artist, diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs index 0354b7c..9f69571 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/Services/PlaybackService.cs @@ -58,6 +58,13 @@ namespace BetterLyrics.WinUI3.Services { SongInfo.AlbumArt = await ImageHelper.ToByteArrayAsync(streamReference); } + else + { + SongInfo.AlbumArt = _musicSearchService.SearchAlbumArtAsync( + SongInfo.Title, + SongInfo.Artist + ); + } SongInfoChanged?.Invoke(this, new SongInfoChangedEventArgs(SongInfo)); } diff --git a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs index f3ad824..f17c121 100644 --- a/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs +++ b/BetterLyrics.WinUI3/BetterLyrics.WinUI3/ViewModels/LyricsRendererViewModel.cs @@ -238,10 +238,10 @@ namespace BetterLyrics.WinUI3.ViewModels _isRelayoutNeeded = true; LyricsStatus = LyricsStatus.Loading; (var lyricsRaw, var lyricsFormat) = await _musicSearchService.SearchLyricsAsync( - SongInfo.Title, - SongInfo.Artist, - SongInfo.Album, - SongInfo.DurationMs ?? 0 + SongInfo?.Title ?? "", + SongInfo?.Artist ?? "", + SongInfo?.Album ?? "", + SongInfo?.DurationMs ?? 0 ); if (lyricsRaw == null) @@ -250,7 +250,13 @@ namespace BetterLyrics.WinUI3.ViewModels } else { - _lyrics = new LyricsParser().Parse(lyricsRaw, lyricsFormat); + _lyrics = new LyricsParser().Parse( + lyricsRaw, + lyricsFormat, + SongInfo.Title, + SongInfo.Artist, + (int)(SongInfo.DurationMs) + ); _isRelayoutNeeded = true; LyricsStatus = LyricsStatus.Found; }