1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

All device enable methods are now async. This fixes #104

This commit is contained in:
SpoinkyNL 2016-06-13 20:17:31 +02:00
parent 47b9b78634
commit b546d98db0
14 changed files with 153 additions and 79 deletions

View File

@ -46,18 +46,20 @@ namespace Artemis.DeviceProviders.Corsair
var visual = new DrawingVisual(); var visual = new DrawingVisual();
using (var c = visual.RenderOpen()) using (var c = visual.RenderOpen())
c.DrawRectangle(brush, null, rect); c.DrawRectangle(brush, null, rect);
var img = ImageUtilities.DrawinVisualToBitmap(visual, rect);
var ledIndex = 0; using (var img = ImageUtilities.DrawinVisualToBitmap(visual, rect))
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.HeadsetSDK.Leds)
{ {
corsairLed.Color = ledIndex == 0
? img.GetPixel(0, 0)
: img.GetPixel((ledIndex + 1)*20 - 1, (ledIndex + 1)*20 - 1);
ledIndex++;
}
var ledIndex = 0;
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.HeadsetSDK.Leds)
{
corsairLed.Color = ledIndex == 0
? img.GetPixel(0, 0)
: img.GetPixel((ledIndex + 1)*20 - 1, (ledIndex + 1)*20 - 1);
ledIndex++;
}
}
// Flush is required for headset to work reliably on CUE2 for some reason // Flush is required for headset to work reliably on CUE2 for some reason
CueSDK.HeadsetSDK.Update(true); CueSDK.HeadsetSDK.Update(true);
} }

View File

@ -46,18 +46,19 @@ namespace Artemis.DeviceProviders.Corsair
var visual = new DrawingVisual(); var visual = new DrawingVisual();
using (var c = visual.RenderOpen()) using (var c = visual.RenderOpen())
c.DrawRectangle(brush, null, rect); c.DrawRectangle(brush, null, rect);
var img = ImageUtilities.DrawinVisualToBitmap(visual, rect);
var ledIndex = 0; using (var img = ImageUtilities.DrawinVisualToBitmap(visual, rect))
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.MouseSDK.Leds)
{ {
corsairLed.Color = ledIndex == 0 var ledIndex = 0;
? img.GetPixel(0, 0) // Color each LED according to one of the pixels
: img.GetPixel((ledIndex + 1)*20 - 1, (ledIndex + 1)*20 - 1); foreach (var corsairLed in CueSDK.MouseSDK.Leds)
ledIndex++; {
corsairLed.Color = ledIndex == 0
? img.GetPixel(0, 0)
: img.GetPixel((ledIndex + 1)*20 - 1, (ledIndex + 1)*20 - 1);
ledIndex++;
}
} }
CueSDK.MouseSDK.Update(); CueSDK.MouseSDK.Update();
} }

View File

