diff --git a/CUE.NET.sln b/CUE.NET.sln index d2be7ea..2440aef 100644 --- a/CUE.NET.sln +++ b/CUE.NET.sln @@ -32,6 +32,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AudioAnalyzer", "AudioAnaly EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example_AudioAnalyzer_full", "Examples\AudioAnalyzer\Example_AudioAnalyzer_full\Example_AudioAnalyzer_full.csproj", "{E06B4E1D-9735-4CB4-BC11-9ECDF27A0972}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Ambilight", "Ambilight", "{1ABADCA4-AC96-4E9F-91C5-232EB824D6DE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example_Ambilight_full", "Examples\Ambilight\Example_Ambilight_full\Example_Ambilight_full.csproj", "{6D7BAF89-A705-4FFA-A3A2-AF93EC3A909C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -50,6 +54,10 @@ Global {E06B4E1D-9735-4CB4-BC11-9ECDF27A0972}.Debug|Any CPU.Build.0 = Debug|Any CPU {E06B4E1D-9735-4CB4-BC11-9ECDF27A0972}.Release|Any CPU.ActiveCfg = Release|Any CPU {E06B4E1D-9735-4CB4-BC11-9ECDF27A0972}.Release|Any CPU.Build.0 = Release|Any CPU + {6D7BAF89-A705-4FFA-A3A2-AF93EC3A909C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6D7BAF89-A705-4FFA-A3A2-AF93EC3A909C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6D7BAF89-A705-4FFA-A3A2-AF93EC3A909C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6D7BAF89-A705-4FFA-A3A2-AF93EC3A909C}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -61,5 +69,7 @@ Global {2F99124B-FAED-432D-B797-45566D373411} = {D69EF6D8-68FF-4C56-B5CB-253971B1DF91} {BE16A0BF-6794-4718-AF27-F2A50078D880} = {1F52DDC9-E9D0-4A7B-8E78-930528203EE6} {E06B4E1D-9735-4CB4-BC11-9ECDF27A0972} = {BE16A0BF-6794-4718-AF27-F2A50078D880} + {1ABADCA4-AC96-4E9F-91C5-232EB824D6DE} = {1F52DDC9-E9D0-4A7B-8E78-930528203EE6} + {6D7BAF89-A705-4FFA-A3A2-AF93EC3A909C} = {1ABADCA4-AC96-4E9F-91C5-232EB824D6DE} EndGlobalSection EndGlobal diff --git a/Examples/Ambilight/Example_Ambilight_full/AbstractAmbilightBrush.cs b/Examples/Ambilight/Example_Ambilight_full/AbstractAmbilightBrush.cs new file mode 100644 index 0000000..8e369df --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/AbstractAmbilightBrush.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using CUE.NET.Brushes; +using Example_Ambilight_full.TakeAsIs; +using Example_Ambilight_full.TakeAsIs.Model; +using Example_Ambilight_full.TakeAsIs.Model.Extensions; +using Example_Ambilight_full.TakeAsIs.ScreenCapturing; + +namespace Example_Ambilight_full +{ + public abstract class AbstractAmbilightBrush : AbstractBrush + { + #region Properties & Fields + + protected readonly IScreenCapture ScreenCapture; + protected readonly AmbilightSettings Settings; + + protected byte[] ScreenPixelData; + + protected int SourceWidth; + protected int SourceHeight; + + protected int OffsetLeft; + protected int OffsetRight; + protected int OffsetTop; + protected int OffsetBottom; + + protected int EffectiveSourceWidth; + protected int EffectiveSourceHeight; + + protected int Increment; + protected float KeyWidthProportion; + protected float KeyHeightProportion; + + #endregion + + #region Constructors + + public AbstractAmbilightBrush(IScreenCapture screenCapture, AmbilightSettings settings) + { + this.ScreenCapture = screenCapture; + this.Settings = settings; + } + + #endregion + + #region Methods + + public override void PerformRender(RectangleF rectangle, IEnumerable renderTargets) + { + ScreenPixelData = ScreenCapture.CaptureScreen(); + + SourceWidth = ScreenCapture.Width; + SourceHeight = ScreenCapture.Height; + + OffsetLeft = Settings.OffsetLeft + (Settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Left) + ? ScreenPixelData.DetectBlackBarLeft(SourceWidth, SourceHeight, Settings.OffsetLeft, Settings.OffsetRight, Settings.OffsetTop, Settings.OffsetBottom) + : 0); + OffsetRight = Settings.OffsetRight + (Settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Right) + ? ScreenPixelData.DetectBlackBarRight(SourceWidth, SourceHeight, Settings.OffsetLeft, Settings.OffsetRight, Settings.OffsetTop, Settings.OffsetBottom) + : 0); + OffsetTop = Settings.OffsetTop + (Settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Top) + ? ScreenPixelData.DetectBlackBarTop(SourceWidth, SourceHeight, Settings.OffsetLeft, Settings.OffsetRight, Settings.OffsetTop, Settings.OffsetBottom) + : 0); + OffsetBottom = Settings.OffsetBottom + (Settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Bottom) + ? ScreenPixelData.DetectBlackBarBottom(SourceWidth, SourceHeight, Settings.OffsetLeft, Settings.OffsetRight, Settings.OffsetTop, Settings.OffsetBottom) + : 0); + + EffectiveSourceWidth = SourceWidth - OffsetLeft - OffsetRight; + EffectiveSourceHeight = (int)Math.Round((SourceHeight - OffsetTop - OffsetBottom) * (Settings.MirroredAmount / 100.0)); + + Increment = Math.Max(1, Math.Min(20, Settings.Downsampling)); + + KeyWidthProportion = EffectiveSourceWidth / rectangle.Width; + KeyHeightProportion = EffectiveSourceHeight / rectangle.Height; + + Opacity = Settings.SmoothMode == SmoothMode.Low ? 0.25f : (Settings.SmoothMode == SmoothMode.Medium ? 0.075f : (Settings.SmoothMode == SmoothMode.High ? 0.025f : 1f /*None*/)); + + base.PerformRender(rectangle, renderTargets); + } + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/Ambilight.cs b/Examples/Ambilight/Example_Ambilight_full/Ambilight.cs new file mode 100644 index 0000000..9cdf656 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/Ambilight.cs @@ -0,0 +1,69 @@ +using System; +using System.Drawing; +using CUE.NET; +using CUE.NET.Brushes; +using CUE.NET.Devices.Generic.Enums; +using Example_Ambilight_full.TakeAsIs; +using Example_Ambilight_full.TakeAsIs.Model; +using Example_Ambilight_full.TakeAsIs.ScreenCapturing; + +namespace Example_Ambilight_full +{ + public class Ambilight + { + #region Properties & Fields + + private readonly IScreenCapture _screenCapture; + private readonly AmbilightSettings _settings; + + #endregion + + #region Constructors + + public Ambilight(IScreenCapture screenCapture, AmbilightSettings settings) + { + this._screenCapture = screenCapture; + this._settings = settings; + } + + #endregion + + #region Methods + + public bool Initialize() + { + try + { + CueSDK.Initialize(); + CueSDK.UpdateMode = UpdateMode.Continuous; + CueSDK.UpdateFrequency = 1 / 20f; + + SetAmbilightBrush(); + _settings.AmbienceCreatorTypeChanged += (sender, args) => SetAmbilightBrush(); + } + catch { return false; } + return true; + } + + private void SetAmbilightBrush() + { + IBrush ambilightBrush; + switch (_settings.AmbienceCreatorType) + { + case AmbienceCreatorType.Mirror: + ambilightBrush = new AmbilightMirrorBrush(_screenCapture, _settings); + break; + case AmbienceCreatorType.Extend: + ambilightBrush = new AmbilightExtendBrush(_screenCapture, _settings); + break; + default: + ambilightBrush = new SolidColorBrush(Color.Black); + break; + } + + CueSDK.KeyboardSDK.Brush = ambilightBrush; + } + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/AmbilightExtendBrush.cs b/Examples/Ambilight/Example_Ambilight_full/AmbilightExtendBrush.cs new file mode 100644 index 0000000..f5835da --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/AmbilightExtendBrush.cs @@ -0,0 +1,59 @@ +using System; +using System.Drawing; +using CUE.NET.Brushes; +using CUE.NET.Devices.Generic; +using Example_Ambilight_full.TakeAsIs; +using Example_Ambilight_full.TakeAsIs.Model; +using Example_Ambilight_full.TakeAsIs.ScreenCapturing; + +namespace Example_Ambilight_full +{ + public class AmbilightExtendBrush : AbstractAmbilightBrush + { + #region Constructors + + public AmbilightExtendBrush(IScreenCapture screenCapture, AmbilightSettings settings) + : base(screenCapture, settings) + { } + + #endregion + + #region Methods + + protected override CorsairColor GetColorAtPoint(RectangleF rectangle, BrushRenderTarget renderTarget) + { + //TODO DarthAffe 05.11.2016: The Key-Rectangle is missing in the render-target, I'll fix that with a future version of CUE.NET. Until then we consider the size of each key to be 10x10mm. + float keyWidth = 10; + + int widthPixels = Math.Max(1, (int)(KeyWidthProportion * keyWidth)); + + int r = 0; + int g = 0; + int b = 0; + int counter = 0; + + int widthOffset = Settings.FlipMode.HasFlag(FlipMode.Horizontal) + ? (int)((SourceWidth - OffsetRight) - (KeyWidthProportion * (renderTarget.Point.X + (keyWidth / 2f)))) + : (int)(OffsetLeft + (KeyWidthProportion * (renderTarget.Point.X - (keyWidth / 2f)))); + int heightOffset = SourceHeight - OffsetBottom - EffectiveSourceHeight; // DarthAffe 05.11.2016: Vertical flipping doesn't mather in Extend-Mode + + // DarthAffe 06.11.2016: Validate offsets - rounding errors might cause problems (heightOffset is safe calculated -> no need to validate) + widthOffset = Math.Max(0, Math.Min(SourceWidth - widthPixels, widthOffset)); + + for (int y = 0; y < EffectiveSourceHeight; y += Increment) + for (int x = 0; x < widthPixels; x += Increment) + { + int offset = ((((heightOffset + y) * SourceWidth) + widthOffset + x) * 4); + + b += ScreenPixelData[offset]; + g += ScreenPixelData[offset + 1]; + r += ScreenPixelData[offset + 2]; + counter++; + } + + return new CorsairColor((byte)(r / counter), (byte)(g / counter), (byte)(b / counter)); + } + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/AmbilightMirrorBrush.cs b/Examples/Ambilight/Example_Ambilight_full/AmbilightMirrorBrush.cs new file mode 100644 index 0000000..4f2e72e --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/AmbilightMirrorBrush.cs @@ -0,0 +1,64 @@ +using System; +using System.Drawing; +using CUE.NET.Brushes; +using CUE.NET.Devices.Generic; +using Example_Ambilight_full.TakeAsIs; +using Example_Ambilight_full.TakeAsIs.Model; +using Example_Ambilight_full.TakeAsIs.ScreenCapturing; + +namespace Example_Ambilight_full +{ + public class AmbilightMirrorBrush : AbstractAmbilightBrush + { + #region Constructors + + public AmbilightMirrorBrush(IScreenCapture screenCapture, AmbilightSettings settings) + : base(screenCapture, settings) + { } + + #endregion + + #region Methods + + protected override CorsairColor GetColorAtPoint(RectangleF rectangle, BrushRenderTarget renderTarget) + { + //TODO DarthAffe 05.11.2016: The Key-Rectangle is missing in the render-target, I'll fix that with a future version of CUE.NET. Until then we consider the size of each key to be 10x10mm. + float keyWidth = 10; + float keyHeight = 10; + + int widthPixels = Math.Max(1, (int)(KeyWidthProportion * keyWidth)); + int heightPixels = Math.Max(1, (int)(KeyHeightProportion * keyHeight)); + + int r = 0; + int g = 0; + int b = 0; + int counter = 0; + + int widthOffset = Settings.FlipMode.HasFlag(FlipMode.Horizontal) + ? ((SourceWidth - OffsetRight) - (int)(KeyWidthProportion * (renderTarget.Point.X + (keyWidth / 2f)))) + : (OffsetLeft + (int)(KeyWidthProportion * (renderTarget.Point.X - (keyWidth / 2f)))); + int heightOffset = Settings.FlipMode.HasFlag(FlipMode.Vertical) + ? ((SourceHeight - OffsetBottom) - (int)(KeyHeightProportion * (renderTarget.Point.Y + (keyHeight / 2f)))) + : ((SourceHeight - OffsetBottom - EffectiveSourceHeight) + (int)(KeyHeightProportion * (renderTarget.Point.Y - (keyHeight / 2f)))); + + // DarthAffe 06.11.2016: Validate offsets - rounding errors might cause problems + widthOffset = Math.Max(0, Math.Min(SourceWidth - widthPixels, widthOffset)); + heightOffset = Math.Max(0, Math.Min(EffectiveSourceHeight - heightPixels, heightOffset)); + + for (int y = 0; y < heightPixels; y += Increment) + for (int x = 0; x < widthPixels; x += Increment) + { + int offset = ((((heightOffset + y) * SourceWidth) + widthOffset + x) * 4); + + b += ScreenPixelData[offset]; + g += ScreenPixelData[offset + 1]; + r += ScreenPixelData[offset + 2]; + counter++; + } + + return new CorsairColor((byte)(r / counter), (byte)(g / counter), (byte)(b / counter)); + } + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/App.config b/Examples/Ambilight/Example_Ambilight_full/App.config new file mode 100644 index 0000000..d1428ad --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/App.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/Examples/Ambilight/Example_Ambilight_full/App.xaml b/Examples/Ambilight/Example_Ambilight_full/App.xaml new file mode 100644 index 0000000..c34c4d0 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/App.xaml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/Examples/Ambilight/Example_Ambilight_full/App.xaml.cs b/Examples/Ambilight/Example_Ambilight_full/App.xaml.cs new file mode 100644 index 0000000..459c07e --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/App.xaml.cs @@ -0,0 +1,67 @@ +using System; +using System.Windows; +using Example_Ambilight_full.TakeAsIs; +using Example_Ambilight_full.TakeAsIs.Helper; +using Example_Ambilight_full.TakeAsIs.ScreenCapturing; +using Example_Ambilight_full.TakeAsIs.UI; +using Hardcodet.Wpf.TaskbarNotification; + +namespace Example_Ambilight_full +{ + public partial class App : Application + { + #region Constants + + private const string PATH_SETTINGS = "Settings.xaml"; + + #endregion + + #region Properties & Fields + + private TaskbarIcon _taskBar; + private AmbilightSettings _settings; + private Ambilight _ambilight; + + #endregion + + #region Methods + + protected override void OnStartup(StartupEventArgs e) + { + base.OnStartup(e); + + try + { + _settings = SerializationHelper.LoadObjectFromFile(PATH_SETTINGS) ?? + new AmbilightSettings(); + IScreenCapture screenCapture = new DX9ScreenCapture(); + + // DarthAffe 05.11.2016: This could be done way cleaner ... + _taskBar = FindResource("Taskbar") as TaskbarIcon; + FrameworkElement configView = _taskBar?.TrayPopup as ConfigView; + if (configView == null) + Shutdown(); + else + configView.DataContext = new ConfigViewModel(_settings); + + _ambilight = new Ambilight(screenCapture, _settings); + if (!_ambilight.Initialize()) + throw new ApplicationException(); + } + catch + { + MessageBox.Show("An error occured while starting the Keyboard-Ambilight.\r\nPlease double check if CUE is running and 'Enable SDK' is checked.", "Can't start Keyboard-Ambilight"); + Shutdown(); + } + } + + protected override void OnExit(ExitEventArgs e) + { + base.OnExit(e); + + SerializationHelper.SaveObjectToFile(_settings, PATH_SETTINGS); + } + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/Example_Ambilight_full.csproj b/Examples/Ambilight/Example_Ambilight_full/Example_Ambilight_full.csproj new file mode 100644 index 0000000..3e7b809 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/Example_Ambilight_full.csproj @@ -0,0 +1,169 @@ + + + + + Debug + AnyCPU + {6D7BAF89-A705-4FFA-A3A2-AF93EC3A909C} + WinExe + Properties + Example_Ambilight_full + Example_Ambilight_full + v4.5 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + + + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Resources\ambilight.ico + + + + ..\..\..\packages\CUE.NET.1.1.0.2\lib\net45\CUE.NET.dll + True + + + ..\..\..\packages\Hardcodet.NotifyIcon.Wpf.1.0.8\lib\net45\Hardcodet.Wpf.TaskbarNotification.dll + True + + + ..\..\..\packages\MahApps.Metro.1.4.0-ALPHA026\lib\net45\MahApps.Metro.dll + True + + + ..\..\..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll + True + + + ..\..\..\packages\SharpDX.Direct3D9.3.1.1\lib\net45\SharpDX.Direct3D9.dll + True + + + + + + ..\..\..\packages\MahApps.Metro.1.4.0-ALPHA026\lib\net45\System.Windows.Interactivity.dll + True + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + + + + + App.xaml + Code + + + + + + + + + + + + + + + + ConfigView.xaml + + + + Designer + MSBuild:Compile + + + Designer + MSBuild:Compile + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/Examples/Ambilight/Example_Ambilight_full/Properties/AssemblyInfo.cs b/Examples/Ambilight/Example_Ambilight_full/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..08737ed --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/Properties/AssemblyInfo.cs @@ -0,0 +1,53 @@ +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Example_Ambilight_full")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Example_Ambilight_full")] +[assembly: AssemblyCopyright("Copyright © Wyrez 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Examples/Ambilight/Example_Ambilight_full/Properties/Resources.Designer.cs b/Examples/Ambilight/Example_Ambilight_full/Properties/Resources.Designer.cs new file mode 100644 index 0000000..8c2406a --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Example_Ambilight_full.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Example_Ambilight_full.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/Properties/Resources.resx b/Examples/Ambilight/Example_Ambilight_full/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Examples/Ambilight/Example_Ambilight_full/Properties/Settings.Designer.cs b/Examples/Ambilight/Example_Ambilight_full/Properties/Settings.Designer.cs new file mode 100644 index 0000000..9eba845 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Example_Ambilight_full.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "14.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/Properties/Settings.settings b/Examples/Ambilight/Example_Ambilight_full/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Examples/Ambilight/Example_Ambilight_full/Resources/ambilight.ico b/Examples/Ambilight/Example_Ambilight_full/Resources/ambilight.ico new file mode 100644 index 0000000..5c001b6 Binary files /dev/null and b/Examples/Ambilight/Example_Ambilight_full/Resources/ambilight.ico differ diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/AmbilightSettings.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/AmbilightSettings.cs new file mode 100644 index 0000000..d1b8302 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/AmbilightSettings.cs @@ -0,0 +1,45 @@ +using System; +using Example_Ambilight_full.TakeAsIs.Model; + +namespace Example_Ambilight_full.TakeAsIs +{ + public class AmbilightSettings + { + private AmbienceCreatorType _ambienceCreatorType = AmbienceCreatorType.Mirror; + + #region Properties & Fields + + public AmbienceCreatorType AmbienceCreatorType + { + get { return _ambienceCreatorType; } + set + { + if (_ambienceCreatorType != value) + { + _ambienceCreatorType = value; + AmbienceCreatorTypeChanged?.Invoke(this, new EventArgs()); + } + } + } + + public int OffsetLeft { get; set; } = 0; + public int OffsetRight { get; set; } = 0; + public int OffsetTop { get; set; } = 0; + public int OffsetBottom { get; set; } = 0; + + public int Downsampling { get; set; } = 2; + public double MirroredAmount { get; set; } = 10; + + public SmoothMode SmoothMode { get; set; } = SmoothMode.Low; + public BlackBarDetectionMode BlackBarDetectionMode { get; set; } = BlackBarDetectionMode.Bottom; + public FlipMode FlipMode { get; set; } = FlipMode.Vertical; + + #endregion + + #region Events + + public event EventHandler AmbienceCreatorTypeChanged; + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Helper/CheckboxEnumFlagHelper.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Helper/CheckboxEnumFlagHelper.cs new file mode 100644 index 0000000..12e5c59 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Helper/CheckboxEnumFlagHelper.cs @@ -0,0 +1,93 @@ +using System; +using System.Windows; +using System.Windows.Controls; +using Example_Ambilight_full.TakeAsIs.Model.Extensions; + +namespace Example_Ambilight_full.TakeAsIs.Helper +{ + public class CheckboxEnumFlagHelper + { + #region DependencyProperties + // ReSharper disable InconsistentNaming + + public static readonly DependencyProperty FlagsProperty = DependencyProperty.RegisterAttached( + "Flags", typeof(Enum), typeof(CheckboxEnumFlagHelper), new FrameworkPropertyMetadata(default(Enum), FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, FlagsChanged)); + + public static void SetFlags(DependencyObject element, Enum value) + { + element.SetValue(FlagsProperty, value); + } + + public static Enum GetFlags(DependencyObject element) + { + return (Enum)element.GetValue(FlagsProperty); + } + + public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached( + "Value", typeof(Enum), typeof(CheckboxEnumFlagHelper), new PropertyMetadata(default(Enum), ValueChanged)); + + public static void SetValue(DependencyObject element, Enum value) + { + element.SetValue(ValueProperty, value); + } + + public static Enum GetValue(DependencyObject element) + { + return (Enum)element.GetValue(ValueProperty); + } + + // ReSharper restore InconsistentNaming + #endregion + + #region Methods + + private static void FlagsChanged(DependencyObject dependencyObject, + DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) + { + UpdateTarget(dependencyObject as CheckBox, dependencyPropertyChangedEventArgs.NewValue as Enum); + } + + private static void ValueChanged(DependencyObject dependencyObject, + DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs) + { + CheckBox checkbox = dependencyObject as CheckBox; + if (checkbox == null) return; + + checkbox.Checked -= UpdateSource; + checkbox.Unchecked -= UpdateSource; + + if (dependencyPropertyChangedEventArgs.NewValue != null) + { + checkbox.Checked += UpdateSource; + checkbox.Unchecked += UpdateSource; + } + + UpdateTarget(checkbox, GetFlags(checkbox)); + } + + private static void UpdateTarget(CheckBox checkbox, Enum flags) + { + if (checkbox == null) return; + + Enum value = GetValue(checkbox); + checkbox.IsChecked = value != null && (flags?.HasFlag(value) ?? false); + } + + private static void UpdateSource(object sender, RoutedEventArgs routedEventArgs) + { + CheckBox checkbox = sender as CheckBox; + if (checkbox == null) return; + + Enum flags = GetFlags(checkbox); + Enum value = GetValue(checkbox); + if (value == null) return; + + if (checkbox.IsChecked ?? false) + SetFlags(checkbox, flags == null ? value : flags.SetFlag(value, true, flags.GetType())); + else + SetFlags(checkbox, flags?.SetFlag(value, false, flags.GetType())); + } + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Helper/SerializationHelper.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Helper/SerializationHelper.cs new file mode 100644 index 0000000..dcecda3 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Helper/SerializationHelper.cs @@ -0,0 +1,50 @@ +using System.IO; +using System.Xml; +using System.Xml.Serialization; + +namespace Example_Ambilight_full.TakeAsIs.Helper +{ + public static class SerializationHelper + { + public static void SaveObjectToFile(T serializableObject, string path) + { + if (serializableObject == null) return; + + try + { + XmlDocument xmlDocument = new XmlDocument(); + XmlSerializer serializer = new XmlSerializer(serializableObject.GetType()); + using (MemoryStream stream = new MemoryStream()) + { + serializer.Serialize(stream, serializableObject); + stream.Seek(0, SeekOrigin.Begin); + xmlDocument.Load(stream); + xmlDocument.Save(path); + } + } + catch {/* Catch'em all */} + } + + public static T LoadObjectFromFile(string fileName) + { + if (string.IsNullOrEmpty(fileName)) return default(T); + + try + { + XmlDocument xmlDocument = new XmlDocument(); + xmlDocument.Load(fileName); + string xmlString = xmlDocument.OuterXml; + + using (StringReader sr = new StringReader(xmlString)) + { + XmlSerializer serializer = new XmlSerializer(typeof(T)); + using (XmlReader reader = new XmlTextReader(sr)) + return (T)serializer.Deserialize(reader); + } + } + catch {/* Catch'em all */} + + return default(T); + } + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/AmbienceCreatorType.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/AmbienceCreatorType.cs new file mode 100644 index 0000000..005c2b0 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/AmbienceCreatorType.cs @@ -0,0 +1,13 @@ +using System.ComponentModel; + +namespace Example_Ambilight_full.TakeAsIs.Model +{ + public enum AmbienceCreatorType + { + [Description("Mirror")] + Mirror, + + [Description("Extend")] + Extend + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/BlackBarDetectionMode.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/BlackBarDetectionMode.cs new file mode 100644 index 0000000..3c194f7 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/BlackBarDetectionMode.cs @@ -0,0 +1,14 @@ +using System; + +namespace Example_Ambilight_full.TakeAsIs.Model +{ + [Flags] + public enum BlackBarDetectionMode + { + None = 0, + Left = 1 << 0, + Right = 1 << 1, + Top = 1 << 2, + Bottom = 1 << 3, + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/Extensions/EnumExtension.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/Extensions/EnumExtension.cs new file mode 100644 index 0000000..4db6b7d --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/Extensions/EnumExtension.cs @@ -0,0 +1,26 @@ +using System; + +namespace Example_Ambilight_full.TakeAsIs.Model.Extensions +{ + public static class EnumExtension + { + #region Methods + + public static Enum SetFlag(this Enum e, Enum value, bool set, Type t) + { + if (e == null || value == null || t == null) return e; + + int eValue = Convert.ToInt32(e); + int valueValue = Convert.ToInt32(value); + + if (set) + eValue |= valueValue; + else + eValue &= ~valueValue; + + return (Enum)Enum.ToObject(t, eValue); + } + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/Extensions/PixelDataExtension.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/Extensions/PixelDataExtension.cs new file mode 100644 index 0000000..5336633 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/Extensions/PixelDataExtension.cs @@ -0,0 +1,89 @@ +namespace Example_Ambilight_full.TakeAsIs.Model.Extensions +{ + public static class PixelDataExtension + { + #region Methods + + public static int DetectBlackBarLeft(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom) + { + int bottomBorder = height - offsetBottom; + int rightBorder = width - offsetRight; + + int blackBarWidth = 0; + for (int x = rightBorder - 1; x >= offsetLeft; x--) + { + for (int y = offsetTop; y < bottomBorder; y++) + { + int offset = ((y * width) + x) * 4; + if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15) + return blackBarWidth; + } + blackBarWidth++; + } + + return width; + } + + public static int DetectBlackBarRight(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom) + { + int bottomBorder = height - offsetBottom; + int rightBorder = width - offsetRight; + + int blackBarWidth = 0; + for (int x = offsetLeft; x < rightBorder; x++) + { + for (int y = offsetTop; y < bottomBorder; y++) + { + int offset = ((y * width) + x) * 4; + if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15) + return blackBarWidth; + } + blackBarWidth++; + } + + return width; + } + + public static int DetectBlackBarTop(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom) + { + int bottomBorder = height - offsetBottom; + int rightBorder = width - offsetRight; + + int blackBarHeight = 0; + for (int y = offsetTop; y < bottomBorder; y++) + { + for (int x = offsetLeft; x < rightBorder; x++) + { + int offset = ((y * width) + x) * 4; + if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15) + return blackBarHeight; + } + blackBarHeight++; + } + + return height; + } + + public static int DetectBlackBarBottom(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom) + { + int bottomBorder = height - offsetBottom; + int rightBorder = width - offsetRight; + + int blackBarHeight = 0; + for (int y = bottomBorder - 1; y >= offsetTop; y--) + { + for (int x = offsetLeft; x < rightBorder; x++) + { + int offset = ((y * width) + x) * 4; + if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15) + return blackBarHeight; + } + blackBarHeight++; + } + + return height; + } + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/FlipMode.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/FlipMode.cs new file mode 100644 index 0000000..3a1d6e0 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/FlipMode.cs @@ -0,0 +1,12 @@ +using System; + +namespace Example_Ambilight_full.TakeAsIs.Model +{ + [Flags] + public enum FlipMode + { + None = 0, + Vertical = 1 << 0, + Horizontal = 1 << 1 + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/SmoothMode.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/SmoothMode.cs new file mode 100644 index 0000000..45d5884 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/Model/SmoothMode.cs @@ -0,0 +1,19 @@ +using System.ComponentModel; + +namespace Example_Ambilight_full.TakeAsIs.Model +{ + public enum SmoothMode + { + [Description("None")] + None, + + [Description("Low")] + Low, + + [Description("Medium")] + Medium, + + [Description("High")] + High + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/ScreenCapturing/DX9ScreenCapture.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/ScreenCapturing/DX9ScreenCapture.cs new file mode 100644 index 0000000..b4cadce --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/ScreenCapturing/DX9ScreenCapture.cs @@ -0,0 +1,64 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows.Media; +using SharpDX; +using SharpDX.Direct3D9; + +namespace Example_Ambilight_full.TakeAsIs.ScreenCapturing +{ + public class DX9ScreenCapture : IScreenCapture + { + #region Properties & Fields + + private Device _device; + private Surface _surface; + private byte[] _buffer; + + public int Width { get; } + public int Height { get; } + public PixelFormat PixelFormat => PixelFormats.Bgr24; + + #endregion + + #region Constructors + + public DX9ScreenCapture() + { + Width = (int)System.Windows.SystemParameters.PrimaryScreenWidth; + Height = (int)System.Windows.SystemParameters.PrimaryScreenHeight; + + PresentParameters presentParams = new PresentParameters(Width, Height) + { + Windowed = true, + SwapEffect = SwapEffect.Discard + }; + + _device = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.SoftwareVertexProcessing, presentParams); + _surface = Surface.CreateOffscreenPlain(_device, Width, Height, Format.A8R8G8B8, Pool.Scratch); + _buffer = new byte[Width * Height * 4]; + } + + #endregion + + #region Methods + + public byte[] CaptureScreen() + { + _device.GetFrontBufferData(0, _surface); + + DataRectangle dr = _surface.LockRectangle(LockFlags.None); + Marshal.Copy(dr.DataPointer, _buffer, 0, _buffer.Length); + _surface.UnlockRectangle(); + + return _buffer; + } + + public void Dispose() + { + _device?.Dispose(); + _surface?.Dispose(); + } + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/ScreenCapturing/IScreenCapture.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/ScreenCapturing/IScreenCapture.cs new file mode 100644 index 0000000..5064abd --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/ScreenCapturing/IScreenCapture.cs @@ -0,0 +1,18 @@ +using System; +using System.Windows.Media; + +namespace Example_Ambilight_full.TakeAsIs.ScreenCapturing +{ + public interface IScreenCapture : IDisposable + { + int Width { get; } + int Height { get; } + PixelFormat PixelFormat { get; } + + /// + /// As Pixel-Data BGRA + /// + /// The Pixel-Data + byte[] CaptureScreen(); + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/UI/ActionCommand.cs b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/UI/ActionCommand.cs new file mode 100644 index 0000000..d521613 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/UI/ActionCommand.cs @@ -0,0 +1,50 @@ +using System; +using System.Windows.Input; + +namespace Example_Ambilight_full.TakeAsIs.UI +{ + public class ActionCommand : ICommand + { + #region Properties & Fields + + private readonly Func _canExecute; + private readonly Action _command; + + #endregion + + #region Constructors + + public ActionCommand(Action command, Func canExecute = null) + { + this._command = command; + this._canExecute = canExecute; + } + + #endregion + + #region Methods + + public bool CanExecute(object parameter) + { + return _canExecute?.Invoke() ?? true; + } + + public void Execute(object parameter) + { + _command?.Invoke(); + } + + public void RaiseCanExecuteChanged() + { + CanExecuteChanged?.Invoke(this, new EventArgs()); + } + + #endregion + + #region Events + + public event EventHandler CanExecuteChanged; + + #endregion + } +} diff --git a/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/UI/ConfigView.xaml b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/UI/ConfigView.xaml new file mode 100644 index 0000000..6005799 --- /dev/null +++ b/Examples/Ambilight/Example_Ambilight_full/TakeAsIs/UI/ConfigView.xaml @@ -0,0 +1,167 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +