dotfiles/.config/quickshell/MusicController.qml

226 lines
9.3 KiB
QML
Raw Permalink Normal View History

2026-03-09 00:07:31 -04:00
import Quickshell
import Quickshell.Services.Mpris
import QtQuick
PanelWindow {
id: controller
required property var walColors
required property string fontFamily
property color bgColor: (walColors.special && walColors.special.background) ? walColors.special.background : "#1d160d"
property color fgColor: (walColors.special && walColors.special.foreground) ? walColors.special.foreground : "#d8d8d3"
property color accentColor: (walColors.colors && walColors.colors.color1) ? walColors.colors.color1 : "#946F50"
property color accent2Color: (walColors.colors && walColors.colors.color2) ? walColors.colors.color2 : "#BA9351"
property color accent3Color: (walColors.colors && walColors.colors.color3) ? walColors.colors.color3 : "#BA9351"
property color accent4Color: (walColors.colors && walColors.colors.color4) ? walColors.colors.color4 : "#BA9351"
property color accent5Color: (walColors.colors && walColors.colors.color5) ? walColors.colors.color5 : "#BA9351"
anchors {
bottom: true
// right: true
}
color: "transparent"
exclusionMode: ExclusionMode.Ignore
implicitHeight: 34
implicitWidth: mainGroup.width + 8
property var player: {
let players = Mpris.players.values
if (!players || players.length === 0) return null
for (let i = 0; i < players.length; i++) {
if (players[i].playbackState === MprisPlaybackState.Playing)
return players[i]
}
return players[0]
}
property bool hovered: hoverArea.containsMouse
Item {
anchors.fill: parent
anchors.margins: 2
MouseArea {
id: hoverArea
anchors.fill: parent
hoverEnabled: true
acceptedButtons: Qt.NoButton
}
Rectangle {
id: mainGroup
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
height: 30
width: infoRow.width + 8
clip: true
color: controller.bgColor
border.color: controller.accentColor
border.width: 2
radius: 100
Behavior on width {
NumberAnimation { duration: 200; easing.type: Easing.InOutQuad }
}
// Track info (default view)
Row {
id: infoRow
anchors.right: parent.right
anchors.rightMargin: 4
anchors.verticalCenter: parent.verticalCenter
spacing: 5
visible: !controller.hovered
BarPill {
id: trackInfoPill
fontFamily: controller.fontFamily
topLeftRadius: 100
bottomLeftRadius: 100
label: {
if (!controller.player) return "No Player"
let artist = controller.player.trackArtist || ""
let title = controller.player.trackTitle || ""
if (artist && title) return artist + " \u2022 " + title
if (title) return title
return controller.player.identity || "Unknown"
}
pillColor: controller.accent2Color
textColor: controller.bgColor
}
BarPill {
fontFamily: controller.fontFamily
label: {
if (!controller.player) return "\uf04c"
if (controller.player.playbackState === MprisPlaybackState.Playing) return "\uf04b"
if (controller.player.playbackState === MprisPlaybackState.Paused) return "\uf04c"
return "\uf04d"
}
pillColor: controller.accentColor
textColor: controller.bgColor
topLeftRadius: 4
bottomLeftRadius: 4
topRightRadius: 100
bottomRightRadius: 100
}
}
// Controls (hover view)
Row {
id: controlsRow
anchors.right: parent.right
anchors.rightMargin: 4
anchors.verticalCenter: parent.verticalCenter
spacing: 5
visible: controller.hovered
property bool hasShuffle: controller.player && controller.player.shuffleSupported
property bool hasLoop: controller.player && controller.player.loopSupported
property int visibleCount: 3 + (hasShuffle ? 1 : 0) + (hasLoop ? 1 : 0)
property real totalSpacing: (visibleCount - 1) * spacing
property real pillWidth: visibleCount > 0 ? (infoRow.width - totalSpacing) / visibleCount : 40
BarPill {
fontFamily: controller.fontFamily
label: "\uf048"
pillColor: controller.accent5Color
textColor: controller.bgColor
width: controlsRow.pillWidth
topLeftRadius: 100
bottomLeftRadius: 100
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: if (controller.player && controller.player.canGoPrevious) controller.player.previous()
}
}
BarPill {
fontFamily: controller.fontFamily
label: {
if (!controller.player) return "\uf04b"
return controller.player.playbackState === MprisPlaybackState.Playing ? "\uf04c" : "\uf04b"
}
pillColor: controller.accent3Color
textColor: controller.bgColor
width: controlsRow.pillWidth
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: if (controller.player && controller.player.canTogglePlaying) controller.player.togglePlaying()
}
}
BarPill {
id: nextPill
fontFamily: controller.fontFamily
label: "\uf051"
pillColor: controller.accent4Color
textColor: controller.bgColor
width: controlsRow.pillWidth
topRightRadius: (!controlsRow.hasShuffle && !controlsRow.hasLoop) ? 100 : 4
bottomRightRadius: (!controlsRow.hasShuffle && !controlsRow.hasLoop) ? 100 : 4
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: if (controller.player && controller.player.canGoNext) controller.player.next()
}
}
BarPill {
id: shufflePill
fontFamily: controller.fontFamily
label: "\uf074"
pillColor: controller.player && controller.player.shuffle ? controller.accent2Color : controller.accentColor
textColor: controller.bgColor
width: controlsRow.pillWidth
visible: controlsRow.hasShuffle
topRightRadius: !controlsRow.hasLoop ? 100 : 4
bottomRightRadius: !controlsRow.hasLoop ? 100 : 4
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: if (controller.player) controller.player.shuffle = !controller.player.shuffle
}
}
BarPill {
fontFamily: controller.fontFamily
label: {
if (!controller.player) return "\uf01e"
if (controller.player.loopState === MprisLoopState.Track) return "\uf021"
return "\uf01e"
}
pillColor: controller.player && controller.player.loopState !== MprisLoopState.None ? controller.accent2Color : controller.accentColor
textColor: controller.bgColor
width: controlsRow.pillWidth
visible: controlsRow.hasLoop
topRightRadius: 100
bottomRightRadius: 100
MouseArea {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
if (!controller.player) return
if (controller.player.loopState === MprisLoopState.None)
controller.player.loopState = MprisLoopState.Playlist
else if (controller.player.loopState === MprisLoopState.Playlist)
controller.player.loopState = MprisLoopState.Track
else
controller.player.loopState = MprisLoopState.None
}
}
}
}
}
}
}