Refactor code structure for improved readability and maintainability

This commit is contained in:
Zhe Fang
2025-06-03 19:13:19 -04:00
parent f24e8b5fcd
commit 4304912395
15 changed files with 118 additions and 86 deletions

View File

@@ -10,7 +10,7 @@
<Identity
Name="37412.BetterLyrics"
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
Version="1.0.0.0" />
Version="1.0.1.0" />
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>

View File

@@ -8,6 +8,7 @@ using Microsoft.UI;
using Microsoft.UI.Xaml.Media.Imaging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Windows.Graphics.Imaging;
using Windows.Media.Control;
@@ -99,9 +100,11 @@ namespace BetterLyrics.WinUI3.ViewModels {
}
public async Task<(List<LyricsLine>, CanvasBitmap?)> SetSongInfoAsync(GlobalSystemMediaTransportControlsSessionMediaProperties? mediaProps, ICanvasAnimatedControl control) {
public async Task<(List<LyricsLine>, SoftwareBitmap?, uint, uint)> SetSongInfoAsync(GlobalSystemMediaTransportControlsSessionMediaProperties? mediaProps, ICanvasAnimatedControl control) {
CanvasBitmap? canvasBitmap = null;
SoftwareBitmap? coverSoftwareBitmap = null;
uint coverImagePixelWidth = 0;
uint coverImagePixelHeight = 0;
Title = mediaProps?.Title;
Artist = mediaProps?.Artist;
@@ -128,14 +131,19 @@ namespace BetterLyrics.WinUI3.ViewModels {
CoverImageDominantColors[i] = Colors.Transparent;
}
} else {
canvasBitmap = await CanvasBitmap.LoadAsync(control, stream);
stream.Seek(0);
CoverImage = new BitmapImage();
await CoverImage.SetSourceAsync(stream);
stream.Seek(0);
var decoder = await BitmapDecoder.CreateAsync(stream);
coverImagePixelHeight = decoder.PixelHeight;
coverImagePixelWidth = decoder.PixelWidth;
coverSoftwareBitmap = await decoder.GetSoftwareBitmapAsync(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied
);
var quantizedColors = await _colorThief.GetPalette(decoder, 3);
for (int i = 0; i < 3; i++) {
Helper.QuantizedColor quantizedColor = quantizedColors[i];
@@ -146,7 +154,7 @@ namespace BetterLyrics.WinUI3.ViewModels {
stream.Dispose();
}
return (GetLyrics(track), canvasBitmap);
return (GetLyrics(track), coverSoftwareBitmap, coverImagePixelWidth, coverImagePixelHeight);
}

View File

@@ -25,6 +25,7 @@ using Windows.Media.Control;
using Color = Windows.UI.Color;
using System.Linq;
using Microsoft.UI.Windowing;
using Windows.Graphics.Imaging;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
@@ -40,7 +41,9 @@ namespace BetterLyrics.WinUI3.Views {
private List<LyricsLine> _lyricsLines = [];
private CanvasBitmap? _canvasCoverBitmap;
private SoftwareBitmap? _coverSoftwareBitmap = null;
private uint _coverImagePixelWidth = 0;
private uint _coverImagePixelHeight = 0;
private float _coverBitmapRotateAngle = 0f;
private float _coverScaleFactor = 1;
@@ -260,7 +263,7 @@ namespace BetterLyrics.WinUI3.Views {
ViewModel.AboutToUpdateUI = true;
await Task.Delay(_animationDurationMs);
(_lyricsLines, _canvasCoverBitmap) = await ViewModel.SetSongInfoAsync(mediaProps, LyricsCanvas);
(_lyricsLines, _coverSoftwareBitmap, _coverImagePixelWidth, _coverImagePixelHeight) = await ViewModel.SetSongInfoAsync(mediaProps, LyricsCanvas);
// Force to show lyrics and scroll to current line even if the music is not playing
LyricsCanvas.Paused = false;
@@ -311,7 +314,7 @@ namespace BetterLyrics.WinUI3.Views {
var b = _lyricsColor.B;
// Draw (dynamic) cover image as the very first layer
if (_settingsService.IsCoverOverlayEnabled && _canvasCoverBitmap != null) {
if (_settingsService.IsCoverOverlayEnabled && _coverSoftwareBitmap != null) {
DrawCoverImage(sender, ds, _settingsService.IsDynamicCoverOverlay);
}
@@ -458,7 +461,6 @@ namespace BetterLyrics.WinUI3.Views {
}
private void DrawCoverImage(ICanvasAnimatedControl control, CanvasDrawingSession ds, bool dynamic) {
if (_settingsService.IsCoverOverlayEnabled && _canvasCoverBitmap != null) {
ds.Transform = Matrix3x2.CreateRotation(_coverBitmapRotateAngle, control.Size.ToVector2() * 0.5f);
@@ -470,17 +472,16 @@ namespace BetterLyrics.WinUI3.Views {
InterpolationMode = CanvasImageInterpolation.HighQualityCubic,
BorderMode = EffectBorderMode.Hard,
Scale = new Vector2(_coverScaleFactor),
Source = _canvasCoverBitmap,
Source = CanvasBitmap.CreateFromSoftwareBitmap(control, _coverSoftwareBitmap),
}
}
};
ds.DrawImage(
coverOverlayEffect,
(float)control.Size.Width / 2 - _canvasCoverBitmap.SizeInPixels.Width * _coverScaleFactor / 2,
(float)control.Size.Height / 2 - _canvasCoverBitmap.SizeInPixels.Height * _coverScaleFactor / 2);
(float)control.Size.Width / 2 - _coverImagePixelWidth * _coverScaleFactor / 2,
(float)control.Size.Height / 2 - _coverImagePixelHeight * _coverScaleFactor / 2);
ds.Transform = Matrix3x2.Identity;
}
}
private void DrawGradientOpacityMask(ICanvasAnimatedControl control, CanvasDrawingSession ds, byte r, byte g, byte b) {
byte verticalEdgeAlpha = (byte)(255 * _settingsService.LyricsVerticalEdgeOpacity / 100f);
@@ -509,13 +510,11 @@ namespace BetterLyrics.WinUI3.Views {
_lyricsGlowEffectAngle %= MathF.PI * 2;
}
if (_settingsService.IsCoverOverlayEnabled && _canvasCoverBitmap != null) {
if (_settingsService.IsCoverOverlayEnabled && _coverSoftwareBitmap != null) {
var diagonal = Math.Sqrt(Math.Pow(_lyricsAreaWidth, 2) + Math.Pow(_lyricsAreaHeight, 2));
_coverScaleFactor = (float)diagonal / Math.Min(
_canvasCoverBitmap.SizeInPixels.Width,
_canvasCoverBitmap.SizeInPixels.Height);
_coverScaleFactor = (float)diagonal / Math.Min(_coverImagePixelWidth, _coverImagePixelHeight);
}

View File

@@ -3,6 +3,7 @@
Local song lyrics presentation app built with WinUI3
## Highlighted features
- Dynamic blur album art as background
- Smooth lyrics fade in/out, zoom in/out effects
- Smooth user interface change from song to song
@@ -17,11 +18,13 @@ Coding in progress...
We provide more than one setting item to better align with your preference
- Theme
- Follow system
- Light
- Dark
- Backdrop
- None
- Mica
- Mica alt
@@ -31,17 +34,19 @@ We provide more than one setting item to better align with your preference
- Transparent
- Album art as background
- Dynamic
- Opacity
- Blur amount
- Lyrics
- Alignment
- Font size
- Line spacing
- Opacity on the edge
- Blur amount
- Glow effect
- Dynamic glow effect
- Language
- English
@@ -49,33 +54,42 @@ We provide more than one setting item to better align with your preference
- Traditional Chinese
## Inspired by
- [BetterNCM](https://github.com/std-microblock/BetterNCM)
- [Lyricify-App](https://github.com/WXRIW/Lyricify-App)
- [椒盐音乐 Salt Player](https://moriafly.com/program/salt-player)
## Demonstration video
See our latest introduction video「BetterLyrics 阶段性开发成果展示」on [Bilibili](https://b23.tv/QjKkYmL)
![alt text](Screenshots/Beelink-SER-8-Moonlight2025-06-0318-35-35-ezgif.com-video-to-gif-converter.gif)
## Screenshots (outdated)
Or watch our introduction video「BetterLyrics 阶段性开发成果展示」(uploaded on 31 May 2025) on Bilibili below (click the cover image to watch):
[![Bilibili](https://i1.hdslb.com/bfs/archive/75a7a1a3803b617574090a91c59785b6c40d0fe5.jpg@672w_378h_1c.avif)](https://b23.tv/QjKkYmL)
## Screenshots
### Split view
![alt text](Screenshots/Snipaste_2025-06-03_16-46-55.png)
![alt text](Screenshots/Snipaste_2025-06-03_16-47-43.png)
![alt text](Screenshots/Snipaste_2025-06-03_17-51-22.png)
### Fullscreen
![alt text](Screenshots/Snipaste_2025-06-03_17-52-51.png)
![alt text](Screenshots/Snipaste_2025-06-03_17-53-07.png)
![alt text](Screenshots/Snipaste_2025-06-03_18-36-05.png)
### Settings
![Settings](/Screenshots/settings.png)
### Light music mode
Will be activated automatically when lyrics are not detected/found
![Light music mode](/Screenshots/light-music.png)
### General music mode
![General music mode](/Screenshots/general-music.png)
### Real-time gif
![Real-time gif](/Screenshots/lyrics-animation.gif)
![alt text](Screenshots/Snipaste_2025-06-03_17-51-52.png)
![alt text](Screenshots/Snipaste_2025-06-03_17-52-00.png)
![alt text](Screenshots/Snipaste_2025-06-03_17-52-05.png)
![alt text](Screenshots/Snipaste_2025-06-03_17-52-11.png)
## Many thanks to
- [Audio Tools Library (ATL) for .NET](https://github.com/Zeugma440/atldotnet)
- [DevWinUI](https://github.com/ghost1372/DevWinUI)
- [Stackoverflow - How to animate Margin property in WPF](https://stackoverflow.com/a/21542882/11048731)
@@ -85,17 +99,28 @@ Will be activated automatically when lyrics are not detected/found
- [Win2D 中的游戏循环CanvasAnimatedControl](https://www.cnblogs.com/walterlv/p/10236395.html)
- [r2d2rigo/Win2D-Samples](https://github.com/r2d2rigo/Win2D-Samples/blob/master/IrisBlurWin2D/IrisBlurWin2D/MainPage.xaml.cs)
## Third-party libraries that this app uses
- CommunityToolkit.Labs.WinUI.MarqueeText
- CommunityToolkit.Labs.WinUI.OpacityMaskView
- CommunityToolkit.Mvvm
- CommunityToolkit.WinUI.Controls.Primitives
- CommunityToolkit.WinUI.Extensions
- DevWinUI
- DevWinUI.Controls
- Microsoft.Extensions.DependencyInjection
- Microsoft.Graphics.Win2D
- Microsoft.Windows.SDK.BuildTools
- Microsoft.WindowsAppSDK
- Microsoft.Xaml.Behaviors.WinUI.Managed
- z440.atl.core
## Third-party libraries that this project uses
```
<PackageReference Include="CommunityToolkit.Labs.WinUI.MarqueeText" Version="0.1.230830" />
<PackageReference Include="CommunityToolkit.Labs.WinUI.OpacityMaskView" Version="0.1.250513-build.2126" />
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageReference Include="CommunityToolkit.WinUI.Behaviors" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Controls.SettingsControls" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Converters" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Extensions" Version="8.2.250402" />
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
<PackageReference Include="DevWinUI" Version="8.2.0" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.5" />
<PackageReference Include="Microsoft.Graphics.Win2D" Version="1.3.2" />
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" Version="10.0.26100.4188" />
<PackageReference Include="Microsoft.WindowsAppSDK" Version="1.7.250513003" />
<PackageReference Include="Microsoft.Xaml.Behaviors.WinUI.Managed" Version="3.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="sqlite-net-pcl" Version="1.9.172" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.5" />
<PackageReference Include="Ude.NetStandard" Version="1.2.0" />
<PackageReference Include="z440.atl.core" Version="6.24.0" />
```
## Any issues and PRs are welcomed

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 175 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 KiB