@ -1,5 +1,6 @@
using System.Drawing; using System.Drawing;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using Artemis.Properties; using Artemis.Properties;
using Artemis.Utilities; using Artemis.Utilities;
@ -7,6 +8,7 @@ using CUE.NET;
using CUE.NET.Brushes; using CUE.NET.Brushes;
using CUE.NET.Devices.Generic.Enums; using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Keyboard; using CUE.NET.Devices.Keyboard;
using MahApps.Metro.Controls.Dialogs;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
using Point = System.Drawing.Point; using Point = System.Drawing.Point;
@ -14,7 +16,6 @@ namespace Artemis.DeviceProviders.Corsair
{ {
public class CorsairRGB : KeyboardProvider public class CorsairRGB : KeyboardProvider
{ {
public ILogger Logger { get; set; }
private CorsairKeyboard _keyboard; private CorsairKeyboard _keyboard;
private ImageBrush _keyboardBrush; private ImageBrush _keyboardBrush;
@ -28,6 +29,37 @@ namespace Artemis.DeviceProviders.Corsair
"If needed, you can select a different keyboard in Artemis under settings."; "If needed, you can select a different keyboard in Artemis under settings.";
} }
public ILogger Logger { get; set; }
public sealed override Task<bool> CanEnableAsync(ProgressDialogController dialog)
{
return Task.Run(() =>
{
// This will skip the check-loop if the SDK is initialized
if (CueSDK.IsInitialized)
return CueSDK.IsSDKAvailable(CorsairDeviceType.Keyboard);
for (var tries = 0; tries < 9; tries++)
{
// Stop trying if cancelled by user
if (dialog != null && dialog.IsCanceled)
{
dialog.SetIndeterminate();
return false;
}
dialog?.SetProgress(0.1*(tries + 1));
if (CueSDK.IsSDKAvailable(CorsairDeviceType.Keyboard))
{
dialog?.SetIndeterminate();
return true;
}
Thread.Sleep(2000);
}
dialog?.SetIndeterminate();
return false;
});
}
public override bool CanEnable() public override bool CanEnable()
{ {
// This will skip the check-loop if the SDK is initialized // This will skip the check-loop if the SDK is initialized

View File

@ -1,4 +1,5 @@
using System.Windows.Media; using System.Threading.Tasks;
using System.Windows.Media;
namespace Artemis.DeviceProviders namespace Artemis.DeviceProviders
{ {
@ -29,6 +30,15 @@ namespace Artemis.DeviceProviders
/// Disables the device /// Disables the device
/// </summary> /// </summary>
public abstract void Disable(); public abstract void Disable();
/// <summary>
/// Tries to enable the device and updates CanUse accordingly asynchronously
/// </summary>
/// <returns></returns>
public Task<bool> TryEnableAsync()
{
return Task.Run(() => TryEnable());
}
} }
public enum DeviceType public enum DeviceType

View File

@ -1,6 +1,8 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Threading.Tasks;
using System.Windows; using System.Windows;
using MahApps.Metro.Controls.Dialogs;
using Brush = System.Windows.Media.Brush; using Brush = System.Windows.Media.Brush;
using Size = System.Windows.Size; using Size = System.Windows.Size;
@ -18,7 +20,6 @@ namespace Artemis.DeviceProviders
public int Height { get; set; } public int Height { get; set; }
public int Width { get; set; } public int Width { get; set; }
public string CantEnableText { get; set; } public string CantEnableText { get; set; }
public PreviewSettings PreviewSettings { get; set; } public PreviewSettings PreviewSettings { get; set; }
public abstract bool CanEnable(); public abstract bool CanEnable();
@ -39,6 +40,16 @@ namespace Artemis.DeviceProviders
public Rect KeyboardRectangle(int scale) => new Rect(new Size(Width*scale, Height*scale)); public Rect KeyboardRectangle(int scale) => new Rect(new Size(Width*scale, Height*scale));
public virtual Task<bool> CanEnableAsync(ProgressDialogController dialog)
{
return Task.Run(() => CanEnable());
}
public virtual Task EnableAsync(ProgressDialogController dialog)
{
return Task.Run(() => Enable());
}
public override void UpdateDevice(Brush brush) public override void UpdateDevice(Brush brush)
{ {
throw new NotImplementedException("KeyboardProvider doesn't implement UpdateDevice, use DrawBitmap instead."); throw new NotImplementedException("KeyboardProvider doesn't implement UpdateDevice, use DrawBitmap instead.");
@ -46,7 +57,8 @@ namespace Artemis.DeviceProviders
public override bool TryEnable() public override bool TryEnable()
{ {
throw new NotImplementedException("KeyboardProvider doesn't implement TryEnable, use CanEnable instead."); throw new NotImplementedException(
"KeyboardProvider doesn't implement TryEnable, use CanEnableAsync instead.");
} }
} }

View File

@ -27,7 +27,7 @@ namespace Artemis.InjectionModules
// Effects // Effects
Bind<EffectViewModel>().To<AudioVisualizerViewModel>().InSingletonScope(); Bind<EffectViewModel>().To<AudioVisualizerViewModel>().InSingletonScope();
Bind<EffectViewModel>().To<TypeWaveViewModel>().InSingletonScope(); Bind<EffectViewModel>().To<TypeWaveViewModel>().InSingletonScope();
//Bind<EffectViewModel>().To<BubblesViewModel>().InSingletonScope(); TODO: Performance Bind<EffectViewModel>().To<BubblesViewModel>().InSingletonScope();
Bind<EffectViewModel>().To<WindowsProfileViewModel>().InSingletonScope(); Bind<EffectViewModel>().To<WindowsProfileViewModel>().InSingletonScope();
// Games // Games

View File

@ -2,11 +2,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks;
using Artemis.DeviceProviders; using Artemis.DeviceProviders;
using Artemis.Events; using Artemis.Events;
using Artemis.Services; using Artemis.Services;
using Artemis.Settings; using Artemis.Settings;
using Caliburn.Micro; using Caliburn.Micro;
using MahApps.Metro.Controls.Dialogs;
using Ninject; using Ninject;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
@ -65,8 +67,14 @@ namespace Artemis.Managers
/// Enables the given keyboard /// Enables the given keyboard
/// </summary> /// </summary>
/// <param name="keyboardProvider"></param> /// <param name="keyboardProvider"></param>
public void EnableKeyboard(KeyboardProvider keyboardProvider) public async void EnableKeyboard(KeyboardProvider keyboardProvider)
{ {
if (ChangingKeyboard)
return;
// Store the old keyboard so it can be used in the event we're raising later
var oldKeyboard = ActiveKeyboard;
lock (this) lock (this)
{ {
ChangingKeyboard = true; ChangingKeyboard = true;
@ -80,9 +88,6 @@ namespace Artemis.Managers
return; return;
} }
// Store the old keyboard so it can be used in the event we're raising later
var oldKeyboard = ActiveKeyboard;
var wasNull = false; var wasNull = false;
if (ActiveKeyboard == null) if (ActiveKeyboard == null)
{ {
@ -90,69 +95,63 @@ namespace Artemis.Managers
ActiveKeyboard = keyboardProvider; ActiveKeyboard = keyboardProvider;
} }
_logger.Debug("Enabling keyboard: {0}", keyboardProvider.Name);
if (!wasNull) if (!wasNull)
ReleaseActiveKeyboard(); ReleaseActiveKeyboard();
var asynchEnable = false;
if (keyboardProvider.CanEnable())
{
FinishEnableKeyboard(keyboardProvider, oldKeyboard);
}
else
{
for (var i = 1; i <= 10; i++)
{
var thread = new Thread(() =>
{
Thread.Sleep(500*i);
asynchEnable = keyboardProvider.CanEnable();
});
_logger.Warn("Failed enabling keyboard: {0}, re-attempt {1} of 10", keyboardProvider.Name, i);
thread.Start();
if (asynchEnable)
break;
}
if (!asynchEnable)
{
// Disable everything if there's no active keyboard found
DialogService.ShowErrorMessageBox(keyboardProvider.CantEnableText);
ActiveKeyboard = null;
General.Default.LastKeyboard = null;
General.Default.Save();
_logger.Warn("Failed enabling keyboard: {0}", keyboardProvider.Name);
ChangingKeyboard = false;
return;
}
FinishEnableKeyboard(keyboardProvider, oldKeyboard);
}
} }
}
private void FinishEnableKeyboard(KeyboardProvider keyboardProvider, KeyboardProvider oldKeyboard) // TODO: LoopManager shouldn't be running at this point
{ _logger.Debug("Enabling keyboard: {0}", keyboardProvider.Name);
// Create a dialog to let the user know Artemis hasn't frozen
ProgressDialogController dialog = null;
if (DialogService.GetActiveWindow() != null)
{
dialog = await DialogService.ShowProgressDialog("Enabling keyboard",
$"Checking if keyboard '{keyboardProvider.Name}' can be enabled...", true);
// May seem a bit cheesy, but it's tidier to have the animation finish
await Task.Delay(500);
}
dialog?.SetIndeterminate();
var canEnable = await keyboardProvider.CanEnableAsync(dialog);
if (!canEnable)
{
if (dialog != null)
await dialog.CloseAsync();
DialogService.ShowErrorMessageBox(keyboardProvider.CantEnableText);
ActiveKeyboard = null;
General.Default.LastKeyboard = null;
General.Default.Save();
_logger.Warn("Failed enabling keyboard: {0}", keyboardProvider.Name);
ChangingKeyboard = false;
return;
}
dialog?.SetMessage($"Enabling keyboard: {keyboardProvider.Name}...");
ActiveKeyboard = keyboardProvider; ActiveKeyboard = keyboardProvider;
ActiveKeyboard.Enable(); await ActiveKeyboard.EnableAsync(dialog);
General.Default.LastKeyboard = ActiveKeyboard.Name; General.Default.LastKeyboard = ActiveKeyboard.Name;
General.Default.Save(); General.Default.Save();
EnableUsableDevices(); EnableUsableDevices();
ChangingKeyboard = false;
_events.PublishOnUIThread(new ActiveKeyboardChanged(oldKeyboard, ActiveKeyboard)); _events.PublishOnUIThread(new ActiveKeyboardChanged(oldKeyboard, ActiveKeyboard));
_logger.Debug("Enabled keyboard: {0}", keyboardProvider.Name); _logger.Debug("Enabled keyboard: {0}", keyboardProvider.Name);
if (dialog != null)
await dialog.CloseAsync();
ChangingKeyboard = false;
} }
private void EnableUsableDevices() private void EnableUsableDevices()
{ {
foreach (var mouseProvider in MiceProviders) foreach (var mouseProvider in MiceProviders)
mouseProvider.TryEnable(); mouseProvider.TryEnableAsync();
foreach (var headsetProvider in HeadsetProviders) foreach (var headsetProvider in HeadsetProviders)
headsetProvider.TryEnable(); headsetProvider.TryEnableAsync();
} }
/// <summary> /// <summary>

View File

@ -134,7 +134,7 @@ namespace Artemis.Managers
if (loopManager != null && !loopManager.Running) if (loopManager != null && !loopManager.Running)
{ {
_logger.Debug("Starting LoopManager for effect change"); _logger.Debug("Starting LoopManager for effect change");
loopManager.Start(); loopManager.StartAsync();
} }
_logger.Debug("Changed active effect to: {0}", effectModel.Name); _logger.Debug("Changed active effect to: {0}", effectModel.Name);

View File

@ -1,6 +1,7 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using System.Timers; using System.Timers;
using Ninject.Extensions.Logging; using Ninject.Extensions.Logging;
using Brush = System.Windows.Media.Brush; using Brush = System.Windows.Media.Brush;
@ -40,7 +41,12 @@ namespace Artemis.Managers
_loopTimer.Dispose(); _loopTimer.Dispose();
} }
public void Start() public Task StartAsync()
{
return Task.Run(() => Start());
}
private void Start()
{ {
if (Running) if (Running)
return; return;
@ -157,6 +163,7 @@ namespace Artemis.Managers
// Update the keyboard // Update the keyboard
_deviceManager.ActiveKeyboard?.DrawBitmap(bitmap); _deviceManager.ActiveKeyboard?.DrawBitmap(bitmap);
bitmap.Dispose();
} }
} }
} }

