From 719cf7dfc927ef9079342553e6cee1a166266962 Mon Sep 17 00:00:00 2001 From: LeZi9916 Date: Fri, 7 Feb 2025 15:15:24 +0800 Subject: [PATCH] fix: GetVideoPathAsync --- .../Types/DataFormats/OnlineSongDetail.cs | 109 +++++++- Assets/Scripts/Utils/SongStorage.cs | 256 +++++++++--------- 2 files changed, 241 insertions(+), 124 deletions(-) diff --git a/Assets/Scripts/Misc/Types/DataFormats/OnlineSongDetail.cs b/Assets/Scripts/Misc/Types/DataFormats/OnlineSongDetail.cs index b974dadc..a590e26b 100644 --- a/Assets/Scripts/Misc/Types/DataFormats/OnlineSongDetail.cs +++ b/Assets/Scripts/Misc/Types/DataFormats/OnlineSongDetail.cs @@ -14,6 +14,7 @@ using System.Buffers; using System.Threading; using Unity.VisualScripting.Antlr3.Runtime; +using System.Security.Policy; #nullable enable namespace MajdataPlay.Types { @@ -45,6 +46,7 @@ internal class OnlineSongDetail: ISongDetail readonly string _fullSizeCoverUriStr = string.Empty; readonly string _coverUriStr = string.Empty; + string? _videoPath = null; AudioSampleWrap? _audioTrack = null; AudioSampleWrap? _previewAudioTrack = null; Sprite? _cover = null; @@ -175,11 +177,47 @@ public async UniTask GetVideoPathAsync(CancellationToken token = default using (await _videoPathLock.LockAsync(token)) { token.ThrowIfCancellationRequested(); + + if(_videoPath is not null) + return _videoPath; var savePath = Path.Combine(_cachePath, "bg.mp4"); + var cacheFlagPath = Path.Combine(_cachePath, $"bg.mp4.cache"); - await CheckAndDownloadFile(_videoUri, savePath, token); + if (File.Exists(cacheFlagPath) && !File.Exists(savePath)) + { + _videoPath = string.Empty; + return _videoPath; + } + for (var i = 0; i <= MajEnv.HTTP_REQUEST_MAX_RETRY; i++) + { + try + { + var httpClient = MajEnv.SharedHttpClient; + using var rsp = await httpClient.GetAsync(_videoUri, HttpCompletionOption.ResponseHeadersRead, token); - return savePath; + if (rsp.StatusCode != System.Net.HttpStatusCode.OK) + { + using var _ = File.Create(cacheFlagPath); + _videoPath = string.Empty; + return _videoPath; + } + else + { + break; + } + } + catch (Exception e) + { + if (i == MajEnv.HTTP_REQUEST_MAX_RETRY) + { + MajDebug.LogError($"Failed to request resource: {_coverUri}\n{e}"); + throw; + } + } + } + await CheckAndDownloadFile(_videoUri, savePath, token); + _videoPath = savePath; + return _videoPath; } } finally @@ -230,7 +268,40 @@ async UniTask GetCompressedCoverAsync(CancellationToken token = default) if (_cover is not null) return _cover; var savePath = Path.Combine(_cachePath, "bg.jpg"); + var cacheFlagPath = Path.Combine(_cachePath, $"bg.jpg.cache"); + if (File.Exists(cacheFlagPath) && !File.Exists(savePath)) + { + _cover = MajEnv.EmptySongCover; + return _cover; + } + for (var i = 0; i <= MajEnv.HTTP_REQUEST_MAX_RETRY; i++) + { + try + { + var httpClient = MajEnv.SharedHttpClient; + using var rsp = await httpClient.GetAsync(_coverUri, HttpCompletionOption.ResponseHeadersRead, token); + + if (rsp.StatusCode != System.Net.HttpStatusCode.OK) + { + using var _ = File.Create(cacheFlagPath); + _cover = MajEnv.EmptySongCover; + return _cover; + } + else + { + break; + } + } + catch (Exception e) + { + if (i == MajEnv.HTTP_REQUEST_MAX_RETRY) + { + MajDebug.LogError($"Failed to request resource: {_coverUri}\n{e}"); + throw; + } + } + } await CheckAndDownloadFile(_coverUri, savePath, token); token.ThrowIfCancellationRequested(); _cover = await SpriteLoader.LoadAsync(savePath, token); @@ -253,7 +324,40 @@ async UniTask GetFullSizeCoverAsync(CancellationToken token = default) if (_fullSizeCover is not null) return _fullSizeCover; var savePath = Path.Combine(_cachePath, "bg_fullSize.jpg"); + var cacheFlagPath = Path.Combine(_cachePath, $"bg_fullSize.jpg.cache"); + if(File.Exists(cacheFlagPath) && !File.Exists(savePath)) + { + _fullSizeCover = MajEnv.EmptySongCover; + return _fullSizeCover; + } + for (var i = 0; i <= MajEnv.HTTP_REQUEST_MAX_RETRY; i++) + { + try + { + var httpClient = MajEnv.SharedHttpClient; + using var rsp = await httpClient.GetAsync(_fullSizeCoverUri, HttpCompletionOption.ResponseHeadersRead, token); + + if (rsp.StatusCode != System.Net.HttpStatusCode.OK) + { + using var _ = File.Create(cacheFlagPath); + _fullSizeCover = MajEnv.EmptySongCover; + return _fullSizeCover; + } + else + { + break; + } + } + catch (Exception e) + { + if (i == MajEnv.HTTP_REQUEST_MAX_RETRY) + { + MajDebug.LogError($"Failed to request resource: {_fullSizeCoverUri}\n{e}"); + throw; + } + } + } await CheckAndDownloadFile(_fullSizeCoverUri, savePath, token); token.ThrowIfCancellationRequested(); _fullSizeCover = await SpriteLoader.LoadAsync(savePath, token); @@ -286,6 +390,7 @@ await Task.Run(async () => return; } using var rsp = await httpClient.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead, token); + rsp.EnsureSuccessStatusCode(); token.ThrowIfCancellationRequested(); MajDebug.Log($"Received http response header from: {uri}"); diff --git a/Assets/Scripts/Utils/SongStorage.cs b/Assets/Scripts/Utils/SongStorage.cs index 28bddb83..cc00b58d 100644 --- a/Assets/Scripts/Utils/SongStorage.cs +++ b/Assets/Scripts/Utils/SongStorage.cs @@ -49,161 +49,173 @@ public static SongCollection WorkingCollection static int _collectionIndex = 0; public static async Task ScanMusicAsync(IProgress progressReporter) { - if (!Directory.Exists(MajEnv.ChartPath)) + try { - Directory.CreateDirectory(MajEnv.ChartPath); - Directory.CreateDirectory(Path.Combine(MajEnv.ChartPath, "default")); - return; + if (!Directory.Exists(MajEnv.ChartPath)) + { + Directory.CreateDirectory(MajEnv.ChartPath); + Directory.CreateDirectory(Path.Combine(MajEnv.ChartPath, "default")); + return; + } + var rootPath = MajEnv.ChartPath; + var songs = await GetCollections(rootPath, progressReporter); + + Collections = songs; + TotalChartCount = await Collections.ToUniTaskAsyncEnumerable().SumAsync(x => x.Count); + MajDebug.Log($"Loaded chart count: {TotalChartCount}"); } - var rootPath = MajEnv.ChartPath; - var task = GetCollections(rootPath,progressReporter); - var songs = await task; - if (task.IsFaulted) + catch(Exception e) { - var e = task.AsTask().Exception.InnerException; MajDebug.LogException(e); - throw e; + throw; } - else - Collections = songs; - TotalChartCount = await Collections.ToUniTaskAsyncEnumerable().SumAsync(x => x.Count); - MajDebug.Log($"Loaded chart count: {TotalChartCount}"); } - static async ValueTask GetCollections(string rootPath, IProgress progressReporter) + static async Task GetCollections(string rootPath, IProgress progressReporter) { - var dirs = new DirectoryInfo(rootPath).GetDirectories(); - List> tasks = new(); - List collections = new(); - - //Local Charts - foreach (var dir in dirs) + try { - var path = dir.FullName; - var files = dir.GetFiles(); - var maidataFile = files.FirstOrDefault(o => o.Name.ToLower() is "maidata.txt"); - var trackFile = files.FirstOrDefault(o => o.Name.ToLower() is "track.mp3" or "track.ogg"); - - if (maidataFile is not null || trackFile is not null) - continue; - - tasks.Add(GetCollection(path)); - } - - var a = Task.WhenAll(tasks); - await a; + var dirs = new DirectoryInfo(rootPath).GetDirectories(); + List> tasks = new(); + List collections = new(); - if (a.IsFaulted) - throw a.Exception.InnerException; - foreach (var task in tasks) - { - if (task.Result != null) - collections.Add(task.Result); - } - //Online Charts - if (MajInstances.Setting.Online.Enable) - { - foreach (var item in MajInstances.Setting.Online.ApiEndpoints) + //Local Charts + foreach (var dir in dirs) { - if (string.IsNullOrEmpty(item.Name)) + var path = dir.FullName; + var files = dir.GetFiles(); + var maidataFile = files.FirstOrDefault(o => o.Name.ToLower() is "maidata.txt"); + var trackFile = files.FirstOrDefault(o => o.Name.ToLower() is "track.mp3" or "track.ogg"); + + if (maidataFile is not null || trackFile is not null) continue; - progressReporter.Report(new ChartScanProgress() - { - StorageType = ChartStorageLocation.Online, - Message = item.Name - }); - var result = await GetOnlineCollection(item); - if (!result.IsEmpty) - collections.Add(result); + + tasks.Add(GetCollection(path)); } - } - //Add all songs to "All" folder - var allcharts = new List(); - foreach (var collection in collections) - { - foreach (var item in collection) + + await Task.WhenAll(tasks); + + foreach (var task in tasks) { - allcharts.Add(item); + if (task.Result != null) + collections.Add(task.Result); } - } - collections.Add(new SongCollection("All", allcharts.ToArray())); - MajDebug.Log("Load Dans"); - var danFiles = new DirectoryInfo(rootPath).GetFiles("*.json"); - foreach (var file in danFiles) - { - var json = File.ReadAllText(file.FullName); - var dan = Serializer.Json.Deserialize(json, new JsonSerializerOptions() + //Online Charts + if (MajInstances.Setting.Online.Enable) { - PropertyNameCaseInsensitive = false - }); - if(dan is null) + foreach (var item in MajInstances.Setting.Online.ApiEndpoints) + { + if (string.IsNullOrEmpty(item.Name)) + continue; + progressReporter.Report(new ChartScanProgress() + { + StorageType = ChartStorageLocation.Online, + Message = item.Name + }); + var result = await GetOnlineCollection(item); + if (!result.IsEmpty) + collections.Add(result); + } + } + //Add all songs to "All" folder + var allcharts = new List(); + foreach (var collection in collections) { - MajDebug.LogError("Failed to load dan file:" + file.FullName); - continue; + foreach (var item in collection) + { + allcharts.Add(item); + } } - List danSongs = new(); - foreach (var hash in dan.SongHashs) + collections.Add(new SongCollection("All", allcharts.ToArray())); + MajDebug.Log("Load Dans"); + var danFiles = new DirectoryInfo(rootPath).GetFiles("*.json"); + foreach (var file in danFiles) { - // search online first (so can upload score) - var songDetail = allcharts.FirstOrDefault(x => x.Hash == hash && x.IsOnline == true); - if (songDetail == null) - songDetail = allcharts.FirstOrDefault(x => x.Hash == hash); - if (songDetail is not null) - danSongs.Add(songDetail); - else + var json = File.ReadAllText(file.FullName); + var dan = Serializer.Json.Deserialize(json, new JsonSerializerOptions() + { + PropertyNameCaseInsensitive = false + }); + if (dan is null) + { + MajDebug.LogError("Failed to load dan file:" + file.FullName); + continue; + } + List danSongs = new(); + foreach (var hash in dan.SongHashs) { - MajDebug.LogError("Cannot find the song with hash:" + hash); - if (dan.IsPlayList) + // search online first (so can upload score) + var songDetail = allcharts.FirstOrDefault(x => x.Hash == hash && x.IsOnline == true); + if (songDetail == null) + songDetail = allcharts.FirstOrDefault(x => x.Hash == hash); + if (songDetail is not null) + danSongs.Add(songDetail); + else { - continue; + MajDebug.LogError("Cannot find the song with hash:" + hash); + if (dan.IsPlayList) + { + continue; + } + danSongs.Clear(); + break; } - danSongs.Clear(); - break; } + if (danSongs.Count == 0) + { + MajDebug.LogError("Failed to load dan, songs are empty or unable to find:" + dan.Name); + continue; + } + collections.Add(new SongCollection(dan.Name, danSongs.ToArray()) + { + Type = dan.IsPlayList ? ChartStorageType.List : ChartStorageType.Dan, + DanInfo = dan.IsPlayList ? null : dan + }); + MajDebug.Log("Loaded Dan:" + dan.Name); } - if(danSongs.Count == 0) - { - MajDebug.LogError("Failed to load dan, songs are empty or unable to find:" + dan.Name); - continue; - } - collections.Add(new SongCollection(dan.Name, danSongs.ToArray()) - { - Type = dan.IsPlayList ? ChartStorageType.List : ChartStorageType.Dan, - DanInfo = dan.IsPlayList ? null : dan - }); - MajDebug.Log("Loaded Dan:" + dan.Name); + return collections.ToArray(); + } + catch(Exception e) + { + MajDebug.LogException(e); + throw; } - return collections.ToArray(); } static async Task GetCollection(string rootPath) { return await Task.Run(async () => { - var thisDir = new DirectoryInfo(rootPath); - var dirs = thisDir.GetDirectories() - .OrderBy(o => o.CreationTime) - .ToList(); - var charts = new List(); - var tasks = new List>(); - foreach (var songDir in dirs) + try { - var files = songDir.GetFiles(); - var maidataFile = files.FirstOrDefault(o => o.Name is "maidata.txt"); - var trackFile = files.FirstOrDefault(o => o.Name is "track.mp3" or "track.ogg"); + var thisDir = new DirectoryInfo(rootPath); + var dirs = thisDir.GetDirectories() + .OrderBy(o => o.CreationTime) + .ToList(); + var charts = new List(); + var tasks = new List>(); + foreach (var songDir in dirs) + { + var files = songDir.GetFiles(); + var maidataFile = files.FirstOrDefault(o => o.Name is "maidata.txt"); + var trackFile = files.FirstOrDefault(o => o.Name is "track.mp3" or "track.ogg"); - if (maidataFile is null || trackFile is null) - continue; + if (maidataFile is null || trackFile is null) + continue; + + var parsingTask = SongDetail.ParseAsync(songDir.FullName); - var parsingTask = SongDetail.ParseAsync(songDir.FullName); + tasks.Add(parsingTask); + } + await Task.WhenAll(tasks); - tasks.Add(parsingTask); + foreach (var task in tasks) + charts.Add(task.Result); + return new SongCollection(thisDir.Name, charts.ToArray()); + } + catch(Exception e) + { + MajDebug.LogException(e); + throw; } - var a = Task.WhenAll(tasks); - await a; - if (a.IsFaulted) - throw a.Exception.InnerException; - foreach (var task in tasks) - charts.Add(task.Result); - return new SongCollection(thisDir.Name, charts.ToArray()); }); } static async Task GetOnlineCollection(ApiEndpoint api) @@ -246,7 +258,7 @@ static async Task GetOnlineCollection(ApiEndpoint api) } catch (Exception e) { - MajDebug.LogError(e); + MajDebug.LogException(e); return collection; } }