Populate richer DIDL-Lite metadata for DLNA cast (#934)

Extend MediaItemMetadata with TrackNumber, Size, BitRate, SampleRate,
BitDepth, and ChannelCount (all already present on Track) and populate
them in Track.Metadata(). Thread them through dlnaplayer.go into the
avtransport.MediaItem so the renderer's DIDL-Lite includes upnp:artist,
upnp:album, upnp:originalTrackNumber, plus <res> attributes for
duration, size, bitrate, sampleFrequency, bitsPerSample, and
nrAudioChannels. The previously dropped Duration field is now
populated too.

For cover art, add a CoverArtPathFn callback on PlaybackManager wired
to ImageManager.GetCoverArtPath in app.go. The DLNA player invokes it
when a track is queued, registers the cached cover-thumbnail path
with the local proxy, and emits the resulting proxy URL as
upnp:albumArtURI so the renderer can display album art alongside the
audio.

Bumps go-upnpcast to pull in the MediaItem fields and DIDL-Lite
emission added in supersonic-app/go-upnpcast#4.
This commit is contained in:
Andrew G. Dunn
2026-06-01 16:39:48 -07:00
committed by GitHub
parent 3205bb33f2
commit 6b6701e973
6 changed files with 101 additions and 42 deletions
+10 -3
View File
@@ -31,6 +31,12 @@ type PlaybackManager struct {
appCfg *AppConfig
cfg *PlaybackConfig
// CoverArtPathFn returns a local filesystem path to the cached cover
// art image for the given CoverArtID. Used by DLNA cast so the
// renderer can fetch album art via the local proxy. Set externally
// (typically wired to ImageManager.GetCoverArtPath).
CoverArtPathFn func(coverArtID string) (string, error)
localPlayer player.BasePlayer
remotePlayersLock sync.Mutex
remotePlayers []RemotePlaybackDevice
@@ -247,17 +253,18 @@ func (p *PlaybackManager) ScanRemotePlayers(ctx context.Context, fastScan bool)
func (p *PlaybackManager) scanRemotePlayers(ctx context.Context, waitSec int) {
devices, _ := device.SearchMediaRenderers(ctx, waitSec, services.AVTransport, services.RenderingControl)
coverArtPathFn := p.CoverArtPathFn
var discovered []RemotePlaybackDevice
for _, d := range devices {
p := RemotePlaybackDevice{
rp := RemotePlaybackDevice{
Name: d.FriendlyName,
URL: d.URL,
Protocol: "DLNA",
new: func() (player.BasePlayer, error) {
return dlna.NewDLNAPlayer(d)
return dlna.NewDLNAPlayer(d, coverArtPathFn)
},
}
discovered = append(discovered, p)
discovered = append(discovered, rp)
}
p.remotePlayersLock.Lock()