commit 7afbff6a129e4fee1ff932312119435ee3311904 Author: Ilya Suhodolskiy Date: Sat May 13 19:20:49 2023 +0400 Initial commit diff --git a/.github/cover.jpg b/.github/cover.jpg new file mode 100644 index 0000000..f02475f Binary files /dev/null and b/.github/cover.jpg differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6ec00ec --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.DS_Store +__debug_bin +dist \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..1a9b89f --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,14 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Run App", + "type": "go", + "request": "launch", + "mode": "auto", + "program": "${workspaceFolder}/main.go", + "cwd": "${workspaceFolder}", + "args": ["-port", "5173"] + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..ee49d70 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cSpell.words": ["ctrack", "osascript", "tmpl"] +} diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..be7ba57 --- /dev/null +++ b/Makefile @@ -0,0 +1,2 @@ +build_app: + go build -ldflags="-s -w" -o ./dist/obs-spotify ./main.go \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..28bd811 --- /dev/null +++ b/README.md @@ -0,0 +1,16 @@ +# OBS Spotify + +![Cover](https://github.com/suhodolskiy/obs-spotify/blob/main/.github/cover.jpg) + +## How to use? + +1. Download ZIP from last release +2. Open obs-spotify binary +3. Add new "Browser" source in OBS +4. Add http://localhost:3000 url +5. Save source + +### Options + +1. `obs-spotify` accepts the port argument. Example ./obs-spotify -port=8888 +2. `?refresh=5s` diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a0bb7de --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module spotify-obs + +go 1.18 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e69de29 diff --git a/index.html b/index.html new file mode 100644 index 0000000..37690cb --- /dev/null +++ b/index.html @@ -0,0 +1,75 @@ + + + + + + + Spotify + + + +
+
+ +
+
+ {{ .Track.Name }} +
{{ .Track.Artist }}
+
+
+ + + diff --git a/main.go b/main.go new file mode 100644 index 0000000..e4e4bb7 --- /dev/null +++ b/main.go @@ -0,0 +1,119 @@ +package main + +import ( + "encoding/json" + "flag" + "fmt" + "net/http" + "os" + "os/exec" + "path/filepath" + "text/template" + "time" +) + +const command = ` + tell application "Spotify" + set ctrack to "{" + set ctrack to ctrack & "\"artist\": \"" & current track's artist & "\"" + set ctrack to ctrack & ",\"album\": \"" & current track's album & "\"" + set ctrack to ctrack & ",\"discNumber\": " & current track's disc number + set ctrack to ctrack & ",\"duration\": " & current track's duration + set ctrack to ctrack & ",\"playedCount\": " & current track's played count + set ctrack to ctrack & ",\"trackNumber\": " & current track's track number + set ctrack to ctrack & ",\"popularity\": " & current track's popularity + set ctrack to ctrack & ",\"id\": \"" & current track's id & "\"" + set ctrack to ctrack & ",\"position\": " & (player position as integer) + set ctrack to ctrack & ",\"name\": \"" & current track's name & "\"" + set ctrack to ctrack & ",\"albumArtist\": \"" & current track's album artist & "\"" + set ctrack to ctrack & ",\"artworkUrl\": \"" & current track's artwork url & "\"" + set ctrack to ctrack & ",\"spotifyUrl\": \"" & current track's spotify url & "\"" + set ctrack to ctrack & "}" + + return ctrack + end tell` + +type SpotifyCurrentTrack struct { + Artist string `json:"artist"` + Album string `json:"album"` + DiscNumber int `json:"discNumber"` + Duration int `json:"duration"` + PlayedCount int `json:"playedCount"` + TrackNumber int `json:"trackNumber"` + Popularity int `json:"popularity"` + ID string `json:"id"` + Name string `json:"name"` + Position int `json:"position"` + AlbumArtist string `json:"albumArtist"` + ArtworkURL string `json:"artworkUrl"` + SpotifyURL string `json:"spotifyUrl"` +} + +type Response struct { + Track SpotifyCurrentTrack + Refresh int64 + Port string +} + +func getCurrentTrack() SpotifyCurrentTrack { + currentTrack := SpotifyCurrentTrack{} + + cmd := exec.Command("osascript", "-e", command) + + output, err := cmd.CombinedOutput() + + if err != nil { + return currentTrack + } + + if err := json.Unmarshal(output, ¤tTrack); err != nil { + return currentTrack + } + + return currentTrack +} + +func main() { + port := flag.String("port", "5783", "http port") + flag.Parse() + + ex, _ := os.Executable() + tmpl, err := template.ParseFiles(filepath.Join(ex, "../index.html")) + + if err != nil { + panic(err) + } + + http.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) { + response := Response{ + Track: getCurrentTrack(), + Refresh: time.Second.Milliseconds(), + Port: *port, + } + + refreshQueryParam := req.URL.Query().Get("refresh") + + if refreshQueryParam != "" { + if duration, err := time.ParseDuration(refreshQueryParam); err == nil { + response.Refresh = duration.Milliseconds() + } + } + + if err := tmpl.Execute(w, response); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } + }) + + http.HandleFunc("/track", func(w http.ResponseWriter, req *http.Request) { + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Access-Control-Allow-Origin", "*") + + resp, _ := json.Marshal(getCurrentTrack()) + + fmt.Fprint(w, string(resp)) + }) + + fmt.Printf("The server is running on port %s!", *port) + + http.ListenAndServe(fmt.Sprintf(":%s", *port), nil) +}