-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
157 lines (128 loc) · 3.61 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// main.go
// Copyright (C) 2024 Ricardo Melo
//
// Distributed under terms of the MIT license.
package main
import (
"flag"
"fmt"
"log"
"os"
"time"
obsws "github.com/christopher-dG/go-obs-websocket"
)
// Config holds the application configuration
type Config struct {
host string
port int
scene1 string
scene2 string
timeout time.Duration
verbose bool
}
var osExit = os.Exit
var (
version = "dev"
commit = "none"
date = "unknown"
)
func main() {
// Initialize logging
log.SetFlags(log.LstdFlags | log.Lshortfile)
// Parse configuration
config := parseFlags()
if config.verbose {
log.Printf("Connecting to OBS at %s:%d\n", config.host, config.port)
log.Printf("Switching between scenes: %s and %s\n", config.scene1, config.scene2)
}
// Create and configure client
client := createClient(config)
defer client.Disconnect()
// Connect with timeout
if err := connectWithTimeout(&client, config.timeout); err != nil {
log.Fatalf("Failed to connect to OBS: %v", err)
}
if err := switchScene(client, config); err != nil {
log.Fatalf("Failed to switch scene: %v", err)
}
}
// parseFlags handles command-line argument parsing and validation
func parseFlags() Config {
config := Config{}
// Add version flag
showVersion := flag.Bool("version", false, "Show version information")
flag.StringVar(&config.host, "host", "localhost", "OBS WebSocket host")
flag.IntVar(&config.port, "port", 4444, "OBS WebSocket port")
flag.DurationVar(&config.timeout, "timeout", 5*time.Second, "Connection timeout")
flag.BoolVar(&config.verbose, "verbose", false, "Enable verbose logging")
// Custom usage message
flag.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: %s [options] <scene1> <scene2>\n\nOptions:\n", os.Args[0])
flag.PrintDefaults()
}
flag.Parse()
// Check if version flag was set
if *showVersion {
fmt.Printf("obs_switchscene %s (commit: %s, built at: %s)\n", version, commit, date)
osExit(0)
}
// Validate positional arguments
args := flag.Args()
if len(args) != 2 {
flag.Usage()
osExit(1)
}
config.scene1 = args[0]
config.scene2 = args[1]
return config
}
// createClient creates and configures an OBS WebSocket client
func createClient(config Config) obsws.Client {
return obsws.Client{
Host: config.host,
Port: config.port,
}
}
// connectWithTimeout attempts to connect to OBS with a timeout
func connectWithTimeout(client *obsws.Client, timeout time.Duration) error {
connectionChan := make(chan error, 1)
go func() {
connectionChan <- client.Connect()
}()
select {
case <-time.After(timeout):
return fmt.Errorf("connection timeout after %v", timeout)
case err := <-connectionChan:
return err
}
}
// switchScene handles the scene switching logic
func switchScene(client obsws.Client, config Config) error {
// Get current scene
sceneList, err := obsws.NewGetSceneListRequest().SendReceive(client)
if err != nil {
return fmt.Errorf("failed to get scene list: %w", err)
}
// Validate that both scenes exist
scenes := make(map[string]bool)
for _, scene := range sceneList.Scenes {
scenes[scene.Name] = true
}
if !scenes[config.scene1] || !scenes[config.scene2] {
return fmt.Errorf("one or both scenes do not exist: %s, %s", config.scene1, config.scene2)
}
// Determine which scene to switch to
targetScene := config.scene1
if sceneList.CurrentScene == config.scene1 {
targetScene = config.scene2
}
// Switch scene
if config.verbose {
log.Printf("Switching to scene: %s\n", targetScene)
}
_, err = obsws.NewSetCurrentSceneRequest(targetScene).SendReceive(client)
if err != nil {
return fmt.Errorf("failed to switch scene: %w", err)
}
return nil
}