diff --git a/src/Project/Sucrose.Backgroundog/Extension/AudioSession.cs b/src/Project/Sucrose.Backgroundog/Extension/AudioSession.cs new file mode 100644 index 000000000..ff18fad84 --- /dev/null +++ b/src/Project/Sucrose.Backgroundog/Extension/AudioSession.cs @@ -0,0 +1,100 @@ +using NPSMLib; +using System.IO; +using SBET = Sucrose.Backgroundog.Extension.Thumbnail; +using SBMI = Sucrose.Backgroundog.Manage.Internal; + +namespace Sucrose.Backgroundog.Extension +{ + internal class AudioSession + { + private static void SetupEvents() + { + if (SBMI.PlayingSession != null) + { + SBMI.DataSource = SBMI.PlayingSession.ActivateMediaPlaybackDataSource(); + SBMI.DataSource.MediaPlaybackDataChanged += (s, e) => SetCurrentSession(); + } + } + + public static void SessionListChanged() + { + SBMI.PlayingSession = SBMI.SessionManager.CurrentSession; + SetupEvents(); + SetCurrentSession(); + } + + private static void SetCurrentSession() + { + if (SBMI.PlayingSession != null) + { + lock (SBMI.LockObject) + { + MediaObjectInfo MediaDetails = SBMI.DataSource.GetMediaObjectInfo(); + MediaPlaybackInfo MediaPlaybackInfo = SBMI.DataSource.GetMediaPlaybackInfo(); + MediaTimelineProperties MediaTimeline = SBMI.DataSource.GetMediaTimelineProperties(); + + string ThumbnailString = null; + + using (Stream Thumbnail = SBMI.DataSource.GetThumbnailStream()) + { + if (Thumbnail != null) + { + ThumbnailString = SBET.Create(Thumbnail); + Thumbnail.Flush(); + } + } + + SBMI.AudioData.State = true; + SBMI.AudioData.Title = MediaDetails.Title; + SBMI.AudioData.Artist = MediaDetails.Artist; + SBMI.AudioData.Subtitle = MediaDetails.Subtitle; + SBMI.AudioData.AlbumTitle = MediaDetails.AlbumTitle; + SBMI.AudioData.AlbumArtist = MediaDetails.AlbumArtist; + SBMI.AudioData.TrackNumber = MediaDetails.TrackNumber; + SBMI.AudioData.AlbumTrackCount = MediaDetails.AlbumTrackCount; + SBMI.AudioData.MediaType = MediaPlaybackDataSource.MediaSchemaToMediaPlaybackMode(MediaDetails.MediaClassPrimaryID); + + SBMI.AudioData.PID = SBMI.PlayingSession?.PID; + SBMI.AudioData.Hwnd = SBMI.PlayingSession?.Hwnd; + SBMI.AudioData.SourceAppId = SBMI.PlayingSession?.SourceAppId; + SBMI.AudioData.SourceDeviceId = SBMI.PlayingSession?.SourceDeviceId; + SBMI.AudioData.RenderDeviceId = SBMI.PlayingSession?.RenderDeviceId; + + SBMI.AudioData.RepeatMode = MediaPlaybackInfo.RepeatMode; + SBMI.AudioData.PropsValid = MediaPlaybackInfo.PropsValid; + SBMI.AudioData.PlaybackRate = MediaPlaybackInfo.PlaybackRate; + SBMI.AudioData.PlaybackMode = MediaPlaybackInfo.PlaybackMode; + SBMI.AudioData.PlaybackCaps = MediaPlaybackInfo.PlaybackCaps; + SBMI.AudioData.PlaybackState = MediaPlaybackInfo.PlaybackState; + SBMI.AudioData.ShuffleEnabled = MediaPlaybackInfo.ShuffleEnabled; + SBMI.AudioData.LastPlayingFileTime = MediaPlaybackInfo.LastPlayingFileTime; + + SBMI.AudioData.EndTime = MediaTimeline.EndTime; + SBMI.AudioData.Position = MediaTimeline.Position; + SBMI.AudioData.StartTime = MediaTimeline.StartTime; + SBMI.AudioData.MinSeekTime = MediaTimeline.MinSeekTime; + SBMI.AudioData.MaxSeekTime = MediaTimeline.MaxSeekTime; + SBMI.AudioData.PositionSetFileTime = MediaTimeline.PositionSetFileTime; + + SBMI.AudioData.ThumbnailString = ThumbnailString; + + if (string.IsNullOrEmpty(ThumbnailString)) + { + SBMI.AudioData.ThumbnailAddress = ThumbnailString; + } + else + { + SBMI.AudioData.ThumbnailAddress = "data:image/png;base64," + ThumbnailString; + } + } + } + else + { + lock (SBMI.LockObject) + { + SBMI.AudioData.State = false; + } + } + } + } +} \ No newline at end of file diff --git a/src/Project/Sucrose.Backgroundog/Extension/Data.cs b/src/Project/Sucrose.Backgroundog/Extension/Data.cs index ccc326905..36f3a3a9f 100644 --- a/src/Project/Sucrose.Backgroundog/Extension/Data.cs +++ b/src/Project/Sucrose.Backgroundog/Extension/Data.cs @@ -155,7 +155,10 @@ public static JObject GetMotherboardInfo() { return new JObject { - { "Name", SBMI.MotherboardData.Name } + { "Name", SBMI.MotherboardData.Name }, + { "Product", SBMI.MotherboardData.Product }, + { "Version", SBMI.MotherboardData.Version }, + { "Manufacturer", SBMI.MotherboardData.Manufacturer } }; } } diff --git a/src/Project/Sucrose.Backgroundog/Extension/Thumbnail.cs b/src/Project/Sucrose.Backgroundog/Extension/Thumbnail.cs new file mode 100644 index 000000000..c784396c3 --- /dev/null +++ b/src/Project/Sucrose.Backgroundog/Extension/Thumbnail.cs @@ -0,0 +1,54 @@ +using System.Drawing.Imaging; +using System.IO; +using SBMM = Sucrose.Backgroundog.Manage.Manager; + +namespace Sucrose.Backgroundog.Extension +{ + internal class Thumbnail + { + public static string Create(Stream stream) + { + using MemoryStream Stream = new(); + + Stream.Seek(0, SeekOrigin.Begin); + stream.CopyTo(Stream); + + if (!SBMM.Windows11_OrGreater) + { + using Bitmap Image = new(Stream); + + if (PixelAlpha(Image, 0, 0)) + { + return CropImage(Image, 34, 1, 233, 233); + } + } + + byte[] Array = Stream.ToArray(); + + return Convert.ToBase64String(Array); + } + + private static bool PixelAlpha(Bitmap Image, int X, int Y) + { + return Image.GetPixel(X, Y).A == 0; + } + + private static string CropImage(Bitmap Image, int X, int Y, int Width, int Height) + { + Rectangle Rect = new(X, Y, Width, Height); + + using Bitmap CroppedBitmap = new(Rect.Width, Rect.Height, Image.PixelFormat); + + Graphics Graphic = Graphics.FromImage(CroppedBitmap); + Graphic.DrawImage(Image, 0, 0, Rect, GraphicsUnit.Pixel); + + using MemoryStream Stream = new(); + + CroppedBitmap.Save(Stream, ImageFormat.Png); + + byte[] ByteImage = Stream.ToArray(); + + return Convert.ToBase64String(ByteImage); + } + } +} \ No newline at end of file diff --git a/src/Project/Sucrose.Backgroundog/Helper/Specification.cs b/src/Project/Sucrose.Backgroundog/Helper/Specification.cs index 1fe87e47a..4549c6791 100644 --- a/src/Project/Sucrose.Backgroundog/Helper/Specification.cs +++ b/src/Project/Sucrose.Backgroundog/Helper/Specification.cs @@ -1,11 +1,9 @@ using LibreHardwareMonitor.Hardware; -using NPSMLib; using Skylark.Enum; using Skylark.Helper; using Skylark.Standard.Extension.Storage; -using System.Drawing.Imaging; -using System.IO; using System.Management; +using SBEAS = Sucrose.Backgroundog.Extension.AudioSession; using SBEUV = Sucrose.Backgroundog.Extension.UpdateVisitor; using SBMI = Sucrose.Backgroundog.Manage.Internal; using SMMM = Sucrose.Manager.Manage.Manager; @@ -82,8 +80,10 @@ public static async Task Start() { SBMI.AudioManagement = false; - SBMI.SessionManager.SessionListChanged += SessionListChanged; + SBMI.SessionManager.SessionListChanged += (s, e) => SBEAS.SessionListChanged(); } + + SBEAS.SessionListChanged(); }); _ = Task.Run(() => @@ -114,6 +114,24 @@ public static async Task Start() } }); + _ = Task.Run(() => + { + if (SBMI.MotherboardManagement) + { + SBMI.MotherboardManagement = false; + + ManagementObjectSearcher Searcher = new("SELECT * FROM Win32_BaseBoard"); + + foreach (ManagementObject Object in Searcher.Get().Cast()) + { + SBMI.MotherboardData.Product = Object["Product"].ToString(); + SBMI.MotherboardData.Version = Object["Version"].ToString(); + SBMI.MotherboardData.Manufacturer = Object["Manufacturer"].ToString(); + break; + } + } + }); + _ = Task.Run(() => { SBMI.Computer.Accept(new SBEUV()); @@ -231,10 +249,7 @@ public static async Task Start() { Hardware.Update(); - SBMI.MotherboardData = new() - { - Name = Hardware.Name - }; + SBMI.MotherboardData.Name = Hardware.Name; } } }); @@ -267,132 +282,5 @@ public static async Task Start() await Task.CompletedTask; } - - private static void SessionListChanged(object sender, NowPlayingSessionManagerEventArgs e) - { - SBMI.PlayingSession = SBMI.SessionManager.CurrentSession; - SetupEvents(); - PrintCurrentSession(); - } - - private static void SetupEvents() - { - if (SBMI.PlayingSession != null) - { - SBMI.DataSource = SBMI.PlayingSession.ActivateMediaPlaybackDataSource(); - SBMI.DataSource.MediaPlaybackDataChanged += M_MediaPlaybackDataChanged; - } - } - - private static void M_MediaPlaybackDataChanged(object sender, MediaPlaybackDataChangedArgs e) - { - PrintCurrentSession(); - } - - private static void PrintCurrentSession() - { - if (SBMI.PlayingSession != null) - { - lock (SBMI.LockObject) - { - MediaObjectInfo MediaDetails = SBMI.DataSource.GetMediaObjectInfo(); - MediaPlaybackInfo MediaPlaybackInfo = SBMI.DataSource.GetMediaPlaybackInfo(); - MediaTimelineProperties MediaTimeline = SBMI.DataSource.GetMediaTimelineProperties(); - - using Stream Thumbnail = SBMI.DataSource.GetThumbnailStream(); - string ThumbnailString = Thumbnail is null ? null : CreateThumbnail(Thumbnail); - - SBMI.AudioData.State = true; - SBMI.AudioData.Title = MediaDetails.Title; - SBMI.AudioData.Artist = MediaDetails.Artist; - SBMI.AudioData.Subtitle = MediaDetails.Subtitle; - SBMI.AudioData.AlbumTitle = MediaDetails.AlbumTitle; - SBMI.AudioData.AlbumArtist = MediaDetails.AlbumArtist; - SBMI.AudioData.TrackNumber = MediaDetails.TrackNumber; - SBMI.AudioData.AlbumTrackCount = MediaDetails.AlbumTrackCount; - SBMI.AudioData.MediaType = MediaPlaybackDataSource.MediaSchemaToMediaPlaybackMode(MediaDetails.MediaClassPrimaryID); - - SBMI.AudioData.PID = SBMI.PlayingSession?.PID; - SBMI.AudioData.Hwnd = SBMI.PlayingSession?.Hwnd; - SBMI.AudioData.SourceAppId = SBMI.PlayingSession?.SourceAppId; - SBMI.AudioData.SourceDeviceId = SBMI.PlayingSession?.SourceDeviceId; - SBMI.AudioData.RenderDeviceId = SBMI.PlayingSession?.RenderDeviceId; - - SBMI.AudioData.RepeatMode = MediaPlaybackInfo.RepeatMode; - SBMI.AudioData.PropsValid = MediaPlaybackInfo.PropsValid; - SBMI.AudioData.PlaybackRate = MediaPlaybackInfo.PlaybackRate; - SBMI.AudioData.PlaybackMode = MediaPlaybackInfo.PlaybackMode; - SBMI.AudioData.PlaybackCaps = MediaPlaybackInfo.PlaybackCaps; - SBMI.AudioData.PlaybackState = MediaPlaybackInfo.PlaybackState; - SBMI.AudioData.ShuffleEnabled = MediaPlaybackInfo.ShuffleEnabled; - SBMI.AudioData.LastPlayingFileTime = MediaPlaybackInfo.LastPlayingFileTime; - - SBMI.AudioData.EndTime = MediaTimeline.EndTime; - SBMI.AudioData.Position = MediaTimeline.Position; - SBMI.AudioData.StartTime = MediaTimeline.StartTime; - SBMI.AudioData.MinSeekTime = MediaTimeline.MinSeekTime; - SBMI.AudioData.MaxSeekTime = MediaTimeline.MaxSeekTime; - SBMI.AudioData.PositionSetFileTime = MediaTimeline.PositionSetFileTime; - - SBMI.AudioData.ThumbnailString = ThumbnailString; - - if (string.IsNullOrEmpty(ThumbnailString)) - { - SBMI.AudioData.ThumbnailAddress = ThumbnailString; - } - else - { - SBMI.AudioData.ThumbnailAddress = "data:image/png;base64," + ThumbnailString; - } - } - } - else - { - lock (SBMI.LockObject) - { - SBMI.AudioData.State = false; - } - } - } - - private static readonly bool isWindows11_OrGreater = Environment.OSVersion.Version.Build >= 22000; - - private static string CreateThumbnail(Stream stream) - { - using MemoryStream ms = new(); - ms.Seek(0, SeekOrigin.Begin); - stream.CopyTo(ms); - if (!isWindows11_OrGreater) - { - //In Win10 there is transparent borders for some apps - using Bitmap bmp = new(ms); - if (IsPixelAlpha(bmp, 0, 0)) - { - return CropImage(bmp, 34, 1, 233, 233); - } - } - byte[] array = ms.ToArray(); - return Convert.ToBase64String(array); - } - - private static string CropImage(Bitmap bmp, int x, int y, int width, int height) - { - Rectangle rect = new(x, y, width, height); - - using Bitmap croppedBitmap = new(rect.Width, rect.Height, bmp.PixelFormat); - - Graphics gfx = Graphics.FromImage(croppedBitmap); - gfx.DrawImage(bmp, 0, 0, rect, GraphicsUnit.Pixel); - - using MemoryStream ms = new(); - croppedBitmap.Save(ms, ImageFormat.Png); - byte[] byteImage = ms.ToArray(); - return Convert.ToBase64String(byteImage); - } - - private static bool IsPixelAlpha(Bitmap bmp, int x, int y) - { - return bmp.GetPixel(x, y).A == 0; - } } } \ No newline at end of file diff --git a/src/Project/Sucrose.Backgroundog/Manage/Internal.cs b/src/Project/Sucrose.Backgroundog/Manage/Internal.cs index 6c0032fb2..9af0d622d 100644 --- a/src/Project/Sucrose.Backgroundog/Manage/Internal.cs +++ b/src/Project/Sucrose.Backgroundog/Manage/Internal.cs @@ -32,6 +32,8 @@ internal static class Internal public static Timer InitializeTimer = null; + public static bool MotherboardManagement = true; + public static readonly object LockObject = new(); public static NowPlayingSession PlayingSession = null; @@ -168,7 +170,10 @@ internal static class Internal public static SBSDMDS MotherboardData = new() { - Name = string.Empty + Name = string.Empty, + Product = string.Empty, + Version = string.Empty, + Manufacturer = string.Empty }; } } \ No newline at end of file diff --git a/src/Project/Sucrose.Backgroundog/Manage/Manager.cs b/src/Project/Sucrose.Backgroundog/Manage/Manager.cs index 1ba44919a..2382bd956 100644 --- a/src/Project/Sucrose.Backgroundog/Manage/Manager.cs +++ b/src/Project/Sucrose.Backgroundog/Manage/Manager.cs @@ -4,6 +4,8 @@ namespace Sucrose.Backgroundog.Manage { internal static class Manager { + public static bool Windows11_OrGreater => Environment.OSVersion.Version.Build >= 22000; + public static Mutex Mutex => new(true, SMR.BackgroundogMutex); } } \ No newline at end of file diff --git a/src/Project/Sucrose.Backgroundog/Struct/Data.cs b/src/Project/Sucrose.Backgroundog/Struct/Data.cs index b9456d99e..ab2446b93 100644 --- a/src/Project/Sucrose.Backgroundog/Struct/Data.cs +++ b/src/Project/Sucrose.Backgroundog/Struct/Data.cs @@ -394,5 +394,17 @@ public struct MotherboardStruct /// /// public string Name; + /// + /// + /// + public string Product; + /// + /// + /// + public string Version; + /// + /// + /// + public string Manufacturer; } } \ No newline at end of file