Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c43b69b4cb | ||
|
|
94b22552e5 | ||
|
|
6deb16f6cb | ||
|
|
e467ab9c73 | ||
|
|
ea038c9c56 | ||
|
|
560250ad30 | ||
|
|
536acc69a5 | ||
|
|
0bbb379912 | ||
|
|
1f4d29e6f2 | ||
|
|
5d1d7476c9 | ||
|
|
e016baefe1 | ||
|
|
70b6194788 | ||
|
|
9f103b0ea3 | ||
|
|
2924140f95 | ||
|
|
3d3f168926 | ||
|
|
63b2285a36 |
@@ -12,7 +12,7 @@
|
||||
<Identity
|
||||
Name="37412.BetterLyrics"
|
||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||
Version="1.0.73.0" />
|
||||
Version="1.0.76.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
|
||||
@@ -21,11 +21,14 @@ namespace BetterLyrics.WinUI3.Models
|
||||
public partial double? DurationMs { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string? SourceAppUserModelId { get; set; } = null;
|
||||
public partial string? PlayerId { get; set; } = null;
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string Title { get; set; }
|
||||
|
||||
[ObservableProperty]
|
||||
public partial string? SongId { get; set; } = null;
|
||||
|
||||
public SongInfo() { }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
public interface ILyricsSearchService
|
||||
{
|
||||
Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token);
|
||||
Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, string? songId, CancellationToken token);
|
||||
|
||||
Task<List<LyricsSearchResult>> SearchAllAsync(string title, string artist, string album, double durationMs, CancellationToken token);
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, CancellationToken token)
|
||||
public async Task<LyricsSearchResult> SearchSmartlyAsync(string mediaSessionId, string title, string artist, string album, double durationMs, string? songId, CancellationToken token)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult();
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
var targetProvider = found.LyricsSearchProvider;
|
||||
if (targetProvider != null)
|
||||
{
|
||||
return await SearchSingleAsync(targetProvider.Value, overridenTitle, overridenArtist, album, durationMs, token);
|
||||
return await SearchSingleAsync(targetProvider.Value, overridenTitle, overridenArtist, album, durationMs, songId, token);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
continue;
|
||||
}
|
||||
|
||||
lyricsSearchResult = await SearchSingleAsync(provider.Provider, overridenTitle, overridenArtist, album, durationMs, token);
|
||||
lyricsSearchResult = await SearchSingleAsync(provider.Provider, overridenTitle, overridenArtist, album, durationMs, null, token);
|
||||
|
||||
if (lyricsSearchResult.IsFound)
|
||||
{
|
||||
@@ -151,13 +151,13 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
var results = new List<LyricsSearchResult>();
|
||||
foreach (var provider in Enum.GetValues<LyricsSearchProvider>())
|
||||
{
|
||||
var searchResult = await SearchSingleAsync(provider, title, artist, album, durationMs, token);
|
||||
var searchResult = await SearchSingleAsync(provider, title, artist, album, durationMs, null, token);
|
||||
results.Add(searchResult);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
private async Task<LyricsSearchResult> SearchSingleAsync(LyricsSearchProvider provider, string title, string artist, string album, double durationMs, CancellationToken token)
|
||||
private async Task<LyricsSearchResult> SearchSingleAsync(LyricsSearchProvider provider, string title, string artist, string album, double durationMs, string? songId, CancellationToken token)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult
|
||||
{
|
||||
@@ -200,13 +200,13 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
lyricsSearchResult = await SearchLrcLibAsync(title, artist, album, (int)(durationMs / 1000));
|
||||
break;
|
||||
case LyricsSearchProvider.QQ:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.QQMusic);
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.QQMusic);
|
||||
break;
|
||||
case LyricsSearchProvider.Kugou:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Kugou);
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.Kugou);
|
||||
break;
|
||||
case LyricsSearchProvider.Netease:
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, Searchers.Netease);
|
||||
lyricsSearchResult = await SearchQQNeteaseKugouAsync(title, artist, album, (int)durationMs, songId, Searchers.Netease);
|
||||
break;
|
||||
case LyricsSearchProvider.AmllTtmlDb:
|
||||
lyricsSearchResult = await SearchAmllTtmlDbAsync(title, artist);
|
||||
@@ -436,7 +436,7 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
return lyricsSearchResult;
|
||||
}
|
||||
|
||||
private static async Task<LyricsSearchResult> SearchQQNeteaseKugouAsync(string title, string artist, string album, int durationMs, Searchers searchers)
|
||||
private static async Task<LyricsSearchResult> SearchQQNeteaseKugouAsync(string title, string artist, string album, int durationMs, string? songId, Searchers searchers)
|
||||
{
|
||||
var lyricsSearchResult = new LyricsSearchResult();
|
||||
|
||||
@@ -457,15 +457,23 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
break;
|
||||
}
|
||||
|
||||
var result = await SearchersHelper.GetSearcher(searchers).SearchForResult(
|
||||
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
|
||||
{
|
||||
DurationMs = durationMs,
|
||||
Album = album,
|
||||
Artists = [artist],
|
||||
Title = title,
|
||||
}
|
||||
);
|
||||
ISearchResult? result;
|
||||
if (searchers == Searchers.Netease && songId != null)
|
||||
{
|
||||
result = new NeteaseSearchResult(title, [artist], album, null, durationMs, songId);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await SearchersHelper.GetSearcher(searchers).SearchForResult(
|
||||
new Lyricify.Lyrics.Models.TrackMultiArtistMetadata()
|
||||
{
|
||||
DurationMs = durationMs,
|
||||
Album = album,
|
||||
Artists = [artist],
|
||||
Title = title,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (result is QQMusicSearchResult qqResult)
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
}
|
||||
|
||||
byte[]? bytes = await Task.Run(async () => await _albumArtSearchService.SearchAsync(
|
||||
SongInfo?.SourceAppUserModelId ?? "",
|
||||
SongInfo?.PlayerId ?? "",
|
||||
_cachedSongInfo.Title,
|
||||
_cachedSongInfo.Artist,
|
||||
_cachedSongInfo?.Album ?? string.Empty,
|
||||
|
||||
@@ -156,11 +156,12 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
SongInfo.Title, SongInfo.Artist, SongInfo.Album, SongInfo.DurationMs);
|
||||
|
||||
var lyricsSearchResult = await Task.Run(async () => await _lyrcsSearchService.SearchSmartlyAsync(
|
||||
SongInfo.SourceAppUserModelId ?? "",
|
||||
SongInfo.PlayerId ?? "",
|
||||
SongInfo.Title,
|
||||
SongInfo.Artist,
|
||||
SongInfo.Album ?? "",
|
||||
SongInfo.DurationMs ?? 0,
|
||||
SongInfo.SongId,
|
||||
token
|
||||
), token);
|
||||
if (token.IsCancellationRequested) return;
|
||||
|
||||
@@ -284,21 +284,21 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
if (!_mediaManager.IsStarted) return;
|
||||
if (mediaSession == null) return;
|
||||
|
||||
string id = mediaSession.Id;
|
||||
string sessionId = mediaSession.Id;
|
||||
|
||||
var desiredSession = GetCurrentSession();
|
||||
|
||||
//RecordMediaSourceProviderInfo(mediaSession);
|
||||
if (mediaSession != desiredSession) return;
|
||||
|
||||
if (!IsMediaSourceEnabled(id))
|
||||
if (!IsMediaSourceEnabled(sessionId))
|
||||
{
|
||||
_cachedSongInfo = null;
|
||||
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
||||
|
||||
if (id == Constants.PlayerID.LXMusic)
|
||||
if (sessionId == Constants.PlayerID.LXMusic)
|
||||
{
|
||||
StopSSE();
|
||||
}
|
||||
@@ -313,38 +313,39 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
currentMediaSourceProviderInfo?.PositionOffset = 0;
|
||||
}
|
||||
|
||||
if (id == Constants.PlayerID.AppleMusic || id == Constants.PlayerID.AppleMusicAlternative)
|
||||
{
|
||||
string fixedArtist = mediaProperties.Artist.Split(" — ").FirstOrDefault() ?? mediaProperties.Artist;
|
||||
string fixedAlbum = mediaProperties.Artist.Split(" — ").LastOrDefault() ?? mediaProperties.AlbumTitle;
|
||||
string fixedArtist = mediaProperties.Artist;
|
||||
string fixedAlbum = mediaProperties.AlbumTitle;
|
||||
string? songId = null;
|
||||
|
||||
_cachedSongInfo = new SongInfo
|
||||
{
|
||||
Title = mediaProperties.Title,
|
||||
Artist = fixedArtist,
|
||||
Album = fixedAlbum,
|
||||
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
|
||||
SourceAppUserModelId = id,
|
||||
};
|
||||
}
|
||||
else
|
||||
if (sessionId == Constants.PlayerID.AppleMusic || sessionId == Constants.PlayerID.AppleMusicAlternative)
|
||||
{
|
||||
_cachedSongInfo = new SongInfo
|
||||
fixedArtist = mediaProperties.Artist.Split(" — ").FirstOrDefault() ?? mediaProperties.Artist;
|
||||
fixedAlbum = mediaProperties.Artist.Split(" — ").LastOrDefault() ?? mediaProperties.AlbumTitle;
|
||||
}
|
||||
else if (sessionId == Constants.PlayerID.NetEaseCloudMusic)
|
||||
{
|
||||
songId = mediaProperties.Genres.FirstOrDefault()?.Replace("NCM-", "");
|
||||
if (songId != null && songId.Length != 10)
|
||||
{
|
||||
Title = mediaProperties.Title,
|
||||
Artist = mediaProperties.Artist,
|
||||
Album = mediaProperties.AlbumTitle,
|
||||
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
|
||||
SourceAppUserModelId = id,
|
||||
};
|
||||
songId = null;
|
||||
}
|
||||
}
|
||||
|
||||
_cachedSongInfo = new SongInfo
|
||||
{
|
||||
Title = mediaProperties.Title,
|
||||
Artist = fixedArtist,
|
||||
Album = fixedAlbum,
|
||||
DurationMs = mediaSession.ControlSession.GetTimelineProperties().EndTime.TotalMilliseconds,
|
||||
PlayerId = sessionId,
|
||||
SongId = songId
|
||||
};
|
||||
_cachedSongInfo.Duration = (int)(_cachedSongInfo.DurationMs / 1000f);
|
||||
|
||||
_logger.LogInformation("Media properties changed: Title: {Title}, Artist: {Artist}, Album: {Album}",
|
||||
mediaProperties.Title, mediaProperties.Artist, mediaProperties.AlbumTitle);
|
||||
|
||||
if (id == Constants.PlayerID.LXMusic)
|
||||
if (sessionId == Constants.PlayerID.LXMusic)
|
||||
{
|
||||
StartSSE();
|
||||
}
|
||||
@@ -353,7 +354,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
StopSSE();
|
||||
}
|
||||
|
||||
if (id == Constants.PlayerID.LXMusic && _lxMusicAlbumArtBytes != null)
|
||||
if (sessionId == Constants.PlayerID.LXMusic && _lxMusicAlbumArtBytes != null)
|
||||
{
|
||||
_SMTCAlbumArtBytes = _lxMusicAlbumArtBytes;
|
||||
}
|
||||
@@ -507,7 +508,7 @@ namespace BetterLyrics.WinUI3.Services.MediaSessionsService
|
||||
{
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, async () =>
|
||||
{
|
||||
if (_cachedSongInfo?.SourceAppUserModelId == Constants.PlayerID.LXMusic)
|
||||
if (_cachedSongInfo?.PlayerId == Constants.PlayerID.LXMusic)
|
||||
{
|
||||
var data = JsonSerializer.Deserialize(e.Message, Serialization.SourceGenerationContext.Default.JsonElement);
|
||||
if (data.ValueKind == JsonValueKind.Number)
|
||||
|
||||
@@ -110,6 +110,10 @@ namespace BetterLyrics.WinUI3
|
||||
[ObservableProperty] public partial Visibility DesktopFlyoutItemVisibility { get; set; } = Visibility.Visible;
|
||||
[ObservableProperty] public partial Visibility PIPFlyoutItemVisibility { get; set; } = Visibility.Visible;
|
||||
[ObservableProperty] public partial Visibility DockFlyoutItemVisibility { get; set; } = Visibility.Visible;
|
||||
[ObservableProperty] public partial Visibility MinimiseButtonVisibility { get; set; } = Visibility.Visible;
|
||||
[ObservableProperty] public partial Visibility MaximiseButtonVisibility { get; set; } = Visibility.Visible;
|
||||
[ObservableProperty] public partial Visibility RestoreButtonVisibility { get; set; } = Visibility.Visible;
|
||||
[ObservableProperty] public partial Visibility CloseButtonVisibility { get; set; } = Visibility.Visible;
|
||||
|
||||
[ObservableProperty] public partial bool IsFullScreenFlyoutItemChecked { get; set; } = false;
|
||||
[ObservableProperty] public partial bool IsDesktopFlyoutItemChecked { get; set; } = false;
|
||||
@@ -305,6 +309,8 @@ namespace BetterLyrics.WinUI3
|
||||
private void SetFullscreenTitleBarControlsStatus()
|
||||
{
|
||||
LockButtonVisibility = DesktopFlyoutItemVisibility = PIPFlyoutItemVisibility = DockFlyoutItemVisibility = Visibility.Collapsed;
|
||||
MinimiseButtonVisibility = MaximiseButtonVisibility = RestoreButtonVisibility = Visibility.Collapsed;
|
||||
CloseButtonVisibility = Visibility.Visible;
|
||||
IsFullScreenFlyoutItemChecked = true;
|
||||
IsImmersiveMode = true;
|
||||
}
|
||||
@@ -312,6 +318,8 @@ namespace BetterLyrics.WinUI3
|
||||
private void SetPIPModeTitleBarControlsStatus()
|
||||
{
|
||||
DesktopFlyoutItemVisibility = FullScreenFlyoutItemVisibility = DockFlyoutItemVisibility = LockButtonVisibility = Visibility.Collapsed;
|
||||
MinimiseButtonVisibility = MaximiseButtonVisibility = RestoreButtonVisibility = Visibility.Collapsed;
|
||||
CloseButtonVisibility = Visibility.Visible;
|
||||
IsImmersiveMode = true;
|
||||
IsPIPFlyoutItemChecked = true;
|
||||
}
|
||||
@@ -324,6 +332,8 @@ namespace BetterLyrics.WinUI3
|
||||
|
||||
overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = false;
|
||||
DesktopFlyoutItemVisibility = LockButtonVisibility = FullScreenFlyoutItemVisibility = PIPFlyoutItemVisibility = Visibility.Collapsed;
|
||||
MinimiseButtonVisibility = MaximiseButtonVisibility = RestoreButtonVisibility = Visibility.Collapsed;
|
||||
CloseButtonVisibility = Visibility.Visible;
|
||||
IsImmersiveMode = true;
|
||||
IsDockFlyoutItemChecked = true;
|
||||
}
|
||||
@@ -337,6 +347,8 @@ namespace BetterLyrics.WinUI3
|
||||
overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = false;
|
||||
DockFlyoutItemVisibility = FullScreenFlyoutItemVisibility = PIPFlyoutItemVisibility = Visibility.Collapsed;
|
||||
LockButtonVisibility = Visibility.Visible;
|
||||
MinimiseButtonVisibility = MaximiseButtonVisibility = RestoreButtonVisibility = Visibility.Collapsed;
|
||||
CloseButtonVisibility = Visibility.Visible;
|
||||
IsDesktopFlyoutItemChecked = true;
|
||||
}
|
||||
|
||||
@@ -349,6 +361,8 @@ namespace BetterLyrics.WinUI3
|
||||
overlappedPresenter.IsMinimizable = overlappedPresenter.IsMaximizable = true;
|
||||
DesktopFlyoutItemVisibility = DockFlyoutItemVisibility = PIPFlyoutItemVisibility = FullScreenFlyoutItemVisibility = Visibility.Visible;
|
||||
LockButtonVisibility = Visibility.Collapsed;
|
||||
MinimiseButtonVisibility = MaximiseButtonVisibility = CloseButtonVisibility = Visibility.Visible;
|
||||
RestoreButtonVisibility = Visibility.Collapsed;
|
||||
IsFullScreenFlyoutItemChecked = IsDesktopFlyoutItemChecked = IsDockFlyoutItemChecked = IsPIPFlyoutItemChecked = false;
|
||||
IsImmersiveMode = _settingsService.AppSettings.GeneralSettings.IsImmersiveMode;
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
private void MediaSessionsService_SongInfoChanged(object? sender, Events.SongInfoChangedEventArgs e)
|
||||
{
|
||||
var current = AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == e.SongInfo?.SourceAppUserModelId)?.FirstOrDefault();
|
||||
var current = AppSettings.MediaSourceProvidersInfo.Where(x => x.Provider == e.SongInfo?.PlayerId)?.FirstOrDefault();
|
||||
if (_mediaSessionsService.Position.TotalSeconds <= 1 && current?.ResetPositionOffsetOnSongChanged == true)
|
||||
{
|
||||
current.PositionOffset = 0;
|
||||
|
||||
@@ -123,11 +123,6 @@
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}" />
|
||||
<MenuFlyoutSeparator />
|
||||
<MenuFlyoutItem
|
||||
x:Uid="SystemTrayExit"
|
||||
Click="ExitAppMenuFlyoutItem_Click"
|
||||
Icon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}" />
|
||||
</MenuFlyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
@@ -145,6 +140,7 @@
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize}"
|
||||
Glyph="" />
|
||||
</ToggleButton>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
@@ -156,6 +152,52 @@
|
||||
<StackPanel.OpacityTransition>
|
||||
<ScalarTransition />
|
||||
</StackPanel.OpacityTransition>
|
||||
|
||||
<!-- Window Minimise -->
|
||||
<Button
|
||||
x:Name="MinimiseButton"
|
||||
Click="MinimiseButton_Click"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
Visibility="{x:Bind ViewModel.MinimiseButtonVisibility, Mode=OneWay}">
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
<!-- Window Maximise -->
|
||||
<Button
|
||||
x:Name="MaximiseButton"
|
||||
Click="MaximiseButton_Click"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
Visibility="{x:Bind ViewModel.MaximiseButtonVisibility, Mode=OneWay}">
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
<!-- Window Restore -->
|
||||
<Button
|
||||
x:Name="RestoreButton"
|
||||
Click="RestoreButton_Click"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
Visibility="{x:Bind ViewModel.RestoreButtonVisibility, Mode=OneWay}">
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
<!-- Window Close -->
|
||||
<Button
|
||||
x:Name="CloseButton"
|
||||
Click="CloseButton_Click"
|
||||
Style="{StaticResource TitleBarButtonStyle}"
|
||||
Visibility="{x:Bind ViewModel.CloseButtonVisibility, Mode=OneWay}">
|
||||
<FontIcon
|
||||
FontFamily="{StaticResource IconFontFamily}"
|
||||
FontSize="{x:Bind ViewModel.TitleBarFontSize, Mode=OneWay}"
|
||||
Glyph="" />
|
||||
</Button>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace BetterLyrics.WinUI3.Views
|
||||
AppWindow.Changed += AppWindow_Changed;
|
||||
|
||||
ExtendsContentIntoTitleBar = true;
|
||||
AppWindow.TitleBar.PreferredHeightOption = TitleBarHeightOption.Collapsed;
|
||||
UpdateTitleBarArea();
|
||||
|
||||
Title = App.ResourceLoader!.GetString("LyricsPageTitle");
|
||||
@@ -134,6 +135,8 @@ namespace BetterLyrics.WinUI3.Views
|
||||
{
|
||||
_settingsService.AppSettings.StandardModeSettings.WindowBounds = new Windows.Foundation.Rect(rect.X, rect.Y, size.Width, size.Height);
|
||||
_settingsService.AppSettings.StandardModeSettings.IsMaximized = overlappedPresenter.State == OverlappedPresenterState.Maximized;
|
||||
ViewModel.MaximiseButtonVisibility = _settingsService.AppSettings.StandardModeSettings.IsMaximized ? Visibility.Collapsed : Visibility.Visible;
|
||||
ViewModel.RestoreButtonVisibility = _settingsService.AppSettings.StandardModeSettings.IsMaximized ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
break;
|
||||
case LyricsWindowMode.DockMode:
|
||||
@@ -222,14 +225,38 @@ namespace BetterLyrics.WinUI3.Views
|
||||
WindowHelper.OpenWindow<MusicGalleryWindow>();
|
||||
}
|
||||
|
||||
private void ExitAppMenuFlyoutItem_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
WindowHelper.ExitApp();
|
||||
}
|
||||
|
||||
private void TipContainerCenter_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
App.Current.LyricsWindowNotificationPanel = TipContainerCenter;
|
||||
}
|
||||
|
||||
private void MinimiseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AppWindow.Presenter is OverlappedPresenter presenter)
|
||||
{
|
||||
presenter.Minimize();
|
||||
}
|
||||
}
|
||||
|
||||
private void MaximiseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AppWindow.Presenter is OverlappedPresenter presenter)
|
||||
{
|
||||
presenter.Maximize();
|
||||
}
|
||||
}
|
||||
|
||||
private void RestoreButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (AppWindow.Presenter is OverlappedPresenter presenter)
|
||||
{
|
||||
presenter.Restore();
|
||||
}
|
||||
}
|
||||
|
||||
private void CloseButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ViewModel.ExitOrClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
19
FAQ/FAQ.md
@@ -1,25 +1,28 @@
|
||||
### Where I can find the logs?
|
||||
`C:\Users\%USERNAME%\AppData\Local\Packages\37412.BetterLyrics_rd1g0rsrrtxw8\LocalCache\logs`
|
||||
### ? Where I can find the logs?
|
||||
`%LocalAppData%\Packages\37412.BetterLyrics_rd1g0rsrrtxw8\LocalCache\logs`
|
||||
|
||||
### How to install ".msixbundle" package? (for test package only)
|
||||
### ? Where I can find the lyrics cache?
|
||||
`%LocalAppData%\Packages\37412.BetterLyrics_rd1g0rsrrtxw8\LocalCache\lyrics`
|
||||
|
||||
### ? How to install ".msixbundle" package? (for test package only)
|
||||
[See this doc](https://github.com/jayfunc/BetterLyrics/blob/dev/How2Install/How2Install.md)
|
||||
|
||||
### Lyrics are moving back and forth constantly, how to fix it?
|
||||
### ? Lyrics are moving back and forth constantly, how to fix it?
|
||||

|
||||
|
||||
Go to Settings > Playback sources > Disable "Lyrics timeline sync" or increase "Lyrics timeline sync threshold"
|
||||
|
||||
### Wrong lyrics are shown, how to fix it?
|
||||
### ? Wrong lyrics are shown, how to fix it?
|
||||

|
||||
|
||||
Open search panel to manually search for the correct lyrics.
|
||||
|
||||
### Playback control panel is not showing in dock mode, how to fix it?
|
||||
### ? Playback control panel is not showing in dock mode, how to fix it?
|
||||

|
||||
|
||||
Hover over the bottom of the lyrics window and click on the white line to show the playback control panel.
|
||||
|
||||
### How to lock/unlock the lyrics window in desktop mode?
|
||||
### ? How to lock/unlock the lyrics window in desktop mode?
|
||||

|
||||
|
||||

|
||||
@@ -30,5 +33,5 @@ Alternatively, you can also use the shortcut `Ctrl+Alt+U` (default) to toggle lo
|
||||
|
||||
You can change the shortcut in Settings > App appearance and behavior > Unlock and lock shortcut keys
|
||||
|
||||
### How to enable/disable immersive mode?
|
||||
### ? How to enable/disable immersive mode?
|
||||

|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) [year] [fullname]
|
||||
Copyright (c) 2025 Zhe Fang
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
81
README.md
@@ -23,7 +23,7 @@ BetterLyrics
|
||||
</div>
|
||||
|
||||
<h4 align="center">
|
||||
Your dynamic lyrics display tool built with WinUI 3 and Win2D — works with local playback and other players
|
||||
Your dynamic lyrics display tool, built with WinUI 3 and Win2D, works with local playback and other players
|
||||
</h3>
|
||||
|
||||
## 🎉 This project was featured by SSPAI!
|
||||
@@ -32,24 +32,22 @@ Check out the article: [BetterLyrics – An immersive and smooth lyrics display
|
||||
|
||||
## 🔈 Feedback and chat group
|
||||
|
||||
- [<img src="BetterLyrics.WinUI3\BetterLyrics.WinUI3\Assets\QQ.png" height="20"> QQ](https://qun.qq.com/universal-share/share?ac=1&authKey=4Q%2BYTq3wZldYpF5SbS5c19ECFsiYoLZFAIcBNNzYpBUtiEjaZ8sZ%2F%2BnFN0qw3lad&busi_data=eyJncm91cENvZGUiOiIxMDU0NzAwMzg4IiwidG9rZW4iOiJiVnhqemVYN0N5QVc3b1ZkR24wWmZOTUtvUkJoWm1JRWlaWW5iZnlBcXJtZUtGc2FFTHNlUlFZMi9iRm03cWF5IiwidWluIjoiMTM5NTczOTY2MCJ9&data=39UmAihyH_o6CZaOs7nk2mO_lz2ruODoDou6pxxh7utcxP4WF5sbDBDOPvZ_Wqfzeey4441anegsLYQJxkrBAA&svctype=4&tempid=h5_group_info) (1054700388)
|
||||
- [<img src="BetterLyrics.WinUI3\BetterLyrics.WinUI3\Assets\Discord.png" height="12"> Discord](https://discord.gg/5yAQPnyCKv)
|
||||
- [<img src="BetterLyrics.WinUI3\BetterLyrics.WinUI3\Assets\Telegram.png" height="16"> Telegram](https://t.me/+svhSLZ7awPsxNGY1)
|
||||
[QQ 群](https://qun.qq.com/universal-share/share?ac=1&authKey=4Q%2BYTq3wZldYpF5SbS5c19ECFsiYoLZFAIcBNNzYpBUtiEjaZ8sZ%2F%2BnFN0qw3lad&busi_data=eyJncm91cENvZGUiOiIxMDU0NzAwMzg4IiwidG9rZW4iOiJiVnhqemVYN0N5QVc3b1ZkR24wWmZOTUtvUkJoWm1JRWlaWW5iZnlBcXJtZUtGc2FFTHNlUlFZMi9iRm03cWF5IiwidWluIjoiMTM5NTczOTY2MCJ9&data=39UmAihyH_o6CZaOs7nk2mO_lz2ruODoDou6pxxh7utcxP4WF5sbDBDOPvZ_Wqfzeey4441anegsLYQJxkrBAA&svctype=4&tempid=h5_group_info) (1054700388) | [Discord Server](https://discord.gg/5yAQPnyCKv) | [Telegram Group](https://t.me/+svhSLZ7awPsxNGY1)
|
||||
|
||||
## 🌟 Highlighted features
|
||||
|
||||
- 🌠 **Pleasing User Interface**
|
||||
- Fluent animations and effects
|
||||
- ↔️ **Strong Lyrics Translation**
|
||||
- Offline machine translation (supporting 30 languages)
|
||||
- Auto reading local lyrics files for embedded translation
|
||||
- Offline machine translation (supporting 30+ languages)
|
||||
- Auto-reading local lyrics files for embedded translation
|
||||
- 🧩 **Various Lyrics Source**
|
||||
- Local storage
|
||||
- 💾 Local storage
|
||||
- Music files (with embedded lyrics)
|
||||
- [.lrc](<https://en.wikipedia.org/wiki/LRC_(file_format)>) files (with both core format and enhanced format)
|
||||
- [.eslrc](https://github.com/ESLyric/release) files
|
||||
- [.ttml](https://en.wikipedia.org/wiki/Timed_Text_Markup_Language) files
|
||||
- Online lyrics providers
|
||||
- ☁️ Online lyrics providers
|
||||
- QQ 音乐
|
||||
- 网易云音乐
|
||||
- 酷狗音乐
|
||||
@@ -58,44 +56,49 @@ Check out the article: [BetterLyrics – An immersive and smooth lyrics display
|
||||
- <details><summary>⚠️ Apple Music (additional config needed)</summary>
|
||||
|
||||
- Open the Apple Music web app and the Developer Tools window. Refresh the page. Return to the Developer Tools window, select Fetch/XHR, select a request, find the Media-User-Token header in the request header, and copy its value.
|
||||
- Open BetterLyrics and go to the Playback Source settings. Enter the copied value in the Media-User-Token (for Apple Music) setting and click the checkbox.
|
||||
- Open BetterLyrics and go to the Playback Source settings. Enter the copied value in the Media-User-Token (for Apple Music) setting and click the accept icon on the right-hand side.
|
||||
|
||||
- 🎶 **Multiple Music Players Supported**
|
||||
|
||||
- <details><summary>⚠️ 网易云音乐</summary>
|
||||
- <details><summary>网易云音乐</summary>
|
||||
|
||||
- Please be sure that that your Netease Cloud Music is at 3.1.4 version
|
||||
- Please make sure that you have latest version (3.1.20+) of 网易云音乐 installed on your PC.
|
||||
- Install the [BetterNCM plugin](https://microblock.cc/betterncm) first
|
||||
- After that, install the InfLink plugin in PluginMarket. After the installation is complete, please restart NetEase Cloud Music. At this point, all preparatory operations have been completed, enjoy it!
|
||||
- ⚠️ Please note that there is issues with timeline due to plugin issue
|
||||
- After that, install the [InfLink-rs](https://github.com/apoint123/inflink-rs) plugin in PluginMarket. After the installation is complete, please restart 网易云音乐. At this point, all preparatory operations have been completed. Enjoy it!
|
||||
|
||||
</details>
|
||||
|
||||
- <details><summary>⚠️ 酷狗音乐</summary>
|
||||
|
||||
- Please make sure that the Kugou Music setting "Support system playback controls, such as lock screen interface" is turned on
|
||||
- No timeline information broadcasted, which means when you change timeline position in Kugou Music, BetterLyrics has no way to detect this change
|
||||
- ⚠️ Please note that there is issues with timeline due to Kugou itself
|
||||
- Please make sure that the 酷狗音乐 setting "Support system playback controls, such as lock screen interface" is turned on
|
||||
- No timeline information broadcast, which means when you change the timeline position in Kugou Music, BetterLyrics has no way to detect this change
|
||||
- ⚠️ Please note that there are issues with the timeline due to Kugou itself
|
||||
|
||||
</details>
|
||||
|
||||
- <details><summary>⚠️ foobar2000</summary>
|
||||
|
||||
- Make sure you have https://github.com/dumbie/foo_mediacontrol installed with it
|
||||
- ⚠️ Please note that there is issues with timeline due to plugin issue
|
||||
- ⚠️ Please note that there are issues with the timeline due to a plugin issue
|
||||
|
||||
</details>
|
||||
|
||||
- Apple Music
|
||||
- Spotify
|
||||
- QQ 音乐
|
||||
- PotPlayer
|
||||
- Media Player (System)
|
||||
|
||||
- <details><summary>QQ 音乐</summary>
|
||||
|
||||
- Please keep it at the latest version
|
||||
- Then open Settings in QQ 音乐, enable "Show System Media Transport Controls (SMTC)".
|
||||
|
||||
</details>
|
||||
|
||||
- <details><summary>LX Music</summary>
|
||||
|
||||
- Please make sure you have enabled "Open API" in LX Music settings page
|
||||
- Then open BetterLyrics, go to settings, go to "Advanced options", input your LX Music server address (mostly like http://127.0.0.1:23330) and there you go!
|
||||
- Then open BetterLyrics, go to settings, go to "Playback sources", input your LX Music server address (mostly like http://127.0.0.1:23330) and there you go!
|
||||
|
||||
</details>
|
||||
|
||||
@@ -119,7 +122,7 @@ Check out the article: [BetterLyrics – An immersive and smooth lyrics display
|
||||
|
||||
- 🪟 **Multiple Display Modes**
|
||||
- **Standard Mode**
|
||||
- Enjoy an immersive listening journey with rich lyrics animations and beautifully dynamic backgrounds
|
||||
- Enjoy an immersive listening journey with rich lyrics, animations and beautifully dynamic backgrounds
|
||||
- **Dock Mode**
|
||||
- A smart animated lyrics bar docked to your screen edge
|
||||
- **Desktop Mode**
|
||||
@@ -127,33 +130,29 @@ Check out the article: [BetterLyrics – An immersive and smooth lyrics display
|
||||
- 🧠 **Smart Behaviors**
|
||||
- Auto hide when music paused
|
||||
|
||||
> This project is still under development, bugs and unexpected behaviors may be existed in the latest branch.
|
||||
> This project is still under development, bugs and unexpected behaviours may exist in the latest branch.
|
||||
|
||||
## Screenshots
|
||||
|
||||
### Standard mode
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
### Standard mode (narrow)
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||
### Standard mode (fullscreen)
|
||||
|
||||

|
||||

|
||||
|
||||
### Dock mode
|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
### Desktop mode
|
||||
|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
## Demonstration
|
||||
|
||||
@@ -177,13 +176,13 @@ Watch our introduction video (uploaded on 18 Aug 2025) on Bilibili [here](https:
|
||||
2. Type https://apps.microsoft.com/detail/9p1wcd1p597r in the link input area
|
||||
3. Select Retail from the drop-down list
|
||||
4. Click the check mark
|
||||
5. Select the largest installation package in the resulting list to download and install. If you fail to install, try to install dependencies packages first.
|
||||
5. Select the largest installation package in the resulting list to download and install. If you fail to install, try to install the dependency packages first.
|
||||
|
||||
### Unable to launch the app?
|
||||
|
||||
If you are using third-party modified Windows, you are probably can not launch the app.
|
||||
If you are using a third-party modified Windows, you probably can not launch the app.
|
||||
|
||||
To solve this issue, please try to download from [Google Drive (v1.0.71.0)](https://drive.google.com/file/d/15FiqmSVG3_SZ9Y-_2ZS_qbFvogbNp5Y5/view?usp=sharing) (may not be the latest version) and follow the instruction [here](https://github.com/jayfunc/BetterLyrics/blob/dev/How2Install/How2Install.md).
|
||||
To solve this issue, please try to download from [Google Drive (v1.0.76.0)](https://drive.google.com/file/d/1dKxp8Zf1xwAtt0JER0wHZ-94f855GdH0/view?usp=drive_link) (may not be the latest version) and follow the instructions [here](https://github.com/jayfunc/BetterLyrics/blob/dev/How2Install/How2Install.md).
|
||||
|
||||
## Build
|
||||
|
||||
@@ -192,17 +191,17 @@ Before you build, make sure that you have already replaced `BetterLyrics\BetterL
|
||||
## 💖 Many thanks to
|
||||
|
||||
- [Lyricify-Lyrics-Helper](https://github.com/WXRIW/Lyricify-Lyrics-Helper)
|
||||
- Provide lyrics fetch, decryption, and parse for QQ, Netease, Kugou sources
|
||||
- Provide lyrics fetch, decryption, and parsing for QQ, Netease, and Kugou sources
|
||||
- [lrclib](https://github.com/tranxuanthang/lrclib)
|
||||
- LRCLIB lyrics API provider
|
||||
- [Manzana-Apple-Music-Lyrics](https://github.com/dropcreations/Manzana-Apple-Music-Lyrics)
|
||||
- Apple Music lyrics fetch using Python
|
||||
- [Audio Tools Library (ATL) for .NET](https://github.com/Zeugma440/atldotnet)
|
||||
- Used for extracting pictures in music files
|
||||
- Used for extracting pictures from music files
|
||||
- [WinUIEx](https://github.com/dotMorten/WinUIEx)
|
||||
- Provide easy ways to access Win32 API regarding windowing
|
||||
- Provide easy ways to access the Win32 API regarding windowing
|
||||
- [TagLib#](https://github.com/mono/taglib-sharp)
|
||||
- Used for reading original lyrics content
|
||||
- Used for reading the original lyrics content
|
||||
- [Vanara](https://github.com/dahall/Vanara)
|
||||
- Win32 API wrapper
|
||||
- [LibreTranslate](https://github.com/LibreTranslate/LibreTranslate)
|
||||
@@ -233,9 +232,9 @@ Fork this project and navigate to `BetterLyrics\BetterLyrics.WinUI3\BetterLyrics
|
||||
|
||||
[](https://www.star-history.com/#jayfunc/BetterLyrics&Date)
|
||||
|
||||
## Any issues and PRs are welcomed
|
||||
## Any issues and PRs are welcome
|
||||
|
||||
If you find a bug please file it in issues or if you have any ideas feel free to share it here.
|
||||
If you find a bug, please file it in issues, or if you have any ideas, feel free to share them here.
|
||||
|
||||
## Donations
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 560 KiB |
|
Before Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 764 KiB |
BIN
Screenshots/desktop.png
Normal file
|
After Width: | Height: | Size: 565 KiB |
|
Before Width: | Height: | Size: 757 KiB |
|
Before Width: | Height: | Size: 34 KiB |
BIN
Screenshots/dock.png
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 694 KiB |
|
Before Width: | Height: | Size: 7.6 MiB |
|
Before Width: | Height: | Size: 775 KiB |
|
Before Width: | Height: | Size: 382 KiB |
BIN
Screenshots/std-fullscreen.png
Normal file
|
After Width: | Height: | Size: 642 KiB |
BIN
Screenshots/std-narrow.png
Normal file
|
After Width: | Height: | Size: 847 KiB |
BIN
Screenshots/std.png
Normal file
|
After Width: | Height: | Size: 823 KiB |