Closed jess-sch closed 6 years ago
Side note: Same thing happens when I use URIs
with a slice containing one URI instead of PlaybackContext
You're surely not stupid! Can you share a little more of your main.go
?
main.go basically looks like this (mostly a copy-paste of that player example):
// - Use "http://localhost:8080/callback" as the redirect URI
// 2. Set the SPOTIFY_ID environment variable to the client ID you got in step 1.
// 3. Set the SPOTIFY_SECRET environment variable to the client secret from step 1.
package main
import (
"fmt"
"log"
"net/http"
"github.com/zmb3/spotify"
)
const redirectURI = "http://localhost:8080/callback"
var (
auth = spotify.NewAuthenticator(redirectURI, spotify.ScopeUserReadCurrentlyPlaying, spotify.ScopeUserReadPlaybackState, spotify.ScopeUserModifyPlaybackState)
ch = make(chan *spotify.Client)
state = "abc123"
)
var queue []spotify.SimpleTrack
func main() {
// We'll want these variables sooner rather than later
var client *spotify.Client
var playerState *spotify.PlayerState
go mgmt(client)
http.HandleFunc("/callback", completeAuth)
http.HandleFunc("/queue/", func(w http.ResponseWriter, r *http.Request) {
[...]
})
http.HandleFunc("/add/", func(w http.ResponseWriter, r *http.Request) {
[...]
})
http.HandleFunc("/search/", func(w http.ResponseWriter, r *http.Request) {
[...]
})
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
[...]
})
go func() {
url := auth.AuthURL(state)
fmt.Println("Please log in to Spotify by visiting the following page in your browser:", url)
// wait for auth to complete
client = <-ch
// use the client to make calls that require authorization
user, err := client.CurrentUser()
if err != nil {
log.Fatal(err)
}
fmt.Println("You are logged in as:", user.ID)
playerState, err = client.PlayerState()
if err != nil {
log.Fatal(err)
}
fmt.Printf("Found your %s (%s)\n", playerState.Device.Type, playerState.Device.Name)
}()
http.ListenAndServe(":8080", nil)
}
func completeAuth(w http.ResponseWriter, r *http.Request) {
tok, err := auth.Token(state, r)
if err != nil {
http.Error(w, "Couldn't get token", http.StatusForbidden)
log.Fatal(err)
}
if st := r.FormValue("state"); st != state {
http.NotFound(w, r)
log.Fatalf("State mismatch: %s != %s\n", st, state)
}
// use the token to get an authenticated client
client := auth.NewClient(tok)
w.Header().Set("Content-Type", "text/html")
w.Write([]byte(`<meta http-equiv="refresh" content="0; url=/" />`))
ch <- &client
}
But I think you may be more interested in the function that actually tells spotify to play the music:
for true{
if len(queue) > 0 {
client.PlayOpt(&spotify.PlayOptions{PlayContext: &queue[0].URI})
time.Sleep(time.Second * time.Duration(queue[0].Duration)
queue = queue[1:]
}else{
time.Sleep(time.Second * 5)
}
}
(Queue is a global []spotify.SimpleTrack
)
My best guess is that you're sharing the client
variable across goroutines without proper synchronization. It may help you use the -race
flag to help diagnose data races.
So now I was able to fix this race condition. Which doesn't fix my issue because I'm still getting SIGSEGV.
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x10 pc=0x76e98e]
goroutine 19 [running]:
github.com/zmb3/spotify.(*Client).PlayOpt(0x0, 0xc4201a4090, 0x0, 0x0)
/home/lumi/go/src/github.com/zmb3/spotify/player.go:286 +0x7e
main.mgmt(0x0, 0xc42007e180)
/home/lumi/Projects/spotiman/mgmt.go:52 +0x160
created by main.main
/home/lumi/Projects/spotiman/main.go:43 +0x109
the line in mgmt.go which causes the SIGSEGV is client.PlayOpt(&spotify.PlayOptions{PlaybackContext: &queue[0].URI})
I believe this issue is caused by this package. c.baseURL
doesn't seem to be set, that's why we're getting a nil pointer dereference.
Sorry, I can't provide comprehensive troubleshooting with a limited view of the code. If you can create a small reproducible example I'd be happy to take a closer look.
Okay so this issue does indeed seem to be o my part... nvm.
Finally fixed it, seems to be that starting the goroutine that controls playback before the auth has completed results in a crash
client.PlayOpt(&spotify.PlayOptions{PlaybackContext: &spotify.URI("SOME_URI")})
always results in a crash. Am I stupid or is this a bug?