Skip to content
This repository has been archived by the owner on Sep 8, 2024. It is now read-only.

feat/gui video common play #2683

Closed
wants to merge 14 commits into from
32 changes: 32 additions & 0 deletions mycroft/enclosure/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def __init__(self, skill):
self.skill = skill
self.on_gui_changed_callback = None
self.config = Configuration.get()
self.video_info = None

@property
def remote_url(self):
Expand Down Expand Up @@ -339,6 +340,37 @@ def show_url(self, url, override_idle=None,
self.show_page("SYSTEM_UrlFrame.qml", override_idle,
override_animations)

def play_video(self, url, title="", override_idle=True):
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
""" Play video stream """
self["playStatus"] = "play"
self["video"] = url
self["title"] = title
self.video_info = {"title": title, "url": url}
self.show_page("SYSTEM_VideoPlayer.qml",
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
override_idle=override_idle)

@property
def is_playing_video(self):
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved
return self.video_info is not None
JarbasAl marked this conversation as resolved.
Show resolved Hide resolved

def pause_video(self):
"""Pause video playback."""
if self.is_playing_video:
self["playStatus"] = "pause"

def stop_video(self):
"""Stop video playback."""
# TODO detect end of media playback from gui
if self.is_playing_video:
self["playStatus"] = "stop"
self.clear()
self.video_info = None

def resume_video(self):
"""Resume paused video playback."""
if self.__session_data.get("playStatus", "stop") == "pause":
self["playStatus"] = "play"

def shutdown(self):
"""Shutdown gui interface.

Expand Down
192 changes: 192 additions & 0 deletions mycroft/res/ui/SYSTEM_VideoPlayer.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import QtMultimedia 5.12
import QtQuick.Layouts 1.4
import QtQuick 2.9
import QtQuick.Controls 2.12 as Controls
import org.kde.kirigami 2.10 as Kirigami
import QtQuick.Window 2.3
import QtGraphicalEffects 1.0

import Mycroft 1.0 as Mycroft
import "." as Local

Mycroft.Delegate {
id: root

property var videoSource: sessionData.video
property var videoStatus: sessionData.playStatus
property var videoThumb: sessionData.videoThumb
property var videoTitle: sessionData.title

//The player is always fullscreen
fillWidth: true
background: Rectangle {
color: "black"
}
leftPadding: 0
topPadding: 0
rightPadding: 0
bottomPadding: 0

onEnabledChanged: syncStatusTimer.restart()
onVideoSourceChanged: syncStatusTimer.restart()
Component.onCompleted: {
syncStatusTimer.restart()
}

Keys.onDownPressed: {
controlBarItem.opened = true
controlBarItem.forceActiveFocus()
}

onFocusChanged: {
console.log("focus changed")
video.forceActiveFocus();
}

Connections {
target: Window.window
onVisibleChanged: {
if(video.playbackState == MediaPlayer.PlayingState) {
video.stop()
}
}
}


// Sometimes can't be restarted reliably immediately, put it in a timer
Timer {
id: syncStatusTimer
interval: 0
onTriggered: {
if (enabled && videoStatus == "play") {
video.play();
} else if (videoStatus == "stop") {
video.stop();
} else {
video.pause();
}
}
}

Timer {
id: delaytimer
}

function delay(delayTime, cb) {
delaytimer.interval = delayTime;
delaytimer.repeat = false;
delaytimer.triggered.connect(cb);
delaytimer.start();
}

controlBar: Local.SeekControl {
id: seekControl
anchors {
// left: parent.left
// right: parent.right
bottom: parent.bottom
}
title: videoTitle
videoControl: video
duration: video.duration
playPosition: video.position
onSeekPositionChanged: video.seek(seekPosition);
z: 1000
}

Item {
id: videoRoot
anchors.fill: parent

Rectangle {
id: infomationBar
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
visible: false
color: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.6)
implicitHeight: vidTitle.implicitHeight + Kirigami.Units.largeSpacing * 2
z: 1001

onVisibleChanged: {
delay(15000, function() {
infomationBar.visible = false;
})
}

Controls.Label {
id: vidTitle
visible: true
maximumLineCount: 2
wrapMode: Text.Wrap
anchors.left: parent.left
anchors.leftMargin: Kirigami.Units.largeSpacing
anchors.verticalCenter: parent.verticalCenter
text: videoTitle
z: 100
}
}

Image {
id: thumbart
anchors.fill: parent
fillMode: Image.PreserveAspectFit
source: root.videoThumb
enabled: root.videoStatus == "stop" ? 1 : 0
visible: root.videoStatus == "stop" ? 1 : 0
}

Video {
id: video
anchors.fill: parent
focus: true
autoLoad: true
autoPlay: false
source: videoSource
readonly property string currentStatus: root.enabled ? root.videoStatus : "pause"

onFocusChanged: {
if(focus){
console.log("focus in video")
}
}

onCurrentStatusChanged: {
switch(currentStatus){
case "stop":
video.stop();
break;
case "pause":
video.pause()
break;
case "play":
video.play()
delay(6000, function() {
infomationBar.visible = false;
})
break;
}
}

Keys.onReturnPressed: {
video.playbackState == MediaPlayer.PlayingState ? video.pause() : video.play()
}

Keys.onDownPressed: {
controlBarItem.opened = true
controlBarItem.forceActiveFocus()
}

MouseArea {
anchors.fill: parent
onClicked: {
controlBarItem.opened = !controlBarItem.opened
}
}

onStatusChanged: {
console.log("Status Changed")
}
}
}
}
Loading