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();
using (var c = visual.RenderOpen())
c.DrawRectangle(brush, null, rect);
var img = ImageUtilities.DrawinVisualToBitmap(visual, rect);
var ledIndex = 0;
// Color each LED according to one of the pixels
foreach (var corsairLed in CueSDK.HeadsetSDK.Leds)
using (var img = ImageUtilities.DrawinVisualToBitmap(visual, rect))
{
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
CueSDK.HeadsetSDK.Update(true);
}

View File

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

View File

@ -1,5 +1,6 @@
using System.Drawing;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using Artemis.Properties;
using Artemis.Utilities;
@ -7,6 +8,7 @@ using CUE.NET;
using CUE.NET.Brushes;
using CUE.NET.Devices.Generic.Enums;
using CUE.NET.Devices.Keyboard;
using MahApps.Metro.Controls.Dialogs;
using Ninject.Extensions.Logging;
using Point = System.Drawing.Point;
@ -14,7 +16,6 @@ namespace Artemis.DeviceProviders.Corsair
{
public class CorsairRGB : KeyboardProvider
{
public ILogger Logger { get; set; }
private CorsairKeyboard _keyboard;
private ImageBrush _keyboardBrush;
@ -28,6 +29,37 @@ namespace Artemis.DeviceProviders.Corsair
"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()
{
// 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
{
@ -29,6 +30,15 @@ namespace Artemis.DeviceProviders
/// Disables the device
/// </summary>
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

View File

@ -1,6 +1,8 @@
using System;
using System.Drawing;
using System.Threading.Tasks;
using System.Windows;
using MahApps.Metro.Controls.Dialogs;
using Brush = System.Windows.Media.Brush;
using Size = System.Windows.Size;
@ -18,7 +20,6 @@ namespace Artemis.DeviceProviders
public int Height { get; set; }
public int Width { get; set; }
public string CantEnableText { get; set; }
public PreviewSettings PreviewSettings { get; set; }
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 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)
{
throw new NotImplementedException("KeyboardProvider doesn't implement UpdateDevice, use DrawBitmap instead.");
@ -46,7 +57,8 @@ namespace Artemis.DeviceProviders
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
Bind<EffectViewModel>().To<AudioVisualizerViewModel>().InSingletonScope();
Bind<EffectViewModel>().To<TypeWaveViewModel>().InSingletonScope();
//Bind<EffectViewModel>().To<BubblesViewModel>().InSingletonScope(); TODO: Performance
Bind<EffectViewModel>().To<BubblesViewModel>().InSingletonScope();
Bind<EffectViewModel>().To<WindowsProfileViewModel>().InSingletonScope();
// Games

View File

@ -2,11 +2,13 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Artemis.DeviceProviders;
using Artemis.Events;
using Artemis.Services;
using Artemis.Settings;
using Caliburn.Micro;
using MahApps.Metro.Controls.Dialogs;
using Ninject;
using Ninject.Extensions.Logging;
@ -65,8 +67,14 @@ namespace Artemis.Managers
/// Enables the given keyboard
/// </summary>
/// <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)
{
ChangingKeyboard = true;
@ -80,9 +88,6 @@ namespace Artemis.Managers
return;
}
// Store the old keyboard so it can be used in the event we're raising later
var oldKeyboard = ActiveKeyboard;
var wasNull = false;
if (ActiveKeyboard == null)
{
@ -90,69 +95,63 @@ namespace Artemis.Managers
ActiveKeyboard = keyboardProvider;
}
_logger.Debug("Enabling keyboard: {0}", keyboardProvider.Name);
if (!wasNull)
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.Enable();
await ActiveKeyboard.EnableAsync(dialog);
General.Default.LastKeyboard = ActiveKeyboard.Name;
General.Default.Save();
EnableUsableDevices();
ChangingKeyboard = false;
_events.PublishOnUIThread(new ActiveKeyboardChanged(oldKeyboard, ActiveKeyboard));
_logger.Debug("Enabled keyboard: {0}", keyboardProvider.Name);
if (dialog != null)
await dialog.CloseAsync();
ChangingKeyboard = false;
}
private void EnableUsableDevices()
{
foreach (var mouseProvider in MiceProviders)
mouseProvider.TryEnable();
mouseProvider.TryEnableAsync();
foreach (var headsetProvider in HeadsetProviders)
headsetProvider.TryEnable();
headsetProvider.TryEnableAsync();
}
/// <summary>

View File

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

View File

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

View File

@ -46,7 +46,6 @@ namespace Artemis.Managers
ProgramEnabled = false;
Running = false;
// TODO: Dependency inject utilities?
KeyboardHook = new KeyboardHook();
@ -94,7 +93,7 @@ namespace Artemis.Managers
{
_logger.Debug("Enabling program");
ProgramEnabled = true;
LoopManager.Start();
LoopManager.StartAsync();
_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.Start();
_loopManager.StartAsync();
if (!ReferenceEquals(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,
bool renderHeadsets)
{
if (MainManager.DeviceManager.ActiveKeyboard == null)
return;
keyboard = GenerateBitmap(keyboard ?? MainManager.DeviceManager.ActiveKeyboard.KeyboardBitmap(4));
}
}

View File

@ -32,7 +32,7 @@ namespace Artemis.Services
{
public class MetroDialogService : DialogService
{
private MetroWindow GetActiveWindow()
public MetroWindow GetActiveWindow()
{
MetroWindow window = null;
@ -128,5 +128,14 @@ namespace Artemis.Services
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)
{
MainManager.DeviceManager.EnableKeyboard(keyboard);
MainManager.LoopManager.Start();
MainManager.LoopManager.StartAsync();
}
else
MainManager.DeviceManager.ReleaseActiveKeyboard(true);