Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df45026638 | ||
|
|
aafc5c9fb5 | ||
|
|
c5fccfbb63 | ||
|
|
42f03b4291 | ||
|
|
3339bb0d41 | ||
|
|
7d60f29845 | ||
|
|
bd7e93f3e6 | ||
|
|
c37c6ab489 | ||
|
|
125794c44f | ||
|
|
f5bdb3a431 |
@@ -12,7 +12,7 @@
|
||||
<Identity
|
||||
Name="37412.BetterLyrics"
|
||||
Publisher="CN=E1428B0E-DC1D-4EA4-ACB1-4556569D5BA9"
|
||||
Version="1.0.89.0" />
|
||||
Version="1.0.90.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="ca4a4830-fc19-40d9-b823-53e2bff3d816" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Media" Version="8.2.250402" />
|
||||
<PackageReference Include="csharp-kana" Version="1.0.2" />
|
||||
<PackageReference Include="csharp-pinyin" Version="1.0.1" />
|
||||
<PackageReference Include="DevWinUI.Controls" Version="9.4.2" />
|
||||
<PackageReference Include="Dubya.WindowsMediaController" Version="2.5.5" />
|
||||
<PackageReference Include="H.NotifyIcon.WinUI" Version="2.3.2" />
|
||||
<PackageReference Include="Hqub.Last.fm" Version="2.5.1" />
|
||||
@@ -86,7 +87,6 @@
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.10" />
|
||||
<PackageReference Include="TagLibSharp" Version="2.3.0" />
|
||||
<PackageReference Include="Ude.NetStandard" Version="1.2.0" />
|
||||
<PackageReference Include="Vanara.PInvoke.CoreAudio" Version="4.2.1" />
|
||||
<PackageReference Include="Vanara.PInvoke.DwmApi" Version="4.2.1" />
|
||||
<PackageReference Include="Vanara.PInvoke.Gdi32" Version="4.2.1" />
|
||||
<PackageReference Include="Vanara.PInvoke.Shell32" Version="4.2.1" />
|
||||
@@ -112,7 +112,6 @@
|
||||
<ItemGroup>
|
||||
<TrimmerRootAssembly Include="TagLibSharp" />
|
||||
<TrimmerRootAssembly Include="NAudio.Wasapi" />
|
||||
<TrimmerRootAssembly Include="Vanara.PInvoke.CoreAudio" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Update="Assets\AIMP.png">
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
<StackPanel>
|
||||
|
||||
<Slider
|
||||
IsEnabled="{x:Bind IsSliderEnabled, Mode=OneWay}"
|
||||
Maximum="{x:Bind Maximum, Mode=OneWay}"
|
||||
Minimum="{x:Bind Minimum, Mode=OneWay}"
|
||||
SnapsTo="Ticks"
|
||||
StepFrequency="{x:Bind Frequency, Mode=OneWay}"
|
||||
Tapped="Slider_Tapped"
|
||||
TickFrequency="{x:Bind Frequency, Mode=OneWay}"
|
||||
TickPlacement="None"
|
||||
ValueChanged="Slider_ValueChanged"
|
||||
Value="{x:Bind Value, Mode=TwoWay}" />
|
||||
|
||||
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using BetterLyrics.WinUI3.Events;
|
||||
using Microsoft.UI.Input;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
@@ -21,18 +22,13 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
{
|
||||
public sealed partial class ExtendedSlider : UserControl
|
||||
{
|
||||
public event EventHandler<RangeBaseValueChangedEventArgs> ValueChanged;
|
||||
public event EventHandler<ExtendedSliderValueChangedByUserEventArgs>? ValueChangedByUser;
|
||||
|
||||
public ExtendedSlider()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void Slider_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
|
||||
{
|
||||
ValueChanged?.Invoke(sender, e);
|
||||
}
|
||||
|
||||
private void Subtract()
|
||||
{
|
||||
if (Value - Frequency < Minimum)
|
||||
@@ -68,7 +64,7 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty FrequencyProperty =
|
||||
DependencyProperty.Register(nameof(Frequency), typeof(double), typeof(ExtendedSlider), new PropertyMetadata(default));
|
||||
DependencyProperty.Register(nameof(Frequency), typeof(double), typeof(ExtendedSlider), new PropertyMetadata(1));
|
||||
public static readonly DependencyProperty MinimumProperty =
|
||||
DependencyProperty.Register(nameof(Minimum), typeof(double), typeof(ExtendedSlider), new PropertyMetadata(default));
|
||||
public static readonly DependencyProperty MaximumProperty =
|
||||
@@ -83,6 +79,8 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
DependencyProperty.Register(nameof(ResetButtonVisibility), typeof(Visibility), typeof(ExtendedSlider), new PropertyMetadata(Visibility.Visible));
|
||||
public static readonly DependencyProperty UnitProperty =
|
||||
DependencyProperty.Register(nameof(Unit), typeof(string), typeof(ExtendedSlider), new PropertyMetadata(""));
|
||||
public static readonly DependencyProperty IsSliderEnabledProperty =
|
||||
DependencyProperty.Register(nameof(IsSliderEnabled), typeof(bool), typeof(ExtendedSlider), new PropertyMetadata(true));
|
||||
|
||||
public double Frequency
|
||||
{
|
||||
@@ -128,20 +126,33 @@ namespace BetterLyrics.WinUI3.Controls
|
||||
get => (string)GetValue(UnitProperty);
|
||||
set => SetValue(UnitProperty, value);
|
||||
}
|
||||
public bool IsSliderEnabled
|
||||
{
|
||||
get => (bool)GetValue(IsSliderEnabledProperty);
|
||||
set => SetValue(IsSliderEnabledProperty, value);
|
||||
}
|
||||
|
||||
private void ResetButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Value = Default;
|
||||
ValueChangedByUser?.Invoke(this, new ExtendedSliderValueChangedByUserEventArgs(Value));
|
||||
}
|
||||
|
||||
private void SubtractButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Subtract();
|
||||
ValueChangedByUser?.Invoke(this, new ExtendedSliderValueChangedByUserEventArgs(Value));
|
||||
}
|
||||
|
||||
private void AddButton_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Add();
|
||||
ValueChangedByUser?.Invoke(this, new ExtendedSliderValueChangedByUserEventArgs(Value));
|
||||
}
|
||||
|
||||
private void Slider_Tapped(object sender, TappedRoutedEventArgs e)
|
||||
{
|
||||
ValueChangedByUser?.Invoke(this, new ExtendedSliderValueChangedByUserEventArgs(Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
<TextBlock Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageTheme" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<controls:SettingsCard x:Uid="SettingsPageTheme">
|
||||
<ComboBox x:Name="ThemeComboBox" SelectedIndex="{x:Bind LyricsBackgroundSettings.LyricsBackgroundTheme, Mode=TwoWay, Converter={StaticResource EnumToIntConverter}}">
|
||||
<ComboBoxItem x:Uid="SettingsPageFollowSystem" />
|
||||
<ComboBoxItem x:Uid="SettingsPageLight" />
|
||||
@@ -26,11 +26,7 @@
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPagePureLayer"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="{x:Bind LyricsBackgroundSettings.IsPureColorOverlayEnabled, Mode=OneWay}">
|
||||
<controls:SettingsExpander x:Uid="SettingsPagePureLayer" IsExpanded="{x:Bind LyricsBackgroundSettings.IsPureColorOverlayEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsPureColorOverlayEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
|
||||
@@ -47,11 +43,7 @@
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageAlbumArtLayer"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=OneWay}">
|
||||
<controls:SettingsExpander x:Uid="SettingsPageAlbumArtLayer" IsExpanded="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsCoverOverlayEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
|
||||
@@ -96,11 +88,7 @@
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageFluidLayer"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="{x:Bind LyricsBackgroundSettings.IsFluidOverlayEnabled, Mode=OneWay}">
|
||||
<controls:SettingsExpander x:Uid="SettingsPageFluidLayer" IsExpanded="{x:Bind LyricsBackgroundSettings.IsFluidOverlayEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsFluidOverlayEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
|
||||
@@ -124,14 +112,24 @@
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageSpectrumLayer"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
Glyph=}"
|
||||
IsExpanded="{x:Bind LyricsBackgroundSettings.IsSpectrumOverlayEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsSpectrumOverlayEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander x:Uid="SettingsPageSnowFlakeLayer" IsExpanded="{x:Bind LyricsBackgroundSettings.IsSnowFlakeOverlayEnabled, Mode=OneWay}">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsSnowFlakeOverlayEnabled, Mode=TwoWay}" />
|
||||
<controls:SettingsExpander.Items>
|
||||
<controls:SettingsCard x:Uid="SettingsPageAmount">
|
||||
<uc:ExtendedSlider
|
||||
Frequency="1"
|
||||
Maximum="100"
|
||||
Minimum="10"
|
||||
ResetButtonVisibility="Collapsed"
|
||||
Value="{x:Bind LyricsBackgroundSettings.SnowFlakeOverlayAmount, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageSpectrumLayer">
|
||||
<ToggleSwitch IsOn="{x:Bind LyricsBackgroundSettings.IsSpectrumOverlayEnabled, Mode=TwoWay}" />
|
||||
</controls:SettingsCard>
|
||||
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ScrollViewer>
|
||||
|
||||
@@ -227,6 +227,18 @@
|
||||
</ComboBox>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDockMonitor" IsEnabled="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.IsWorkArea, Mode=OneWay}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<ComboBox ItemsSource="{x:Bind ViewModel.MonitorDeviceNames, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.MonitorDeviceName, Mode=TwoWay}" />
|
||||
<Button
|
||||
Command="{x:Bind ViewModel.RefreshMonitorDeviceNamesCommand}"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
@@ -251,18 +263,6 @@
|
||||
</controls:SettingsExpander.Items>
|
||||
</controls:SettingsExpander>
|
||||
|
||||
<controls:SettingsCard x:Uid="SettingsPageDockMonitor" HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily}, Glyph=}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<ComboBox ItemsSource="{x:Bind ViewModel.MonitorDeviceNames, Mode=OneWay}" SelectedItem="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.MonitorDeviceName, Mode=TwoWay}" />
|
||||
<Button
|
||||
Command="{x:Bind ViewModel.RefreshMonitorDeviceNamesCommand}"
|
||||
Content="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
FontSize=12,
|
||||
Glyph=}"
|
||||
Style="{StaticResource GhostButtonStyle}" />
|
||||
</StackPanel>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsExpander
|
||||
x:Uid="SettingsPageWindowBounds"
|
||||
HeaderIcon="{ui:FontIcon FontFamily={StaticResource IconFontFamily},
|
||||
|
||||
@@ -322,7 +322,7 @@
|
||||
|
||||
<!-- LX music server -->
|
||||
<TextBlock x:Uid="SettingsPageLXMusicServer" Style="{StaticResource SettingsSectionHeaderTextBlockStyle}" />
|
||||
<controls:SettingsCard Header="SettingsPageServerAddress">
|
||||
<controls:SettingsCard x:Uid="SettingsPageServerAddress">
|
||||
<StackPanel Orientation="Horizontal" Spacing="6">
|
||||
<TextBox
|
||||
IsEnabled="{x:Bind ViewModel.IsLXMusicServerTesting, Converter={StaticResource BoolNegationConverter}, Mode=OneWay}"
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Events
|
||||
{
|
||||
public class ExtendedSliderValueChangedByUserEventArgs : EventArgs
|
||||
{
|
||||
public double Value { get; set; }
|
||||
|
||||
public ExtendedSliderValueChangedByUserEventArgs(double value)
|
||||
{
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,6 +117,11 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
return new Vector3((float)color.R / 0xff, (float)color.G / 0xff, (float)color.B / 0xff);
|
||||
}
|
||||
|
||||
public static Color GetRandomColor()
|
||||
{
|
||||
return Color.FromArgb(255, (byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256), (byte)Random.Shared.Next(0, 256));
|
||||
}
|
||||
|
||||
public static System.Drawing.Color GetAccentColor(IntPtr myHwnd, string monitorDeviceName, WindowPixelSampleMode mode)
|
||||
{
|
||||
if (!User32.GetWindowRect(myHwnd, out RECT myRect)) return System.Drawing.Color.Transparent;
|
||||
|
||||
@@ -9,6 +9,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Xml.Linq;
|
||||
using LyricsData = BetterLyrics.WinUI3.Models.LyricsData;
|
||||
|
||||
@@ -98,7 +99,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
}
|
||||
}
|
||||
|
||||
private void FillRomanizationLyricsData()
|
||||
private async Task FillRomanizationLyricsData()
|
||||
{
|
||||
var chinese = LyricsDataArr.Where(x => x.LanguageCode == "zh").FirstOrDefault();
|
||||
if (chinese != null)
|
||||
|
||||
@@ -6,7 +6,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class PhoneticHelper
|
||||
public static class PhoneticHelper
|
||||
{
|
||||
public const string PinyinCode = "zh-pinyin";
|
||||
public const string JyutpingCode = "zh-jyutping";
|
||||
@@ -34,7 +34,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public static string ToRomaji(string text)
|
||||
{
|
||||
return Kana.Kana.KanaToRomaji(text).ToStr();
|
||||
return Kana.Kana.KanaToRomaji(text, Kana.Error.Ignore).ToStr();
|
||||
}
|
||||
|
||||
public static string ToPinyin(string text, Pinyin.ManTone.Style style = Pinyin.ManTone.Style.TONE)
|
||||
|
||||
@@ -1,37 +1,35 @@
|
||||
using BetterLyrics.WinUI3.Models.Settings;
|
||||
using NAudio.Dsp;
|
||||
using NAudio.Dsp;
|
||||
using NAudio.Wave;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public class SpectrumAnalyzer : IDisposable
|
||||
public partial class SpectrumAnalyzer : IDisposable
|
||||
{
|
||||
private WasapiLoopbackCapture _capture;
|
||||
|
||||
private WasapiLoopbackCapture? _capture;
|
||||
|
||||
private int _sampleRate = 48000;
|
||||
private readonly int _fftLength = 2048;
|
||||
|
||||
|
||||
private readonly float[] _fftLeftBuffer;
|
||||
private readonly float[] _fftRightBuffer;
|
||||
|
||||
private readonly Complex[] _fftLeftData;
|
||||
private readonly Complex[] _fftRightData;
|
||||
|
||||
private float[] _spectrumLeftData;
|
||||
private float[] _spectrumRightData;
|
||||
private float[] _spectrumData;
|
||||
|
||||
private float[]? _spectrumLeftData;
|
||||
private float[]? _spectrumRightData;
|
||||
private float[]? _spectrumData;
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
|
||||
private double[] _hammingWindow;
|
||||
|
||||
private float[] _currentSpectrum;
|
||||
public float[] SmoothSpectrum { get; private set; }
|
||||
|
||||
public int BarCount { get; set; } = 32;
|
||||
public int Sensitivity { get; set; } = 10;
|
||||
private float[]? _currentSpectrum;
|
||||
public float[]? SmoothSpectrum { get; private set; }
|
||||
|
||||
public int BarCount { get; set; } = 16;
|
||||
public int Sensitivity { get; set; } = 100;
|
||||
public float SmoothingFactor { get; set; } = 0.95f;
|
||||
public bool IsCapturing { get; private set; } = false;
|
||||
|
||||
@@ -51,12 +49,13 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public void StartCapture()
|
||||
{
|
||||
_currentSpectrum = new float[BarCount];
|
||||
SmoothSpectrum = new float[BarCount];
|
||||
|
||||
try
|
||||
{
|
||||
_capture = new WasapiLoopbackCapture();
|
||||
_currentSpectrum = new float[BarCount];
|
||||
SmoothSpectrum = new float[BarCount];
|
||||
|
||||
_capture = new();
|
||||
|
||||
_sampleRate = _capture.WaveFormat.SampleRate;
|
||||
_spectrumLeftData = new float[(int)(24000.0f / _sampleRate * _fftLength) / 2];
|
||||
_spectrumRightData = new float[(int)(24000.0f / _sampleRate * _fftLength) / 2];
|
||||
@@ -67,9 +66,7 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
IsCapturing = true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
public void StopCapture()
|
||||
@@ -100,10 +97,15 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
_fftRightData[i].Y = 0;
|
||||
}
|
||||
|
||||
if (_spectrumData == null || _spectrumRightData == null || _currentSpectrum == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// FFT
|
||||
FastFourierTransform.FFT(true, (int)Math.Log(_fftLength, 2), _fftLeftData);
|
||||
FastFourierTransform.FFT(true, (int)Math.Log(_fftLength, 2), _fftRightData);
|
||||
for (int i = 0; i < _spectrumLeftData.Length; i++)
|
||||
for (int i = 0; i < _spectrumLeftData?.Length; i++)
|
||||
{
|
||||
float real = (float)_fftLeftData[i].X;
|
||||
float imaginary = (float)_fftLeftData[i].Y;
|
||||
@@ -132,6 +134,11 @@ namespace BetterLyrics.WinUI3.Helper
|
||||
|
||||
public void UpdateSmoothSpectrum()
|
||||
{
|
||||
if (SmoothSpectrum == null || _currentSpectrum == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < BarCount; i++)
|
||||
{
|
||||
SmoothSpectrum[i] = SmoothSpectrum[i] * SmoothingFactor +
|
||||
|
||||
@@ -1,74 +1,62 @@
|
||||
using Microsoft.UI.Dispatching;
|
||||
using NAudio.CoreAudioApi;
|
||||
using System;
|
||||
using Vanara.Extensions;
|
||||
using Vanara.PInvoke;
|
||||
using static Vanara.PInvoke.CoreAudio;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BetterLyrics.WinUI3.Helper
|
||||
{
|
||||
public static class SystemVolumeHelper
|
||||
{
|
||||
private readonly static IMMDeviceEnumerator _deviceEnumerator = new();
|
||||
private static IAudioEndpointVolume? _endpointVolume = null;
|
||||
private static VolumeCallbackImpl? _callbackImpl;
|
||||
private static int _masterVolume = 0;
|
||||
private static MMDeviceEnumerator? _deviceEnumerator;
|
||||
private static MMDevice? _defaultDevice;
|
||||
private static DispatcherQueue _dispatcherQueue = DispatcherQueue.GetForCurrentThread();
|
||||
|
||||
public static event Action<int>? VolumeChanged;
|
||||
/// <summary>
|
||||
/// 当系统音量或静音状态改变时触发。
|
||||
/// </summary>
|
||||
public static event EventHandler<int>? VolumeNotification;
|
||||
|
||||
static SystemVolumeHelper()
|
||||
{
|
||||
var device = _deviceEnumerator.GetDefaultAudioEndpoint(EDataFlow.eRender, ERole.eMultimedia);
|
||||
if (device != null)
|
||||
_deviceEnumerator = new MMDeviceEnumerator();
|
||||
_defaultDevice = _deviceEnumerator.GetDefaultAudioEndpoint(DataFlow.Render, Role.Multimedia);
|
||||
|
||||
if (_defaultDevice != null)
|
||||
{
|
||||
device.Activate(typeof(IAudioEndpointVolume).GUID, 0, null, out var obj);
|
||||
if (obj is IAudioEndpointVolume endpointVolume)
|
||||
{
|
||||
_endpointVolume = endpointVolume;
|
||||
_callbackImpl = new VolumeCallbackImpl();
|
||||
_endpointVolume.RegisterControlChangeNotify(_callbackImpl);
|
||||
}
|
||||
_defaultDevice.AudioEndpointVolume.OnVolumeNotification += AudioEndpointVolume_OnVolumeNotification;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取当前系统主音量(0~100)。
|
||||
/// </summary>
|
||||
public static int GetMasterVolume()
|
||||
private static void AudioEndpointVolume_OnVolumeNotification(AudioVolumeNotificationData data)
|
||||
{
|
||||
if (_endpointVolume != null)
|
||||
_dispatcherQueue?.TryEnqueue(() =>
|
||||
{
|
||||
double level = _endpointVolume.GetMasterVolumeLevelScalar();
|
||||
_masterVolume = (int)(level * 100);
|
||||
VolumeNotification?.Invoke(null, (int)(data.MasterVolume * 100));
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取或设置系统主音量 (0 到 100)。
|
||||
/// </summary>
|
||||
public static int MasterVolume
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_defaultDevice == null)
|
||||
return 0;
|
||||
|
||||
return (int)(_defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar * 100);
|
||||
}
|
||||
|
||||
return _masterVolume;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置当前系统主音量(0~100)。
|
||||
/// </summary>
|
||||
public static void SetMasterVolume(int volume)
|
||||
{
|
||||
if (_masterVolume == volume) return;
|
||||
|
||||
_masterVolume = volume;
|
||||
_endpointVolume?.SetMasterVolumeLevelScalar(_masterVolume / 100f, Guid.Empty);
|
||||
}
|
||||
|
||||
// 内部回调实现
|
||||
private class VolumeCallbackImpl : IAudioEndpointVolumeCallback
|
||||
{
|
||||
HRESULT IAudioEndpointVolumeCallback.OnNotify(nint pNotify)
|
||||
set
|
||||
{
|
||||
var data = pNotify.ToStructure<AUDIO_VOLUME_NOTIFICATION_DATA>();
|
||||
_masterVolume = (int)(data.fMasterVolume * 100);
|
||||
_dispatcherQueue.TryEnqueue(DispatcherQueuePriority.Low, () =>
|
||||
{
|
||||
VolumeChanged?.Invoke(_masterVolume);
|
||||
});
|
||||
return HRESULT.S_OK;
|
||||
if (_defaultDevice == null)
|
||||
return;
|
||||
|
||||
_defaultDevice.AudioEndpointVolume.MasterVolumeLevelScalar = value / 100f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@ namespace BetterLyrics.WinUI3.Models.Settings
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsSpectrumOverlayEnabled { get; set; } = false;
|
||||
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial bool IsSnowFlakeOverlayEnabled { get; set; } = false;
|
||||
[ObservableProperty][NotifyPropertyChangedRecipients] public partial int SnowFlakeOverlayAmount { get; set; } = 50;
|
||||
|
||||
|
||||
public LyricsBackgroundSettings() { }
|
||||
|
||||
|
||||
@@ -49,16 +49,7 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.DockHeight):
|
||||
case nameof(LyricsWindowStatus.DockPlacement):
|
||||
if (LiveStates.LyricsWindowStatus.IsWorkArea)
|
||||
{
|
||||
WindowHelper.UpdateWorkArea<LyricsWindow>();
|
||||
await Task.Delay(300);
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(GetWindowBoundsWhenWorkArea());
|
||||
}
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.MonitorDeviceName):
|
||||
// 记录切换前的窗口状态是否沾满屏幕
|
||||
bool isStretchedToMonitor = LiveStates.LyricsWindowStatus.WindowBounds == LiveStates.LyricsWindowStatus.MonitorBounds;
|
||||
LiveStates.LyricsWindowStatus.UpdateMonitorBounds();
|
||||
if (LiveStates.LyricsWindowStatus.IsWorkArea)
|
||||
{
|
||||
@@ -66,22 +57,6 @@ namespace BetterLyrics.WinUI3.Services.LiveStatesService
|
||||
await Task.Delay(300);
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(GetWindowBoundsWhenWorkArea());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (isStretchedToMonitor)
|
||||
{
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(LiveStates.LyricsWindowStatus.MonitorBounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
WindowHelper.MoveAndResize<LyricsWindow>(new Rect(
|
||||
LiveStates.LyricsWindowStatus.MonitorBounds.X,
|
||||
LiveStates.LyricsWindowStatus.MonitorBounds.Y,
|
||||
Math.Min(LiveStates.LyricsWindowStatus.MonitorBounds.Width, LiveStates.LyricsWindowStatus.WindowBounds.Width),
|
||||
Math.Min(LiveStates.LyricsWindowStatus.MonitorBounds.Height, LiveStates.LyricsWindowStatus.WindowBounds.Height)
|
||||
));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case nameof(LyricsWindowStatus.IsShownInSwitchers):
|
||||
WindowHelper.SetIsShowInSwitchers<LyricsWindow>(LiveStates.LyricsWindowStatus.IsShownInSwitchers);
|
||||
|
||||
@@ -519,31 +519,36 @@ namespace BetterLyrics.WinUI3.Services.LyricsSearchService
|
||||
{
|
||||
var response = await Lyricify.Lyrics.Helpers.ProviderHelper.KugouApi.GetSearchLyrics(hash: kugouResult.Hash);
|
||||
string? original = null;
|
||||
var candidateWithTranslation = response?.Candidates.Where(x => x.TransId != null).FirstOrDefault();
|
||||
SearchLyricsResponse.Candidate? candidate;
|
||||
if (candidateWithTranslation != null)
|
||||
{
|
||||
candidate = candidateWithTranslation;
|
||||
}
|
||||
else
|
||||
{
|
||||
candidate = response?.Candidates.FirstOrDefault();
|
||||
}
|
||||
var candidate = response?.Candidates.FirstOrDefault();
|
||||
if (candidate != null)
|
||||
{
|
||||
original = await Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyricsAsync(candidate.Id, candidate.AccessKey);
|
||||
if (candidate.TransId != null)
|
||||
if (original != null)
|
||||
{
|
||||
string? translated = await Lyricify.Lyrics.Decrypter.Krc.Helper.GetLyricsAsync(candidate.TransId, candidate.AccessKey);
|
||||
if (!string.IsNullOrEmpty(translated))
|
||||
var parsedList = Lyricify.Lyrics.Parsers.KrcParser.ParseLyrics(original);
|
||||
if (parsedList != null)
|
||||
{
|
||||
FileHelper.WriteLyricsCache(
|
||||
title,
|
||||
artist,
|
||||
translated,
|
||||
LyricsFormat.Lrc,
|
||||
PathHelper.KugouTranslationCacheDirectory
|
||||
);
|
||||
string translated = "";
|
||||
foreach (var item in parsedList)
|
||||
{
|
||||
if (item is Lyricify.Lyrics.Models.FullSyllableLineInfo fullSyllableLineInfo)
|
||||
{
|
||||
var startTimeSpan = TimeSpan.FromMilliseconds(fullSyllableLineInfo.StartTime ?? 0);
|
||||
string startTimeStr = startTimeSpan.ToString(@"mm\:ss\.ff");
|
||||
string chTranslation = fullSyllableLineInfo.Translations.GetValueOrDefault("zh") ?? "";
|
||||
translated += $"[{startTimeStr}]{chTranslation}\n";
|
||||
}
|
||||
}
|
||||
if (!string.IsNullOrEmpty(translated))
|
||||
{
|
||||
FileHelper.WriteLyricsCache(
|
||||
title,
|
||||
artist,
|
||||
translated,
|
||||
LyricsFormat.Lrc,
|
||||
PathHelper.KugouTranslationCacheDirectory
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1192,6 +1192,9 @@ If you encounter any problems, please go to the Settings page, About tab, and vi
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>Current value: </value>
|
||||
</data>
|
||||
<data name="SettingsPageSnowFlakeLayer.Header" xml:space="preserve">
|
||||
<value>Snow flake layer</value>
|
||||
</data>
|
||||
<data name="SettingsPageSongInfo.Text" xml:space="preserve">
|
||||
<value>Song title & artist</value>
|
||||
</data>
|
||||
|
||||
@@ -1192,6 +1192,9 @@
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>現在の値: </value>
|
||||
</data>
|
||||
<data name="SettingsPageSnowFlakeLayer.Header" xml:space="preserve">
|
||||
<value>スノーフレークレイヤー</value>
|
||||
</data>
|
||||
<data name="SettingsPageSongInfo.Text" xml:space="preserve">
|
||||
<value>曲のタイトル&アーティスト</value>
|
||||
</data>
|
||||
|
||||
@@ -1192,6 +1192,9 @@
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>현재 가치 : </value>
|
||||
</data>
|
||||
<data name="SettingsPageSnowFlakeLayer.Header" xml:space="preserve">
|
||||
<value>스노우 플레이크 레이어</value>
|
||||
</data>
|
||||
<data name="SettingsPageSongInfo.Text" xml:space="preserve">
|
||||
<value>노래 제목 및 아티스트</value>
|
||||
</data>
|
||||
|
||||
@@ -1192,6 +1192,9 @@
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>当前值: </value>
|
||||
</data>
|
||||
<data name="SettingsPageSnowFlakeLayer.Header" xml:space="preserve">
|
||||
<value>雪花层</value>
|
||||
</data>
|
||||
<data name="SettingsPageSongInfo.Text" xml:space="preserve">
|
||||
<value>歌曲标题和艺术家</value>
|
||||
</data>
|
||||
|
||||
@@ -1192,6 +1192,9 @@
|
||||
<data name="SettingsPageSliderPrefix.Text" xml:space="preserve">
|
||||
<value>目前值: </value>
|
||||
</data>
|
||||
<data name="SettingsPageSnowFlakeLayer.Header" xml:space="preserve">
|
||||
<value>雪花層</value>
|
||||
</data>
|
||||
<data name="SettingsPageSongInfo.Text" xml:space="preserve">
|
||||
<value>歌曲標題和藝術家</value>
|
||||
</data>
|
||||
|
||||
@@ -38,8 +38,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
|
||||
LiveStates = _liveStatesService.LiveStates;
|
||||
|
||||
Volume = SystemVolumeHelper.GetMasterVolume();
|
||||
SystemVolumeHelper.VolumeChanged += SystemVolumeHelper_VolumeChanged;
|
||||
Volume = SystemVolumeHelper.MasterVolume;
|
||||
SystemVolumeHelper.VolumeNotification += SystemVolumeHelper_VolumeNotification;
|
||||
|
||||
_mediaSessionsService = mediaSessionsService;
|
||||
_mediaSessionsService.SongInfoChanged += PlaybackService_SongInfoChanged;
|
||||
@@ -49,16 +49,16 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
IsSongPlaying = _mediaSessionsService.IsPlaying;
|
||||
}
|
||||
|
||||
private void SystemVolumeHelper_VolumeNotification(object? sender, int e)
|
||||
{
|
||||
Volume = e;
|
||||
}
|
||||
|
||||
private void PlaybackService_TimelineChanged(object? sender, Events.TimelineChangedEventArgs e)
|
||||
{
|
||||
SongDurationSeconds = (int)e.End.TotalSeconds;
|
||||
}
|
||||
|
||||
private void SystemVolumeHelper_VolumeChanged(int volume)
|
||||
{
|
||||
Volume = volume;
|
||||
}
|
||||
|
||||
private void PlaybackService_IsPlayingChanged(object? sender, Events.IsPlayingChangedEventArgs e)
|
||||
{
|
||||
IsSongPlaying = e.IsPlaying;
|
||||
@@ -139,11 +139,6 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
TimelineSliderThumbLyricsLine = _mediaSessionsService.CurrentLyricsData?.GetLyricsLine(value);
|
||||
}
|
||||
|
||||
partial void OnVolumeChanged(int value)
|
||||
{
|
||||
SystemVolumeHelper.SetMasterVolume(value);
|
||||
}
|
||||
|
||||
public void Receive(PropertyChangedMessage<TimeSpan> message)
|
||||
{
|
||||
if (message.Sender is LyricsRendererViewModel.LyricsRendererViewModel)
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
public void DrawSpectrum(ICanvasAnimatedControl control, CanvasDrawingSession ds)
|
||||
{
|
||||
if (_spectrumAnalyzer != null && _liveStatesService.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.IsSpectrumOverlayEnabled)
|
||||
if (_spectrumAnalyzer != null && _spectrumAnalyzer.SmoothSpectrum != null && _liveStatesService.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.IsSpectrumOverlayEnabled)
|
||||
{
|
||||
var points = new Vector2[_spectrumAnalyzer.BarCount];
|
||||
float pointSpacing = 0;
|
||||
@@ -133,6 +133,17 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
points[i] = new Vector2(x, y);
|
||||
}
|
||||
|
||||
// 限制最高点高度
|
||||
var minY = points.OrderBy(p => p.Y).FirstOrDefault().Y;
|
||||
var limitY = _canvasHeight * (1 - 0.1f);
|
||||
if (minY < limitY)
|
||||
{
|
||||
var num = (float)(limitY / minY);
|
||||
points = points.Select(p => new Vector2(p.X, p.Y * num)).ToArray();
|
||||
}
|
||||
// 防止越过画布边界
|
||||
points = points.Select(p => new Vector2(p.X, (float)(Math.Min(_canvasHeight, p.Y)))).ToArray();
|
||||
|
||||
// 用于填充的闭合路径
|
||||
using var pathBuilder = new CanvasPathBuilder(ds);
|
||||
pathBuilder.BeginFigure(points[0]);
|
||||
@@ -164,21 +175,25 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
using var geometry = CanvasGeometry.CreatePath(pathBuilder);
|
||||
var gradientStops = new CanvasGradientStop[]
|
||||
{
|
||||
new() { Position = 0.0f, Color = _albumArtAccentColor1Transition.Value },
|
||||
new() { Position = 1.0f, Color = Colors.Transparent }
|
||||
new() { Position = 0.0f, Color = Colors.Transparent },
|
||||
new() { Position = 0.8f, Color = Colors.Transparent },
|
||||
new() { Position = 1.0f, Color = _adaptiveColoredFontColor ?? _albumArtAccentColor1Transition.Value }
|
||||
};
|
||||
|
||||
using var gradientBrush = new CanvasLinearGradientBrush(ds, gradientStops);
|
||||
gradientBrush.StartPoint = new Vector2((float)_canvasWidth / 2, (float)_canvasHeight);
|
||||
gradientBrush.EndPoint = new Vector2((float)_canvasWidth / 2, points.Select(p => p.Y).Min());
|
||||
gradientBrush.StartPoint = new Vector2(0, 0);
|
||||
gradientBrush.EndPoint = new Vector2(0, (float)_canvasHeight);
|
||||
|
||||
// 使用渐变画刷填充
|
||||
ds.FillGeometry(geometry, gradientBrush);
|
||||
|
||||
// 纯色
|
||||
//ds.FillGeometry(geometry, _adaptiveColoredFontColor ?? _albumArtAccentColor1Transition.Value);
|
||||
|
||||
// 绘制轮廓线
|
||||
// var lineColor = Colors.SkyBlue;
|
||||
// float strokeWidth = 2f;
|
||||
// session.DrawGeometry(geometry, lineColor, strokeWidth);
|
||||
//var lineColor = Colors.SkyBlue;
|
||||
//float strokeWidth = 2f;
|
||||
//ds.DrawGeometry(geometry, _albumArtAccentColor4Transition.Value, strokeWidth);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -340,7 +355,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
using var combinedDs = combined.CreateDrawingSession();
|
||||
|
||||
// 先铺一层带默认透明度的已经加了模糊效果的歌词作为最底层(背景歌词层次)
|
||||
using var backgroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
|
||||
using var backgroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
|
||||
_liveStatesService.LiveStates.LyricsWindowStatus.LyricsStyleSettings.LyricsFontStrokeWidth, _bgFontColor);
|
||||
|
||||
using var backgroundEffect = CanvasHelper.CreateBackgroundEffect(line, backgroundFontEffect, _lyricsOpacityTransition.Value);
|
||||
@@ -356,7 +371,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_liveStatesService.LiveStates.LyricsWindowStatus.LyricsEffectSettings.IsLyricsLineFadeEnabled);
|
||||
using var lineMask = CanvasHelper.CreateLineMask(control, line);
|
||||
|
||||
using var foregroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
|
||||
using var foregroundFontEffect = CanvasHelper.CreateFontEffect(line, control, _strokeFontColor,
|
||||
_liveStatesService.LiveStates.LyricsWindowStatus.LyricsStyleSettings.LyricsFontStrokeWidth, _fgFontColor);
|
||||
|
||||
using var effectLayer = new CanvasCommandList(control);
|
||||
|
||||
@@ -257,8 +257,10 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
_fluidEffect = null;
|
||||
}
|
||||
|
||||
private async void UpdateFluidEffect(ICanvasAnimatedControl control)
|
||||
private async void RecreateFluidEffect(ICanvasAnimatedControl control)
|
||||
{
|
||||
DisposeFluidEffect();
|
||||
|
||||
StorageFile file = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///Assets/FluidEffect.bin"));
|
||||
IBuffer buffer = await FileIO.ReadBufferAsync(file);
|
||||
var bytes = buffer.ToArray();
|
||||
|
||||
@@ -100,6 +100,10 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
{
|
||||
_isSpectrumOverlayEnabledChanged = true;
|
||||
}
|
||||
else if (message.PropertyName == nameof(LyricsBackgroundSettings.IsFluidOverlayEnabled))
|
||||
{
|
||||
_isFluidOverlayEnabledChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
private bool _isAlbumArtSizeChanged = false;
|
||||
|
||||
private bool _isSpectrumOverlayEnabledChanged = true;
|
||||
private bool _isFluidOverlayEnabledChanged = true;
|
||||
|
||||
private bool _isLyrics3DMatrixChanged = true;
|
||||
|
||||
@@ -76,11 +77,21 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
|
||||
//_effect?.Properties["iTime"] = Convert.ToSingle(TotalTime.TotalSeconds);
|
||||
|
||||
if (_fluidEffect == null)
|
||||
if (_isFluidOverlayEnabledChanged)
|
||||
{
|
||||
UpdateFluidEffect(control);
|
||||
if (_liveStatesService.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.IsFluidOverlayEnabled)
|
||||
{
|
||||
RecreateFluidEffect(control);
|
||||
}
|
||||
else
|
||||
{
|
||||
DisposeFluidEffect();
|
||||
}
|
||||
|
||||
_isFluidOverlayEnabledChanged = false;
|
||||
}
|
||||
else
|
||||
|
||||
if (_fluidEffect != null)
|
||||
{
|
||||
var effectTime = Convert.ToSingle(_fluidEffect.Properties["iTime"]);
|
||||
effectTime += Convert.ToSingle(_elapsedTime.TotalSeconds);
|
||||
@@ -710,11 +721,11 @@ namespace BetterLyrics.WinUI3.ViewModels.LyricsRendererViewModel
|
||||
{
|
||||
if (isLight)
|
||||
{
|
||||
_adaptiveColoredFontColor = _albumArtDarkAccentColors.FirstOrDefault();
|
||||
_adaptiveColoredFontColor = _albumArtDarkAccentColors.ElementAtOrDefault(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
_adaptiveColoredFontColor = _albumArtLightAccentColors.FirstOrDefault();
|
||||
_adaptiveColoredFontColor = _albumArtLightAccentColors.ElementAtOrDefault(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -173,8 +173,8 @@ namespace BetterLyrics.WinUI3.ViewModels
|
||||
{
|
||||
var lyricsParser = new LyricsParser();
|
||||
lyricsParser.Parse(
|
||||
MappedSongSearchQuery?.MappedTitle ?? "",
|
||||
MappedSongSearchQuery?.MappedArtist ?? "",
|
||||
MappedSongSearchQuery?.MappedTitle ?? "",
|
||||
MappedSongSearchQuery?.MappedArtist ?? "",
|
||||
value?.Raw, (int?)_mediaSessionsService.SongInfo?.DurationMs, value?.Provider);
|
||||
LyricsDataArr = [.. lyricsParser.LyricsDataArr];
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
||||
xmlns:converters="using:CommunityToolkit.WinUI.Converters"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:dev="using:DevWinUI"
|
||||
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
|
||||
xmlns:labs="using:CommunityToolkit.Labs.WinUI.MarqueeTextRns"
|
||||
xmlns:local="using:BetterLyrics.WinUI3.Views"
|
||||
@@ -25,7 +26,8 @@
|
||||
SizeChanged="RootGrid_SizeChanged">
|
||||
<!-- Lyrics area -->
|
||||
<renderer:LyricsRenderer />
|
||||
<!--<Image Source="/Assets/Cover.jpg" />-->
|
||||
|
||||
<dev:SnowFlakeEffect FlakeCount="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.SnowFlakeOverlayAmount, Mode=OneWay}" Visibility="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.LyricsBackgroundSettings.IsSnowFlakeOverlayEnabled, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
|
||||
<!-- No music playing placeholder -->
|
||||
<Grid x:Name="NoMusicPlayingGrid" Background="{ThemeResource AcrylicBackgroundFillColorBaseBrush}">
|
||||
@@ -36,9 +38,6 @@
|
||||
FontFamily="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.LyricsStyleSettings.LyricsCJKFontFamily, Mode=OneWay}"
|
||||
FontSize="{x:Bind ViewModel.LiveStates.LyricsWindowStatus.LyricsStyleSettings.OriginalLyricsFontSize, Mode=OneWay}"
|
||||
TextWrapping="Wrap" />
|
||||
<StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
|
||||
<HyperlinkButton x:Uid="SettingsPageFAQ" NavigateUri="{x:Bind const:Link.FAQUrl}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<Grid.OpacityTransition>
|
||||
<ScalarTransition />
|
||||
@@ -137,11 +136,13 @@
|
||||
<Button.ContextFlyout>
|
||||
<Flyout x:Name="VolumeFlyout" ShouldConstrainToRootBounds="False">
|
||||
<uc:ExtendedSlider
|
||||
Frequency="1"
|
||||
Frequency="10"
|
||||
IsSliderEnabled="False"
|
||||
Maximum="100"
|
||||
Minimum="0"
|
||||
ResetButtonVisibility="Collapsed"
|
||||
Unit="%"
|
||||
ValueChangedByUser="ExtendedSlider_ValueChangedByUser"
|
||||
Value="{x:Bind ViewModel.Volume, Mode=TwoWay}" />
|
||||
</Flyout>
|
||||
</Button.ContextFlyout>
|
||||
|
||||
@@ -180,5 +180,10 @@ namespace BetterLyrics.WinUI3.Views
|
||||
BottomCommandFlyout.ShowAt(BottomCommandFlyoutTrigger);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExtendedSlider_ValueChangedByUser(object sender, Events.ExtendedSliderValueChangedByUserEventArgs e)
|
||||
{
|
||||
SystemVolumeHelper.MasterVolume = ViewModel.Volume;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 372 KiB |
61
README.md
@@ -1,13 +1,23 @@
|
||||

|
||||
|
||||
<div align=center>
|
||||
<img src="BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Logo.png" alt="" width="64">
|
||||
<img src="BetterLyrics.WinUI3/BetterLyrics.WinUI3/Assets/Logo.png" alt="" width="96">
|
||||
</div>
|
||||
|
||||
<h2 align=center>
|
||||
BetterLyrics
|
||||
</h2>
|
||||
|
||||
<h4 align="center">
|
||||
Your dynamic lyrics display tool, built with WinUI 3 and Win2D, works with in-app playback and other players
|
||||
</h4>
|
||||
|
||||
<div align="center">
|
||||
|
||||
[**_Click here to view wiki_**](https://github.com/jayfunc/BetterLyrics/wiki)
|
||||
|
||||
</div>
|
||||
|
||||
<div align=center>
|
||||
|
||||
   
|
||||
@@ -20,17 +30,6 @@ BetterLyrics
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div align="center">
|
||||
|
||||
[**_Click here to view wiki_**](https://github.com/jayfunc/BetterLyrics/wiki)
|
||||
|
||||
</div>
|
||||
|
||||
<h4 align="center">
|
||||
Your dynamic lyrics display tool, built with WinUI 3 and Win2D, works with in-app playback and other players
|
||||
</h4>
|
||||
|
||||
## 🎉 This project was featured by SSPAI!
|
||||
|
||||
Check out the article: [BetterLyrics – An immersive and smooth lyrics display tool designed for Windows](https://sspai.com/post/101028)
|
||||
@@ -42,7 +41,12 @@ Check out the article: [BetterLyrics – An immersive and smooth lyrics display
|
||||
## 🌟 Highlighted features
|
||||
|
||||
- 🌠 **Pleasing User Interface**
|
||||
- Fluent animations and effects
|
||||
- Smooth and highly personalized style, animations and effects
|
||||
- Immersive fluid background
|
||||
- Perspective/fan-shaped lyrics
|
||||
- Snowflake effect
|
||||
- Multiple lyrics scrolling functions
|
||||
- ... (and more)
|
||||
- ↔️ **Strong Lyrics Translation**
|
||||
- Offline machine translation (supporting 30+ languages)
|
||||
- Auto-reading local lyrics files for embedded translation
|
||||
@@ -81,26 +85,18 @@ Check out the article: [BetterLyrics – An immersive and smooth lyrics display
|
||||
|
||||
## Screenshots
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
> ⚠️ Due to GIF format and frame rate limitations, the displayed effect is for preview only. Please refer to the actual device for the actual effect.
|
||||
|
||||
<div style="display: flex; justify-content: space-around; align-items: flex-start;">
|
||||
<img src="Screenshots/std.png" width="49%" >
|
||||
<img src="Screenshots/std-narrow.png" width="49%">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-around; align-items: flex-start;">
|
||||
<img src="Screenshots/PixPin_2025-10-24_18-13-44.gif" width="49%" >
|
||||
<img src="Screenshots/std-fullscreen.png" width="49%">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-around; align-items: flex-start;">
|
||||
<img src="Screenshots/dock.png" width="49%" >
|
||||
<img src="Screenshots/desktop.png" width="49%">
|
||||
</div>
|
||||
|
||||
<div style="display: flex; justify-content: space-around; align-items: flex-start;">
|
||||
<img src="Screenshots/PixPin_2025-10-24_18-17-17.gif" width="49%" >
|
||||
</div>
|
||||

|
||||

|
||||
|
||||
## Demonstration
|
||||
|
||||
@@ -136,6 +132,7 @@ Before you build, make sure that you have already replaced `BetterLyrics\BetterL
|
||||
| [LibreTranslate](https://github.com/LibreTranslate/LibreTranslate) | Provide the ability for offline lyrics translation |
|
||||
| [Isolation](https://github.com/Storyteller-Studios/Isolation) | Dynamic fluid background implementation |
|
||||
| [SpectrumVisualization](https://github.com/Johnwikix/SpectrumVisualization) | Audio visualization reference |
|
||||
| [DevWinUI](https://github.com/ghost1372/DevWinUI) | Provide many out-of-the-box features for building WinUI 3 applications |
|
||||
| ... | ... |
|
||||
|
||||
### Tutorials/Blogs/etc.
|
||||
@@ -163,7 +160,7 @@ Visit https://crowdin.com/project/betterlyrics/invite?h=c9bfb28fce061484883c0891
|
||||
## Star history
|
||||
|
||||
<div style="display: flex; justify-content: space-around; align-items: flex-start;">
|
||||
<img src="https://api.star-history.com/svg?repos=jayfunc/BetterLyrics&type=Date)](https://www.star-history.com/#jayfunc/BetterLyrics&Date" width="49%" >
|
||||
<img src="https://api.star-history.com/svg?repos=jayfunc/BetterLyrics&type=Date)](https://www.star-history.com/#jayfunc/BetterLyrics&Date" width="100%" >
|
||||
</div>
|
||||
|
||||
## Any issues and PRs are welcome
|
||||
|
||||
BIN
Screenshots/Snipaste_2025-10-31_19-23-17.png
Normal file
|
After Width: | Height: | Size: 620 KiB |
BIN
Screenshots/Snipaste_2025-10-31_19-27-34.png
Normal file
|
After Width: | Height: | Size: 629 KiB |
|
Before Width: | Height: | Size: 642 KiB After Width: | Height: | Size: 642 KiB |
BIN
Screenshots/fs2.png
Normal file
|
After Width: | Height: | Size: 466 KiB |
BIN
Screenshots/narrow.png
Normal file
|
After Width: | Height: | Size: 530 KiB |
|
Before Width: | Height: | Size: 847 KiB |
|
Before Width: | Height: | Size: 823 KiB After Width: | Height: | Size: 578 KiB |