Add mutex and context for better playlist handling

nostruct
Stein Ivar Berghei 2022-11-28 14:02:17 +01:00
parent 8a3e07c1d1
commit 16498a8c7d
2 changed files with 82 additions and 39 deletions

8
bot.go
View File

@ -5,6 +5,7 @@ import (
"log" "log"
"os" "os"
"os/signal" "os/signal"
"sync"
"syscall" "syscall"
"time" "time"
@ -43,6 +44,9 @@ func init() {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
app.plmutex = &sync.Mutex{}
log.Println("bot.go done.") log.Println("bot.go done.")
} }
@ -50,11 +54,9 @@ type App struct {
discord *discordgo.Session discord *discordgo.Session
voice *discordgo.VoiceConnection voice *discordgo.VoiceConnection
youtube *youtube.Service youtube *youtube.Service
queue *Queue
ambiance beep.Mixer ambiance beep.Mixer
curamb Ambiance curamb Ambiance
events events.EventEmmiter events events.EventEmmiter
next bool
db *pgx.Conn db *pgx.Conn
router *httprouter.Router router *httprouter.Router
active []string active []string
@ -63,6 +65,8 @@ type App struct {
mpdc context.CancelFunc mpdc context.CancelFunc
mpdw *mpd.Watcher mpdw *mpd.Watcher
mpd *mpd.Client mpd *mpd.Client
plmutex *sync.Mutex
plcancel context.CancelFunc
} }
func main() { func main() {

113
events.go
View File

@ -1,6 +1,7 @@
package main package main
import ( import (
"context"
"dndmusicbot/opus" "dndmusicbot/opus"
discordspeaker "dndmusicbot/speaker" discordspeaker "dndmusicbot/speaker"
"encoding/json" "encoding/json"
@ -305,7 +306,12 @@ func (app *App) songInfo(payload ...interface{}) {
func (app *App) stop(payload ...interface{}) { func (app *App) stop(payload ...interface{}) {
log.Println("stop event received") log.Println("stop event received")
app.plmutex.Lock()
if app.plcancel != nil {
app.plcancel()
}
app.mpd.Stop() app.mpd.Stop()
app.plmutex.Unlock()
msg := make(map[string]interface{}) msg := make(map[string]interface{})
msg["event"] = "stop" msg["event"] = "stop"
@ -315,7 +321,9 @@ func (app *App) stop(payload ...interface{}) {
func (app *App) prevSong(payload ...interface{}) { func (app *App) prevSong(payload ...interface{}) {
log.Println("prev_song event received") log.Println("prev_song event received")
app.plmutex.Lock()
err := app.mpd.Previous() err := app.mpd.Previous()
app.plmutex.Unlock()
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
@ -323,7 +331,10 @@ func (app *App) prevSong(payload ...interface{}) {
func (app *App) nextSong(payload ...interface{}) { func (app *App) nextSong(payload ...interface{}) {
log.Println("next_song event received") log.Println("next_song event received")
app.plmutex.Lock()
err := app.mpd.Next() err := app.mpd.Next()
app.plmutex.Unlock()
if err != nil { if err != nil {
log.Println(err) log.Println(err)
} }
@ -431,12 +442,23 @@ func (app *App) loadPlaylist(payload ...interface{}) {
log.Println("Unable to shuffle playlist") log.Println("Unable to shuffle playlist")
return return
} }
app.plmutex.Lock()
if app.plcancel != nil {
app.plcancel()
}
app.mpd.Stop() app.mpd.Stop()
app.mpd.Clear() app.mpd.Clear()
app.plmutex.Unlock()
ctx, cancel := context.WithCancel(context.Background())
app.plcancel = cancel
go func() { go func() {
defer cancel()
for _, vid := range list { for _, vid := range list {
log.Printf("Adding %s", vid)
ytinfo, err := app.Video(vid) ytinfo, err := app.Video(vid)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
@ -455,43 +477,60 @@ func (app *App) loadPlaylist(payload ...interface{}) {
continue continue
} }
// state:stop // Run as a local function so we can defer the mutex unlock incase one of these errors.
songid, err := app.mpd.AddID(string(yt), 0) ok := func() (ok bool) {
if err != nil { app.plmutex.Lock()
log.Println(err) defer app.plmutex.Unlock()
continue
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)
} }
}() }()
} }