Skip to content

Commit

Permalink
本地音乐加载优化,index等待修复 fix #62
Browse files Browse the repository at this point in the history
  • Loading branch information
Miaoyww committed Sep 28, 2024
1 parent f3fb8bd commit 30594a5
Show file tree
Hide file tree
Showing 7 changed files with 160 additions and 73 deletions.
5 changes: 1 addition & 4 deletions NonsPlayer.Core/Models/LocalMusic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,7 @@ public bool Init()
{
Name = Path.GetFileNameWithoutExtension(track.Title);
}

Cover = LocalUtils.CompressAndConvertToByteArray(GetCover(track), 80, 80);



Md5 = track.GetHashCode().ToString();
Id = $"{Name}_{Md5}";
Url = track.Path;
Expand Down
2 changes: 1 addition & 1 deletion NonsPlayer.Core/Utils/LocalUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static bool IsMusic(string path)
{
if (imageData == null) return null;

using var ms = new MemoryStream(imageData);
using var ms = new MemoryStream(imageData);
Image image = Image.Load(ms);
image.Mutate(x => x.Resize(width, height));
using var msOutput = new MemoryStream();
Expand Down
1 change: 1 addition & 0 deletions NonsPlayer/Components/Views/MusicListItemCard.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
FontSize="14"
HorizontalAlignment="Center" VerticalAlignment="Center" Margin="0,0,20,0"
Padding="0"
MinWidth="40"
FontWeight="Medium" />
<Border Grid.Column="1" Name="CoverBorder"
Background="{x:Bind ViewModel.Cover, Mode=OneWay}"
Expand Down
43 changes: 43 additions & 0 deletions NonsPlayer/Services/GlobalThreadPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using NonsPlayer.Core.Services;
using System.Collections.Concurrent;

namespace NonsPlayer.Services;

public class GlobalThreadPool
{
public static GlobalThreadPool Instance { get; } = new(16);
private readonly BlockingCollection<Action> _taskQueue = new();
private readonly Thread[] _workers;

public GlobalThreadPool(int numberOfThreads)
{
_workers = new Thread[numberOfThreads];
for (int i = 0; i < numberOfThreads; i++)
{
_workers[i] = new Thread(Worker);
_workers[i].Start();
}
}

private void Worker()
{
foreach (var task in _taskQueue.GetConsumingEnumerable())
{
task();
}
}

public void Enqueue(Action task)
{
_taskQueue.Add(task);
}

public void Shutdown()
{
_taskQueue.CompleteAdding();
foreach (var worker in _workers)
{
worker.Join();
}
}
}
15 changes: 7 additions & 8 deletions NonsPlayer/Services/LocalService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public class LocalService

private const string _dataKey = "local_dictionaries.json";
public ObservableCollection<LocalFolderModel> Directories = new();
public HashSet<LocalMusic> Songs = new();
public HashSet<LocalArtist> Artists = new();
public HashSet<LocalAlbum> Albums = new();
public List<LocalMusic> Songs = new();
public List<LocalArtist> Artists = new();
public List<LocalAlbum> Albums = new();

private FileService FileService = App.GetService<FileService>();

Expand All @@ -40,23 +40,22 @@ public bool TryAddDirection(string path)
return true;
}

public bool TryAddSong(LocalMusic song)
public void AddSong(LocalMusic song)
{
foreach (LocalMusic songItem in Songs)
{
if (songItem.FilePath.Equals(song.FilePath)) return false;
if (songItem.FilePath.Equals(song.FilePath)) return;
}

LocalFolderChanged?.Invoke(string.Empty);
var result = Songs.Add(song);
return result;
Songs.Add(song);
}

