Merge pull request #762 from zacaj/feature/nowPlaying-album-year

Fix #741: add album year to now playing
This commit is contained in:
Drew Weymouth
2025-11-26 14:21:57 -05:00
committed by GitHub
24 changed files with 100 additions and 47 deletions
+1 -1
View File
@@ -174,7 +174,7 @@
"Show info": "Info anzeigen",
"Show notification on track change": "Benachrichtigung bei Titelwechsel anzeigen",
"Show play queue": "Wiedergabeliste anzeigen",
"Show year in album grid cards": "Erscheinungsjahr in Alben-Übersicht anzeigen",
"Show year in album grid and now playing": "Erscheinungsjahr in Alben-Übersicht anzeigen",
"Shuffle": "Zufallswiedergabe",
"Shuffle albums": "Alben zufällig wiedergeben",
"Shuffle tracks": "Titel zufällig wiedergeben",
+1 -1
View File
@@ -209,7 +209,7 @@
"Show info": "Show info",
"Show notification on track change": "Show notification on track change",
"Show play queue": "Show play queue",
"Show year in album grid cards": "Show year in album grid cards",
"Show year in album grid and now playing": "Show year in album grid and now playing",
"Shuffle": "Shuffle",
"Shuffled": "Shuffled",
"Shuffle albums": "Shuffle albums",
+1 -1
View File
@@ -182,7 +182,7 @@
"Show info": "Mostrar información",
"Show notification on track change": "Mostrar notificación en cambio de pista",
"Show play queue": "Mostrar cola de reproducción",
"Show year in album grid cards": "Mostrar año en tarjetas de cuadrícula de álbumes",
"Show year in album grid and now playing": "Mostrar año en tarjetas de cuadrícula de álbumes",
"Shuffle": "Aleatorio",
"Shuffle albums": "Aleatorio álbumes",
"Shuffle tracks": "Aleatorio pistas",
+1 -1
View File
@@ -202,7 +202,7 @@
"Show info": "Afficher les informations",
"Show notification on track change": "Afficher une notification à chaque changement de piste",
"Show play queue": "Afficher la file d'attente",
"Show year in album grid cards": "Afficher les années sous les vignettes d'albums",
"Show year in album grid and now playing": "Afficher les années sous les vignettes d'albums",
"Shuffle": "Mélanger",
"Shuffled": "Mélangés",
"Shuffle albums": "Mélanger les albums",
+1 -1
View File
@@ -173,7 +173,7 @@
"Show info": "Mostra informazioni",
"Show notification on track change": "Mostra notifica quando cambia la traccia",
"Show play queue": "Mostra coda",
"Show year in album grid cards": "Mostra l'anno nella griglia degli album",
"Show year in album grid and now playing": "Mostra l'anno nella griglia degli album",
"Shuffle": "Casuale",
"Shuffle albums": "Album casuali",
"Shuffle tracks": "Tracce casuali",
+1 -1
View File
@@ -195,7 +195,7 @@
"Show info": "情報を表示",
"Show notification on track change": "トラックの変更時に通知を表示する",
"Show play queue": "再生キューを表示",
"Show year in album grid cards": "アルバムのグリッドカードに年を表示",
"Show year in album grid and now playing": "アルバムのグリッドカードに年を表示",
"Shuffle": "シャッフル",
"Shuffle albums": "アルバムをシャッフル",
"Shuffle tracks": "トラックをシャッフル",
+1 -1
View File
@@ -195,7 +195,7 @@
"Show info": "정보 표시",
"Show notification on track change": "트랙 변경 시 알림 표시",
"Show play queue": "대기열 표시",
"Show year in album grid cards": "앨범 그리드에서 연도를 표시",
"Show year in album grid and now playing": "앨범 그리드에서 연도를 표시",
"Shuffle": "셔플",
"Shuffle albums": "앨범 셔플하기",
"Shuffle tracks": "트랙 셔플하기",
+1 -1
View File
@@ -189,7 +189,7 @@
"Show info": "Toon info",
"Show notification on track change": "Toon melding bij veranderen nummer",
"Show play queue": "Toon afspeelwachtrij",
"Show year in album grid cards": "Geef jaar weer in album rooster",
"Show year in album grid and now playing": "Geef jaar weer in album rooster",
"Shuffle": "Door mekaar smijten",
"Shuffle albums": "Albums door mekaar smijten",
"Shuffle tracks": "Nummers door mekaar smijten",
+1 -1
View File
@@ -185,7 +185,7 @@
"Show info": "Pokaż informacje",
"Show notification on track change": "Pokaż powiadomienie o zmianie ścieżki",
"Show play queue": "Pokaż kolejkę odtwarzania",
"Show year in album grid cards": "Pokaż rok w zakładce albumu",
"Show year in album grid and now playing": "Pokaż rok w zakładce albumu",
"Shuffle": "Wymieszaj",
"Shuffle albums": "Wymieszaj album",
"Shuffle tracks": "Wymieszaj ścieżki",
+1 -1
View File
@@ -191,7 +191,7 @@
"Show info": "Mostrar informações",
"Show notification on track change": "Mostrar notificação ao mudar de faixa",
"Show play queue": "Mostrar fila de reprodução",
"Show year in album grid cards": "Mostrar ano nos cartões da grade de álbuns",
"Show year in album grid and now playing": "Mostrar ano nos cartões da grade de álbuns",
"Shuffle": "Aleatório",
"Shuffle albums": "Álbuns em ordem aleatória",
"Shuffle tracks": "Faixas em ordem aleatória",
+1 -1
View File
@@ -165,7 +165,7 @@
"Show": "Arată",
"Show info": "Arată informații",
"Show notification on track change": "Arată notificare la schimbarea melodiei",
"Show year in album grid cards": "Arată anul în gridul de albume",
"Show year in album grid and now playing": "Arată anul în gridul de albume",
"Shuffle": "Amestecare",
"Shuffle albums": "Amestecă albume",
"Shuffle tracks": "Amestecă melodii",
+1 -1
View File
@@ -197,7 +197,7 @@
"Show info": "Информация",
"Show notification on track change": "Уведомлять при смене композиции",
"Show play queue": "Очередь воспроизведения",
"Show year in album grid cards": "Показывать год на карточках альбомов",
"Show year in album grid and now playing": "Показывать год на карточках альбомов",
"Shuffle": "Вперемешку",
"Shuffle albums": "Перемешать альбомы",
"Shuffle tracks": "Перемешать композиции",
+1 -1
View File
@@ -195,7 +195,7 @@
"Show info": "显示信息",
"Show notification on track change": "曲目更改时显示通知",
"Show play queue": "显示播放队列",
"Show year in album grid cards": "在专辑网格卡中显示年份",
"Show year in album grid and now playing": "在专辑网格卡中显示年份",
"Shuffle": "随机播放",
"Shuffle albums": "随机播放专辑",
"Shuffle tracks": "随机播放曲目",
+1 -1
View File
@@ -195,7 +195,7 @@
"Show info": "显示信息",
"Show notification on track change": "曲目更改时显示通知",
"Show play queue": "显示播放队列",
"Show year in album grid cards": "在专辑网格卡中显示年份",
"Show year in album grid and now playing": "在专辑网格卡中显示年份",
"Shuffle": "随机播放",
"Shuffle albums": "随机播放专辑",
"Shuffle tracks": "随机播放曲目",
+1 -1
View File
@@ -165,7 +165,7 @@
"Show": "顯示",
"Show info": "顯示資訊",
"Show notification on track change": "曲目更改時顯示通知",
"Show year in album grid cards": "在專輯網格卡中顯示年份",
"Show year in album grid and now playing": "在專輯網格卡中顯示年份",
"Shuffle": "隨機播放",
"Shuffle albums": "隨機播放專輯",
"Shuffle tracks": "隨機播放曲目",
+13 -7
View File
@@ -24,12 +24,14 @@ type BottomPanel struct {
AuxControls *widgets.AuxControls
container *fyne.Container
cfg *backend.Config
}
var _ fyne.Widget = (*BottomPanel)(nil)
func NewBottomPanel(pm *backend.PlaybackManager, im *backend.ImageManager, contr *controller.Controller, useWaveformSeekbar bool) *BottomPanel {
bp := &BottomPanel{}
func NewBottomPanel(pm *backend.PlaybackManager, im *backend.ImageManager, contr *controller.Controller, cfg *backend.Config) *BottomPanel {
bp := &BottomPanel{cfg: cfg}
bp.ExtendBaseWidget(bp)
pm.OnSongChange(bp.onSongChange)
@@ -47,6 +49,7 @@ func NewBottomPanel(pm *backend.PlaybackManager, im *backend.ImageManager, contr
pm.OnStopped(util.FyneDoFunc(func() { bp.Controls.SetPlaying(false) }))
bp.NowPlaying = widgets.NewNowPlayingCard()
bp.NowPlaying.ShowAlbumYear = cfg.AlbumsPage.ShowYears
bp.NowPlaying.OnCoverTapped = func() {
contr.NavigateTo(controller.NowPlayingRoute())
}
@@ -65,10 +68,8 @@ func NewBottomPanel(pm *backend.PlaybackManager, im *backend.ImageManager, contr
contr.DoAddTracksToPlaylistWorkflow([]string{tr.ID})
}
}
bp.NowPlaying.OnAlbumNameTapped = func() {
if tr, ok := pm.NowPlaying().(*mediaprovider.Track); ok {
contr.NavigateTo(controller.AlbumRoute(tr.AlbumID))
}
bp.NowPlaying.OnAlbumNameTapped = func(albumID string) {
contr.NavigateTo(controller.AlbumRoute(albumID))
}
bp.NowPlaying.OnArtistNameTapped = func(artistID string) {
contr.NavigateTo(controller.ArtistRoute(artistID))
@@ -86,7 +87,7 @@ func NewBottomPanel(pm *backend.PlaybackManager, im *backend.ImageManager, contr
contr.ShowShareDialog(tr.ID)
}
}
bp.Controls = widgets.NewPlayerControls(useWaveformSeekbar)
bp.Controls = widgets.NewPlayerControls(cfg.Playback.UseWaveformSeekbar)
bp.Controls.OnPlayPause(func() {
pm.PlayPause()
})
@@ -148,6 +149,11 @@ func (bp *BottomPanel) updateWaveformImg(img *backend.WaveformImage) {
})
}
func (bp *BottomPanel) Refresh() {
bp.NowPlaying.ShowAlbumYear = bp.cfg.AlbumsPage.ShowYears
bp.BaseWidget.Refresh()
}
func (bp *BottomPanel) CreateRenderer() fyne.WidgetRenderer {
bp.ExtendBaseWidget(bp)
return widget.NewSimpleRenderer(bp.container)
+8 -2
View File
@@ -79,6 +79,7 @@ type nowPlayingPageState struct {
mp mediaprovider.MediaProvider
canRate bool
canShare bool
cfg *backend.Config
}
func NewNowPlayingPage(
@@ -92,9 +93,10 @@ func NewNowPlayingPage(
mp mediaprovider.MediaProvider,
canRate bool,
canShare bool,
cfg *backend.Config,
) *NowPlayingPage {
state := nowPlayingPageState{
conf: conf, contr: contr, pool: pool, sm: sm, lm: lm, im: im, pm: pm, mp: mp, canRate: canRate, canShare: canShare,
conf: conf, contr: contr, pool: pool, sm: sm, lm: lm, im: im, pm: pm, mp: mp, canRate: canRate, canShare: canShare, cfg: cfg,
}
if page, ok := pool.Obtain(util.WidgetTypeNowPlayingPage).(*NowPlayingPage); ok && page != nil {
page.nowPlayingPageState = state
@@ -127,6 +129,7 @@ func NewNowPlayingPage(
a.card.OnSetRating = func(rating int) {
a.contr.SetTrackRatings([]string{a.nowPlayingID}, rating)
}
a.card.ShowAlbumYear = cfg.AlbumsPage.ShowYears
a.queueList = widgets.NewPlayQueueList(a.im, false)
a.relatedList = widgets.NewPlayQueueList(a.im, true)
@@ -474,7 +477,7 @@ func (a *NowPlayingPage) Reload() {
}
func (s *nowPlayingPageState) Restore() Page {
return NewNowPlayingPage(s.conf, s.contr, s.pool, s.sm, s.lm, s.im, s.pm, s.mp, s.canRate, s.canShare)
return NewNowPlayingPage(s.conf, s.contr, s.pool, s.sm, s.lm, s.im, s.pm, s.mp, s.canRate, s.canShare, s.cfg)
}
var _ CanShowPlayTime = (*NowPlayingPage)(nil)
@@ -527,6 +530,9 @@ func (a *NowPlayingPage) Refresh() {
}
}
a.BaseWidget.Refresh()
a.card.ShowAlbumYear = a.cfg.AlbumsPage.ShowYears
a.card.Update(a.nowPlaying)
}
func (a *NowPlayingPage) saveSelectedTab(tabNum int) {
+1 -1
View File
@@ -50,7 +50,7 @@ func (r Router) CreatePage(rte controller.Route) Page {
case controller.Genres:
return NewGenresPage(r.Controller, r.App.ServerManager.Server)
case controller.NowPlaying:
return NewNowPlayingPage(&r.App.Config.NowPlayingConfig, r.Controller, r.widgetPool, r.App.ServerManager, r.App.LyricsManager, r.App.ImageManager, r.App.PlaybackManager, r.App.ServerManager.Server, canRate, canShare)
return NewNowPlayingPage(&r.App.Config.NowPlayingConfig, r.Controller, r.widgetPool, r.App.ServerManager, r.App.LyricsManager, r.App.ImageManager, r.App.PlaybackManager, r.App.ServerManager.Server, canRate, canShare, r.App.Config)
case controller.Playlist:
return NewPlaylistPage(rte.Arg, &r.App.Config.PlaylistPage, r.widgetPool, r.Controller, r.App.ServerManager, r.App.PlaybackManager, r.App.ImageManager)
case controller.Playlists:
+1 -1
View File
@@ -184,7 +184,7 @@ func (s *SettingsDialog) createGeneralTab(canSaveQueueToServer bool) *container.
trackNotif := widget.NewCheckWithData(lang.L("Show notification on track change"),
binding.BindBool(&s.config.Application.ShowTrackChangeNotification))
albumGridYears := widget.NewCheck(lang.L("Show year in album grid cards"), func(b bool) {
albumGridYears := widget.NewCheck(lang.L("Show year in album grid and now playing"), func(b bool) {
s.config.AlbumsPage.ShowYears = b
s.config.FavoritesPage.ShowAlbumYears = b
if s.OnPageNeedsRefresh != nil {
+5 -2
View File
@@ -85,7 +85,10 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
m.Controller.NavHandler = m.Router.NavigateTo
m.Controller.ReloadFunc = m.BrowsingPane.Reload
m.Controller.CurPageFunc = m.BrowsingPane.CurrentPage
m.Controller.RefreshPageFunc = m.BrowsingPane.RefreshPage
m.Controller.RefreshPageFunc = func() {
m.BrowsingPane.RefreshPage()
m.BottomPanel.Refresh()
}
m.Controller.SelectAllPageFunc = m.BrowsingPane.SelectAll
m.Controller.UnselectAllPageFunc = m.BrowsingPane.UnselectAll
m.Controller.ToastProvider = m.ToastOverlay
@@ -102,7 +105,7 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
))
}
m.BottomPanel = NewBottomPanel(app.PlaybackManager, app.ImageManager, m.Controller, m.Controller.App.Config.Playback.UseWaveformSeekbar)
m.BottomPanel = NewBottomPanel(app.PlaybackManager, app.ImageManager, m.Controller, app.Config)
app.PlaybackManager.OnSongChange(func(item mediaprovider.MediaItem, _ *mediaprovider.Track) {
fyne.Do(func() { m.UpdateOnTrackChange(item) })
})
+13
View File
@@ -2,6 +2,7 @@ package widgets
import (
"image"
"strconv"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
@@ -20,6 +21,7 @@ type LargeNowPlayingCard struct {
CaptionedImage
DisableRating bool
ShowAlbumYear bool
isRadio bool
trackName *widget.RichText
@@ -30,6 +32,8 @@ type LargeNowPlayingCard struct {
ratingFavoriteContainer *fyne.Container
cover *ImagePlaceholder
albumYear string
OnArtistNameTapped func(artistID string)
OnAlbumNameTapped func()
OnRadioURLTapped func(url string)
@@ -72,6 +76,7 @@ func NewLargeNowPlayingCard() *LargeNowPlayingCard {
n.trackName.Truncation = fyne.TextTruncateEllipsis
n.albumName.SizeName = myTheme.SizeNameSubSubHeadingText
n.albumName.OnTapped = n.onAlbumNameTapped
n.albumName.SuffixParenthesized = true
n.artistName.OnTapped = n.onArtistNameTapped
n.artistName.SizeName = myTheme.SizeNameSubSubHeadingText
@@ -125,6 +130,7 @@ func (n *LargeNowPlayingCard) Update(item mediaprovider.MediaItem) {
n.trackName.Segments[0].(*widget.TextSegment).Text = ""
n.artistName.BuildSegments([]string{}, []string{})
n.albumName.BuildSegments([]string{}, []string{})
n.albumName.Suffix = ""
n.rating.Rating = 0
n.favorite.Favorite = false
n.ratingFavoriteContainer.Hidden = true
@@ -143,11 +149,13 @@ func (n *LargeNowPlayingCard) Update(item mediaprovider.MediaItem) {
n.cover.PlaceholderIcon = myTheme.TracksIcon
n.ratingFavoriteContainer.Hidden = false
n.isRadio = false
n.albumYear = strconv.Itoa(tr.Year)
} else if rd, ok := item.(*mediaprovider.RadioStation); ok {
n.artistName.BuildSegments([]string{rd.HomePageURL}, []string{rd.HomePageURL})
n.ratingFavoriteContainer.Hidden = true
n.cover.PlaceholderIcon = myTheme.RadioIcon
n.isRadio = true
n.albumYear = ""
}
n.Refresh()
@@ -163,5 +171,10 @@ func (n *LargeNowPlayingCard) Refresh() {
} else {
n.rating.Enable()
}
if n.ShowAlbumYear {
n.albumName.Suffix = n.albumYear
} else {
n.albumName.Suffix = ""
}
n.BaseWidget.Refresh()
}
+12 -4
View File
@@ -14,10 +14,12 @@ type MultiHyperlink struct {
Segments []MultiHyperlinkSegment
// Suffix string that is appended (with · separator)
// only if there is enough room
// Suffix string that is appended (with · separator, or parenthesized
// if SuffixParenthesized is true) only if there is enough room
Suffix string
SuffixParenthesized bool
OnMouseIn func(*desktop.MouseEvent)
OnMouseOut func()
OnTapped func(string)
@@ -139,12 +141,18 @@ func (c *MultiHyperlink) layoutObjects() {
i += 1
c.content.Objects = c.objects[:2*i-1]
if i == len(c.Segments) && c.Suffix != "" {
var suffixText string
if c.SuffixParenthesized {
suffixText = "\u2009(" + c.Suffix + ")"
} else {
suffixText = "· " + c.Suffix
}
if c.suffixLabel == nil {
c.suffixLabel = ttwidget.NewRichTextWithText("· " + c.Suffix)
c.suffixLabel = ttwidget.NewRichTextWithText(suffixText)
c.suffixLabel.OnMouseIn = c.callOnMouseIn
c.suffixLabel.OnMouseOut = c.callOnMouseOut
} else {
c.suffixLabel.Segments[0].(*widget.TextSegment).Text = "· " + c.Suffix
c.suffixLabel.Segments[0].(*widget.TextSegment).Text = suffixText
}
sizeName := c.sizeName()
if c.SuffixSizeName != "" {
+27 -14
View File
@@ -2,6 +2,7 @@ package widgets
import (
"image"
"strconv"
"fyne.io/fyne/v2/lang"
@@ -15,7 +16,6 @@ import (
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
ttwidget "github.com/dweymouth/fyne-tooltip/widget"
)
// Shows the current album art, track name, artist name, and album name
@@ -24,17 +24,20 @@ type NowPlayingCard struct {
widget.BaseWidget
DisableRating bool
ShowAlbumYear bool
trackName *OptionHyperlink
artistName *MultiHyperlink
albumName *ttwidget.Hyperlink
albumName *MultiHyperlink
cover *ImagePlaceholder
menu *widget.PopUpMenu
ratingMenu *fyne.MenuItem
albumYear string
OnTrackNameTapped func()
OnArtistNameTapped func(artistID string)
OnAlbumNameTapped func()
OnAlbumNameTapped func(albumID string)
OnCoverTapped func()
OnSetRating func(rating int)
OnSetFavorite func(favorite bool)
@@ -47,7 +50,7 @@ func NewNowPlayingCard() *NowPlayingCard {
n := &NowPlayingCard{
trackName: NewOptionHyperlink(),
artistName: NewMultiHyperlink(),
albumName: ttwidget.NewHyperlink("", nil),
albumName: NewMultiHyperlink(),
}
n.ExtendBaseWidget(n)
n.cover = NewImagePlaceholder(myTheme.TracksIcon, 85)
@@ -56,7 +59,8 @@ func NewNowPlayingCard() *NowPlayingCard {
n.cover.Hidden = true
n.trackName.Hidden = true
n.albumName.Hidden = true
n.albumName.Truncation = fyne.TextTruncateEllipsis
n.albumName.SuffixParenthesized = true
n.albumName.SuffixSizeName = myTheme.SizeNameSubText
n.trackName.SetTextStyle(fyne.TextStyle{Bold: true})
n.trackName.OnShowMenu = n.showMenu
n.albumName.OnTapped = n.onAlbumNameTapped
@@ -71,9 +75,9 @@ func (n *NowPlayingCard) MinSize() fyne.Size {
return fyne.NewSize(n.BaseWidget.MinSize().Width, 85)
}
func (n *NowPlayingCard) onAlbumNameTapped() {
func (n *NowPlayingCard) onAlbumNameTapped(albumID string) {
if n.OnAlbumNameTapped != nil {
n.OnAlbumNameTapped()
n.OnAlbumNameTapped(albumID)
}
}
@@ -138,28 +142,28 @@ func (n *NowPlayingCard) Update(track mediaprovider.MediaItem) {
if track == nil {
n.trackName.SetTextAndToolTip("")
n.artistName.BuildSegments([]string{}, []string{})
n.albumName.SetText("")
n.albumName.SetToolTip("")
n.albumName.BuildSegments([]string{}, []string{})
n.albumYear = ""
n.cover.Hidden = true
} else {
n.cover.Hidden = false
n.trackName.SetTextAndToolTip(track.Metadata().Name)
if tr, ok := track.(*mediaprovider.Track); ok {
n.artistName.BuildSegments(tr.ArtistNames, tr.ArtistIDs)
n.albumName.SetText(tr.Album)
n.albumName.SetToolTip(tr.Album)
n.albumName.BuildSegments([]string{tr.Album}, []string{tr.AlbumID})
n.albumYear = strconv.Itoa(tr.Year)
n.cover.PlaceholderIcon = myTheme.TracksIcon
} else {
n.artistName.BuildSegments([]string{}, []string{})
n.albumName.SetText("")
n.albumName.SetToolTip("")
n.albumName.BuildSegments([]string{}, []string{})
n.albumName.Suffix = ""
n.cover.PlaceholderIcon = myTheme.RadioIcon
}
}
n.trackName.Hidden = n.trackName.Text() == ""
n.trackName.SetMenuBtnEnabled(n.cover.PlaceholderIcon != myTheme.RadioIcon)
n.artistName.Hidden = len(n.artistName.Segments) == 0
n.albumName.Hidden = n.albumName.Text == ""
n.albumName.Hidden = len(n.albumName.Segments) == 0
n.Refresh()
}
@@ -167,6 +171,15 @@ func (n *NowPlayingCard) SetImage(cover image.Image) {
n.cover.SetImage(cover, true)
}
func (n *NowPlayingCard) Refresh() {
if n.ShowAlbumYear {
n.albumName.Suffix = n.albumYear
} else {
n.albumName.Suffix = ""
}
n.BaseWidget.Refresh()
}
func (n *NowPlayingCard) showMenu(btnPos fyne.Position) {
if n.menu == nil {
n.ratingMenu = util.NewRatingSubmenu(n.onSetRating)
+5 -1
View File
@@ -457,7 +457,11 @@ func (t *tracklistRowBase) doUpdate(tm *util.TrackListModel, rowNum int) {
t.composer.BuildSegments(tr.ComposerNames, tr.ComposerIDs)
t.genre.BuildSegments(tr.Genres, tr.Genres)
t.dur.Text = util.SecondsToMMSS(tr.Duration.Seconds())
t.year.Text = strconv.Itoa(tr.Year)
if tr.Year != 0 {
t.year.Text = strconv.Itoa(tr.Year)
} else {
t.year.Text = ""
}
t.plays.Text = strconv.Itoa(int(tr.PlayCount))
t.lastPlayed.Text = util.LastPlayedDisplayString(tr.LastPlayed)
t.comment.Text = strings.ReplaceAll(tr.Comment, "\n", " ")