mirror of
https://github.com/jayfunc/BetterLyrics.git
synced 2026-01-12 19:08:33 +08:00
602 lines
23 KiB
C#
602 lines
23 KiB
C#
// 2025/6/23 by Zhe Fang
|
||
|
||
using BetterLyrics.WinUI3.Enums;
|
||
using BetterLyrics.WinUI3.Events;
|
||
using BetterLyrics.WinUI3.Helper;
|
||
using BetterLyrics.WinUI3.Models;
|
||
using BetterLyrics.WinUI3.Models.Settings;
|
||
using BetterLyrics.WinUI3.Services;
|
||
using BetterLyrics.WinUI3.Services.LastFMService;
|
||
using BetterLyrics.WinUI3.Services.LibWatcherService;
|
||
using BetterLyrics.WinUI3.Services.LyricsSearchService;
|
||
using BetterLyrics.WinUI3.Services.MediaSessionsService;
|
||
using BetterLyrics.WinUI3.Services.SettingsService;
|
||
using BetterLyrics.WinUI3.Services.TranslateService;
|
||
using CommunityToolkit.Mvvm.ComponentModel;
|
||
using CommunityToolkit.WinUI;
|
||
using Microsoft.Extensions.Logging;
|
||
using Microsoft.Graphics.Canvas;
|
||
using Microsoft.Graphics.Canvas.Text;
|
||
using Microsoft.UI;
|
||
using Microsoft.UI.Text;
|
||
using Microsoft.UI.Xaml;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using Windows.Graphics.Imaging;
|
||
using Windows.UI;
|
||
|
||
namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||
{
|
||
public partial class LyricsRendererViewModel : BaseViewModel
|
||
{
|
||
private LyricsStyleSettings _lyricsStyleSettings;
|
||
private LyricsEffectSettings _lyricsEffectSettings;
|
||
|
||
private bool _isLastFMTrackEnabled = false;
|
||
private bool _isLastFMTracked = false;
|
||
private TimeSpan _totalPlayingTime = TimeSpan.Zero;
|
||
|
||
private TimeSpan _elapsedTime = TimeSpan.Zero;
|
||
|
||
[ObservableProperty]
|
||
[NotifyPropertyChangedRecipients]
|
||
public partial TimeSpan TotalTime { get; set; } = TimeSpan.Zero;
|
||
|
||
private TimeSpan _positionOffset = TimeSpan.Zero;
|
||
|
||
private int _songDurationMs = (int)TimeSpan.FromMinutes(99).TotalMilliseconds;
|
||
|
||
private Stopwatch? _drawFrameStopwatch;
|
||
private int _drawFrameCount = 0;
|
||
private int _displayedDrawFrameCount = 0;
|
||
|
||
private Queue<SoftwareBitmap?> _cachedAlbumArtSwBitmaps = [];
|
||
|
||
private SoftwareBitmap? _lastAlbumArtSwBitmap = null;
|
||
private SoftwareBitmap? _albumArtSwBitmap = null;
|
||
|
||
private CanvasBitmap? _lastAlbumArtCanvasBitmap = null;
|
||
private CanvasBitmap? _albumArtCanvasBitmap = null;
|
||
|
||
private CanvasBitmap? _coverAcrylicNoiseCanvasBitmap = null;
|
||
|
||
private double _albumArtSize = 0f;
|
||
|
||
private string? _lastSongTitle;
|
||
private string? _songTitle;
|
||
|
||
private string? _lastSongArtist;
|
||
private string? _songArtist;
|
||
|
||
private double _canvasWidth = 0f;
|
||
private double _canvasHeight = 0f;
|
||
|
||
private readonly double _defaultScale = 0.75f;
|
||
private readonly double _highlightedScale = 1.0f;
|
||
|
||
private readonly double _coverRotateBaseSpeed = 0.003f;
|
||
private double _rotateAngle = 0f;
|
||
|
||
private double _canvasTargetYScrollOffset = 0;
|
||
|
||
[ObservableProperty]
|
||
[NotifyPropertyChangedRecipients]
|
||
public partial LyricsSearchProvider? LyricsSearchProvider { get; set; } = null;
|
||
|
||
[ObservableProperty]
|
||
[NotifyPropertyChangedRecipients]
|
||
public partial TranslationSearchProvider? TranslationSearchProvider { get; set; } = null;
|
||
|
||
private readonly double _lyricsGlowEffectAmount = 8f;
|
||
|
||
private double _maxLyricsWidth = 0f;
|
||
|
||
private readonly ISettingsService _settingsService;
|
||
private readonly ILyricsSearchService _lyrcsSearchService;
|
||
private readonly ILibWatcherService _libWatcherService;
|
||
private readonly IMediaSessionsService _mediaSessionsService;
|
||
private readonly ITranslateService _translateService;
|
||
private readonly ILastFMService _lastFMService;
|
||
private readonly ILogger _logger;
|
||
|
||
private readonly double _leftMargin = 36f;
|
||
private readonly double _middleMargin = 36f;
|
||
private readonly double _rightMargin = 36f;
|
||
private readonly double _topMargin = 36f;
|
||
private readonly double _bottomMargin = 36f;
|
||
|
||
private Color _adaptiveGrayedFontColor = Colors.Transparent;
|
||
private Color? _adaptiveColoredFontColor = null;
|
||
|
||
private Color _albumArtLightAccentColor = Colors.Transparent;
|
||
private Color _albumArtDarkAccentColor = Colors.Transparent;
|
||
private Color _environmentalColor = Colors.Transparent;
|
||
|
||
private Color _lightColor = Colors.White;
|
||
private Color _darkColor = Colors.Black;
|
||
|
||
private Color _bgFontColor;
|
||
private Color _fgFontColor;
|
||
private Color _strokeFontColor;
|
||
|
||
private int _playingLineIndex = -1;
|
||
|
||
private int _startVisibleLineIndex = -1;
|
||
private int _endVisibleLineIndex = -1;
|
||
|
||
private bool _isDebugOverlayEnabled = false;
|
||
private bool _isDesktopMode = false;
|
||
private bool _isDockMode = false;
|
||
|
||
private bool _isPlaying = true;
|
||
|
||
private bool _isLyricsWindowLocked = false;
|
||
private bool _isMouseWithinWindow = false;
|
||
|
||
private bool _isLayoutChanged = true;
|
||
|
||
private int _langIndex = 0;
|
||
|
||
private List<LyricsData> _lyricsDataArr = [];
|
||
|
||
private int _timelineSyncThreshold = 0;
|
||
|
||
private CanvasTextFormat _lyricsTextFormat = new()
|
||
{
|
||
HorizontalAlignment = CanvasHorizontalAlignment.Left,
|
||
VerticalAlignment = CanvasVerticalAlignment.Top,
|
||
FontSize = 12,
|
||
};
|
||
private CanvasTextFormat _titleTextFormat = new()
|
||
{
|
||
FontSize = 18,
|
||
FontWeight = FontWeights.Bold,
|
||
HorizontalAlignment = CanvasHorizontalAlignment.Left,
|
||
WordWrapping = CanvasWordWrapping.NoWrap,
|
||
TrimmingSign = CanvasTrimmingSign.Ellipsis,
|
||
TrimmingGranularity = CanvasTextTrimmingGranularity.Character,
|
||
};
|
||
private CanvasTextFormat _artistTextFormat = new()
|
||
{
|
||
FontSize = 16,
|
||
FontWeight = FontWeights.Bold,
|
||
HorizontalAlignment = CanvasHorizontalAlignment.Left,
|
||
WordWrapping = CanvasWordWrapping.NoWrap,
|
||
TrimmingSign = CanvasTrimmingSign.Ellipsis,
|
||
TrimmingGranularity = CanvasTextTrimmingGranularity.Character,
|
||
};
|
||
private CanvasTextFormat _debugTextFormat = new()
|
||
{
|
||
FontSize = 12,
|
||
FontWeight = FontWeights.ExtraBlack,
|
||
};
|
||
|
||
private LatestOnlyTaskRunner _refreshLyricsRunner = new();
|
||
private LatestOnlyTaskRunner _showTranslationsRunner = new();
|
||
|
||
private LyricsDisplayType _displayTypeReceived;
|
||
private LyricsDisplayType _displayType;
|
||
|
||
private LyricsLayoutOrientation _lyricsLayoutOrientation;
|
||
|
||
[ObservableProperty]
|
||
public partial bool IsTranslating { get; set; } = false;
|
||
|
||
[ObservableProperty]
|
||
public partial SongInfo? SongInfo { get; set; }
|
||
|
||
[ObservableProperty]
|
||
[NotifyPropertyChangedRecipients]
|
||
public partial ElementTheme ThemeTypeSent { get; set; }
|
||
|
||
private int GetCurrentPlayingLineIndex()
|
||
{
|
||
var totalMs = TotalTime.TotalMilliseconds + _positionOffset.TotalMilliseconds;
|
||
if (totalMs < _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.FirstOrDefault()?.StartMs) return 0;
|
||
|
||
for (int i = 0; i < _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.Count; i++)
|
||
{
|
||
var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i);
|
||
if (line == null) continue;
|
||
var nextLine = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(i + 1);
|
||
if (nextLine != null && line.StartMs <= totalMs && totalMs < nextLine.StartMs)
|
||
{
|
||
return i;
|
||
}
|
||
else if (nextLine == null && line.StartMs <= totalMs)
|
||
{
|
||
return i;
|
||
}
|
||
}
|
||
|
||
return GetMaxLyricsLineIndexBoundaries().Item2;
|
||
}
|
||
|
||
private void GetLinePlayingProgress(int lineIndex, out int charStartIndex, out int charLength, out double charProgress)
|
||
{
|
||
charStartIndex = 0;
|
||
charLength = 0;
|
||
charProgress = 0f;
|
||
|
||
var line = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(lineIndex);
|
||
if (line == null) return;
|
||
var nextLine = _lyricsDataArr.ElementAtOrDefault(_langIndex)?.LyricsLines.ElementAtOrDefault(lineIndex + 1);
|
||
|
||
int lineEndMs;
|
||
if (line.EndMs != null) lineEndMs = line.EndMs.Value;
|
||
else if (nextLine != null) lineEndMs = nextLine.StartMs;
|
||
else lineEndMs = _songDurationMs;
|
||
|
||
double now = (double)TotalTime.TotalMilliseconds + (double)_positionOffset.TotalMilliseconds;
|
||
|
||
// 1. 还没到本句
|
||
if (now < line.StartMs)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 2. 已经超过本句
|
||
if (now > lineEndMs)
|
||
{
|
||
charProgress = 1f;
|
||
charStartIndex = line.OriginalText.Length - 1;
|
||
charLength = 1;
|
||
return;
|
||
}
|
||
|
||
// 3. 有逐字时间轴
|
||
if (line.LyricsChars != null && line.LyricsChars.Count > 1)
|
||
{
|
||
int charTimingsCount = line.LyricsChars.Count;
|
||
for (int i = 0; i < charTimingsCount; i++)
|
||
{
|
||
var timing = line.LyricsChars[i];
|
||
var nextTiming = line.LyricsChars.ElementAtOrDefault(i + 1);
|
||
|
||
int timingEndMs;
|
||
if (timing.EndMs != null) timingEndMs = timing.EndMs.Value;
|
||
else if (nextTiming != null) timingEndMs = nextTiming.StartMs;
|
||
else timingEndMs = lineEndMs;
|
||
|
||
charStartIndex = timing.StartIndex;
|
||
charLength = timing.Text.Length;
|
||
|
||
// 当前时间在某个字的高亮区间
|
||
if (now >= timing.StartMs && now <= timingEndMs)
|
||
{
|
||
if (timingEndMs != timing.StartMs)
|
||
{
|
||
charProgress = (now - timing.StartMs) / (timingEndMs - timing.StartMs);
|
||
}
|
||
else
|
||
{
|
||
charProgress = 0f;
|
||
}
|
||
return;
|
||
}
|
||
else if (now > timingEndMs && (nextTiming == null || now < nextTiming?.StartMs))
|
||
{
|
||
charProgress = 1f;
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 没有逐字时间轴,均匀分配每个字的高亮时间
|
||
int textLength = line.OriginalText.Length;
|
||
if (textLength == 0) return;
|
||
|
||
double lineProgress = (now - line.StartMs) / (lineEndMs - line.StartMs);
|
||
lineProgress = Math.Clamp(lineProgress, 0f, 1f);
|
||
|
||
// 计算当前高亮到第几个字
|
||
double charFloatIndex = lineProgress * textLength;
|
||
int charIndex = (int)charFloatIndex;
|
||
charStartIndex = Math.Clamp(charIndex, 0, textLength - 1);
|
||
charLength = 1;
|
||
|
||
// 当前字的进度(0~1)
|
||
charProgress = charFloatIndex - charIndex;
|
||
}
|
||
}
|
||
|
||
private Tuple<int, int> GetMaxLyricsLineIndexBoundaries()
|
||
{
|
||
if (
|
||
SongInfo == null
|
||
|| _lyricsDataArr.ElementAtOrDefault(_langIndex) == null
|
||
|| _lyricsDataArr[_langIndex].LyricsLines.Count == 0
|
||
)
|
||
{
|
||
return new Tuple<int, int>(-1, -1);
|
||
}
|
||
|
||
return new Tuple<int, int>(0, _lyricsDataArr[_langIndex].LyricsLines.Count - 1);
|
||
}
|
||
|
||
private void LibWatcherService_MusicLibraryFilesChanged(object? sender, LibChangedEventArgs e)
|
||
{
|
||
_logger.LogInformation("Music library files changed: {ChangeType} {FilePath}, refreshing lyrics...", e.ChangeType, e.FilePath);
|
||
_ = _refreshLyricsRunner.RunAsync(async token =>
|
||
{
|
||
await RefreshLyricsAsync(token);
|
||
});
|
||
}
|
||
|
||
private void PlaybackService_IsPlayingChanged(object? sender, IsPlayingChangedEventArgs e)
|
||
{
|
||
_isPlaying = e.IsPlaying;
|
||
}
|
||
|
||
private void PlaybackService_TimelineChanged(object? sender, TimelineChangedEventArgs e)
|
||
{
|
||
var diff = Math.Abs(TotalTime.TotalMilliseconds - e.Position.TotalMilliseconds);
|
||
if (diff >= _timelineSyncThreshold)
|
||
{
|
||
TotalTime = e.Position;
|
||
if (TotalTime.TotalSeconds <= 1)
|
||
{
|
||
_totalPlayingTime = TimeSpan.Zero;
|
||
_isLastFMTracked = false;
|
||
}
|
||
}
|
||
// 大跨度,刷新布局,避免歌词不显示
|
||
if (diff >= _timelineSyncThreshold + 5000)
|
||
{
|
||
_isLayoutChanged = true;
|
||
}
|
||
}
|
||
|
||
private void PlaybackService_SongInfoChanged(object? sender, SongInfoChangedEventArgs e)
|
||
{
|
||
SongInfo = e.SongInfo;
|
||
|
||
UpdateTimelineSyncThreshold();
|
||
UpdatePositionOffset();
|
||
UpdateIsLastFMTrackEnabled();
|
||
|
||
if (SongInfo?.Title != _songTitle || SongInfo?.Artist != _songArtist)
|
||
{
|
||
_lastSongTitle = _songTitle;
|
||
_songTitle = SongInfo?.Title;
|
||
|
||
_lastSongArtist = _songArtist;
|
||
_songArtist = SongInfo?.Artist;
|
||
|
||
_songDurationMs = (int)(SongInfo?.DurationMs ?? TimeSpan.FromMinutes(99).TotalMilliseconds);
|
||
|
||
_songInfoOpacityTransition.Reset(0f);
|
||
_songInfoOpacityTransition.StartTransition(1f);
|
||
|
||
_logger.LogInformation("Song info changed: Title={Title}, Artist={Artist}, refreshing lyrics...", _songTitle, _songArtist);
|
||
_ = _refreshLyricsRunner.RunAsync(async token =>
|
||
{
|
||
await RefreshLyricsAsync(token);
|
||
});
|
||
TotalTime = TimeSpan.Zero;
|
||
|
||
// 处理 Last.fm 追踪
|
||
_totalPlayingTime = TimeSpan.Zero;
|
||
_isLastFMTracked = false;
|
||
}
|
||
}
|
||
|
||
private void PlaybackService_AlbumArtChangedChanged(object? sender, AlbumArtChangedEventArgs e)
|
||
{
|
||
if (e.AlbumArtSwBitmap != _albumArtSwBitmap)
|
||
{
|
||
_cachedAlbumArtSwBitmaps.Append(_albumArtSwBitmap);
|
||
|
||
_lastAlbumArtSwBitmap = _albumArtSwBitmap;
|
||
|
||
if (_cachedAlbumArtSwBitmaps.Count > 2)
|
||
{
|
||
_cachedAlbumArtSwBitmaps.Dequeue()?.Dispose();
|
||
}
|
||
|
||
_cachedAlbumArtSwBitmaps.Append(e.AlbumArtSwBitmap);
|
||
|
||
_albumArtSwBitmap = e.AlbumArtSwBitmap;
|
||
|
||
if (_cachedAlbumArtSwBitmaps.Count > 2)
|
||
{
|
||
_cachedAlbumArtSwBitmaps.Dequeue()?.Dispose();
|
||
}
|
||
|
||
_albumArtChanged = true;
|
||
|
||
_albumArtLightAccentColor = e.AlbumArtLightAccentColor ?? Colors.Transparent;
|
||
_albumArtDarkAccentColor = e.AlbumArtDarkAccentColor ?? Colors.Transparent;
|
||
|
||
UpdateColorConfig();
|
||
}
|
||
else
|
||
{
|
||
e.AlbumArtSwBitmap?.Dispose();
|
||
}
|
||
}
|
||
|
||
private void UpdateTranslations()
|
||
{
|
||
TranslationSearchProvider = null;
|
||
_lyricsDataArr.ElementAtOrDefault(0)?.SetDisplayedTextInOriginalText();
|
||
_isLayoutChanged = true;
|
||
|
||
IsTranslating = true;
|
||
if (_settingsService.AppSettings.TranslationSettings.IsTranslationEnabled)
|
||
{
|
||
_ = _refreshLyricsRunner.RunAsync(async token =>
|
||
{
|
||
await SetDisplayedAlongWithTranslationsAsync(token);
|
||
IsTranslating = false;
|
||
_isLayoutChanged = true;
|
||
});
|
||
}
|
||
else
|
||
{
|
||
_lyricsDataArr.ElementAtOrDefault(0)?.SetDisplayedTextInOriginalText();
|
||
_langIndex = 0;
|
||
IsTranslating = false;
|
||
_isLayoutChanged = true;
|
||
}
|
||
}
|
||
|
||
private async Task SetDisplayedAlongWithTranslationsAsync(CancellationToken token)
|
||
{
|
||
_logger.LogInformation("Showing translation for lyrics...");
|
||
string targetLangCode = LanguageHelper.GetUserTargetLanguageCode();
|
||
string? originalText = _lyricsDataArr.FirstOrDefault()?.WrappedOriginalText;
|
||
if (originalText == null) return;
|
||
|
||
string? originalLangCode = LanguageHelper.DetectLanguageCode(originalText);
|
||
|
||
if (originalLangCode == targetLangCode)
|
||
{
|
||
_logger.LogInformation("Original lyrics already in target language: {TargetLangCode}", targetLangCode);
|
||
_lyricsDataArr[0].SetDisplayedTextInOriginalText();
|
||
}
|
||
else
|
||
{
|
||
// Try get translation from itself first
|
||
int found = _translateService.SearchTranslatedLyricsItself(_lyricsDataArr);
|
||
if (found >= 0)
|
||
{
|
||
if (_settingsService.AppSettings.TranslationSettings.ShowTranslationOnly)
|
||
{
|
||
_lyricsDataArr[found].SetDisplayedTextInOriginalText();
|
||
_langIndex = found;
|
||
}
|
||
else
|
||
{
|
||
_lyricsDataArr[0].SetDisplayedTextAlongWith(_lyricsDataArr[found], _lyricsStyleSettings.LyricsTranslationSeparator, 50);
|
||
_langIndex = 0;
|
||
}
|
||
TranslationSearchProvider = LyricsSearchProvider.ToTranslationSearchProvider();
|
||
}
|
||
else if (_settingsService.AppSettings.TranslationSettings.IsLibreTranslateEnabled)
|
||
{
|
||
string translated = string.Empty;
|
||
try
|
||
{
|
||
translated = await _translateService.TranslateTextAsync(originalText, targetLangCode, token);
|
||
if (translated == string.Empty) return;
|
||
|
||
if (_settingsService.AppSettings.TranslationSettings.ShowTranslationOnly)
|
||
{
|
||
_lyricsDataArr[^1] = _lyricsDataArr[0].CreateLyricsDataFrom(translated);
|
||
_lyricsDataArr[^1].SetDisplayedTextInOriginalText();
|
||
_langIndex = _lyricsDataArr.Count - 1;
|
||
}
|
||
else
|
||
{
|
||
_lyricsDataArr[0].SetDisplayedTextAlongWith(translated, _lyricsStyleSettings.LyricsTranslationSeparator);
|
||
_langIndex = 0;
|
||
}
|
||
TranslationSearchProvider = Enums.TranslationSearchProvider.LibreTranslate;
|
||
token.ThrowIfCancellationRequested();
|
||
}
|
||
catch (Exception)
|
||
{
|
||
App.Current.LyricsWindowNotificationPanel?.Notify(App.ResourceLoader?.GetString("LibreTranslateFailed")!, Microsoft.UI.Xaml.Controls.InfoBarSeverity.Error);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
private async Task RefreshLyricsAsync(CancellationToken token)
|
||
{
|
||
LyricsSearchProvider = null;
|
||
_logger.LogInformation("Refreshing lyrics...");
|
||
|
||
_lyricsDataArr = [LyricsData.GetLoadingPlaceholder()];
|
||
_isLayoutChanged = true;
|
||
|
||
string? lyricsRaw = null;
|
||
LyricsSearchProvider? lyricsSearchProvider = null;
|
||
|
||
if (SongInfo != null)
|
||
{
|
||
(lyricsRaw, lyricsSearchProvider) = await _lyrcsSearchService.SearchAsync(
|
||
SongInfo.SourceAppUserModelId ?? "",
|
||
SongInfo.Title,
|
||
SongInfo.Artist,
|
||
SongInfo.Album ?? "",
|
||
SongInfo.DurationMs ?? 0,
|
||
token
|
||
);
|
||
LyricsSearchProvider = lyricsSearchProvider;
|
||
_logger.LogInformation("Lyrics search result: {LyricsRaw}", lyricsRaw ?? "null");
|
||
token.ThrowIfCancellationRequested();
|
||
_lyricsDataArr = new LyricsParser().Parse(lyricsRaw, (int?)SongInfo?.DurationMs);
|
||
FillTranslationFromCache(LyricsSearchProvider);
|
||
}
|
||
else
|
||
{
|
||
_logger.LogWarning("SongInfo is null, cannot search lyrics.");
|
||
}
|
||
|
||
_logger.LogInformation("Parsed lyrics: {MultiLangLyricsCount} languages", _lyricsDataArr.Count);
|
||
|
||
// This ensures that original lyrics are always shown while waiting for translations
|
||
_lyricsDataArr[0].SetDisplayedTextInOriginalText();
|
||
_isLayoutChanged = true;
|
||
|
||
UpdateTranslations();
|
||
}
|
||
|
||
private void FillTranslationFromCache(LyricsSearchProvider? provider)
|
||
{
|
||
string? translationRaw = null;
|
||
switch (provider)
|
||
{
|
||
case Enums.LyricsSearchProvider.QQ:
|
||
translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.QQTranslationCacheDirectory);
|
||
break;
|
||
case Enums.LyricsSearchProvider.Kugou:
|
||
break;
|
||
case Enums.LyricsSearchProvider.Netease:
|
||
translationRaw = Helper.FileHelper.ReadLyricsCache(SongInfo!.Title, SongInfo.Artist, LyricsFormat.Lrc, Helper.PathHelper.NeteaseTranslationCacheDirectory);
|
||
break;
|
||
case Enums.LyricsSearchProvider.LrcLib:
|
||
break;
|
||
case Enums.LyricsSearchProvider.AmllTtmlDb:
|
||
break;
|
||
case Enums.LyricsSearchProvider.LocalMusicFile:
|
||
break;
|
||
case Enums.LyricsSearchProvider.LocalLrcFile:
|
||
break;
|
||
case Enums.LyricsSearchProvider.LocalEslrcFile:
|
||
break;
|
||
case Enums.LyricsSearchProvider.LocalTtmlFile:
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
if (translationRaw != null)
|
||
{
|
||
var translationData = new LyricsParser().Parse(translationRaw, (int?)SongInfo?.DurationMs);
|
||
if (provider == Enums.LyricsSearchProvider.QQ)
|
||
{
|
||
foreach (var data in translationData)
|
||
{
|
||
foreach (var item in data.LyricsLines)
|
||
{
|
||
if (item.OriginalText == "//")
|
||
{
|
||
item.OriginalText = "";
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
_lyricsDataArr = _lyricsDataArr.Concat(translationData).ToList();
|
||
}
|
||
}
|
||
}
|
||
}
|