VideoPlayView.qml 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. /**
  2. * Copyright (c) 2012 Nokia Corporation.
  3. */
  4. import QtQuick 1.1
  5. import com.nokia.meego 1.0
  6. Item {
  7. id: videoPlayView
  8. // Enable/Disable rewinding/fast forwarding.
  9. property bool enableScrubbing: false
  10. // Set the video playback in either full or partial screen.
  11. property bool isFullScreen: false
  12. property bool isPortrait: visual.inPortrait
  13. // Video information data to be shown, when in partial screen mode.
  14. property string videoTitle: ""
  15. property int videoLength: 0
  16. property string videoAuthor: ""
  17. property int numLikes: 0
  18. property int numDislikes: 0
  19. property int viewCount: 0
  20. property string videoDescription: ""
  21. property string videoSource: ""
  22. property double topAreaProportion: visual.topAreaProportion
  23. property double bottomAreaProportion: visual.bottomAreaProportion
  24. property double leftAreaProportion: visual.leftAreaProportion
  25. property double rightAreaProportion: visual.rightAreaProportion
  26. // Ease of access handle for the VideoPlayerView Item.
  27. property alias videoPlayer: videoPlayerLoader.item
  28. // Property to observe the application shown/hidden status
  29. property bool applicationActive: Qt.application.active
  30. // Signalled, when exiting the Video player.
  31. signal videoExit
  32. // Function for setting the shown video information & setting the
  33. // video URL.
  34. function setVideoData(videoData) {
  35. videoPlayView.videoTitle = videoData.m_title ? videoData.m_title : "";
  36. videoPlayView.videoLength = videoData.m_duration ? videoData.m_duration : 0;
  37. videoPlayView.videoAuthor = videoData.m_author ? videoData.m_author : "";
  38. videoPlayView.numLikes = videoData.m_numLikes ? videoData.m_numLikes : 0;
  39. videoPlayView.numDislikes = videoData.m_numDislikes ? videoData.m_numDislikes : 0;
  40. videoPlayView.viewCount = videoData.m_viewCount ? videoData.m_viewCount : 0;
  41. videoPlayView.videoDescription = videoData.m_description ? videoData.m_description : "";
  42. // At least the m_contentUrl HAS to be defined!
  43. videoPlayView.videoSource = videoData.m_contentUrl;
  44. }
  45. function __showVideoControls(showControls) {
  46. overlayLoader.state = showControls ? "" : "Hidden";
  47. }
  48. function __toggleVideoControls() {
  49. // Disable automatic control hiding
  50. controlHideTimer.shouldRun = false;
  51. controlHideTimer.stop();
  52. if (overlayLoader.state == "") {
  53. overlayLoader.state = "Hidden";
  54. } else {
  55. overlayLoader.state = "";
  56. }
  57. }
  58. function __handleExit() {
  59. videoPlayer.stop();
  60. videoPlayer.disconnect();
  61. videoPlayView.videoExit();
  62. }
  63. function __playbackStarted() {
  64. controlHideTimer.startHideTimer();
  65. }
  66. Keys.onPressed: {
  67. if (!event.isAutoRepeat) {
  68. switch (event.key) {
  69. case Qt.Key_Right:
  70. console.log("TODO: Fast forward");
  71. event.accepted = true;
  72. break;
  73. case Qt.Key_Left:
  74. console.log("TODO: Reverse");
  75. event.accepted = true;
  76. break;
  77. case Qt.Key_Select:
  78. case Qt.Key_Enter:
  79. case Qt.Key_Return:
  80. if(videoPlayer.isPlaying) {
  81. videoPlayer.pause();
  82. } else {
  83. videoPlayer.play();
  84. }
  85. event.accepted = true;
  86. break;
  87. }
  88. }
  89. }
  90. // When going to background, pause the playback. And when returning from
  91. // background, resume playback.
  92. onApplicationActiveChanged: {
  93. if (videoPlayer) {
  94. if(applicationActive) {
  95. videoPlayer.play();
  96. } else {
  97. videoPlayer.pause();
  98. }
  99. }
  100. }
  101. anchors.fill: parent
  102. // A timer, which will give a small amount of time for the (page changing)
  103. // transitions to complete before the video loading is started. This is
  104. // done this way because otherwise the immediate loading of the video would
  105. // cause lagging & un-smooth animations.
  106. Timer {
  107. id: timer
  108. running: true
  109. interval: visual.animationDurationPrettyLong
  110. onTriggered: {
  111. stop();
  112. // The video playback area itself. Size for it is being determined
  113. // by the orientation and calculated proportionally based
  114. // on the parent dimensions.
  115. videoPlayerLoader.sourceComponent =
  116. Qt.createComponent("VideoPlayerView.qml");
  117. if (videoPlayerLoader.status === Loader.Ready) {
  118. if (videoPlayView.isFullScreen) {
  119. videoPlayer.toggled.connect(__toggleVideoControls);
  120. videoPlayer.playbackStarted.connect(__playbackStarted);
  121. }
  122. videoPlayer.stop();
  123. __showVideoControls(true);
  124. videoPlayer.source = videoPlayView.videoSource;
  125. videoPlayer.play();
  126. } else {
  127. console.log("Player loader NOT READY! Status: "
  128. + videoPlayerLoader.status);
  129. }
  130. }
  131. }
  132. // Timer responsible for hiding controls after entering
  133. // full screen player.
  134. Timer {
  135. id: controlHideTimer
  136. property bool shouldRun: videoPlayView.isFullScreen ? true : false
  137. function startHideTimer() {
  138. if (controlHideTimer.shouldRun) {
  139. start();
  140. }
  141. }
  142. running: false
  143. interval: visual.videoControlsHideTimeout
  144. onTriggered: {
  145. controlHideTimer.shouldRun = false;
  146. if (videoPlayer.isPlaying) {
  147. __showVideoControls(false);
  148. }
  149. }
  150. }
  151. Component {
  152. id: videoTitleComp
  153. VideoInfoTextLabel {
  154. maximumLineCount: isPortrait ? 2 : 1
  155. wrapMode: Text.WordWrap
  156. elide: Text.ElideRight
  157. text: videoPlayView.videoTitle
  158. font.bold: true
  159. }
  160. }
  161. // Loader, which selects what to show on the upper part of the screen.
  162. Loader {
  163. id: upperAreaLoader
  164. anchors {
  165. top: parent.top
  166. topMargin: videoPlayView.isFullScreen ? 0 : visual.margins
  167. left: parent.left
  168. leftMargin: videoPlayView.isFullScreen ? 0 : visual.margins
  169. right: parent.right
  170. }
  171. height: videoPlayView.isFullScreen ?
  172. 0 : (videoPlayView.height * topAreaProportion)
  173. sourceComponent: videoPlayView.isFullScreen ? undefined : videoTitleComp
  174. }
  175. // The Video can be played either in portrait or landscape mode. The
  176. // VideoInformationView is selected to be on the bottom when in portrait,
  177. // and when in landscape, the information is shown on the right side.
  178. Component {
  179. id: videoInformation
  180. VideoInformationView {
  181. videoTitle: videoPlayView.videoTitle
  182. numLikes: videoPlayView.numLikes
  183. numDislikes: videoPlayView.numDislikes
  184. viewCount: videoPlayView.viewCount
  185. }
  186. }
  187. // Loader, which selects what to show on the bottom part of the screen.
  188. Loader {
  189. id: bottomAreaLoader
  190. height: videoPlayView.isFullScreen ?
  191. 0 : (videoPlayView.height * bottomAreaProportion)
  192. width: videoPlayView.isFullScreen ? 0 : (videoPlayView.width / 3)
  193. anchors {
  194. bottom: parent.bottom
  195. bottomMargin: videoPlayView.isFullScreen ? 0 : visual.margins
  196. horizontalCenter: parent.horizontalCenter
  197. }
  198. sourceComponent: videoPlayView.isFullScreen ?
  199. undefined : (isPortrait ?
  200. videoInformation : undefined)
  201. }
  202. // In landscape there's an extra loader for the right side of the screen,
  203. // which will load basically the same information (views, likes & dislikes)
  204. // as in the upperAreaLoader in portrait mode.
  205. Loader {
  206. id: rightAreaLoader
  207. width: videoPlayView.isFullScreen ? 0 : (videoPlayView.width / 5)
  208. height: videoPlayView.isFullScreen ? 0 : videoPlayerLoader.height
  209. anchors {
  210. right: parent.right
  211. rightMargin: videoPlayView.isFullScreen ?
  212. 0 : (visual.isE6 ?
  213. visual.margins * 9 : visual.margins * 6)
  214. verticalCenter: videoPlayView.verticalCenter
  215. }
  216. sourceComponent: videoPlayView.isFullScreen ?
  217. undefined : (isPortrait ? undefined : videoInformation)
  218. }
  219. // Loader for the VideoPlayerComponent. NOTE: The sourceComponent will be
  220. // set a bit later, after the timer has triggered.
  221. Loader {
  222. id: videoPlayerLoader
  223. height: videoPlayView.isFullScreen ? screen.height : (videoPlayView.height
  224. * (1 - visual.topAreaProportion - visual.bottomAreaProportion))
  225. anchors {
  226. top: upperAreaLoader.bottom
  227. left: parent.left
  228. right: parent.right
  229. leftMargin: videoPlayView.isFullScreen ?
  230. 0 : (videoPlayView.width * visual.leftAreaProportion)
  231. rightMargin: videoPlayView.isFullScreen ?
  232. 0 : (videoPlayView.width * visual.rightAreaProportion)
  233. }
  234. }
  235. // Overlay controls on top of the video. Also always shown, when in
  236. // landscape and not in full screen video playback mode.
  237. Component {
  238. id: overlayComponent
  239. VideoPlayerControls {
  240. id: videoPlayerControls
  241. timePlayed: videoPlayer ? videoPlayer.timePlayed : 0
  242. timeDuration: videoPlayer ? videoPlayer.duration : 0
  243. isPlaying: videoPlayer ? videoPlayer.isPlaying : false
  244. enableScrubbing: videoPlayView.enableScrubbing
  245. onBackButtonPressed: {
  246. __handleExit();
  247. }
  248. onPausePressed: {
  249. videoPlayer.pause();
  250. }
  251. onPlayPressed: {
  252. videoPlayer.play();
  253. }
  254. onPlaybackPositionChanged: {
  255. videoPlayer.setPosition(playbackPosition);
  256. }
  257. }
  258. }
  259. // Loader for the overlay components, i.e. the VideoPlayerControls.
  260. Loader {
  261. id: overlayLoader
  262. state: "Hidden"
  263. sourceComponent: overlayComponent
  264. // Don't use anchoring here, use y-coordinate instead, so that
  265. // it can be animated.
  266. y: parent.height - visual.controlAreaHeight
  267. width: videoPlayView.width
  268. height: visual.controlAreaHeight
  269. states: [
  270. // Inactive state.
  271. State {
  272. name: "Hidden"
  273. PropertyChanges {
  274. target: overlayLoader
  275. // Move the controls 'beneath' the screen
  276. // and make it completely transparent.
  277. y: videoPlayView.height
  278. opacity: 0.0
  279. }
  280. }
  281. ]
  282. transitions: [
  283. // Transition between active and inactive states.
  284. Transition {
  285. from: ""; to: "Hidden"; reversible: true
  286. ParallelAnimation {
  287. PropertyAnimation {
  288. properties: "opacity"
  289. easing.type: Easing.InOutExpo
  290. duration: visual.animationDurationShort
  291. }
  292. PropertyAnimation {
  293. properties: "y"
  294. duration: visual.animationDurationNormal
  295. }
  296. }
  297. }
  298. ]
  299. }
  300. }