diff --git a/backend/playbackengine.go b/backend/playbackengine.go index f2e2526..f4589eb 100644 --- a/backend/playbackengine.go +++ b/backend/playbackengine.go @@ -248,7 +248,7 @@ func (p *playbackEngine) StopAndClearPlayQueue() { } func (p *playbackEngine) GetPlayQueue() []mediaprovider.MediaItem { - return p.deepCopyTrackSlice(p.playQueue) + return p.deepCopyMediaItemSlice(p.playQueue) } // Any time the user changes the favorite status of a track elsewhere in the app, @@ -274,8 +274,8 @@ func (p *playbackEngine) OnTrackRatingChanged(id string, rating int) { // Replaces the play queue with the given set of tracks. // Does not stop playback if the currently playing track is in the new queue, // but updates the now playing index to point to the first instance of the track in the new queue. -func (p *playbackEngine) UpdatePlayQueue(tracks []*mediaprovider.Track) error { - newQueue := p.copyTrackSliceToMediaItemSlice(tracks) +func (p *playbackEngine) UpdatePlayQueue(items []mediaprovider.MediaItem) error { + newQueue := p.deepCopyMediaItemSlice(items) newNowPlayingIdx := -1 if p.nowPlayingIdx >= 0 { nowPlayingID := p.playQueue[p.nowPlayingIdx].Metadata().ID @@ -548,7 +548,7 @@ func (p *playbackEngine) sendNowPlayingScrobble() { // creates a deep copy of the track info so that we can maintain our own state // (play count increases, favorite, and rating) without messing up other views' track models -func (p *playbackEngine) deepCopyTrackSlice(tracks []mediaprovider.MediaItem) []mediaprovider.MediaItem { +func (p *playbackEngine) deepCopyMediaItemSlice(tracks []mediaprovider.MediaItem) []mediaprovider.MediaItem { newTracks := make([]mediaprovider.MediaItem, len(tracks)) for i, tr := range tracks { newTracks[i] = tr.Copy() diff --git a/backend/playbackmanager.go b/backend/playbackmanager.go index 6c8e175..2581082 100644 --- a/backend/playbackmanager.go +++ b/backend/playbackmanager.go @@ -126,8 +126,8 @@ func (p *PlaybackManager) LoadTracks(tracks []*mediaprovider.Track, insertQueueM // Replaces the play queue with the given set of tracks. // Does not stop playback if the currently playing track is in the new queue, // but updates the now playing index to point to the first instance of the track in the new queue. -func (p *PlaybackManager) UpdatePlayQueue(tracks []*mediaprovider.Track) error { - return p.engine.UpdatePlayQueue(tracks) +func (p *PlaybackManager) UpdatePlayQueue(items []mediaprovider.MediaItem) error { + return p.engine.UpdatePlayQueue(items) } func (p *PlaybackManager) PlayAlbum(albumID string, firstTrack int, shuffle bool) error { diff --git a/sharedutil/sharedutil.go b/sharedutil/sharedutil.go index c407783..b549331 100644 --- a/sharedutil/sharedutil.go +++ b/sharedutil/sharedutil.go @@ -112,6 +112,9 @@ const ( MoveDown ) +// TODO: it's a shame the below function is just duplicated for a slice of mediaprovider.MediaItem +// Find out if there's a better way with refactoring. + // Reorder tracks and return a new track slice. // idxToMove must contain only valid indexes into tracks, and no repeats func ReorderTracks(tracks []*mediaprovider.Track, idxToMove []int, op TrackReorderOp) []*mediaprovider.Track { @@ -166,6 +169,60 @@ func ReorderTracks(tracks []*mediaprovider.Track, idxToMove []int, op TrackReord return newTracks } +// Reorder media items and return a new item slice. +// idxToMove must contain only valid indexes into items, and no repeats +func ReorderMediaItems(items []mediaprovider.MediaItem, idxToMove []int, op TrackReorderOp) []mediaprovider.MediaItem { + newTracks := make([]mediaprovider.MediaItem, len(items)) + switch op { + case MoveToTop: + topIdx := 0 + botIdx := len(idxToMove) + idxToMoveSet := ToSet(idxToMove) + for i, t := range items { + if _, ok := idxToMoveSet[i]; ok { + newTracks[topIdx] = t + topIdx++ + } else { + newTracks[botIdx] = t + botIdx++ + } + } + case MoveToBottom: + topIdx := 0 + botIdx := len(items) - len(idxToMove) + idxToMoveSet := ToSet(idxToMove) + for i, t := range items { + if _, ok := idxToMoveSet[i]; ok { + newTracks[botIdx] = t + botIdx++ + } else { + newTracks[topIdx] = t + topIdx++ + } + } + case MoveUp: + first := firstIdxCanMoveUp(idxToMove) + copy(newTracks, items) + for _, i := range idxToMove { + if i < first { + continue + } + newTracks[i-1], newTracks[i] = newTracks[i], newTracks[i-1] + } + case MoveDown: + last := lastIdxCanMoveDown(idxToMove, len(items)) + copy(newTracks, items) + for i := len(idxToMove) - 1; i >= 0; i-- { + idx := idxToMove[i] + if idx > last { + continue + } + newTracks[idx+1], newTracks[idx] = newTracks[idx], newTracks[idx+1] + } + } + return newTracks +} + func firstIdxCanMoveUp(idxs []int) int { prevIdx := -1 slices.Sort(idxs) diff --git a/ui/browsing/nowplayingpage.go b/ui/browsing/nowplayingpage.go index c182bf8..c0334b2 100644 --- a/ui/browsing/nowplayingpage.go +++ b/ui/browsing/nowplayingpage.go @@ -43,7 +43,7 @@ type NowPlayingPage struct { curRelatedID string // id of track currrently used to populate related list totalTime float64 lastPlayPos float64 - queue []*mediaprovider.Track + queue []mediaprovider.MediaItem related []*mediaprovider.Track lyricLock sync.Mutex @@ -122,7 +122,7 @@ func NewNowPlayingPage( a.queueList = widgets.NewPlayQueueList(a.im) a.relatedList = widgets.NewPlayQueueList(a.im) - a.queueList.OnReorderTracks = a.doSetNewTrackOrder + a.queueList.OnReorderItems = a.doSetNewTrackOrder a.queueList.OnDownload = contr.ShowDownloadDialog a.queueList.OnShare = func(tracks []*mediaprovider.Track) { if len(tracks) > 0 { @@ -401,12 +401,11 @@ func (a *NowPlayingPage) Reload() { a.relatedList.DisableRating = !a.canRate a.relatedList.DisableSharing = !a.canShare - // TODO - //a.queue = a.pm.GetPlayQueue() - a.queueList.SetTracks(a.queue) + a.queue = a.pm.GetPlayQueue() + a.queueList.SetItems(a.queue) a.totalTime = 0.0 for _, tr := range a.queue { - a.totalTime += float64(tr.Duration) + a.totalTime += float64(tr.Metadata().Duration) } a.formatStatusLine() } @@ -459,11 +458,11 @@ func (a *NowPlayingPage) doSetNewTrackOrder(trackIDs []string, op sharedutil.Tra trackIDSet := sharedutil.ToSet(trackIDs) idxs := make([]int, 0, len(trackIDs)) for i, tr := range a.queue { - if _, ok := trackIDSet[tr.ID]; ok { + if _, ok := trackIDSet[tr.Metadata().ID]; ok { idxs = append(idxs, i) } } - newTracks := sharedutil.ReorderTracks(a.queue, idxs, op) + newTracks := sharedutil.ReorderMediaItems(a.queue, idxs, op) a.pm.UpdatePlayQueue(newTracks) } diff --git a/ui/util/tracklistutil.go b/ui/util/tracklistutil.go index 0601329..d24e611 100644 --- a/ui/util/tracklistutil.go +++ b/ui/util/tracklistutil.go @@ -8,76 +8,82 @@ import ( ) type TrackListModel struct { - Track *mediaprovider.Track + Item mediaprovider.MediaItem Selected bool } +// Returns the item as a *mediaprovider.Track, or panics if not a Track +// Use for tracklists that can only contain tracks (ie not PlayQueueList) +func (t TrackListModel) Track() *mediaprovider.Track { + return t.Item.(*mediaprovider.Track) +} + func ToTrackListModels(trs []*mediaprovider.Track) []*TrackListModel { return sharedutil.MapSlice(trs, func(tr *mediaprovider.Track) *TrackListModel { - return &TrackListModel{Track: tr, Selected: false} + return &TrackListModel{Item: tr, Selected: false} }) } -func SelectedTracks(tracks []*TrackListModel) []*mediaprovider.Track { - return sharedutil.FilterMapSlice(tracks, func(tm *TrackListModel) (*mediaprovider.Track, bool) { - return tm.Track, tm.Selected +func SelectedTracks(items []*TrackListModel) []*mediaprovider.Track { + return sharedutil.FilterMapSlice(items, func(tm *TrackListModel) (*mediaprovider.Track, bool) { + return tm.Track(), tm.Selected }) } -func SelectedTrackIDs(tracks []*TrackListModel) []string { - return sharedutil.FilterMapSlice(tracks, func(tm *TrackListModel) (string, bool) { - return tm.Track.ID, tm.Selected +func SelectedItemIDs(items []*TrackListModel) []string { + return sharedutil.FilterMapSlice(items, func(tm *TrackListModel) (string, bool) { + return tm.Item.Metadata().ID, tm.Selected }) } -func SelectTrack(tracks []*TrackListModel, idx int) { - if tracks[idx].Selected { +func SelectItem(items []*TrackListModel, idx int) { + if items[idx].Selected { return } - UnselectAllTracks(tracks) - tracks[idx].Selected = true + UnselectAllItems(items) + items[idx].Selected = true } -func SelectAllTracks(tracks []*TrackListModel) { - for _, tm := range tracks { +func SelectAllItems(items []*TrackListModel) { + for _, tm := range items { tm.Selected = true } } -func UnselectAllTracks(tracks []*TrackListModel) { - for _, tm := range tracks { +func UnselectAllItems(items []*TrackListModel) { + for _, tm := range items { tm.Selected = false } } -func SelectTrackRange(tracks []*TrackListModel, idx int) { - if tracks[idx].Selected { +func SelectItemRange(items []*TrackListModel, idx int) { + if items[idx].Selected { return } lastSelected := -1 - for i := len(tracks) - 1; i >= 0; i-- { - if tracks[i].Selected { + for i := len(items) - 1; i >= 0; i-- { + if items[i].Selected { lastSelected = i break } } if lastSelected < 0 { - tracks[idx].Selected = true + items[idx].Selected = true return } from := min(idx, lastSelected) to := max(idx, lastSelected) for i := from; i <= to; i++ { - tracks[i].Selected = true + items[i].Selected = true } } -func FindTrackByID(tracks []*TrackListModel, id string) (*mediaprovider.Track, int) { - idx := slices.IndexFunc(tracks, func(tr *TrackListModel) bool { - return tr.Track.ID == id +func FindTrackByID(items []*TrackListModel, id string) (*mediaprovider.Track, int) { + idx := slices.IndexFunc(items, func(tr *TrackListModel) bool { + return tr.Item.Metadata().ID == id }) if idx >= 0 { - return tracks[idx].Track, idx + return items[idx].Track(), idx } return nil, -1 } diff --git a/ui/widgets/playqueuelist.go b/ui/widgets/playqueuelist.go index c402f21..d7ac04d 100644 --- a/ui/widgets/playqueuelist.go +++ b/ui/widgets/playqueuelist.go @@ -23,6 +23,11 @@ import ( const playQueueListThumbnailSize = 52 +type PlayQueueListModel struct { + Item mediaprovider.MediaItem + Selected bool +} + type PlayQueueList struct { widget.BaseWidget @@ -33,12 +38,12 @@ type PlayQueueList struct { OnAddToPlaylist func(trackIDs []string) OnSetFavorite func(trackIDs []string, fav bool) OnSetRating func(trackIDs []string, rating int) - OnRemoveFromQueue func(trackIDs []string) + OnRemoveFromQueue func(itemIDs []string) OnDownload func(tracks []*mediaprovider.Track, downloadName string) OnShare func(tracks []*mediaprovider.Track) OnShowArtistPage func(artistID string) OnPlayTrackAt func(idx int) - OnReorderTracks func(trackIDs []string, op sharedutil.TrackReorderOp) + OnReorderItems func(itemIDs []string, op sharedutil.TrackReorderOp) list *FocusList menu *widget.PopUpMenu @@ -49,7 +54,7 @@ type PlayQueueList struct { colLayout *layouts.ColumnsLayout tracksMutex sync.RWMutex - tracks []*util.TrackListModel + items []*util.TrackListModel } func NewPlayQueueList(im *backend.ImageManager) *PlayQueueList { @@ -78,16 +83,16 @@ func NewPlayQueueList(im *backend.ImageManager) *PlayQueueList { // we could have removed tracks from the list in between // Fyne calling the length callback and this update callback // so the itemID may be out of bounds. if so, do nothing. - if itemID >= len(p.tracks) { + if itemID >= len(p.items) { p.tracksMutex.RUnlock() return } - model := p.tracks[itemID] + model := p.items[itemID] p.tracksMutex.RUnlock() tr := item.(*PlayQueueListRow) p.list.SetItemForID(itemID, tr) - if tr.trackID != model.Track.ID || tr.ListItemID != itemID { + if tr.trackID != model.Item.Metadata().ID || tr.ListItemID != itemID { tr.ListItemID = itemID } tr.Update(model, itemID+1) @@ -100,7 +105,17 @@ func NewPlayQueueList(im *backend.ImageManager) *PlayQueueList { func (p *PlayQueueList) SetTracks(trs []*mediaprovider.Track) { p.tracksMutex.Lock() p.list.ClearItemForIDMap() - p.tracks = util.ToTrackListModels(trs) + p.items = util.ToTrackListModels(trs) + p.tracksMutex.Unlock() + p.Refresh() +} + +func (p *PlayQueueList) SetItems(items []mediaprovider.MediaItem) { + p.tracksMutex.Lock() + p.list.ClearItemForIDMap() + p.items = sharedutil.MapSlice(items, func(item mediaprovider.MediaItem) *util.TrackListModel { + return &util.TrackListModel{Item: item} + }) p.tracksMutex.Unlock() p.Refresh() } @@ -109,8 +124,8 @@ func (p *PlayQueueList) SetTracks(trs []*mediaprovider.Track) { func (p *PlayQueueList) SetNowPlaying(trackID string) { prevNowPlaying := p.nowPlayingID p.tracksMutex.RLock() - trPrev, idxPrev := util.FindTrackByID(p.tracks, prevNowPlaying) - tr, idx := util.FindTrackByID(p.tracks, trackID) + trPrev, idxPrev := util.FindTrackByID(p.items, prevNowPlaying) + tr, idx := util.FindTrackByID(p.items, trackID) p.tracksMutex.RUnlock() p.nowPlayingID = trackID if trPrev != nil { @@ -123,14 +138,14 @@ func (p *PlayQueueList) SetNowPlaying(trackID string) { func (p *PlayQueueList) SelectAll() { p.tracksMutex.RLock() - util.SelectAllTracks(p.tracks) + util.SelectAllItems(p.items) p.tracksMutex.RUnlock() p.list.Refresh() } func (p *PlayQueueList) UnselectAll() { p.tracksMutex.RLock() - util.UnselectAllTracks(p.tracks) + util.UnselectAllItems(p.items) p.tracksMutex.RUnlock() p.Refresh() } @@ -138,7 +153,7 @@ func (p *PlayQueueList) UnselectAll() { func (p *PlayQueueList) lenTracks() int { p.tracksMutex.RLock() defer p.tracksMutex.RUnlock() - return len(p.tracks) + return len(p.items) } func (t *PlayQueueList) onArtistTapped(artistID string) { @@ -172,19 +187,19 @@ func (p *PlayQueueList) onSelectTrack(idx int) { func (p *PlayQueueList) selectTrack(idx int) { p.tracksMutex.RLock() defer p.tracksMutex.RUnlock() - util.SelectTrack(p.tracks, idx) + util.SelectItem(p.items, idx) } func (p *PlayQueueList) selectAddOrRemove(idx int) { p.tracksMutex.RLock() defer p.tracksMutex.RUnlock() - p.tracks[idx].Selected = !p.tracks[idx].Selected + p.items[idx].Selected = !p.items[idx].Selected } func (p *PlayQueueList) selectRange(idx int) { p.tracksMutex.RLock() defer p.tracksMutex.RUnlock() - util.SelectTrackRange(p.tracks, idx) + util.SelectItemRange(p.items, idx) } func (p *PlayQueueList) onShowContextMenu(e *fyne.PointEvent, trackIdx int) { @@ -233,8 +248,8 @@ func (p *PlayQueueList) onShowContextMenu(e *fyne.PointEvent, trackIdx int) { }) remove.Icon = theme.ContentRemoveIcon() reorder := util.NewReorderTracksSubmenu(func(tro sharedutil.TrackReorderOp) { - if p.OnReorderTracks != nil { - p.OnReorderTracks(p.selectedTrackIDs(), tro) + if p.OnReorderItems != nil { + p.OnReorderItems(p.selectedTrackIDs(), tro) } }) @@ -262,13 +277,13 @@ func (p *PlayQueueList) onShowContextMenu(e *fyne.PointEvent, trackIdx int) { func (t *PlayQueueList) selectedTracks() []*mediaprovider.Track { t.tracksMutex.RLock() defer t.tracksMutex.RUnlock() - return util.SelectedTracks(t.tracks) + return util.SelectedTracks(t.items) } func (t *PlayQueueList) selectedTrackIDs() []string { t.tracksMutex.RLock() defer t.tracksMutex.RUnlock() - return util.SelectedTrackIDs(t.tracks) + return util.SelectedItemIDs(t.items) } func (p *PlayQueueList) CreateRenderer() fyne.WidgetRenderer { @@ -355,19 +370,19 @@ func (p *PlayQueueListRow) Update(tm *util.TrackListModel, rowNum int) { // Update info that can change if this row is bound to // a new track (*mediaprovider.Track) - tr := tm.Track - if tr.ID != p.trackID { - p.imageLoader.Load(tm.Track.CoverArtID) + meta := tm.Item.Metadata() + if meta.ID != p.trackID { + p.imageLoader.Load(meta.CoverArtID) p.EnsureUnfocused() - p.trackID = tr.ID - p.title.Text = tr.Title - p.artist.BuildSegments(tr.ArtistNames, tr.ArtistIDs) - p.time.Text = util.SecondsToTimeString(float64(tr.Duration)) + p.trackID = meta.ID + p.title.Text = meta.Name + p.artist.BuildSegments(meta.Artists, meta.ArtistIDs) + p.time.Text = util.SecondsToTimeString(float64(meta.Duration)) changed = true } // Render whether track is playing or not - if isPlaying := p.playQueueList.nowPlayingID == tr.ID; isPlaying != p.isPlaying { + if isPlaying := p.playQueueList.nowPlayingID == meta.ID; isPlaying != p.isPlaying { p.isPlaying = isPlaying p.title.TextStyle.Bold = isPlaying diff --git a/ui/widgets/tracklist.go b/ui/widgets/tracklist.go index d5f5d43..0957799 100644 --- a/ui/widgets/tracklist.go +++ b/ui/widgets/tracklist.go @@ -171,7 +171,7 @@ func NewTracklist(tracks []*mediaprovider.Track, im *backend.ImageManager, useCo tr := item.(TracklistRow) t.list.SetItemForID(itemID, tr) - if tr.TrackID() != model.Track.ID || tr.ItemID() != itemID { + if tr.TrackID() != model.Item.Metadata().ID || tr.ItemID() != itemID { tr.SetItemID(itemID) } i := -1 // signal that we want to display the actual track num. @@ -206,7 +206,7 @@ func (t *Tracklist) TrackAt(idx int) *mediaprovider.Track { log.Println("error: Tracklist.TrackAt: index out of range") return nil } - return t.tracks[idx].Track + return t.tracks[idx].Track() } func (t *Tracklist) SetVisibleColumns(cols []string) { @@ -324,7 +324,7 @@ func (t *Tracklist) GetTracks() []*mediaprovider.Track { t.tracksMutex.RLock() defer t.tracksMutex.RUnlock() return sharedutil.MapSlice(t.tracks, func(tm *util.TrackListModel) *mediaprovider.Track { - return tm.Track + return tm.Track() }) } @@ -338,7 +338,7 @@ func (t *Tracklist) AppendTracks(trs []*mediaprovider.Track) { func (t *Tracklist) SelectAll() { t.tracksMutex.RLock() - util.SelectAllTracks(t.tracks) + util.SelectAllItems(t.tracks) t.tracksMutex.RUnlock() t.list.Refresh() } @@ -350,7 +350,7 @@ func (t *Tracklist) UnselectAll() { func (t *Tracklist) unselectAll() { t.tracksMutex.RLock() - util.UnselectAllTracks(t.tracks) + util.UnselectAllItems(t.tracks) t.tracksMutex.RUnlock() } @@ -358,7 +358,7 @@ func (t *Tracklist) SelectAndScrollToTrack(trackID string) { t.tracksMutex.RLock() idx := -1 for i, tr := range t.tracks { - if tr.Track.ID == trackID { + if tr.Item.Metadata().ID == trackID { idx = i tr.Selected = true } else { @@ -422,30 +422,30 @@ func (t *Tracklist) doSortTracks() { t.tracks = t.tracksOrigOrder } case ColumnTitle: - t.stringSort(func(tr *util.TrackListModel) string { return tr.Track.Title }) + t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Title }) case ColumnArtist: - t.stringSort(func(tr *util.TrackListModel) string { return strings.Join(tr.Track.ArtistNames, ", ") }) + t.stringSort(func(tr *util.TrackListModel) string { return strings.Join(tr.Track().ArtistNames, ", ") }) case ColumnAlbum: - t.stringSort(func(tr *util.TrackListModel) string { return tr.Track.Album }) + t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Album }) case ColumnPath: - t.stringSort(func(tr *util.TrackListModel) string { return tr.Track.FilePath }) + t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().FilePath }) case ColumnRating: - t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track.Rating) }) + t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track().Rating) }) case ColumnTime: - t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track.Duration) }) + t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track().Duration) }) case ColumnYear: - t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track.Year) }) + t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track().Year) }) case ColumnSize: - t.intSort(func(tr *util.TrackListModel) int64 { return tr.Track.Size }) + t.intSort(func(tr *util.TrackListModel) int64 { return tr.Track().Size }) case ColumnPlays: - t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track.PlayCount) }) + t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track().PlayCount) }) case ColumnComment: - t.stringSort(func(tr *util.TrackListModel) string { return tr.Track.Comment }) + t.stringSort(func(tr *util.TrackListModel) string { return tr.Track().Comment }) case ColumnBitrate: - t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track.BitRate) }) + t.intSort(func(tr *util.TrackListModel) int64 { return int64(tr.Track().BitRate) }) case ColumnFavorite: t.intSort(func(tr *util.TrackListModel) int64 { - if tr.Track.Favorite { + if tr.Track().Favorite { return 1 } return 0 @@ -492,13 +492,13 @@ func (t *Tracklist) selectAddOrRemove(idx int) { func (t *Tracklist) selectTrack(idx int) { t.tracksMutex.RLock() defer t.tracksMutex.RUnlock() - util.SelectTrack(t.tracks, idx) + util.SelectItem(t.tracks, idx) } func (t *Tracklist) selectRange(idx int) { t.tracksMutex.RLock() defer t.tracksMutex.RUnlock() - util.SelectTrackRange(t.tracks, idx) + util.SelectItemRange(t.tracks, idx) } func (t *Tracklist) onShowContextMenu(e *fyne.PointEvent, trackIdx int) { @@ -663,7 +663,7 @@ func (t *Tracklist) selectedTracks() []*mediaprovider.Track { func (t *Tracklist) SelectedTrackIDs() []string { t.tracksMutex.RLock() defer t.tracksMutex.RUnlock() - return util.SelectedTrackIDs(t.tracks) + return util.SelectedItemIDs(t.tracks) } func (t *Tracklist) lenTracks() int { diff --git a/ui/widgets/tracklistrow.go b/ui/widgets/tracklistrow.go index 0e9bf0f..394d0bd 100644 --- a/ui/widgets/tracklistrow.go +++ b/ui/widgets/tracklistrow.go @@ -175,8 +175,8 @@ func NewExpandedTracklistRow(tracklist *Tracklist, im *backend.ImageManager, pla } func (t *ExpandedTracklistRow) Update(tm *util.TrackListModel, rowNum int) { - if t.trackID != tm.Track.ID { - t.imageLoader.Load(tm.Track.CoverArtID) + if t.trackID != tm.Track().ID { + t.imageLoader.Load(tm.Track().CoverArtID) } t.tracklistRowBase.Update(tm, rowNum) } @@ -256,10 +256,10 @@ func (t *tracklistRowBase) Update(tm *util.TrackListModel, rowNum int) { // Update info that can change if this row is bound to // a new track (*mediaprovider.Track) - tr := tm.Track - if tr.ID != t.trackID { + tr := tm.Track() + if id := tr.ID; id != t.trackID { t.EnsureUnfocused() - t.trackID = tr.ID + t.trackID = id t.name.Segments[0].(*widget.TextSegment).Text = tr.Title t.artist.BuildSegments(tr.ArtistNames, tr.ArtistIDs)