public void AddSongs(IEnumerable<LocalMusic> songs)
{
foreach (LocalMusic inputSongItem in songs)
{
TryAddSong(inputSongItem);
AddSong(inputSongItem);
}

LocalFolderChanged?.Invoke(string.Empty);
Expand Down
56 changes: 50 additions & 6 deletions NonsPlayer/ViewModels/Local/LocalMusicLibViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using ABI.Windows.Devices.Midi;
using CommunityToolkit.Mvvm.ComponentModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using NonsPlayer.Components.Models;
using NonsPlayer.Contracts.ViewModels;
using NonsPlayer.Core.Contracts.Models.Music;
using NonsPlayer.Core.Models;
using NonsPlayer.Core.Utils;
using NonsPlayer.Helpers;
using NonsPlayer.Models;
using NonsPlayer.Services;
using System.Collections.Concurrent;
using System.Collections.ObjectModel;
using static NonsPlayer.Core.Services.ControlFactory;

Expand All @@ -19,8 +22,10 @@ public partial class LocalMusicLibViewModel : ObservableObject, INavigationAware
public ObservableCollection<MusicModel> SongModels = new();
public ObservableCollection<LocalArtistModel> ArtistModels = new();
public ObservableCollection<LocalAlbumModel> AlbumModels = new();

private int taskCount = 8;
private int completedTasks = 0;
private LocalService localService = App.GetService<LocalService>();
private int currentItemGroupIndex;

public LocalMusicLibViewModel()
{
Expand All @@ -31,14 +36,10 @@ public async void Refresh()
{
var index = 0;
SongModels.Clear();
await LoadMusicItemsByGroup();
foreach (LocalMusic song in localService.Songs)
{
index++;
SongModels.Add(new MusicModel() { Index = index.ToString("D2"), Music = song, });
if (!song.IsInit)
{
if (!song.Init()) return;
}
if (song.Artists != null)
{
foreach (LocalArtist artist in song.Artists)
Expand Down Expand Up @@ -89,6 +90,49 @@ public async void Refresh()
}
}

public async void OnScrollViewerViewChanged(object? sender, ScrollViewerViewChangedEventArgs e)
{
if (sender is ScrollViewer scrollViewer)
{
var offset = scrollViewer.VerticalOffset;

var height = scrollViewer.ScrollableHeight;
if (height - offset <
AppConfig.Instance.AppSettings.PlaylistTrackCount &&
currentItemGroupIndex < localService.Songs.Count - 1)
await LoadMusicItemsByGroup();
}
}

/// <summary>
/// 用于分组加载MusicItem
/// </summary>
private async Task LoadMusicItemsByGroup()
{
for (var i = 0; i < AppConfig.Instance.AppSettings.PlaylistTrackCount; i++)
{
int currentIndex = currentItemGroupIndex + i;
if (currentIndex >= localService.Songs.Count) break; // 确保索引有效
GlobalThreadPool.Instance.Enqueue(() =>
{
var music = localService.Songs[currentIndex];
if (!music.IsInit)
{
music.Init();
music.Cover = LocalUtils.CompressAndConvertToByteArray(music.GetCover(), 80, 80);
}
var model = new MusicModel { Music = music, Index = (currentIndex + 1).ToString("D2") };
ServiceHelper.DispatcherQueue.TryEnqueue(() =>
{
SongModels.Add(model);
});
});
}

currentItemGroupIndex += AppConfig.Instance.AppSettings.PlaylistTrackCount;
}

public void OnNavigatedTo(object parameter)
{
}
Expand Down
111 changes: 57 additions & 54 deletions NonsPlayer/Views/Local/LocalMusicLibPage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,62 +10,65 @@
xmlns:views="using:NonsPlayer.Components.Views"
xmlns:models="using:NonsPlayer.Models"
mc:Ignorable="d">
<ScrollViewer>
<Grid Margin="{StaticResource PageCommonMargin}">
<Grid Margin="{StaticResource PageContentCommonMargin}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="本地音乐库"
Style="{StaticResource CommonTextStyle}"
FontSize="30" />
<SelectorBar Grid.Column="1"
VerticalAlignment="Center"
Margin="20,-4,0,0"
SelectionChanged="SelectorBar_OnSelectionChanged">
<SelectorBarItem x:Name="SelectorMusic"
Margin="0,0,10,0"
Tag="music"
IsSelected="True">
<TextBlock x:Name="MusicTextBlock"
Margin="5"
FontSize="20"
Style="{StaticResource CommonTextStyle}" />
</SelectorBarItem>
<SelectorBarItem x:Name="SelectorAlbum"
Tag="album"
Margin="0,0,10,0">
<TextBlock x:Name="AlbumTextBlock"
Margin="5"
FontSize="20"
Style="{StaticResource CommonTextStyle}" />
</SelectorBarItem>
<SelectorBarItem x:Name="SelectorArtist"
Tag="artist"
Margin="0,0,10,0">
<TextBlock x:Name="ArtistTextBlock"
Margin="5"
FontSize="20"
Style="{StaticResource CommonTextStyle}" />
</SelectorBarItem>
</SelectorBar>
</Grid>
<Grid Grid.Row="1">
<views:MusicListBar Visibility="{x:Bind MusicVisibility, Mode=OneWay}"
MusicItems="{x:Bind ViewModel.SongModels, Mode=OneWay}" />
<views:LocalArtistListBar Visibility="{x:Bind ArtistVisibility, Mode=OneWay}"
Models="{x:Bind ViewModel.ArtistModels, Mode=OneWay}" />
<Grid>
<ScrollViewer ViewChanged="{x:Bind ViewModel.OnScrollViewerViewChanged}">
<Grid Margin="{StaticResource PageCommonMargin}">
<Grid Margin="{StaticResource PageContentCommonMargin}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0"
Text="本地音乐库"
Style="{StaticResource CommonTextStyle}"
FontSize="30" />
<SelectorBar Grid.Column="1"
VerticalAlignment="Center"
Margin="20,-4,0,0"
SelectionChanged="SelectorBar_OnSelectionChanged">
<SelectorBarItem x:Name="SelectorMusic"
Margin="0,0,10,0"
Tag="music"
IsSelected="True">
<TextBlock x:Name="MusicTextBlock"
Margin="5"
FontSize="20"
Style="{StaticResource CommonTextStyle}" />
</SelectorBarItem>
<SelectorBarItem x:Name="SelectorAlbum"
Tag="album"
Margin="0,0,10,0">
<TextBlock x:Name="AlbumTextBlock"
Margin="5"
FontSize="20"
Style="{StaticResource CommonTextStyle}" />
</SelectorBarItem>
<SelectorBarItem x:Name="SelectorArtist"
Tag="artist"
Margin="0,0,10,0">
<TextBlock x:Name="ArtistTextBlock"
Margin="5"
FontSize="20"
Style="{StaticResource CommonTextStyle}" />
</SelectorBarItem>
</SelectorBar>
</Grid>
<Grid Grid.Row="1">
<views:MusicListBar Visibility="{x:Bind MusicVisibility, Mode=OneWay}"
MusicItems="{x:Bind ViewModel.SongModels, Mode=OneWay}" />
<views:LocalArtistListBar Visibility="{x:Bind ArtistVisibility, Mode=OneWay}"
Models="{x:Bind ViewModel.ArtistModels, Mode=OneWay}" />
</Grid>
</Grid>

</Grid>
</ScrollViewer>
</Grid>

</Grid>
</ScrollViewer>

</Page>

0 comments on commit 30594a5

Please sign in to comment.