Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(57)

Side by Side Diff: ui/file_manager/video_player/js/video_player.js

Issue 307863004: [Video Player] Re-factoring the code (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Addressed the comments Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/file_manager/video_player/js/background.js ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 'use strict'; 5 'use strict';
6 6
7 /** 7 /**
8 * Displays error message.
9 * @param {string} message Message id.
10 */
11 function showErrorMessage(message) {
12 var errorBanner = document.querySelector('#error');
13 errorBanner.textContent =
14 loadTimeData.getString(message);
15 errorBanner.setAttribute('visible', 'true');
16
17 // The window is hidden if the video has not loaded yet.
18 chrome.app.window.current().show();
19 }
20
21 /**
22 * Handles playback (decoder) errors.
23 */
24 function onPlaybackError() {
25 showErrorMessage('GALLERY_VIDEO_DECODING_ERROR');
26 decodeErrorOccured = true;
27
28 // Disable inactivity watcher, and disable the ui, by hiding tools manually.
29 controls.inactivityWatcher.disabled = true;
30 document.querySelector('#video-player').setAttribute('disabled', 'true');
31
32 // Detach the video element, since it may be unreliable and reset stored
33 // current playback time.
34 controls.cleanup();
35 controls.clearState();
36
37 // Avoid reusing a video element.
38 video.parentNode.removeChild(video);
39 video = null;
40 }
41
42 /**
43 * @param {Element} playerContainer Main container. 8 * @param {Element} playerContainer Main container.
44 * @param {Element} videoContainer Container for the video element. 9 * @param {Element} videoContainer Container for the video element.
45 * @param {Element} controlsContainer Container for video controls. 10 * @param {Element} controlsContainer Container for video controls.
46 * @constructor 11 * @constructor
47 */ 12 */
48 function FullWindowVideoControls( 13 function FullWindowVideoControls(
49 playerContainer, videoContainer, controlsContainer) { 14 playerContainer, videoContainer, controlsContainer) {
50 VideoControls.call(this, 15 VideoControls.call(this,
51 controlsContainer, 16 controlsContainer,
52 onPlaybackError, 17 this.onPlaybackError_.wrap(this),
53 loadTimeData.getString.wrap(loadTimeData), 18 loadTimeData.getString.wrap(loadTimeData),
54 this.toggleFullScreen_.wrap(this), 19 this.toggleFullScreen_.wrap(this),
55 videoContainer); 20 videoContainer);
56 21
57 this.playerContainer_ = playerContainer; 22 this.playerContainer_ = playerContainer;
23 this.decodeErrorOccured = false;
58 24
59 this.updateStyle(); 25 this.updateStyle();
60 window.addEventListener('resize', this.updateStyle.wrap(this)); 26 window.addEventListener('resize', this.updateStyle.wrap(this));
61
62 document.addEventListener('keydown', function(e) { 27 document.addEventListener('keydown', function(e) {
63 if (e.keyIdentifier == 'U+0020') { // Space 28 if (e.keyIdentifier == 'U+0020') { // Space
64 this.togglePlayStateWithFeedback(); 29 this.togglePlayStateWithFeedback();
65 e.preventDefault(); 30 e.preventDefault();
66 } 31 }
67 if (e.keyIdentifier == 'U+001B') { // Escape 32 if (e.keyIdentifier == 'U+001B') { // Escape
68 util.toggleFullScreen( 33 util.toggleFullScreen(
69 chrome.app.window.current(), 34 chrome.app.window.current(),
70 false); // Leave the full screen mode. 35 false); // Leave the full screen mode.
71 e.preventDefault(); 36 e.preventDefault();
(...skipping 15 matching lines...) Expand all
87 this.__defineGetter__('inactivityWatcher', function() { 52 this.__defineGetter__('inactivityWatcher', function() {
88 return this.inactivityWatcher_; 53 return this.inactivityWatcher_;
89 }); 54 });
90 55
91 this.inactivityWatcher_.check(); 56 this.inactivityWatcher_.check();
92 } 57 }
93 58
94 FullWindowVideoControls.prototype = { __proto__: VideoControls.prototype }; 59 FullWindowVideoControls.prototype = { __proto__: VideoControls.prototype };
95 60
96 /** 61 /**
62 * Displays error message.
63 * @param {string} message Message id.
64 * @private
65 */
66 FullWindowVideoControls.prototype.showErrorMessage_ = function(message) {
67 var errorBanner = document.querySelector('#error');
68 errorBanner.textContent =
69 loadTimeData.getString(message);
70 errorBanner.setAttribute('visible', 'true');
71
72 // The window is hidden if the video has not loaded yet.
73 chrome.app.window.current().show();
74 };
75
76 /**
77 * Handles playback (decoder) errors.
78 * @private
79 */
80 FullWindowVideoControls.prototype.onPlaybackError_ = function() {
81 this.showErrorMessage_('GALLERY_VIDEO_DECODING_ERROR');
82 this.decodeErrorOccured = true;
83
84 // Disable inactivity watcher, and disable the ui, by hiding tools manually.
85 this.inactivityWatcher.disabled = true;
86 document.querySelector('#video-player').setAttribute('disabled', 'true');
87
88 // Detach the video element, since it may be unreliable and reset stored
89 // current playback time.
90 this.cleanup();
91 this.clearState();
92
93 // Avoid reusing a video element.
94 player.unloadVideo();
95 };
96
97 /**
97 * Toggles the full screen mode. 98 * Toggles the full screen mode.
98 * @private 99 * @private
99 */ 100 */
100 FullWindowVideoControls.prototype.toggleFullScreen_ = function() { 101 FullWindowVideoControls.prototype.toggleFullScreen_ = function() {
101 var appWindow = chrome.app.window.current(); 102 var appWindow = chrome.app.window.current();
102 util.toggleFullScreen(appWindow, !util.isFullScreen(appWindow)); 103 util.toggleFullScreen(appWindow, !util.isFullScreen(appWindow));
103 }; 104 };
104 105
105 // TODO(mtomasz): Convert it to class members: crbug.com/171191. 106 /**
106 var decodeErrorOccured; 107 * @constructor
107 var video; 108 */
108 var controls; 109 function VideoPlayer() {
110 this.controls_ = null;
111 this.videoElement_ = null;
112 this.videos_ = null;
113
114 Object.seal(this);
115 }
116
117 VideoPlayer.prototype = {
118 get controls() {
119 return this.controls_;
120 }
121 };
109 122
110 /** 123 /**
111 * Initializes the video player window. 124 * Initializes the video player window. This method must be called after DOM
125 * initialization.
126 * @param {Array.<Object.<string, Object>>} videos List of videos.
112 */ 127 */
113 function loadVideoPlayer() { 128 VideoPlayer.prototype.prepare = function(videos) {
114 document.ondragstart = function(e) { e.preventDefault() }; 129 document.ondragstart = function(e) { e.preventDefault() };
115 130
116 chrome.fileBrowserPrivate.getStrings(function(strings) { 131 this.videos_ = videos;
117 loadTimeData.data = strings;
118 132
119 var url = window.videoUrl; 133 this.controls_ = new FullWindowVideoControls(
120 document.title = window.videoTitle; 134 document.querySelector('#video-player'),
135 document.querySelector('#video-container'),
136 document.querySelector('#controls'));
121 137
122 controls = new FullWindowVideoControls( 138 var reloadVideo = function(e) {
123 document.querySelector('#video-player'), 139 if (this.controls_.decodeErrorOccured &&
124 document.querySelector('#video-container'), 140 // Ignore shortcut keys
125 document.querySelector('#controls')); 141 !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
142 this.playVideo();
143 e.preventDefault();
144 }
145 }.wrap(this);
126 146
127 var reloadVideo = function(e) { 147 document.addEventListener('keydown', reloadVideo, true);
128 if (decodeErrorOccured && 148 document.addEventListener('click', reloadVideo, true);
129 // Ignore shortcut keys 149 };
130 !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) {
131 loadVideo(url);
132 e.preventDefault();
133 }
134 };
135
136 loadVideo(url);
137 document.addEventListener('keydown', reloadVideo, true);
138 document.addEventListener('click', reloadVideo, true);
139 });
140 }
141 150
142 /** 151 /**
143 * Unloads the player. 152 * Unloads the player.
144 */ 153 */
145 function unload() { 154 function unload() {
146 if (!controls.getMedia()) 155 if (!player.controls || !player.controls.getMedia())
147 return; 156 return;
148 157
149 controls.savePosition(true /* exiting */); 158 player.controls.savePosition(true /* exiting */);
150 controls.cleanup(); 159 player.controls.cleanup();
151 } 160 }
152 161
153 /** 162 /**
154 * Reloads the player. 163 * Loads the video file.
155 * @param {string} url URL of the video file. 164 * @param {string} url URL of the video file.
165 * @param {string} title Title of the video file.
166 * @param {function(number, number)=} opt_callback Completion callback.
167 * @private
156 */ 168 */
157 function loadVideo(url) { 169 VideoPlayer.prototype.loadVideo_ = function(url, title, opt_callback) {
158 // Re-enable ui and hide error message if already displayed. 170 this.unloadVideo();
171
172 document.title = title;
173
174 // Re-enables ui and hide error message if already displayed.
159 document.querySelector('#video-player').removeAttribute('disabled'); 175 document.querySelector('#video-player').removeAttribute('disabled');
160 document.querySelector('#error').removeAttribute('visible'); 176 document.querySelector('#error').removeAttribute('visible');
161 controls.inactivityWatcher.disabled = false; 177 this.controls.inactivityWatcher.disabled = false;
162 decodeErrorOccured = false; 178 this.controls.decodeErrorOccured = false;
163 179
180 this.videoElement_ = document.createElement('video');
181 document.querySelector('#video-container').appendChild(this.videoElement_);
182 this.controls.attachMedia(this.videoElement_);
183
184 this.videoElement_.src = url;
185 this.videoElement_.load();
186 if (opt_callback)
187 this.videoElement_.addEventListener('loadedmetadata', opt_callback);
188 };
189
190 /**
191 * Plays the video.
192 */
193 VideoPlayer.prototype.playVideo = function() {
194 var currentVideo = this.videos_[0];
195 this.loadVideo_(currentVideo.fileUrl,
196 currentVideo.entry.name,
197 this.onVideoReady_.wrap(this));
198 };
199
200 /**
201 * Unloads the current video.
202 */
203 VideoPlayer.prototype.unloadVideo = function() {
164 // Detach the previous video element, if exists. 204 // Detach the previous video element, if exists.
165 if (video) 205 if (this.videoElement_)
166 video.parentNode.removeChild(video); 206 this.videoElement_.parentNode.removeChild(this.videoElement_);
207 this.videoElement_ = null;
208 };
167 209
168 video = document.createElement('video'); 210 /**
169 document.querySelector('#video-container').appendChild(video); 211 * Called when the video is ready after starting to load.
170 controls.attachMedia(video); 212 * @private
213 */
214 VideoPlayer.prototype.onVideoReady_ = function() {
215 // TODO: chrome.app.window soon will be able to resize the content area.
216 // Until then use approximate title bar height.
217 var TITLE_HEIGHT = 33;
171 218
172 video.src = url; 219 var videoWidth = this.videoElement_.videoWidth;
173 video.load(); 220 var videoHeight = this.videoElement_.videoHeight;
174 video.addEventListener('loadedmetadata', function() {
175 // TODO: chrome.app.window soon will be able to resize the content area.
176 // Until then use approximate title bar height.
177 var TITLE_HEIGHT = 33;
178 221
179 var aspect = video.videoWidth / video.videoHeight; 222 var aspect = videoWidth / videoHeight;
180 var newWidth = video.videoWidth; 223 var newWidth = videoWidth;
181 var newHeight = video.videoHeight + TITLE_HEIGHT; 224 var newHeight = videoHeight + TITLE_HEIGHT;
182 225
183 var shrinkX = newWidth / window.screen.availWidth; 226 var shrinkX = newWidth / window.screen.availWidth;
184 var shrinkY = newHeight / window.screen.availHeight; 227 var shrinkY = newHeight / window.screen.availHeight;
185 if (shrinkX > 1 || shrinkY > 1) { 228 if (shrinkX > 1 || shrinkY > 1) {
186 if (shrinkY > shrinkX) { 229 if (shrinkY > shrinkX) {
187 newHeight = newHeight / shrinkY; 230 newHeight = newHeight / shrinkY;
188 newWidth = (newHeight - TITLE_HEIGHT) * aspect; 231 newWidth = (newHeight - TITLE_HEIGHT) * aspect;
189 } else { 232 } else {
190 newWidth = newWidth / shrinkX; 233 newWidth = newWidth / shrinkX;
191 newHeight = newWidth / aspect + TITLE_HEIGHT; 234 newHeight = newWidth / aspect + TITLE_HEIGHT;
192 }
193 } 235 }
236 }
194 237
195 var oldLeft = window.screenX; 238 var oldLeft = window.screenX;
196 var oldTop = window.screenY; 239 var oldTop = window.screenY;
197 var oldWidth = window.outerWidth; 240 var oldWidth = window.outerWidth;
198 var oldHeight = window.outerHeight; 241 var oldHeight = window.outerHeight;
199 242
200 if (!oldWidth && !oldHeight) { 243 if (!oldWidth && !oldHeight) {
201 oldLeft = window.screen.availWidth / 2; 244 oldLeft = window.screen.availWidth / 2;
202 oldTop = window.screen.availHeight / 2; 245 oldTop = window.screen.availHeight / 2;
203 } 246 }
204 247
205 var appWindow = chrome.app.window.current(); 248 var appWindow = chrome.app.window.current();
206 appWindow.resizeTo(newWidth, newHeight); 249 appWindow.resizeTo(newWidth, newHeight);
207 appWindow.moveTo(oldLeft - (newWidth - oldWidth) / 2, 250 appWindow.moveTo(oldLeft - (newWidth - oldWidth) / 2,
208 oldTop - (newHeight - oldHeight) / 2); 251 oldTop - (newHeight - oldHeight) / 2);
209 appWindow.show(); 252 appWindow.show();
210 253
211 video.play(); 254 this.videoElement_.play();
255 };
256
257 /**
258 * Initialize the list of videos.
259 * @param {function(Array.<Object>)} callback Called with the video list when
260 * it is ready.
261 **/
262 function initVideos(callback) {
263 if (window.videos) {
264 var videos = window.videos;
265 window.videos = null;
266 callback(videos);
267 return;
268 }
269
270 chrome.runtime.onMessage.addListener(
271 function(request, sender, sendResponse) {
272 var videos = window.videos;
273 window.videos = null;
274 callback(videos);
275 });
276 }
277
278 var player = new VideoPlayer();
279
280 /**
281 * Initializes the strings.
282 * @param {function()} callback Called when the sting data is ready.
283 **/
284 function initStrings(callback) {
285 chrome.fileBrowserPrivate.getStrings(function(strings) {
286 loadTimeData.data = strings;
287 callback();
212 }); 288 });
213 } 289 }
214 290
215 util.addPageLoadHandler(loadVideoPlayer); 291 var initPromise = Promise.all(
292 [new Promise(initVideos.wrap(null)),
293 new Promise(initStrings.wrap(null)),
294 new Promise(util.addPageLoadHandler.wrap(null))]);
295
296 initPromise.then(function(results) {
297 var videos = results[0];
298 player.prepare(videos);
299 return new Promise(player.playVideo.wrap(player));
300 });
OLDNEW
« no previous file with comments | « ui/file_manager/video_player/js/background.js ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698