View File

@ -46,7 +46,6 @@ namespace Artemis.Managers
ProgramEnabled = false; ProgramEnabled = false;
Running = false; Running = false;
// TODO: Dependency inject utilities? // TODO: Dependency inject utilities?
KeyboardHook = new KeyboardHook(); KeyboardHook = new KeyboardHook();
@ -94,7 +93,7 @@ namespace Artemis.Managers
{ {
_logger.Debug("Enabling program"); _logger.Debug("Enabling program");
ProgramEnabled = true; ProgramEnabled = true;
LoopManager.Start(); LoopManager.StartAsync();
_events.PublishOnUIThread(new ToggleEnabled(ProgramEnabled)); _events.PublishOnUIThread(new ToggleEnabled(ProgramEnabled));
} }

View File

@ -68,7 +68,7 @@ namespace Artemis.Managers
} }
// LoopManager might be running, this method won't do any harm in that case. // LoopManager might be running, this method won't do any harm in that case.
_loopManager.Start(); _loopManager.StartAsync();
if (!ReferenceEquals(ProfilePreviewModel.Profile, activePreview.ProfileEditor.SelectedProfile)) if (!ReferenceEquals(ProfilePreviewModel.Profile, activePreview.ProfileEditor.SelectedProfile))
ProfilePreviewModel.Profile = activePreview.ProfileEditor.SelectedProfile; ProfilePreviewModel.Profile = activePreview.ProfileEditor.SelectedProfile;

