mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Created first working version of an ambilight (WIP)
This commit is contained in:
parent
53e8e9c44e
commit
fc723d8e38
@ -250,6 +250,14 @@
|
|||||||
<HintPath>..\packages\Process.NET.1.0.5\lib\Process.NET.dll</HintPath>
|
<HintPath>..\packages\Process.NET.1.0.5\lib\Process.NET.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="SharpDX, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="SharpDX.Direct3D9, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
|
||||||
|
<HintPath>..\packages\SharpDX.Direct3D9.3.1.1\lib\net45\SharpDX.Direct3D9.dll</HintPath>
|
||||||
|
<Private>True</Private>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="Splat, Version=1.6.2.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
|
<HintPath>..\packages\Splat.1.6.2\lib\Net45\Splat.dll</HintPath>
|
||||||
<Private>True</Private>
|
<Private>True</Private>
|
||||||
@ -392,6 +400,18 @@
|
|||||||
<Compile Include="Profiles\Layers\Animations\NoneAnimation.cs" />
|
<Compile Include="Profiles\Layers\Animations\NoneAnimation.cs" />
|
||||||
<Compile Include="Profiles\Layers\Models\EventPropertiesModel.cs" />
|
<Compile Include="Profiles\Layers\Models\EventPropertiesModel.cs" />
|
||||||
<Compile Include="Profiles\Layers\Models\KeyboardEventPropertiesModel.cs" />
|
<Compile Include="Profiles\Layers\Models\KeyboardEventPropertiesModel.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbienceCreator\AmbienceCreatorMirror.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbienceCreator\AvgColor.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbienceCreator\IAmbienceCreator.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesModel.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesView.xaml.cs">
|
||||||
|
<DependentUpon>AmbientLightPropertiesView.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesViewModel.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightType.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\DX9ScreenCapture.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\IScreenCapture.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\ScreenCaptureManager.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesModel.cs" />
|
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesModel.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml.cs">
|
<Compile Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml.cs">
|
||||||
<DependentUpon>AudioPropertiesView.xaml</DependentUpon>
|
<DependentUpon>AudioPropertiesView.xaml</DependentUpon>
|
||||||
@ -746,6 +766,10 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesView.xaml">
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
</Page>
|
||||||
<Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml">
|
<Page Include="Profiles\Layers\Types\Audio\AudioPropertiesView.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using Artemis.Profiles.Layers.Animations;
|
using Artemis.Profiles.Layers.Animations;
|
||||||
using Artemis.Profiles.Layers.Conditions;
|
using Artemis.Profiles.Layers.Conditions;
|
||||||
using Artemis.Profiles.Layers.Interfaces;
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
|
using Artemis.Profiles.Layers.Types.AmbientLight;
|
||||||
using Artemis.Profiles.Layers.Types.Audio;
|
using Artemis.Profiles.Layers.Types.Audio;
|
||||||
using Artemis.Profiles.Layers.Types.Folder;
|
using Artemis.Profiles.Layers.Types.Folder;
|
||||||
using Artemis.Profiles.Layers.Types.Generic;
|
using Artemis.Profiles.Layers.Types.Generic;
|
||||||
@ -41,10 +42,12 @@ namespace Artemis.InjectionModules
|
|||||||
Bind<ILayerType>().To<GenericType>();
|
Bind<ILayerType>().To<GenericType>();
|
||||||
Bind<ILayerType>().To<KeyPressType>();
|
Bind<ILayerType>().To<KeyPressType>();
|
||||||
Bind<ILayerType>().To<AudioType>();
|
Bind<ILayerType>().To<AudioType>();
|
||||||
|
Bind<ILayerType>().To<AmbientLightType>();
|
||||||
|
|
||||||
// Bind some Layer Types to self as well in order to allow JSON.NET injection
|
// Bind some Layer Types to self as well in order to allow JSON.NET injection
|
||||||
Bind<KeyPressType>().ToSelf();
|
Bind<KeyPressType>().ToSelf();
|
||||||
Bind<AudioType>().ToSelf();
|
Bind<AudioType>().ToSelf();
|
||||||
|
Bind<AmbientLightType>().ToSelf();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
|
||||||
|
{
|
||||||
|
public class AmbienceCreatorMirror : IAmbienceCreator
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public byte[] GetAmbience(byte[] data, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight)
|
||||||
|
{
|
||||||
|
int heightPixelCount = (int)Math.Round(sourceHeight * 0.1);
|
||||||
|
int sourceHeightOffset = sourceHeight - heightPixelCount;
|
||||||
|
|
||||||
|
AvgColor[] avgData = new AvgColor[targetWidth * targetHeight];
|
||||||
|
double widthPixels = (sourceWidth / (double)targetWidth);
|
||||||
|
double heightPixels = (heightPixelCount / (double)targetHeight);
|
||||||
|
int targetHeightIndex = 0;
|
||||||
|
double heightCounter = heightPixels;
|
||||||
|
|
||||||
|
for (int y = 0; y < heightPixelCount; y += 2)
|
||||||
|
{
|
||||||
|
if (y >= heightCounter)
|
||||||
|
{
|
||||||
|
heightCounter += heightPixels;
|
||||||
|
targetHeightIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int targetWidthIndex = 0;
|
||||||
|
double widthCounter = widthPixels;
|
||||||
|
|
||||||
|
for (int x = 0; x < sourceWidth; x += 2)
|
||||||
|
{
|
||||||
|
if (x >= widthCounter)
|
||||||
|
{
|
||||||
|
widthCounter += widthPixels;
|
||||||
|
targetWidthIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int newOffset = (targetHeightIndex * targetWidth) + targetWidthIndex;
|
||||||
|
int offset = ((((sourceHeightOffset + y) * sourceWidth) + x) * 4);
|
||||||
|
|
||||||
|
if (avgData[newOffset] == null)
|
||||||
|
avgData[newOffset] = new AvgColor();
|
||||||
|
|
||||||
|
AvgColor avgDataObject = avgData[newOffset];
|
||||||
|
|
||||||
|
avgDataObject.AddB(data[offset]);
|
||||||
|
avgDataObject.AddG(data[offset + 1]);
|
||||||
|
avgDataObject.AddR(data[offset + 2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
avgData = FlipVertical(avgData, targetWidth);
|
||||||
|
return ToByteArray(avgData, targetWidth, targetHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] ToByteArray(AvgColor[] colors, int width, int height)
|
||||||
|
{
|
||||||
|
byte[] newData = new byte[width * height * 3];
|
||||||
|
int counter = 0;
|
||||||
|
foreach (AvgColor color in colors)
|
||||||
|
{
|
||||||
|
newData[counter++] = color.B;
|
||||||
|
newData[counter++] = color.G;
|
||||||
|
newData[counter++] = color.R;
|
||||||
|
}
|
||||||
|
|
||||||
|
return newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private T[] FlipVertical<T>(T[] data, int width)
|
||||||
|
{
|
||||||
|
T[] flipped = new T[data.Length];
|
||||||
|
for (int i = 0, j = data.Length - width; i < data.Length; i += width, j -= width)
|
||||||
|
for (int k = 0; k < width; ++k)
|
||||||
|
flipped[i + k] = data[j + k];
|
||||||
|
|
||||||
|
return flipped;
|
||||||
|
}
|
||||||
|
|
||||||
|
private T[] FlipHorizontal<T>(T[] data, int width)
|
||||||
|
{
|
||||||
|
T[] flipped = new T[data.Length];
|
||||||
|
for (int i = 0; i < data.Length; i += width)
|
||||||
|
for (int j = 0, k = width - 1; j < width; ++j, --k)
|
||||||
|
flipped[i + j] = data[i + k];
|
||||||
|
|
||||||
|
return flipped;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
|
||||||
|
{
|
||||||
|
public class AvgColor
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private int _rCount = 0;
|
||||||
|
private int _r = 0;
|
||||||
|
private int _gCount = 0;
|
||||||
|
private int _g = 0;
|
||||||
|
private int _bCount = 0;
|
||||||
|
private int _b = 0;
|
||||||
|
|
||||||
|
public byte R => (byte)(_r / _rCount);
|
||||||
|
public byte G => (byte)(_g / _gCount);
|
||||||
|
public byte B => (byte)(_b / _bCount);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public void AddR(byte r)
|
||||||
|
{
|
||||||
|
_r += r;
|
||||||
|
_rCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddG(byte g)
|
||||||
|
{
|
||||||
|
_g += g;
|
||||||
|
_gCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddB(byte b)
|
||||||
|
{
|
||||||
|
_b += b;
|
||||||
|
_bCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
|
||||||
|
{
|
||||||
|
public interface IAmbienceCreator
|
||||||
|
{
|
||||||
|
byte[] GetAmbience(byte[] data, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
using System.Windows.Media;
|
||||||
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
||||||
|
{
|
||||||
|
public class AmbientLightPropertiesModel : LayerPropertiesModel
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
//HACK DarthAffe 30.10.2016: The 'normal' Brush-Property destoys the profile since Drawing-Brushes cannot be deserialized.
|
||||||
|
[JsonIgnore]
|
||||||
|
public Brush AmbientLightBrush { get; set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public AmbientLightPropertiesModel(LayerPropertiesModel properties)
|
||||||
|
: base(properties)
|
||||||
|
{
|
||||||
|
Brush = new SolidColorBrush(Color.FromRgb(0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
<UserControl x:Class="Artemis.Profiles.Layers.Types.AmbientLight.AmbientLightPropertiesView"
|
||||||
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
|
mc:Ignorable="d"
|
||||||
|
d:DesignHeight="600" d:DesignWidth="500">
|
||||||
|
<Grid>
|
||||||
|
<TextBlock Text="TODO - Add some Properties" />
|
||||||
|
</Grid>
|
||||||
|
</UserControl>
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
using System.Windows.Controls;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
||||||
|
{
|
||||||
|
public partial class AmbientLightPropertiesView : UserControl
|
||||||
|
{
|
||||||
|
public AmbientLightPropertiesView()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
||||||
|
{
|
||||||
|
public class AmbientLightPropertiesViewModel : LayerPropertiesViewModel
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public AmbientLightPropertiesViewModel(LayerEditorViewModel editorVm)
|
||||||
|
: base(editorVm)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public override void ApplyProperties()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using System.Windows.Media.Imaging;
|
||||||
|
using Artemis.Models.Interfaces;
|
||||||
|
using Artemis.Profiles.Layers.Abstract;
|
||||||
|
using Artemis.Profiles.Layers.Interfaces;
|
||||||
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
using Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator;
|
||||||
|
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
|
||||||
|
using Artemis.ViewModels.Profiles;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
||||||
|
{
|
||||||
|
public class AmbientLightType : ILayerType
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
public string Name => "Keyboard - Ambient Light";
|
||||||
|
public bool ShowInEdtor => true;
|
||||||
|
public DrawType DrawType => DrawType.Keyboard;
|
||||||
|
|
||||||
|
private IAmbienceCreator _lastAmbienceCreator;
|
||||||
|
private byte[] _lastData;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public LayerPropertiesViewModel SetupViewModel(LayerEditorViewModel layerEditorViewModel,
|
||||||
|
LayerPropertiesViewModel layerPropertiesViewModel)
|
||||||
|
{
|
||||||
|
if (layerPropertiesViewModel is AmbientLightPropertiesViewModel)
|
||||||
|
return layerPropertiesViewModel;
|
||||||
|
return new AmbientLightPropertiesViewModel(layerEditorViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetupProperties(LayerModel layerModel)
|
||||||
|
{
|
||||||
|
if (layerModel.Properties is AmbientLightPropertiesModel)
|
||||||
|
return;
|
||||||
|
|
||||||
|
layerModel.Properties = new AmbientLightPropertiesModel(layerModel.Properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(LayerModel layerModel, IDataModel dataModel, bool isPreview = false)
|
||||||
|
{
|
||||||
|
int width = (int)Math.Round(layerModel.Properties.Width);
|
||||||
|
int height = (int)Math.Round(layerModel.Properties.Height);
|
||||||
|
|
||||||
|
byte[] data = ScreenCaptureManager.GetLastScreenCapture();
|
||||||
|
_lastData = GetAmbienceCreator().GetAmbience(data, ScreenCaptureManager.LastCaptureWidth, ScreenCaptureManager.LastCaptureHeight, width, height);
|
||||||
|
|
||||||
|
int stride = (width * ScreenCaptureManager.LastCapturePixelFormat.BitsPerPixel + 7) / 8;
|
||||||
|
((AmbientLightPropertiesModel)layerModel.Properties).AmbientLightBrush = new DrawingBrush(
|
||||||
|
new ImageDrawing(BitmapSource.Create(width, height, 96, 96, ScreenCaptureManager.LastCapturePixelFormat, null, _lastData, stride), new Rect(0, 0, width, height)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Draw(LayerModel layer, DrawingContext c)
|
||||||
|
{
|
||||||
|
Rect rect = new Rect(layer.Properties.X * 4,
|
||||||
|
layer.Properties.Y * 4,
|
||||||
|
layer.Properties.Width * 4,
|
||||||
|
layer.Properties.Height * 4);
|
||||||
|
|
||||||
|
c.DrawRectangle(((AmbientLightPropertiesModel)layer.Properties).AmbientLightBrush, null, rect);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImageSource DrawThumbnail(LayerModel layer)
|
||||||
|
{
|
||||||
|
//TODO DarthAffe 30.10.2016: Add a real thumbnail
|
||||||
|
Rect thumbnailRect = new Rect(0, 0, 18, 18);
|
||||||
|
DrawingVisual visual = new DrawingVisual();
|
||||||
|
using (DrawingContext c = visual.RenderOpen())
|
||||||
|
c.DrawRectangle(new SolidColorBrush(Colors.Magenta), new Pen(new SolidColorBrush(Colors.DarkMagenta), 2), thumbnailRect);
|
||||||
|
|
||||||
|
return new DrawingImage(visual.Drawing);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IAmbienceCreator GetAmbienceCreator()
|
||||||
|
{
|
||||||
|
//TODO DarthAffe 30.10.2016: Create from settings
|
||||||
|
return _lastAmbienceCreator ?? (_lastAmbienceCreator = new AmbienceCreatorMirror());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,64 @@
|
|||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Windows.Forms;
|
||||||
|
using System.Windows.Media;
|
||||||
|
using SharpDX;
|
||||||
|
using SharpDX.Direct3D9;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
|
||||||
|
{
|
||||||
|
public class DX9ScreenCapture : IScreenCapture
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
private Device _device;
|
||||||
|
|
||||||
|
public int Width { get; }
|
||||||
|
public int Height { get; }
|
||||||
|
public PixelFormat PixelFormat => PixelFormats.Bgr24;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
public DX9ScreenCapture()
|
||||||
|
{
|
||||||
|
Width = Screen.PrimaryScreen.Bounds.Width;
|
||||||
|
Height = Screen.PrimaryScreen.Bounds.Height;
|
||||||
|
|
||||||
|
PresentParameters presentParams = new PresentParameters(Width, Height)
|
||||||
|
{
|
||||||
|
Windowed = true,
|
||||||
|
SwapEffect = SwapEffect.Discard
|
||||||
|
};
|
||||||
|
|
||||||
|
_device = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.SoftwareVertexProcessing, presentParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
public byte[] CaptureScreen()
|
||||||
|
{
|
||||||
|
using (Surface s = Surface.CreateOffscreenPlain(_device, Width, Height, Format.A8R8G8B8, Pool.Scratch))
|
||||||
|
{
|
||||||
|
_device.GetFrontBufferData(0, s);
|
||||||
|
DataRectangle dr = s.LockRectangle(LockFlags.None);
|
||||||
|
|
||||||
|
byte[] buffer = new byte[Width * Height * 4];
|
||||||
|
Marshal.Copy(dr.DataPointer, buffer, 0, buffer.Length);
|
||||||
|
|
||||||
|
s.UnlockRectangle();
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
_device?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
using System;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
|
||||||
|
{
|
||||||
|
public interface IScreenCapture : IDisposable
|
||||||
|
{
|
||||||
|
int Width { get; }
|
||||||
|
int Height { get; }
|
||||||
|
PixelFormat PixelFormat { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// As Pixel-Data BGRA
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The Pixel-Data</returns>
|
||||||
|
byte[] CaptureScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,93 @@
|
|||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Windows.Media;
|
||||||
|
|
||||||
|
namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
|
||||||
|
{
|
||||||
|
public static class ScreenCaptureManager
|
||||||
|
{
|
||||||
|
#region Properties & Fields
|
||||||
|
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
|
private static readonly IScreenCapture _screenCapture;
|
||||||
|
|
||||||
|
private static Thread _worker;
|
||||||
|
private static DateTime _lastCaptureAccess;
|
||||||
|
private static volatile byte[] _lastScreenCapture;
|
||||||
|
private static volatile bool _isRunning = false;
|
||||||
|
|
||||||
|
public static double StandByTime { get; set; } = 3;
|
||||||
|
public static double UpdateRate { get; set; } = 1f / 20f; // DarthAffe 29.10.2016: I think 20 FPS should be enough as default
|
||||||
|
|
||||||
|
public static int LastCaptureWidth { get; private set; }
|
||||||
|
public static int LastCaptureHeight { get; private set; }
|
||||||
|
public static PixelFormat LastCapturePixelFormat { get; private set; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
static ScreenCaptureManager()
|
||||||
|
{
|
||||||
|
_screenCapture = new DX9ScreenCapture();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
private static void Update()
|
||||||
|
{
|
||||||
|
while ((DateTime.Now - _lastCaptureAccess).TotalSeconds < StandByTime)
|
||||||
|
{
|
||||||
|
DateTime lastCapture = DateTime.Now;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CaptureScreen();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("[CaptureLoop]: " + ex.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sleep = (int)((UpdateRate - (DateTime.Now - lastCapture).TotalSeconds) * 1000);
|
||||||
|
if (sleep > 0)
|
||||||
|
Thread.Sleep(sleep);
|
||||||
|
}
|
||||||
|
|
||||||
|
_isRunning = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CaptureScreen()
|
||||||
|
{
|
||||||
|
_lastScreenCapture = _screenCapture.CaptureScreen();
|
||||||
|
LastCaptureWidth = _screenCapture.Width;
|
||||||
|
LastCaptureHeight = _screenCapture.Height;
|
||||||
|
LastCapturePixelFormat = _screenCapture.PixelFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StartLoop()
|
||||||
|
{
|
||||||
|
if (_isRunning) return;
|
||||||
|
|
||||||
|
_isRunning = true;
|
||||||
|
_worker = new Thread(Update);
|
||||||
|
_worker.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] GetLastScreenCapture()
|
||||||
|
{
|
||||||
|
_lastCaptureAccess = DateTime.Now;
|
||||||
|
if (!_isRunning)
|
||||||
|
{
|
||||||
|
// DarthAffe 29.10.2016: Make sure, that _lastScreenCapture is newer returned without data.
|
||||||
|
CaptureScreen();
|
||||||
|
StartLoop();
|
||||||
|
}
|
||||||
|
return _lastScreenCapture;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -24,6 +24,8 @@
|
|||||||
<package id="NLog" version="4.3.10" targetFramework="net461" />
|
<package id="NLog" version="4.3.10" targetFramework="net461" />
|
||||||
<package id="NLog.Schema" version="4.3.10" targetFramework="net461" />
|
<package id="NLog.Schema" version="4.3.10" targetFramework="net461" />
|
||||||
<package id="Process.NET" version="1.0.5" targetFramework="net461" />
|
<package id="Process.NET" version="1.0.5" targetFramework="net461" />
|
||||||
|
<package id="SharpDX" version="3.1.1" targetFramework="net461" />
|
||||||
|
<package id="SharpDX.Direct3D9" version="3.1.1" targetFramework="net461" />
|
||||||
<package id="Splat" version="1.6.2" targetFramework="net461" />
|
<package id="Splat" version="1.6.2" targetFramework="net461" />
|
||||||
<package id="SpotifyAPI-NET" version="2.12.0" targetFramework="net461" />
|
<package id="SpotifyAPI-NET" version="2.12.0" targetFramework="net461" />
|
||||||
<package id="squirrel.windows" version="1.4.4" targetFramework="net461" />
|
<package id="squirrel.windows" version="1.4.4" targetFramework="net461" />
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user