Add media player selector
This commit is contained in:
parent
14274f0aac
commit
97ee13d7b5
2 changed files with 100 additions and 3 deletions
|
|
@ -130,15 +130,24 @@ Singleton {
|
||||||
Timer {
|
Timer {
|
||||||
id: positionTimer
|
id: positionTimer
|
||||||
interval: 1000
|
interval: 1000
|
||||||
running: currentPlayer && currentPlayer.isPlaying && currentPlayer.length > 0
|
running: currentPlayer && currentPlayer.isPlaying && currentPlayer.length > 0 && currentPlayer.playbackState === MprisPlaybackState.Playing
|
||||||
repeat: true
|
repeat: true
|
||||||
onTriggered: {
|
onTriggered: {
|
||||||
if (currentPlayer && currentPlayer.isPlaying) {
|
if (currentPlayer && currentPlayer.isPlaying && currentPlayer.playbackState === MprisPlaybackState.Playing) {
|
||||||
currentPosition = currentPlayer.position
|
currentPosition = currentPlayer.position
|
||||||
|
} else {
|
||||||
|
running = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset position when player state changes
|
||||||
|
onCurrentPlayerChanged: {
|
||||||
|
if (!currentPlayer || !currentPlayer.isPlaying || currentPlayer.playbackState !== MprisPlaybackState.Playing) {
|
||||||
|
currentPosition = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reacts to player list changes
|
// Reacts to player list changes
|
||||||
Connections {
|
Connections {
|
||||||
target: Mpris.players
|
target: Mpris.players
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,89 @@ Rectangle {
|
||||||
spacing: 12
|
spacing: 12
|
||||||
visible: !!MusicManager.currentPlayer
|
visible: !!MusicManager.currentPlayer
|
||||||
|
|
||||||
|
// Player selector
|
||||||
|
ComboBox {
|
||||||
|
id: playerSelector
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: 40
|
||||||
|
visible: MusicManager.getAvailablePlayers().length > 1
|
||||||
|
model: MusicManager.getAvailablePlayers()
|
||||||
|
textRole: "identity"
|
||||||
|
currentIndex: MusicManager.selectedPlayerIndex
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 120
|
||||||
|
implicitHeight: 40
|
||||||
|
color: Theme.surfaceVariant
|
||||||
|
border.color: playerSelector.activeFocus ? Theme.accentPrimary : Theme.outline
|
||||||
|
border.width: 1
|
||||||
|
radius: 16
|
||||||
|
}
|
||||||
|
|
||||||
|
contentItem: Text {
|
||||||
|
leftPadding: 12
|
||||||
|
rightPadding: playerSelector.indicator.width + playerSelector.spacing
|
||||||
|
text: playerSelector.displayText
|
||||||
|
font.pixelSize: 13
|
||||||
|
color: Theme.textPrimary
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
|
||||||
|
indicator: Text {
|
||||||
|
x: playerSelector.width - width - 12
|
||||||
|
y: playerSelector.topPadding + (playerSelector.availableHeight - height) / 2
|
||||||
|
text: "arrow_drop_down"
|
||||||
|
font.family: "Material Symbols Outlined"
|
||||||
|
font.pixelSize: 24
|
||||||
|
color: Theme.textPrimary
|
||||||
|
}
|
||||||
|
|
||||||
|
popup: Popup {
|
||||||
|
y: playerSelector.height
|
||||||
|
width: playerSelector.width
|
||||||
|
implicitHeight: contentItem.implicitHeight
|
||||||
|
padding: 1
|
||||||
|
|
||||||
|
contentItem: ListView {
|
||||||
|
clip: true
|
||||||
|
implicitHeight: contentHeight
|
||||||
|
model: playerSelector.popup.visible ? playerSelector.delegateModel : null
|
||||||
|
currentIndex: playerSelector.highlightedIndex
|
||||||
|
|
||||||
|
ScrollIndicator.vertical: ScrollIndicator {}
|
||||||
|
}
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: Theme.surfaceVariant
|
||||||
|
border.color: Theme.outline
|
||||||
|
border.width: 1
|
||||||
|
radius: 16
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delegate: ItemDelegate {
|
||||||
|
width: playerSelector.width
|
||||||
|
contentItem: Text {
|
||||||
|
text: modelData.identity
|
||||||
|
font.pixelSize: 13
|
||||||
|
color: Theme.textPrimary
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
highlighted: playerSelector.highlightedIndex === index
|
||||||
|
|
||||||
|
background: Rectangle {
|
||||||
|
color: highlighted ? Theme.accentPrimary.toString().replace(/#/, "#1A") : "transparent"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onActivated: {
|
||||||
|
MusicManager.selectedPlayerIndex = index;
|
||||||
|
MusicManager.updateCurrentPlayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Album art and spectrum
|
// Album art and spectrum
|
||||||
RowLayout {
|
RowLayout {
|
||||||
spacing: 12
|
spacing: 12
|
||||||
|
|
@ -183,7 +266,12 @@ Rectangle {
|
||||||
color: Qt.rgba(Theme.textPrimary.r, Theme.textPrimary.g, Theme.textPrimary.b, 0.15)
|
color: Qt.rgba(Theme.textPrimary.r, Theme.textPrimary.g, Theme.textPrimary.b, 0.15)
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|
||||||
property real progressRatio: Math.min(1, MusicManager.trackLength > 0 ? (MusicManager.currentPosition / MusicManager.trackLength) : 0)
|
property real progressRatio: {
|
||||||
|
if (!MusicManager.currentPlayer || !MusicManager.isPlaying || MusicManager.trackLength <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return Math.min(1, MusicManager.currentPosition / MusicManager.trackLength);
|
||||||
|
}
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
id: progressFill
|
id: progressFill
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue