Unity 8
VideoPlayer.qml
1 /*
2  * Copyright (C) 2016 Canonical, Ltd.
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; version 3.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program. If not, see <http://www.gnu.org/licenses/>.
15  */
16 
17 import QtQuick 2.12
18 import QtMultimedia 5.0
19 import Ubuntu.Components 1.3
20 import Ubuntu.Thumbnailer 0.1
21 import "../../Components"
22 
23 Item {
24  id: root
25 
26  property alias screenshot: image.source
27  property alias mediaPlayer: videoOutput.source
28  property int orientation: Qt.PortraitOrientation
29  property bool fixedHeight: false
30  property var maximumEmbeddedHeight
31 
32  property alias playButtonBackgroundColor: playButton.color
33  property alias playButtonIconColor: playButtonIcon.color
34 
35  implicitHeight: {
36  if (parent && orientation === Qt.LandscapeOrientation) {
37  return parent.height;
38  }
39  return content.height;
40  }
41 
42  signal clicked
43  signal positionChanged
44 
45  Item {
46  id: content
47  anchors {
48  left: parent.left
49  right: parent.right
50  verticalCenter: parent.verticalCenter
51  }
52  height: {
53  if (root.orientation === Qt.LandscapeOrientation || fixedHeight) {
54  return root.height;
55  }
56  var proposedHeight = videoOutput.height;
57  if (maximumEmbeddedHeight !== undefined && maximumEmbeddedHeight < proposedHeight) {
58  return maximumEmbeddedHeight;
59  }
60  return proposedHeight;
61  }
62  clip: image.height > videoOutput.height
63 
64  LazyImage {
65  id: image
66  objectName: "screenshot"
67  anchors {
68  left: parent.left
69  right: parent.right
70  verticalCenter: parent.verticalCenter
71  }
72  scaleTo: "width"
73  lastScaledDimension: playButton.height + units.gu(2)
74  initialHeight: lastScaledDimension
75  useUbuntuShape: false
76 
77  visible: !mediaPlayer || mediaPlayer.playbackState === MediaPlayer.StoppedState
78  }
79 
80  VideoOutput {
81  id: videoOutput
82  anchors.centerIn: parent
83 
84  width: root.width
85  height: {
86  if (fixedHeight) {
87  return root.height;
88  }
89  var proposedHeight = mediaPlayer && mediaPlayer.metaData.resolution !== undefined ?
90  (mediaPlayer.metaData.resolution.height / mediaPlayer.metaData.resolution.width) * width :
91  image.height;
92  if (maximumEmbeddedHeight !== undefined && maximumEmbeddedHeight < proposedHeight) {
93  return maximumEmbeddedHeight;
94  }
95  return proposedHeight;
96  }
97 
98  source: mediaPlayer
99  visible: mediaPlayer && mediaPlayer.playbackState !== MediaPlayer.StoppedState || false
100 
101  Connections {
102  target: mediaPlayer
103  onError: {
104  if (error !== MediaPlayer.NoError) {
105  errorTimer.restart();
106  }
107  }
108  }
109  }
110  }
111 
112  Rectangle {
113  id: playButton
114  readonly property bool bigButton: parent.width > units.gu(40)
115  anchors.centerIn: content
116  width: bigButton ? units.gu(10) : units.gu(8)
117  height: width
118  visible: mediaPlayer && mediaPlayer.playbackState !== MediaPlayer.PlayingState || false
119  opacity: 0.85
120  radius: width/2
121 
122  Behavior on width { UbuntuNumberAnimation {} }
123 
124  Icon {
125  id: playButtonIcon
126  anchors.fill: parent
127  anchors.margins: units.gu(1)
128  name: errorTimer.running ? "dialog-warning-symbolic" : "media-playback-start"
129  }
130  }
131 
132  ActivityIndicator {
133  anchors.centerIn: content
134  running: {
135  if (!mediaPlayer) return false;
136  return mediaPlayer.status === MediaPlayer.Stalled ||
137  (mediaPlayer.playbackState === MediaPlayer.PlayingState && mediaPlayer.status === MediaPlayer.Loading);
138  }
139  }
140 
141  MouseArea {
142  id: contentMouseArea
143  anchors.fill: content
144  enabled: !errorTimer.running
145  hoverEnabled: mediaPlayer && mediaPlayer.playbackState !== MediaPlayer.StoppedState || false
146 
147  onClicked: root.clicked()
148  onPositionChanged: root.positionChanged()
149  }
150 
151  Timer {
152  id: errorTimer
153  interval: 2000
154  }
155 }