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"
"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() {

113
events.go
View File

@ -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)
}
}()
}