using System.Text; using Bmp.Core.Common.Net; using Bmp.Core.Common.Utility; namespace Bmp.Core.Lite.Playback.Inputs; public class InputSourceProviderLite { protected InputSourceProviderLite() { } public static string[] ExpandPaths(string inputPath) { // TODO: InputSourceProvider::ExpandPath M3U(8) ISO ZIP RAR 7Z / InURL // TODO: InputSourceProvider::ExpandPath EventBus for warn and err // [http[s]://foo.bar/]foo.zip?#path/to/inner/01.flac // [http[s]://foo.bar/]foo.iso?#DSD.ISO#1 var (exists, size) = FileCheckSize(inputPath); if (exists) { var ex = Path.GetExtension(inputPath).ToLower(); using var stream = ReadContentAsSeekableStream(inputPath); // TODO: ExpandPaths Pack Files : ISO zip rar 7z more // ------------ m3u/8 ------------ if (size.HasValue && size > 1024 * 1024) { // > 1MB may not playlist, skip } else { const string sign_ExtM3u = "#EXTM3U"; if (Encoding.ASCII.GetString(stream.ReadBytes(sign_ExtM3u.Length)) == sign_ExtM3u) { stream.Position = 0; var lines = stream.ReadLines(ex == ".m3u8" ? Encoding.UTF8 : null); return lines.Where(p => p.StartsWith("#") == false).ToArray(); } } } return new[] { inputPath }; } // ----- utils ----- protected static readonly IReadOnlyList CoverFilePaths = new List { "./Cover.jpg", "./Folder.jpg", "BK/Cover.jpg", "PIC/Cover.jpg", "PICS/Cover.jpg", "SCAN/Cover.jpg", "SCANS/Cover.jpg", "./Cover.webp", "./Folder.webp", "BK/Cover.webp", "PIC/Cover.webp", "PICS/Cover.webp", "SCAN/Cover.webp", "SCANS/Cover.webp", "./Cover.png", "./Folder.png", "BK/Cover.png", "PIC/Cover.png", "PICS/Cover.png", "SCAN/Cover.png", "SCANS/Cover.png" }; protected static string ProcessUrlOrPathForFFMPEG(string urlOrPath) { var processedUrlOrPath = urlOrPath; if (Uri.TryCreate(urlOrPath, UriKind.Absolute, out var url)) { if (url.IsFile) processedUrlOrPath = url.LocalPath; else if (url.IsAbsoluteUri) processedUrlOrPath = url.AbsoluteUri; } return processedUrlOrPath; } public static (bool exists, long? size) FileCheckSize(string urlOrPath) { var exists = false; long? size = null; if (!Uri.TryCreate(urlOrPath, UriKind.RelativeOrAbsolute, out var uri) || uri.IsAbsoluteUri == false || uri.IsFile) { if (!File.Exists(urlOrPath)) return (exists, size); exists = true; var fileInfo = new FileInfo(urlOrPath); size = fileInfo.Length; } else if (uri.IsAbsoluteUri && uri.Scheme.ToLower() == "data") { var base64 = urlOrPath.Split(",").LastOrDefault(); if (base64 != null) { try { var bytes = Convert.FromBase64String(base64); exists = true; return (exists, bytes.Length); } catch (Exception e) { //TODO: 消息机制 错误 解析 DataURI 失败 无法获取大小 Console.WriteLine(e); } } } else { using var client = new HttpClient(); // use GET instead of HEAD for compatible using var request = new HttpRequestMessage(HttpMethod.Get, urlOrPath); using var response = client.Send(request, HttpCompletionOption.ResponseHeadersRead); exists = response.IsSuccessStatusCode; if (exists && response.Content.Headers.ContentLength.HasValue) size = response.Content.Headers.ContentLength.Value; } return (exists, size); } public static ReadOnlyMemory ReadContent(string urlOrPath) { if (!Uri.TryCreate(urlOrPath, UriKind.RelativeOrAbsolute, out var uri) || uri.IsAbsoluteUri == false || uri.IsFile) { if (File.Exists(urlOrPath)) { return File.ReadAllBytes(urlOrPath); } } else { using var client = new HttpClient(); var req = new HttpRequestMessage(HttpMethod.Get, urlOrPath); var response = client.Send(req); if (response.IsSuccessStatusCode) { ReadOnlyMemory result = null; Task.Run(async () => { result = await response.Content.ReadAsByteArrayAsync(); }).Wait(); return result; } } return null; } public static Stream ReadContentAsSeekableStream(string urlOrPath) { if (!Uri.TryCreate(urlOrPath, UriKind.RelativeOrAbsolute, out var uri) || uri.IsAbsoluteUri == false || uri.IsFile) { return File.OpenRead(urlOrPath); } if (uri.IsAbsoluteUri && uri.Scheme.ToLower() == "data") { var base64 = urlOrPath.Split(",").LastOrDefault(); if (base64 != null) { try { var bytes = Convert.FromBase64String(base64); return new MemoryStream(bytes); } catch (Exception e) { //TODO: 消息机制 错误 解析 DataURI 失败 Console.WriteLine(e); throw; } } } return new SeekableHttpStream(urlOrPath); } }