From 8aa79a1e13495f6c112010e83011966c7fe1c80b Mon Sep 17 00:00:00 2001 From: Stein Ivar Berghei Date: Thu, 22 Dec 2022 12:43:40 +0100 Subject: [PATCH] Restructure to not use a App struct --- bot.go | 47 +++---------- db.go | 16 +++-- discord.go | 10 ++- events.go | 162 ++++++++++++++++++++++-------------------- mixer.go | 71 +++++++++++++++++++ mpd.go | 27 ++++--- queue.go | 203 ----------------------------------------------------- routes.go | 36 +++++----- ws.go | 8 +-- youtube.go | 48 +++---------- 10 files changed, 229 insertions(+), 399 deletions(-) create mode 100644 mixer.go delete mode 100644 queue.go diff --git a/bot.go b/bot.go index 9cda1af..3768de5 100644 --- a/bot.go +++ b/bot.go @@ -9,17 +9,9 @@ import ( "syscall" "time" - "github.com/diamondburned/arikawa/v3/state" - "github.com/diamondburned/arikawa/v3/voice" - "github.com/faiface/beep" - "github.com/fhs/gompd/v2/mpd" "github.com/gohugoio/hugo/cache/filecache" - "github.com/jackc/pgx/v5" - "github.com/julienschmidt/httprouter" - "github.com/kataras/go-events" "github.com/spf13/afero" "github.com/spf13/viper" - "google.golang.org/api/youtube/v3" ) const ( @@ -30,8 +22,9 @@ const ( ) var ( - app = new(App) config = viper.GetViper() + bfs = afero.NewBasePathFs(afero.NewOsFs(), "cache") + cache = filecache.NewCache(bfs, 1*time.Hour, "") ) func init() { @@ -46,34 +39,12 @@ func init() { log.Fatal(err) } - app.plmutex = &sync.Mutex{} + mpd_mutex = &sync.Mutex{} log.Println("bot.go done.") } -type App struct { - discord *state.State - voice *voice.Session - youtube *youtube.Service - ambiance beep.Mixer - curamb Ambiance - events events.EventEmmiter - db *pgx.Conn - router *httprouter.Router - active []string - plidx int - cache *filecache.Cache - mpdc context.CancelFunc - mpdw *mpd.Watcher - mpd *mpd.Client - plmutex *sync.Mutex - plcancel context.CancelFunc -} - func main() { - bfs := afero.NewBasePathFs(afero.NewOsFs(), "cache") - app.cache = filecache.NewCache(bfs, 1*time.Hour, "") - ticker := time.NewTicker(300 * time.Millisecond) ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM, os.Interrupt) @@ -82,15 +53,15 @@ func main() { for { select { case <-ctx.Done(): - app.db.Close(ctx) - app.mpdw.Close() - app.mpdc() - app.voice.Leave(ctx) + db.Close(ctx) + mpdw.Close() + mpdcf() + dvoice.Leave(ctx) dgvc() - app.discord.Close() + dstate.Close() return case <-ticker.C: - app.events.Emit("tick") + ev.Emit("tick") } } } diff --git a/db.go b/db.go index f23ecc6..6ff39f7 100644 --- a/db.go +++ b/db.go @@ -8,11 +8,13 @@ import ( "github.com/jackc/pgx/v5" ) +var db *pgx.Conn + func init() { log.Println("db.go loading..") var err error - app.db, err = pgx.Connect(context.Background(), config.GetString("db.connstring")) + db, err = pgx.Connect(context.Background(), config.GetString("db.connstring")) if err != nil { log.Fatal(err) } @@ -25,8 +27,8 @@ type Playlist struct { Title string } -func (app App) GetPlaylists() (playlists []Playlist, err error) { - rows, err := app.db.Query(context.Background(), "SELECT id, url, title FROM playlists") +func GetPlaylists() (playlists []Playlist, err error) { + rows, err := db.Query(context.Background(), "SELECT id, url, title FROM playlists") if err != nil { return nil, err } @@ -35,8 +37,8 @@ func (app App) GetPlaylists() (playlists []Playlist, err error) { return } -func (app App) GetPlaylist(id uuid.UUID) (*Playlist, error) { - rows, err := app.db.Query(context.Background(), "SELECT id, url, title FROM playlists where id=$1 limit 1", id) +func GetPlaylist(id uuid.UUID) (*Playlist, error) { + rows, err := db.Query(context.Background(), "SELECT id, url, title FROM playlists where id=$1 limit 1", id) if err != nil { return nil, err } @@ -50,9 +52,9 @@ func (app App) GetPlaylist(id uuid.UUID) (*Playlist, error) { return out, nil } -func (app App) AddPlaylist(title string, uri string) (uuid.UUID, error) { +func AddPlaylist(title string, uri string) (uuid.UUID, error) { id := uuid.New() - _, err := app.db.Exec(context.Background(), "INSERT INTO playlists VALUES ($1, $2, $3)", id, title, uri) + _, err := db.Exec(context.Background(), "INSERT INTO playlists VALUES ($1, $2, $3)", id, title, uri) if err != nil { return *new(uuid.UUID), err } diff --git a/discord.go b/discord.go index 42e3966..2f801bd 100644 --- a/discord.go +++ b/discord.go @@ -11,7 +11,11 @@ import ( "github.com/diamondburned/arikawa/v3/voice/voicegateway" ) -var dgvc context.CancelFunc +var ( + dstate *state.State + dvoice *voice.Session + dgvc context.CancelFunc +) func init() { log.Println("discord.go loading..") @@ -47,8 +51,8 @@ func init() { v.Speaking(ctx, voicegateway.NotSpeaking) - app.discord = s - app.voice = v + dstate = s + dvoice = v discordspeaker.Init(v) diff --git a/events.go b/events.go index 9d75bc7..cc5d893 100644 --- a/events.go +++ b/events.go @@ -30,40 +30,46 @@ type SongInfo struct { Song string `json:"song,omitempty"` } -var l = rate.Sometimes{Interval: 800 * time.Millisecond} +var ( + l = rate.Sometimes{Interval: 800 * time.Millisecond} +) + +var ( + ev events.EventEmmiter +) func init() { log.Println("events.go loading...") - app.events = events.New() + ev = events.New() - app.events.On("load_playlist", app.loadPlaylist) - app.events.On("add_playlist", app.addPlaylist) + ev.On("load_playlist", loadPlaylist) + ev.On("add_playlist", addPlaylist) - //app.events.On("preload_song", app.preloadSong) - //app.events.On("song_over", app.songInfo) - //app.events.On("song_start", app.songInfo) - app.events.On("player", app.songInfo) - //app.events.On("song_position", app.songPosition) + //ev.On("preload_song", app.preloadSong) + //ev.On("song_over", app.songInfo) + //ev.On("song_start", app.songInfo) + ev.On("player", songInfo) + //ev.On("song_position", app.songPosition) - app.events.On("ambiance_play", app.ambiancePlay) - app.events.On("ambiance_stop", app.ambianceStop) - app.events.On("ambiance_add", app.ambianceAdd) + ev.On("ambiance_play", ambiancePlay) + ev.On("ambiance_stop", ambianceStop) + ev.On("ambiance_add", ambianceAdd) - app.events.On("stop", app.stop) - app.events.On("next", app.nextSong) - app.events.On("prev", app.prevSong) + ev.On("stop", stop) + ev.On("next", nextSong) + ev.On("prev", prevSong) - app.events.On("vol_up", app.volup) - app.events.On("vol_down", app.voldown) - app.events.On("vol_set", app.volset) + ev.On("vol_up", volup) + ev.On("vol_down", voldown) + ev.On("vol_set", volset) - //app.events.On("tick", app.checkQueue) - app.events.On("tick", app.songPosition) - //app.events.On("tick", app.checkTimeleft) + //ev.On("tick", app.checkQueue) + ev.On("tick", songPosition) + //ev.On("tick", app.checkTimeleft) } -func (app *App) volup(payload ...interface{}) { +func volup(payload ...interface{}) { if !(len(payload) > 0) { log.Println("volup called without a payload.") return @@ -91,7 +97,7 @@ func (app *App) volup(payload ...interface{}) { } } -func (app *App) voldown(payload ...interface{}) { +func voldown(payload ...interface{}) { if !(len(payload) > 0) { log.Println("voldown called without a payload.") return @@ -119,7 +125,7 @@ func (app *App) voldown(payload ...interface{}) { } } -func (app *App) volset(payload ...interface{}) { +func volset(payload ...interface{}) { if !(len(payload) > 0) { log.Println("volset called without a payload.") return @@ -147,10 +153,10 @@ func (app *App) volset(payload ...interface{}) { amb_volume.Volume = vol } - app.sendVolume() + sendVolume() } -func (app *App) sendVolume() { +func sendVolume() { msg := make(map[string]interface{}) out := make(map[string]float64) msg["event"] = "volume" @@ -160,16 +166,16 @@ func (app *App) sendVolume() { ws_msg <- msg } -func (app *App) songInfoEvent(event string) map[string]interface{} { +func songInfoEvent(event string) map[string]interface{} { msg := make(map[string]interface{}) msg["event"] = event - status, err := app.mpd.Status() + status, err := mpdc.Status() if err != nil { log.Println(err) return nil } - cur, err := app.mpd.CurrentSong() + cur, err := mpdc.CurrentSong() if err != nil { log.Println(err) return nil @@ -211,7 +217,7 @@ func (app *App) songInfoEvent(event string) map[string]interface{} { return nil } - pl, err := app.GetPlaylist(plid) + pl, err := GetPlaylist(plid) if err != nil { log.Println(err) return nil @@ -241,7 +247,7 @@ func (app *App) songInfoEvent(event string) map[string]interface{} { return msg } -func (app *App) ambiancePlay(payload ...interface{}) { +func ambiancePlay(payload ...interface{}) { if !(len(payload) > 0) { log.Println("ambiance_play called without a payload.") return @@ -289,14 +295,14 @@ func (app *App) ambiancePlay(payload ...interface{}) { } discordspeaker.Lock() - app.ambiance.Clear() - app.ambiance.Add(volume) + amb_mixer.Clear() + amb_mixer.Add(volume) discordspeaker.Unlock() msg := make(map[string]interface{}) out := make(map[string]interface{}) - app.curamb = amb + amb_curr = amb msg["event"] = "ambiance_play" out["id"] = id @@ -304,10 +310,10 @@ func (app *App) ambiancePlay(payload ...interface{}) { ws_msg <- msg } -func (app *App) ambianceStop(payload ...interface{}) { +func ambianceStop(payload ...interface{}) { log.Println("Stopping ambiance") discordspeaker.Lock() - app.ambiance.Clear() + amb_mixer.Clear() discordspeaker.Unlock() msg := make(map[string]interface{}) @@ -316,7 +322,7 @@ func (app *App) ambianceStop(payload ...interface{}) { } -func (app *App) ambianceAdd(payload ...interface{}) { +func ambianceAdd(payload ...interface{}) { if !(len(payload) > 0) { log.Println("addPlaylist called without a payload.") return @@ -359,8 +365,8 @@ func (app *App) ambianceAdd(payload ...interface{}) { ws_msg <- msg } -func (app *App) songPosition(payload ...interface{}) { - status, err := app.mpd.Status() +func songPosition(payload ...interface{}) { + status, err := mpdc.Status() if err != nil { log.Println(err) return @@ -395,24 +401,24 @@ func (app *App) songPosition(payload ...interface{}) { } -func (app *App) songInfo(payload ...interface{}) { +func songInfo(payload ...interface{}) { log.Println("song_info event received") - msg := app.songInfoEvent("song_info") + msg := songInfoEvent("song_info") if msg != nil { ws_msg <- msg } } -func (app *App) stop(payload ...interface{}) { +func stop(payload ...interface{}) { log.Println("stop event received") - app.plmutex.Lock() - if app.plcancel != nil { - app.plcancel() + mpd_mutex.Lock() + if mpd_plcf != nil { + mpd_plcf() } - app.mpd.Stop() - app.plmutex.Unlock() + mpdc.Stop() + mpd_mutex.Unlock() msg := make(map[string]interface{}) msg["event"] = "stop" @@ -420,28 +426,28 @@ func (app *App) stop(payload ...interface{}) { ws_msg <- msg } -func (app *App) prevSong(payload ...interface{}) { +func prevSong(payload ...interface{}) { log.Println("prev_song event received") - app.plmutex.Lock() - err := app.mpd.Previous() - app.plmutex.Unlock() + mpd_mutex.Lock() + err := mpdc.Previous() + mpd_mutex.Unlock() if err != nil { log.Println(err) } } -func (app *App) nextSong(payload ...interface{}) { +func nextSong(payload ...interface{}) { log.Println("next_song event received") - app.plmutex.Lock() - err := app.mpd.Next() - app.plmutex.Unlock() + mpd_mutex.Lock() + err := mpdc.Next() + mpd_mutex.Unlock() if err != nil { log.Println(err) } } -func (app *App) addPlaylist(payload ...interface{}) { +func addPlaylist(payload ...interface{}) { if !(len(payload) > 0) { log.Println("addPlaylist called without a payload.") return @@ -481,12 +487,12 @@ func (app *App) addPlaylist(payload ...interface{}) { return } - _, err = app.Playlist(plid) + _, err = YTPlaylist(plid) if err != nil { log.Println("Error getting youtube playlist info,", plid) } - id, err := app.AddPlaylist(pltitle, plid) + id, err := AddPlaylist(pltitle, plid) if err != nil { log.Println("Error getting youtube playlist info,", plid) } @@ -499,7 +505,7 @@ func (app *App) addPlaylist(payload ...interface{}) { ws_msg <- msg } -func (app *App) loadPlaylist(payload ...interface{}) { +func loadPlaylist(payload ...interface{}) { log.Println("load_playlist event received") if !(len(payload) > 0) { @@ -526,13 +532,13 @@ func (app *App) loadPlaylist(payload ...interface{}) { } log.Println("Loading new playlist: ", id) - pl, err := app.GetPlaylist(id) + pl, err := GetPlaylist(id) if err != nil { log.Println("Unable to find playlist with id,", id) return } - list, err := app.Playlist(pl.Url) + list, err := YTPlaylist(pl.Url) if err != nil { log.Println("Error getting playlist info,", id) return @@ -543,16 +549,16 @@ func (app *App) loadPlaylist(payload ...interface{}) { log.Println("Unable to shuffle playlist") return } - app.plmutex.Lock() - if app.plcancel != nil { - app.plcancel() + mpd_mutex.Lock() + if mpd_plcf != nil { + mpd_plcf() } - app.mpd.Stop() - app.mpd.Clear() - app.plmutex.Unlock() + mpdc.Stop() + mpdc.Clear() + mpd_mutex.Unlock() ctx, cancel := context.WithCancel(context.Background()) - app.plcancel = cancel + mpd_plcf = cancel go func() { defer cancel() @@ -560,13 +566,13 @@ func (app *App) loadPlaylist(payload ...interface{}) { for _, vid := range list { log.Printf("Adding %s", vid) - ytinfo, err := app.Video(vid) + ytinfo, err := YTVideo(vid) if err != nil { log.Println(err) continue } - _, yt, err := app.cache.GetOrCreateBytes(vid+".txt", func() ([]byte, error) { + _, yt, err := cache.GetOrCreateBytes(vid+".txt", func() ([]byte, error) { uri, err := NewYTdl(vid) if err != nil { return nil, err @@ -580,8 +586,8 @@ func (app *App) loadPlaylist(payload ...interface{}) { // 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() + mpd_mutex.Lock() + defer mpd_mutex.Unlock() if ctx.Err() != nil { return false @@ -590,41 +596,41 @@ func (app *App) loadPlaylist(payload ...interface{}) { ok = true // state:stop - songid, err := app.mpd.AddID(string(yt), 0) + songid, err := mpdc.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) + mpdcmd := mpdc.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) + mpdcmd = mpdc.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) + mpdcmd = mpdc.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()) + mpdcmd = mpdc.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) + mpdc.Play(-1) return }() diff --git a/mixer.go b/mixer.go new file mode 100644 index 0000000..4a4bbbc --- /dev/null +++ b/mixer.go @@ -0,0 +1,71 @@ +package main + +import ( + "log" + "time" + + "github.com/faiface/beep" + "github.com/faiface/beep/effects" + + "dndmusicbot/ffmpeg" + discordspeaker "dndmusicbot/speaker" +) + +var ( + pl_volume *effects.Volume + amb_volume *effects.Volume + amb_mixer beep.Mixer + amb_curr Ambiance +) + +func init() { + log.Println("queue.go loading..") + + amb_mixer = beep.Mixer{} + + amb_volume = &effects.Volume{ + Streamer: &amb_mixer, + Base: 2, + Volume: 2, + Silent: false, + } + discordspeaker.Play(amb_volume) + + mpdstream, err := NewMPD() + if err != nil { + log.Fatal(err) + } + + pl_volume = &effects.Volume{ + Streamer: mpdstream, + Base: 2, + Volume: -2, + Silent: false, + } + + discordspeaker.Play(pl_volume) + + /* + app.queue = new(Queue) + app.queue.list = list.New() + app.queue.Events = app.events + discordspeaker.Play(app.queue) + */ + + log.Println("queue.go done.") +} + +type Song struct { + Title string + Channel string + VideoID string + Length time.Duration + PCM *ffmpeg.PCM + Playlist Playlist + DLuri string +} + +func (s *Song) NewStream() (err error) { + s.PCM, err = ffmpeg.NewPCM(s.DLuri, sampleRate, channels) + return +} diff --git a/mpd.go b/mpd.go index b32ff0a..22baed2 100644 --- a/mpd.go +++ b/mpd.go @@ -7,6 +7,7 @@ import ( "os" "os/exec" "strconv" + "sync" "syscall" "text/template" "time" @@ -21,6 +22,14 @@ type MPD struct { f beep.Format } +var ( + mpdcf context.CancelFunc + mpdw *mpd.Watcher + mpdc *mpd.Client + mpd_mutex *sync.Mutex + mpd_plcf context.CancelFunc +) + func init() { log.Println("mpd.go loading..") @@ -62,7 +71,7 @@ func init() { ctx, cancel := context.WithCancel(context.Background()) - app.mpdc = cancel + mpdcf = cancel cmd := exec.CommandContext( ctx, @@ -86,20 +95,20 @@ func init() { // wait for mpd to start. time.Sleep(2 * time.Second) - app.mpd, err = mpd.Dial("unix", config.GetString("mpd.sock")) + mpdc, err = mpd.Dial("unix", config.GetString("mpd.sock")) if err != nil { log.Fatal(err) } - app.mpd.Repeat(true) - app.mpd.Random(true) + mpdc.Repeat(true) + mpdc.Random(true) - err = app.mpd.EnableOutput(0) + err = mpdc.EnableOutput(0) if err != nil { log.Fatal(err) } - app.mpdw, err = mpd.NewWatcher("unix", config.GetString("mpd.sock"), "") + mpdw, err = mpd.NewWatcher("unix", config.GetString("mpd.sock"), "") if err != nil { log.Fatal(err) } @@ -107,9 +116,9 @@ func init() { go func() { for { select { - case ev := <-app.mpdw.Event: - app.events.Emit(events.EventName(ev)) - case err := <-app.mpdw.Error: + case e := <-mpdw.Event: + ev.Emit(events.EventName(e)) + case err := <-mpdw.Error: log.Println(err) return } diff --git a/queue.go b/queue.go deleted file mode 100644 index 072f343..0000000 --- a/queue.go +++ /dev/null @@ -1,203 +0,0 @@ -package main - -import ( - "container/list" - "log" - "time" - - "github.com/faiface/beep" - "github.com/faiface/beep/effects" - "github.com/kataras/go-events" - - "dndmusicbot/ffmpeg" - discordspeaker "dndmusicbot/speaker" -) - -var pl_volume *effects.Volume -var amb_volume *effects.Volume - -func init() { - log.Println("queue.go loading..") - - app.ambiance = beep.Mixer{} - - amb_volume = &effects.Volume{ - Streamer: &app.ambiance, - Base: 2, - Volume: 2, - Silent: false, - } - discordspeaker.Play(amb_volume) - - mpdstream, err := NewMPD() - if err != nil { - log.Fatal(err) - } - - pl_volume = &effects.Volume{ - Streamer: mpdstream, - Base: 2, - Volume: -2, - Silent: false, - } - - discordspeaker.Play(pl_volume) - - /* - app.queue = new(Queue) - app.queue.list = list.New() - app.queue.Events = app.events - discordspeaker.Play(app.queue) - */ - - log.Println("queue.go done.") -} - -type Song struct { - Title string - Channel string - VideoID string - Length time.Duration - PCM *ffmpeg.PCM - Playlist Playlist - DLuri string -} - -func (s *Song) NewStream() (err error) { - s.PCM, err = ffmpeg.NewPCM(s.DLuri, sampleRate, channels) - return -} - -type Queue struct { - Events events.EventEmmiter - playing bool - list *list.List - current *list.Element -} - -func (q Queue) IsPlaying() bool { - return q.playing -} - -func (q *Queue) Play() { - q.playing = true - if q.list.Len() > 0 { - play := q.list.Front() - q.current = play - app.events.Emit("song_start") - } -} - -func (q *Queue) Add(s *Song) { - el := q.list.PushBack(s) - if el == q.list.Front() { - q.Play() - } -} - -func (q Queue) QLen() int { - return q.list.Len() -} - -func (q Queue) Current() *Song { - if q.current == nil { - return new(Song) - } - return q.current.Value.(*Song) -} - -func (q *Queue) Reset() { - err := app.mpd.Clear() - if err != nil { - log.Println(err) - } -} - -func (q *Queue) Next() { - if q.current == nil { - return - } - next := q.current.Next() - if next == nil { - next = q.list.Front() - } - - pcm := next.Value.(*Song).PCM - if pcm != nil && pcm.Position() != 0 { - err := next.Value.(*Song).NewStream() - log.Println(err) - } - - q.current = next -} - -func (q *Queue) Prev() { - if q.current == nil { - return - } - - prev := q.current.Prev() - if prev == nil { - prev = q.list.Back() - } - - err := prev.Value.(*Song).NewStream() - if err != nil { - log.Println(err) - } - - q.current = prev -} - -func (q *Queue) Preload() { -} - -func (q *Queue) Stream(samples [][2]float64) (n int, ok bool) { - // We use the filled variable to track how many samples we've - // successfully filled already. We loop until all samples are filled. - filled := 0 - - for filled < len(samples) { - // There are no streamers in the queue, so we stream silence. - if q.current == nil || q.list.Len() == 0 { - for i := range samples[filled:] { - samples[i][0] = 0 - samples[i][1] = 0 - } - break - } - - // We stream from the first streamer in the queue. - n, ok := q.current.Value.(*Song).PCM.Stream(samples[filled:]) - // If it's drained, we pop it from the queue, thus continuing with - // the next streamer. - if !ok { - q.Next() - q.Events.Emit("song_over", nil) - } - // We update the number of filled samples. - filled += n - } - - return len(samples), true -} - -func (q *Queue) Err() error { - return nil -} - -func (q *Queue) Position() int { - if q.current == nil || q.current.Value.(*Song).PCM == nil { - return 0 - } - - return q.current.Value.(*Song).PCM.Position() -} - -func (q Queue) Len() int { - if q.current == nil { - return 0 - } - - return int(q.current.Value.(*Song).Length.Milliseconds()) -} diff --git a/routes.go b/routes.go index 67fa944..0242817 100644 --- a/routes.go +++ b/routes.go @@ -18,16 +18,18 @@ var upgrader = websocket.Upgrader{ WriteBufferSize: 1024, } +var router *httprouter.Router + func init() { - app.router = httprouter.New() + router = httprouter.New() - app.router.GET("/", app.Index) - app.router.GET("/play/:playlist", app.Play) - app.router.GET("/reset", app.Reset) - app.router.GET("/public/*js", app.ServeFiles) - app.router.GET("/css/*css", app.ServeFiles) + router.GET("/", Index) + router.GET("/play/:playlist", Play) + router.GET("/reset", Reset) + router.GET("/public/*js", ServeFiles) + router.GET("/css/*css", ServeFiles) - app.router.HandlerFunc("GET", "/ws", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + router.HandlerFunc("GET", "/ws", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Printf("WS connection from %v\n", r.RemoteAddr) conn, err := upgrader.Upgrade(w, r, nil) if err != nil { @@ -42,7 +44,7 @@ func init() { })) go func() { - log.Fatal(http.ListenAndServe(":8824", app.router)) + log.Fatal(http.ListenAndServe(":8824", router)) }() } @@ -51,7 +53,7 @@ type IndexData struct { Ambiance []Ambiance } -func (app App) ServeFiles(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { +func ServeFiles(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { filePath := filepath.Join(".", r.URL.Path) file, err := os.Open(filePath) @@ -73,8 +75,8 @@ func (app App) ServeFiles(w http.ResponseWriter, r *http.Request, _ httprouter.P http.ServeContent(w, r, filename, t, file) } -func (app App) Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - playlists, err := app.GetPlaylists() +func Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + playlists, err := GetPlaylists() if err != nil { http.Error(w, "Unable to get playlists. "+err.Error(), http.StatusInternalServerError) } @@ -94,11 +96,11 @@ func (app App) Index(w http.ResponseWriter, r *http.Request, _ httprouter.Params } } -func (app *App) Play(w http.ResponseWriter, r *http.Request, p httprouter.Params) { +func Play(w http.ResponseWriter, r *http.Request, p httprouter.Params) { plname := p.ByName("playlist") if plname == "reset" { - app.events.Emit("stop", nil) + ev.Emit("stop", nil) return } @@ -107,14 +109,14 @@ func (app *App) Play(w http.ResponseWriter, r *http.Request, p httprouter.Params http.Error(w, "Unable to parse uuid. "+err.Error(), http.StatusInternalServerError) } - app.events.Emit("new_playlist", plid) + ev.Emit("new_playlist", plid) } -func (app *App) Add(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { +func Add(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { r.ParseForm() } -func (app *App) Reset(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { - app.events.Emit("stop", nil) +func Reset(w http.ResponseWriter, r *http.Request, _ httprouter.Params) { + ev.Emit("stop", nil) } diff --git a/ws.go b/ws.go index 097877f..f52eede 100644 --- a/ws.go +++ b/ws.go @@ -64,7 +64,7 @@ func handleWS(c *websocket.Conn) error { return nil }) - msg := app.songInfoEvent("song_info") + msg := songInfoEvent("song_info") vol := make(map[string]interface{}) volout := make(map[string]float64) @@ -77,11 +77,11 @@ func handleWS(c *websocket.Conn) error { c.WriteJSON(msg) c.WriteJSON(vol) - if app.ambiance.Len() > 0 { + if amb_mixer.Len() > 0 { msg := make(map[string]interface{}) out := make(map[string]interface{}) msg["event"] = "ambiance_play" - out["id"] = app.curamb.Id + out["id"] = amb_curr.Id msg["payload"] = out c.WriteJSON(msg) } else { @@ -97,6 +97,6 @@ func handleWS(c *websocket.Conn) error { return err } - app.events.Emit(events.EventName(msg.Event), msg.Payload) + ev.Emit(events.EventName(msg.Event), msg.Payload) } } diff --git a/youtube.go b/youtube.go index 885018e..d65b577 100644 --- a/youtube.go +++ b/youtube.go @@ -9,7 +9,6 @@ import ( "errors" "io" "log" - "math/big" "time" mrand "math/rand" @@ -19,6 +18,8 @@ import ( "google.golang.org/api/youtube/v3" ) +var yt_svc *youtube.Service + func init() { log.Println("youtube.go loading..") @@ -26,7 +27,7 @@ func init() { apikey := config.GetString("youtube.apikey") - app.youtube, err = youtube.NewService(context.Background(), option.WithAPIKey(apikey)) + yt_svc, err = youtube.NewService(context.Background(), option.WithAPIKey(apikey)) if err != nil { log.Fatal(err) } @@ -46,39 +47,6 @@ func ShufflePlaylist(list []string) ([]string, error) { return list, nil } -func (app *App) GetSong(list []string) string { - return list[app.plidx] -} - -func (app *App) GetNextSong(list []string) string { - app.plidx++ - if app.plidx >= len(app.active) { - app.plidx = 0 - } - return list[app.plidx] -} - -func (app *App) GetPrevSong(list []string) string { - app.plidx-- - if app.plidx < 0 { - app.plidx = len(list) - } - return list[app.plidx] -} - -func GetRandomSong(list []string) string { - if !(len(list) > 0) { - return "" - } - - idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(list)-1))) - if err != nil { - log.Println("Failed to get random int, ", err) - return "" - } - return list[idx.Int64()] -} - type VideoInfo struct { Title string Channel string @@ -86,9 +54,9 @@ type VideoInfo struct { Uri string } -func (app App) Video(vid string) (out VideoInfo, err error) { - _, r, err := app.cache.GetOrCreate(vid+".videoinfo", func() (io.ReadCloser, error) { - call := app.youtube.Videos.List([]string{"snippet", "contentDetails"}) +func YTVideo(vid string) (out VideoInfo, err error) { + _, r, err := cache.GetOrCreate(vid+".videoinfo", func() (io.ReadCloser, error) { + call := yt_svc.Videos.List([]string{"snippet", "contentDetails"}) call.MaxResults(1) call.Id(vid) resp, err := call.Do() @@ -128,8 +96,8 @@ func (app App) Video(vid string) (out VideoInfo, err error) { return out, nil } -func (app App) Playlist(playlist string) ([]string, error) { - call := app.youtube.PlaylistItems.List([]string{"contentDetails"}) +func YTPlaylist(playlist string) ([]string, error) { + call := yt_svc.PlaylistItems.List([]string{"contentDetails"}) pageToken := "" call = call.MaxResults(50) call = call.PlaylistId(playlist)