First worked example
This commit is contained in:
parent
c4f7e3e73a
commit
55e8aa6dc1
3
spinclock/.gitignore
vendored
Normal file
3
spinclock/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
au.id.hawkins.sd.spinclock.sdPlugin/spinclock
|
||||||
|
au.id.hawkins.sd.spinclock.sdPlugin/spinclock.exe
|
||||||
|
|
33
spinclock/README.md
Normal file
33
spinclock/README.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Example Stream Deck plugin - "spinclock"
|
||||||
|
|
||||||
|
This plugin displays a minimalist clock - the number on the clock is the hour (24h time)
|
||||||
|
and the rotation indicates the minute. With a little practice it should become easy to
|
||||||
|
tell the time with some accuracy.
|
||||||
|
|
||||||
|
Tapping on a clock changes its colour to a random colour.
|
||||||
|
|
||||||
|
# Trying it out
|
||||||
|
|
||||||
|
Check this code out somewhere.
|
||||||
|
|
||||||
|
Symlink `the au.id.hawkins.sd.spinclock.sdPlugin` directory into your
|
||||||
|
plugin directory. See [Elgato's documentation](https://docs.elgato.com/sdk/plugins/getting-started#id-4.-add-the-plugin-to-stream-deck).
|
||||||
|
|
||||||
|
Compile the code, using the `./build.sh` script (sorry Windows users, no `.bat` file, patches welcome).
|
||||||
|
|
||||||
|
Restart the Stream Deck software, your plugin should now be available in the list on the right hand side. When you drag it
|
||||||
|
onto your profile, the plugin will start.
|
||||||
|
|
||||||
|
Stdout/stderr logs are available, on Mac they are at:
|
||||||
|
|
||||||
|
/Users/<username>/Library/Logs/ElgatoStreamDeck
|
||||||
|
|
||||||
|
# Making changes
|
||||||
|
|
||||||
|
After modifying the code, rebuild using the script, and simply kill the running process to make Stream Deck restart it for you:
|
||||||
|
|
||||||
|
killall spinclock
|
||||||
|
|
||||||
|
Note that if your plugin restarts too many times in short succession,
|
||||||
|
Stream Deck will disable it completely (see the logs above) - the
|
||||||
|
only way I know of to recover is to restart the Stream Deck software.
|
43
spinclock/au.id.hawkins.sd.spinclock.sdPlugin/manifest.json
Normal file
43
spinclock/au.id.hawkins.sd.spinclock.sdPlugin/manifest.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"UUID": "au.id.hawkins.sd.spinclock",
|
||||||
|
"SDKVersion": 2,
|
||||||
|
"Author": "Justin Hawkins",
|
||||||
|
"CodePath": "spinclock",
|
||||||
|
"CodePathWin": "spinclock.exe",
|
||||||
|
"Description": "A spinning clock",
|
||||||
|
"Name": "SpinClock",
|
||||||
|
"Icon": "spinclock",
|
||||||
|
"DisableAutomaticStates": false,
|
||||||
|
"URL": "https://github.com/tardisx/streamdeck-plugin-examples/spinclock",
|
||||||
|
"Version": "1.0.0",
|
||||||
|
"OS": [
|
||||||
|
{
|
||||||
|
"Platform": "mac",
|
||||||
|
"MinimumVersion": "10.11"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Platform": "windows",
|
||||||
|
"MinimumVersion": "10"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Software": {
|
||||||
|
"MinimumVersion": "6.5"
|
||||||
|
},
|
||||||
|
"Category": "Clocks",
|
||||||
|
"CategoryIcon": "spinclock",
|
||||||
|
"Actions": [
|
||||||
|
{
|
||||||
|
"Icon": "spinclock",
|
||||||
|
"Name": "SpinClock!",
|
||||||
|
"States": [
|
||||||
|
{
|
||||||
|
"Image": ""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"Controllers": ["Keypad"],
|
||||||
|
|
||||||
|
"Tooltip": "A clock that tells time by rotation",
|
||||||
|
"UUID": "au.id.hawkins.sd.spinclock.clock"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
BIN
spinclock/au.id.hawkins.sd.spinclock.sdPlugin/spinclock@1x.png
Normal file
BIN
spinclock/au.id.hawkins.sd.spinclock.sdPlugin/spinclock@1x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
BIN
spinclock/au.id.hawkins.sd.spinclock.sdPlugin/spinclock@2x.png
Normal file
BIN
spinclock/au.id.hawkins.sd.spinclock.sdPlugin/spinclock@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
3
spinclock/build.sh
Executable file
3
spinclock/build.sh
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
GOOS=darwin GOOARCH=arm64 go build -o au.id.hawkins.sd.spinclock.sdPlugin/spinclock .
|
||||||
|
GOOS=windows GOOARCH=amd64 go build -o au.id.hawkins.sd.spinclock.sdPlugin/spinclock.exe .
|
7
spinclock/go.mod
Normal file
7
spinclock/go.mod
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
module spinclock
|
||||||
|
|
||||||
|
go 1.22.1
|
||||||
|
|
||||||
|
require github.com/tardisx/streamdeck-plugin v0.0.7
|
||||||
|
|
||||||
|
require github.com/gorilla/websocket v1.5.3 // indirect
|
6
spinclock/go.sum
Normal file
6
spinclock/go.sum
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||||
|
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/tardisx/streamdeck-plugin v0.0.6 h1:vtaRHiKtcW09jMMIqcg0m+wBMqOq3Cl2PX3ktr7PTAM=
|
||||||
|
github.com/tardisx/streamdeck-plugin v0.0.6/go.mod h1:ysAJDI3Pi6zIbR3/jX7Pvduy6XGu68caZtSxn5t16V4=
|
||||||
|
github.com/tardisx/streamdeck-plugin v0.0.7 h1:YpII9PYlIXExe8+DPdffJxCM/2uftCpZGRpNq2rMiZw=
|
||||||
|
github.com/tardisx/streamdeck-plugin v0.0.7/go.mod h1:ysAJDI3Pi6zIbR3/jX7Pvduy6XGu68caZtSxn5t16V4=
|
116
spinclock/main.go
Normal file
116
spinclock/main.go
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"math/rand"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/tardisx/streamdeck-plugin"
|
||||||
|
"github.com/tardisx/streamdeck-plugin/events"
|
||||||
|
"github.com/tardisx/streamdeck-plugin/tools"
|
||||||
|
)
|
||||||
|
|
||||||
|
// keep track of instances we've seen, each one has a different
|
||||||
|
// colour
|
||||||
|
type clocks struct {
|
||||||
|
contextColour map[string]string
|
||||||
|
lock sync.Mutex
|
||||||
|
}
|
||||||
|
|
||||||
|
// template for making a clock image in SVG
|
||||||
|
const svgClock = `
|
||||||
|
<svg width="144" height="144" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect width="144" height="144" fill="black"/>
|
||||||
|
<text x="72" y="108"
|
||||||
|
font-family="Arial, sans-serif"
|
||||||
|
font-size="96"
|
||||||
|
font-weight="bold"
|
||||||
|
fill="%s"
|
||||||
|
text-anchor="middle"
|
||||||
|
dominant-baseline="central"
|
||||||
|
transform="rotate(%d, 72, 72)">
|
||||||
|
%02d
|
||||||
|
</text>
|
||||||
|
</svg>`
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
clocks := clocks{
|
||||||
|
contextColour: map[string]string{},
|
||||||
|
lock: sync.Mutex{},
|
||||||
|
}
|
||||||
|
slog.Info("Starting up")
|
||||||
|
c := streamdeck.NewWithLogger(slog.Default())
|
||||||
|
|
||||||
|
slog.Info("Registering handlers")
|
||||||
|
c.RegisterHandler(func(e events.ERWillAppear) {
|
||||||
|
// clock appeared, give it a random colour
|
||||||
|
slog.Info("appearing " + e.Context)
|
||||||
|
clocks.lock.Lock()
|
||||||
|
defer clocks.lock.Unlock()
|
||||||
|
clocks.contextColour[e.Context] = randRGB()
|
||||||
|
})
|
||||||
|
c.RegisterHandler(func(e events.ERWillDisappear) {
|
||||||
|
// Stop updating this clock by simply removing it from our struct.
|
||||||
|
// Note that this is not required, and in this case it means that
|
||||||
|
// when it gets re-instantiated it will get a new colour.
|
||||||
|
// But it is good practice to not spend CPU on updating things that
|
||||||
|
// are not currently being displayed.
|
||||||
|
slog.Info("disappearing " + e.Context)
|
||||||
|
clocks.lock.Lock()
|
||||||
|
defer clocks.lock.Unlock()
|
||||||
|
delete(clocks.contextColour, e.Context)
|
||||||
|
})
|
||||||
|
c.RegisterHandler(func(e events.ERKeyDown) {
|
||||||
|
// button pressed, change its colour
|
||||||
|
slog.Info("keyDown " + e.Context)
|
||||||
|
clocks.lock.Lock()
|
||||||
|
defer clocks.lock.Unlock()
|
||||||
|
clocks.contextColour[e.Context] = randRGB()
|
||||||
|
drawClock(c, e.Context, clocks.contextColour[e.Context])
|
||||||
|
})
|
||||||
|
|
||||||
|
slog.Info("Connecting web socket")
|
||||||
|
err := c.Connect()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// update all clocks, continuously
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
clocks.lock.Lock()
|
||||||
|
for context, colour := range clocks.contextColour {
|
||||||
|
drawClock(c, context, colour)
|
||||||
|
}
|
||||||
|
clocks.lock.Unlock()
|
||||||
|
time.Sleep(time.Second)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
slog.Info("waiting for the end")
|
||||||
|
c.WaitForPluginExit()
|
||||||
|
}
|
||||||
|
|
||||||
|
func drawClock(c streamdeck.Connection, context string, colour string) {
|
||||||
|
// rotation for this minute of the hour
|
||||||
|
rot := int(360.0 * (float64(time.Now().Minute()) / 60.0))
|
||||||
|
// generate the SVG
|
||||||
|
svg := fmt.Sprintf(svgClock, colour, rot, time.Now().Hour())
|
||||||
|
|
||||||
|
// create the event
|
||||||
|
newImage := events.NewESSetImage(
|
||||||
|
context,
|
||||||
|
tools.SVGToPayload(svg),
|
||||||
|
events.EventTargetBoth,
|
||||||
|
nil)
|
||||||
|
|
||||||
|
// send it
|
||||||
|
c.Send(newImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
// randRGB creates a random colour
|
||||||
|
func randRGB() string {
|
||||||
|
return fmt.Sprintf("#%02x%02x%02x", rand.Intn(256), rand.Intn(256), rand.Intn(256))
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user