Warning, /system/mycroft-gui/import/qml/VideoPlayer.qml is written in an unsupported language. File is not indexed.
0001 /*
0002 * Copyright 2019 by Aditya Mehra <aix.m@outlook.com>
0003 * Copyright 2019 by Marco Martin <mart@kde.org>
0004 *
0005 * Licensed under the Apache License, Version 2.0 (the "License");
0006 * you may not use this file except in compliance with the License.
0007 * You may obtain a copy of the License at
0008 *
0009 * http://www.apache.org/licenses/LICENSE-2.0
0010 *
0011 * Unless required by applicable law or agreed to in writing, software
0012 * distributed under the License is distributed on an "AS IS" BASIS,
0013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014 * See the License for the specific language governing permissions and
0015 * limitations under the License.
0016 *
0017 */
0018
0019 import QtQuick 2.15
0020 import QtQuick.Controls 2.15 as Controls
0021 import QtQuick.Templates 2.15 as Templates
0022 import QtQuick.Layouts 1.15
0023 import org.kde.kirigami 2.19 as Kirigami
0024 import Mycroft 1.0 as Mycroft
0025 import QtMultimedia
0026
0027 Item {
0028 id: root
0029
0030 property alias source: video.source
0031 property string status: "stop"
0032 property bool progressBar: true
0033 property bool hasNextAction: true
0034 property bool hasPreviousAction: true
0035 property bool controlBarOpened: false
0036 property var nextAction
0037 property var previousAction
0038 property alias currentState: video.status
0039
0040 onEnabledChanged: syncStatusTimer.restart()
0041 onSourceChanged: syncStatusTimer.restart()
0042 Component.onCompleted: syncStatusTimer.restart()
0043
0044 function formatTime(timeInMs) {
0045 if (!timeInMs || timeInMs <= 0) return "0:00"
0046 var seconds = timeInMs / 1000;
0047 var minutes = Math.floor(seconds / 60)
0048 seconds = Math.floor(seconds % 60)
0049 if (seconds < 10) seconds = "0" + seconds;
0050 return minutes + ":" + seconds
0051 }
0052
0053 Timer {
0054 id: hideTimer
0055 interval: 5000
0056 onTriggered: root.controlBarOpened = false;
0057 }
0058
0059 // Sometimes can't be restarted reliably immediately, put it in a timer
0060 Timer {
0061 id: syncStatusTimer
0062 interval: 0
0063 onTriggered: {
0064 if (enabled && status == "play") {
0065 video.play();
0066 } else if (status == "stop") {
0067 video.stop();
0068 } else {
0069 video.pause();
0070 }
0071 }
0072 }
0073
0074 Video {
0075 id: video
0076 anchors.fill: parent
0077 focus: true
0078 autoLoad: true
0079 autoPlay: false
0080 readonly property string currentStatus: root.enabled ? root.status : "pause"
0081 Keys.onSpacePressed: video.playbackState == MediaPlayer.PlayingState ? video.pause() : video.play()
0082 Keys.onLeftPressed: video.seek(video.position - 5000)
0083 Keys.onRightPressed: video.seek(video.position + 5000)
0084
0085 onSourceChanged: {
0086 console.log(source)
0087 }
0088
0089 onCurrentStatusChanged: {
0090 switch(currentStatus){
0091 case "stop":
0092 video.stop();
0093 break;
0094 case "pause":
0095 video.pause()
0096 break;
0097 case "play":
0098 video.play()
0099 break;
0100 }
0101 }
0102
0103 MouseArea {
0104 anchors.fill: parent
0105 onClicked: controlBarOpened = !controlBarOpened
0106 }
0107 }
0108
0109
0110 Rectangle {
0111 anchors.left: parent.left
0112 anchors.right: parent.right
0113 anchors.bottom: parent.bottom
0114 clip: true
0115 implicitHeight: controlLayout.implicitHeight + Kirigami.Units.largeSpacing * 2
0116 color: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.6)
0117 opacity: controlBarOpened
0118
0119 Behavior on opacity {
0120 OpacityAnimator {
0121 duration: Kirigami.Units.longDuration
0122 easing.type: Easing.InOutCubic
0123 }
0124 }
0125
0126 onOpacityChanged: {
0127 if (controlBarOpened) {
0128 hideTimer.restart();
0129 }
0130 }
0131
0132 RowLayout {
0133 id: controlLayout
0134 anchors.fill: parent
0135 anchors.margins: Kirigami.Units.largeSpacing
0136
0137 Controls.RoundButton {
0138 id: backButton
0139 Layout.minimumWidth: Kirigami.Units.iconSizes.smallMedium
0140 Layout.minimumHeight: width
0141 Layout.fillWidth: true
0142 Layout.fillHeight: true
0143 Layout.maximumWidth: Kirigami.Units.gridUnit * 3
0144 Layout.maximumHeight: width
0145 icon.name: "go-previous-symbolic"
0146 z: 1000
0147 onClicked: {
0148 Mycroft.MycroftController.sendRequest("mycroft.gui.screen.close", {});
0149 video.stop();
0150 }
0151 }
0152
0153 Controls.RoundButton {
0154 id: previousButton
0155 Layout.minimumWidth: Kirigami.Units.iconSizes.smallMedium
0156 Layout.minimumHeight: width
0157 Layout.fillWidth: true
0158 Layout.fillHeight: true
0159 Layout.maximumWidth: Kirigami.Units.gridUnit * 3
0160 Layout.maximumHeight: width
0161 focus: false
0162 icon.name: "media-seek-backward"
0163 visible: hasNextAction
0164 onClicked: {
0165 triggerGuiEvent(previousAction, {})
0166 previousButton.focus = false
0167 }
0168 }
0169
0170 Controls.RoundButton {
0171 id: playButton
0172 Layout.minimumWidth: Kirigami.Units.iconSizes.medium
0173 Layout.minimumHeight: width
0174 Layout.fillWidth: true
0175 Layout.fillHeight: true
0176 Layout.maximumWidth: Kirigami.Units.gridUnit * 4
0177 Layout.maximumHeight: width
0178 focus: false
0179 icon.name: video.playbackState === MediaPlayer.PlayingState ? "media-playback-pause" : "media-playback-start"
0180 onClicked: {
0181 video.playbackState === MediaPlayer.PlayingState ? video.pause() : video.play()
0182 playButton.focus = false
0183 }
0184 }
0185
0186 Controls.RoundButton {
0187 id: nextButton
0188 Layout.minimumWidth: Kirigami.Units.iconSizes.smallMedium
0189 Layout.minimumHeight: width
0190 Layout.fillWidth: true
0191 Layout.fillHeight: true
0192 Layout.maximumWidth: Kirigami.Units.gridUnit * 3
0193 Layout.maximumHeight: width
0194 focus: false
0195 icon.name: "media-seek-forward"
0196 visible: hasPreviousAction
0197 onClicked: {
0198 triggerGuiEvent(nextAction, {})
0199 nextButton.focus = false
0200 }
0201 }
0202
0203 Templates.Slider {
0204 id: slider
0205 Layout.fillWidth: true
0206 Layout.alignment: Qt.AlignVCenter
0207 implicitHeight: Kirigami.Units.gridUnit
0208 value: video.position
0209 from: 0
0210 to: video.duration
0211 z: 1000
0212 onMoved: {
0213 video.seek(value);
0214 hideTimer.restart();
0215 }
0216 handle: Rectangle {
0217 x: slider.position * (parent.width - width)
0218 implicitWidth: Kirigami.Units.gridUnit
0219 implicitHeight: implicitWidth
0220 radius: width
0221 }
0222 background: Item {
0223 Rectangle {
0224 id: groove
0225 anchors {
0226 verticalCenter: parent.verticalCenter
0227 left: parent.left
0228 right: parent.right
0229 }
0230 radius: height
0231 height: Math.round(Kirigami.Units.gridUnit/3)
0232 color: Qt.rgba(Kirigami.Theme.textColor.r, Kirigami.Theme.textColor.g, Kirigami.Theme.textColor.b, 0.3)
0233 Rectangle {
0234 anchors {
0235 left: parent.left
0236 top: parent.top
0237 bottom: parent.bottom
0238 }
0239 radius: height
0240 color: Kirigami.Theme.highlightColor
0241 width: slider.position * (parent.width - slider.handle.width/2) + slider.handle.width/2
0242 }
0243 }
0244
0245 Controls.Label {
0246 anchors {
0247 left: parent.left
0248 top: groove.bottom
0249 topMargin: Kirigami.Units.smallSpacing
0250 }
0251 horizontalAlignment: Text.AlignLeft
0252 verticalAlignment: Text.AlignVCenter
0253 text: formatTime(playPosition)
0254 color: "white"
0255 }
0256
0257 Controls.Label {
0258 anchors {
0259 right: parent.right
0260 top: groove.bottom
0261 topMargin: Kirigami.Units.smallSpacing
0262 }
0263 horizontalAlignment: Text.AlignRight
0264 verticalAlignment: Text.AlignVCenter
0265 text: formatTime(duration)
0266 }
0267 }
0268 }
0269 }
0270 }
0271 }
0272