Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Plasma
Plasma Mobile
Commits
bbe9bbf9
Commit
bbe9bbf9
authored
Apr 08, 2022
by
Devin Lin
🎨
Browse files
widgets/mediaplayer: Add support for controlling multiple media sources
Implement
#135
parent
79c4dac7
Pipeline
#161581
passed with stages
in 1 minute and 21 seconds
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
components/mobileshell/qml/widgets/mediacontrols/MediaControlsSource.qml
View file @
bbe9bbf9
...
...
@@ -12,25 +12,52 @@ import org.kde.plasma.core 2.0 as PlasmaCore
PlasmaCore.DataSource
{
id
:
mpris2Source
readonly
property
string
source
:
"
@multiplex
"
readonly
property
var
playerData
:
data
[
source
]
readonly
property
bool
hasPlayer
:
sources
.
length
>
1
&&
!!
playerData
readonly
property
string
identity
:
hasPlayer
?
playerData
.
Identity
:
""
readonly
property
bool
playing
:
hasPlayer
&&
playerData
.
PlaybackStatus
===
"
Playing
"
readonly
property
bool
canControl
:
hasPlayer
&&
playerData
.
CanControl
readonly
property
bool
canGoBack
:
hasPlayer
&&
playerData
.
CanGoPrevious
readonly
property
bool
canGoNext
:
hasPlayer
&&
playerData
.
CanGoNext
engine
:
"
mpris2
"
connectedSources
:
sources
readonly
property
string
multiplexSource
:
"
@multiplex
"
property
var
mprisSourcesModel
:
[]
readonly
property
bool
hasPlayer
:
sources
.
length
>
1
readonly
property
var
currentMetadata
:
hasPlayer
?
playerData
.
Metadata
:
({})
function
startOperation
(
src
,
op
)
{
var
service
=
serviceForSource
(
src
)
var
operation
=
service
.
operationDescription
(
op
)
return
service
.
startOperationCall
(
operation
)
}
readonly
property
string
track
:
{
const
xesamTitle
=
currentMetadata
[
"
xesam:title
"
]
function
goPrevious
(
source
)
{
startOperation
(
source
,
"
Previous
"
);
}
function
goNext
(
source
)
{
startOperation
(
source
,
"
Next
"
);
}
function
playPause
(
source
)
{
startOperation
(
source
,
"
PlayPause
"
);
}
function
isPlaying
(
source
)
{
return
data
[
source
]
?
data
[
source
].
PlaybackStatus
===
"
Playing
"
:
false
;
}
function
canControl
(
source
)
{
return
data
[
source
]
?
data
[
source
].
CanControl
:
false
;
}
function
canGoBack
(
source
)
{
return
data
[
source
]
?
data
[
source
].
CanGoPrevious
:
false
;
}
function
canGoNext
(
source
)
{
return
data
[
source
]
?
data
[
source
].
CanGoNext
:
false
;
}
function
track
(
source
)
{
if
(
!
data
[
source
])
{
return
""
;
}
const
xesamTitle
=
data
[
source
].
Metadata
[
"
xesam:title
"
]
if
(
xesamTitle
)
{
return
xesamTitle
}
// if no track title is given, print out the file name
const
xesamUrl
=
current
Metadata
[
"
xesam:url
"
]
?
current
Metadata
[
"
xesam:url
"
].
toString
()
:
""
const
xesamUrl
=
data
[
source
].
Metadata
[
"
xesam:url
"
]
?
data
[
source
].
Metadata
[
"
xesam:url
"
].
toString
()
:
""
if
(
!
xesamUrl
)
{
return
""
}
...
...
@@ -41,25 +68,43 @@ PlasmaCore.DataSource {
const
lastUrlPart
=
xesamUrl
.
substring
(
lastSlashPos
+
1
)
return
decodeURIComponent
(
lastUrlPart
)
}
readonly
property
string
artist
:
currentMetadata
[
"
xesam:artist
"
]
||
""
readonly
property
string
albumArt
:
currentMetadata
[
"
mpris:artUrl
"
]
||
""
engine
:
"
mpris2
"
connectedSources
:
[
source
]
function
startOperation
(
op
)
{
var
service
=
serviceForSource
(
source
)
var
operation
=
service
.
operationDescription
(
op
)
return
service
.
startOperationCall
(
operation
)
function
artist
(
source
)
{
return
data
[
source
]
?
data
[
source
].
Metadata
[
"
xesam:artist
"
]
||
""
:
""
;
}
function
goPrevious
()
{
startOperation
(
"
Previous
"
);
function
albumArt
(
source
)
{
return
data
[
source
]
?
data
[
source
].
Metadata
[
"
mpris:artUrl
"
]
||
""
:
""
;
}
function
goNext
()
{
startOperation
(
"
Next
"
);
function
updateMprisSourcesModel
()
{
let
model
=
[];
let
sources
=
mpris2Source
.
sources
;
for
(
let
i
=
0
;
i
<
sources
.
length
;
++
i
)
{
let
source
=
sources
[
i
];
if
(
source
===
mpris2Source
.
multiplexSource
)
{
continue
;
}
const
playerData
=
mpris2Source
.
data
[
source
];
// source data is removed before its name is removed from the list
if
(
!
playerData
)
{
continue
;
}
model
.
push
({
'
application
'
:
playerData
[
"
Identity
"
],
'
source
'
:
source
,
});
}
mprisSourcesModel
=
model
;
}
function
playPause
(
source
)
{
startOperation
(
"
PlayPause
"
);
Component.onCompleted
:
{
mpris2Source
.
serviceForSource
(
"
@multiplex
"
).
enableGlobalShortcuts
()
updateMprisSourcesModel
()
}
onSourceAdded
:
updateMprisSourcesModel
()
onSourceRemoved
:
updateMprisSourcesModel
();
}
components/mobileshell/qml/widgets/mediacontrols/MediaControlsWidget.qml
View file @
bbe9bbf9
...
...
@@ -17,109 +17,155 @@ import org.kde.plasma.extras 2.0 as PlasmaExtras
import
"
../../components
"
as
Components
Components.BaseItem
{
/**
* Embeddable component that provides MPRIS control.
*/
Item
{
id
:
root
visible
:
mpris2Source
.
hasPlayer
padding
:
visible
?
Kirigami
.
Units
.
largeSpacing
+
Kirigami
.
Units
.
smallSpacing
:
0
implicitHeight
:
visible
?
bottomPadding
+
topPadding
+
PlasmaCore
.
Units
.
gridUnit
*
2
+
PlasmaCore
.
Units
.
smallSpacing
:
0
background
:
BlurredBackground
{
imageSource
:
mpris2Source
.
albumArt
readonly
property
real
padding
:
Kirigami
.
Units
.
largeSpacing
+
Kirigami
.
Units
.
smallSpacing
readonly
property
real
contentHeight
:
PlasmaCore
.
Units
.
gridUnit
*
2
+
PlasmaCore
.
Units
.
smallSpacing
implicitHeight
:
visible
?
padding
*
2
+
contentHeight
:
0
MediaControlsSource
{
id
:
mpris2Source
}
contentItem
:
PlasmaCore.ColorScope
{
colorGroup
:
PlasmaCore
.
Theme
.
ComplementaryColorGroup
width
:
root
.
width
-
root
.
leftPadding
-
root
.
rightPadding
// page indicator
RowLayout
{
z
:
1
visible
:
view
.
count
>
1
spacing
:
Kirigami
.
Units
.
smallSpacing
anchors.bottomMargin
:
Kirigami
.
Units
.
smallSpacing
*
2
anchors.bottom
:
view
.
bottom
anchors.horizontalCenter
:
parent
.
horizontalCenter
MediaControlsSource
{
id
:
mpris2Source
Repeater
{
model
:
view
.
count
delegate
:
Rectangle
{
width
:
Kirigami
.
Units
.
smallSpacing
height
:
Kirigami
.
Units
.
smallSpacing
radius
:
width
/
2
color
:
Qt
.
rgba
(
255
,
255
,
255
,
view
.
currentIndex
==
model
.
index
?
1
:
0.5
)
}
}
}
// list of app media widgets
QQC2.SwipeView
{
id
:
view
clip
:
true
RowLayout
{
id
:
controlsRow
width
:
parent
.
width
height
:
parent
.
height
spacing
:
0
anchors.fill
:
parent
Repeater
{
model
:
mpris2Source
.
mprisSourcesModel
delegate
:
Components.BaseItem
{
id
:
playerItem
property
string
source
:
modelData
.
source
padding
:
root
.
padding
implicitHeight
:
root
.
contentHeight
+
root
.
padding
*
2
implicitWidth
:
root
.
width
background
:
BlurredBackground
{
imageSource
:
mpris2Source
.
albumArt
(
playerItem
.
source
)
}
contentItem
:
PlasmaCore.ColorScope
{
colorGroup
:
PlasmaCore
.
Theme
.
ComplementaryColorGroup
width
:
playerItem
.
width
-
playerItem
.
leftPadding
-
playerItem
.
rightPadding
RowLayout
{
id
:
controlsRow
width
:
parent
.
width
height
:
parent
.
height
spacing
:
0
enabled
:
mpris2Source
.
canControl
enabled
:
mpris2Source
.
canControl
(
playerItem
.
source
)
Image
{
id
:
albumArt
Layout.preferredWidth
:
height
Layout.fillHeight
:
true
asynchronous
:
true
fillMode
:
Image
.
PreserveAspectFit
source
:
mpris2Source
.
albumArt
sourceSize.height
:
height
visible
:
status
===
Image
.
Loading
||
status
===
Image
.
Ready
}
Image
{
id
:
albumArt
Layout.preferredWidth
:
height
Layout.fillHeight
:
true
asynchronous
:
true
fillMode
:
Image
.
PreserveAspectFit
source
:
mpris2Source
.
albumArt
(
playerItem
.
source
)
sourceSize.height
:
height
visible
:
status
===
Image
.
Loading
||
status
===
Image
.
Ready
}
ColumnLayout
{
Layout.leftMargin
:
albumArt
.
visible
?
Kirigami
.
Units
.
largeSpacing
:
0
Layout.fillWidth
:
true
spacing
:
Kirigami
.
Units
.
smallSpacing
ColumnLayout
{
Layout.leftMargin
:
albumArt
.
visible
?
Kirigami
.
Units
.
largeSpacing
:
0
Layout.fillWidth
:
true
spacing
:
Kirigami
.
Units
.
smallSpacing
QQC2.Label
{
Layout.fillWidth
:
true
wrapMode
:
Text
.
NoWrap
elide
:
Text
.
ElideRight
text
:
mpris2Source
.
track
||
i18n
(
"
No media playing
"
)
textFormat
:
Text
.
PlainText
font.pointSize
:
PlasmaCore
.
Theme
.
defaultFont
.
pointSize
maximumLineCount
:
1
color
:
"
white
"
}
QQC2.Label
{
Layout.fillWidth
:
true
wrapMode
:
Text
.
NoWrap
elide
:
Text
.
ElideRight
text
:
mpris2Source
.
track
(
playerItem
.
source
)
||
i18n
(
"
No media playing
"
)
textFormat
:
Text
.
PlainText
font.pointSize
:
PlasmaCore
.
Theme
.
defaultFont
.
pointSize
maximumLineCount
:
1
color
:
"
white
"
}
QQC2.Label
{
Layout.fillWidth
:
true
wrapMode
:
Text
.
NoWrap
elide
:
Text
.
ElideRight
// if no artist is given, show player name instead
text
:
mpris2Source
.
artist
||
mpris2Source
.
identity
||
""
textFormat
:
Text
.
PlainText
font.pointSize
:
PlasmaCore
.
Theme
.
smallestFont
.
pointSize
maximumLineCount
:
1
opacity
:
0.9
color
:
"
white
"
}
}
QQC2.Label
{
Layout.fillWidth
:
true
wrapMode
:
Text
.
NoWrap
elide
:
Text
.
ElideRight
// if no artist is given, show player name instead
text
:
mpris2Source
.
artist
(
playerItem
.
source
)
||
modelData
.
application
||
""
textFormat
:
Text
.
PlainText
font.pointSize
:
PlasmaCore
.
Theme
.
smallestFont
.
pointSize
maximumLineCount
:
1
opacity
:
0.9
color
:
"
white
"
}
}
PlasmaComponents3.ToolButton
{
Layout.fillHeight
:
true
Layout.preferredWidth
:
height
enabled
:
mpris2Source
.
canGoBack
icon.name
:
LayoutMirroring
.
enabled
?
"
media-skip-forward
"
:
"
media-skip-backward
"
icon.width
:
PlasmaCore
.
Units
.
iconSizes
.
small
icon.height
:
PlasmaCore
.
Units
.
iconSizes
.
small
onClicked
:
mpris2Source
.
goPrevious
()
visible
:
mpris2Source
.
canGoBack
||
mpris2Source
.
canGoNext
Accessible.name
:
i18nd
(
"
plasma_lookandfeel_org.kde.lookandfeel
"
,
"
Previous track
"
)
}
PlasmaComponents3.ToolButton
{
Layout.fillHeight
:
true
Layout.preferredWidth
:
height
enabled
:
mpris2Source
.
canGoBack
(
playerItem
.
source
)
icon.name
:
LayoutMirroring
.
enabled
?
"
media-skip-forward
"
:
"
media-skip-backward
"
icon.width
:
PlasmaCore
.
Units
.
iconSizes
.
small
icon.height
:
PlasmaCore
.
Units
.
iconSizes
.
small
onClicked
:
mpris2Source
.
goPrevious
(
playerItem
.
source
)
visible
:
mpris2Source
.
canGoBack
(
playerItem
.
source
)
||
mpris2Source
.
canGoNext
(
playerItem
.
source
)
Accessible.name
:
i18nd
(
"
plasma_lookandfeel_org.kde.lookandfeel
"
,
"
Previous track
"
)
}
PlasmaComponents3.ToolButton
{
Layout.fillHeight
:
true
Layout.preferredWidth
:
height
icon.name
:
mpris2Source
.
p
laying
?
"
media-playback-pause
"
:
"
media-playback-start
"
icon.width
:
PlasmaCore
.
Units
.
iconSizes
.
small
icon.height
:
PlasmaCore
.
Units
.
iconSizes
.
small
onClicked
:
mpris2Source
.
playPause
()
Accessible.name
:
i18nd
(
"
plasma_lookandfeel_org.kde.lookandfeel
"
,
"
Play or Pause media
"
)
}
PlasmaComponents3.ToolButton
{
Layout.fillHeight
:
true
Layout.preferredWidth
:
height
icon.name
:
mpris2Source
.
isP
laying
(
playerItem
.
source
)
?
"
media-playback-pause
"
:
"
media-playback-start
"
icon.width
:
PlasmaCore
.
Units
.
iconSizes
.
small
icon.height
:
PlasmaCore
.
Units
.
iconSizes
.
small
onClicked
:
mpris2Source
.
playPause
(
playerItem
.
source
)
Accessible.name
:
i18nd
(
"
plasma_lookandfeel_org.kde.lookandfeel
"
,
"
Play or Pause media
"
)
}
PlasmaComponents3.ToolButton
{
Layout.fillHeight
:
true
Layout.preferredWidth
:
height
enabled
:
mpris2Source
.
canGoNext
icon.name
:
LayoutMirroring
.
enabled
?
"
media-skip-backward
"
:
"
media-skip-forward
"
icon.width
:
PlasmaCore
.
Units
.
iconSizes
.
small
icon.height
:
PlasmaCore
.
Units
.
iconSizes
.
small
onClicked
:
mpris2Source
.
goNext
()
visible
:
mpris2Source
.
canGoBack
||
mpris2Source
.
canGoNext
Accessible.name
:
i18nd
(
"
plasma_lookandfeel_org.kde.lookandfeel
"
,
"
Next track
"
)
PlasmaComponents3.ToolButton
{
Layout.fillHeight
:
true
Layout.preferredWidth
:
height
enabled
:
mpris2Source
.
canGoBack
(
playerItem
.
source
)
icon.name
:
LayoutMirroring
.
enabled
?
"
media-skip-backward
"
:
"
media-skip-forward
"
icon.width
:
PlasmaCore
.
Units
.
iconSizes
.
small
icon.height
:
PlasmaCore
.
Units
.
iconSizes
.
small
onClicked
:
mpris2Source
.
goNext
(
playerItem
.
source
)
visible
:
mpris2Source
.
canGoBack
(
playerItem
.
source
)
||
mpris2Source
.
canGoNext
(
playerItem
.
source
)
Accessible.name
:
i18nd
(
"
plasma_lookandfeel_org.kde.lookandfeel
"
,
"
Next track
"
)
}
}
}
}
}
}
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment