diff --git a/RESOURCES.md b/RESOURCES.md
new file mode 100644
index 0000000..db66e3f
--- /dev/null
+++ b/RESOURCES.md
@@ -0,0 +1,11 @@
+# Resources
+
+This a list of attributions and giving credit to the sources and inspiration for various elements of this project
+
+## Images
+
+### Icons
+
+
+[plugin by Galaktionoff from the Noun Project](https://thenounproject.com/search/?q=plugin&i=1692300#)
+
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/.template.config/template.json b/Templates/StreamDeck.PluginTemplate.Csharp/content/.template.config/template.json
index 108ec74..54439b2 100644
--- a/Templates/StreamDeck.PluginTemplate.Csharp/content/.template.config/template.json
+++ b/Templates/StreamDeck.PluginTemplate.Csharp/content/.template.config/template.json
@@ -34,7 +34,8 @@
"datatype": "string",
"description": "The name of the stream deck plugin.",
"defaultValue": "MyPlugin",
- "replaces": "$(PluginName)"
+ "replaces": "$(PluginName)",
+ "fileRename": "_PluginName_"
},
"uuid": {
"type": "parameter",
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/DefaultPluginAction.cs b/Templates/StreamDeck.PluginTemplate.Csharp/content/DefaultPluginAction.cs
deleted file mode 100644
index 440ed5b..0000000
--- a/Templates/StreamDeck.PluginTemplate.Csharp/content/DefaultPluginAction.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using StreamDeckLib;
-using StreamDeckLib.Messages;
-using System.Dynamic;
-using System.Threading.Tasks;
-
-namespace _StreamDeckPlugin_
-{
-
- // This value must match the UUID for the action in the manifest.json
- // file, so that it can be called from the Stream Deck.
- [ActionUuid(Uuid = "$(UUID).DefaultPluginAction")]
- internal class DefaultPluginAction : BaseStreamDeckAction
- {
- private static int _Counter = 0;
- private static bool _IsPropertyInspectorConnected = false;
-
- public override async Task OnKeyUp(StreamDeckEventPayload args)
- {
- _Counter++;
- await Manager.SetTitleAsync(args.context, _Counter.ToString());
-
- if (_Counter % 10 == 0)
- {
- await Manager.ShowAlertAsync(args.context);
- }
- else if (_Counter % 15 == 0)
- {
- await Manager.OpenUrlAsync(args.context, "https://www.bing.com");
- }
- else if (_Counter % 3 == 0)
- {
- await Manager.ShowOkAsync(args.context);
- }
- else if (_Counter % 7 == 0)
- {
- await Manager.SetImageAsync(args.context, "Fritz.png");
- }
- }
-
- public override async Task OnWillAppear(StreamDeckEventPayload args)
- {
- if (args.payload != null && args.payload.settings != null && args.payload.settings.counter != null)
- {
- _Counter = args.payload.settings.counter;
- }
- await Manager.SetTitleAsync(args.context, _Counter.ToString());
- }
-
- public override async Task OnWillDisappear(StreamDeckEventPayload args)
- {
-
- var settings = new { counter = _Counter };
-
- await Manager.SetSettingsAsync(args.context, settings);
- }
-
- public override Task OnPropertyInspectorConnected(PropertyInspectorEventPayload args)
- {
- _IsPropertyInspectorConnected = true;
- return Task.CompletedTask;
- }
-
- public override Task OnPropertyInspectorDisconnected(PropertyInspectorEventPayload args)
- {
- _IsPropertyInspectorConnected = false;
- return Task.CompletedTask;
- }
-
- public async override Task OnPropertyInspectorMessageReceived(PropertyInspectorEventPayload args)
- {
- if (args.SettingsPayloadHasProperty("starting_number"))
- {
- _Counter = args.GetSettingsPayloadValue("starting_number");
- await Manager.SetTitleAsync(args.context, _Counter.ToString());
- }
-
- }
- }
-}
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/_PluginName_Action.cs b/Templates/StreamDeck.PluginTemplate.Csharp/content/_PluginName_Action.cs
new file mode 100644
index 0000000..4ff3243
--- /dev/null
+++ b/Templates/StreamDeck.PluginTemplate.Csharp/content/_PluginName_Action.cs
@@ -0,0 +1,67 @@
+using StreamDeckLib;
+using StreamDeckLib.Messages;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace _StreamDeckPlugin_
+{
+ [ActionUuid(Uuid="$(UUID)")]
+ public class $(PluginName)Action : BaseStreamDeckActionWithSettingsModel
+ {
+ // Cheer 342 cpayette 15/2/19
+ // Cheer 100 devlead 15/2/19
+ // Cheer 200 kevin_downs Jan 11, 2019
+ // Cheer 401 cpayette Jan 15, 2019
+ // Cheer 2501 themikejolley Jan 15, 2019
+ // Cheer 100 wolfgang_blitz Jan 15, 2019
+ // Cheer 157 jongalloway Jan 15, 2019
+ // Cheer 100 johanb Jan 15, 2019
+ // Cheer 400 faniereynders Jan 15, 2019
+ // Cheer 100 TomMcQ Jan 15, 2019
+ // Cheer 361 Crazy240sx Jan 15, 2019
+ // Cheer 600 yarrgh Jan 15, 2019
+ // Cheer 1030 kulu83 Jan 15, 2019
+ // Cheer 2500 Auth0Bobby Jan 15, 2019
+
+ public override async Task OnKeyUp(StreamDeckEventPayload args)
+ {
+ SettingsModel.Counter++;
+ await Manager.SetTitleAsync(args.context, SettingsModel.Counter.ToString());
+
+ if (SettingsModel.Counter % 10 == 0)
+ {
+ await Manager.ShowAlertAsync(args.context);
+ }
+ else if (SettingsModel.Counter % 15 == 0)
+ {
+ await Manager.OpenUrlAsync(args.context, "https://www.bing.com");
+ }
+ else if (SettingsModel.Counter % 3 == 0)
+ {
+ await Manager.ShowOkAsync(args.context);
+ }
+ else if (SettingsModel.Counter % 7 == 0)
+ {
+ await Manager.SetImageAsync(args.context, "images/Fritz.png");
+ }
+
+ //update settings
+ await Manager.SetSettingsAsync(args.context, SettingsModel);
+ }
+
+ public override async Task OnDidReceiveSettings(StreamDeckEventPayload args)
+ {
+ await base.OnDidReceiveSettings(args);
+ await Manager.SetTitleAsync(args.context, SettingsModel.Counter.ToString());
+ }
+
+ public override async Task OnWillAppear(StreamDeckEventPayload args)
+ {
+ await base.OnWillAppear(args);
+ await Manager.SetTitleAsync(args.context, SettingsModel.Counter.ToString());
+ }
+
+ }
+}
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/_StreamDeckPlugin_.cmd b/Templates/StreamDeck.PluginTemplate.Csharp/content/_StreamDeckPlugin_.cmd
new file mode 100644
index 0000000..65c672e
--- /dev/null
+++ b/Templates/StreamDeck.PluginTemplate.Csharp/content/_StreamDeckPlugin_.cmd
@@ -0,0 +1,2 @@
+cd %appdata%\Elgato\StreamDeck\Plugins\$(UUID)
+_StreamDeckPlugin_.exe -break %*
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/_StreamDeckPlugin_.csproj b/Templates/StreamDeck.PluginTemplate.Csharp/content/_StreamDeckPlugin_.csproj
index aad5c36..21ab1ef 100644
--- a/Templates/StreamDeck.PluginTemplate.Csharp/content/_StreamDeckPlugin_.csproj
+++ b/Templates/StreamDeck.PluginTemplate.Csharp/content/_StreamDeckPlugin_.csproj
@@ -65,6 +65,33 @@
PreserveNewest
+
+ PreserveNewest
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+ PreserveNewest
+
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/images/Fritz.png b/Templates/StreamDeck.PluginTemplate.Csharp/content/images/Fritz.png
new file mode 100644
index 0000000..e0f8970
Binary files /dev/null and b/Templates/StreamDeck.PluginTemplate.Csharp/content/images/Fritz.png differ
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/images/category/categoryIcon.png b/Templates/StreamDeck.PluginTemplate.Csharp/content/images/category/categoryIcon.png
new file mode 100644
index 0000000..2132054
Binary files /dev/null and b/Templates/StreamDeck.PluginTemplate.Csharp/content/images/category/categoryIcon.png differ
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/images/category/categoryIcon@2x.png b/Templates/StreamDeck.PluginTemplate.Csharp/content/images/category/categoryIcon@2x.png
new file mode 100644
index 0000000..e8541bb
Binary files /dev/null and b/Templates/StreamDeck.PluginTemplate.Csharp/content/images/category/categoryIcon@2x.png differ
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/manifest.json b/Templates/StreamDeck.PluginTemplate.Csharp/content/manifest.json
index 9b5f934..a3224c0 100644
--- a/Templates/StreamDeck.PluginTemplate.Csharp/content/manifest.json
+++ b/Templates/StreamDeck.PluginTemplate.Csharp/content/manifest.json
@@ -2,7 +2,7 @@
"Actions": [
{
"Icon": "images/actionIcon",
- "Name": "$(PluginName)",
+ "Name": "$(PluginName)Action",
"States": [
{
"Image": "images/actionDefaultImage",
@@ -15,7 +15,10 @@
"UUID": "$(UUID).DefaultPluginAction"
}
],
- "Author": "",
+ "Category": "Your Plugin Category",
+ "CategoryIcon": "images/category/categoryIcon.png",
+ "Disabled": false,
+ "Author": "Your Name",
"CodePathWin": "_StreamDeckPlugin_.exe",
"CodePathMac": "_StreamDeckPlugin_",
"PropertyInspectorPath": "property_inspector/property_inspector.html",
@@ -24,7 +27,11 @@
"Icon": "images/pluginIcon",
"URL": "https://www.elgato.com/gaming/stream-deck",
"Version": "1.0",
- "OS": [
+ "SDKVersion": 2,
+ "Software": {
+ "MinimumVersion": "4.1"
+ },
+ "OS": [
{
"Platform": "mac",
"MinimumVersion" : "10.11"
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/models/CounterSettingsModel.cs b/Templates/StreamDeck.PluginTemplate.Csharp/content/models/CounterSettingsModel.cs
new file mode 100644
index 0000000..4095586
--- /dev/null
+++ b/Templates/StreamDeck.PluginTemplate.Csharp/content/models/CounterSettingsModel.cs
@@ -0,0 +1,7 @@
+namespace _StreamDeckPlugin_.Models
+{
+ public class CounterSettingsModel
+ {
+ public int Counter { get; set; } = 0;
+ }
+}
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/property_inspector/js/property-inspector.js b/Templates/StreamDeck.PluginTemplate.Csharp/content/property_inspector/js/property-inspector.js
index 0406265..9282c63 100644
--- a/Templates/StreamDeck.PluginTemplate.Csharp/content/property_inspector/js/property-inspector.js
+++ b/Templates/StreamDeck.PluginTemplate.Csharp/content/property_inspector/js/property-inspector.js
@@ -2,39 +2,60 @@
// as well as some info about our plugin, as sent by Stream Deck software
var websocket = null,
uuid = null,
- inInfo = null,
- actionInfo = {};
+ inInfo = null,
+ actionInfo = {},
+ settingsModel = {
+ Counter: 0
+ };
-function connectSocket(inPort, inUUID, inRegisterEvent, inInfo, inActionInfo) {
+function connectElgatoStreamDeckSocket(inPort, inUUID, inRegisterEvent, inInfo, inActionInfo) {
uuid = inUUID;
actionInfo = JSON.parse(inActionInfo);
inInfo = JSON.parse(inInfo);
websocket = new WebSocket('ws://localhost:' + inPort);
+ //initialize values
+ if (actionInfo.payload.settings.settingsModel) {
+ settingsModel.Counter = actionInfo.payload.settings.settingsModel.Counter;
+ }
+
+ document.getElementById('txtCounterValue').value = settingsModel.Counter;
+
websocket.onopen = function () {
- var json = { event: inRegisterEvent, uuid: inUUID };
- // register property inspector to Stream Deck
- websocket.send(JSON.stringify(json));
- sendValueToPlugin('propertyInspectorConnected', 'property_inspector');
- };
-}
+ var json = { event: inRegisterEvent, uuid: inUUID };
+ // register property inspector to Stream Deck
+ websocket.send(JSON.stringify(json));
-window.addEventListener('unload', function (event) {
- sendValueToPlugin('propertyInspectorDisconnected', 'property_inspector');
-});
+ };
-function sendValueToPlugin(value, param) {
- if (websocket) {
- const json = {
- "action": actionInfo['action'],
- "event": "sendToPlugin",
- "context": uuid,
- "payload": {
- [param]: value
- }
- };
- websocket.send(JSON.stringify(json));
+ websocket.onmessage = function (evt) {
+ // Received message from Stream Deck
+ var jsonObj = JSON.parse(evt.data);
+ var sdEvent = jsonObj['event'];
+ switch (sdEvent) {
+ case "didReceiveSettings":
+ if (jsonObj.payload.settings.settingsModel.Counter) {
+ settingsModel.Counter = jsonObj.payload.settings.settingsModel.Counter;
+ document.getElementById('txtCounterValue').value = settingsModel.Counter;
+ }
+ break;
+ default:
+ break;
}
+ };
}
+const setSettings = (value, param) => {
+ if (websocket) {
+ settingsModel[param] = value;
+ var json = {
+ "event": "setSettings",
+ "context": uuid,
+ "payload": {
+ "settingsModel": settingsModel
+ }
+ };
+ websocket.send(JSON.stringify(json));
+ }
+};
diff --git a/Templates/StreamDeck.PluginTemplate.Csharp/content/property_inspector/property_inspector.html b/Templates/StreamDeck.PluginTemplate.Csharp/content/property_inspector/property_inspector.html
index cca8caa..8956485 100644
--- a/Templates/StreamDeck.PluginTemplate.Csharp/content/property_inspector/property_inspector.html
+++ b/Templates/StreamDeck.PluginTemplate.Csharp/content/property_inspector/property_inspector.html
@@ -14,9 +14,9 @@
Elgato SDK Documentation -> https://developer.elgato.com/documentation/stream-deck/sdk/property-inspector/
-->
-
diff --git a/src/SamplePlugin/MySampleAction.cs b/src/SamplePlugin/MySampleAction.cs
deleted file mode 100644
index ccdc0ac..0000000
--- a/src/SamplePlugin/MySampleAction.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using Microsoft.Extensions.Logging;
-using SamplePlugin.Models;
-using Serilog.Core;
-using StreamDeckLib;
-using StreamDeckLib.Messages;
-using System;
-using System.Threading.Tasks;
-
-namespace SamplePlugin
-{
- [ActionUuid(Uuid = "com.csharpfritz.samplePlugin.action")]
- internal class MySampleAction : BaseStreamDeckAction
- {
-
- // Cheer 200 kevin_downs Jan 11, 2019
- // Cheer 401 cpayette Jan 15, 2019
- // Cheer 2501 themikejolley Jan 15, 2019
- // Cheer 100 wolfgang_blitz Jan 15, 2019
- // Cheer 157 jongalloway Jan 15, 2019
- // Cheer 100 johanb Jan 15, 2019
- // Cheer 400 faniereynders Jan 15, 2019
- // Cheer 100 TomMcQ Jan 15, 2019
- // Cheer 361 Crazy240sx Jan 15, 2019
- // Cheer 600 yarrgh Jan 15, 2019
- // Cheer 1030 kulu83 Jan 15, 2019
- // Cheer 2500 Auth0Bobby Jan 15, 2019
-
- private SampleActionSettingsModel _settingsModel = new SampleActionSettingsModel();
- private bool _IsPropertyInspectorConnected = false;
-
- public override async Task OnKeyUp(StreamDeckEventPayload args)
- {
-
- // Cheer 342 cpayette 15/2/19
- // Cheer 100 devlead 15/2/19
-
- Logger.LogTrace($"Button pressed: {args}");
-
- _settingsModel.Counter++;
- await Manager.SetTitleAsync(args.context, _settingsModel.Counter.ToString());
-
- if (_settingsModel.Counter % 10 == 0)
- {
- await Manager.ShowAlertAsync(args.context);
- }
- else if (_settingsModel.Counter % 15 == 0)
- {
- await Manager.OpenUrlAsync(args.context, "https://www.bing.com");
- }
- else if (_settingsModel.Counter % 3 == 0)
- {
- await Manager.ShowOkAsync(args.context);
- }
- else if (_settingsModel.Counter == 0)
- {
- await Manager.SetImageAsync(args.context, "images/Fritz.png");
- }
-
- await Manager.SendToPropertyInspectorAsync(args.context, _settingsModel);
- }
-
- public override async Task OnWillAppear(StreamDeckEventPayload args)
- {
-
- if (args.PayloadSettingsHasProperty("Counter"))
- {
- _settingsModel.Counter = args.GetPayloadSettingsValue("Counter");
- }
- await Manager.SetTitleAsync(args.context, _settingsModel.Counter.ToString());
- }
-
- public override async Task OnWillDisappear(StreamDeckEventPayload args)
- {
- await Manager.SetSettingsAsync(args.context, _settingsModel);
- }
-
- public override async Task OnPropertyInspectorConnected(PropertyInspectorEventPayload args)
- {
- _IsPropertyInspectorConnected = true;
- await Manager.SendToPropertyInspectorAsync(args.context, _settingsModel);
- }
-
- public override Task OnPropertyInspectorDisconnected(PropertyInspectorEventPayload args)
- {
- _IsPropertyInspectorConnected = false;
- return Task.CompletedTask;
- }
-
- public override async Task OnPropertyInspectorMessageReceived(PropertyInspectorEventPayload args)
- {
- if (args.SettingsPayloadHasProperty("Counter"))
- {
- _settingsModel.Counter = args.GetSettingsPayloadValue("Counter");
-
- }
- await Manager.SetTitleAsync(args.context, _settingsModel.Counter.ToString());
-
- }
- }
-}
diff --git a/src/SamplePlugin/MySamplePluginAction.cs b/src/SamplePlugin/MySamplePluginAction.cs
new file mode 100644
index 0000000..8b03973
--- /dev/null
+++ b/src/SamplePlugin/MySamplePluginAction.cs
@@ -0,0 +1,65 @@
+using SamplePlugin.Models;
+using StreamDeckLib;
+using StreamDeckLib.Messages;
+using System.Threading.Tasks;
+
+namespace SamplePlugin
+{
+ [ActionUuid(Uuid = "com.csharpfritz.samplePlugin.action")]
+ public class MySamplePluginAction : BaseStreamDeckActionWithSettingsModel
+ {
+ // Cheer 342 cpayette 15/2/19
+ // Cheer 100 devlead 15/2/19
+ // Cheer 200 kevin_downs Jan 11, 2019
+ // Cheer 401 cpayette Jan 15, 2019
+ // Cheer 2501 themikejolley Jan 15, 2019
+ // Cheer 100 wolfgang_blitz Jan 15, 2019
+ // Cheer 157 jongalloway Jan 15, 2019
+ // Cheer 100 johanb Jan 15, 2019
+ // Cheer 400 faniereynders Jan 15, 2019
+ // Cheer 100 TomMcQ Jan 15, 2019
+ // Cheer 361 Crazy240sx Jan 15, 2019
+ // Cheer 600 yarrgh Jan 15, 2019
+ // Cheer 1030 kulu83 Jan 15, 2019
+ // Cheer 2500 Auth0Bobby Jan 15, 2019
+
+ public override async Task OnKeyUp(StreamDeckEventPayload args)
+ {
+ SettingsModel.Counter++;
+ await Manager.SetTitleAsync(args.context, SettingsModel.Counter.ToString());
+
+ if (SettingsModel.Counter % 10 == 0)
+ {
+ await Manager.ShowAlertAsync(args.context);
+ }
+ else if (SettingsModel.Counter % 15 == 0)
+ {
+ await Manager.OpenUrlAsync(args.context, "https://www.bing.com");
+ }
+ else if (SettingsModel.Counter % 3 == 0)
+ {
+ await Manager.ShowOkAsync(args.context);
+ }
+ else if (SettingsModel.Counter % 7 == 0)
+ {
+ await Manager.SetImageAsync(args.context, "images/Fritz.png");
+ }
+
+ //update settings
+ await Manager.SetSettingsAsync(args.context, SettingsModel);
+ }
+
+ public override async Task OnDidReceiveSettings(StreamDeckEventPayload args)
+ {
+ await base.OnDidReceiveSettings(args);
+ await Manager.SetTitleAsync(args.context, SettingsModel.Counter.ToString());
+ }
+
+ public override async Task OnWillAppear(StreamDeckEventPayload args)
+ {
+ await base.OnWillAppear(args);
+ await Manager.SetTitleAsync(args.context, SettingsModel.Counter.ToString());
+ }
+
+ }
+}
diff --git a/src/SamplePlugin/Program.cs b/src/SamplePlugin/Program.cs
index 619c8b3..25979a6 100644
--- a/src/SamplePlugin/Program.cs
+++ b/src/SamplePlugin/Program.cs
@@ -1,30 +1,24 @@
-using StreamDeckLib;
+using StreamDeckLib;
using System.Threading.Tasks;
namespace SamplePlugin
{
-
class Program
{
-
// Cheer 200 careypayette February 14, 2019
// Cheer 100 roberttables February 14, 2019
// Cheer 100 careypayette February 15, 2019
// Cheer 100 devlead 15/2/2019
-
static async Task Main(string[] args)
{
-
using (var config = StreamDeckLib.Config.ConfigurationBuilder.BuildDefaultConfiguration(args))
{
-
await ConnectionManager.Initialize(args, config.LoggerFactory)
- .RegisterAllActions(typeof(Program).Assembly)
- .StartAsync();
-
+ .RegisterAllActions(typeof(Program).Assembly)
+ .StartAsync();
}
-
}
+
}
}
diff --git a/src/SamplePlugin/SamplePlugin.csproj b/src/SamplePlugin/SamplePlugin.csproj
index f68b9ea..32f25ad 100644
--- a/src/SamplePlugin/SamplePlugin.csproj
+++ b/src/SamplePlugin/SamplePlugin.csproj
@@ -77,16 +77,7 @@
PreserveNewest
- Always
-
-
- PreserveNewest
-
-
- PreserveNewest
-
-
- PreserveNewest
+ PreserveNewest
diff --git a/src/SamplePlugin/images/category/categoryIcon.png b/src/SamplePlugin/images/category/categoryIcon.png
new file mode 100644
index 0000000..2132054
Binary files /dev/null and b/src/SamplePlugin/images/category/categoryIcon.png differ
diff --git a/src/SamplePlugin/images/category/categoryIcon@2x.png b/src/SamplePlugin/images/category/categoryIcon@2x.png
new file mode 100644
index 0000000..e8541bb
Binary files /dev/null and b/src/SamplePlugin/images/category/categoryIcon@2x.png differ
diff --git a/src/SamplePlugin/manifest.json b/src/SamplePlugin/manifest.json
index fe86212..22255fc 100644
--- a/src/SamplePlugin/manifest.json
+++ b/src/SamplePlugin/manifest.json
@@ -1,20 +1,23 @@
{
- "Actions": [
- {
- "Icon": "images/actionIcon",
- "Name": "SamplePlugin",
- "States": [
- {
- "Image": "images/actionDefaultImage",
- "TitleAlignment": "middle",
- "FontSize": "16"
- }
- ],
- "SupportedInMultiActions": false,
- "Tooltip": "How many times did you get pwned today? Keep track with this counter.",
- "UUID": "com.csharpfritz.samplePlugin.action"
- }
- ],
+ "Actions": [
+ {
+ "Icon": "images/actionIcon",
+ "Name": "SamplePluginAction",
+ "States": [
+ {
+ "Image": "images/actionDefaultImage",
+ "TitleAlignment": "middle",
+ "FontSize": "16"
+ }
+ ],
+ "SupportedInMultiActions": false,
+ "Tooltip": "How many times did you get pwned today? Keep track with this counter.",
+ "UUID": "com.csharpfritz.samplePlugin.action"
+ }
+ ],
+ "Category": "Fritz & Friends",
+ "CategoryIcon": "images/category/categoryIcon.png",
+ "Disabled": false,
"Author": "Jeffrey T. Fritz",
"CodePathWin": "SamplePlugin.cmd",
"CodePathMac": "SamplePlugin",
@@ -22,8 +25,12 @@
"Description": "The Sample Plugin",
"Name": "Sample Plugin",
"Icon": "images/pluginIcon",
- "URL": "https://www.elgato.com/gaming/stream-deck",
- "Version": "1.2",
+ "URL": "https://github.com/FritzAndFriends",
+ "Version": "1.3",
+ "SDKVersion": 2,
+ "Software": {
+ "MinimumVersion": "4.1"
+ },
"OS": [
{
"Platform": "mac",
diff --git a/src/SamplePlugin/models/CounterSettingsModel.cs b/src/SamplePlugin/models/CounterSettingsModel.cs
new file mode 100644
index 0000000..74e0551
--- /dev/null
+++ b/src/SamplePlugin/models/CounterSettingsModel.cs
@@ -0,0 +1,7 @@
+namespace SamplePlugin.Models
+{
+ public class CounterSettingsModel
+ {
+ public int Counter { get; set; } = 0;
+ }
+}
diff --git a/src/SamplePlugin/models/SampleActionSettingsModel.cs b/src/SamplePlugin/models/SampleActionSettingsModel.cs
new file mode 100644
index 0000000..1f07685
--- /dev/null
+++ b/src/SamplePlugin/models/SampleActionSettingsModel.cs
@@ -0,0 +1,7 @@
+namespace SamplePlugin.Models
+{
+ public class SampleActionSettingsModel
+ {
+ public int Counter { get; set; } = 0;
+ }
+}
diff --git a/src/SamplePlugin/property_inspector/js/property-inspector.js b/src/SamplePlugin/property_inspector/js/property-inspector.js
index faf71e2..8e090fc 100644
--- a/src/SamplePlugin/property_inspector/js/property-inspector.js
+++ b/src/SamplePlugin/property_inspector/js/property-inspector.js
@@ -1,5 +1,5 @@
// global websocket, used to communicate from/to Stream Deck software
-// as well as some info about our plugin, as sent by Stream Deck software
+// as well as some info about our plugin, as sent by Stream Deck software
var websocket = null,
uuid = null,
inInfo = null,
@@ -8,68 +8,53 @@ var websocket = null,
Counter: 0
};
-function connectSocket(inPort, inUUID, inRegisterEvent, inInfo, inActionInfo) {
+function connectElgatoStreamDeckSocket(inPort, inUUID, inRegisterEvent, inInfo, inActionInfo) {
uuid = inUUID;
actionInfo = JSON.parse(inActionInfo);
inInfo = JSON.parse(inInfo);
websocket = new WebSocket('ws://localhost:' + inPort);
+ //initialize values
+ if (actionInfo.payload.settings.settingsModel) {
+ settingsModel.Counter = actionInfo.payload.settings.settingsModel.Counter;
+ }
+
+ document.getElementById('txtCounterValue').value = settingsModel.Counter;
+
websocket.onopen = function () {
- var json = { event: inRegisterEvent, uuid: inUUID };
- // register property inspector to Stream Deck
- websocket.send(JSON.stringify(json));
- sendEventToPlugin('propertyInspectorConnected');
+ var json = { event: inRegisterEvent, uuid: inUUID };
+ // register property inspector to Stream Deck
+ websocket.send(JSON.stringify(json));
+
};
websocket.onmessage = function (evt) {
- // Received message from Stream Deck
- var jsonObj = JSON.parse(evt.data);
- var sdEvent = jsonObj['event'];
- switch (sdEvent) {
- case "sendToPropertyInspector":
- if (jsonObj.payload.settingsModel.Counter) {
- settingsModel.Counter = jsonObj.payload.settingsModel.Counter;
- document.getElementById('txtCounterValue').value = settingsModel.Counter;
+ // Received message from Stream Deck
+ var jsonObj = JSON.parse(evt.data);
+ var sdEvent = jsonObj['event'];
+ switch (sdEvent) {
+ case "didReceiveSettings":
+ if (jsonObj.payload.settings.settingsModel.Counter) {
+ settingsModel.Counter = jsonObj.payload.settings.settingsModel.Counter;
+ document.getElementById('txtCounterValue').value = settingsModel.Counter;
+ }
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
- }
};
}
-window.addEventListener('unload', function (event) {
- sendEventToPlugin('propertyInspectorDisconnected');
-});
-
-function sendValueToPlugin(value, param) {
- if (websocket) {
- settingsModel[param] = value;
- const json = {
- "action": actionInfo['action'],
- "event": "sendToPlugin",
- "context": uuid,
- "payload": {
- "settingsModel": settingsModel
- }
- };
- websocket.send(JSON.stringify(json));
- }
-}
-
-function sendEventToPlugin(value, param) {
+function setSettings(value, param) {
if (websocket) {
settingsModel[param] = value;
- const json = {
- "action": actionInfo['action'],
- "event": "sendToPlugin",
+ var json = {
+ "event": "setSettings",
"context": uuid,
"payload": {
- "property_inspector": value
+ "settingsModel": settingsModel
}
};
websocket.send(JSON.stringify(json));
}
-}
-
-
+};
diff --git a/src/SamplePlugin/property_inspector/property_inspector.html b/src/SamplePlugin/property_inspector/property_inspector.html
index f88f6ed..7ed2669 100644
--- a/src/SamplePlugin/property_inspector/property_inspector.html
+++ b/src/SamplePlugin/property_inspector/property_inspector.html
@@ -13,10 +13,10 @@
and
Elgato SDK Documentation -> https://developer.elgato.com/documentation/stream-deck/sdk/property-inspector/
-->
-
-
diff --git a/src/StreamDeckLib.Test/ActionManager_UnitTests.cs b/src/StreamDeckLib.Test/ActionManager_UnitTests.cs
new file mode 100644
index 0000000..6834f99
--- /dev/null
+++ b/src/StreamDeckLib.Test/ActionManager_UnitTests.cs
@@ -0,0 +1,123 @@
+using System;
+using Xunit;
+
+namespace StreamDeckLib.Test
+{
+
+ public class ActionManagerShould
+ {
+
+ [Fact]
+ public void ThrowActionNotRegisteredException_WhenRetrievingAnUnregisteredAction()
+ {
+ // Arrange
+ using (var SUT = new ActionManager(null))
+ {
+ // Act
+
+ // Assert
+ Assert.Throws(() => SUT.GetAction("UUID1"));
+
+ }
+ }
+
+ [Fact]
+ public void ShowOneSingleActionRegistered_WhenRegisteringOnlyOneAction()
+ {
+ //
+ // Arrange
+ //
+
+ var testAction = new StubAction();
+ BaseStreamDeckAction returnedAction;
+
+ //
+ // Act
+ //
+ using (var SUT = new ActionManager(null))
+ {
+
+ SUT.RegisterAction("UUID1");
+ returnedAction = SUT.GetActionInstance("UUID1");
+ }
+
+ //
+ // Assert
+ //
+ Assert.NotNull(returnedAction);
+
+ Assert.IsType(returnedAction);
+ }
+
+
+
+ [Fact]
+ public void ShouldReturnTrue_WhenInquiredAboutRegistrationOfRegisteredActionUUID()
+ {
+ //
+ // Arrange
+ //
+ using (var SUT = new ActionManager(null))
+ {
+
+ //
+ // Act
+ //
+ SUT.RegisterAction("UUID1");
+
+ //
+ // Assert
+ //
+ Assert.True(SUT.IsActionRegistered("UUID1"));
+
+ }
+ }
+
+
+ [Fact]
+ public void ShouldReturnFalse_WhenInquiredAboutRegistrationOfUnregisteredActionUUID()
+ {
+ //
+ // Arrange
+ //
+ using (var SUT = new ActionManager(null))
+ {
+
+ //
+ // Act
+ //
+ SUT.RegisterAction("UUID1");
+
+ //
+ // Assert
+ //
+ Assert.False(SUT.IsActionRegistered("UUID2"));
+
+ }
+ }
+
+
+
+ [Fact]
+ public void ShouldReturnTrue_WhenInquiredAboutRegistrationOfActionUUIDWithDifferentCasing()
+ {
+ //
+ // Arrange
+ //
+ using (var SUT = new ActionManager(null))
+ {
+
+ //
+ // Act
+ //
+ SUT.RegisterAction("UUID1");
+
+ //
+ // Assert
+ //
+ Assert.True(SUT.IsActionRegistered("uuID1"));
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/StreamDeckLib.Test/ConnectionManager_UnitTests.cs b/src/StreamDeckLib.Test/ConnectionManager_UnitTests.cs
index 9ea6167..47b56ed 100644
--- a/src/StreamDeckLib.Test/ConnectionManager_UnitTests.cs
+++ b/src/StreamDeckLib.Test/ConnectionManager_UnitTests.cs
@@ -23,51 +23,62 @@ public void ThrowAnArgumentException_WhenInitializedWithEmptyArgs()
action.Should().Throw();
}
+ [Fact]
+ public async Task ShouldRegisterEvent_WhenInitializedWithCorrectArgs()
+ {
+ // Arrange
+ var stub = new StubProxy()
+ {
+ InspectRegister = (e, uuid) =>
+ {
+ Assert.Equal(StubProxy.TEST_EVENT, e);
+ Assert.Equal(uuid, uuid);
+ }
+ };
+
+ // Act
+ var tokenSource = new CancellationTokenSource();
+ var task = ConnectionManager.Initialize(StubProxy.ValidCommandLineArguments, null, stub)
+ .StartAsync(tokenSource.Token);
+
+ // Assert
+ Assert.Null(task.Exception);
+ tokenSource.Cancel();
+
+ }
+
+
[Fact]
- public async Task ShouldRegisterEvent_WhenInitializedWithCorrectArgs()
+ public async Task ShouldRegisterAllActions_WhenRegisteringAllActions()
{
- // Arrange
- var stub = new StubProxy()
- {
- InspectRegister = (e, uuid) =>
- {
- Assert.Equal(StubProxy.TEST_EVENT, e);
- Assert.Equal(uuid, uuid);
- }
- };
- // Act
- var tokenSource = new CancellationTokenSource();
- var task = ConnectionManager.Initialize(StubProxy.ValidCommandLineArguments, null, stub)
- .StartAsync(tokenSource.Token);
-
- // Assert
- Assert.Null(task.Exception);
- tokenSource.Cancel();
+ Func action = () => ConnectionManager.Initialize(StubProxy.ValidCommandLineArguments)
+ .RegisterAllActions(this.GetType().Assembly);
- }
+ action.Should()
+ .NotThrow("No problems when registering All Actions");
- //[Fact]
- //public async Task ShouldThrowArgumentNullException_WhenRegisteringANullAction()
- //{
- // //
- // // Arrange
- // //
+ }
- // Func action = () => ConnectionManager.Initialize(StubProxy.ValidCommandLineArguments)
- // .RegisterAction(null);
+ [Fact]
+ public async Task ShouldHaveConnectionManagerAssigned_WhenGettingAnActionInstance()
+ {
+ var cm = ConnectionManager.Initialize(StubProxy.ValidCommandLineArguments)
+ .RegisterActionType("Unique_Action_ID_1", typeof(StubAction));
+ var action = cm.GetInstanceOfAction("FAKECONTEXT", "Unique_Action_ID_1") as StubAction;
+ action.GetConnectionManager().Should().NotBeNull("An action must have a connection manager assigned");
- // //
- // // Act
- // //
- // action.
+ }
- // //
- // // Assert
- // //
- // Should().Throw("A null BaseStreamDeckAction can not and should not be registered.");
- //}
+ [Fact]
+ public async Task ShouldHaveLoggerAssigned_WhenGettingAnActionInstance()
+ {
+ var cm = ConnectionManager.Initialize(StubProxy.ValidCommandLineArguments)
+ .RegisterActionType("Unique_Action_ID_1", typeof(StubAction));
+ var action = cm.GetInstanceOfAction("FAKECONTEXT", "Unique_Action_ID_1") as StubAction;
+ action.Logger.Should().NotBeNull("An action must have a logger assigned");
+ }
[Fact]
@@ -107,47 +118,33 @@ public async Task ShouldThrowDuplicateActionRegistrationException_WhenRegisterin
// Assert
//
- //TODO: Wording? "unique UUID" is like saying "PIN number". It's "just" a test, but still syntactically incorrect.
+ //TODO: Wording? "unique UUID" is like saying "PIN number". It's "just" a test, but still syntactically incorrect.
action.Should()
.Throw("each BaseStreamDeckAction type should have its own unique UUID.");
}
- //[Fact]
- //public async Task ShouldNotThrowAnyExceptions_WhenRegistringMultipleUniqueActions()
- //{
- // //
- // // Arrange
- // //
-
-
- // Func action = () => ConnectionManager.Initialize(StubProxy.ValidCommandLineArguments)
- // .RegisterAction(new StubAction("Unique_Action_ID_1"))
- // .RegisterAction(new StubAction("Unique_Action_ID_2"));
-
-
- // //
- // // Assert
- // //
-
- // //TODO: Wording? "unique UUID" is like saying "PIN number". It's "just" a test, but still syntactically incorrect.
- // action.Should()
- // .NotThrow("registering multiple unique actions is valid");
- //}
-
[Fact]
- public async Task ShouldRegisterAllActions_WhenRegisteringAllActions()
+ public async Task ShouldNotThrowAnyExceptions_WhenRegistringMultipleUniqueActions()
{
+ //
+ // Arrange
+ //
- Func action = () => ConnectionManager.Initialize(StubProxy.ValidCommandLineArguments)
- .RegisterAllActions(this.GetType().Assembly);
- action.Should()
- .NotThrow("No problems when registering All Actions");
+ Func action = () => ConnectionManager.Initialize(StubProxy.ValidCommandLineArguments)
+ .RegisterActionType("com.csharpfritz.samplePlugin.action", typeof(StubAction))
+ .RegisterActionType("com.csharpfritz.samplePlugin.action2", typeof(StubAction));
- }
+ //
+ // Assert
+ //
+ //TODO: Wording? "unique UUID" is like saying "PIN number". It's "just" a test, but still syntactically incorrect.
+ action.Should()
+ .NotThrow("registering multiple unique actions is valid");
+ }
}
diff --git a/src/StreamDeckLib.Test/Stubs/StubAction.cs b/src/StreamDeckLib.Test/Stubs/StubAction.cs
index e2d1d42..cb1c694 100644
--- a/src/StreamDeckLib.Test/Stubs/StubAction.cs
+++ b/src/StreamDeckLib.Test/Stubs/StubAction.cs
@@ -1,9 +1,15 @@
+using System;
+
namespace StreamDeckLib.Test
{
- [ActionUuid(Uuid ="Test UUID")]
+ [ActionUuid(Uuid = "Test UUID")]
public class StubAction : BaseStreamDeckAction
{
+ internal ConnectionManager GetConnectionManager()
+ {
+ return this.Manager;
+ }
}
}
diff --git a/src/StreamDeckLib/ActionManager.cs b/src/StreamDeckLib/ActionManager.cs
new file mode 100644
index 0000000..0c1a616
--- /dev/null
+++ b/src/StreamDeckLib/ActionManager.cs
@@ -0,0 +1,319 @@
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Reflection;
+
+namespace StreamDeckLib
+{
+
+ public partial class ActionManager : IDisposable
+ {
+ #region Type and instance properties
+
+ // We will use a string equality comparer for our dictionaries which ignores case and is for invariant culture.
+ private static readonly IEqualityComparer _StringEqualityComparer = StringComparer.Create(CultureInfo.InvariantCulture, true);
+
+ //string is the action UUID, type is the class type of the action
+ private readonly Dictionary _Actions;
+
+ //string is the context, there will only ever be one action per context
+ private readonly Dictionary _ActionInstances;
+
+ // The logger we will receive when being instantiated. Defaults to a NullLogger is none is specified.
+ private readonly ILogger _Logger;
+
+ private ConnectionManager _ConnectionManager;
+
+ #endregion
+
+
+ #region Constructors
+
+ private ActionManager()
+ {
+ this._Actions = new Dictionary(_StringEqualityComparer);
+ this._ActionInstances = new Dictionary(_StringEqualityComparer);
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// An instance of a logger ( class.
+ public ActionManager(ConnectionManager manager, ILogger logger = null) : this()
+ {
+ this._Logger = logger ?? NullLoggerFactory.Instance.CreateLogger(nameof(ActionManager));
+ this._ConnectionManager = manager;
+ }
+
+ #endregion
+
+
+ #region Action registration methods
+
+
+ ///
+ /// Registers an action type for a given UUID.
+ ///
+ /// The instance of .
+ /// The UUID for the action.
+ /// The type to be registered for the . Must inherit from .
+ public ActionManager RegisterAction(string actionUUID)
+ where TActionType : BaseStreamDeckAction
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(RegisterAction)}(string)");
+
+ this._Actions.Add(actionUUID, typeof(TActionType));
+ return this;
+ }
+
+
+ ///
+ /// Registers an action type for a given UUID.
+ ///
+ /// The instance of .
+ /// The UUID for the action.
+ /// The type to be registered for the . Must inherit from .
+ /// If the does not inherit from ,
+ /// a exception is thrown.
+ public ActionManager RegisterActionType(string actionUuid, Type actionType)
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(RegisterActionType)}(string, Type)");
+
+ // Check that we've got a UUID to use for registration.
+ if (string.IsNullOrWhiteSpace(actionUuid))
+ {
+ throw new IncompleteActionDefinitionException($"The UUID for the \"{actionType.Name}\" action was not specified.");
+ }
+
+ if (_Actions.ContainsKey(actionUuid))
+ {
+ throw new DuplicateActionRegistrationException(actionUuid);
+ }
+
+ // Ensure that the type we're registering inherits from BaseStreamDeckAction.
+ if (!actionType.IsSubclassOf(typeof(BaseStreamDeckAction)))
+ {
+ throw new TypeDoesNotInheritFromBaseStreamDeckAction(actionType.Name, actionType.FullName, actionType.Assembly.FullName);
+ }
+
+ this._Actions.Add(actionUuid, actionType);
+ return this;
+ }
+
+
+ ///
+ /// Registers all actions which are decorated with an
+ /// withn a given .
+ ///
+ /// The instance of .
+ /// The from within which actions are to be registered.
+ public ActionManager RegisterAllActions(Assembly actionsAssembly)
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(RegisterAllActions)}(assembly)");
+
+ var actions = actionsAssembly.GetTypes().Where(type => Attribute.IsDefined(type, typeof(ActionUuidAttribute)));
+ foreach (var actionType in actions)
+ {
+ var attr = actionType.GetCustomAttributes(typeof(ActionUuidAttribute), true).FirstOrDefault() as ActionUuidAttribute;
+ this.RegisterActionType(attr.Uuid, actionType);
+ }
+ return this;
+ }
+
+ #endregion
+
+
+ #region Action instance creation and retrieval
+
+ ///
+ /// Gets an instance of an action from an action UUID.
+ ///
+ /// A new instance of an action.
+ /// The UUID of the action type which is requested.
+ /// The specific type of action to be returned.
+ /// If no type is found to match the , an exception
+ /// of type is thrown.
+ public TActionType GetActionInstance(string actionUUID)
+ where TActionType : BaseStreamDeckAction
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(GetActionInstance)}(string)");
+
+ if (this._Actions.ContainsKey(actionUUID))
+ {
+ var instance = Activator.CreateInstance(this._Actions[actionUUID]) as TActionType;
+ instance.Logger = _Logger;
+ instance.Manager = _ConnectionManager;
+ return instance;
+ }
+
+ throw new ActionNotRegisteredException(actionUUID);
+ }
+
+
+ ///
+ /// Checks whether an action is registered for a given UUID.
+ ///
+ /// true, if action registered was registered, false otherwise.
+ /// The UUID to check
+ public bool IsActionRegistered(string actionUUID)
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(IsActionRegistered)}(string)");
+
+ return this._Actions.ContainsKey(actionUUID);
+ }
+
+
+ ///
+ /// Gets a new instance of an registered with a UUID
+ /// of . This instance will not be stored or managed,
+ /// and cannot be reused.
+ ///
+ /// A new instance of the action
+ /// The UUID of the action type which is to be instantiated
+ ///
+ /// Throws a exception if there is no action with
+ /// a UUID of registered.
+ ///
+ public BaseStreamDeckAction GetAction(string actionUUID)
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(GetAction)}(string)");
+
+ return this.CreateActionInstanceByUUID(actionUUID);
+ }
+
+
+ private BaseStreamDeckAction CreateActionInstanceByUUID(string actionUuid, bool throwIfNotRegistered = true)
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(CreateActionInstanceByUUID)}(string, bool)");
+ if (this._Actions.ContainsKey(actionUuid))
+ {
+ var instance = Activator.CreateInstance(this._Actions[actionUuid]) as BaseStreamDeckAction;
+ instance.Logger = _Logger;
+ instance.Manager = _ConnectionManager;
+ return instance;
+
+ }
+
+ if (throwIfNotRegistered)
+ {
+ throw new ActionNotRegisteredException(actionUuid);
+ }
+
+ return null;
+ }
+
+ #endregion
+
+
+ #region Specific action instance creation, registration, and retrieval (by Stream Deck context)
+
+
+ ///
+ /// Registers the action instance.
+ ///
+ /// The action instance.
+ /// The key to be used when registering the action instance.
+ /// This is typically the value of the .
+ /// Action instance.
+ public ActionManager RegisterActionInstance(string instanceKey, BaseStreamDeckAction actionInstance)
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(RegisterAction)}(string, BaseStreamDeckAction)");
+ return this.RegisterActionInstanceInternal(instanceKey, actionInstance);
+ }
+
+ private ActionManager RegisterActionInstanceInternal(string instanceKey, BaseStreamDeckAction actionInstance, bool throwIfInstanceIsNull = true)
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(RegisterActionInstanceInternal)}(string, BaseStreamDeckAction, bool)");
+
+ if (null == actionInstance && (!throwIfInstanceIsNull))
+ {
+ this._Logger.LogDebug($"The instance to register with a key of {instanceKey} was null, but prevent raising an exception was specified.");
+ return this;
+ }
+
+ if (null == actionInstance && throwIfInstanceIsNull)
+ {
+ throw new ArgumentNullException($"Could not register an action instance with a key of \"{instanceKey}\"");
+ }
+
+ this._Logger.LogDebug($"Registering an instance of {actionInstance.GetType().FullName} with a key of \"{instanceKey}\".");
+ if (this._ActionInstances.ContainsKey(instanceKey))
+ {
+ throw new DuplicateActionInstanceRegistrationException(instanceKey);
+ }
+
+ this._ActionInstances.Add(instanceKey, actionInstance);
+
+ return this;
+ }
+
+
+ ///
+ /// Gets the instance of action.
+ ///
+ /// The instance of action.
+ /// Context.
+ /// Action UUID.
+ internal BaseStreamDeckAction GetActionForContext(string context, string actionUuid)
+ {
+ this._Logger.LogTrace($"{nameof(ActionManager)}.{nameof(GetActionForContext)}(string, string)");
+
+ //see if context exists, if so, return the associated action
+ if (this._ActionInstances.ContainsKey(context))
+ {
+ return this._ActionInstances[context];
+ }
+
+ //see if we have a recorded type for the action
+ var actionInstance = this.CreateActionInstanceByUUID(actionUuid, false);
+ this.RegisterActionInstanceInternal(context, actionInstance, false);
+
+ return actionInstance;
+ }
+
+
+ #endregion
+
+
+ #region IDisposable Support
+
+ private bool disposedValue = false; // To detect redundant calls
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (!disposedValue)
+ {
+ if (disposing)
+ {
+ // TODO: dispose managed state (managed objects).
+ }
+
+ // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
+ // TODO: set large fields to null.
+
+ disposedValue = true;
+ }
+ }
+
+ // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
+ // ~ActionManager() {
+ // // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ // Dispose(false);
+ // }
+
+ // This code added to correctly implement the disposable pattern.
+ public void Dispose()
+ {
+ // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
+ Dispose(true);
+ // TODO: uncomment the following line if the finalizer is overridden above.
+ // GC.SuppressFinalize(this);
+ }
+
+ #endregion
+
+ }
+}
diff --git a/src/StreamDeckLib/BaseStreamDeckAction.cs b/src/StreamDeckLib/BaseStreamDeckAction.cs
index 0c41f32..48595f2 100644
--- a/src/StreamDeckLib/BaseStreamDeckAction.cs
+++ b/src/StreamDeckLib/BaseStreamDeckAction.cs
@@ -56,11 +56,13 @@ public string ActionUuid
public virtual Task OnApplicationDidTerminate(StreamDeckEventPayload args) => Task.CompletedTask;
- public virtual Task OnPropertyInspectorMessageReceived(PropertyInspectorEventPayload args) => Task.CompletedTask;
+ public virtual Task OnDidReceiveSettings(StreamDeckEventPayload args) => Task.CompletedTask;
- public virtual Task OnPropertyInspectorConnected(PropertyInspectorEventPayload args) => Task.CompletedTask;
+ public virtual Task OnDidReceiveGlobalSettings(StreamDeckEventPayload args) => Task.CompletedTask;
- public virtual Task OnPropertyInspectorDisconnected(PropertyInspectorEventPayload args) => Task.CompletedTask;
-
- }
+ public virtual Task OnPropertyInspectorDidDisappear(StreamDeckEventPayload args) => Task.CompletedTask;
+
+ public virtual Task OnPropertyInspectorDidAppear(StreamDeckEventPayload args) => Task.CompletedTask;
+
+ }
}
diff --git a/src/StreamDeckLib/BaseStreamDeckActionWithSettingsModel.cs b/src/StreamDeckLib/BaseStreamDeckActionWithSettingsModel.cs
new file mode 100644
index 0000000..7a3db3a
--- /dev/null
+++ b/src/StreamDeckLib/BaseStreamDeckActionWithSettingsModel.cs
@@ -0,0 +1,41 @@
+using StreamDeckLib.Messages;
+using System;
+using System.Threading.Tasks;
+
+namespace StreamDeckLib
+{
+ public abstract class BaseStreamDeckActionWithSettingsModel : BaseStreamDeckAction
+ {
+ public T SettingsModel { get; } = Activator.CreateInstance();
+
+ public override Task OnDidReceiveSettings(StreamDeckEventPayload args)
+ {
+ SetModelProperties(args);
+ return Task.CompletedTask;
+ }
+
+ public override Task OnWillAppear(StreamDeckEventPayload args)
+ {
+ SetModelProperties(args);
+ return Task.CompletedTask;
+ }
+
+ protected void SetModelProperties(StreamDeckEventPayload args)
+ {
+ var properties = typeof(T).GetProperties();
+ foreach (var prop in properties)
+ {
+ if (args.payload != null && args.payload.settings != null && args.payload.settings.settingsModel != null)
+ {
+ if (args.PayloadSettingsHasProperty(prop.Name))
+ {
+ var value = args.GetPayloadSettingsValue(prop.Name);
+ var value2 = Convert.ChangeType(value, prop.PropertyType);
+ prop.SetValue(SettingsModel, value2);
+ }
+ }
+ }
+ }
+
+ }
+}
diff --git a/src/StreamDeckLib/ConnectionManager.cs b/src/StreamDeckLib/ConnectionManager.cs
index c354c5a..9bd3846 100644
--- a/src/StreamDeckLib/ConnectionManager.cs
+++ b/src/StreamDeckLib/ConnectionManager.cs
@@ -24,8 +24,20 @@ public partial class ConnectionManager : IDisposable
private string _RegisterEvent;
private IStreamDeckProxy _Proxy;
+ // Cheer 225 cpayette 26/2/19
+ // Cheer 10700 roberttables 26/2/19
+ // Cheer 840 auth0bobby 26/2/19
+ // Cheer 13629 themichaeljolley 26/2/19
+ // Cheer 182 sqlmistermagoo 26/2/19
+ // Cheer 100 acrophobicpixie 26/2/19
+ // Cheer 492 danerd 26/2/19
+ // Cheer 500 tealoldman 26/2/19
+ // Cheer 500 kittishomestead 26/2/19
+ // Cheer 5500 electrichavoc 26/2/19
+
private ConnectionManager()
{
+ this._ActionManager = new ActionManager(this, _Logger);
}
public Messages.Info Info { get; private set; }
@@ -70,7 +82,9 @@ public static ConnectionManager Initialize(string[] commandLineArgs,
private static ConnectionManager Initialize(int port, string uuid,
string registerEvent, string info,
- ILoggerFactory loggerFactory, IStreamDeckProxy streamDeckProxy)
+ ILoggerFactory loggerFactory,
+ IStreamDeckProxy streamDeckProxy,
+ ActionManager actionManager = null)
{
// TODO: Validate the info parameter
var myInfo = JsonConvert.DeserializeObject(info);
@@ -152,43 +166,19 @@ private async Task Run(CancellationToken token)
continue;
}
- if (_ActionEventsIgnore.Contains(msg.Event)) { continue; }
-
- var action = GetInstanceOfAction(msg.context, msg.action);
- if (action == null)
- {
- _Logger.LogWarning($"The action requested (\"{msg.action}\") was not found as being registered with the plugin");
- continue;
- }
-
-
- //property inspector payload
- if (msg.Event == "sendToPlugin")
+ if (string.IsNullOrWhiteSpace(msg.context) && string.IsNullOrWhiteSpace(msg.action))
+ {
+ _Logger.LogInformation($"System event received: ${msg.Event}");
+ continue;
+ }
+ var action = GetInstanceOfAction(msg.context, msg.action);
+ if (action == null)
{
- var piMsg = JsonConvert.DeserializeObject(jsonString);
- if (piMsg.EventPayloadHasProperty("property_inspector"))
- {
- //property inspector event
- var piEvent = piMsg.GetEventPayloadValue("property_inspector");
- if (!_PropertyInspectorActionDictionary.ContainsKey(piEvent))
- {
- _Logger.LogWarning($"Plugin does not handle the Property Inspector event '{piEvent}'");
- continue;
- }
- else
- {
- _PropertyInspectorActionDictionary[piEvent]?.Invoke(action, piMsg);
- continue;
-
- }
-
- }
-
- //property inspector property value event
- _PropertyInspectorActionDictionary[piMsg.Event]?.Invoke(action, piMsg);
+ _Logger.LogWarning($"The action requested (\"{msg.action}\") was not found as being registered with the plugin");
continue;
}
+
if (!_EventDictionary.ContainsKey(msg.Event))
{
_Logger.LogWarning($"Plugin does not handle the event '{msg.Event}'");
@@ -280,30 +270,26 @@ public async Task SetSettingsAsync(string context, dynamic value)
await _Proxy.SendStreamDeckEvent(args);
}
- public async Task SetStateAsync(string context, int state)
+ public async Task SetGlobalSettingsAsync(string context, dynamic value)
{
- var args = new SetStateArgs
+ var args = new SetGlobalSettingsArgs()
{
context = context,
- payload = new SetStateArgs.Payload
- {
- state = state
- }
+ payload = new { settingsModel = value }
};
await _Proxy.SendStreamDeckEvent(args);
}
- public async Task SendToPropertyInspectorAsync(string context, dynamic payload)
+ public async Task SetStateAsync(string context, int state)
{
-
- var uuid = _contextActions[context].ActionUuid;
-
- var args = new SendToPropertyInspectorArgs
+ var args = new SetStateArgs
{
- action = uuid,
- context = context,
- payload = new { settingsModel = payload }
+ context = context,
+ payload = new SetStateArgs.Payload
+ {
+ state = state
+ }
};
await _Proxy.SendStreamDeckEvent(args);
@@ -339,6 +325,20 @@ public async Task OpenUrlAsync(string context, string url)
await _Proxy.SendStreamDeckEvent(args);
}
+
+ public async Task GetSettingsAsync(string context)
+ {
+ var args = new GetSettingsArgs() { context = context };
+ await _Proxy.SendStreamDeckEvent(args);
+ }
+
+
+ public async Task GetGlobalSettingsAsync(string context)
+ {
+ var args = new GetGlobalSettingsArgs() { context = context };
+ await _Proxy.SendStreamDeckEvent(args);
+ }
+
#endregion
#region IDisposable Support
diff --git a/src/StreamDeckLib/ConnectionManager_Actions.cs b/src/StreamDeckLib/ConnectionManager_Actions.cs
index b05e04b..4bc4ec3 100644
--- a/src/StreamDeckLib/ConnectionManager_Actions.cs
+++ b/src/StreamDeckLib/ConnectionManager_Actions.cs
@@ -7,59 +7,25 @@ namespace StreamDeckLib
{
partial class ConnectionManager
{
- //string is the action UUID, type is the class type of the action
- private Dictionary _actions = new Dictionary();
- //string is the context, there will only ever be one action per context
- private Dictionary _contextActions = new Dictionary();
+ private ActionManager _ActionManager;
- //Cheer 100 svavablount 15/2/19
- public ConnectionManager RegisterActionType(string actionUuid, Type actionType)
- {
- if (string.IsNullOrWhiteSpace(actionUuid)){
- throw new IncompleteActionDefinitionException("");
- }
- if(_actions.ContainsKey(actionUuid))
- {
- throw new DuplicateActionRegistrationException(actionUuid);
- }
- _actions.Add(actionUuid, actionType);
- return this;
- }
+ //Cheer 100 svavablount 15/2/19
+ public ConnectionManager RegisterActionType(string actionUuid, Type actionType)
+ {
+ this._ActionManager.RegisterActionType(actionUuid, actionType);
+ return this;
+ }
- public BaseStreamDeckAction GetInstanceOfAction(string context, string actionUuid)
- {
- //see if context exists, if so, return the associated action
- if (_contextActions.Any(x => x.Key.Equals(context)))
- {
- return _contextActions[context];
- }
- else
- {
- //see if we have a recorded type for the action
- if (_actions.Any(x => x.Key.Equals(actionUuid)))
+ public BaseStreamDeckAction GetInstanceOfAction(string context, string actionUuid)
{
- var t = _actions[actionUuid];
- var action = Activator.CreateInstance(t) as BaseStreamDeckAction;
- action.Manager = this;
- action.Logger = _LoggerFactory.CreateLogger(action.ActionUuid);
- _contextActions.Add(context, action);
- return action;
+ return this._ActionManager.GetActionForContext(context, actionUuid);
}
- }
- return null;
- }
+ public ConnectionManager RegisterAllActions(Assembly assembly)
+ {
+ this._ActionManager.RegisterAllActions(assembly);
+ return this;
+ }
- public ConnectionManager RegisterAllActions(Assembly assembly)
- {
- var actions = assembly.GetTypes().Where(t => Attribute.IsDefined(t, typeof(ActionUuidAttribute)));
- foreach (var actionType in actions)
- {
- var attr = actionType.GetCustomAttributes(typeof(ActionUuidAttribute), true).FirstOrDefault() as ActionUuidAttribute;
- this.RegisterActionType(attr.Uuid, actionType);
- }
- return this;
}
-
- }
}
diff --git a/src/StreamDeckLib/ConnectionManager_Events.cs b/src/StreamDeckLib/ConnectionManager_Events.cs
index b0b2917..77ce420 100644
--- a/src/StreamDeckLib/ConnectionManager_Events.cs
+++ b/src/StreamDeckLib/ConnectionManager_Events.cs
@@ -9,33 +9,23 @@ partial class ConnectionManager
{
// Cheer ramblinggeek 100 January 21, 2019
-
private static readonly Dictionary> _EventDictionary
= new Dictionary>()
{
- ["keyDown"] = (action, args) => action.OnKeyDown(args),
- ["keyUp"] = (action, args) => action.OnKeyUp(args),
- ["willAppear"] = (action, args) => action.OnWillAppear(args),
- ["willDisappear"] = (action, args) => action.OnWillDisappear(args),
- ["titleParametersDidChange"] = (action, args) => action.OnTitleParametersDidChange(args),
- ["deviceDidConnect"] = (action, args) => action.OnDeviceDidConnect(args),
- ["deviceDidDisconnect"] = (action, args) => action.OnDeviceDidDisconnect(args),
- ["applicationDidLaunch"] = (action, args) => action.OnApplicationDidLaunch(args),
- ["applicationDidTerminate"] = (action, args) => action.OnApplicationDidTerminate(args),
- };
-
- private static readonly string[] _ActionEventsIgnore = new[] {
- "deviceDidConnect", "deviceDidDisconnect", "applicationDidLaunch", "applicationDidTerminate"
+ ["keyDown"] = (plugin, args) => plugin.OnKeyDown(args),
+ ["keyUp"] = (plugin, args) => plugin.OnKeyUp(args),
+ ["willAppear"] = (plugin, args) => plugin.OnWillAppear(args),
+ ["willDisappear"] = (plugin, args) => plugin.OnWillDisappear(args),
+ ["titleParametersDidChange"] = (plugin, args) => plugin.OnTitleParametersDidChange(args),
+ ["deviceDidConnect"] = (plugin, args) => plugin.OnDeviceDidConnect(args),
+ ["deviceDidDisconnect"] = (plugin, args) => plugin.OnDeviceDidDisconnect(args),
+ ["applicationDidLaunch"] = (plugin, args) => plugin.OnApplicationDidLaunch(args),
+ ["applicationDidTerminate"] = (plugin, args) => plugin.OnApplicationDidTerminate(args),
+ ["didReceiveSettings"] = (plugin, args) => plugin.OnDidReceiveSettings(args),
+ ["didReceiveGlobalSettings"] = (plugin, args) => plugin.OnDidReceiveGlobalSettings(args),
+ ["propertyInspectorDidDisappear"] = (plugin, args) => plugin.OnPropertyInspectorDidDisappear(args),
+ ["propertyInspectorDidAppear"] = (plugin, args) => plugin.OnPropertyInspectorDidAppear(args)
};
-
- private static readonly Dictionary> _PropertyInspectorActionDictionary
- = new Dictionary>()
- {
- ["propertyInspectorConnected"] = (action, args) => action.OnPropertyInspectorConnected(args),
- ["propertyInspectorDisconnected"] = (action, args) => action.OnPropertyInspectorDisconnected(args),
- ["sendToPlugin"] = (action, args) => action.OnPropertyInspectorMessageReceived(args)
- };
-
}
}
diff --git a/src/StreamDeckLib/Exceptions/DuplicateActionInstanceRegistrationException.cs b/src/StreamDeckLib/Exceptions/DuplicateActionInstanceRegistrationException.cs
new file mode 100644
index 0000000..42b0a92
--- /dev/null
+++ b/src/StreamDeckLib/Exceptions/DuplicateActionInstanceRegistrationException.cs
@@ -0,0 +1,28 @@
+using System;
+using System.Runtime.Serialization;
+
+namespace StreamDeckLib
+{
+ [Serializable]
+ public class DuplicateActionInstanceRegistrationException : Exception
+ {
+ private static string GenerateErrorMessageForUUID(string key) => $"An action with a key value of \"{key}\" has already been registered.";
+
+ public string Key { get; }
+
+ public DuplicateActionInstanceRegistrationException(string key) : base(GenerateErrorMessageForUUID(key))
+ {
+ this.Key = key;
+ }
+
+ public DuplicateActionInstanceRegistrationException(string uuid, Exception innerException) : base(GenerateErrorMessageForUUID(uuid), innerException)
+ {
+ }
+
+ protected DuplicateActionInstanceRegistrationException(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+
+
+}
diff --git a/src/StreamDeckLib/Exceptions/TypeDoesNotInheritFromBaseStreamDeckAction.cs b/src/StreamDeckLib/Exceptions/TypeDoesNotInheritFromBaseStreamDeckAction.cs
new file mode 100644
index 0000000..7781f0b
--- /dev/null
+++ b/src/StreamDeckLib/Exceptions/TypeDoesNotInheritFromBaseStreamDeckAction.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Reflection;
+using System.Runtime.Serialization;
+
+namespace StreamDeckLib
+{
+ [Serializable]
+ public class TypeDoesNotInheritFromBaseStreamDeckAction : Exception
+ {
+ private string fullName;
+ private string assemblyName;
+
+ public TypeDoesNotInheritFromBaseStreamDeckAction()
+ {
+ }
+
+ public TypeDoesNotInheritFromBaseStreamDeckAction(string message) : base(message)
+ {
+ }
+
+
+ public TypeDoesNotInheritFromBaseStreamDeckAction(string simpleName, string fullName, string assemblyName)
+ : this($"The type \"{simpleName}\" (\"{fullName}\") from assembly \"{assemblyName}\" does not inherit from required base class \"{nameof(BaseStreamDeckAction)}\".")
+ {
+
+ this.fullName = fullName;
+
+ this.assemblyName = assemblyName;
+
+ }
+
+
+ public TypeDoesNotInheritFromBaseStreamDeckAction(string message, Exception innerException) : base(message, innerException)
+ {
+ }
+
+ protected TypeDoesNotInheritFromBaseStreamDeckAction(SerializationInfo info, StreamingContext context) : base(info, context)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/StreamDeckLib/Messages/BaseStreamDeckArgs.cs b/src/StreamDeckLib/Messages/BaseStreamDeckArgs.cs
index d798e2e..0833ba8 100644
--- a/src/StreamDeckLib/Messages/BaseStreamDeckArgs.cs
+++ b/src/StreamDeckLib/Messages/BaseStreamDeckArgs.cs
@@ -1,15 +1,15 @@
-using Newtonsoft.Json;
+using Newtonsoft.Json;
namespace StreamDeckLib.Messages
{
- public abstract class BaseStreamDeckArgs
- {
- [JsonProperty(PropertyName = "event")]
- public abstract string Event
- {
- get;
- }
+ public abstract class BaseStreamDeckArgs
+ {
+ [JsonProperty(PropertyName = "event")]
+ public abstract string Event
+ {
+ get;
+ }
- public string context { get; set; }
- }
+ public string context { get; set; }
+ }
}
diff --git a/src/StreamDeckLib/Messages/GetGlobalSettingsArgs.cs b/src/StreamDeckLib/Messages/GetGlobalSettingsArgs.cs
new file mode 100644
index 0000000..0e4c617
--- /dev/null
+++ b/src/StreamDeckLib/Messages/GetGlobalSettingsArgs.cs
@@ -0,0 +1,7 @@
+namespace StreamDeckLib.Messages
+{
+ public class GetGlobalSettingsArgs : BaseStreamDeckArgs
+ {
+ public override string Event => "getGlobalSettings";
+ }
+}
diff --git a/src/StreamDeckLib/Messages/GetSettingsArgs.cs b/src/StreamDeckLib/Messages/GetSettingsArgs.cs
new file mode 100644
index 0000000..2d64395
--- /dev/null
+++ b/src/StreamDeckLib/Messages/GetSettingsArgs.cs
@@ -0,0 +1,7 @@
+namespace StreamDeckLib.Messages
+{
+ public class GetSettingsArgs : BaseStreamDeckArgs
+ {
+ public override string Event => "getSettings";
+ }
+}
diff --git a/src/StreamDeckLib/Messages/LogMessageArgs.cs b/src/StreamDeckLib/Messages/LogMessageArgs.cs
new file mode 100644
index 0000000..633c349
--- /dev/null
+++ b/src/StreamDeckLib/Messages/LogMessageArgs.cs
@@ -0,0 +1,12 @@
+namespace StreamDeckLib.Messages
+{
+ public class LogMessageArgs : BaseStreamDeckArgs
+ {
+ public override string Event => "logMessage";
+ public Payload payload { get; set; }
+ public class Payload
+ {
+ public string message { get; set; }
+ }
+ }
+}
diff --git a/src/StreamDeckLib/Messages/SendToPropertyInspectorArgs.cs b/src/StreamDeckLib/Messages/SendToPropertyInspectorArgs.cs
deleted file mode 100644
index 0ad0505..0000000
--- a/src/StreamDeckLib/Messages/SendToPropertyInspectorArgs.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-namespace StreamDeckLib.Messages
-{
- public class SendToPropertyInspectorArgs : BaseStreamDeckArgs
- {
-
- public override string Event => "sendToPropertyInspector";
-
- public string action { get; set; }
-
- public dynamic payload { get; set; }
-
- }
-
-}
diff --git a/src/StreamDeckLib/Messages/SetGlobalSettingsArgs.cs b/src/StreamDeckLib/Messages/SetGlobalSettingsArgs.cs
new file mode 100644
index 0000000..9ae2a8c
--- /dev/null
+++ b/src/StreamDeckLib/Messages/SetGlobalSettingsArgs.cs
@@ -0,0 +1,8 @@
+namespace StreamDeckLib.Messages
+{
+ public class SetGlobalSettingsArgs : BaseStreamDeckArgs
+ {
+ public override string Event => "setGlobalSettings";
+ public dynamic payload { get; set; }
+ }
+}
diff --git a/src/StreamDeckLib/Messages/SetStateArgs.cs b/src/StreamDeckLib/Messages/SetStateArgs.cs
index 7d8a430..be46e28 100644
--- a/src/StreamDeckLib/Messages/SetStateArgs.cs
+++ b/src/StreamDeckLib/Messages/SetStateArgs.cs
@@ -1,4 +1,4 @@
-namespace StreamDeckLib.Messages
+namespace StreamDeckLib.Messages
{
public class SetStateArgs : BaseStreamDeckArgs
{
@@ -6,7 +6,7 @@ public class SetStateArgs : BaseStreamDeckArgs
public Payload payload { get; set; }
public class Payload
{
- public int state{ get; set; }
+ public int state { get; set; }
}
}
diff --git a/src/StreamDeckLib/Messages/ShowAlertArgs.cs b/src/StreamDeckLib/Messages/ShowAlertArgs.cs
index 704b5fa..cdbd0ed 100644
--- a/src/StreamDeckLib/Messages/ShowAlertArgs.cs
+++ b/src/StreamDeckLib/Messages/ShowAlertArgs.cs
@@ -1,7 +1,7 @@
-namespace StreamDeckLib.Messages
+namespace StreamDeckLib.Messages
{
- public class ShowAlertArgs : BaseStreamDeckArgs
- {
- public override string Event => "showAlert";
- }
+ public class ShowAlertArgs : BaseStreamDeckArgs
+ {
+ public override string Event => "showAlert";
+ }
}
diff --git a/src/StreamDeckLib/Messages/ShowOkArgs.cs b/src/StreamDeckLib/Messages/ShowOkArgs.cs
index a357fc9..c6669db 100644
--- a/src/StreamDeckLib/Messages/ShowOkArgs.cs
+++ b/src/StreamDeckLib/Messages/ShowOkArgs.cs
@@ -1,7 +1,7 @@
-namespace StreamDeckLib.Messages
+namespace StreamDeckLib.Messages
{
- public class ShowOkArgs : BaseStreamDeckArgs
- {
- public override string Event => "showOk";
- }
+ public class ShowOkArgs : BaseStreamDeckArgs
+ {
+ public override string Event => "showOk";
+ }
}
diff --git a/src/StreamDeckLib/Messages/StreamDeckEventPayloadExtensions.cs b/src/StreamDeckLib/Messages/StreamDeckEventPayloadExtensions.cs
index 7061988..866dae2 100644
--- a/src/StreamDeckLib/Messages/StreamDeckEventPayloadExtensions.cs
+++ b/src/StreamDeckLib/Messages/StreamDeckEventPayloadExtensions.cs
@@ -1,4 +1,4 @@
-using Newtonsoft.Json.Linq;
+using Newtonsoft.Json.Linq;
using System;
using System.ComponentModel;
@@ -9,7 +9,7 @@ public static class StreamDeckEventPayloadExtensions
public static bool PayloadSettingsHasProperty(this StreamDeckEventPayload obj, string propertyName)
{
var jObj = obj.payload.settings as JObject;
-
+
return jObj.Count > 0 && obj.payload.settings.settingsModel[propertyName] != null;
}
diff --git a/src/StreamDeckLib/Messages/StreamDeckInfo.cs b/src/StreamDeckLib/Messages/StreamDeckInfo.cs
index fd17e63..e738fec 100644
--- a/src/StreamDeckLib/Messages/StreamDeckInfo.cs
+++ b/src/StreamDeckLib/Messages/StreamDeckInfo.cs
@@ -1,9 +1,10 @@
-namespace StreamDeckLib.Messages
+namespace StreamDeckLib.Messages
{
public class Info
{
public Application application { get; set; }
public Device[] devices { get; set; }
+ public int devicePixelRatio { get; set; }
public class Application
{
diff --git a/src/StreamDeckLib/StreamDeckProxy.cs b/src/StreamDeckLib/StreamDeckProxy.cs
index a1e3e43..d270259 100644
--- a/src/StreamDeckLib/StreamDeckProxy.cs
+++ b/src/StreamDeckLib/StreamDeckProxy.cs
@@ -1,4 +1,4 @@
-using Newtonsoft.Json;
+using Newtonsoft.Json;
using StreamDeckLib.Messages;
using System;
using System.Collections.Generic;