add shared callback impl between mpv and jukebox players
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user