| OLD | NEW |
| 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 /** | 5 /** |
| 6 * @param {!HTMLElement} playerContainer Main container. | 6 * @param {!HTMLElement} playerContainer Main container. |
| 7 * @param {!HTMLElement} videoContainer Container for the video element. | 7 * @param {!HTMLElement} videoContainer Container for the video element. |
| 8 * @param {!HTMLElement} controlsContainer Container for video controls. | 8 * @param {!HTMLElement} controlsContainer Container for video controls. |
| 9 * @constructor | 9 * @constructor |
| 10 * @struct | 10 * @struct |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 FullWindowVideoControls.prototype.getInactivityWatcher = function() { | 107 FullWindowVideoControls.prototype.getInactivityWatcher = function() { |
| 108 return this.inactivityWatcher_; | 108 return this.inactivityWatcher_; |
| 109 }; | 109 }; |
| 110 | 110 |
| 111 /** | 111 /** |
| 112 * Displays error message. | 112 * Displays error message. |
| 113 * | 113 * |
| 114 * @param {string} message Message id. | 114 * @param {string} message Message id. |
| 115 */ | 115 */ |
| 116 FullWindowVideoControls.prototype.showErrorMessage = function(message) { | 116 FullWindowVideoControls.prototype.showErrorMessage = function(message) { |
| 117 var errorBanner = queryRequiredElement(document, '#error'); | 117 var errorBanner = getRequiredElement('error'); |
| 118 errorBanner.textContent = loadTimeData.getString(message); | 118 errorBanner.textContent = loadTimeData.getString(message); |
| 119 errorBanner.setAttribute('visible', 'true'); | 119 errorBanner.setAttribute('visible', 'true'); |
| 120 | 120 |
| 121 // The window is hidden if the video has not loaded yet. | 121 // The window is hidden if the video has not loaded yet. |
| 122 chrome.app.window.current().show(); | 122 chrome.app.window.current().show(); |
| 123 }; | 123 }; |
| 124 | 124 |
| 125 /** | 125 /** |
| 126 * Handles playback (decoder) errors. | 126 * Handles playback (decoder) errors. |
| 127 * @param {MediaError} error Error object. | 127 * @param {MediaError} error Error object. |
| 128 * @private | 128 * @private |
| 129 */ | 129 */ |
| 130 FullWindowVideoControls.prototype.onPlaybackError_ = function(error) { | 130 FullWindowVideoControls.prototype.onPlaybackError_ = function(error) { |
| 131 if (error.target && error.target.error && | 131 if (error.target && error.target.error && |
| 132 error.target.error.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) { | 132 error.target.error.code === MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED) { |
| 133 if (this.casting) | 133 if (this.casting) |
| 134 this.showErrorMessage('VIDEO_PLAYER_VIDEO_FILE_UNSUPPORTED_FOR_CAST'); | 134 this.showErrorMessage('VIDEO_PLAYER_VIDEO_FILE_UNSUPPORTED_FOR_CAST'); |
| 135 else | 135 else |
| 136 this.showErrorMessage('VIDEO_PLAYER_VIDEO_FILE_UNSUPPORTED'); | 136 this.showErrorMessage('VIDEO_PLAYER_VIDEO_FILE_UNSUPPORTED'); |
| 137 this.decodeErrorOccured = false; | 137 this.decodeErrorOccured = false; |
| 138 } else { | 138 } else { |
| 139 this.showErrorMessage('VIDEO_PLAYER_PLAYBACK_ERROR'); | 139 this.showErrorMessage('VIDEO_PLAYER_PLAYBACK_ERROR'); |
| 140 this.decodeErrorOccured = true; | 140 this.decodeErrorOccured = true; |
| 141 } | 141 } |
| 142 | 142 |
| 143 // Disable inactivity watcher, and disable the ui, by hiding tools manually. | 143 // Disable inactivity watcher, and disable the ui, by hiding tools manually. |
| 144 this.getInactivityWatcher().disabled = true; | 144 this.getInactivityWatcher().disabled = true; |
| 145 queryRequiredElement(document, '#video-player') | 145 getRequiredElement('video-player').setAttribute('disabled', 'true'); |
| 146 .setAttribute('disabled', 'true'); | |
| 147 | 146 |
| 148 // Detach the video element, since it may be unreliable and reset stored | 147 // Detach the video element, since it may be unreliable and reset stored |
| 149 // current playback time. | 148 // current playback time. |
| 150 this.cleanup(); | 149 this.cleanup(); |
| 151 this.clearState(); | 150 this.clearState(); |
| 152 | 151 |
| 153 // Avoid reusing a video element. | 152 // Avoid reusing a video element. |
| 154 player.unloadVideo(); | 153 player.unloadVideo(); |
| 155 }; | 154 }; |
| 156 | 155 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 * initialization. | 211 * initialization. |
| 213 * @param {!Array<!FileEntry>} videos List of videos. | 212 * @param {!Array<!FileEntry>} videos List of videos. |
| 214 */ | 213 */ |
| 215 VideoPlayer.prototype.prepare = function(videos) { | 214 VideoPlayer.prototype.prepare = function(videos) { |
| 216 this.videos_ = videos; | 215 this.videos_ = videos; |
| 217 | 216 |
| 218 var preventDefault = function(event) { event.preventDefault(); }.wrap(null); | 217 var preventDefault = function(event) { event.preventDefault(); }.wrap(null); |
| 219 | 218 |
| 220 document.ondragstart = preventDefault; | 219 document.ondragstart = preventDefault; |
| 221 | 220 |
| 222 var maximizeButton = queryRequiredElement(document, '.maximize-button'); | 221 var maximizeButton = queryRequiredElement('.maximize-button'); |
| 223 maximizeButton.addEventListener( | 222 maximizeButton.addEventListener( |
| 224 'click', | 223 'click', |
| 225 function(event) { | 224 function(event) { |
| 226 var appWindow = chrome.app.window.current(); | 225 var appWindow = chrome.app.window.current(); |
| 227 if (appWindow.isMaximized()) | 226 if (appWindow.isMaximized()) |
| 228 appWindow.restore(); | 227 appWindow.restore(); |
| 229 else | 228 else |
| 230 appWindow.maximize(); | 229 appWindow.maximize(); |
| 231 event.stopPropagation(); | 230 event.stopPropagation(); |
| 232 }.wrap(null)); | 231 }.wrap(null)); |
| 233 maximizeButton.addEventListener('mousedown', preventDefault); | 232 maximizeButton.addEventListener('mousedown', preventDefault); |
| 234 | 233 |
| 235 var minimizeButton = queryRequiredElement(document, '.minimize-button'); | 234 var minimizeButton = queryRequiredElement('.minimize-button'); |
| 236 minimizeButton.addEventListener( | 235 minimizeButton.addEventListener( |
| 237 'click', | 236 'click', |
| 238 function(event) { | 237 function(event) { |
| 239 chrome.app.window.current().minimize(); | 238 chrome.app.window.current().minimize(); |
| 240 event.stopPropagation(); | 239 event.stopPropagation(); |
| 241 }.wrap(null)); | 240 }.wrap(null)); |
| 242 minimizeButton.addEventListener('mousedown', preventDefault); | 241 minimizeButton.addEventListener('mousedown', preventDefault); |
| 243 | 242 |
| 244 var closeButton = queryRequiredElement(document, '.close-button'); | 243 var closeButton = queryRequiredElement('.close-button'); |
| 245 closeButton.addEventListener( | 244 closeButton.addEventListener( |
| 246 'click', | 245 'click', |
| 247 function(event) { | 246 function(event) { |
| 248 window.close(); | 247 window.close(); |
| 249 event.stopPropagation(); | 248 event.stopPropagation(); |
| 250 }.wrap(null)); | 249 }.wrap(null)); |
| 251 closeButton.addEventListener('mousedown', preventDefault); | 250 closeButton.addEventListener('mousedown', preventDefault); |
| 252 | 251 |
| 253 var menu = queryRequiredElement(document, '#cast-menu'); | 252 cr.ui.decorate(getRequiredElement('cast-menu'), cr.ui.Menu); |
| 254 cr.ui.decorate(menu, cr.ui.Menu); | |
| 255 | 253 |
| 256 this.controls_ = new FullWindowVideoControls( | 254 this.controls_ = new FullWindowVideoControls( |
| 257 queryRequiredElement(document, '#video-player'), | 255 getRequiredElement('video-player'), |
| 258 queryRequiredElement(document, '#video-container'), | 256 getRequiredElement('video-container'), |
| 259 queryRequiredElement(document, '#controls')); | 257 getRequiredElement('controls')); |
| 260 | 258 |
| 261 var reloadVideo = function(e) { | 259 var reloadVideo = function(e) { |
| 262 if (this.controls_.decodeErrorOccured && | 260 if (this.controls_.decodeErrorOccured && |
| 263 // Ignore shortcut keys | 261 // Ignore shortcut keys |
| 264 !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) { | 262 !e.ctrlKey && !e.altKey && !e.shiftKey && !e.metaKey) { |
| 265 this.reloadCurrentVideo(function() { | 263 this.reloadCurrentVideo(function() { |
| 266 this.videoElement_.play(); | 264 this.videoElement_.play(); |
| 267 }.wrap(this)); | 265 }.wrap(this)); |
| 268 e.preventDefault(); | 266 e.preventDefault(); |
| 269 } | 267 } |
| 270 }.wrap(this); | 268 }.wrap(this); |
| 271 | 269 |
| 272 var arrowRight = queryRequiredElement(document, '.arrow-box .arrow.right'); | 270 var arrowRight = queryRequiredElement('.arrow-box .arrow.right'); |
| 273 arrowRight.addEventListener('click', this.advance_.wrap(this, 1)); | 271 arrowRight.addEventListener('click', this.advance_.wrap(this, 1)); |
| 274 var arrowLeft = queryRequiredElement(document, '.arrow-box .arrow.left'); | 272 var arrowLeft = queryRequiredElement('.arrow-box .arrow.left'); |
| 275 arrowLeft.addEventListener('click', this.advance_.wrap(this, 0)); | 273 arrowLeft.addEventListener('click', this.advance_.wrap(this, 0)); |
| 276 | 274 |
| 277 var videoPlayerElement = queryRequiredElement(document, '#video-player'); | 275 var videoPlayerElement = getRequiredElement('video-player'); |
| 278 if (videos.length > 1) | 276 if (videos.length > 1) |
| 279 videoPlayerElement.setAttribute('multiple', true); | 277 videoPlayerElement.setAttribute('multiple', true); |
| 280 else | 278 else |
| 281 videoPlayerElement.removeAttribute('multiple'); | 279 videoPlayerElement.removeAttribute('multiple'); |
| 282 | 280 |
| 283 document.addEventListener('keydown', reloadVideo); | 281 document.addEventListener('keydown', reloadVideo); |
| 284 document.addEventListener('click', reloadVideo); | 282 document.addEventListener('click', reloadVideo); |
| 285 }; | 283 }; |
| 286 | 284 |
| 287 /** | 285 /** |
| (...skipping 15 matching lines...) Expand all Loading... |
| 303 * @param {!FileEntry} video Entry of the video to be played. | 301 * @param {!FileEntry} video Entry of the video to be played. |
| 304 * @param {function()=} opt_callback Completion callback. | 302 * @param {function()=} opt_callback Completion callback. |
| 305 * @private | 303 * @private |
| 306 */ | 304 */ |
| 307 VideoPlayer.prototype.loadVideo_ = function(video, opt_callback) { | 305 VideoPlayer.prototype.loadVideo_ = function(video, opt_callback) { |
| 308 this.unloadVideo(true); | 306 this.unloadVideo(true); |
| 309 | 307 |
| 310 this.loadQueue_.run(function(callback) { | 308 this.loadQueue_.run(function(callback) { |
| 311 document.title = video.name; | 309 document.title = video.name; |
| 312 | 310 |
| 313 queryRequiredElement(document, '#title').innerText = video.name; | 311 getRequiredElement('title').innerText = video.name; |
| 314 | 312 |
| 315 var videoPlayerElement = queryRequiredElement(document, '#video-player'); | 313 var videoPlayerElement = getRequiredElement('video-player'); |
| 316 if (this.currentPos_ === (this.videos_.length - 1)) | 314 if (this.currentPos_ === (this.videos_.length - 1)) |
| 317 videoPlayerElement.setAttribute('last-video', true); | 315 videoPlayerElement.setAttribute('last-video', true); |
| 318 else | 316 else |
| 319 videoPlayerElement.removeAttribute('last-video'); | 317 videoPlayerElement.removeAttribute('last-video'); |
| 320 | 318 |
| 321 if (this.currentPos_ === 0) | 319 if (this.currentPos_ === 0) |
| 322 videoPlayerElement.setAttribute('first-video', true); | 320 videoPlayerElement.setAttribute('first-video', true); |
| 323 else | 321 else |
| 324 videoPlayerElement.removeAttribute('first-video'); | 322 videoPlayerElement.removeAttribute('first-video'); |
| 325 | 323 |
| 326 // Re-enables ui and hides error message if already displayed. | 324 // Re-enables ui and hides error message if already displayed. |
| 327 queryRequiredElement(document, '#video-player').removeAttribute('disabled'); | 325 getRequiredElement('video-player').removeAttribute('disabled'); |
| 328 queryRequiredElement(document, '#error').removeAttribute('visible'); | 326 getRequiredElement('error').removeAttribute('visible'); |
| 329 this.controls.detachMedia(); | 327 this.controls.detachMedia(); |
| 330 this.controls.getInactivityWatcher().disabled = true; | 328 this.controls.getInactivityWatcher().disabled = true; |
| 331 this.controls.decodeErrorOccured = false; | 329 this.controls.decodeErrorOccured = false; |
| 332 this.controls.casting = !!this.currentCast_; | 330 this.controls.casting = !!this.currentCast_; |
| 333 | 331 |
| 334 videoPlayerElement.setAttribute('loading', true); | 332 videoPlayerElement.setAttribute('loading', true); |
| 335 | 333 |
| 336 var media = new MediaManager(video); | 334 var media = new MediaManager(video); |
| 337 | 335 |
| 338 Promise.all([media.getThumbnail(), media.getToken(false)]) | 336 Promise.all([media.getThumbnail(), media.getToken(false)]) |
| 339 .then(function(results) { | 337 .then(function(results) { |
| 340 var url = results[0]; | 338 var url = results[0]; |
| 341 var token = results[1]; | 339 var token = results[1]; |
| 342 if (url && token) { | 340 if (url && token) { |
| 343 queryRequiredElement(document, '#thumbnail').style.backgroundImage = | 341 getRequiredElement('thumbnail').style.backgroundImage = |
| 344 'url(' + url + '&access_token=' + token + ')'; | 342 'url(' + url + '&access_token=' + token + ')'; |
| 345 } else { | 343 } else { |
| 346 queryRequiredElement(document, '#thumbnail').style.backgroundImage = | 344 getRequiredElement('thumbnail').style.backgroundImage = ''; |
| 347 ''; | |
| 348 } | 345 } |
| 349 }) | 346 }) |
| 350 .catch(function() { | 347 .catch(function() { |
| 351 // Shows no image on error. | 348 // Shows no image on error. |
| 352 queryRequiredElement(document, '#thumbnail').style.backgroundImage = | 349 getRequiredElement('thumbnail').style.backgroundImage = ''; |
| 353 ''; | |
| 354 }); | 350 }); |
| 355 | 351 |
| 356 var videoElementInitializePromise; | 352 var videoElementInitializePromise; |
| 357 if (this.currentCast_) { | 353 if (this.currentCast_) { |
| 358 metrics.recordPlayType(metrics.PLAY_TYPE.CAST); | 354 metrics.recordPlayType(metrics.PLAY_TYPE.CAST); |
| 359 | 355 |
| 360 videoPlayerElement.setAttribute('casting', true); | 356 videoPlayerElement.setAttribute('casting', true); |
| 361 | 357 |
| 362 queryRequiredElement(document, '#cast-name').textContent = | 358 getRequiredElement('cast-name').textContent = |
| 363 this.currentCast_.friendlyName; | 359 this.currentCast_.friendlyName; |
| 364 | 360 |
| 365 videoPlayerElement.setAttribute('castable', true); | 361 videoPlayerElement.setAttribute('castable', true); |
| 366 | 362 |
| 367 videoElementInitializePromise = media.isAvailableForCast() | 363 videoElementInitializePromise = media.isAvailableForCast() |
| 368 .then(function(result) { | 364 .then(function(result) { |
| 369 if (!result) | 365 if (!result) |
| 370 return Promise.reject('No casts are available.'); | 366 return Promise.reject('No casts are available.'); |
| 371 | 367 |
| 372 return new Promise(function(fulfill, reject) { | 368 return new Promise(function(fulfill, reject) { |
| 373 chrome.cast.requestSession( | 369 chrome.cast.requestSession( |
| 374 fulfill, reject, undefined, this.currentCast_.label); | 370 fulfill, reject, undefined, this.currentCast_.label); |
| 375 }.bind(this)).then(function(session) { | 371 }.bind(this)).then(function(session) { |
| 376 session.addUpdateListener(this.onCastSessionUpdateBound_); | 372 session.addUpdateListener(this.onCastSessionUpdateBound_); |
| 377 | 373 |
| 378 this.currentSession_ = session; | 374 this.currentSession_ = session; |
| 379 this.videoElement_ = new CastVideoElement(media, session); | 375 this.videoElement_ = new CastVideoElement(media, session); |
| 380 this.controls.attachMedia(this.videoElement_); | 376 this.controls.attachMedia(this.videoElement_); |
| 381 }.bind(this)); | 377 }.bind(this)); |
| 382 }.bind(this)); | 378 }.bind(this)); |
| 383 } else { | 379 } else { |
| 384 metrics.recordPlayType(metrics.PLAY_TYPE.LOCAL); | 380 metrics.recordPlayType(metrics.PLAY_TYPE.LOCAL); |
| 385 videoPlayerElement.removeAttribute('casting'); | 381 videoPlayerElement.removeAttribute('casting'); |
| 386 | 382 |
| 387 this.videoElement_ = document.createElement('video'); | 383 this.videoElement_ = document.createElement('video'); |
| 388 queryRequiredElement(document, '#video-container').appendChild( | 384 getRequiredElement('video-container').appendChild(this.videoElement_); |
| 389 this.videoElement_); | |
| 390 | 385 |
| 391 this.controls.attachMedia(this.videoElement_); | 386 this.controls.attachMedia(this.videoElement_); |
| 392 this.videoElement_.src = video.toURL(); | 387 this.videoElement_.src = video.toURL(); |
| 393 | 388 |
| 394 media.isAvailableForCast().then(function(result) { | 389 media.isAvailableForCast().then(function(result) { |
| 395 if (result) | 390 if (result) |
| 396 videoPlayerElement.setAttribute('castable', true); | 391 videoPlayerElement.setAttribute('castable', true); |
| 397 else | 392 else |
| 398 videoPlayerElement.removeAttribute('castable'); | 393 videoPlayerElement.removeAttribute('castable'); |
| 399 }).catch(function() { | 394 }).catch(function() { |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 571 this.reloadCurrentVideo(); | 566 this.reloadCurrentVideo(); |
| 572 callback(); | 567 callback(); |
| 573 }.wrap(this)); | 568 }.wrap(this)); |
| 574 }; | 569 }; |
| 575 | 570 |
| 576 /** | 571 /** |
| 577 * Set the list of casts. | 572 * Set the list of casts. |
| 578 * @param {Array<Object>} casts List of casts. | 573 * @param {Array<Object>} casts List of casts. |
| 579 */ | 574 */ |
| 580 VideoPlayer.prototype.setCastList = function(casts) { | 575 VideoPlayer.prototype.setCastList = function(casts) { |
| 581 var videoPlayerElement = queryRequiredElement(document, '#video-player'); | 576 var videoPlayerElement = getRequiredElement('video-player'); |
| 582 var menu = queryRequiredElement(document, '#cast-menu'); | 577 var menu = getRequiredElement('cast-menu'); |
| 583 menu.innerHTML = ''; | 578 menu.innerHTML = ''; |
| 584 | 579 |
| 585 // TODO(yoshiki): Handle the case that the current cast disappears. | 580 // TODO(yoshiki): Handle the case that the current cast disappears. |
| 586 | 581 |
| 587 if (casts.length === 0) { | 582 if (casts.length === 0) { |
| 588 videoPlayerElement.removeAttribute('cast-available'); | 583 videoPlayerElement.removeAttribute('cast-available'); |
| 589 if (this.currentCast_) | 584 if (this.currentCast_) |
| 590 this.onCurrentCastDisappear_(); | 585 this.onCurrentCastDisappear_(); |
| 591 return; | 586 return; |
| 592 } | 587 } |
| (...skipping 25 matching lines...) Expand all Loading... |
| 618 } | 613 } |
| 619 this.updateCheckOnCastMenu_(); | 614 this.updateCheckOnCastMenu_(); |
| 620 videoPlayerElement.setAttribute('cast-available', true); | 615 videoPlayerElement.setAttribute('cast-available', true); |
| 621 }; | 616 }; |
| 622 | 617 |
| 623 /** | 618 /** |
| 624 * Updates the check status of the cast menu items. | 619 * Updates the check status of the cast menu items. |
| 625 * @private | 620 * @private |
| 626 */ | 621 */ |
| 627 VideoPlayer.prototype.updateCheckOnCastMenu_ = function() { | 622 VideoPlayer.prototype.updateCheckOnCastMenu_ = function() { |
| 628 var menu = queryRequiredElement(document, '#cast-menu'); | 623 var menuItems = getRequiredElement('cast-menu').menuItems; |
| 629 var menuItems = menu.menuItems; | |
| 630 for (var i = 0; i < menuItems.length; i++) { | 624 for (var i = 0; i < menuItems.length; i++) { |
| 631 var item = menuItems[i]; | 625 var item = menuItems[i]; |
| 632 if (this.currentCast_ === null) { | 626 if (this.currentCast_ === null) { |
| 633 // Playing on this computer. | 627 // Playing on this computer. |
| 634 if (item.castLabel === '') | 628 if (item.castLabel === '') |
| 635 item.checked = true; | 629 item.checked = true; |
| 636 else | 630 else |
| 637 item.checked = false; | 631 item.checked = false; |
| 638 } else { | 632 } else { |
| 639 // Playing on cast device. | 633 // Playing on cast device. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 698 return new Promise(function(fulfill, reject) { | 692 return new Promise(function(fulfill, reject) { |
| 699 util.URLsToEntries(window.appState.items, function(entries) { | 693 util.URLsToEntries(window.appState.items, function(entries) { |
| 700 metrics.recordOpenVideoPlayerAction(); | 694 metrics.recordOpenVideoPlayerAction(); |
| 701 metrics.recordNumberOfOpenedFiles(entries.length); | 695 metrics.recordNumberOfOpenedFiles(entries.length); |
| 702 | 696 |
| 703 player.prepare(entries); | 697 player.prepare(entries); |
| 704 player.playFirstVideo(player, fulfill); | 698 player.playFirstVideo(player, fulfill); |
| 705 }.wrap()); | 699 }.wrap()); |
| 706 }.wrap()); | 700 }.wrap()); |
| 707 }.wrap()); | 701 }.wrap()); |
| OLD | NEW |