From faf067ce7e2583921fffdc25022cb6d9926f6e8b Mon Sep 17 00:00:00 2001 From: Drew Weymouth Date: Sun, 1 Sep 2024 08:45:09 -0700 Subject: [PATCH] add shared callback impl between mpv and jukebox players --- backend/playbackengine.go | 1 - backend/player/jukebox/jukeboxplayer.go | 6 +++ backend/player/mpv/player.go | 68 ++++--------------------- backend/player/player.go | 65 +++++++++++++++++++++++ 4 files changed, 80 insertions(+), 60 deletions(-) diff --git a/backend/playbackengine.go b/backend/playbackengine.go index 0d69cc3..4b050dd 100644 --- a/backend/playbackengine.go +++ b/backend/playbackengine.go @@ -279,7 +279,6 @@ func (p *playbackEngine) LoadRadioStation(radio *mediaprovider.RadioStation, ins func (p *playbackEngine) StopAndClearPlayQueue() { changed := len(p.playQueue) > 0 p.player.Stop() - p.doUpdateTimePos(false) p.playQueue = nil p.nowPlayingIdx = -1 if changed { diff --git a/backend/player/jukebox/jukeboxplayer.go b/backend/player/jukebox/jukeboxplayer.go index 52e7cb6..3518beb 100644 --- a/backend/player/jukebox/jukeboxplayer.go +++ b/backend/player/jukebox/jukeboxplayer.go @@ -14,6 +14,8 @@ const ( ) type JukeboxPlayer struct { + player.BasePlayerCallbackImpl + provider mediaprovider.JukeboxProvider state int // stopped, playing, paused @@ -49,6 +51,7 @@ func (j *JukeboxPlayer) Continue() error { } j.state = playing + j.InvokeOnPlaying() return nil } @@ -61,6 +64,7 @@ func (j *JukeboxPlayer) Pause() error { } // TODO: calculate paused at time j.state = paused + j.InvokeOnPaused() return nil } @@ -72,6 +76,7 @@ func (j *JukeboxPlayer) Stop() error { return err } j.state = stopped + j.InvokeOnStopped() return nil } @@ -112,6 +117,7 @@ func (j *JukeboxPlayer) SeekSeconds(secs float64) error { j.seeking = true err := j.provider.JukeboxSeek(j.curTrack, int(secs)) j.seeking = false + j.InvokeOnSeek() return err } diff --git a/backend/player/mpv/player.go b/backend/player/mpv/player.go index 076f83f..18f50e2 100644 --- a/backend/player/mpv/player.go +++ b/backend/player/mpv/player.go @@ -7,8 +7,8 @@ import ( "math" "strconv" - "github.com/supersonic-app/go-mpv" "github.com/dweymouth/supersonic/backend/player" + "github.com/supersonic-app/go-mpv" ) // Error returned by many Player functions if called before the player has not been initialized. @@ -50,6 +50,8 @@ var _ player.URLPlayer = (*Player)(nil) // Player encapsulates the mpv instance and provides functions // to control it and to check its status. type Player struct { + player.BasePlayerCallbackImpl + mpv *mpv.Mpv initialized bool vol int @@ -66,13 +68,6 @@ type Player struct { peaksEnabled bool bgCancel context.CancelFunc - - // callbacks - onPaused []func() - onStopped []func() - onPlaying []func() - onSeek []func() - onTrackChange []func() } // Returns a new player. @@ -403,33 +398,6 @@ func (p *Player) IsSeeking() bool { return p.seeking && p.status.State == player.Playing } -// Registers a callback which is invoked when the player transitions to the Paused state. -func (p *Player) OnPaused(cb func()) { - p.onPaused = append(p.onPaused, cb) -} - -// Registers a callback which is invoked when the player transitions to the Stopped state. -func (p *Player) OnStopped(cb func()) { - p.onStopped = append(p.onStopped, cb) -} - -// Registers a callback which is invoked when the player transitions to the Playing state. -func (p *Player) OnPlaying(cb func()) { - p.onPlaying = append(p.onPlaying, cb) -} - -// Registers a callback which is invoked whenever a seek event occurs. -func (p *Player) OnSeek(cb func()) { - p.onSeek = append(p.onSeek, cb) -} - -// Registers a callback which is invoked when the currently playing track changes, -// or when playback begins at any time from the Stopped state. -// Callback is invoked with the index of the currently playing track (zero-based). -func (p *Player) OnTrackChange(cb func()) { - p.onTrackChange = append(p.onTrackChange, cb) -} - // Destroy the player. func (p *Player) Destroy() { if p.bgCancel != nil { @@ -466,23 +434,11 @@ func (p *Player) GetPeaks() (float64, float64, float64, float64) { func (p *Player) setState(s player.State) { switch { case s == player.Playing && p.status.State != player.Playing: - defer func() { - for _, cb := range p.onPlaying { - cb() - } - }() + defer p.InvokeOnPlaying() case s == player.Paused && p.status.State != player.Paused: - defer func() { - for _, cb := range p.onPaused { - cb() - } - }() + defer p.InvokeOnPaused() case s == player.Stopped && p.status.State != player.Stopped: - defer func() { - for _, cb := range p.onStopped { - cb() - } - }() + defer p.InvokeOnStopped() } p.status.State = s } @@ -523,21 +479,15 @@ func (p *Player) eventHandler(ctx context.Context) { p.seeking = false } case mpv.EVENT_SEEK: - for _, cb := range p.onSeek { - cb() - } + p.InvokeOnSeek() case mpv.EVENT_FILE_LOADED: p.curPlaylistPos, _ = p.getInt64Property("playlist-pos") if p.status.State == player.Paused { // seek while paused switches to a new file // mpv does not fire seek event in this case - for _, cb := range p.onSeek { - cb() - } - } - for _, cb := range p.onTrackChange { - cb() + p.InvokeOnSeek() } + p.InvokeOnTrackChange() case mpv.EVENT_IDLE: p.status.Duration = 0 p.status.TimePos = 0 diff --git a/backend/player/player.go b/backend/player/player.go index 5ab77e1..778c941 100644 --- a/backend/player/player.go +++ b/backend/player/player.go @@ -82,3 +82,68 @@ func (r ReplayGainMode) String() string { return "no" } } + +type BasePlayerCallbackImpl struct { + onPaused []func() + onStopped []func() + onPlaying []func() + onSeek []func() + onTrackChange []func() +} + +// Registers a callback which is invoked when the player transitions to the Paused state. +func (p *BasePlayerCallbackImpl) OnPaused(cb func()) { + p.onPaused = append(p.onPaused, cb) +} + +// Registers a callback which is invoked when the player transitions to the Stopped state. +func (p *BasePlayerCallbackImpl) OnStopped(cb func()) { + p.onStopped = append(p.onStopped, cb) +} + +// Registers a callback which is invoked when the player transitions to the Playing state. +func (p *BasePlayerCallbackImpl) OnPlaying(cb func()) { + p.onPlaying = append(p.onPlaying, cb) +} + +// Registers a callback which is invoked whenever a seek event occurs. +func (p *BasePlayerCallbackImpl) OnSeek(cb func()) { + p.onSeek = append(p.onSeek, cb) +} + +// Registers a callback which is invoked when the currently playing track changes, +// or when playback begins at any time from the Stopped state. +// Callback is invoked with the index of the currently playing track (zero-based). +func (p *BasePlayerCallbackImpl) OnTrackChange(cb func()) { + p.onTrackChange = append(p.onTrackChange, cb) +} + +func (p *BasePlayerCallbackImpl) InvokeOnPaused() { + for _, cb := range p.onPaused { + cb() + } +} + +func (p *BasePlayerCallbackImpl) InvokeOnPlaying() { + for _, cb := range p.onPlaying { + cb() + } +} + +func (p *BasePlayerCallbackImpl) InvokeOnStopped() { + for _, cb := range p.onStopped { + cb() + } +} + +func (p *BasePlayerCallbackImpl) InvokeOnSeek() { + for _, cb := range p.onSeek { + cb() + } +} + +func (p *BasePlayerCallbackImpl) InvokeOnTrackChange() { + for _, cb := range p.onTrackChange { + cb() + } +}