diff --git a/windows/Audio/AudioTag.cs b/windows/Audio/AudioTag.cs index 637d072..0b161cf 100644 --- a/windows/Audio/AudioTag.cs +++ b/windows/Audio/AudioTag.cs @@ -44,19 +44,16 @@ public static AudioTag ReadTag(string audioFile, bool picture=false) AudioTag audioTag = new AudioTag(audioFile); try { -#if DEBUG -#else - //TagLib.File tagFile = TagLib.File.Create(audioFile); - //audioTag.Name = tagFile.Tag.Title; - //audioTag.Singer = tagFile.Tag.JoinedAlbumArtists; - //audioTag.Album = tagFile.Tag.Album; - //audioTag.Length = (int)Math.Floor(tagFile.Properties.Duration.TotalMilliseconds); - //audioTag.Duration = tagFile.Properties.Duration.ToString("mm\\:ss"); - //if (picture && tagFile.Tag.Pictures.Length > 0) - //{ - // audioTag.SetPicture(tagFile.Tag.Pictures[0].Data.Data, tagFile.Tag.Pictures[0].MimeType); - //} -#endif + TagLib.File tagFile = TagLib.File.Create(audioFile); + audioTag.Name = tagFile.Tag.Title; + audioTag.Singer = tagFile.Tag.JoinedAlbumArtists; + audioTag.Album = tagFile.Tag.Album; + audioTag.Length = (int)Math.Floor(tagFile.Properties.Duration.TotalMilliseconds); + audioTag.Duration = tagFile.Properties.Duration.ToString("mm\\:ss"); + if (picture && tagFile.Tag.Pictures.Length > 0) + { + audioTag.SetPicture(tagFile.Tag.Pictures[0].Data.Data, tagFile.Tag.Pictures[0].MimeType); + } } catch (Exception ex) { diff --git a/windows/Server/HttpHandler.cs b/windows/Server/HttpHandler.cs index fc05d93..7b6657d 100644 --- a/windows/Server/HttpHandler.cs +++ b/windows/Server/HttpHandler.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.IO; using System.Net; -using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows; @@ -13,17 +12,19 @@ namespace Musiche.Server { public class HttpHandler : Handler, IHandler { - private readonly Dictionary routers = new Dictionary(); - private readonly HashSet installChineseFonts = new HashSet(); + private readonly Dictionary> routers; + private static readonly string installChineseFontsJson = string.Empty; private readonly FileHandler fileHandler = new FileHandler(); public HttpHandler(MainWindow window, AudioPlay audioPlay) : base(window, audioPlay) { - InitFonts(); - routers = Utils.ReadRouter(this); + routers = Router.ReadHttpRouter(this); } - private void InitFonts() + static HttpHandler() { + ServicePointManager.ServerCertificateValidationCallback += + (sender, certificate, chain, sslPolicyErrors) => true; + HashSet installChineseFonts = new HashSet(); foreach (var family in System.Windows.Media.Fonts.SystemFontFamilies) { foreach (var keyPair in family.FamilyNames) @@ -35,12 +36,7 @@ private void InitFonts() } } } - } - - static HttpHandler() - { - ServicePointManager.ServerCertificateValidationCallback += - (sender, certificate, chain, sslPolicyErrors) => true; + installChineseFontsJson = JsonConvert.SerializeObject(installChineseFonts); } [Router("*")] @@ -61,6 +57,13 @@ public async Task ClipboardIndex(HttpListenerContext ctx) } } + [Router("/version")] + public async Task GetVersion(HttpListenerContext ctx) + { + byte[] data = fileHandler.GetFile("version"); + await SendString(ctx, data != null ? Encoding.UTF8.GetString(data) : Utils.App.Version); + } + [Router("/title")] public async Task SetTitle(HttpListenerContext ctx) { @@ -235,7 +238,7 @@ public async Task SetHide(HttpListenerContext ctx) [Router("/fonts")] public async Task InstalledFonts(HttpListenerContext ctx) { - await SendString(ctx, JsonConvert.SerializeObject(installChineseFonts), "text/json"); + await SendString(ctx, installChineseFontsJson, "text/json"); } [Router("/image")] @@ -466,20 +469,27 @@ public async Task Handle(HttpListenerContext context) return; } string router = context.Request.Url?.LocalPath.TrimEnd('/') ?? "*"; - routers.TryGetValue(router.ToUpper(), out MethodInfo methodInfo); - if (methodInfo == null) + routers.TryGetValue(router.ToUpper(), out Func func); + if (func == null) { - methodInfo = routers["*"]; + func = routers["*"]; } try { - if (methodInfo?.Invoke(this, new object[] { context }) is Task task) await task; - context.Response.Close(); + if (func == null) + { + context.Response.StatusCode = (int)HttpStatusCode.NotFound; + } + else + { + await func(context); + } } catch (Exception ex) { Logger.Logger.Error("Handle Http Error: ", ex); } + finally { context.Response.Close(); } } } } diff --git a/windows/Server/HttpProxy.cs b/windows/Server/HttpProxy.cs index 346001c..b82dce9 100644 --- a/windows/Server/HttpProxy.cs +++ b/windows/Server/HttpProxy.cs @@ -52,34 +52,6 @@ public static async Task Request(ProxyRequestData data) response.ContentEncoding ?? string.Empty, response.CharacterSet ?? string.Empty, resHeaders); - //using (Stream responseStream = response.GetResponseStream()) - //{ - - // if (response.ContentEncoding?.ToLower() == "gzip") - // { - // using (Stream gzipStream = new GZipStream(responseStream, CompressionMode.Decompress)) - // { - // return new ProxyResponseData( - // Utils.StreamToBytes(gzipStream), - // (int)response.StatusCode, - // response.ContentType, - // response.ContentEncoding, - // response.CharacterSet ?? string.Empty, - // resHeaders); - // } - // } - // else - // { - // return new ProxyResponseData( - // responseStream, - // response.ContentLength, - // (int)response.StatusCode, - // response.ContentType, - // response.ContentEncoding ?? string.Empty, - // response.CharacterSet ?? string.Empty, - // resHeaders); - // } - //} } catch (Exception ex) { diff --git a/windows/Server/Router.cs b/windows/Server/Router.cs new file mode 100644 index 0000000..dfd67e0 --- /dev/null +++ b/windows/Server/Router.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.WebSockets; +using System.Reflection; +using System.Threading.Tasks; + +namespace Musiche.Server +{ + public class Router + { + public static Dictionary> ReadHttpRouter(object obj) + { + Dictionary> routers = new Dictionary>(); + if(obj == null) return routers; + Type type = obj.GetType(); + MethodInfo[] methods = type.GetMethods(); + foreach (MethodInfo method in methods) + { + if(!IsParameterRoute(method, typeof(HttpListenerContext))) continue; + RouterAttribute[] attributes = (RouterAttribute[])method.GetCustomAttributes(typeof(RouterAttribute), false); + var func = method.IsStatic ? + (Func)Delegate.CreateDelegate(typeof(Func), method) : + (Func)Delegate.CreateDelegate(typeof(Func), obj, method); + foreach (RouterAttribute attribute in attributes) + { + routers.Add(attribute.Router.ToUpper(), func); + } + } + return routers; + } + public static Dictionary> ReadWebSocketRouter(object obj) + { + Dictionary> routers = new Dictionary>(); + if (obj == null) return routers; + Type type = obj.GetType(); + MethodInfo[] methods = type.GetMethods(); + foreach (MethodInfo method in methods) + { + if (!IsParameterRoute(method, typeof(WebSocket))) continue; + RouterAttribute[] attributes = (RouterAttribute[])method.GetCustomAttributes(typeof(RouterAttribute), false); + var func = method.IsStatic ? + (Func)Delegate.CreateDelegate(typeof(Func), method) : + (Func)Delegate.CreateDelegate(typeof(Func), obj, method); + foreach (RouterAttribute attribute in attributes) + { + routers.Add(attribute.Router.ToUpper(), func); + } + } + return routers; + } + + private static Func ToHttpRouteMethod(MethodInfo method) + { + if (method.IsStatic) + { + return (Func)Delegate.CreateDelegate(typeof(Func), method); + } + else + { + object instance = Activator.CreateInstance(method.DeclaringType); + return (Func)Delegate.CreateDelegate(typeof(Func), instance, method); + } + } + + private static Func ToWebSocketRouteMethod(MethodInfo method) + { + if (method.IsStatic) + { + return (Func)Delegate.CreateDelegate(typeof(Func), method); + } + else + { + object instance = Activator.CreateInstance(method.DeclaringType); + return (Func)Delegate.CreateDelegate(typeof(Func), instance, method); + } + } + + private static bool IsParameterRoute(MethodInfo method, Type parameterType) + { + return method.GetCustomAttributes().OfType().Any() + && method.DeclaringType != null + && method.ReturnType == typeof(Task) + && method.GetParameters().Length == 1 + && method.GetParameters().First().ParameterType == parameterType; + } + } +} diff --git a/windows/Server/Utils.cs b/windows/Server/Utils.cs deleted file mode 100644 index 81cc7dd..0000000 --- a/windows/Server/Utils.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Reflection; - -namespace Musiche.Server -{ - public class Utils - { - public static Dictionary ReadRouter(object obj) - { - Type type = obj.GetType(); - MethodInfo[] methods = type.GetMethods(); - Dictionary routers = new Dictionary(); - foreach (MethodInfo method in methods) - { - RouterAttribute[] attributes = (RouterAttribute[])method.GetCustomAttributes(typeof(RouterAttribute), false); - - foreach (RouterAttribute attribute in attributes) - { - routers.Add(attribute.Router.ToUpper(), method); - } - } - return routers; - } - - public static byte[] StreamToBytes(Stream stream) - { - using (var ms = new MemoryStream()) - { - stream.CopyTo(ms); - return ms.ToArray(); - } - } - } -} diff --git a/windows/Server/WebSocketHandler.cs b/windows/Server/WebSocketHandler.cs index f4fb0a9..4dd65ff 100644 --- a/windows/Server/WebSocketHandler.cs +++ b/windows/Server/WebSocketHandler.cs @@ -13,15 +13,15 @@ namespace Musiche.Server { public class WebSocketHandler : Handler, IHandler { - private readonly Dictionary routers; + private readonly Dictionary> routers; private readonly HashSet webSockets = new HashSet(); public WebSocketHandler(MainWindow window, AudioPlay audioPlay) : base(window, audioPlay) { - routers = Utils.ReadRouter(this); + routers = Router.ReadWebSocketRouter(this); } [Router("/status")] - public async Task WSStatus(WebSocket webSocket, string[] commands) + public async Task WSStatus(WebSocket webSocket) { var status = await GetStatus(); status.Add("type", "status"); @@ -70,11 +70,9 @@ public async Task Handle(HttpListenerContext context) foreach (var message in messageList) { var commands = message.Split(','); - routers.TryGetValue(commands[0].ToUpper(), out MethodInfo methodInfo); - if (methodInfo != null) + if (routers.TryGetValue(commands[0].ToUpper(), out Func func)) { - var task = methodInfo.Invoke(this, new object[] { webSocket, commands }) as Task; - if (task != null) await task; + await func(webSocket); } } } diff --git a/windows/Utils/App.cs b/windows/Utils/App.cs new file mode 100644 index 0000000..c743f17 --- /dev/null +++ b/windows/Utils/App.cs @@ -0,0 +1,11 @@ +namespace Musiche.Utils +{ + public class App + { + public static readonly string Version; + static App() + { + Version = System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetEntryAssembly().Location)?.ProductVersion ?? string.Empty; + } + } +}