fritzandfriends / streamdecktoolkit Goto Github PK
View Code? Open in Web Editor NEWA .NET Standard library, template, and tools for building extensions to the Elgato Stream Deck
License: MIT License
A .NET Standard library, template, and tools for building extensions to the Elgato Stream Deck
License: MIT License
now that the inner loop for mac users is complete, bring that forward into the template so we can do a dotnet new elGAHto
I would love to use the framework while developing in F# - this might need some discussion though as to how similar the F# interface should be to the C# one given the differences in idioms between the languages (objects vs bare functions and things like that.)
Would it be worth trying to add F# support to this template with the -lang=F#
switch or should we look at building a different template for an F# project?
Is your feature request related to a problem? Please describe.
GitHub Action to create .streamDeckPlugin
From the Elgato Docs:
Describe the solution you'd like
A GitHub action that can run the DistributionTool and produce a .streamDeckPlugin
binary.
Steps
DistributionTool
(Win or Mac)DistributionTool.exe -b -i com.elgato.counter.sdPlugin -o Release
This could then be added to other Actions like
I've never written a GHA, can you distribute binaries like the DistributionTool
with it?
Would you just pull it from here and extract, seems a lot of work each time?
Tool Options
USAGE: DistributionTool [-h] [-b] [-v] [-i FILE] [-o DIRECTORY]
This tool can be used to validate and export plugins for the Elgato Stream Deck Plugin Store.
OPTIONAL ARGUMENTS:
-b, --build Verify and build a plugin.
-v, --version The version number of this tool.
-h, --help This help dialog.
-i FILE, --input FILE Path to the plugin (.sdPlugin).
-o DIRECTORY, --output DIRECTORY Path to the output directory.
For updates and further help visit https://developer.elgato.com.
Describe alternatives you've considered
Manually running the above steps.
Additional context
I've emailed Elgato asking if they are likely to produce their own GHA and what the options will be to upload to the store.
** Is there one or more bugs reported related to this suggestion? If so, mention them below**
#144
#158
Create a sample property inspector (configuration pane) to add configuration, options, parameters, etc.
SDK Reference page: https://developer.elgato.com/documentation/stream-deck/sdk/property-inspector/
Sample code: https://developer.elgato.com/documentation/stream-deck/samples/pisamples/
Describe the bug
The didReceiveGlobalSettings
never propagated to actions.
To Reproduce
Steps to reproduce the behavior:
setGlobalSettings
instead of a setSettings
override
of the OnDidReceiveGlobalSettings
methodExpected behavior
When overriding the method on an action, it should be called by the ConnectionManager
Error Details
N/A
Screenshots
N/A
Desktop (please complete the following information):
Additional context
I was able to pinpoint the issue to this :
https://github.com/FritzAndFriends/StreamDeckToolkit/blob/dev/src/StreamDeckLib/ConnectionManager.cs#L186
In the lastest version of the code, this calls the BroadcastMessage()
method, which should work. But in the code of the StreamDeckLib nuget (v0.4.480), it goes to:
if (string.IsNullOrWhiteSpace(msg.context) && string.IsNullOrWhiteSpace(msg.action))
{
ConnectionManager._Logger.LogInformation("System event received: $" + msg.Event);
continue;
}
Which make the ConnectionManager discard the call basically.
My guess then it's just that the StreamDeckLib code is out of sync with the nuget.
When creating a new plugin using the template on OSX, the post-build action to execute the RegisterPluginAndStartStreamDeck.sh
no longer copies the built plugin to the elgato plugins directory correctly.
During the stream on Sunday Feb 3rd, @csharpfritz accepted a PR to this file that reverted it to an old broken version. During the stream, @csharpfritz chose the broken version because it had good comments. I will add some comments to the fixed version and submit a PR.
The RegisterPluginAndStartStreamDeck.* scripts are duplicated in multiple spots. This causes them to get out of sync easily as they are updated.
The template should build with no changes when a plugin is created and no code is added
Would be nice to have a editorconfig added to force consistent code formating.
For those from other OS's or from containers, what is the prerequisites to running the dotnet
command mentioned in the readme?
The project readme needs to have more information added to describe the project, how to reference it, and how to use the template
We need to provide some instructions for folks who want to contribute
We need to start a docs folder that will eventually publish to a website for developers who want to use this project
Describe the bug
NuGet description and content for the packages is the default and not clear as to what the package does
To Reproduce
Preferable
https://www.nuget.org/packages/StreamDeckLib/
Describe the bug
There appears to be a memory leak in the stream deck library with applications remaining after the Stream Deck application is closed
To Reproduce
Preferable
src/SamplePlugin
Alternatively
Steps to reproduce the behavior:
Expected behavior
Custom plugin application should terminate
Desktop (please complete the following information):
Describe the bug
The default template project does not run on MacOS. The build deploys and the process for the plugin appears to start, but does not execute.
To Reproduce
Start a new plugin project from the template, build and add plugin to stream deck. Execution fails.
Expected behavior
The plugin sample from the base template should just run. "F5" ready if you will.
Error Details
The plugin fails with an error message from ConnectionManager line 66
throw new ArgumentException($"{nameof(commandLineArgs)} must be the commandline args that the StreamDeck application calls this program with.");
Desktop (please complete the following information):
Additional context
In comparison, in windows the template plugin just works. Open the solution/project, start debugging, add the plugin to the stream deck and BOOM!
We need to replace the *.png files in /Templates/StreamDeck.PluginTemplate.Csharp/content
Is your feature request related to a problem? Please describe.
I want to be able to dynamically register actions based on the Actions that are present in the manifest.json
.
It would be nice to already have an manifest
object available at startup to interact with.
Describe the solution you'd like
The ConfigurationBuilder has a LoggerFactory today. It would be nice to expose the manifest.json
as a part of the ConfigurationBuilder
.
or
Let it be its own entity like ManifestParser
or something like that that can supply you with a parsed Manifest object on start up.
I'd love to be able to do:
foreach( Action action in Manifest.Actions)
{
cm.RegisterAction(new MyAction(action.uuid);
}
Additional context
My goal is to use StreamDeckToolkit to create a totally self contained PowerShell script runner. You will be able to do:
New-StreamDeckAction -X 3 -Y 4 -Icon foo.png -ScriptBlock {
Write-Host "hello world"
}
and then once you restart StreamDeck.exe
, it will show up.
To do this, I'd like to still only have 1 instance of the StreamDeckToolkit running so I need to be able to dynamically make Actions.
Describe the bug
The README instructions for uninstalling the template locally fails on OSX.
To Reproduce
Steps to reproduce the behavior:
dotnet new -i Templates/StreamDeck.PluginTemplate.Csharp
dotnet new -u Templates/StreamDeck.PluginTemplate.Csharp
Expected behavior
The template should be removed.
Error Details
The -u
flag expects a fully qualified path. On my local machine running the following command successfully removes the template.
dotnet new -u ~/src/notmyself/StreamDeckToolkit/Templates/StreamDeck.PluginTemplate.Csharp
Desktop (please complete the following information):
Is your feature request related to a problem? Please describe.
To help reduce duplication of effort, when launching the post-build event on non-Windows environments, we should check to see if PowerShell Core is installed. If it is, we should call pwsh
with the RegisterPluginAndStartStreamDeck.ps1
as it will likely have the most current and up-to-date changes before the shell script (RegisterPluginAndStartStreamDeck.sh
) will
Describe the solution you'd like
From the RegisterPluginAndStartStreamDeck.sh
script, check for the presence of PowerShell Core. There are myriad ways of doing this, but we should strive to make sure that the method used is compatible with a base Bash shell, that is, /bin/sh
.
Describe alternatives you've considered
Within the community, we've tried to keep parity between the PowerShell and Shell scripts, however, there is a lot more experience and comfort writing PowerShell than Shell scripts.
Additional context
None
Is there one or more bugs reported related to this suggestion? If so, mention them below
none
Is your feature request related to a problem? Please describe.
I need to be able to dynamically set the UUID because I want to make Actions on the fly. Today, you can only statically set the UUID so I can't really do this short of recompilation or reflection.
Describe the solution you'd like
Additional context
My goal is to use StreamDeckToolkit to create a totally self contained PowerShell script runner. You will be able to do:
New-StreamDeckAction -X 3 -Y 4 -Icon foo.png -ScriptBlock {
Write-Host "hello world"
}
and then once you restart StreamDeck.exe
, it will show up.
To do this, I'd like to still only have 1 instance of the StreamDeckToolkit running so I need to be able to dynamically set the UUID.
the public members decorated with [Option] attributes and the the whole args processing can be moved into a specialized method in StreamDeckLib, thus reducing a) the amount of boilerplate code and b) the neccessary direct references of the generated plugins.
Is your feature request related to a problem? Please describe.
Documentation should be generated and delivered using ReadTheDocs
Describe the solution you'd like
ReadTheDocs
The build currently supports only Windows environments as it has hard-coded paths to the C:\Program Files
path within a ps1 file. This will be different on Mac, but to fix it we should implement a similar approach as issue #17 (which is satisfied by PR #16). In #16, I created a sh
file that stops the Stream Deck
process in the same way as the original ps1
file. So, this works on Mac and Linux.
This issue will be considerably larger, however and will contain the following tweaks:
[ ] Figure out where Mac stores the plugins
[ ] Use the jq library for doing the JSON parsing & querying
[ ] Use traditional bash syntax to do the file moves or up-level this as MSBuild copy tasks (though probably the former at first)
Describe the bug
The post-build powershell and bash scripts are out of sync in the plugin template project.
The code to initialize a StreamDeckLib based plugin should be as short and simple as possible. Currently, we add about 50 lines of code to Program.cs to get things started.
That's too much.
Is your feature request related to a problem? Please describe.
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
Describe the solution you'd like
A clear and concise description of what you want to happen.
Describe alternatives you've considered
A clear and concise description of any alternative solutions or features you've considered.
Additional context
Add any other context or screenshots about the feature request here.
** Is there one or more bugs reported related to this suggestion? If so, mention them below***
#
#
Is your feature request related to a problem? Please describe.
From the onset of the project, we've known that we need to support more than one action within the plugin. The code is beginning to get to the point where implementing support for this will be more complicated.
Describe the solution you'd like
An example of a plugin which implements and registers more than one action
Describe alternatives you've considered
The only alternatives are to roll/implement changes individually, or create one plugin project and directory per action.
Additional context
n/a
Describe the bug
When running the template for the first time the counter doesn't work.
When you create an Action using the template
manifest.json
"UUID": "$(UUID).DefaultPluginAction"
Should this be
"UUID": "$(UUID).$(PluginName)PluginAction"
So that is matches
_PluginName_Action.cs
[ActionUuid(Uuid="$(UUID)")]
From example in the Sample:
manifest.json
"UUID": "com.csharpfritz.samplePlugin.action"
MySamplePluginAction.cs
[ActionUuid(Uuid = "com.csharpfritz.samplePlugin.action")]
To Reproduce
Preferable
Create a new Action from the template, build and run in your StreamDeck, drag in the action, click, fails to increase counter.
@jamesmontemagno Twitch Stream - Stream Deck Extension for My Stream Timer
Expected behavior
Counter increases
Error Details
Logs: C:\Users\[USER]\AppData\Roaming\Elgato\StreamDeck\Plugins\[PLUGIN NAME].sdPlugin
Screenshots
N/A
Desktop (please complete the following information):
Additional context
N/A
What's the best way to debug the plugin?
Is it enough to add:
public static void Main(string[] args)
{
#if DEBUG
System.Diagnostics.Debugger.Launch();
#endif
// code
}
p.s. I'll add it to Docs
Describe the bug
When I call Logger.*
, the log entry I expect to be written to the log file is not written.
To Reproduce
Steps to reproduce the behaviour:
Expected behavior
The log entry(ies) to be written to file
Error Details
No error reported
Screenshots
n/a
Desktop (please complete the following information):
Additional context
The first log entry, about initializing the plugin gets written, but nothing else afterward.
Describe the bug
The CategoryIcon
has the incorrect path, and the sample CategoryIcon.png
, [email protected]
aren't copied to the ouput folder
To Reproduce
Create a new Action using the template, build, open your StreamDeck and navigate to your Action, the category icon is blank
Expected behavior
The icon should appear
Desktop (please complete the following information):
Additional context
N/A
[This has been completed already via PR #16 and serves as a placeholder]
Lets get Roslyn Analyzer to check if plugin devs use Elgato StreamDeck best practices
We are unable to fetch settings properly after they've been set
Is your feature request related to a problem? Please describe.
The documentation does not currently make any mention about packaging or distributing the application once development is at a "big D done" stage. The only mention of anything remotely related is the process which copies the assets to the Plugins
directory.
Describe the solution you'd like
There are several different ways in which this can be approached. The least of these which should be included is information (and link to the docs) about the actual packaging process.
Additionally, providing a sample script, and perhaps a sample CI file (Azure DevOps, GitHub Actions, CircleCI, AppVeyor, etc) as a best practice would go a long way to making this final step easier, especially since this shouldn't be an action which is performed as frequently.
Describe alternatives you've considered
n/a
Additional context
Stream Deck SDK links to the documentation about:
Releases
sectionIs there one or more bugs reported related to this suggestion? If so, mention them below
n/a
I wanted to bring this up for discussion before making any changes since the implications are quite far-reaching. I also I didn't feel it would be a wise use of time, nor would it be considerate, to start applying or imposing a pattern without community involvement.
In working through the multiple action support, and then having @codingbandit's changes integrated, it dawned on me that our current directory structure, in both the sample as well as the template, is not sustainable for a few reasons.
xxxAction.cs
file in the same root directoryplugin_inspector
directoryThere are benefits which we can take from the current structure and apply as a good example or best/recommended practice. The one which immediately comes to mind is the plugin inspectors, and how they can share common resources - *.js
, *.css
, *.html
, and such files.
What we really need is to a) identify and prioritize potential pain points and pitfalls, b) determine which issues must be addressed through best practice examples, and which are acceptable with simple guidance provided, and c) implement the changes as agreed upon.
.cs
file, the root directory can get to feeling cluttered very quicklyConnectionManager
, BaseStreamDeckAction
) from the rest of the implementation of the custom actions?I have some thoughts (and opinions) on how I envision the project being structured, which I will detail in a later comment, however, I would also like to get some feedback and comments on whether this really is an issue which should be addressed at this time (am I a gun jumping alarmist?), and so, thoughts, opinions, and feedback on possible structure.
This project should add an extension method to configure Serilog logging for the StreamDeckLib
Describe the bug
When I run the documented command dotnet add package StreamDeckPluginTemplate
, I get the following error
Could not find any project in
<Current path>
.
To Reproduce
Preferable
From a command line, run the command dotnet add package StreamDeckPluginTemplate
Expected behavior
For the template to be installed and available when I type dotnet new
Error Details
n/a
Screenshots
n/a
Desktop (please complete the following information):
Additional context
n/a
Describe the bug
Trying to open mystreamtimer://countdown/?mins=15
fails.
var url = mystreamtimer://countdown/?topofhour`
await Manager.OpenUrlAsync(args.context, "https://www.bing.com");
Manager.OpenUrlAsync(args.context, "https://www.bing.com");
To Reproduce
Preferable
See @jamesmontemagno's stream
Stream Deck Extension for My Stream Timer
Expected behavior
Any url opens
Examples
mystreamtimer://countdown/?mins=15
mystreamtimer://countdown/?to=15:30
mystreamtimer://countdown/?topofhour
Added code from SO
private void OpenUrl(string url)
{
try
{
Process.Start(url);
}
catch
{
// hack because of this: https://github.com/dotnet/corefx/issues/10361
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
url = url.Replace("&", "^&");
Process.Start(new ProcessStartInfo("cmd", $"/c start {url}") { CreateNoWindow = true });
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
Process.Start("xdg-open", url);
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
{
Process.Start("open", url);
}
else
{
throw;
}
}
}
Error Details
N/A
Screenshots
N/A
Desktop (please complete the following information):
Additional context
N/A
Describe the bug
Following the guide for Exporting your plugin for distribution you get an error when packaging.
2 issues
CodePath
in manifestTo Reproduce
Download the DistributionTool
from the above page.
Run the command
DistributionTool Error: The plugin has an invalid unique identifier: [UUID]. The unique identifier must be a uniform type identifier (UTI) that contains only lowercase alphanumeric characters (a-z, 0-9), hyphen (-), and period (.). The string must be in reverse-DNS format.
C:\Users\[USER]\AppData\Roaming\Elgato\StreamDeck\Plugins>DistributionTool.exe -b -i [UUID] -o Release
DistributionTool using printf
DistributionTool Validating and exporting the plugin [UUID]
DistributionTool Error: The CodePath property is missing in the manifest.json file. Please add a valid "CodePath" property to the manifest.json.
DistributionTool Error: The plugin is invalid
Expected behavior
The tool can output a .streamDeckPlugin
for distribution from the Template.
Error Details
Error: The CodePath property is missing in the manifest.json file. Please add a valid "CodePath" property to the manifest.json.
Screenshots
N/A
Desktop (please complete the following information):
Additional context
Fix for #144.
Adding an extra CodePath
doesn't work if CodePathWin
and CodePathMac
still exist.
We need to start testing and ensuring the API continues to work properly
We need a simple emulator that will allow contributors who don't have the hardware to code against debug their extensions / toolkit code
Currently, the build fails on macOS, and presumably, Linux as well, regardless of the build method. The errors come from the pre and post build step, which invokes PowerShell to stop and start the StreamDeck application. These operations are not valid on non-Windows PCs.
The steps should have an execution condition, allowing their execution only on Windows PCs.
Add runtime identifiers which will be used at build time based on the current build environment.
See my comment here for a more detailed/thorough explanation of the apparent workings of the <RuntimeIdentifier[s]>
elements.
Post-build actions and other settings are missing from the template.
Describe the bug
The command dotnet new streamdeck-plugin -n FirstPlugin
fails with a restore error.
To Reproduce
Steps to reproduce the behavior:
dotnet new streamdeck-plugin -n FirstPlugin
Expected behavior
The project should be created and the restore should succeed.
Error Details
dotnet new streamdeck-plugin -n FirstPlugin
The template "Stream Deck Plugin" was created successfully.
Processing post-creation actions...
Running 'dotnet restore' on FirstPlugin/FirstPlugin.csproj...
Restoring packages for /Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj...
/Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj : error NU1102: Unable to find package StreamDeckLib with version (>= 1.0.0)
/Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj : error NU1102: - Found 14 version(s) in nuget.org [ Nearest version: 0.2.354 ]
Generating MSBuild file /Users/bobby/src/notmyself/FirstPlugin/obj/FirstPlugin.csproj.nuget.g.props.
Generating MSBuild file /Users/bobby/src/notmyself/FirstPlugin/obj/FirstPlugin.csproj.nuget.g.targets.
Restore failed in 1.2 sec for /Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj.
Restore failed.
Post action failed.
Description: Restore NuGet packages required by this project.
Manual instructions: Run 'dotnet restore'
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
Using the current development branch version of the stream deck plugin template does not build.
Steps to recreate:
dotnet new -i Templates/StreamDeck.PluginTemplate.Csharp
cd ~/dev/repos
dotnet new streamdeck-plugin -n FirstPlugin
cd FirstPlugin
dotnet build
Result:
dotnet build
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Restore completed in 46.41 ms for /Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj.
MyPlugin.cs(13,4): error CS1997: Since 'MyPlugin.OnKeyUp(StreamDeckEventPayload)' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task<T>'? [/Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj]
MyPlugin.cs(9,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. [/Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj]
Program.cs(49,29): error CS1501: No overload for method 'Initialize' takes 5 arguments [/Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj]
Build FAILED.
MyPlugin.cs(9,30): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. [/Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj]
MyPlugin.cs(13,4): error CS1997: Since 'MyPlugin.OnKeyUp(StreamDeckEventPayload)' is an async method that returns 'Task', a return keyword must not be followed by an object expression. Did you intend to return 'Task<T>'? [/Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj]
Program.cs(49,29): error CS1501: No overload for method 'Initialize' takes 5 arguments [/Users/bobby/src/notmyself/FirstPlugin/FirstPlugin.csproj]
1 Warning(s)
2 Error(s)
Time Elapsed 00:00:02.76
Related to #15
Further progress adding unit tests may be limited by the current tight coupling of the Connection Manager to its ClientWebSocket in the _Socket field which is preventing mocking of the un-managed resource in a unit test.
This will need to be addressed through some form of IOC; either with the introduction of a DI container or some other design pattern such as the injection of a ClientWebSocket factory object alongside the existing logger factory
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.