diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index 09fb424d3..065d941fb 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -152,8 +152,8 @@ True - ..\packages\CUE.NET.1.0.3\lib\net45\CUE.NET.dll - True + False + ..\..\..\CUE.NET\bin\CUE.NET.dll ..\packages\DeltaCompressionDotNet.1.0.0\lib\net45\DeltaCompressionDotNet.dll @@ -246,6 +246,10 @@ ..\packages\squirrel.windows.1.4.4\lib\Net45\NuGet.Squirrel.dll True + + ..\packages\Process.NET.1.0.1\lib\Process.NET.dll + True + ..\packages\Splat.1.6.2\lib\Net45\Splat.dll True @@ -331,6 +335,7 @@ + @@ -363,7 +368,6 @@ - @@ -385,11 +389,23 @@ UnrealTournamentView.xaml - - - - - + + + + + + + + + + + WoWView.xaml + + + + + + @@ -410,10 +426,14 @@ + + MousematPropertiesView.xaml + + + - @@ -632,6 +652,8 @@ Code + + @@ -713,6 +735,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer @@ -725,6 +751,10 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer @@ -841,6 +871,7 @@ + diff --git a/Artemis/Artemis/DeviceProviders/Corsair/CorsairMousemats.cs b/Artemis/Artemis/DeviceProviders/Corsair/CorsairMousemats.cs new file mode 100644 index 000000000..63c656c24 --- /dev/null +++ b/Artemis/Artemis/DeviceProviders/Corsair/CorsairMousemats.cs @@ -0,0 +1,104 @@ +using System; +using System.Drawing; +using System.Linq; +using System.Threading; +using CUE.NET; +using CUE.NET.Devices.Generic.Enums; +using CUE.NET.Devices.Mousemat.Enums; +using Ninject.Extensions.Logging; + +namespace Artemis.DeviceProviders.Corsair +{ + internal class CorsairMousemats : DeviceProvider + { + public CorsairMousemats(ILogger logger) + { + Logger = logger; + Type = DeviceType.Mousemat; + } + + public ILogger Logger { get; set; } + + public override bool TryEnable() + { + CanUse = CanInitializeSdk(); + if (CanUse && !CueSDK.IsInitialized) + CueSDK.Initialize(); + + Logger.Debug("Attempted to enable Corsair mousemat. CanUse: {0}", CanUse); + + if (CanUse) + CueSDK.MousematSDK.UpdateMode = UpdateMode.Manual; + + return CanUse; + } + + public override void Disable() + { + throw new NotImplementedException("Can only disable a keyboard"); + } + + public override void UpdateDevice(Bitmap bitmap) + { + if (!CanUse || bitmap == null) + return; + if (bitmap.Width != bitmap.Height) + throw new ArgumentException("Bitmap must be a perfect square"); + + var yStep = (double) bitmap.Width/5; + var xStep = (double) bitmap.Width/7; + + // This approach will break if any mousemats with different LED amounts are released, for now it will do. + using (bitmap) + { + var ledIndex = 1; + // Color each LED according to one of the pixels + foreach (var corsairLed in CueSDK.MousematSDK.Leds.OrderBy(l => l.ToString())) + { + Color col; + // Left side + if (ledIndex < 6) + { + col = ledIndex != 5 + ? bitmap.GetPixel(0, (int) (ledIndex*yStep + yStep/2)) + : bitmap.GetPixel(0, (int) (ledIndex*yStep) - 1); + } + // Bottom + else if (ledIndex < 11) + { + // Start at index 2 because the corner belongs to the left side + var zoneIndex = ledIndex - 4; + col = bitmap.GetPixel((int) (zoneIndex*xStep + xStep/2), 0); + } + // Right side + else + { + var zoneIndex = ledIndex - 10; + col = zoneIndex != 5 + ? bitmap.GetPixel(0, bitmap.Height - ((int) (zoneIndex*yStep + yStep/2))) + : bitmap.GetPixel(0, bitmap.Height - ((int) (zoneIndex*yStep) - 1)); + } + + corsairLed.Color = col; + ledIndex++; + } + } + CueSDK.MousematSDK.Update(); + } + + private static bool CanInitializeSdk() + { + // This will skip the check-loop if the SDK is initialized + if (CueSDK.IsInitialized) + return CueSDK.IsSDKAvailable(CorsairDeviceType.Mousemat); + + for (var tries = 0; tries < 9; tries++) + { + if (CueSDK.IsSDKAvailable(CorsairDeviceType.Mousemat)) + return true; + Thread.Sleep(2000); + } + return false; + } + } +} \ No newline at end of file diff --git a/Artemis/Artemis/DeviceProviders/DeviceProvider.cs b/Artemis/Artemis/DeviceProviders/DeviceProvider.cs index 970fa50ad..9399328e0 100644 --- a/Artemis/Artemis/DeviceProviders/DeviceProvider.cs +++ b/Artemis/Artemis/DeviceProviders/DeviceProvider.cs @@ -46,6 +46,7 @@ namespace Artemis.DeviceProviders Keyboard, Mouse, Headset, - Generic + Generic, + Mousemat } } \ No newline at end of file diff --git a/Artemis/Artemis/InjectionModules/DeviceModules.cs b/Artemis/Artemis/InjectionModules/DeviceModules.cs index 32e101b64..86ecdcc59 100644 --- a/Artemis/Artemis/InjectionModules/DeviceModules.cs +++ b/Artemis/Artemis/InjectionModules/DeviceModules.cs @@ -22,6 +22,9 @@ namespace Artemis.InjectionModules // Headsets Bind().To().InSingletonScope(); + // Mousemats + Bind().To().InSingletonScope(); + // Other Bind().To().InSingletonScope(); } diff --git a/Artemis/Artemis/InjectionModules/ProfileModules.cs b/Artemis/Artemis/InjectionModules/ProfileModules.cs index e5e99ee50..a31c40b5d 100644 --- a/Artemis/Artemis/InjectionModules/ProfileModules.cs +++ b/Artemis/Artemis/InjectionModules/ProfileModules.cs @@ -9,6 +9,7 @@ using Artemis.Profiles.Layers.Types.Keyboard; using Artemis.Profiles.Layers.Types.KeyboardGif; using Artemis.Profiles.Layers.Types.KeyPress; using Artemis.Profiles.Layers.Types.Mouse; +using Artemis.Profiles.Layers.Types.Mousemat; using Ninject.Modules; namespace Artemis.InjectionModules @@ -36,6 +37,7 @@ namespace Artemis.InjectionModules Bind().To(); Bind().To(); Bind().To(); + Bind().To(); Bind().To(); Bind().To(); Bind().To(); diff --git a/Artemis/Artemis/Managers/DeviceManager.cs b/Artemis/Artemis/Managers/DeviceManager.cs index 676d3da13..362f5cc11 100644 --- a/Artemis/Artemis/Managers/DeviceManager.cs +++ b/Artemis/Artemis/Managers/DeviceManager.cs @@ -31,6 +31,7 @@ namespace Artemis.Managers MiceProviders = deviceProviders.Where(d => d.Type == DeviceType.Mouse).ToList(); HeadsetProviders = deviceProviders.Where(d => d.Type == DeviceType.Headset).ToList(); GenericProviders = deviceProviders.Where(d => d.Type == DeviceType.Generic).ToList(); + MousematProviders = deviceProviders.Where(d => d.Type == DeviceType.Mousemat).ToList(); _logger.Info("Intialized DeviceManager with {0} device providers", deviceProviders.Count); } @@ -38,6 +39,7 @@ namespace Artemis.Managers public List MiceProviders { get; set; } public List HeadsetProviders { get; set; } public List GenericProviders { get; set; } + public List MousematProviders { get; set; } [Inject] public MetroDialogService DialogService { get; set; } @@ -47,6 +49,8 @@ namespace Artemis.Managers public KeyboardProvider ActiveKeyboard { get; set; } public bool ChangingKeyboard { get; private set; } + + public event EventHandler OnKeyboardChangedEvent; /// @@ -137,6 +141,8 @@ namespace Artemis.Managers headsetProvider.TryEnableAsync(); foreach (var genericProvider in GenericProviders) genericProvider.TryEnableAsync(); + foreach (var mousematProviders in MousematProviders) + mousematProviders.TryEnableAsync(); } /// diff --git a/Artemis/Artemis/Managers/LoopManager.cs b/Artemis/Artemis/Managers/LoopManager.cs index b4c3e40a3..cda3dec0a 100644 --- a/Artemis/Artemis/Managers/LoopManager.cs +++ b/Artemis/Artemis/Managers/LoopManager.cs @@ -132,18 +132,20 @@ namespace Artemis.Managers var mice = _deviceManager.MiceProviders.Where(m => m.CanUse).ToList(); var headsets = _deviceManager.HeadsetProviders.Where(m => m.CanUse).ToList(); var generics = _deviceManager.GenericProviders.Where(m => m.CanUse).ToList(); + var mousemats = _deviceManager.MousematProviders.Where(m => m.CanUse).ToList(); + var keyboardOnly = !mice.Any() && !headsets.Any() && !generics.Any() && !mousemats.Any(); // Setup the frame for this tick using (var frame = new RenderFrame(_deviceManager.ActiveKeyboard)) { if (renderEffect.Initialized) - renderEffect.Render(frame, !mice.Any() && !headsets.Any() && !generics.Any()); + renderEffect.Render(frame, keyboardOnly); // Draw enabled overlays on top of the renderEffect foreach (var overlayModel in _effectManager.EnabledOverlays) { overlayModel.Update(); - overlayModel.RenderOverlay(frame, !mice.Any() && !headsets.Any() && !generics.Any()); + overlayModel.RenderOverlay(frame, keyboardOnly); } // Update the keyboard @@ -156,6 +158,8 @@ namespace Artemis.Managers headset.UpdateDevice(frame.HeadsetBitmap); foreach (var generic in generics) generic.UpdateDevice(frame.GenericBitmap); + foreach (var mousemat in mousemats) + mousemat.UpdateDevice(frame.MousematBitmap); } } } @@ -177,6 +181,9 @@ namespace Artemis.Managers GenericBitmap = new Bitmap(40, 40); GenericBitmap.SetResolution(96, 96); + MousematBitmap = new Bitmap(40, 40); + MousematBitmap.SetResolution(96, 96); + using (var g = Graphics.FromImage(KeyboardBitmap)) g.Clear(Color.Black); using (var g = Graphics.FromImage(MouseBitmap)) @@ -185,12 +192,15 @@ namespace Artemis.Managers g.Clear(Color.Black); using (var g = Graphics.FromImage(GenericBitmap)) g.Clear(Color.Black); + using (var g = Graphics.FromImage(MousematBitmap)) + g.Clear(Color.Black); } public Bitmap KeyboardBitmap { get; set; } public Bitmap MouseBitmap { get; set; } public Bitmap HeadsetBitmap { get; set; } public Bitmap GenericBitmap { get; set; } + public Bitmap MousematBitmap { get; set; } public void Dispose() { diff --git a/Artemis/Artemis/Managers/MainManager.cs b/Artemis/Artemis/Managers/MainManager.cs index b0d8fe146..3c28c588e 100644 --- a/Artemis/Artemis/Managers/MainManager.cs +++ b/Artemis/Artemis/Managers/MainManager.cs @@ -114,7 +114,7 @@ namespace Artemis.Managers if (!ProgramEnabled) return; - var runningProcesses = Process.GetProcesses(); + var runningProcesses = System.Diagnostics.Process.GetProcesses(); // If the currently active effect is a disabled game, get rid of it. if (EffectManager.ActiveEffect != null) diff --git a/Artemis/Artemis/Models/EffectModel.cs b/Artemis/Artemis/Models/EffectModel.cs index c0ec5cbb6..eb81fd9de 100644 --- a/Artemis/Artemis/Models/EffectModel.cs +++ b/Artemis/Artemis/Models/EffectModel.cs @@ -88,6 +88,12 @@ namespace Artemis.Models Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Generic), DataModel, devRec, false, true); } + // Render mousemats layer-by-layer + using (var g = Graphics.FromImage(frame.MousematBitmap)) + { + Profile?.DrawLayers(g, renderLayers.Where(rl => rl.LayerType.DrawType == DrawType.Mousemat), + DataModel, devRec, false, true); + } // Trace debugging if (DateTime.Now.AddSeconds(-2) <= LastTrace) diff --git a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualization.cs b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualization.cs deleted file mode 100644 index 677970011..000000000 --- a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualization.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.ComponentModel; -using System.Configuration; - -namespace Artemis.Modules.Effects.AudioVisualizer -{ - // This class allows you to handle specific events on the settings class: - // The SettingChanging event is raised before a setting's value is changed. - // The PropertyChanged event is raised after a setting's value is changed. - // The SettingsLoaded event is raised after the setting values are loaded. - // The SettingsSaving event is raised before the setting values are saved. - internal sealed partial class AudioVisualization - { - private void SettingChangingEventHandler(object sender, SettingChangingEventArgs e) - { - // Add code to handle the SettingChangingEvent event here. - } - - private void SettingsSavingEventHandler(object sender, CancelEventArgs e) - { - // Add code to handle the SettingsSaving event here. - } - } -} \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs deleted file mode 100644 index 90ede32ce..000000000 --- a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerModel.cs +++ /dev/null @@ -1,206 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Linq; -using Artemis.Managers; -using Artemis.Models; -using Artemis.Modules.Effects.AudioVisualizer.Utilities; -using Artemis.Profiles.Layers.Models; -using Artemis.Utilities; -using Artemis.Utilities.Keyboard; -using NAudio.CoreAudioApi; -using NAudio.Wave; - -namespace Artemis.Modules.Effects.AudioVisualizer -{ - public class AudioVisualizerModel : EffectModel - { - private const int FftLength = 2048; - private readonly SampleAggregator _sampleAggregator = new SampleAggregator(FftLength); - private bool _fromBottom; - private bool _generating; - private int _sensitivity; - private IWaveIn _waveIn; - - public AudioVisualizerModel(MainManager mainManager) : base(mainManager, null, null) - { - Name = "Audiovisualizer"; - DeviceIds = new List(); - SpectrumData = new List(); - Initialized = false; - } - - public int Lines { get; set; } - - public List SpectrumData { get; set; } - public List SoundRectangles { get; set; } - - public List DeviceIds { get; set; } - public string SelectedDeviceId { get; set; } - - public override void Dispose() - { - Initialized = false; - _sampleAggregator.PerformFFT = false; - _sampleAggregator.FftCalculated -= FftCalculated; - - if (_waveIn == null) - return; - _waveIn.StopRecording(); - _waveIn.DataAvailable -= OnDataAvailable; - _waveIn = null; - } - - public override void Enable() - { - Initialized = false; - Lines = MainManager.DeviceManager.ActiveKeyboard.Width; - - // TODO: Device selection - SelectedDeviceId = new MMDeviceEnumerator() - .EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active) - .FirstOrDefault()?.ID; - - // Apply settings - SoundRectangles = new List(); - for (var i = 0; i < Lines; i++) - { - SoundRectangles.Add(new KeyboardRectangle( - MainManager.DeviceManager.ActiveKeyboard, - 0, 0, new List - { - Color.Red, - Color.Yellow, - Color.Lime - }, - LinearGradientMode.Vertical) - {ContainedBrush = false, Height = 0}); - } - _sensitivity = 2; - _fromBottom = true; - _sampleAggregator.FftCalculated += FftCalculated; - _sampleAggregator.PerformFFT = true; - - // Start listening for sound data - _waveIn = new WasapiLoopbackCapture(); - _waveIn.DataAvailable += OnDataAvailable; - _waveIn.StartRecording(); - - Initialized = true; - } - - public override void Update() - { - // TODO: Use lock instead of a bool - // Start filling the model - _generating = true; - - if (SelectedDeviceId == null) - return; - - var device = new MMDeviceEnumerator() - .EnumerateAudioEndPoints(DataFlow.All, DeviceState.Active) - .FirstOrDefault(d => d.ID == SelectedDeviceId); - - if (device == null || SpectrumData == null) - return; - if (!SpectrumData.Any()) - return; - - // Parse spectrum data - for (var i = 0; i < Lines; i++) - { - int height; - if (SpectrumData.Count - 1 < i || SpectrumData[i] == 0) - height = 0; - else - height = (int) Math.Round(SpectrumData[i]/2.55); - - // Apply Sensitivity setting - height = height*_sensitivity; - var keyboardHeight = - (int) Math.Round(MainManager.DeviceManager.ActiveKeyboard.Height/100.00*height*KeyboardScale); - if (keyboardHeight > SoundRectangles[i].Height) - SoundRectangles[i].Height = keyboardHeight; - else - SoundRectangles[i].Height = SoundRectangles[i].Height - - 5; // was FadeSpeed setting - // Apply Bars setting - SoundRectangles[i].X = i*KeyboardScale; - SoundRectangles[i].Width = KeyboardScale; - - if (_fromBottom) - SoundRectangles[i].Y = MainManager.DeviceManager.ActiveKeyboard.Height*KeyboardScale - - SoundRectangles[i].Height; - } - _generating = false; - } - - private void OnDataAvailable(object sender, WaveInEventArgs e) - { - var buffer = e.Buffer; - var bytesRecorded = e.BytesRecorded; - var bufferIncrement = _waveIn.WaveFormat.BlockAlign; - - for (var index = 0; index < bytesRecorded; index += bufferIncrement) - { - var sample32 = BitConverter.ToSingle(buffer, index); - _sampleAggregator.Add(sample32); - } - } - - private void FftCalculated(object sender, FftEventArgs e) - { - if (_generating) - return; - - int x; - var b0 = 0; - - SpectrumData.Clear(); - for (x = 0; x < Lines; x++) - { - float peak = 0; - var b1 = (int) Math.Pow(2, x*10.0/(Lines - 1)); - if (b1 > 2047) - b1 = 2047; - if (b1 <= b0) - b1 = b0 + 1; - for (; b0 < b1; b0++) - { - if (peak < e.Result[1 + b0].X) - peak = e.Result[1 + b0].X; - } - var y = (int) (Math.Sqrt(peak)*3*255 - 4); - if (y > 255) - y = 255; - if (y < 0) - y = 0; - SpectrumData.Add((byte) y); - } - } - - public override List GetRenderLayers(bool keyboardOnly) - { - return null; - } - - public override void Render(RenderFrame frame, bool keyboardOnly) - { - if (SpectrumData == null || SoundRectangles == null) - return; - - // Lock the _spectrumData array while busy with it - _generating = true; - - using (var g = Graphics.FromImage(frame.KeyboardBitmap)) - { - foreach (var soundRectangle in SoundRectangles) - soundRectangle.Draw(g); - } - - _generating = false; - } - } -} \ No newline at end of file diff --git a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerView.xaml b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerView.xaml index 0884c7690..efdc30bd3 100644 --- a/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerView.xaml +++ b/Artemis/Artemis/Modules/Effects/AudioVisualizer/AudioVisualizerView.xaml @@ -3,110 +3,31 @@ 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" - xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" - xmlns:cal="http://www.caliburnproject.org" - xmlns:controls="http://metro.mahapps.com/winfx/xaml/controls" mc:Ignorable="d" d:DesignHeight="476.986" d:DesignWidth="538.772"> - - - - - - - - - - - - - - - - - - - Color used on top - - + - - - Color used in the middle + + + + + + + + - - - - - Color used on the bottom - - - - - - Grow bars bottom - - - - - - Volume sensitivity multiplier - - - - - - Bar fade-out speed - - - - - -