Files
qbz/crates/qbz-qt/qml/immersive/ImmersiveTrackMeta.qml
T
vicrodh a2a99a72cc perf(qt): bring the immersive onto the pulse (83% -> 25% GPU)
- AlbumReactivePanel: drop the eight 100ms Behaviors on 30 Hz data (a
  retriggered Behavior animates at display rate and every animation
  frame is a full-window present), and read the settle — not the
  publishing bridge list — in the energy formulas (the .length guard
  re-evaluated the visual bindings on every FFT publish).
- LyricsSyncEngine: the fast cadence rides the pulse; the 250 ms idle
  re-check keeps its own timer.
- EqualizerBars: the phase accumulates on the pulse and the 'active'
  gate is host-provided (invisible subtrees still dirty the window).

Measured on the owner's machine, immersive reactive panel open:
132 -> ~33 presents/s, 83% -> ~25% GPU.

km
2026-08-13 13:02:10 -06:00

111 lines
3.8 KiB
QML

// ImmersiveTrackMeta — the homologated immersive track-info block (§6.7 of
// the 2026-08-02 immersive-port contract), port of ImmersiveTrackInfo in
// crates/qbz-ui/ui/immersive/ImmersiveTrackInfo.slint:78-143.
//
// HOMOLOGATED look/spacing across AlbumReactive / Static / Coverflow (and the
// SPLIT left column, §5.6): spacing 6px, the "Now Playing" indicator padded
// 8px below, the quality badge padded 12px above, fonts 28/18/14.
//
// Every row reads QbzPlayer.np* (the Slint block reads NowPlayingState):
// "Now Playing" + EqualizerBars — VISIBLE ONLY WHILE npPlaying (:85,:100)
// title 28px/700 elide center (:106-113)
// artist 18px #ffffffb3 elide center (:116-122)
// album 14px italic #ffffff80, only when non-empty (:125-132)
// QualityBadgeFull (tier + detail), self-hides when tier == "" (:135-141)
//
// The Slint root is a VerticalLayout with alignment: center — the Qt twin is
// a Column whose width the MOUNT sets (every B3 mount passes the panel width)
// and whose rows center themselves horizontally.
import QtQuick
import com.blitzfc.qbz
import "../controls"
Column {
id: root
/// Equalizer tint + "Now Playing" label color (Slint equalizer-tint).
property color equalizerTint: "#7c3aed"
spacing: 6
// "Now Playing" indicator: equalizer bars + label, shown only while
// playing (:85-103). The Slint HorizontalLayout carries padding-bottom 8
// — the wrapper Item's +8 height is that padding.
Item {
visible: QbzPlayer.npPlaying
width: parent.width
height: visible ? npRow.implicitHeight + 8 : 0
Row {
id: npRow
anchors.horizontalCenter: parent.horizontalCenter
spacing: 8
height: 14
EqualizerBars {
tint: root.equalizerTint
// The gate lives at the mount (EqualizerBars.qml explains
// why): this host sits inside the always-mounted ImmersiveView.
active: QbzImmersive.open
anchors.verticalCenter: parent.verticalCenter
}
Text {
text: QbzSession.tr("Now Playing", QbzSession.trRev)
color: root.equalizerTint
font.pixelSize: 12
font.weight: Font.DemiBold
font.letterSpacing: 0.5
anchors.verticalCenter: parent.verticalCenter
}
}
}
// Track title (:106-113).
Text {
width: parent.width
text: QbzPlayer.npTitle
color: "#ffffff"
font.pixelSize: 28
font.weight: Font.Bold
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
}
// Artist (:116-122). Slint #ffffffb3 (RRGGBBAA) -> #b3ffffff.
Text {
width: parent.width
text: QbzPlayer.npArtist
color: "#b3ffffff"
font.pixelSize: 18
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
}
// Album (italic, dimmer), only when present (:125-132).
Text {
visible: QbzPlayer.npAlbum !== ""
width: parent.width
text: QbzPlayer.npAlbum
color: "#80ffffff"
font.pixelSize: 14
font.italic: true
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
}
// Quality badge, centered, padding-top 12 (:135-141). Self-hides when
// tier == "" (QualityBadgeFull's own gate) — the wrapper collapses with
// it so the 12px pad vanishes too.
Item {
visible: QbzPlayer.npQualityTier !== ""
width: parent.width
height: visible ? badge.implicitHeight + 12 : 0
QualityBadgeFull {
id: badge
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
tier: QbzPlayer.npQualityTier
detail: QbzPlayer.npQualityDetail
}
}
}