don't assume MPV player in now playing page
This commit is contained in:
@@ -51,6 +51,7 @@ type PlaybackManager struct {
|
|||||||
onPaused []func()
|
onPaused []func()
|
||||||
onStopped []func()
|
onStopped []func()
|
||||||
onPlaying []func()
|
onPlaying []func()
|
||||||
|
onPlayerChange []func()
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewPlaybackManager(
|
func NewPlaybackManager(
|
||||||
@@ -122,6 +123,14 @@ func (pm *PlaybackManager) invokeNoArgCallbacks(cbs []func()) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PlaybackManager) CurrentPlayer() player.BasePlayer {
|
||||||
|
return p.player
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PlaybackManager) OnPlayerChange(cb func()) {
|
||||||
|
p.onPlayerChange = append(p.onPlayerChange, cb)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PlaybackManager) IsSeeking() bool {
|
func (p *PlaybackManager) IsSeeking() bool {
|
||||||
return p.player.IsSeeking()
|
return p.player.IsSeeking()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ type nowPlayingPageState struct {
|
|||||||
pool *util.WidgetPool
|
pool *util.WidgetPool
|
||||||
conf *backend.NowPlayingPageConfig
|
conf *backend.NowPlayingPageConfig
|
||||||
pm *backend.PlaybackManager
|
pm *backend.PlaybackManager
|
||||||
p *mpv.Player
|
|
||||||
canRate bool
|
canRate bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,17 +51,16 @@ func NewNowPlayingPage(
|
|||||||
pool *util.WidgetPool,
|
pool *util.WidgetPool,
|
||||||
conf *backend.NowPlayingPageConfig,
|
conf *backend.NowPlayingPageConfig,
|
||||||
pm *backend.PlaybackManager,
|
pm *backend.PlaybackManager,
|
||||||
p *mpv.Player, // TODO: once other player backends are supported (eg uPnP), refactor
|
|
||||||
canRate bool,
|
canRate bool,
|
||||||
) *NowPlayingPage {
|
) *NowPlayingPage {
|
||||||
a := &NowPlayingPage{nowPlayingPageState: nowPlayingPageState{
|
a := &NowPlayingPage{nowPlayingPageState: nowPlayingPageState{
|
||||||
contr: contr, pool: pool, conf: conf, pm: pm, p: p, canRate: canRate,
|
contr: contr, pool: pool, conf: conf, pm: pm, canRate: canRate,
|
||||||
}}
|
}}
|
||||||
a.ExtendBaseWidget(a)
|
a.ExtendBaseWidget(a)
|
||||||
|
|
||||||
p.OnPaused(a.formatStatusLine)
|
pm.OnPaused(a.formatStatusLine)
|
||||||
p.OnPlaying(a.formatStatusLine)
|
pm.OnPlaying(a.formatStatusLine)
|
||||||
p.OnStopped(a.formatStatusLine)
|
pm.OnStopped(a.formatStatusLine)
|
||||||
|
|
||||||
if t := a.pool.Obtain(util.WidgetTypeTracklist); t != nil {
|
if t := a.pool.Obtain(util.WidgetTypeTracklist); t != nil {
|
||||||
a.tracklist = t.(*widgets.Tracklist)
|
a.tracklist = t.(*widgets.Tracklist)
|
||||||
@@ -136,7 +134,8 @@ func (a *NowPlayingPage) OnPlayTimeUpdate(_, _ float64) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (a *NowPlayingPage) formatStatusLine() {
|
func (a *NowPlayingPage) formatStatusLine() {
|
||||||
playerStats := a.p.GetStatus()
|
curPlayer := a.pm.CurrentPlayer()
|
||||||
|
playerStats := curPlayer.GetStatus()
|
||||||
lastStatus := a.statusLabel.Text
|
lastStatus := a.statusLabel.Text
|
||||||
state := "Stopped"
|
state := "Stopped"
|
||||||
switch playerStats.State {
|
switch playerStats.State {
|
||||||
@@ -161,32 +160,40 @@ func (a *NowPlayingPage) formatStatusLine() {
|
|||||||
status := fmt.Sprintf("%s (%d/%d)%s", state, trackNum,
|
status := fmt.Sprintf("%s (%d/%d)%s", state, trackNum,
|
||||||
len(a.queue), statusSuffix)
|
len(a.queue), statusSuffix)
|
||||||
|
|
||||||
if state == "Stopped" {
|
mediaInfo := ""
|
||||||
a.statusLabel.Text = fmt.Sprintf("%s | Total time: %s", status, util.SecondsToTimeString(a.totalTime))
|
if state != "Stopped" {
|
||||||
} else {
|
mediaInfo = a.formatMediaInfoStr(curPlayer)
|
||||||
audioInfo, err := a.p.GetMediaInfo()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("error getting playback status: %s", err.Error())
|
|
||||||
}
|
|
||||||
codec := audioInfo.Codec
|
|
||||||
if len(codec) <= 4 && !strings.EqualFold(codec, "opus") {
|
|
||||||
codec = strings.ToUpper(codec) // FLAC, MP3, AAC, etc
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: bit depth intentionally omitted since MPV reports the decoded bit depth
|
|
||||||
// i.e. 24 bit files get reported as 32 bit. Also b/c bit depth isn't meaningful for lossy.
|
|
||||||
a.statusLabel.Text = fmt.Sprintf("%s · %s %g kHz, %d kbps | Total time: %s",
|
|
||||||
status,
|
|
||||||
codec,
|
|
||||||
float64(audioInfo.Samplerate)/1000,
|
|
||||||
audioInfo.Bitrate/1000,
|
|
||||||
util.SecondsToTimeString(a.totalTime))
|
|
||||||
}
|
}
|
||||||
|
if mediaInfo != "" {
|
||||||
|
mediaInfo = " · " + mediaInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
a.statusLabel.Text = fmt.Sprintf("%s%s | Total time: %s", status, mediaInfo, util.SecondsToTimeString(a.totalTime))
|
||||||
if lastStatus != a.statusLabel.Text {
|
if lastStatus != a.statusLabel.Text {
|
||||||
a.statusLabel.Refresh()
|
a.statusLabel.Refresh()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *NowPlayingPage) formatMediaInfoStr(player player.BasePlayer) string {
|
||||||
|
mpv, ok := player.(*mpv.Player)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
audioInfo, err := mpv.GetMediaInfo()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("error getting playback status: %s", err.Error())
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
codec := audioInfo.Codec
|
||||||
|
if len(codec) <= 4 && !strings.EqualFold(codec, "opus") {
|
||||||
|
codec = strings.ToUpper(codec) // FLAC, MP3, AAC, etc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: bit depth intentionally omitted since MPV reports the decoded bit depth
|
||||||
|
// i.e. 24 bit files get reported as 32 bit. Also b/c bit depth isn't meaningful for lossy.
|
||||||
|
return fmt.Sprintf("%s %g kHz, %d kbps", codec, float64(audioInfo.Samplerate)/1000, audioInfo.Bitrate/1000)
|
||||||
|
}
|
||||||
|
|
||||||
func (a *NowPlayingPage) Reload() {
|
func (a *NowPlayingPage) Reload() {
|
||||||
a.load("")
|
a.load("")
|
||||||
}
|
}
|
||||||
@@ -217,5 +224,5 @@ func (a *NowPlayingPage) load(highlightedTrackID string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *nowPlayingPageState) Restore() Page {
|
func (s *nowPlayingPageState) Restore() Page {
|
||||||
return NewNowPlayingPage("", s.contr, s.pool, s.conf, s.pm, s.p, s.canRate)
|
return NewNowPlayingPage("", s.contr, s.pool, s.conf, s.pm, s.canRate)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ func (r Router) CreatePage(rte controller.Route) Page {
|
|||||||
return NewGenresPage(r.Controller, r.App.ServerManager.Server)
|
return NewGenresPage(r.Controller, r.App.ServerManager.Server)
|
||||||
case controller.NowPlaying:
|
case controller.NowPlaying:
|
||||||
_, canRate := r.App.ServerManager.Server.(mediaprovider.SupportsRating)
|
_, canRate := r.App.ServerManager.Server.(mediaprovider.SupportsRating)
|
||||||
return NewNowPlayingPage(rte.Arg, r.Controller, r.widgetPool, &r.App.Config.NowPlayingPage, r.App.PlaybackManager, r.App.Player, canRate)
|
return NewNowPlayingPage(rte.Arg, r.Controller, r.widgetPool, &r.App.Config.NowPlayingPage, r.App.PlaybackManager, canRate)
|
||||||
case controller.Playlist:
|
case controller.Playlist:
|
||||||
return NewPlaylistPage(rte.Arg, &r.App.Config.PlaylistPage, r.widgetPool, r.Controller, r.App.ServerManager, r.App.PlaybackManager, r.App.ImageManager)
|
return NewPlaylistPage(rte.Arg, &r.App.Config.PlaylistPage, r.widgetPool, r.Controller, r.App.ServerManager, r.App.PlaybackManager, r.App.ImageManager)
|
||||||
case controller.Playlists:
|
case controller.Playlists:
|
||||||
|
|||||||
Reference in New Issue
Block a user