mpris: crossfade album art on session switch

This commit is contained in:
Damocles 2026-04-16 20:55:10 +02:00
parent 1ae953fc73
commit a878067e16

View file

@ -122,7 +122,7 @@ M.BarSection {
panelTitle: "Now Playing" panelTitle: "Now Playing"
contentWidth: 280 contentWidth: 280
// Album art always 1:1 // Album art always 1:1, crossfades on session switch
Item { Item {
width: parent.width width: parent.width
height: width height: width
@ -133,22 +133,71 @@ M.BarSection {
color: M.Theme.base02 color: M.Theme.base02
} }
// Outgoing art snaps to current opacity, then fades out
Image {
id: _artImgPrev
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
asynchronous: true
opacity: 0
NumberAnimation {
id: _prevFadeOut
target: _artImgPrev
property: "opacity"
to: 0
duration: 300
easing.type: Easing.InOutCubic
}
}
// Incoming art fades in once loaded
Image { Image {
id: _artImg id: _artImg
anchors.fill: parent anchors.fill: parent
fillMode: Image.PreserveAspectCrop fillMode: Image.PreserveAspectCrop
visible: _hasArt
asynchronous: true asynchronous: true
source: root._cachedArt opacity: 0
property bool _hasArt: false property bool _hasArt: false
onStatusChanged: if (status === Image.Ready)
_hasArt = true onStatusChanged: {
if (status === Image.Ready && source !== "") {
_hasArt = true;
_artFadeIn.start();
_prevFadeOut.start();
} else if (status === Image.Error) {
_hasArt = false;
}
}
NumberAnimation {
id: _artFadeIn
target: _artImg
property: "opacity"
to: 1
duration: 300
easing.type: Easing.InOutCubic
}
Connections { Connections {
target: root target: root
function on_CachedArtChanged() { function on_CachedArtChanged() {
if (!root._cachedArt) if (!root._cachedArt) {
_artFadeIn.stop();
_prevFadeOut.stop();
_artImg._hasArt = false; _artImg._hasArt = false;
_artImg.opacity = 0;
_artImgPrev.opacity = 0;
_artImg.source = "";
} else if (root._cachedArt !== _artImg.source) {
_prevFadeOut.stop();
_artFadeIn.stop();
_artImgPrev.source = _artImg.source;
_artImgPrev.opacity = _artImg.opacity;
_artImg.opacity = 0;
_artImg.source = root._cachedArt;
}
} }
} }
} }
@ -187,7 +236,7 @@ M.BarSection {
anchors.right: parent.right anchors.right: parent.right
anchors.bottom: parent.bottom anchors.bottom: parent.bottom
height: 40 height: 40
visible: _artImg.visible visible: _artImg._hasArt
gradient: Gradient { gradient: Gradient {
GradientStop { GradientStop {
position: 0 position: 0
@ -206,7 +255,7 @@ M.BarSection {
color: M.Theme.base04 color: M.Theme.base04
font.pixelSize: 28 font.pixelSize: 28
font.family: M.Theme.iconFontFamily font.family: M.Theme.iconFontFamily
visible: _artImg.status !== Image.Ready visible: !_artImg._hasArt
} }
} }