142 lines
4.5 KiB
QML
142 lines
4.5 KiB
QML
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
import Quickshell.Services.Mpris
|
|
import "." as M
|
|
import "../services" as S
|
|
import "../applets" as C
|
|
|
|
M.BarSection {
|
|
id: root
|
|
spacing: S.Theme.moduleSpacing
|
|
opacity: S.Modules.mpris.enable && player !== null ? 1 : 0
|
|
visible: opacity > 0
|
|
tooltip: ""
|
|
|
|
property int _playerIdx: 0
|
|
readonly property var _players: (Mpris.players.values ?? []).filter(p => p.trackTitle || p.playbackState === MprisPlaybackState.Playing || p.playbackState === MprisPlaybackState.Paused)
|
|
readonly property MprisPlayer player: _players[_playerIdx] ?? _players[0] ?? null
|
|
readonly property bool playing: player?.playbackState === MprisPlaybackState.Playing
|
|
|
|
// Reset index if current player disappears
|
|
on_PlayersChanged: if (_playerIdx >= _players.length)
|
|
_playerIdx = 0
|
|
property string _cachedArt: ""
|
|
property string _artTrack: ""
|
|
|
|
// Cache art URL at root level so it's captured even when panel is hidden
|
|
readonly property string _artUrl: player?.trackArtUrl ?? ""
|
|
readonly property string _currentTrack: player?.trackTitle ?? ""
|
|
on_ArtUrlChanged: if (_artUrl)
|
|
_cachedArt = _artUrl
|
|
on_CurrentTrackChanged: if (_currentTrack !== _artTrack) {
|
|
_artTrack = _currentTrack;
|
|
_cachedArt = _artUrl || "";
|
|
}
|
|
|
|
// Preload art while panel is hidden
|
|
Image {
|
|
visible: false
|
|
source: root._cachedArt
|
|
asynchronous: true
|
|
}
|
|
|
|
// Cava visualizer - 16 bars, raw output mode
|
|
property var _cavaBars: Array(16).fill(0)
|
|
property bool _cavaActive: false
|
|
|
|
on_ShowPanelChanged: {
|
|
if (_showPanel) {
|
|
_cavaKillTimer.stop();
|
|
_cavaActive = true;
|
|
} else {
|
|
_cavaKillTimer.restart();
|
|
}
|
|
}
|
|
|
|
Timer {
|
|
id: _cavaKillTimer
|
|
interval: 30000
|
|
onTriggered: root._cavaActive = false
|
|
}
|
|
|
|
Process {
|
|
id: cavaProc
|
|
running: root.playing && root._cavaActive
|
|
command: ["sh", "-c", "cfg=$(mktemp /tmp/nova-cava-XXXXXX.conf);" + "cat > \"$cfg\" << 'CAVAEOF'\n" + "[general]\nbars=16\nframerate=30\n[output]\nmethod=raw\nraw_target=/dev/stdout\ndata_format=ascii\nascii_max_range=100\n" + "CAVAEOF\n" + "trap 'rm -f \"$cfg\"' EXIT;" + "exec cava -p \"$cfg\""]
|
|
stdout: SplitParser {
|
|
splitMarker: "\n"
|
|
onRead: line => {
|
|
const vals = line.split(";").filter(s => s).map(Number);
|
|
if (vals.length >= 16)
|
|
root._cavaBars = vals.map(v => v / 100);
|
|
}
|
|
}
|
|
}
|
|
|
|
required property var bar
|
|
|
|
property bool _pinned: false
|
|
readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered
|
|
readonly property bool _showPanel: _anyHover || _pinned
|
|
|
|
on_AnyHoverChanged: {
|
|
if (_anyHover)
|
|
_unpinTimer.stop();
|
|
else if (_pinned)
|
|
_unpinTimer.start();
|
|
}
|
|
|
|
Timer {
|
|
id: _unpinTimer
|
|
interval: 500
|
|
onTriggered: root._pinned = false
|
|
}
|
|
|
|
M.BarIcon {
|
|
icon: root.playing ? "\uF04B" : (root.player?.playbackState === MprisPlaybackState.Paused ? "\uDB80\uDFE4" : "\uDB81\uDCDB")
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: root._pinned = !root._pinned
|
|
}
|
|
}
|
|
M.BarLabel {
|
|
label: root.player?.trackTitle || root.player?.identity || ""
|
|
elide: Text.ElideRight
|
|
width: Math.min(implicitWidth, 200)
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
MouseArea {
|
|
anchors.fill: parent
|
|
cursorShape: Qt.PointingHandCursor
|
|
onClicked: root._pinned = !root._pinned
|
|
}
|
|
}
|
|
|
|
M.HoverPanel {
|
|
id: hoverPanel
|
|
showPanel: root._showPanel
|
|
screen: QsWindow.window?.screen ?? null
|
|
anchorItem: root
|
|
accentColor: root.accentColor
|
|
panelNamespace: "nova-mpris"
|
|
panelTitle: "Now Playing"
|
|
contentWidth: 280
|
|
|
|
C.MprisApplet {
|
|
width: hoverPanel.contentWidth
|
|
player: root.player
|
|
players: root._players
|
|
playing: root.playing
|
|
accentColor: root.accentColor
|
|
cachedArt: root._cachedArt
|
|
cavaBars: root._cavaBars
|
|
playerIdx: root._playerIdx
|
|
onPlayerSwitched: idx => {
|
|
root._playerIdx = idx;
|
|
hoverPanel.keepOpen(400);
|
|
}
|
|
}
|
|
}
|
|
}
|