diff --git a/bot.go b/bot.go index 3a70482..32d416e 100644 --- a/bot.go +++ b/bot.go @@ -5,6 +5,7 @@ import ( "log" "os" "os/signal" + "sync" "syscall" "time" @@ -43,6 +44,9 @@ func init() { if err != nil { log.Fatal(err) } + + app.plmutex = &sync.Mutex{} + log.Println("bot.go done.") } @@ -50,11 +54,9 @@ type App struct { discord *discordgo.Session voice *discordgo.VoiceConnection youtube *youtube.Service - queue *Queue ambiance beep.Mixer curamb Ambiance events events.EventEmmiter - next bool db *pgx.Conn router *httprouter.Router active []string @@ -63,6 +65,8 @@ type App struct { mpdc context.CancelFunc mpdw *mpd.Watcher mpd *mpd.Client + plmutex *sync.Mutex + plcancel context.CancelFunc } func main() { diff --git a/events.go b/events.go index 05f57b7..13f80c0 100644 --- a/events.go +++ b/events.go @@ -1,6 +1,7 @@ package main import ( + "context" "dndmusicbot/opus" discordspeaker "dndmusicbot/speaker" "encoding/json" @@ -305,7 +306,12 @@ func (app *App) songInfo(payload ...interface{}) { func (app *App) stop(payload ...interface{}) { log.Println("stop event received") + app.plmutex.Lock() + if app.plcancel != nil { + app.plcancel() + } app.mpd.Stop() + app.plmutex.Unlock() msg := make(map[string]interface{}) msg["event"] = "stop" @@ -315,7 +321,9 @@ func (app *App) stop(payload ...interface{}) { func (app *App) prevSong(payload ...interface{}) { log.Println("prev_song event received") + app.plmutex.Lock() err := app.mpd.Previous() + app.plmutex.Unlock() if err != nil { log.Println(err) } @@ -323,7 +331,10 @@ func (app *App) prevSong(payload ...interface{}) { func (app *App) nextSong(payload ...interface{}) { log.Println("next_song event received") + + app.plmutex.Lock() err := app.mpd.Next() + app.plmutex.Unlock() if err != nil { log.Println(err) } @@ -431,12 +442,23 @@ func (app *App) loadPlaylist(payload ...interface{}) { log.Println("Unable to shuffle playlist") return } - + app.plmutex.Lock() + if app.plcancel != nil { + app.plcancel() + } app.mpd.Stop() app.mpd.Clear() + app.plmutex.Unlock() + + ctx, cancel := context.WithCancel(context.Background()) + app.plcancel = cancel go func() { + defer cancel() + for _, vid := range list { + log.Printf("Adding %s", vid) + ytinfo, err := app.Video(vid) if err != nil { log.Println(err) @@ -455,43 +477,60 @@ func (app *App) loadPlaylist(payload ...interface{}) { continue } - // state:stop - songid, err := app.mpd.AddID(string(yt), 0) - if err != nil { - log.Println(err) - continue + // Run as a local function so we can defer the mutex unlock incase one of these errors. + ok := func() (ok bool) { + app.plmutex.Lock() + defer app.plmutex.Unlock() + + if ctx.Err() != nil { + return false + } + + ok = true + + // state:stop + songid, err := app.mpd.AddID(string(yt), 0) + if err != nil { + log.Println(err) + return + } + + mpdcmd := app.mpd.Command("%s %d %s %s", mpd.Quoted("addtagid"), songid, mpd.Quoted("artist"), ytinfo.Channel) + err = mpdcmd.OK() + if err != nil { + log.Println(err) + return + } + + mpdcmd = app.mpd.Command("%s %d %s %s", mpd.Quoted("addtagid"), songid, mpd.Quoted("title"), ytinfo.Title) + err = mpdcmd.OK() + if err != nil { + log.Println(err) + return + } + + mpdcmd = app.mpd.Command("%s %d %s %s", mpd.Quoted("addtagid"), songid, mpd.Quoted("location"), vid) + err = mpdcmd.OK() + if err != nil { + log.Println(err) + return + } + + mpdcmd = app.mpd.Command("%s %d %s %s", mpd.Quoted("addtagid"), songid, mpd.Quoted("album"), pl.Id.String()) + err = mpdcmd.OK() + if err != nil { + log.Println(err) + return + } + + app.mpd.Play(-1) + + return + }() + + if !ok { + break } - - mpdcmd := app.mpd.Command("%s %d %s %s", mpd.Quoted("addtagid"), songid, mpd.Quoted("artist"), ytinfo.Channel) - err = mpdcmd.OK() - if err != nil { - log.Println(err) - continue - } - - mpdcmd = app.mpd.Command("%s %d %s %s", mpd.Quoted("addtagid"), songid, mpd.Quoted("title"), ytinfo.Title) - err = mpdcmd.OK() - if err != nil { - log.Println(err) - continue - } - - mpdcmd = app.mpd.Command("%s %d %s %s", mpd.Quoted("addtagid"), songid, mpd.Quoted("location"), vid) - err = mpdcmd.OK() - if err != nil { - log.Println(err) - continue - } - - mpdcmd = app.mpd.Command("%s %d %s %s", mpd.Quoted("addtagid"), songid, mpd.Quoted("album"), pl.Id.String()) - err = mpdcmd.OK() - if err != nil { - log.Println(err) - continue - } - - app.mpd.Play(-1) - } }() }