93 lines
2.4 KiB
Go
93 lines
2.4 KiB
Go
|
package obsws
|
||
|
|
||
|
import (
|
||
|
"strconv"
|
||
|
"sync"
|
||
|
"time"
|
||
|
|
||
|
"github.com/gorilla/websocket"
|
||
|
"github.com/mitchellh/mapstructure"
|
||
|
)
|
||
|
|
||
|
const bufferSize = 100
|
||
|
|
||
|
var (
|
||
|
receiveTimeout = time.Duration(0)
|
||
|
messageID = 0
|
||
|
lock = sync.Mutex{}
|
||
|
)
|
||
|
|
||
|
// Client is the interface to obs-websocket.
|
||
|
// Client{Host: "localhost", Port: 4444} will probably work if you haven't configured OBS.
|
||
|
type Client struct {
|
||
|
Host string // Host (probably "localhost").
|
||
|
Port int // Port (OBS default is 4444).
|
||
|
Password string // Password (OBS default is "").
|
||
|
conn *websocket.Conn // Underlying connection to OBS.
|
||
|
receiveTimeout time.Duration // Maximum blocking time for receiving request responses
|
||
|
connected bool // True until Disconnect is called.
|
||
|
handlers map[string]func(e Event) // Event handlers.
|
||
|
respQ chan map[string]interface{} // Queue of received responses.
|
||
|
}
|
||
|
|
||
|
// poll listens for responses/events.
|
||
|
// This function blocks until Disconnect is called.
|
||
|
func (c *Client) poll() {
|
||
|
Logger.Println("started polling")
|
||
|
|
||
|
for c.connected {
|
||
|
m := make(map[string]interface{})
|
||
|
if err := c.conn.ReadJSON(&m); err != nil {
|
||
|
if !c.connected {
|
||
|
return
|
||
|
}
|
||
|
Logger.Println("read from WS:", err)
|
||
|
continue
|
||
|
}
|
||
|
|
||
|
if _, ok := m["message-id"]; ok {
|
||
|
c.handleResponse(m)
|
||
|
} else {
|
||
|
c.handleEvent(m)
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Connected returns wheter or not the client is connected.
|
||
|
func (c *Client) Connected() bool {
|
||
|
return c.connected
|
||
|
}
|
||
|
|
||
|
// SetReceiveTimeout sets the maximum blocking time for receiving request responses.
|
||
|
// If set to 0 (the default), there is no timeout.
|
||
|
func SetReceiveTimeout(timeout time.Duration) {
|
||
|
receiveTimeout = timeout
|
||
|
}
|
||
|
|
||
|
// getMessageID generates a string that the client has not yet used.
|
||
|
func getMessageID() string {
|
||
|
lock.Lock()
|
||
|
messageID++
|
||
|
id := strconv.Itoa(messageID)
|
||
|
lock.Unlock()
|
||
|
return id
|
||
|
}
|
||
|
|
||
|
// mapToStruct serializes a map into a struct.
|
||
|
func mapToStruct(data map[string]interface{}, dest interface{}) error {
|
||
|
decoder, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
|
||
|
TagName: "json",
|
||
|
Result: dest,
|
||
|
})
|
||
|
if err != nil {
|
||
|
Logger.Println("initializing decoder:", err)
|
||
|
return err
|
||
|
}
|
||
|
if err = decoder.Decode(data); err != nil {
|
||
|
Logger.Printf("unmarshalling map -> %T: %v", dest, err)
|
||
|
Logger.Printf("input: %#v\n", data)
|
||
|
return err
|
||
|
}
|
||
|
return nil
|
||
|
}
|