add shared callback impl between mpv and jukebox players

This commit is contained in:
Drew Weymouth
2024-09-01 08:45:09 -07:00
parent c2efb048e2
commit faf067ce7e
4 changed files with 80 additions and 60 deletions
-1
View File
@@ -279,7 +279,6 @@ func (p *playbackEngine) LoadRadioStation(radio *mediaprovider.RadioStation, ins
func (p *playbackEngine) StopAndClearPlayQueue() { func (p *playbackEngine) StopAndClearPlayQueue() {
changed := len(p.playQueue) > 0 changed := len(p.playQueue) > 0
p.player.Stop() p.player.Stop()
p.doUpdateTimePos(false)
p.playQueue = nil p.playQueue = nil
p.nowPlayingIdx = -1 p.nowPlayingIdx = -1
if changed { if changed {
+6
View File
@@ -14,6 +14,8 @@ const (
) )
type JukeboxPlayer struct { type JukeboxPlayer struct {
player.BasePlayerCallbackImpl
provider mediaprovider.JukeboxProvider provider mediaprovider.JukeboxProvider
state int // stopped, playing, paused state int // stopped, playing, paused
@@ -49,6 +51,7 @@ func (j *JukeboxPlayer) Continue() error {
} }
j.state = playing j.state = playing
j.InvokeOnPlaying()
return nil return nil
} }
@@ -61,6 +64,7 @@ func (j *JukeboxPlayer) Pause() error {
} }
// TODO: calculate paused at time // TODO: calculate paused at time
j.state = paused j.state = paused
j.InvokeOnPaused()
return nil return nil
} }
@@ -72,6 +76,7 @@ func (j *JukeboxPlayer) Stop() error {
return err return err
} }
j.state = stopped j.state = stopped
j.InvokeOnStopped()
return nil return nil
} }
@@ -112,6 +117,7 @@ func (j *JukeboxPlayer) SeekSeconds(secs float64) error {
j.seeking = true j.seeking = true
err := j.provider.JukeboxSeek(j.curTrack, int(secs)) err := j.provider.JukeboxSeek(j.curTrack, int(secs))
j.seeking = false j.seeking = false
j.InvokeOnSeek()
return err return err
} }
+9 -59
View File
@@ -7,8 +7,8 @@ import (
"math" "math"
"strconv" "strconv"
"github.com/supersonic-app/go-mpv"
"github.com/dweymouth/supersonic/backend/player" "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. // 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 // Player encapsulates the mpv instance and provides functions
// to control it and to check its status. // to control it and to check its status.
type Player struct { type Player struct {
player.BasePlayerCallbackImpl
mpv *mpv.Mpv mpv *mpv.Mpv
initialized bool initialized bool
vol int vol int
@@ -66,13 +68,6 @@ type Player struct {
peaksEnabled bool peaksEnabled bool
bgCancel context.CancelFunc bgCancel context.CancelFunc
// callbacks
onPaused []func()
onStopped []func()
onPlaying []func()
onSeek []func()
onTrackChange []func()
} }
// Returns a new player. // Returns a new player.
@@ -403,33 +398,6 @@ func (p *Player) IsSeeking() bool {
return p.seeking && p.status.State == player.Playing 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. // Destroy the player.
func (p *Player) Destroy() { func (p *Player) Destroy() {
if p.bgCancel != nil { if p.bgCancel != nil {
@@ -466,23 +434,11 @@ func (p *Player) GetPeaks() (float64, float64, float64, float64) {
func (p *Player) setState(s player.State) { func (p *Player) setState(s player.State) {
switch { switch {
case s == player.Playing && p.status.State != player.Playing: case s == player.Playing && p.status.State != player.Playing:
defer func() { defer p.InvokeOnPlaying()
for _, cb := range p.onPlaying {
cb()
}
}()
case s == player.Paused && p.status.State != player.Paused: case s == player.Paused && p.status.State != player.Paused:
defer func() { defer p.InvokeOnPaused()
for _, cb := range p.onPaused {
cb()
}
}()
case s == player.Stopped && p.status.State != player.Stopped: case s == player.Stopped && p.status.State != player.Stopped:
defer func() { defer p.InvokeOnStopped()
for _, cb := range p.onStopped {
cb()
}
}()
} }
p.status.State = s p.status.State = s
} }
@@ -523,21 +479,15 @@ func (p *Player) eventHandler(ctx context.Context) {
p.seeking = false p.seeking = false
} }
case mpv.EVENT_SEEK: case mpv.EVENT_SEEK:
for _, cb := range p.onSeek { p.InvokeOnSeek()
cb()
}
case mpv.EVENT_FILE_LOADED: case mpv.EVENT_FILE_LOADED:
p.curPlaylistPos, _ = p.getInt64Property("playlist-pos") p.curPlaylistPos, _ = p.getInt64Property("playlist-pos")
if p.status.State == player.Paused { if p.status.State == player.Paused {
// seek while paused switches to a new file // seek while paused switches to a new file
// mpv does not fire seek event in this case // mpv does not fire seek event in this case
for _, cb := range p.onSeek { p.InvokeOnSeek()
cb()
}
}
for _, cb := range p.onTrackChange {
cb()
} }
p.InvokeOnTrackChange()
case mpv.EVENT_IDLE: case mpv.EVENT_IDLE:
p.status.Duration = 0 p.status.Duration = 0
p.status.TimePos = 0 p.status.TimePos = 0
+65
View File
@@ -82,3 +82,68 @@ func (r ReplayGainMode) String() string {
return "no" 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()
}
}