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