View File

@ -94,6 +94,9 @@ namespace Artemis.Modules.Overlays.VolumeDisplay
public override void RenderOverlay(ref Bitmap keyboard, ref Brush mouse, ref Brush headset, bool renderMice, public override void RenderOverlay(ref Bitmap keyboard, ref Brush mouse, ref Brush headset, bool renderMice,
bool renderHeadsets) bool renderHeadsets)
{ {
if (MainManager.DeviceManager.ActiveKeyboard == null)
return;
keyboard = GenerateBitmap(keyboard ?? MainManager.DeviceManager.ActiveKeyboard.KeyboardBitmap(4)); keyboard = GenerateBitmap(keyboard ?? MainManager.DeviceManager.ActiveKeyboard.KeyboardBitmap(4));
} }
} }

View File

@ -32,7 +32,7 @@ namespace Artemis.Services
{ {
public class MetroDialogService : DialogService public class MetroDialogService : DialogService
{ {
private MetroWindow GetActiveWindow() public MetroWindow GetActiveWindow()
{ {
MetroWindow window = null; MetroWindow window = null;
@ -128,5 +128,14 @@ namespace Artemis.Services
return res.Value; return res.Value;
} }
public Task<ProgressDialogController> ShowProgressDialog(string title, string message, bool isCancelable = false,
MetroDialogSettings settings = null)
{
return GetActiveWindow() == null
? null
: GetActiveWindow().Dispatcher.Invoke(() =>
GetActiveWindow()?.ShowProgressAsync(title, message, isCancelable, settings));
}
} }
} }

View File

@ -167,7 +167,7 @@ namespace Artemis.ViewModels.Flyouts
if (keyboard != null) if (keyboard != null)
{ {
MainManager.DeviceManager.EnableKeyboard(keyboard); MainManager.DeviceManager.EnableKeyboard(keyboard);
MainManager.LoopManager.Start(); MainManager.LoopManager.StartAsync();
} }
else else
MainManager.DeviceManager.ReleaseActiveKeyboard(true); MainManager.DeviceManager.ReleaseActiveKeyboard(true);