From b6a668b32bd9891f8adf306abfbd26297840adfb Mon Sep 17 00:00:00 2001 From: Starrah Date: Tue, 28 Jul 2026 23:49:35 +0800 Subject: [PATCH 1/7] =?UTF-8?q?fix:=20remove=20MaiLib=20&=20SimaiSharp=20a?= =?UTF-8?q?gain=20=E5=AE=83=E4=BB=AC=E5=9C=A8=20c411998a=20=E4=B8=AD?= =?UTF-8?q?=E8=A2=AB=E5=86=8D=E6=AC=A1=E5=9C=B0=E9=94=99=E8=AF=AF=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0=E8=BF=9B=E6=9D=A5=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MaiLib | 1 - SimaiSharp | 1 - 2 files changed, 2 deletions(-) delete mode 160000 MaiLib delete mode 160000 SimaiSharp diff --git a/MaiLib b/MaiLib deleted file mode 160000 index c76e94e1..00000000 --- a/MaiLib +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c76e94e16592db4510e6f3b5f86cd2b7b360a350 diff --git a/SimaiSharp b/SimaiSharp deleted file mode 160000 index bcaf9387..00000000 --- a/SimaiSharp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit bcaf9387fb8dce045edba2415d8a8cca1d5057a7 From b1a424190fe0796945e50d6da58de49a3002e95e Mon Sep 17 00:00:00 2001 From: Starrah Date: Tue, 28 Jul 2026 23:55:58 +0800 Subject: [PATCH 2/7] =?UTF-8?q?fix:=204d250b86=20=E4=B8=AD=E5=B0=86XV2Core?= =?UTF-8?q?Lib=E6=9B=BF=E6=8D=A2=E4=B8=BAAcbCore=EF=BC=8C=E4=BD=86slnx?= =?UTF-8?q?=E4=B8=AD=E6=9C=AA=E5=81=9A=E7=9B=B8=E5=90=8C=E6=9B=B4=E6=94=B9?= =?UTF-8?q?=EF=BC=8C=E5=AF=BC=E8=87=B4=E9=A1=B9=E7=9B=AE=E6=97=A0=E6=B3=95?= =?UTF-8?q?from-scratch=E5=9C=B0=E7=BC=96=E8=AF=91=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Sitreamai.slnx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Sitreamai.slnx b/Sitreamai.slnx index 084d400c..20dc41b5 100644 --- a/Sitreamai.slnx +++ b/Sitreamai.slnx @@ -19,10 +19,7 @@ - - - - + From 2a1ec588600273d721fbf9a9d9ff64679ab61e3d Mon Sep 17 00:00:00 2001 From: Starrah Date: Wed, 29 Jul 2026 17:18:27 +0800 Subject: [PATCH 3/7] =?UTF-8?q?fix:=20Windows=E4=B8=8B=EF=BC=8C=E5=BC=80?= =?UTF-8?q?=E5=90=AF=E8=BF=9C=E7=A8=8B=E6=A8=A1=E5=BC=8F=E6=A8=A1=E5=BC=8F?= =?UTF-8?q?=E4=BD=86=E4=BB=8E=E6=9C=AC=E6=9C=BA=E8=AE=BF=E9=97=AE=EF=BC=88?= =?UTF-8?q?=E5=A6=82=E6=9C=AC=E5=9C=B0debug=E5=BC=80=E5=8F=91=E7=AD=89?= =?UTF-8?q?=E6=83=85=E5=86=B5=EF=BC=89=EF=BC=8C=E4=B9=9F=E4=BC=9A=E8=A2=AB?= =?UTF-8?q?=E8=AF=AF=E5=88=A4=E4=B8=BAisPhotino=E3=80=82=20=E6=94=B6?= =?UTF-8?q?=E7=AA=84=E4=BA=86isPhotino=E7=9A=84=E5=88=A4=E6=96=AD=E6=9D=A1?= =?UTF-8?q?=E4=BB=B6=E3=80=82=20=E5=90=8C=E6=97=B6=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BA=86`return=20Forbid()`=E7=9A=84=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=EF=BC=88=E4=BC=9A=E5=BC=95=E8=B5=B7500=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/AssetDir/ImportBrowseController.cs | 6 +++--- MaiChartManager/Front/src/client/api.ts | 9 ++++++--- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/MaiChartManager/Controllers/AssetDir/ImportBrowseController.cs b/MaiChartManager/Controllers/AssetDir/ImportBrowseController.cs index c547a223..51c2477d 100644 --- a/MaiChartManager/Controllers/AssetDir/ImportBrowseController.cs +++ b/MaiChartManager/Controllers/AssetDir/ImportBrowseController.cs @@ -23,7 +23,7 @@ public record ImportDirEntry(string Name, string Path, bool IsDirectory); public ActionResult PickImportFolder() { // 仅本地桌面场景,export / 远程模式下禁止 - if (StaticSettings.Config.Export) return Forbid(); + if (StaticSettings.Config.Export) return StatusCode(StatusCodes.Status403Forbidden); // 如果直接 return Forbid(); 的话,会由于框架内部的某些authentication scheme机制造成抛异常,导致500 var path = dialogService.PickFolder(); logger.LogInformation("PickImportFolder: {path}", path); // 取消时 PickFolder 返回 null,这里原样返回(前端按取消处理) @@ -35,7 +35,7 @@ public record ImportDirEntry(string Name, string Path, bool IsDirectory); public ActionResult> ListImportDir([FromQuery] string path) { // 仅本地桌面场景,export / 远程模式下禁止 - if (StaticSettings.Config.Export) return Forbid(); + if (StaticSettings.Config.Export) return StatusCode(StatusCodes.Status403Forbidden); if (string.IsNullOrEmpty(path) || !Directory.Exists(path)) { return Ok(Array.Empty()); @@ -64,7 +64,7 @@ public ActionResult> ListImportDir([FromQuery] strin public IActionResult ReadImportFile([FromQuery] string path, [FromQuery] string? name = null) { // 仅本地桌面场景,export / 远程模式下禁止 - if (StaticSettings.Config.Export) return Forbid(); + if (StaticSettings.Config.Export) return StatusCode(StatusCodes.Status403Forbidden); var fullPath = string.IsNullOrEmpty(name) ? path : Path.Combine(path, name); if (string.IsNullOrEmpty(fullPath) || !System.IO.File.Exists(fullPath)) { diff --git a/MaiChartManager/Front/src/client/api.ts b/MaiChartManager/Front/src/client/api.ts index 2655781a..fe94a0a8 100644 --- a/MaiChartManager/Front/src/client/api.ts +++ b/MaiChartManager/Front/src/client/api.ts @@ -43,9 +43,12 @@ export const getUrl = (suffix: string) => { return `${base}/MaiChartManagerServlet/${suffix}`; } -// 是否运行在 Photino(WebKitGTK) 宿主:本地宿主但不是 Windows WebView2。 -// WebKitGTK 不支持 window.open 弹新窗口,需要走后端用系统浏览器打开。 -export const isPhotino = isLocalHost && !isWebView; +// 是否运行在 Photino(WebKitGTK) 宿主。 +// 不能仅用 isLocalHost && !isWebView:因为Export 模式下用本机浏览器访问 localhost 也满足该条件。 +// Photino 暴露 window.external.sendMessage(见 PreviewChartButton),普通浏览器没有。 +export const isPhotino = + isLocalHost && !isWebView && + typeof (window as any).external?.sendMessage === 'function'; // 用系统浏览器打开一个 http/https URL(后端 xdg-open 等)。 // 给 Photino 用:WebKitGTK 弹不出 window.open 的新窗口,预览谱面等改为外部浏览器打开。 From 0b44584676efcea7ca11ac038c88e28e8bf8d98e Mon Sep 17 00:00:00 2001 From: Starrah Date: Wed, 29 Jul 2026 17:44:53 +0800 Subject: [PATCH 4/7] =?UTF-8?q?fix:=20fe4e433=20=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=BF=E5=BE=97isAbortError=E7=9A=84?= =?UTF-8?q?=E6=9D=A1=E4=BB=B6=E5=88=A4=E6=96=AD=E8=BF=87=E4=BA=8E=E4=B8=A5?= =?UTF-8?q?=E8=8B=9B=EF=BC=8C=E5=AF=BC=E8=87=B4=E6=AD=A3=E5=B8=B8=E7=9A=84?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E5=85=B3=E9=97=AD=E7=AA=97=E5=8F=A3=E7=AD=89?= =?UTF-8?q?=EF=BC=88ImportChartButton:closeModal=EF=BC=89=E8=A2=AB?= =?UTF-8?q?=E8=AF=AF=E5=88=A4=E4=B8=BA=E9=9D=9EAbortError=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ImportCreateChartButton/ImportChartButton/importErrors.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/MaiChartManager/Front/src/views/Charts/ImportCreateChartButton/ImportChartButton/importErrors.ts b/MaiChartManager/Front/src/views/Charts/ImportCreateChartButton/ImportChartButton/importErrors.ts index b9873df8..bb472904 100644 --- a/MaiChartManager/Front/src/views/Charts/ImportCreateChartButton/ImportChartButton/importErrors.ts +++ b/MaiChartManager/Front/src/views/Charts/ImportCreateChartButton/ImportChartButton/importErrors.ts @@ -33,6 +33,4 @@ export const getCaptureTarget = (errorValue: unknown): unknown => { return errorValue.error; }; -export const isAbortError = (errorValue: unknown): boolean => - errorValue instanceof DOMException && errorValue.name === "AbortError" || - errorValue instanceof Error && errorValue.name === "AbortError"; +export const isAbortError = (errorValue: any): boolean => errorValue?.name === "AbortError" From 50f436be49ef0a566e9d2c84a1a84773195b4595 Mon Sep 17 00:00:00 2001 From: Starrah Date: Wed, 29 Jul 2026 18:28:29 +0800 Subject: [PATCH 5/7] =?UTF-8?q?fix:=204d250b86=20=E4=B8=AD=EF=BC=8C?= =?UTF-8?q?=E6=8A=8AWindows=E4=B8=8B=E7=9A=84MP3=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E6=A8=A1=E5=BC=8F=E4=B9=9F=E7=BB=99=E6=89=AC=E4=BA=86=E3=80=82?= =?UTF-8?q?=E7=8E=B0=E5=9C=A8=E6=8A=8A=E5=AE=83=E5=8A=A0=E5=9B=9E=E6=9D=A5?= =?UTF-8?q?=EF=BC=8CMP3=E5=85=BC=E5=AE=B9=E6=A8=A1=E5=BC=8F=E4=BB=85?= =?UTF-8?q?=E5=9C=A8Windows=E4=B8=8B=E5=8F=AF=E7=94=A8=E3=80=82=20?= =?UTF-8?q?=E5=90=8C=E6=97=B6=E5=9C=A8Linux=E4=B8=8B=EF=BC=8C=E9=9A=90?= =?UTF-8?q?=E8=97=8F=E5=85=BC=E5=AE=B9=E6=A8=A1=E5=BC=8F=E7=9A=84=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/App/AppVersionController.cs | 24 +++++++++++++++---- MaiChartManager/Front/src/client/apiGen.ts | 13 ++++++++-- .../ImportChartButton/ErrorDisplayIdInput.tsx | 6 ++--- MaiChartManager/Utils/Audio.cs | 23 ++++++++++++++---- 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/MaiChartManager/Controllers/App/AppVersionController.cs b/MaiChartManager/Controllers/App/AppVersionController.cs index 01e1454b..ae8e47c9 100644 --- a/MaiChartManager/Controllers/App/AppVersionController.cs +++ b/MaiChartManager/Controllers/App/AppVersionController.cs @@ -8,16 +8,24 @@ namespace MaiChartManager.Controllers.App; public class AppVersionController(StaticSettings settings, ILogger logger) : ControllerBase { #if WINDOWS - public record AppVersionResult(string Version, int GameVersion, IapManager.LicenseStatus License, VideoConvert.HardwareAccelerationStatus HardwareAcceleration, string H264Encoder, string Locale); + public record AppVersionResult(string Version, int GameVersion, IapManager.LicenseStatus License, VideoConvert.HardwareAccelerationStatus HardwareAcceleration, string H264Encoder, string Locale, string Platform, bool Export); [HttpGet] public AppVersionResult GetAppVersion() { - return new AppVersionResult(Application.ProductVersion, settings.gameVersion, IapManager.License, VideoConvert.HardwareAcceleration, VideoConvert.H264Encoder, StaticSettings.CurrentLocale); + return new AppVersionResult( + Application.ProductVersion, + settings.gameVersion, + IapManager.License, + VideoConvert.HardwareAcceleration, + VideoConvert.H264Encoder, + StaticSettings.CurrentLocale, + OperatingSystem.IsWindows() ? "Windows" : "Linux", + StaticSettings.Config.Export); } #else public enum LicenseStatus { Pending, Active, Inactive } - public record AppVersionResult(string Version, int GameVersion, LicenseStatus License, VideoConvert.HardwareAccelerationStatus HardwareAcceleration, string H264Encoder, string Locale); + public record AppVersionResult(string Version, int GameVersion, LicenseStatus License, VideoConvert.HardwareAccelerationStatus HardwareAcceleration, string H264Encoder, string Locale, string Platform, bool Export); [HttpGet] public AppVersionResult GetAppVersion() @@ -29,7 +37,15 @@ public AppVersionResult GetAppVersion() var info = (System.Reflection.AssemblyInformationalVersionAttribute?)System.Attribute .GetCustomAttribute(asm, typeof(System.Reflection.AssemblyInformationalVersionAttribute)); var version = info?.InformationalVersion?.Split('+')[0] ?? "linux"; - return new AppVersionResult(version, settings.gameVersion, LicenseStatus.Active, VideoConvert.HardwareAcceleration, VideoConvert.H264Encoder, StaticSettings.CurrentLocale); + return new AppVersionResult( + version, + settings.gameVersion, + LicenseStatus.Active, + VideoConvert.HardwareAcceleration, + VideoConvert.H264Encoder, + StaticSettings.CurrentLocale, + OperatingSystem.IsWindows() ? "Windows" : "Linux", + StaticSettings.Config.Export); } #endif } diff --git a/MaiChartManager/Front/src/client/apiGen.ts b/MaiChartManager/Front/src/client/apiGen.ts index ae3b8c81..0b44405e 100644 --- a/MaiChartManager/Front/src/client/apiGen.ts +++ b/MaiChartManager/Front/src/client/apiGen.ts @@ -17,6 +17,14 @@ export enum VerifyStatus { Valid = "Valid", } +export enum StorePurchaseStatus { + Succeeded = "Succeeded", + AlreadyPurchased = "AlreadyPurchased", + NotPurchased = "NotPurchased", + NetworkError = "NetworkError", + ServerError = "ServerError", +} + export enum ShiftMethod { Legacy = "Legacy", Bar = "Bar", @@ -70,6 +78,8 @@ export interface AppVersionResult { hardwareAcceleration?: HardwareAccelerationStatus; h264Encoder?: string | null; locale?: string | null; + platform?: string | null; + export?: boolean; } export interface AudioPreviewTime { @@ -385,8 +395,7 @@ export interface RequestExportMaidataRequest { export interface RequestPurchaseResult { errorMessage?: string | null; - /** @format int32 */ - status?: number; + status?: StorePurchaseStatus; } export interface Section { diff --git a/MaiChartManager/Front/src/views/Charts/ImportCreateChartButton/ImportChartButton/ErrorDisplayIdInput.tsx b/MaiChartManager/Front/src/views/Charts/ImportCreateChartButton/ImportChartButton/ErrorDisplayIdInput.tsx index 524a3de4..18b2b6c8 100644 --- a/MaiChartManager/Front/src/views/Charts/ImportCreateChartButton/ImportChartButton/ErrorDisplayIdInput.tsx +++ b/MaiChartManager/Front/src/views/Charts/ImportCreateChartButton/ImportChartButton/ErrorDisplayIdInput.tsx @@ -2,7 +2,7 @@ import { computed, defineComponent, PropType, useId, watch } from "vue"; import { Button, CheckBox, Modal, NumberInput, Popover, Section, Select } from "@munet/ui"; import type { ImportChartMessageEx, ImportMeta, SavedOptions, TempOptions } from "./types"; import noJacket from '@/assets/noJacket.webp'; -import { addVersionList, genreList, showNeedPurchaseDialog } from "@/store/refs"; +import { addVersionList, genreList, showNeedPurchaseDialog, version } from "@/store/refs"; import GenreInput from "@/components/GenreInput"; import VersionInput from "@/components/VersionInput"; import { UTAGE_GENRE } from "@/consts"; @@ -76,7 +76,7 @@ export default defineComponent({
-
+ {version.value?.platform === 'Windows' &&
{t('chart.import.option.ignoreGapless')} {{ @@ -84,7 +84,7 @@ export default defineComponent({ default: () =>
{t('chart.import.option.ignoreGaplessTip')}
}}
-
+
}
} , diff --git a/MaiChartManager/Utils/Audio.cs b/MaiChartManager/Utils/Audio.cs index e592bd27..cb47e98b 100644 --- a/MaiChartManager/Utils/Audio.cs +++ b/MaiChartManager/Utils/Audio.cs @@ -67,9 +67,11 @@ public static Stream ConvertToWav(Stream src, string extension, float padding = using WaveStream reader = extension switch { ".ogg" => new NAudio.Vorbis.VorbisWaveReader(src, true), - ".mp3" when !forceUseNAudio => new WaveFileReader(ConvertToWavViaFfmpeg(src, ".mp3")), // 默认情况下,优先使用ffmpeg - // WAV / WMA / AAC(以及 MP3+forceUseNAudio 的兼容模式)原本走 Windows-only 的 MediaFoundation, - // 跨平台改为用 ffmpeg 把任意输入解码成 16bit PCM wav,再用 NAudio WaveFileReader 读取。 + // MP3 兼容模式(ignoreGapless):仅在 Windows 上用 MediaFoundation 解码, + // 这会忽略 MP3 Gapless 元数据,从而表现与 Visual Maimai 等软件一致的行为。 + // Linux 上无 MediaFoundation,因此兼容模式不可用(不管开不开启兼容模式,都一定会落到下面的ffmpeg逻辑中) + ".mp3" when forceUseNAudio && SupportsMp3CompatibilityMode => new StreamMediaFoundationReader(src), + // 一般情况(MP3 默认、WAV、WMA、AAC 等):走 ffmpeg 解码为 16bit PCM wav。 _ => new WaveFileReader(ConvertToWavViaFfmpeg(src, extension)), }; // 关于上述MP3 Gapless问题的影响等具体讨论,详见 https://github.com/MuNET-OSS/MaiChartManager/issues/40 @@ -99,14 +101,27 @@ public static Stream ConvertToWav(Stream src, string extension, float padding = stream.Position = 0; return stream; } + + /// MP3 兼容模式(ignoreGapless)依赖 Windows MediaFoundation,Linux 上不可用。 + public static bool SupportsMp3CompatibilityMode => OperatingSystem.IsWindows(); // 用 ffmpeg 把任意输入流(按 ext 写到临时文件)解码成 16bit PCM wav,返回 wav 的内存流。 // 替代 Windows-only 的 MediaFoundation,跨平台可用(系统 ffmpeg 已配好)。 private static MemoryStream ConvertToWavViaFfmpeg(Stream src, string ext) { - var tempFileGuid = Guid.NewGuid(); // ext 形如 ".mp3"/".wav"/".aac" 等;去掉前导点用作临时输入文件后缀 var inputExt = string.IsNullOrEmpty(ext) ? "" : (ext.StartsWith('.') ? ext : "." + ext); + + // 输入已是 wav 时无需 ffmpeg 转码,直接拷贝流内容 + if (inputExt.Equals(".wav", StringComparison.OrdinalIgnoreCase)) + { + var ms = new MemoryStream(); + src.CopyTo(ms); + ms.Position = 0; + return ms; + } + + var tempFileGuid = Guid.NewGuid(); var inputPath = Path.Combine(StaticSettings.tempPath, $"ConvertToWav_{tempFileGuid:N}{inputExt}"); var outputPath = Path.Combine(StaticSettings.tempPath, $"ConvertToWav_{tempFileGuid:N}.wav"); try From 3503ed1b56b4d5b761da58dc93d64131d86b2a5d Mon Sep 17 00:00:00 2001 From: Starrah Date: Wed, 29 Jul 2026 18:48:04 +0800 Subject: [PATCH 6/7] =?UTF-8?q?chore:=20=E5=B0=8F=E5=B0=8F=E5=9C=B0?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MaiChartManager/Locale.Designer.cs | 56 +++++++++++++-------------- MaiChartManager/Locale.resx | 2 +- MaiChartManager/Locale.zh-Hans.resx | 2 +- MaiChartManager/Locale.zh-Hant.resx | 2 +- MaiChartManager/Utils/ImageConvert.cs | 51 ++++++++++++++---------- 5 files changed, 61 insertions(+), 52 deletions(-) diff --git a/MaiChartManager/Locale.Designer.cs b/MaiChartManager/Locale.Designer.cs index c1819e57..14ac8a42 100644 --- a/MaiChartManager/Locale.Designer.cs +++ b/MaiChartManager/Locale.Designer.cs @@ -140,6 +140,33 @@ internal static string AwbNotFound { } } + /// + /// Looks up a localized string similar to Selected folder does not exist. + /// + internal static string BatchConvertPvFolderNotFound { + get { + return ResourceManager.GetString("BatchConvertPvFolderNotFound", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Batch PV conversion requires sponsor activation. + /// + internal static string BatchConvertPvNeedLicense { + get { + return ResourceManager.GetString("BatchConvertPvNeedLicense", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to No PV files found in the matching format. + /// + internal static string BatchConvertPvNoFiles { + get { + return ResourceManager.GetString("BatchConvertPvNoFiles", resourceCulture); + } + } + /// /// Looks up a localized string similar to Browser window not initialized. /// @@ -667,7 +694,7 @@ internal static string MusicIdExists { } /// - /// Looks up a localized string similar to Music has no charts. + /// Looks up a localized string similar to Music has no valid charts. /// internal static string MusicNoCharts { get { @@ -801,33 +828,6 @@ internal static string SelectVideoToConvert { } } - /// - /// Looks up a localized string similar to Batch PV conversion requires sponsor activation. - /// - internal static string BatchConvertPvNeedLicense { - get { - return ResourceManager.GetString("BatchConvertPvNeedLicense", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to No PV files found in the matching format. - /// - internal static string BatchConvertPvNoFiles { - get { - return ResourceManager.GetString("BatchConvertPvNoFiles", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Selected folder does not exist. - /// - internal static string BatchConvertPvFolderNotFound { - get { - return ResourceManager.GetString("BatchConvertPvFolderNotFound", resourceCulture); - } - } - /// /// Looks up a localized string similar to Unknown error. /// diff --git a/MaiChartManager/Locale.resx b/MaiChartManager/Locale.resx index 6c7f2324..12ea3470 100644 --- a/MaiChartManager/Locale.resx +++ b/MaiChartManager/Locale.resx @@ -199,7 +199,7 @@ If you notice any issues with the conversion result, you can try testing it in A A chart with difficulty {0} will be ignored - Music has no charts + Music has no valid charts Chart difficulty {0} contains {1}-note division, this value cannot exceed 384. Most cases can be fixed by modifying the chart diff --git a/MaiChartManager/Locale.zh-Hans.resx b/MaiChartManager/Locale.zh-Hans.resx index c8536ba3..c12c0efd 100644 --- a/MaiChartManager/Locale.zh-Hans.resx +++ b/MaiChartManager/Locale.zh-Hans.resx @@ -191,7 +191,7 @@ 有一个难度为 {0} 的谱面将被忽略 - 乐曲没有谱面 + 乐曲中没有有效的谱面 谱面难度 {0} 存在 {1} 分音符,这个数值不能大于 384。绝大多数这样的情况都是可以修改谱面解决的 diff --git a/MaiChartManager/Locale.zh-Hant.resx b/MaiChartManager/Locale.zh-Hant.resx index 72dbff24..94349f91 100644 --- a/MaiChartManager/Locale.zh-Hant.resx +++ b/MaiChartManager/Locale.zh-Hant.resx @@ -191,7 +191,7 @@ 有一個難度為 {0} 的譜面將被忽略 - 樂曲沒有譜面 + 樂曲中沒有有效的譜面 譜面難度 {0} 存在 {1} 分音符,這個數值不能大於 384。絕大多數這樣的情況都是可以修改譜面解決的 diff --git a/MaiChartManager/Utils/ImageConvert.cs b/MaiChartManager/Utils/ImageConvert.cs index 223b0996..8c4f4c97 100644 --- a/MaiChartManager/Utils/ImageConvert.cs +++ b/MaiChartManager/Utils/ImageConvert.cs @@ -23,31 +23,40 @@ public static class ImageConvert public static byte[]? GetTextureAsPngData(string inputAbPath) { var am = new AssetsManager(); - var bunInst = am.LoadBundleFile(inputAbPath, true); - var afileInst = am.LoadAssetsFileFromBundle(bunInst, 0, false); - - foreach (var info in afileInst.file.Metadata.AssetInfos) + BundleFileInstance? bunInst = null; + try { - var baseField = am.GetBaseField(afileInst, info); - if (baseField.IsDummy || baseField.TypeName != "Texture2D") continue; + bunInst = am.LoadBundleFile(inputAbPath, true); + var afileInst = am.LoadAssetsFileFromBundle(bunInst, 0, false); + + foreach (var info in afileInst.file.Metadata.AssetInfos) + { + var baseField = am.GetBaseField(afileInst, info); + if (baseField.IsDummy || baseField.TypeName != "Texture2D") continue; - var tex = TextureFile.ReadTextureFile(baseField); - // 从 bundle 内解析贴图像素数据:同时覆盖 inline "image data" 与 bundle 内部的 .resS streamData。 - // 游戏原始封面的像素数据存在 bundle 内部的 .resS 里,必须用 bundle 解析, - // 不能只读文件系统目录(之前用 FillPictureData(目录) 会导致原始封面解析失败、接口返回 404)。 - tex.SetPictureDataFromBundle(bunInst); - if (tex.pictureData is null || tex.pictureData.Length == 0) return null; + var tex = TextureFile.ReadTextureFile(baseField); + // 从 bundle 内解析贴图像素数据:同时覆盖 inline "image data" 与 bundle 内部的 .resS streamData。 + // 游戏原始封面的像素数据存在 bundle 内部的 .resS 里,必须用 bundle 解析, + // 不能只读文件系统目录(之前用 FillPictureData(目录) 会导致原始封面解析失败、接口返回 404)。 + tex.SetPictureDataFromBundle(bunInst); + if (tex.pictureData is null || tex.pictureData.Length == 0) return null; - var bgra = TextureFile.DecodeManagedData( - tex.pictureData, (TextureFormat)tex.m_TextureFormat, tex.m_Width, tex.m_Height, true); - if (bgra is null || bgra.Length == 0) return null; + var bgra = TextureFile.DecodeManagedData( + tex.pictureData, (TextureFormat)tex.m_TextureFormat, tex.m_Width, tex.m_Height, true); + if (bgra is null || bgra.Length == 0) return null; - using var image = Image.LoadPixelData(bgra, tex.m_Width, tex.m_Height); - image.Mutate(x => x.Flip(FlipMode.Vertical)); - using var ms = new MemoryStream(); - image.SaveAsPng(ms); - return ms.ToArray(); + using var image = Image.LoadPixelData(bgra, tex.m_Width, tex.m_Height); + image.Mutate(x => x.Flip(FlipMode.Vertical)); + using var ms = new MemoryStream(); + image.SaveAsPng(ms); + return ms.ToArray(); + } + return null; + } + finally + { + if (bunInst is not null) + am.UnloadBundleFile(bunInst); } - return null; } } From 9a067175e8669784307ee11f86d8feef61b72b85 Mon Sep 17 00:00:00 2001 From: Starrah Date: Wed, 29 Jul 2026 20:04:17 +0800 Subject: [PATCH 7/7] =?UTF-8?q?fix:=20=E5=AF=B9wav=E6=A0=BC=E5=BC=8F?= =?UTF-8?q?=E7=9A=84=E6=96=87=E4=BB=B6=E4=B9=9F=E4=BC=9A=E8=B0=83=E7=94=A8?= =?UTF-8?q?ffmpeg=E8=BD=AC=E6=8D=A2=E3=80=82=20=E5=90=A6=E5=88=99=EF=BC=8C?= =?UTF-8?q?=E5=8E=8B=E7=BC=A9=20WAV=EF=BC=88=E4=BE=8B=E5=A6=82=20ADPCM?= =?UTF-8?q?=EF=BC=89=E7=8E=B0=E5=9C=A8=E4=BC=9A=E5=9C=A8=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E6=97=B6=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- MaiChartManager/Utils/Audio.cs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/MaiChartManager/Utils/Audio.cs b/MaiChartManager/Utils/Audio.cs index cb47e98b..ba875a09 100644 --- a/MaiChartManager/Utils/Audio.cs +++ b/MaiChartManager/Utils/Audio.cs @@ -112,18 +112,10 @@ private static MemoryStream ConvertToWavViaFfmpeg(Stream src, string ext) // ext 形如 ".mp3"/".wav"/".aac" 等;去掉前导点用作临时输入文件后缀 var inputExt = string.IsNullOrEmpty(ext) ? "" : (ext.StartsWith('.') ? ext : "." + ext); - // 输入已是 wav 时无需 ffmpeg 转码,直接拷贝流内容 - if (inputExt.Equals(".wav", StringComparison.OrdinalIgnoreCase)) - { - var ms = new MemoryStream(); - src.CopyTo(ms); - ms.Position = 0; - return ms; - } - var tempFileGuid = Guid.NewGuid(); + // 输入/输出须用不同文件名,以防输入也是 .wav时,输入输出相同文件名导致报错。 var inputPath = Path.Combine(StaticSettings.tempPath, $"ConvertToWav_{tempFileGuid:N}{inputExt}"); - var outputPath = Path.Combine(StaticSettings.tempPath, $"ConvertToWav_{tempFileGuid:N}.wav"); + var outputPath = Path.Combine(StaticSettings.tempPath, $"ConvertToWav_{tempFileGuid:N}_out.wav"); try { Directory.CreateDirectory(StaticSettings.tempPath);