rs8/cmd/obsconnect/obs.go

344 lines
8.4 KiB
Go

package main
import (
obs "github.com/andreykaipov/goobs"
obse "github.com/andreykaipov/goobs/api/events"
obss "github.com/andreykaipov/goobs/api/events/subscriptions"
obssc "github.com/andreykaipov/goobs/api/requests/scenes"
obst "github.com/andreykaipov/goobs/api/requests/transitions"
"github.com/rileys-trash-can/rs8"
"gopkg.in/yaml.v3"
"log"
"math/rand"
"os"
"os/exec"
"time"
)
var Config config
type config struct {
Serial string `yaml:"serial.port"`
Boolshit bool `yaml:"boolshit"` // enables disables bullshit
OBSAddr string `yaml:"obs.addr"` // ip with port
OBSPass string `yaml:"obs.pass"` // password
TransAuto string `yaml:"trans.auto"` // transition used for auto button
TransTake string `yaml:"trans.take"` // transition used for take button
}
func readconfig() {
f, err := os.OpenFile("config.yml", os.O_RDONLY, 0755)
if err != nil {
log.Fatalf("Failed to open config: %s", err)
}
defer f.Close()
dec := yaml.NewDecoder(f)
err = dec.Decode(&Config)
if err != nil {
log.Fatalf("Failed to decode config: %s", err)
}
}
func main() {
log.SetFlags(log.Flags() | log.Lshortfile)
readconfig()
port := Config.Serial
conn, err := rs8.Open(port)
if err != nil {
log.Fatalf("Failed to connect: %s", err)
}
// conn.InitBlynk()
ch := conn.ReadCh()
obsc, err := obs.New(Config.OBSAddr,
obs.WithPassword(Config.OBSPass),
obs.WithEventSubscriptions(obss.Scenes),
)
if err != nil {
log.Fatalf("Failed to connect: %s", err)
}
t, err := obsc.Transitions.GetTransitionKindList()
if err != nil {
log.Fatalf("Failed to connect gtkl: %s", err)
}
for _, name := range t.TransitionKinds {
log.Printf(" > %s", name)
}
sl, err := obsc.Scenes.GetSceneList()
if err != nil {
log.Fatalf("Failed to gsl: %s", err)
}
sceneindex := make([]string, 8)
scenenamemap := make(map[string]int)
lim := lower(len(sl.Scenes), 8)
for i := 0; i < lim; i++ {
sceneindex[i] = sl.Scenes[lim-i-1].SceneName
scenenamemap[sl.Scenes[lim-i-1].SceneName] = i
}
for k, v := range sceneindex {
log.Printf("%d %v", k, v)
}
log.Printf("scenemap: %+#v", scenenamemap)
const (
TBAR uint8 = iota
)
ticker := time.NewTicker(time.Second / 10)
changed := make(map[uint8]struct{})
debounce := make(map[uint16]time.Time)
var tbarbos float64
deb := func(t uint16) bool {
now := time.Now()
last, ok := debounce[t]
if !ok {
debounce[t] = now
return false
}
if last.Before(now.Add(-time.Millisecond * 100)) {
debounce[t] = now
return false
}
return true
}
go obsc.Listen(func(l any) {
switch event := l.(type) {
case *obse.CurrentPreviewSceneChanged:
log.Printf("current preview scene: %s %d", event.SceneName, scenenamemap[event.SceneName]+1)
program := make([]rs8.CmdLight, 0)
for i := uint8(0); i < 8; i++ {
program = append(program, rs8.CmdLight{
Type: rs8.ButtonPreview,
Value: i,
State: rs8.LightOff,
})
}
program[7-scenenamemap[event.SceneName]].State = rs8.LightOn
conn.LightCmdCh <- program
break
case *obse.CurrentProgramSceneChanged:
log.Printf("current program scene: %s %d", event.SceneName, scenenamemap[event.SceneName]+1)
program := make([]rs8.CmdLight, 0)
for i := uint8(0); i < 8; i++ {
program = append(program, rs8.CmdLight{
Type: rs8.ButtonProgram,
Value: i,
State: rs8.LightOff,
})
}
program[7-scenenamemap[event.SceneName]].State = rs8.LightOn
conn.LightCmdCh <- program
break
default:
//log.Printf("non handled thingy %T", event)
break
}
})
for {
select {
case <-ticker.C:
if _, ok := changed[TBAR]; ok {
_, err = obsc.Transitions.SetTBarPosition(&obst.SetTBarPositionParams{
Position: i(tbarbos),
Release: i(tbarbos == 0 || tbarbos == 1),
})
if err != nil {
log.Printf("Error setting tbar: %s", err)
}
}
changed = make(map[uint8]struct{})
case e := <-ch:
switch event := e.(type) {
case *rs8.EventButton:
if event.Direction != 0 {
continue
}
switch event.Type {
case rs8.ButtonProgram:
log.Printf("Setting Program to %d", 7-event.Value)
obsc.Scenes.SetCurrentProgramScene(&obssc.SetCurrentProgramSceneParams{
SceneName: &sceneindex[7-event.Value],
})
break
case rs8.ButtonPreview:
log.Printf("Setting Program to %d", 7-event.Value)
obsc.Scenes.SetCurrentPreviewScene(&obssc.SetCurrentPreviewSceneParams{
SceneName: &sceneindex[7-event.Value],
})
break
case rs8.ButtonAutoTakeDSK:
switch event.Value {
case 0x01: // TAKE or 0x02
if deb(rs8.ButtonAutoTakeDSK<<8 | 0x01) {
continue
}
go func() {
oldprog, err := obsc.Scenes.GetCurrentProgramScene()
if err != nil {
log.Printf("oldprogram: %s (uuid %s)", oldprog.SceneName, oldprog.SceneUuid)
}
_, err = obsc.Transitions.SetCurrentSceneTransition(&obst.SetCurrentSceneTransitionParams{
TransitionName: &Config.TransTake,
})
if err != nil {
log.Printf("set transition: %s", err)
}
_, err = obsc.Transitions.TriggerStudioModeTransition()
if err != nil {
log.Printf("Studiomodetransition: %s", err)
}
_, err = obsc.Scenes.SetCurrentPreviewScene(&obssc.SetCurrentPreviewSceneParams{
SceneUuid: &oldprog.SceneUuid,
})
if err != nil {
log.Printf("set current preview: %s", err)
}
}()
case 0x03: // AUTO
go func() {
oldprog, err := obsc.Scenes.GetCurrentProgramScene()
if err != nil {
log.Printf("oldprogram: %s (uuid %s)", oldprog.SceneName, oldprog.SceneUuid)
}
_, err = obsc.Transitions.SetCurrentSceneTransition(&obst.SetCurrentSceneTransitionParams{
TransitionName: &Config.TransAuto,
})
if err != nil {
log.Printf("set transition: %s", err)
}
_, err = obsc.Transitions.TriggerStudioModeTransition()
if err != nil {
log.Printf("Studiomodetransition: %s", err)
}
_, err = obsc.Scenes.SetCurrentPreviewScene(&obssc.SetCurrentPreviewSceneParams{
SceneUuid: &oldprog.SceneUuid,
})
if err != nil {
log.Printf("set current preview: %s", err)
}
}()
if Config.Boolshit {
go exec.Command("gti").Run()
}
case 0x05: // DDR
if Config.Boolshit {
println(" ____ ____ ____\n| _ \\| _ \\| _ \\\n| | | | | | | |_) |\n| |_| | |_| | _ <\n|____/|____/|_| \\_\\")
println(ddrquote())
}
}
}
break
case *rs8.EventSlider:
if event.Type == rs8.SliderTbar {
value := (float64(event.Value)) / 250
if value > 1 {
value = 1
}
if value < 0 {
value = 0
}
log.Printf("tbar %1.3f", value)
tbarbos = value
changed[TBAR] = struct{}{}
continue
}
log.Printf("%X %3d", event.Type, event.Value)
}
}
}
obsc.Disconnect()
}
func i[K any](a K) *K {
return &a
}
func lower(a, b int) int {
if a > b {
return b
}
return a
}
var ddrquotes = []string{
"Niemand hat die Absicht eine Mauer zu bauen",
"Den Sozialismus in seinem Lauf, hält weder Ochs noch Esel auf.",
"Frieden ist nicht alles, aber ohne Frieden ist alles nichts.",
"Wir müssen lernen, wie die Gesellschaft so zu gestalten, dass die Menschen glücklich sind.",
"Die Partei hat immer recht.",
"Vorwärts immer, rückwärts nimmer!",
"Den Sozialismus in seinem Lauf, hält weder Ochs noch Esel auf.",
"Frieden ist nicht alles, aber ohne Frieden ist alles nichts.",
"Wir müssen lernen, wie die Gesellschaft so zu gestalten, dass die Menschen glücklich sind.",
"Die Partei hat immer recht.",
"Vorwärts immer, rückwärts nimmer!",
"Wer kämpft, kann verlieren. Wer nicht kämpft, hat schon verloren.",
"Es muss demokratisiert werden im tiefsten Sinne des Wortes, die Wirtschaft, die Wissenschaft, das kulturelle Leben.",
"Freundschaft, das ist das schönste auf der Welt.",
"Niemand hat die Absicht, eine Mauer zu errichten.",
"Die Wahrheit ist, dass wir noch nicht da sind, wo wir sein sollten.",
"Die Zukunft gehört dem Sozialismus.",
"Der Weg der sozialistischen Partei ist der Weg des Volkes.",
"Wir haben das Glück, in einer Zeit zu leben, in der wir Zeugen eines großen historischen Wandels sind.",
"Sozialismus ist das Gegenteil von Egoismus.",
"Die Kunst ist eine Waffe der Revolution.",
}
func ddrquote() string {
return ddrquotes[rand.Intn(len(ddrquotes))]
}