Skip to content

Commit

Permalink
Merge pull request #62 from BarRaider/direct-streamdeck-comms
Browse files Browse the repository at this point in the history
Improve performance and error handling by directly communicating with SD
  • Loading branch information
BarRaider authored Dec 8, 2022
2 parents 7fee049 + 8612fb1 commit 69cb52a
Show file tree
Hide file tree
Showing 66 changed files with 3,906 additions and 252 deletions.
6 changes: 5 additions & 1 deletion barraider-sdtools/Backend/ISDConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ public interface ISDConnection : IDisposable
/// Event received when the Property Inspector for an instance is removed from the Stream Deck software user interface, for example when selecting a different instance.
/// </summary>
event EventHandler<SDEventReceivedEventArgs<PropertyInspectorDidDisappear>> OnPropertyInspectorDidDisappear;
/// <summary>
/// Event received when the computer wakes up
/// </summary>
event EventHandler<SDEventReceivedEventArgs<SystemDidWakeUp>> OnSystemDidWakeUp;

#endregion

Expand Down Expand Up @@ -199,6 +203,6 @@ public interface ISDConnection : IDisposable
/// StreamDeckConnection object, initialized based on the args received when launching the program
/// </summary>
[JsonIgnore]
streamdeck_client_csharp.StreamDeckConnection StreamDeckConnection { get; }
Communication.StreamDeckConnection StreamDeckConnection { get; }
}
}
46 changes: 18 additions & 28 deletions barraider-sdtools/Backend/PluginContainer.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
using Newtonsoft.Json.Linq;
using streamdeck_client_csharp;
using streamdeck_client_csharp.Events;
using BarRaider.SdTools.Communication;
using BarRaider.SdTools.Communication.SDEvents;
using BarRaider.SdTools.Payloads;
using BarRaider.SdTools.Wrappers;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
Expand All @@ -10,6 +12,7 @@ namespace BarRaider.SdTools
{
class PluginContainer
{
private const int STREAMDECK_INITIAL_CONNECTION_TIMEOUT_SECONDS = 60;
private StreamDeckConnection connection;
private readonly ManualResetEvent connectEvent = new ManualResetEvent(false);
private readonly ManualResetEvent disconnectEvent = new ManualResetEvent(false);
Expand Down Expand Up @@ -50,14 +53,12 @@ public void Run(StreamDeckOptions options)

// Start the connection
connection.Run();
#if DEBUG
Logger.Instance.LogMessage(TracingLevel.DEBUG, $"Plugin Loaded: UUID: {pluginUUID} Device Info: {deviceInfo}");
#endif
Logger.Instance.LogMessage(TracingLevel.INFO, $"Plugin version: {deviceInfo.Plugin.Version}");
Logger.Instance.LogMessage(TracingLevel.INFO, "Connecting to Stream Deck");
Logger.Instance.LogMessage(TracingLevel.INFO, "Connecting to Stream Deck...");

// Wait for up to 10 seconds to connect
if (connectEvent.WaitOne(TimeSpan.FromSeconds(10)))
// Time to wait for initial connection
if (connectEvent.WaitOne(TimeSpan.FromSeconds(STREAMDECK_INITIAL_CONNECTION_TIMEOUT_SECONDS)))
{
Logger.Instance.LogMessage(TracingLevel.INFO, "Connected to Stream Deck");

Expand All @@ -74,7 +75,7 @@ public void Run(StreamDeckOptions options)
}

// Button pressed
private async void Connection_OnKeyDown(object sender, StreamDeckEventReceivedEventArgs<KeyDownEvent> e)
private async void Connection_OnKeyDown(object sender, SDEventReceivedEventArgs<KeyDownEvent> e)
{
await instancesLock.WaitAsync();
try
Expand All @@ -85,7 +86,7 @@ private async void Connection_OnKeyDown(object sender, StreamDeckEventReceivedEv

if (instances.ContainsKey(e.Event.Context))
{
KeyPayload payload = new KeyPayload(GenerateKeyCoordinates(e.Event.Payload.Coordinates),
KeyPayload payload = new KeyPayload(e.Event.Payload.Coordinates,
e.Event.Payload.Settings, e.Event.Payload.State, e.Event.Payload.UserDesiredState, e.Event.Payload.IsInMultiAction);
instances[e.Event.Context].KeyPressed(payload);
}
Expand All @@ -97,7 +98,7 @@ private async void Connection_OnKeyDown(object sender, StreamDeckEventReceivedEv
}

// Button released
private async void Connection_OnKeyUp(object sender, StreamDeckEventReceivedEventArgs<KeyUpEvent> e)
private async void Connection_OnKeyUp(object sender, SDEventReceivedEventArgs<KeyUpEvent> e)
{
await instancesLock.WaitAsync();
try
Expand All @@ -108,7 +109,7 @@ private async void Connection_OnKeyUp(object sender, StreamDeckEventReceivedEven

if (instances.ContainsKey(e.Event.Context))
{
KeyPayload payload = new KeyPayload(GenerateKeyCoordinates(e.Event.Payload.Coordinates),
KeyPayload payload = new KeyPayload(e.Event.Payload.Coordinates,
e.Event.Payload.Settings, e.Event.Payload.State, e.Event.Payload.UserDesiredState, e.Event.Payload.IsInMultiAction);
instances[e.Event.Context].KeyReleased(payload);
}
Expand Down Expand Up @@ -138,7 +139,7 @@ private async void RunTick()
}

// Action is loaded in the Stream Deck
private async void Connection_OnWillAppear(object sender, StreamDeckEventReceivedEventArgs<WillAppearEvent> e)
private async void Connection_OnWillAppear(object sender, SDEventReceivedEventArgs<WillAppearEvent> e)
{
SDConnection conn = new SDConnection(connection, pluginUUID, deviceInfo, e.Event.Action, e.Event.Context, e.Event.Device);
await instancesLock.WaitAsync();
Expand All @@ -157,7 +158,7 @@ private async void Connection_OnWillAppear(object sender, StreamDeckEventReceive
Logger.Instance.LogMessage(TracingLevel.INFO, $"WillAppear called for already existing context {e.Event.Context} (might be inside a multi-action)");
return;
}
InitialPayload payload = new InitialPayload(GenerateKeyCoordinates(e.Event.Payload.Coordinates),
InitialPayload payload = new InitialPayload(e.Event.Payload.Coordinates,
e.Event.Payload.Settings, e.Event.Payload.State, e.Event.Payload.IsInMultiAction, deviceInfo);
instances[e.Event.Context] = (PluginBase)Activator.CreateInstance(supportedActions[e.Event.Action], conn, payload);
}
Expand All @@ -177,7 +178,7 @@ private async void Connection_OnWillAppear(object sender, StreamDeckEventReceive
}
}

private async void Connection_OnWillDisappear(object sender, StreamDeckEventReceivedEventArgs<WillDisappearEvent> e)
private async void Connection_OnWillDisappear(object sender, SDEventReceivedEventArgs<WillDisappearEvent> e)
{
await instancesLock.WaitAsync();
try
Expand All @@ -199,7 +200,7 @@ private async void Connection_OnWillDisappear(object sender, StreamDeckEventRece
}

// Settings updated
private async void Connection_OnDidReceiveSettings(object sender, StreamDeckEventReceivedEventArgs<DidReceiveSettingsEvent> e)
private async void Connection_OnDidReceiveSettings(object sender, SDEventReceivedEventArgs<DidReceiveSettingsEvent> e)
{
await instancesLock.WaitAsync();
try
Expand All @@ -220,7 +221,7 @@ private async void Connection_OnDidReceiveSettings(object sender, StreamDeckEven
}

// Global settings updated
private async void Connection_OnDidReceiveGlobalSettings(object sender, StreamDeckEventReceivedEventArgs<DidReceiveGlobalSettingsEvent> e)
private async void Connection_OnDidReceiveGlobalSettings(object sender, SDEventReceivedEventArgs<DidReceiveGlobalSettingsEvent> e)
{
await instancesLock.WaitAsync();
try
Expand Down Expand Up @@ -252,16 +253,5 @@ private void Connection_OnDisconnected(object sender, EventArgs e)
Logger.Instance.LogMessage(TracingLevel.INFO, "Disconnect event received");
disconnectEvent.Set();
}

private KeyCoordinates GenerateKeyCoordinates(Coordinates coordinates)
{
if (coordinates == null)
{
return null;
}

return new KeyCoordinates() { Column = coordinates.Columns, Row = coordinates.Rows };
}

}
}
43 changes: 28 additions & 15 deletions barraider-sdtools/Backend/SDConnection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
using BarRaider.SdTools.Wrappers;
using BarRaider.SdTools.Events;
using BarRaider.SdTools.Payloads;
using BarRaider.SdTools.Communication;
using BarRaider.SdTools.Communication.SDEvents;

namespace BarRaider.SdTools
{
Expand Down Expand Up @@ -70,6 +72,10 @@ public class SDConnection : ISDConnection
/// Event received when the Property Inspector for an instance is removed from the Stream Deck software user interface, for example when selecting a different instance.
/// </summary>
public event EventHandler<SDEventReceivedEventArgs<PropertyInspectorDidDisappear>> OnPropertyInspectorDidDisappear;
/// <summary>
/// Event received when the computer wakes up
/// </summary>
public event EventHandler<SDEventReceivedEventArgs<SystemDidWakeUp>> OnSystemDidWakeUp;

#endregion

Expand Down Expand Up @@ -145,7 +151,7 @@ public async Task SetImageAsync(string base64Image, int? state = null, bool forc
if (forceSendToStreamdeck || hash != previousImageHash)
{
previousImageHash = hash;
await StreamDeckConnection.SetImageAsync(base64Image, ContextId, streamdeck_client_csharp.SDKTarget.HardwareAndSoftware, state);
await StreamDeckConnection.SetImageAsync(base64Image, ContextId, SDKTarget.HardwareAndSoftware, state);
}
}

Expand All @@ -162,7 +168,7 @@ public async Task SetImageAsync(Image image, int? state = null, bool forceSendTo
if (forceSendToStreamdeck || hash != previousImageHash)
{
previousImageHash = hash;
await StreamDeckConnection.SetImageAsync(image, ContextId, streamdeck_client_csharp.SDKTarget.HardwareAndSoftware, state);
await StreamDeckConnection.SetImageAsync(image, ContextId, SDKTarget.HardwareAndSoftware, state);
}
}

Expand All @@ -183,7 +189,7 @@ public async Task SetDefaultImageAsync()
/// <returns></returns>
public async Task SetTitleAsync(string title, int? state = null)
{
await StreamDeckConnection.SetTitleAsync(title, ContextId, streamdeck_client_csharp.SDKTarget.HardwareAndSoftware, state);
await StreamDeckConnection.SetTitleAsync(title, ContextId, SDKTarget.HardwareAndSoftware, state);
}

/// <summary>
Expand Down Expand Up @@ -307,7 +313,7 @@ public async Task SetStateAsync(uint state)
/// StreamDeckConnection object, initialized based on the args received when launching the program
/// </summary>
[JsonIgnore]
public streamdeck_client_csharp.StreamDeckConnection StreamDeckConnection { get; private set; }
public StreamDeckConnection StreamDeckConnection { get; private set; }

/// <summary>
/// Public constructor, a StreamDeckConnection object is required along with the current action and context IDs
Expand All @@ -319,7 +325,7 @@ public async Task SetStateAsync(uint state)
/// <param name="actionId"></param>
/// <param name="contextId"></param>
/// /// <param name="deviceId"></param>
public SDConnection(streamdeck_client_csharp.StreamDeckConnection connection, string pluginUUID, StreamDeckInfo deviceInfo, string actionId, string contextId, string deviceId)
public SDConnection(StreamDeckConnection connection, string pluginUUID, StreamDeckInfo deviceInfo, string actionId, string contextId, string deviceId)
{
StreamDeckConnection = connection;
this.pluginUUID = pluginUUID;
Expand All @@ -336,6 +342,7 @@ public SDConnection(streamdeck_client_csharp.StreamDeckConnection connection, st
StreamDeckConnection.OnDeviceDidConnect += Connection_OnDeviceDidConnect;
StreamDeckConnection.OnPropertyInspectorDidAppear += Connection_OnPropertyInspectorDidAppear;
StreamDeckConnection.OnPropertyInspectorDidDisappear += Connection_OnPropertyInspectorDidDisappear;
StreamDeckConnection.OnSystemDidWakeUp += StreamDeckConnection_OnSystemDidWakeUp;
}

/// <summary>
Expand All @@ -351,65 +358,71 @@ public void Dispose()
StreamDeckConnection.OnDeviceDidConnect -= Connection_OnDeviceDidConnect;
StreamDeckConnection.OnPropertyInspectorDidAppear -= Connection_OnPropertyInspectorDidAppear;
StreamDeckConnection.OnPropertyInspectorDidDisappear -= Connection_OnPropertyInspectorDidDisappear;
StreamDeckConnection.OnSystemDidWakeUp -= StreamDeckConnection_OnSystemDidWakeUp;
}


#region Event Wrappers

private void Connection_OnPropertyInspectorDidDisappear(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs<streamdeck_client_csharp.Events.PropertyInspectorDidDisappearEvent> e)
private void Connection_OnPropertyInspectorDidDisappear(object sender, SDEventReceivedEventArgs<PropertyInspectorDidDisappearEvent> e)
{
if (e.Event.Context == ContextId)
{
OnPropertyInspectorDidDisappear?.Invoke(this, new SDEventReceivedEventArgs<PropertyInspectorDidDisappear>(new PropertyInspectorDidDisappear(e.Event.Action, e.Event.Context, e.Event.Device)));
}
}

private void Connection_OnPropertyInspectorDidAppear(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs<streamdeck_client_csharp.Events.PropertyInspectorDidAppearEvent> e)
private void Connection_OnPropertyInspectorDidAppear(object sender, SDEventReceivedEventArgs<PropertyInspectorDidAppearEvent> e)
{
if (e.Event.Context == ContextId)
{
OnPropertyInspectorDidAppear?.Invoke(this, new SDEventReceivedEventArgs<PropertyInspectorDidAppear>(new PropertyInspectorDidAppear(e.Event.Action, e.Event.Context, e.Event.Device)));
}
}

private void Connection_OnDeviceDidConnect(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs<streamdeck_client_csharp.Events.DeviceDidConnectEvent> e)
private void Connection_OnDeviceDidConnect(object sender, SDEventReceivedEventArgs<DeviceDidConnectEvent> e)
{
OnDeviceDidConnect?.Invoke(this, new SDEventReceivedEventArgs<DeviceDidConnect>(new DeviceDidConnect(e.Event.DeviceInfo.ToStreamDeckDeviceInfo(e.Event.Device))));
OnDeviceDidConnect?.Invoke(this, new SDEventReceivedEventArgs<DeviceDidConnect>(new DeviceDidConnect(e.Event.DeviceInfo)));
}

private void Connection_OnDeviceDidDisconnect(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs<streamdeck_client_csharp.Events.DeviceDidDisconnectEvent> e)
private void Connection_OnDeviceDidDisconnect(object sender, SDEventReceivedEventArgs<DeviceDidDisconnectEvent> e)
{
OnDeviceDidDisconnect?.Invoke(this, new SDEventReceivedEventArgs<DeviceDidDisconnect>(new DeviceDidDisconnect(e.Event.Device)));
}

private void Connection_OnApplicationDidTerminate(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs<streamdeck_client_csharp.Events.ApplicationDidTerminateEvent> e)
private void Connection_OnApplicationDidTerminate(object sender, SDEventReceivedEventArgs<ApplicationDidTerminateEvent> e)
{
OnApplicationDidTerminate?.Invoke(this, new SDEventReceivedEventArgs<ApplicationDidTerminate>(new ApplicationDidTerminate(new Payloads.ApplicationPayload(e.Event.Payload.Application))));
}

private void Connection_OnApplicationDidLaunch(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs<streamdeck_client_csharp.Events.ApplicationDidLaunchEvent> e)
private void Connection_OnApplicationDidLaunch(object sender, SDEventReceivedEventArgs<ApplicationDidLaunchEvent> e)
{
OnApplicationDidLaunch?.Invoke(this, new SDEventReceivedEventArgs<ApplicationDidLaunch>(new ApplicationDidLaunch(new Payloads.ApplicationPayload(e.Event.Payload.Application))));
}

private void Connection_OnTitleParametersDidChange(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs<streamdeck_client_csharp.Events.TitleParametersDidChangeEvent> e)
private void Connection_OnTitleParametersDidChange(object sender, SDEventReceivedEventArgs<TitleParametersDidChangeEvent> e)
{
if (e.Event.Context == ContextId)
{
var payload = e.Event.Payload;
var newPayload = new TitleParametersPayload(payload.Settings, payload.Coordinates.ToKeyCoordinates(), payload.State, payload.Title, payload.TitleParameters.ToSDTitleParameters());
var newPayload = new TitleParametersPayload(payload.Settings, payload.Coordinates, payload.State, payload.Title, payload.TitleParameters);
OnTitleParametersDidChange?.Invoke(this, new SDEventReceivedEventArgs<TitleParametersDidChange>(new TitleParametersDidChange(e.Event.Action, e.Event.Context, e.Event.Device, newPayload)));
}
}

private void Connection_OnSendToPlugin(object sender, streamdeck_client_csharp.StreamDeckEventReceivedEventArgs<streamdeck_client_csharp.Events.SendToPluginEvent> e)
private void Connection_OnSendToPlugin(object sender, SDEventReceivedEventArgs<SendToPluginEvent> e)
{
if (e.Event.Context == ContextId)
{
OnSendToPlugin?.Invoke(this, new SDEventReceivedEventArgs<SendToPlugin>(new SendToPlugin(e.Event.Action, e.Event.Context, e.Event.Payload)));
}
}

private void StreamDeckConnection_OnSystemDidWakeUp(object sender, SDEventReceivedEventArgs<SystemDidWakeUpEvent> e)
{
OnSystemDidWakeUp?.Invoke(this, new SDEventReceivedEventArgs<SystemDidWakeUp>(new SystemDidWakeUp()));
}

#endregion
}
}
Loading

0 comments on commit 69cb52a

Please sign in to comment.