More work on Multimedia
This commit is contained in:
parent
8ad40dcf56
commit
2ad624329c
@ -185,5 +185,8 @@
|
|||||||
<file>ui/connection/SetupWizard.qml</file>
|
<file>ui/connection/SetupWizard.qml</file>
|
||||||
<file>ui/system/NetworkSettingsPage.qml</file>
|
<file>ui/system/NetworkSettingsPage.qml</file>
|
||||||
<file>ui/devicepages/DeviceBrowserPage.qml</file>
|
<file>ui/devicepages/DeviceBrowserPage.qml</file>
|
||||||
|
<file>ui/devicelistpages/MediaDeviceListPage.qml</file>
|
||||||
|
<file>ui/components/MediaControls.qml</file>
|
||||||
|
<file>ui/components/MediaArtworkImage.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
|||||||
@ -30,6 +30,8 @@ Item {
|
|||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
anchors.margins: 1
|
anchors.margins: 1
|
||||||
z: -1
|
z: -1
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
// horizontalAlignment: Image.AlignTop
|
||||||
// opacity: .5
|
// opacity: .5
|
||||||
// Rectangle {
|
// Rectangle {
|
||||||
// anchors.fill: parent
|
// anchors.fill: parent
|
||||||
|
|||||||
47
nymea-app/ui/components/MediaArtworkImage.qml
Normal file
47
nymea-app/ui/components/MediaArtworkImage.qml
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Controls.Material 2.1
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: root
|
||||||
|
property Device device: null
|
||||||
|
|
||||||
|
readonly property StateType artworkStateType: device ? device.deviceClass.stateTypes.findByName("artwork") : null
|
||||||
|
readonly property State artworkState: artworkStateType ? device.states.getState(artworkStateType.id) : null
|
||||||
|
|
||||||
|
readonly property StateType playerTypeStateType: device ? device.deviceClass.stateTypes.findByName("playerType") : null
|
||||||
|
readonly property State playerTypeState: playerTypeStateType ? device.states.getState(playerTypeStateType.id) : null
|
||||||
|
|
||||||
|
Pane {
|
||||||
|
Material.elevation: 2
|
||||||
|
anchors.centerIn: parent
|
||||||
|
height: fallback.visible ? Math.min(parent.height, parent.width) : artworkImage.paintedHeight - 1
|
||||||
|
width: fallback.visible ? Math.min(parent.height, parent.width) : artworkImage.paintedWidth - 1
|
||||||
|
padding: 0
|
||||||
|
contentItem: Rectangle {
|
||||||
|
color: "black"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: artworkImage
|
||||||
|
anchors.fill: parent
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
source: root.artworkState.value
|
||||||
|
visible: source !== ""
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorIcon {
|
||||||
|
id: fallback
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: Math.min(parent.height, parent.width) - app.margins * 2
|
||||||
|
height: Math.min(parent.height, parent.width) - app.margins * 2
|
||||||
|
|
||||||
|
name: root.playerTypeState.value === "video" ? "../images/stock_video.svg" : "../images/stock_music.svg"
|
||||||
|
visible: artworkImage.status !== Image.Ready || artworkImage.source === ""
|
||||||
|
// color: app.primaryColor
|
||||||
|
color: "white"
|
||||||
|
}
|
||||||
|
}
|
||||||
73
nymea-app/ui/components/MediaControls.qml
Normal file
73
nymea-app/ui/components/MediaControls.qml
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Controls.Material 2.1
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import Nymea 1.0
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
id: root
|
||||||
|
implicitHeight: iconSize + app.margins
|
||||||
|
|
||||||
|
property Device device: null
|
||||||
|
property int iconSize: app.iconSize * 1.5
|
||||||
|
|
||||||
|
readonly property StateType playbackStateType: device ? device.deviceClass.stateTypes.findByName("playbackStatus") : null
|
||||||
|
readonly property State playbackState: playbackStateType ? device.states.getState(playbackStateType.id) : null
|
||||||
|
|
||||||
|
function executeAction(actionName, params) {
|
||||||
|
var actionTypeId = device.deviceClass.actionTypes.findByName(actionName).id;
|
||||||
|
engine.deviceManager.executeAction(device.id, actionTypeId, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
ProgressButton {
|
||||||
|
Layout.preferredHeight: root.iconSize * .6
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
imageSource: "../images/media-skip-backward.svg"
|
||||||
|
longpressImageSource: "../images/media-seek-backward.svg"
|
||||||
|
enabled: root.playbackState.value !== "Stopped"
|
||||||
|
repeat: true
|
||||||
|
onClicked: {
|
||||||
|
root.executeAction("skipBack")
|
||||||
|
}
|
||||||
|
onLongpressed: {
|
||||||
|
root.executeAction("fastRewind")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
ProgressButton {
|
||||||
|
Layout.preferredHeight: root,iconSize
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
imageSource: root.playbackState && root.playbackState.value === "Playing" ? "../images/media-playback-pause.svg" : "../images/media-playback-start.svg"
|
||||||
|
longpressImageSource: "../images/media-playback-stop.svg"
|
||||||
|
longpressEnabled: root.playbackState.value !== "Stopped"
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
if (root.playbackState.value === "Playing") {
|
||||||
|
root.executeAction("pause")
|
||||||
|
} else {
|
||||||
|
root.executeAction("play")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onLongpressed: {
|
||||||
|
root.executeAction("stop")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
ProgressButton {
|
||||||
|
Layout.preferredHeight: root.iconSize * .6
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
imageSource: "../images/media-skip-forward.svg"
|
||||||
|
longpressImageSource: "../images/media-seek-forward.svg"
|
||||||
|
enabled: root.playbackState.value !== "Stopped"
|
||||||
|
repeat: true
|
||||||
|
onClicked: {
|
||||||
|
root.executeAction("skipNext")
|
||||||
|
}
|
||||||
|
onLongpressed: {
|
||||||
|
root.executeAction("fastForward")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item { Layout.fillWidth: true }
|
||||||
|
}
|
||||||
170
nymea-app/ui/devicelistpages/MediaDeviceListPage.qml
Normal file
170
nymea-app/ui/devicelistpages/MediaDeviceListPage.qml
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
import QtQuick 2.5
|
||||||
|
import QtQuick.Controls 2.1
|
||||||
|
import QtQuick.Controls.Material 2.1
|
||||||
|
import QtQuick.Layouts 1.1
|
||||||
|
import Nymea 1.0
|
||||||
|
import QtGraphicalEffects 1.0
|
||||||
|
import "../components"
|
||||||
|
|
||||||
|
DeviceListPageBase {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
header: NymeaHeader {
|
||||||
|
text: qsTr("Media")
|
||||||
|
onBackPressed: pageStack.pop()
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
anchors.fill: parent
|
||||||
|
model: root.devicesProxy
|
||||||
|
|
||||||
|
delegate: ItemDelegate {
|
||||||
|
id: itemDelegate
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
property bool inline: width > 500
|
||||||
|
|
||||||
|
property Device device: devicesProxy.get(index);
|
||||||
|
property DeviceClass deviceClass: device.deviceClass
|
||||||
|
|
||||||
|
readonly property StateType playbackStateType: deviceClass.stateTypes.findByName("playbackStatus")
|
||||||
|
readonly property State playbackState: playbackStateType ? device.states.getState(playbackStateType.id) : null
|
||||||
|
|
||||||
|
bottomPadding: index === ListView.view.count - 1 ? topPadding : 0
|
||||||
|
contentItem: Pane {
|
||||||
|
id: contentItem
|
||||||
|
Material.elevation: 2
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
topPadding: 0
|
||||||
|
bottomPadding: 0
|
||||||
|
|
||||||
|
contentItem: ItemDelegate {
|
||||||
|
leftPadding: 0
|
||||||
|
rightPadding: 0
|
||||||
|
topPadding: 0
|
||||||
|
bottomPadding: 0
|
||||||
|
contentItem: ColumnLayout {
|
||||||
|
spacing: 0
|
||||||
|
Rectangle {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
Layout.preferredHeight: app.mediumFont + app.margins
|
||||||
|
color: Qt.rgba(app.foregroundColor.r, app.foregroundColor.g, app.foregroundColor.b, .05)
|
||||||
|
RowLayout {
|
||||||
|
anchors { verticalCenter: parent.verticalCenter; left: parent.left; right: parent.right; margins: app.margins }
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: model.name
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
name: "../images/battery/battery-020.svg"
|
||||||
|
visible: itemDelegate.deviceClass.interfaces.indexOf("battery") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("batteryCritical").id).value === true
|
||||||
|
}
|
||||||
|
ColorIcon {
|
||||||
|
Layout.preferredHeight: app.iconSize * .5
|
||||||
|
Layout.preferredWidth: height
|
||||||
|
name: "../images/dialog-warning-symbolic.svg"
|
||||||
|
visible: itemDelegate.deviceClass.interfaces.indexOf("connectable") >= 0 && itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("connected").id).value === false
|
||||||
|
color: "red"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
RowLayout {
|
||||||
|
ColumnLayout {
|
||||||
|
id: leftColummn
|
||||||
|
Layout.margins: app.margins
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: itemDelegate.playbackState.value === "Stopped" ?
|
||||||
|
qsTr("No playback")
|
||||||
|
: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("title").id).value
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
// font.pixelSize: app.largeFont
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("artist").id).value
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
text: itemDelegate.device.states.getState(itemDelegate.deviceClass.stateTypes.findByName("collection").id).value
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
font.pixelSize: app.smallFont
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
MediaControls {
|
||||||
|
visible: itemDelegate.deviceClass.interfaces.indexOf("mediacontroller") >= 0
|
||||||
|
device: itemDelegate.device
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Item {
|
||||||
|
Layout.preferredHeight: leftColummn.height + app.margins * 2
|
||||||
|
Layout.preferredWidth: height * .7
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: artworkContainer
|
||||||
|
anchors.fill: parent
|
||||||
|
Image {
|
||||||
|
id: artworkImage
|
||||||
|
width: artworkImage.sourceSize.width * height / artworkImage.sourceSize.height
|
||||||
|
anchors { top: parent.top; right: parent.right; bottom: parent.bottom }
|
||||||
|
readonly property StateType artworkStateType: device ? device.deviceClass.stateTypes.findByName("artwork") : null
|
||||||
|
readonly property State artworkState: artworkStateType ? device.states.getState(artworkStateType.id) : null
|
||||||
|
source: artworkState ? artworkState.value : ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: maskRect
|
||||||
|
anchors.centerIn: parent
|
||||||
|
height: parent.width
|
||||||
|
width: parent.height
|
||||||
|
gradient: Gradient {
|
||||||
|
GradientStop { position: 0; color: "transparent" }
|
||||||
|
GradientStop { position: 1; color: "red" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderEffect {
|
||||||
|
anchors.fill: parent
|
||||||
|
property variant source: ShaderEffectSource {
|
||||||
|
sourceItem: artworkContainer
|
||||||
|
hideSource: true
|
||||||
|
}
|
||||||
|
property variant mask: ShaderEffectSource {
|
||||||
|
sourceItem: maskRect
|
||||||
|
hideSource: true
|
||||||
|
}
|
||||||
|
|
||||||
|
fragmentShader: "
|
||||||
|
varying highp vec2 qt_TexCoord0;
|
||||||
|
uniform sampler2D source;
|
||||||
|
uniform sampler2D mask;
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
highp vec4 sourceColor = texture2D(source, qt_TexCoord0);
|
||||||
|
highp float alpha = texture2D(mask, vec2(qt_TexCoord0.y, qt_TexCoord0.x)).a;
|
||||||
|
sourceColor *= alpha;
|
||||||
|
gl_FragColor = sourceColor;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
enterPage(index, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -41,6 +41,7 @@ DevicePageBase {
|
|||||||
SwipeView {
|
SwipeView {
|
||||||
id: swipeView
|
id: swipeView
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
interactive: root.deviceClass.browsable
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
GridLayout {
|
GridLayout {
|
||||||
@ -51,32 +52,10 @@ DevicePageBase {
|
|||||||
columnSpacing: app.margins
|
columnSpacing: app.margins
|
||||||
rowSpacing: app.margins
|
rowSpacing: app.margins
|
||||||
|
|
||||||
Pane {
|
MediaArtworkImage {
|
||||||
Layout.fillWidth: true
|
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
Layout.minimumWidth: parent.width / 2
|
Layout.preferredWidth: parent.width / parent.columns
|
||||||
Material.elevation: 2
|
device: root.device
|
||||||
padding: 0
|
|
||||||
|
|
||||||
contentItem: Rectangle {
|
|
||||||
color: app.foregroundColor
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: artworkImage
|
|
||||||
anchors.fill: parent
|
|
||||||
fillMode: Image.PreserveAspectFit
|
|
||||||
source: root.stateValue("artwork")
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorIcon {
|
|
||||||
id: fallback
|
|
||||||
anchors.fill: parent
|
|
||||||
anchors.margins: app.margins * 2
|
|
||||||
name: root.stateValue("playerType") === "video" ? "../images/stock_video.svg" : "../images/stock_music.svg"
|
|
||||||
visible: artworkImage.status !== Image.Ready || artworkImage.source === ""
|
|
||||||
color: app.primaryColor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
@ -110,62 +89,9 @@ DevicePageBase {
|
|||||||
text: root.stateValue("collection")
|
text: root.stateValue("collection")
|
||||||
}
|
}
|
||||||
|
|
||||||
RowLayout {
|
MediaControls {
|
||||||
Layout.fillWidth: true
|
device: root.device
|
||||||
Item { Layout.fillWidth: true }
|
iconSize: app.iconSize * 2
|
||||||
|
|
||||||
ProgressButton {
|
|
||||||
Layout.preferredHeight: app.iconSize
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
imageSource: "../images/media-skip-backward.svg"
|
|
||||||
longpressImageSource: "../images/media-seek-backward.svg"
|
|
||||||
repeat: true
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
root.executeAction("skipBack")
|
|
||||||
}
|
|
||||||
onLongpressed: {
|
|
||||||
root.executeAction("fastRewind")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
|
|
||||||
ProgressButton {
|
|
||||||
Layout.preferredHeight: app.iconSize * 2
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
imageSource: root.playbackState.value === "Playing" ? "../images/media-playback-pause.svg" : "../images/media-playback-start.svg"
|
|
||||||
longpressImageSource: "../images/media-playback-stop.svg"
|
|
||||||
longpressEnabled: root.playbackState.value !== "Stopped"
|
|
||||||
|
|
||||||
onClicked: {
|
|
||||||
if (root.playbackState.value === "Playing") {
|
|
||||||
root.executeAction("pause")
|
|
||||||
} else {
|
|
||||||
root.executeAction("play")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onLongpressed: {
|
|
||||||
root.executeAction("stop")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
ProgressButton {
|
|
||||||
Layout.preferredHeight: app.iconSize
|
|
||||||
Layout.preferredWidth: height
|
|
||||||
imageSource: "../images/media-skip-forward.svg"
|
|
||||||
longpressImageSource: "../images/media-seek-forward.svg"
|
|
||||||
repeat: true
|
|
||||||
onClicked: {
|
|
||||||
root.executeAction("skipNext")
|
|
||||||
}
|
|
||||||
onLongpressed: {
|
|
||||||
root.executeAction("fastForward")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Item { Layout.fillWidth: true }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,6 +205,7 @@ DevicePageBase {
|
|||||||
Item {
|
Item {
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
Layout.preferredHeight: 2
|
Layout.preferredHeight: 2
|
||||||
|
visible: root.deviceClass.browsable
|
||||||
Rectangle {
|
Rectangle {
|
||||||
height: parent.height
|
height: parent.height
|
||||||
width: parent.width / 2
|
width: parent.width / 2
|
||||||
|
|||||||
@ -13,13 +13,7 @@ MainPageTile {
|
|||||||
disconnected: devicesSubProxyConnectables.count > 0
|
disconnected: devicesSubProxyConnectables.count > 0
|
||||||
batteryCritical: devicesSubProxyBattery.count > 0
|
batteryCritical: devicesSubProxyBattery.count > 0
|
||||||
|
|
||||||
backgroundImage: currentDevice.deviceClass.interfaces.indexOf("mediametadataprovider") >= 0 ?
|
backgroundImage: inlineControlLoader.item && inlineControlLoader.item.hasOwnProperty("backgroundImage") ? inlineControlLoader.item.backgroundImage : ""
|
||||||
currentDevice.states.getState(currentDevice.deviceClass.stateTypes.findByName("artwork").id).value : ""
|
|
||||||
|
|
||||||
property int currentDeviceIndex: 0
|
|
||||||
readonly property Device currentDevice: devicesProxy.get(currentDeviceIndex)
|
|
||||||
// readonly property State currentBackgroundState: currentDevice.state
|
|
||||||
|
|
||||||
|
|
||||||
onClicked: {
|
onClicked: {
|
||||||
var page;
|
var page;
|
||||||
@ -55,6 +49,9 @@ MainPageTile {
|
|||||||
case "powersocket":
|
case "powersocket":
|
||||||
page = "PowerSocketsDeviceListPage.qml";
|
page = "PowerSocketsDeviceListPage.qml";
|
||||||
break;
|
break;
|
||||||
|
case "media":
|
||||||
|
page = "MediaDeviceListPage.qml";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
page = "GenericDeviceListPage.qml"
|
page = "GenericDeviceListPage.qml"
|
||||||
}
|
}
|
||||||
@ -84,6 +81,9 @@ MainPageTile {
|
|||||||
filterBatteryCritical: true
|
filterBatteryCritical: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
property int currentDeviceIndex: 0
|
||||||
|
readonly property Device currentDevice: devicesProxy.get(currentDeviceIndex)
|
||||||
|
|
||||||
contentItem: Loader {
|
contentItem: Loader {
|
||||||
id: inlineControlLoader
|
id: inlineControlLoader
|
||||||
anchors {
|
anchors {
|
||||||
@ -105,7 +105,6 @@ MainPageTile {
|
|||||||
// return labelComponent;
|
// return labelComponent;
|
||||||
|
|
||||||
case "light":
|
case "light":
|
||||||
case "media":
|
|
||||||
case "garagegate":
|
case "garagegate":
|
||||||
case "blind":
|
case "blind":
|
||||||
case "extendedblind":
|
case "extendedblind":
|
||||||
@ -115,12 +114,66 @@ MainPageTile {
|
|||||||
case "extendedawning":
|
case "extendedawning":
|
||||||
case "powersocket":
|
case "powersocket":
|
||||||
return buttonComponent
|
return buttonComponent
|
||||||
|
case "media":
|
||||||
|
return mediaControlComponent
|
||||||
default:
|
default:
|
||||||
console.warn("DevicesPageDelegate, inlineControl: Unhandled interface", model.name)
|
console.warn("DevicesPageDelegate, inlineControl: Unhandled interface", model.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Component {
|
||||||
|
id: mediaControlComponent
|
||||||
|
RowLayout {
|
||||||
|
id: inlineMediaControl
|
||||||
|
|
||||||
|
property string backgroundImage: artworkState ? artworkState.value : ""
|
||||||
|
|
||||||
|
property int currentDeviceIndex: 0
|
||||||
|
readonly property Device currentDevice: devicesProxy.get(currentDeviceIndex)
|
||||||
|
readonly property StateType playbackStateType: currentDevice.deviceClass.stateTypes.findByName("playbackStatus")
|
||||||
|
readonly property State playbackState: currentDevice.states.getState(playbackStateType.id)
|
||||||
|
readonly property StateType artworkStateType: currentDevice.deviceClass.stateTypes.findByName("artwork")
|
||||||
|
readonly property State artworkState: artworkStateType ? currentDevice.states.getState(artworkStateType.id) : null
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
for (var i = 0; i < devicesProxy.count; i++) {
|
||||||
|
var d = devicesProxy.get(i);
|
||||||
|
var st = d.deviceClass.stateTypes.findByName("playbackStatus")
|
||||||
|
var s = d.states.getState(st.id)
|
||||||
|
s.valueChanged.connect(function() {updateTile()})
|
||||||
|
}
|
||||||
|
updateTile();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTile() {
|
||||||
|
var playingIndex = -1;
|
||||||
|
var pausedIndex = -1;
|
||||||
|
for (var i = 0; i < devicesProxy.count; i++) {
|
||||||
|
var d = devicesProxy.get(i);
|
||||||
|
var st = d.deviceClass.stateTypes.findByName("playbackStatus");
|
||||||
|
if (!st) continue;
|
||||||
|
var s = d.states.getState(st.id);
|
||||||
|
if (playingIndex === -1 && s.value === "Playing") {
|
||||||
|
playingIndex = i;
|
||||||
|
} else if (pausedIndex === -1 && s.value === "Paused") {
|
||||||
|
pausedIndex = -i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (playingIndex !== -1) {
|
||||||
|
currentDeviceIndex = playingIndex;
|
||||||
|
} else if (pausedIndex !== -1) {
|
||||||
|
currentDeviceIndex = pausedIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaControls {
|
||||||
|
iconSize: app.iconSize * 1.2
|
||||||
|
device: inlineMediaControl.currentDevice
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Component {
|
Component {
|
||||||
id: buttonComponent
|
id: buttonComponent
|
||||||
ColumnLayout {
|
ColumnLayout {
|
||||||
|
|||||||
Reference in New Issue
Block a user