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