mirror of
https://github.com/jwetzell/showbridge-go.git
synced 2026-04-29 14:25:31 +00:00
Compare commits
13 Commits
v0.18.0
...
feat/js-wa
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d4cb251e9 | ||
|
|
050ada6a70 | ||
|
|
882af2948a | ||
|
|
e2e9fb5eb6 | ||
|
|
411888d8db | ||
|
|
e367d6eb5d | ||
|
|
7659f412fb | ||
|
|
85964f5e25 | ||
|
|
b9e8bb66c6 | ||
|
|
2f9ca82b81 | ||
|
|
25579cb941 | ||
|
|
9134f034c7 | ||
|
|
204ccab683 |
27
.github/labeler.yml
vendored
27
.github/labeler.yml
vendored
@@ -1,27 +0,0 @@
|
||||
config:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "internal/config/**"
|
||||
|
||||
framer:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "internal/framer/**"
|
||||
|
||||
module:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "internal/module/**"
|
||||
|
||||
processor:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "internal/processor/**"
|
||||
|
||||
router:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "router*"
|
||||
|
||||
route:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "internal/route/**"
|
||||
|
||||
cli:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file: "cmd/showbridge/**"
|
||||
18
.github/workflows/label-pr.yaml
vendored
18
.github/workflows/label-pr.yaml
vendored
@@ -1,18 +0,0 @@
|
||||
# Taken from https://github.com/go-gitea/gitea
|
||||
name: Add labels to PR
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
jobs:
|
||||
labeler:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
|
||||
with:
|
||||
sync-labels: true
|
||||
@@ -25,6 +25,7 @@ Simple protocol router _/s_
|
||||
- [OSC](https://opensoundcontrol.stanford.edu/spec-1_0.html)
|
||||
- [FreeD](https://ptzoptics.com/freed/)
|
||||
- [SIP](https://en.wikipedia.org/wiki/Session_Initiation_Protocol)
|
||||
- [Redis](https://redis.io/)
|
||||
|
||||
### CLI Usage
|
||||
|
||||
@@ -36,9 +37,10 @@ USAGE:
|
||||
showbridge [global options]
|
||||
|
||||
GLOBAL OPTIONS:
|
||||
--config string path to config file (default: "./config.yaml")
|
||||
--log-level string set log level (default: "info")
|
||||
--log-format string log format to use (default: "text")
|
||||
--config string path to config file (default: "./config.yaml") [$SHOWBRIDGE_CONFIG]
|
||||
--log-level string set log level (default: "info") [$SHOWBRIDGE_LOG_LEVEL]
|
||||
--log-format string log format to use (default: "text") [$SHOWBRIDGE_LOG_FORMAT]
|
||||
--trace enable OpenTelemetry tracing [$SHOWBRIDGE_TRACE]
|
||||
--help, -h show help
|
||||
--version, -v print the version
|
||||
```
|
||||
|
||||
5
app/demo/document.go
Normal file
5
app/demo/document.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package main
|
||||
|
||||
import "syscall/js"
|
||||
|
||||
var document = js.Global().Get("document")
|
||||
71
app/demo/index.html
Normal file
71
app/demo/index.html
Normal file
@@ -0,0 +1,71 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<script src="wasm_exec.js"></script>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#output-container {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#log-container {
|
||||
background-color: #1e1e1e;
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
overflow-y: auto;
|
||||
overflow-x: scroll;
|
||||
box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
#logs {
|
||||
margin: 0;
|
||||
padding-left: 2px;
|
||||
font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.4;
|
||||
color: #a8cc8c;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const container = document.getElementById("log-container");
|
||||
|
||||
function isScrolledToBottom() {
|
||||
const scrollThreshold = 1;
|
||||
return (
|
||||
container.scrollHeight - container.clientHeight <=
|
||||
container.scrollTop + scrollThreshold
|
||||
);
|
||||
}
|
||||
function scrollToBottomManual() {
|
||||
const container = document.getElementById("log-container");
|
||||
// Set scrollTop to the maximum value possible (scrollHeight - clientHeight)
|
||||
container.scrollTop = container.scrollHeight - container.clientHeight;
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="output-container">
|
||||
<div id="output"></div>
|
||||
</div>
|
||||
|
||||
<div id="log-container">
|
||||
<pre id="logs"></pre>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const go = new Go();
|
||||
WebAssembly.instantiateStreaming(
|
||||
fetch("main.wasm"),
|
||||
go.importObject,
|
||||
).then((result) => {
|
||||
go.run(result.instance);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
42
app/demo/log.go
Normal file
42
app/demo/log.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import "syscall/js"
|
||||
|
||||
type LogWriter struct {
|
||||
Element js.Value
|
||||
Container js.Value
|
||||
}
|
||||
|
||||
func (pw *LogWriter) ScrollToBottom() {
|
||||
scrollHeight := pw.Container.Get("scrollHeight").Int()
|
||||
clientHeight := pw.Container.Get("clientHeight").Int()
|
||||
pw.Container.Set("scrollTop", scrollHeight-clientHeight)
|
||||
}
|
||||
|
||||
func (pw *LogWriter) IsScrolledToBottom() bool {
|
||||
scrollHeight := pw.Container.Get("scrollHeight").Int()
|
||||
clientHeight := pw.Container.Get("clientHeight").Int()
|
||||
scrollTop := pw.Container.Get("scrollTop").Int()
|
||||
return scrollHeight-clientHeight <= scrollTop+25
|
||||
}
|
||||
|
||||
func (pw *LogWriter) Write(p []byte) (n int, err error) {
|
||||
if !pw.Element.IsUndefined() {
|
||||
currentText := pw.Element.Get("textContent").String()
|
||||
newText := currentText + string(p)
|
||||
pw.Element.Set("textContent", newText)
|
||||
if pw.IsScrolledToBottom() {
|
||||
pw.ScrollToBottom()
|
||||
}
|
||||
}
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
func NewLogWriter(id string) *LogWriter {
|
||||
element := document.Call("getElementById", id)
|
||||
container := element.Get("parentElement")
|
||||
return &LogWriter{
|
||||
Element: element,
|
||||
Container: container,
|
||||
}
|
||||
}
|
||||
71
app/demo/main.go
Normal file
71
app/demo/main.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/jwetzell/showbridge-go"
|
||||
"github.com/jwetzell/showbridge-go/internal/config"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
slog.SetLogLoggerLevel(slog.LevelDebug)
|
||||
slog.SetDefault(slog.New(slog.NewTextHandler(NewLogWriter("logs"), &slog.HandlerOptions{
|
||||
Level: slog.LevelDebug,
|
||||
})))
|
||||
|
||||
router, moduleConfigErrors, routeConfigErrors := showbridge.NewRouter(config.Config{
|
||||
Api: config.ApiConfig{
|
||||
Enabled: false,
|
||||
Port: 0,
|
||||
},
|
||||
Modules: []config.ModuleConfig{
|
||||
{
|
||||
Id: "midi",
|
||||
Type: "midi.input",
|
||||
Params: map[string]any{
|
||||
"port": "Launchpad S",
|
||||
},
|
||||
},
|
||||
},
|
||||
Routes: []config.RouteConfig{
|
||||
{
|
||||
Input: "midi",
|
||||
Processors: []config.ProcessorConfig{
|
||||
{
|
||||
Type: "debug.log",
|
||||
},
|
||||
{
|
||||
Type: "web.set",
|
||||
Params: map[string]any{
|
||||
"id": "output",
|
||||
"property": "textContent",
|
||||
"value": "{{.Payload}}",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if len(moduleConfigErrors) > 0 {
|
||||
for _, err := range moduleConfigErrors {
|
||||
println("Module config error:", err.Error)
|
||||
}
|
||||
}
|
||||
|
||||
if len(routeConfigErrors) > 0 {
|
||||
for _, err := range routeConfigErrors {
|
||||
println("Route config error:", err.Error)
|
||||
}
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
go func() {
|
||||
router.Start(ctx)
|
||||
fmt.Println("router stopped")
|
||||
}()
|
||||
<-ctx.Done()
|
||||
}
|
||||
@@ -38,9 +38,10 @@ func main() {
|
||||
Version: version,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Value: "./config.yaml",
|
||||
Usage: "path to config file",
|
||||
Name: "config",
|
||||
Value: "./config.yaml",
|
||||
Usage: "path to config file",
|
||||
Sources: cli.EnvVars("SHOWBRIDGE_CONFIG"),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "log-level",
|
||||
@@ -53,6 +54,7 @@ func main() {
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Sources: cli.EnvVars("SHOWBRIDGE_LOG_LEVEL"),
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "log-format",
|
||||
@@ -65,11 +67,13 @@ func main() {
|
||||
}
|
||||
return nil
|
||||
},
|
||||
Sources: cli.EnvVars("SHOWBRIDGE_LOG_FORMAT"),
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "trace",
|
||||
Value: false,
|
||||
Usage: "enable OpenTelemetry tracing",
|
||||
Name: "trace",
|
||||
Value: false,
|
||||
Usage: "enable OpenTelemetry tracing",
|
||||
Sources: cli.EnvVars("SHOWBRIDGE_TRACE"),
|
||||
},
|
||||
},
|
||||
Action: run,
|
||||
|
||||
10
go.mod
10
go.mod
@@ -14,7 +14,7 @@ require (
|
||||
github.com/jwetzell/free-d-go v0.1.0
|
||||
github.com/jwetzell/osc-go v0.2.0
|
||||
github.com/jwetzell/psn-go v0.3.0
|
||||
github.com/nats-io/nats-server/v2 v2.12.5
|
||||
github.com/nats-io/nats-server/v2 v2.12.6
|
||||
github.com/nats-io/nats.go v1.49.0
|
||||
github.com/redis/go-redis/v9 v9.18.0
|
||||
github.com/urfave/cli/v3 v3.7.0
|
||||
@@ -53,7 +53,7 @@ require (
|
||||
github.com/klauspost/compress v1.18.4 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.8.0 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.8.1 // indirect
|
||||
github.com/nats-io/nkeys v0.4.15 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/ncruces/go-strftime v1.0.0 // indirect
|
||||
@@ -74,11 +74,11 @@ require (
|
||||
go.opentelemetry.io/proto/otlp v1.9.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/crypto v0.49.0 // indirect
|
||||
golang.org/x/net v0.51.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/sync v0.20.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
golang.org/x/time v0.15.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260209200024-4cfbd4190f57 // indirect
|
||||
|
||||
20
go.sum
20
go.sum
@@ -87,10 +87,10 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76 h1:KGuD/pM2JpL9FAYvBrnBBeENKZNh6eNtjqytV6TYjnk=
|
||||
github.com/minio/highwayhash v1.0.4-0.20251030100505-070ab1a87a76/go.mod h1:GGYsuwP/fPD6Y9hMiXuapVvlIUEhFhMTh0rxU3ik1LQ=
|
||||
github.com/nats-io/jwt/v2 v2.8.0 h1:K7uzyz50+yGZDO5o772eRE7atlcSEENpL7P+b74JV1g=
|
||||
github.com/nats-io/jwt/v2 v2.8.0/go.mod h1:me11pOkwObtcBNR8AiMrUbtVOUGkqYjMQZ6jnSdVUIA=
|
||||
github.com/nats-io/nats-server/v2 v2.12.5 h1:EOHLbsLJgUHUwzkj9gBTOlubkX+dmSs0EYWMdBiHivU=
|
||||
github.com/nats-io/nats-server/v2 v2.12.5/go.mod h1:JQDAKcwdXs0NRhvYO31dzsXkzCyDkOBS7SKU3Nozu14=
|
||||
github.com/nats-io/jwt/v2 v2.8.1 h1:V0xpGuD/N8Mi+fQNDynXohVvp7ZztevW5io8CUWlPmU=
|
||||
github.com/nats-io/jwt/v2 v2.8.1/go.mod h1:nWnOEEiVMiKHQpnAy4eXlizVEtSfzacZ1Q43LIRavZg=
|
||||
github.com/nats-io/nats-server/v2 v2.12.6 h1:Egbx9Vl7Ch8wTtpXPGqbehkZ+IncKqShUxvrt1+Enc8=
|
||||
github.com/nats-io/nats-server/v2 v2.12.6/go.mod h1:4HPlrvtmSO3yd7KcElDNMx9kv5EBJBnJJzQPptXlheo=
|
||||
github.com/nats-io/nats.go v1.49.0 h1:yh/WvY59gXqYpgl33ZI+XoVPKyut/IcEaqtsiuTJpoE=
|
||||
github.com/nats-io/nats.go v1.49.0/go.mod h1:fDCn3mN5cY8HooHwE2ukiLb4p4G4ImmzvXyJt+tGwdw=
|
||||
github.com/nats-io/nkeys v0.4.15 h1:JACV5jRVO9V856KOapQ7x+EY8Jo3qw1vJt/9Jpwzkk4=
|
||||
@@ -163,20 +163,20 @@ go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
go.yaml.in/yaml/v2 v2.4.2/go.mod h1:081UH+NErpNdqlCXm3TtEran0rJZGxAYx9hb/ELlsPU=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
|
||||
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
|
||||
golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo=
|
||||
golang.org/x/net v0.51.0/go.mod h1:aamm+2QF5ogm02fjy5Bb7CQ0WMt1/WVM7FtyaTLlA9Y=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||
golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
|
||||
golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/time v0.15.0 h1:bbrp8t3bGUeFOx08pvsMYRTCVSMk89u4tKbNOZbp88U=
|
||||
golang.org/x/time v0.15.0/go.mod h1:Y4YMaQmXwGQZoFaVFk4YpCt4FLQMYKZe9oeV/f4MSno=
|
||||
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
7
internal/module/desktop.go
Normal file
7
internal/module/desktop.go
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build cgo
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
|
||||
)
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build cgo
|
||||
//go:build cgo || js
|
||||
|
||||
package module
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/jwetzell/showbridge-go/internal/common"
|
||||
"github.com/jwetzell/showbridge-go/internal/config"
|
||||
"gitlab.com/gomidi/midi/v2"
|
||||
_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
|
||||
)
|
||||
|
||||
type MIDIInput struct {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build cgo
|
||||
//go:build cgo || js
|
||||
|
||||
package module
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"github.com/jwetzell/showbridge-go/internal/common"
|
||||
"github.com/jwetzell/showbridge-go/internal/config"
|
||||
"gitlab.com/gomidi/midi/v2"
|
||||
_ "gitlab.com/gomidi/midi/v2/drivers/rtmididrv"
|
||||
)
|
||||
|
||||
type MIDIOutput struct {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -64,7 +64,7 @@ func (t *TimeTimer) Start(ctx context.Context) error {
|
||||
router, ok := ctx.Value(common.RouterContextKey).(common.RouteIO)
|
||||
|
||||
if !ok {
|
||||
return errors.New("net.tcp.client unable to get router from context")
|
||||
return errors.New("time.timer unable to get router from context")
|
||||
}
|
||||
t.router = router
|
||||
moduleContext, cancel := context.WithCancel(ctx)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
//go:build !js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
@@ -31,8 +34,9 @@ func init() {
|
||||
Type: "object",
|
||||
Properties: map[string]*jsonschema.Schema{
|
||||
"ip": {
|
||||
Title: "IP",
|
||||
Type: "string",
|
||||
Title: "IP",
|
||||
Type: "string",
|
||||
Default: json.RawMessage(`"0.0.0.0"`),
|
||||
},
|
||||
"port": {
|
||||
Title: "Port",
|
||||
@@ -40,8 +44,15 @@ func init() {
|
||||
Minimum: jsonschema.Ptr[float64](1024),
|
||||
Maximum: jsonschema.Ptr[float64](65535),
|
||||
},
|
||||
"bufferSize": {
|
||||
Title: "Buffer Size",
|
||||
Type: "integer",
|
||||
Minimum: jsonschema.Ptr[float64](1),
|
||||
Maximum: jsonschema.Ptr[float64](65535),
|
||||
Default: json.RawMessage("2048"),
|
||||
},
|
||||
},
|
||||
Required: []string{"ip", "port"},
|
||||
Required: []string{"port"},
|
||||
AdditionalProperties: nil,
|
||||
},
|
||||
New: func(moduleConfig config.ModuleConfig) (common.Module, error) {
|
||||
|
||||
91
internal/module/web-onclick.go
Normal file
91
internal/module/web-onclick.go
Normal file
@@ -0,0 +1,91 @@
|
||||
//go:build js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"syscall/js"
|
||||
"time"
|
||||
|
||||
"github.com/google/jsonschema-go/jsonschema"
|
||||
"github.com/jwetzell/showbridge-go/internal/common"
|
||||
"github.com/jwetzell/showbridge-go/internal/config"
|
||||
)
|
||||
|
||||
type WebOnClick struct {
|
||||
config config.ModuleConfig
|
||||
ctx context.Context
|
||||
router common.RouteIO
|
||||
logger *slog.Logger
|
||||
ElementId string
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterModule(ModuleRegistration{
|
||||
Type: "web.onclick",
|
||||
Title: "On Click",
|
||||
ParamsSchema: &jsonschema.Schema{
|
||||
Type: "object",
|
||||
Properties: map[string]*jsonschema.Schema{
|
||||
"id": {
|
||||
Title: "Element ID",
|
||||
Type: "string",
|
||||
Description: "ID of the HTML element to attach the click listener to",
|
||||
},
|
||||
},
|
||||
Required: []string{"duration"},
|
||||
AdditionalProperties: nil,
|
||||
},
|
||||
New: func(config config.ModuleConfig) (common.Module, error) {
|
||||
params := config.Params
|
||||
|
||||
idString, err := params.GetString("id")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("web.onclick id error: %w", err)
|
||||
}
|
||||
|
||||
return &WebOnClick{ElementId: idString, config: config, logger: CreateLogger(config)}, nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (woc *WebOnClick) Id() string {
|
||||
return woc.config.Id
|
||||
}
|
||||
|
||||
func (woc *WebOnClick) Type() string {
|
||||
return woc.config.Type
|
||||
}
|
||||
|
||||
func (woc *WebOnClick) Start(ctx context.Context) error {
|
||||
woc.logger.Debug("running")
|
||||
router, ok := ctx.Value(common.RouterContextKey).(common.RouteIO)
|
||||
|
||||
if !ok {
|
||||
return errors.New("net.tcp.client unable to get router from context")
|
||||
}
|
||||
woc.router = router
|
||||
woc.ctx = ctx
|
||||
|
||||
element := js.Global().Get("document").Call("getElementById", woc.ElementId)
|
||||
|
||||
if element.IsNull() || element.IsUndefined() {
|
||||
return fmt.Errorf("web.onclick unable to find element with id: %s", woc.ElementId)
|
||||
}
|
||||
|
||||
element.Set("onclick", js.FuncOf(func(js.Value, []js.Value) interface{} {
|
||||
if woc.router != nil {
|
||||
woc.router.HandleInput(woc.ctx, woc.Id(), time.Now())
|
||||
}
|
||||
return nil
|
||||
}))
|
||||
|
||||
<-ctx.Done()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (woc *WebOnClick) Stop() {
|
||||
}
|
||||
7
internal/module/web.go
Normal file
7
internal/module/web.go
Normal file
@@ -0,0 +1,7 @@
|
||||
//go:build js
|
||||
|
||||
package module
|
||||
|
||||
import (
|
||||
_ "gitlab.com/gomidi/midi/v2/drivers/webmididrv"
|
||||
)
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
|
||||
@@ -21,6 +21,11 @@ type HTTPRequestDo struct {
|
||||
URL *template.Template
|
||||
}
|
||||
|
||||
type HTTPResponse struct {
|
||||
Status int
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (hrd *HTTPRequestDo) Process(ctx context.Context, wrappedPayload common.WrappedPayload) (common.WrappedPayload, error) {
|
||||
|
||||
templateData := wrappedPayload
|
||||
@@ -79,7 +84,7 @@ func init() {
|
||||
"method": {
|
||||
Title: "HTTP Method",
|
||||
Type: "string",
|
||||
Enum: []any{"GET", "POST"},
|
||||
Enum: []any{"GET", "POST", "PUT", "PATCH", "DELETE"},
|
||||
},
|
||||
"url": {
|
||||
Title: "URL",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
@@ -17,11 +19,6 @@ type HTTPResponseCreate struct {
|
||||
config config.ProcessorConfig
|
||||
}
|
||||
|
||||
type HTTPResponse struct {
|
||||
Status int
|
||||
Body []byte
|
||||
}
|
||||
|
||||
func (hrc *HTTPResponseCreate) Process(ctx context.Context, wrappedPayload common.WrappedPayload) (common.WrappedPayload, error) {
|
||||
templateData := wrappedPayload
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build cgo
|
||||
//go:build cgo || js
|
||||
|
||||
package processor
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build cgo
|
||||
//go:build cgo || js
|
||||
|
||||
package processor
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build cgo
|
||||
//go:build cgo || js
|
||||
|
||||
package processor
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build cgo
|
||||
//go:build cgo || js
|
||||
|
||||
package processor
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
//go:build !js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
|
||||
102
internal/processor/web-set.go
Normal file
102
internal/processor/web-set.go
Normal file
@@ -0,0 +1,102 @@
|
||||
//go:build js
|
||||
|
||||
package processor
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log/slog"
|
||||
"syscall/js"
|
||||
|
||||
"github.com/google/jsonschema-go/jsonschema"
|
||||
"github.com/jwetzell/showbridge-go/internal/common"
|
||||
"github.com/jwetzell/showbridge-go/internal/config"
|
||||
)
|
||||
|
||||
type WebSet struct {
|
||||
config config.ProcessorConfig
|
||||
ModuleId string
|
||||
ElementId string
|
||||
Property string
|
||||
Value *template.Template
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
func (kvs *WebSet) Process(ctx context.Context, wrappedPayload common.WrappedPayload) (common.WrappedPayload, error) {
|
||||
|
||||
element := js.Global().Get("document").Call("getElementById", kvs.ElementId)
|
||||
|
||||
if element.IsNull() || element.IsUndefined() {
|
||||
wrappedPayload.End = true
|
||||
return wrappedPayload, fmt.Errorf("web.set unable to find element with id: %s", kvs.ElementId)
|
||||
}
|
||||
|
||||
var valueBuffer bytes.Buffer
|
||||
err := kvs.Value.Execute(&valueBuffer, wrappedPayload)
|
||||
|
||||
if err != nil {
|
||||
wrappedPayload.End = true
|
||||
return wrappedPayload, err
|
||||
}
|
||||
|
||||
element.Set(kvs.Property, valueBuffer.String())
|
||||
return wrappedPayload, nil
|
||||
}
|
||||
|
||||
func (kvs *WebSet) Type() string {
|
||||
return kvs.config.Type
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterProcessor(ProcessorRegistration{
|
||||
Type: "web.set",
|
||||
Title: "Set Web Element Property",
|
||||
ParamsSchema: &jsonschema.Schema{
|
||||
Type: "object",
|
||||
Properties: map[string]*jsonschema.Schema{
|
||||
"id": {
|
||||
Title: "Element ID",
|
||||
Type: "string",
|
||||
},
|
||||
"property": {
|
||||
Title: "Property",
|
||||
Type: "string",
|
||||
},
|
||||
"value": {
|
||||
Title: "Value",
|
||||
Type: "string",
|
||||
},
|
||||
},
|
||||
Required: []string{"id", "property", "value"},
|
||||
AdditionalProperties: nil,
|
||||
},
|
||||
New: func(config config.ProcessorConfig) (Processor, error) {
|
||||
|
||||
params := config.Params
|
||||
|
||||
idString, err := params.GetString("id")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("web.set id error: %w", err)
|
||||
}
|
||||
|
||||
propertyString, err := params.GetString("property")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("web.set property error: %w", err)
|
||||
}
|
||||
|
||||
valueString, err := params.GetString("value")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("web.set value error: %w", err)
|
||||
}
|
||||
valueTemplate, err := template.New("template").Parse(valueString)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &WebSet{config: config, ElementId: idString, Property: propertyString, Value: valueTemplate, logger: slog.Default().With("component", "processor", "type", config.Type)}, nil
|
||||
},
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user