feat: display multiple mpris players
This commit is contained in:
parent
5e5f265de6
commit
0ce0c58162
1 changed files with 125 additions and 105 deletions
|
@ -1,3 +1,5 @@
|
|||
pragma ComponentBehavior: Bound
|
||||
|
||||
import QtQuick.Effects
|
||||
import QtQuick.Controls
|
||||
import QtQuick.Layouts
|
||||
|
@ -11,123 +13,141 @@ BRectangle {
|
|||
id: mprisSmall
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: 200
|
||||
|
||||
radius: 15
|
||||
clip: true
|
||||
border.color: "transparent"
|
||||
visible: list.count
|
||||
|
||||
visible: Player.current ?? false
|
||||
|
||||
BlurredImage {
|
||||
source: Player.current?.trackArtUrl ?? ""
|
||||
ListView {
|
||||
id: list
|
||||
anchors.fill: parent
|
||||
radius: parent.radius
|
||||
}
|
||||
model: Mpris.players
|
||||
orientation: Qt.Horizontal
|
||||
snapMode: ListView.SnapOneItem
|
||||
spacing: 10
|
||||
delegate: Item {
|
||||
id: card
|
||||
required property var modelData
|
||||
property MprisPlayer player: modelData
|
||||
width: mprisSmall.width
|
||||
height: mprisSmall.height
|
||||
|
||||
RowLayout {
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
BRoundedImage {
|
||||
id: im
|
||||
color: "transparent"
|
||||
visible: false
|
||||
source: Player.current?.trackArtUrl ?? ""
|
||||
radius: 15
|
||||
}
|
||||
|
||||
MultiEffect {
|
||||
id: effect
|
||||
source: im
|
||||
autoPaddingEnabled: true
|
||||
shadowBlur: 1.0
|
||||
shadowColor: 'black'
|
||||
shadowEnabled: true
|
||||
Layout.margins: 20
|
||||
Layout.preferredWidth: parent.height - (Layout.margins * 2)
|
||||
Layout.preferredHeight: parent.height - (Layout.margins * 2)
|
||||
Layout.maximumWidth: {
|
||||
const mWidth = parent.width - (Layout.margins * 2);
|
||||
return mWidth > 0 ? mWidth : 0;
|
||||
}
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
Layout.maximumWidth: parent.width / 2
|
||||
Layout.fillWidth: true
|
||||
clip: true
|
||||
|
||||
Text {
|
||||
text: Player.current?.trackTitle ?? "Unknown Track"
|
||||
color: "white"
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.maximumWidth: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
text: Player.current?.trackAlbum ?? "Unknown Album"
|
||||
color: "white"
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.maximumWidth: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
text: Player.current?.trackAlbumArtist ?? "Unknown Artist"
|
||||
color: "white"
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.maximumWidth: parent.width
|
||||
elide: Text.ElideRight
|
||||
BlurredImage {
|
||||
source: card.player?.trackArtUrl ?? ""
|
||||
anchors.fill: parent
|
||||
radius: 15
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
BIconButton {
|
||||
source: Quickshell.iconPath("media-seek-backward")
|
||||
onClicked: Player.current.previous()
|
||||
size: 20
|
||||
}
|
||||
BIconButton {
|
||||
source: Quickshell.iconPath(Player.isPlaying ? "media-playback-pause" : "media-playback-start")
|
||||
onClicked: Player.current.togglePlaying()
|
||||
size: 20
|
||||
anchors.fill: parent
|
||||
clip: true
|
||||
BRoundedImage {
|
||||
id: im
|
||||
color: "transparent"
|
||||
visible: false
|
||||
source: card.player?.trackArtUrl ?? ""
|
||||
radius: 15
|
||||
}
|
||||
|
||||
BIconButton {
|
||||
source: Quickshell.iconPath("media-seek-forward")
|
||||
onClicked: Player.current.next()
|
||||
size: 20
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: slider
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 10
|
||||
Layout.minimumHeight: 3
|
||||
from: 0
|
||||
to: Player.current?.length ?? 0
|
||||
value: Player.current?.position ?? 0
|
||||
enabled: (Player.current?.canSeek && Player.current?.positionSupported) ?? false
|
||||
|
||||
onMoved: {
|
||||
if (Player.current)
|
||||
Player.current.position = value;
|
||||
MultiEffect {
|
||||
id: effect
|
||||
source: im
|
||||
autoPaddingEnabled: true
|
||||
shadowBlur: 1.0
|
||||
shadowColor: 'black'
|
||||
shadowEnabled: true
|
||||
Layout.margins: 20
|
||||
Layout.preferredWidth: parent.height - (Layout.margins * 2)
|
||||
Layout.preferredHeight: parent.height - (Layout.margins * 2)
|
||||
Layout.maximumWidth: {
|
||||
const mWidth = parent.width - (Layout.margins * 2);
|
||||
return mWidth > 0 ? mWidth : 0;
|
||||
}
|
||||
Layout.fillHeight: true
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
const con = () => mprisSmall.player?.positionChanged.connect(() => {
|
||||
slider.value = Player.current?.position;
|
||||
});
|
||||
con();
|
||||
Player.currentChanged.connect(() => {
|
||||
con();
|
||||
});
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.maximumWidth: parent.width / 2
|
||||
Layout.fillWidth: true
|
||||
clip: true
|
||||
|
||||
FrameAnimation {
|
||||
// only emit the signal when the position is actually changing.
|
||||
running: Player.current?.playbackState == MprisPlaybackState.Playing
|
||||
// emit the positionChanged signal every frame.
|
||||
onTriggered: Player.current?.positionChanged()
|
||||
Text {
|
||||
text: card.player?.trackTitle ?? "Unknown Track"
|
||||
color: "white"
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.maximumWidth: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
text: card.player?.trackAlbum ?? "Unknown Album"
|
||||
color: "white"
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.maximumWidth: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
Text {
|
||||
text: card.player?.trackAlbumArtist ?? "Unknown Artist"
|
||||
color: "white"
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
Layout.maximumWidth: parent.width
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
BIconButton {
|
||||
source: Quickshell.iconPath("media-seek-backward")
|
||||
onClicked: card.player?.previous()
|
||||
size: 20
|
||||
}
|
||||
BIconButton {
|
||||
source: Quickshell.iconPath(card.player.playbackState === MprisPlaybackState.Playing ? "media-playback-pause" : "media-playback-start")
|
||||
onClicked: card.player?.togglePlaying()
|
||||
size: 20
|
||||
}
|
||||
|
||||
BIconButton {
|
||||
source: Quickshell.iconPath("media-seek-forward")
|
||||
onClicked: card.player?.next()
|
||||
size: 20
|
||||
}
|
||||
}
|
||||
|
||||
Slider {
|
||||
id: slider
|
||||
Layout.fillWidth: true
|
||||
Layout.minimumWidth: 10
|
||||
Layout.minimumHeight: 3
|
||||
from: 0
|
||||
to: card.player?.length ?? 0
|
||||
value: card.player?.position ?? 0
|
||||
enabled: (card.player?.canSeek && card.player?.positionSupported) ?? false
|
||||
|
||||
onMoved: {
|
||||
if (card.player)
|
||||
card.player.position = value;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
const con = () => card.player?.positionChanged.connect(() => {
|
||||
slider.value = card.player?.position;
|
||||
});
|
||||
con();
|
||||
Player.currentChanged.connect(() => {
|
||||
con();
|
||||
});
|
||||
}
|
||||
|
||||
FrameAnimation {
|
||||
// only emit the signal when the position is actually changing.
|
||||
running: card.player?.playbackState == MprisPlaybackState.Playing
|
||||
// emit the positionChanged signal every frame.
|
||||
onTriggered: card.player?.positionChanged()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue