Skip to content

Commit

Permalink
Beginning of reworked PlaybackManager - PARTIAL
Browse files Browse the repository at this point in the history
  • Loading branch information
dweymouth committed Dec 22, 2023
1 parent 0cd58cb commit d9eca8d
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 220 deletions.
119 changes: 72 additions & 47 deletions backend/playbackmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,25 +64,26 @@ func NewPlaybackManager(
// clamp to 99% to avoid any possible rounding issues
scrobbleCfg.ThresholdPercent = clamp(scrobbleCfg.ThresholdPercent, 0, 99)
pm := &PlaybackManager{
ctx: ctx,
sm: s,
player: p,
scrobbleCfg: scrobbleCfg,
transcodeCfg: transcodeCfg,
}
p.OnTrackChange(func(tracknum int) {
if tracknum >= len(pm.playQueue) {
return
}
ctx: ctx,
sm: s,
player: p,
scrobbleCfg: scrobbleCfg,
transcodeCfg: transcodeCfg,
nowPlayingIdx: -1,
}
p.OnTrackChange(func() {
pm.checkScrobble() // scrobble the previous song if needed
if pm.player.GetStatus().State == player.Playing {
pm.playTimeStopwatch.Start()
}
pm.nowPlayingIdx = tracknum
pm.nowPlayingIdx++
pm.curTrackTime = float64(pm.playQueue[pm.nowPlayingIdx].Duration)
pm.sendNowPlayingScrobble() // Must come before invokeOnChangeCallbacks b/c track may immediately be scrobbled
pm.invokeOnSongChangeCallbacks()
pm.doUpdateTimePos()
if pm.nowPlayingIdx < len(pm.playQueue)-1 {
pm.setTrack(pm.nowPlayingIdx+1, true)
}
})
p.OnSeek(func() {
pm.doUpdateTimePos()
Expand All @@ -95,6 +96,7 @@ func NewPlaybackManager(
pm.doUpdateTimePos()
pm.invokeOnSongChangeCallbacks()
pm.invokeNoArgCallbacks(pm.onStopped)
pm.nowPlayingIdx = -1
})
p.OnPaused(func() {
pm.playTimeStopwatch.Stop()
Expand Down Expand Up @@ -205,32 +207,24 @@ func (p *PlaybackManager) LoadPlaylist(playlistID string, appendToQueue bool, sh
func (p *PlaybackManager) LoadTracks(tracks []*mediaprovider.Track, appendToQueue, shuffle bool) error {
if !appendToQueue {
p.player.Stop()
p.nowPlayingIdx = 0
p.nowPlayingIdx = -1
p.playQueue = nil
}
nums := util.Range(len(tracks))
if shuffle {
util.ShuffleSlice(nums)
}
needToSetNext := appendToQueue && len(tracks) > 0 && p.nowPlayingIdx == len(p.playQueue)-1
for _, i := range nums {

if urlP, ok := p.player.(player.URLPlayer); ok {
url, err := p.sm.Server.GetStreamURL(tracks[i].ID, p.transcodeCfg.ForceRawFile)
if err != nil {
return err
}
urlP.AppendFile(url)
} else if trP, ok := p.player.(player.TrackPlayer); ok {
trP.AppendTrack(tracks[i])
} else {
panic("unsupported player type")
}
// ensure a deep copy of the track info so that we can maintain our own state
// (tracking play count increases, favorite, and rating) without messing up
// other views' track models
tr := *tracks[i]
p.playQueue = append(p.playQueue, &tr)
}
if needToSetNext {
p.setTrack(p.nowPlayingIdx+1, true)
}
return nil
}

Expand All @@ -241,7 +235,7 @@ func (p *PlaybackManager) PlayAlbum(albumID string, firstTrack int, shuffle bool
if p.replayGainCfg.Mode == ReplayGainAuto {
p.SetReplayGainMode(player.ReplayGainAlbum)
}
return p.player.PlayTrackAt(firstTrack)
return p.PlayTrackAt(firstTrack)
}

func (p *PlaybackManager) PlayPlaylist(playlistID string, firstTrack int, shuffle bool) error {
Expand All @@ -251,7 +245,7 @@ func (p *PlaybackManager) PlayPlaylist(playlistID string, firstTrack int, shuffl
if p.replayGainCfg.Mode == ReplayGainAuto {
p.SetReplayGainMode(player.ReplayGainTrack)
}
return p.player.PlayTrackAt(firstTrack)
return p.PlayTrackAt(firstTrack)
}

func (p *PlaybackManager) PlayTrack(trackID string) error {
Expand All @@ -267,11 +261,15 @@ func (p *PlaybackManager) PlayTrack(trackID string) error {
}

func (p *PlaybackManager) PlayFromBeginning() error {
return p.player.PlayTrackAt(0)
return p.PlayTrackAt(0)
}

func (p *PlaybackManager) PlayTrackAt(idx int) error {
return p.player.PlayTrackAt(idx)
if idx < 0 || idx >= len(p.playQueue) {
return errors.New("track index out of range")
}
p.nowPlayingIdx = idx - 1
return p.setTrack(idx, false)
}

func (p *PlaybackManager) PlayRandomSongs(genreName string) {
Expand Down Expand Up @@ -325,7 +323,7 @@ func (p *PlaybackManager) OnTrackRatingChanged(id string, rating int) {

func (p *PlaybackManager) RemoveTracksFromQueue(trackIDs []string) {
newQueue := make([]*mediaprovider.Track, 0, len(p.playQueue)-len(trackIDs))
rmCount := 0
//rmCount := 0
idSet := sharedutil.ToSet(trackIDs)
isPlayingTrackRemoved := false
for i, tr := range p.playQueue {
Expand All @@ -336,13 +334,14 @@ func (p *PlaybackManager) RemoveTracksFromQueue(trackIDs []string) {
// If we are removing the currently playing track, we need to scrobble it
p.checkScrobble()
}
if err := p.player.RemoveTrackAt(i - rmCount); err == nil {
rmCount++
} else {
log.Printf("error removing track: %v", err.Error())
// did not remove this track
newQueue = append(newQueue, tr)
}
// if err := p.player.RemoveTrackAt(i - rmCount); err == nil {
// rmCount++
//} else {
var err error
log.Printf("error removing track: %v", err.Error())
// did not remove this track
newQueue = append(newQueue, tr)
//}
} else {
// not removing this track
newQueue = append(newQueue, tr)
Expand All @@ -359,9 +358,9 @@ func (p *PlaybackManager) RemoveTracksFromQueue(trackIDs []string) {
// Stop playback and clear the play queue.
func (p *PlaybackManager) StopAndClearPlayQueue() {
p.player.Stop()
p.player.ClearPlayQueue()
p.doUpdateTimePos()
p.playQueue = nil
p.nowPlayingIdx = -1
}

func (p *PlaybackManager) SetReplayGainOptions(config ReplayGainConfig) {
Expand Down Expand Up @@ -423,17 +422,17 @@ func (p *PlaybackManager) SetNextLoopMode() error {
if err != nil {
return err
}
for _, cb := range p.onLoopModeChange {
cb(p.player.GetLoopMode())
}
//for _, cb := range p.onLoopModeChange {
// cb(p.player.GetLoopMode())
//}

return nil
}

func (p *PlaybackManager) SetLoopMode(loopMode player.LoopMode) error {
if err := p.player.SetLoopMode(player.LoopMode(loopMode)); err != nil {
return err
}
//if err := p.player.SetLoopMode(player.LoopMode(loopMode)); err != nil {
// return err
//}

for _, cb := range p.onLoopModeChange {
cb(loopMode)
Expand All @@ -443,7 +442,8 @@ func (p *PlaybackManager) SetLoopMode(loopMode player.LoopMode) error {
}

func (p *PlaybackManager) GetLoopMode() player.LoopMode {
return p.player.GetLoopMode()
return 0
//return p.player.GetLoopMode()
}

func (p *PlaybackManager) PlayerStatus() player.Status {
Expand All @@ -466,14 +466,17 @@ func (p *PlaybackManager) Volume() int {
}

func (p *PlaybackManager) SeekNext() error {
return p.player.SeekNext()
if p.CurrentPlayer().GetStatus().State == player.Stopped {
return nil
}
return p.PlayTrackAt(p.nowPlayingIdx + 1)
}

func (p *PlaybackManager) SeekBackOrPrevious() error {
if p.player.GetStatus().TimePos > 3 {
if p.nowPlayingIdx == 0 || p.player.GetStatus().TimePos > 3 {
return p.player.SeekSeconds(0)
}
return p.player.SeekPrevious()
return p.PlayTrackAt(p.nowPlayingIdx - 1)
}

// Seek to given absolute position in the current track by seconds.
Expand Down Expand Up @@ -501,6 +504,9 @@ func (p *PlaybackManager) Pause() error {
}

func (p *PlaybackManager) Continue() error {
if p.player.GetStatus().State == player.Stopped {
return p.PlayFromBeginning()
}
return p.player.Continue()
}

Expand All @@ -516,6 +522,25 @@ func (p *PlaybackManager) PlayPause() error {
return errors.New("unreached - invalid player state")
}

func (p *PlaybackManager) setTrack(idx int, next bool) error {
if urlP, ok := p.player.(player.URLPlayer); ok {
url, err := p.sm.Server.GetStreamURL(p.playQueue[idx].ID, p.transcodeCfg.ForceRawFile)
if err != nil {
return err
}
if next {
return urlP.SetNextFile(url)
}
return urlP.PlayFile(url)
} else if trP, ok := p.player.(player.TrackPlayer); ok {
if next {
return trP.SetNextTrack(p.playQueue[idx])
}
return trP.PlayTrack(p.playQueue[idx])
}
panic("Unsupported player type")
}

// call BEFORE updating p.nowPlayingIdx
func (p *PlaybackManager) checkScrobble() {
if !p.scrobbleCfg.Enabled || len(p.playQueue) == 0 || p.nowPlayingIdx < 0 {
Expand Down
Loading

0 comments on commit d9eca8d

Please sign in to comment.