blob: cb7bfd755142889c80f2e950951acf66def10cc6 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';
/**
* Display error message.
* @param {string} message Message id.
*/
function showErrorMessage(message) {
var errorBanner = document.querySelector('#error');
errorBanner.textContent =
loadTimeData.getString(message);
errorBanner.setAttribute('visible', 'true');
// The window is hidden if the video has not loaded yet.
chrome.app.window.current().show();
}
/**
* Handles playback (decoder) errors.
*/
function onPlaybackError() {
showErrorMessage('GALLERY_VIDEO_DECODING_ERROR');
decodeErrorOccured = true;
// Disable inactivity watcher, and disable the ui, by hiding tools manually.
controls.inactivityWatcher.disabled = true;
document.querySelector('#video-player').setAttribute('disabled', 'true');
// Detach the video element, since it may be unreliable and reset stored
// current playback time.
controls.cleanup();
controls.clearState();
// Avoid reusing a video element.
video.parentNode.removeChild(video);
video = null;
}
/**
* @param {Element} playerContainer Main container.
* @param {Element} videoContainer Container for the video element.
* @param {Element} controlsContainer Container for video controls.
* @constructor
*/
function FullWindowVideoControls(
playerContainer, videoContainer, controlsContainer) {
VideoControls.call(this,
controlsContainer,
onPlaybackError,
loadTimeData.getString.bind(loadTimeData),
this.toggleFullScreen_.bind(this),
videoContainer);
this.playerContainer_ = playerContainer;
this.updateStyle();
window.addEventListener('resize', this.updateStyle.bind(this));
document.addEventListener('keydown', function(e) {
if (e.keyIdentifier == 'U+0020') { // Space
this.togglePlayStateWithFeedback();
e.preventDefault();
}
if (e.keyIdentifier == 'U+001B') { // Escape
util.toggleFullScreen(
chrome.app.window.current(),
false); // Leave the full screen mode.
e.preventDefault();
}
}.bind(this));
// TODO(mtomasz): Simplify. crbug.com/254318.
videoContainer.addEventListener('click', function(e) {
if (e.ctrlKey) {
this.toggleLoopedModeWithFeedback(true);
if (!this.isPlaying())
this.togglePlayStateWithFeedback();
} else {
this.togglePlayStateWithFeedback();
}
}.bind(this));
this.inactivityWatcher_ = new MouseInactivityWatcher(playerContainer);
this.__defineGetter__('inactivityWatcher', function() {
return this.inactivityWatcher_;
});
this.inactivityWatcher_.check();
}
FullWindowVideoControls.prototype = { __proto__: VideoControls.prototype };
/**
* Save the current state so that it survives page/app reload.
*/
FullWindowVideoControls.prototype.onPlayStateChanged = function() {
this.encodeState();
};
/**
* Restore the state after the video is loaded.
*/
FullWindowVideoControls.prototype.restorePlayState = function() {
if (!this.decodeState()) {
VideoControls.prototype.restorePlayState.apply(this, arguments);
this.play();
}
};
/**
* Toggles the full screen mode.
* @private
*/
FullWindowVideoControls.prototype.toggleFullScreen_ = function() {
var appWindow = chrome.app.window.current();
util.toggleFullScreen(appWindow, !util.isFullScreen(appWindow));
};
// TODO(mtomasz): Convert it to class members: crbug.com/171191.
var decodeErrorOccured;
var video;
var controls;
var metadataCache;
var volumeManager;
var selectedItemFilesystemPath;
/**
* Initialize the video player window.
*/
function loadVideoPlayer() {
document.ondragstart = function(e) { e.preventDefault() };
chrome.fileBrowserPrivate.getStrings(function(strings) {
VolumeManager.getInstance(function(inVolumeManager) {
loadTimeData.data = strings;
controls = new FullWindowVideoControls(
document.querySelector('#video-player'),
document.querySelector('#video-container'),
document.querySelector('#controls'));
metadataCache = MetadataCache.createFull();
volumeManager = inVolumeManager;
volumeManager.addEventListener('externally-unmounted',
onExternallyUnmounted);
// If the video player is starting before the first instance of the File
// Manager then it does not have access to filesystem URLs.
// Request it now.
chrome.fileBrowserPrivate.requestFileSystem('compatible', reload);
var reloadVideo = function(e) {
if (decodeErrorOccured) {
reload();
e.preventDefault();
}
};
document.addEventListener('keydown', reloadVideo, true);
document.addEventListener('click', reloadVideo, true);
});
});
}
/**
* Closes video player when a volume containing the played item is unmounted.
* @param {Event} event The unmount event.
*/
function onExternallyUnmounted(event) {
if (!selectedItemFilesystemPath)
return;
if (selectedItemFilesystemPath.indexOf(event.mountPath) == 0)
window.close();
}
/**
* Unload the player.
*/
function unload() {
if (!controls.getMedia())
return;
controls.savePosition(true /* exiting */);
controls.cleanup();
}
/**
* Reload the player.
*/
function reload() {
// Re-enable ui and hide error message if already displayed.
document.querySelector('#video-player').removeAttribute('disabled');
document.querySelector('#error').removeAttribute('visible');
controls.inactivityWatcher.disabled = false;
decodeErrorOccured = false;
var src;
if (window.appState) {
util.saveAppState();
src = window.appState.url;
} else {
src = document.location.search.substr(1);
}
if (!src) {
showErrorMessage('GALLERY_VIDEO_ERROR');
return;
}
document.title = decodeURIComponent(src.split('/').pop());
metadataCache.get(src, 'streaming', function(streaming) {
if (streaming && !navigator.onLine) {
showErrorMessage('GALLERY_VIDEO_OFFLINE');
return;
}
// Detach the previous video element, if exists.
if (video)
video.parentNode.removeChild(video);
video = document.createElement('video');
document.querySelector('#video-container').appendChild(video);
controls.attachMedia(video);
video.src = src;
video.load();
video.addEventListener('loadedmetadata', function() {
// TODO: chrome.app.window soon will be able to resize the content area.
// Until then use approximate title bar height.
var TITLE_HEIGHT = 28;
var aspect = video.videoWidth / video.videoHeight;
var newWidth = video.videoWidth;
var newHeight = video.videoHeight + TITLE_HEIGHT;
var shrinkX = newWidth / window.screen.availWidth;
var shrinkY = newHeight / window.screen.availHeight;
if (shrinkX > 1 || shrinkY > 1) {
if (shrinkY > shrinkX) {
newHeight = newHeight / shrinkY;
newWidth = (newHeight - TITLE_HEIGHT) * aspect;
} else {
newWidth = newWidth / shrinkX;
newHeight = newWidth / aspect + TITLE_HEIGHT;
}
}
var oldLeft = window.screenX;
var oldTop = window.screenY;
var oldWidth = window.outerWidth;
var oldHeight = window.outerHeight;
if (!oldWidth && !oldHeight) {
oldLeft = window.screen.availWidth / 2;
oldTop = window.screen.availHeight / 2;
}
var appWindow = chrome.app.window.current();
appWindow.resizeTo(newWidth, newHeight);
appWindow.moveTo(oldLeft - (newWidth - oldWidth) / 2,
oldTop - (newHeight - oldHeight) / 2);
appWindow.show();
});
// Resolve real filesystem path of the current video.
selectedItemFilesystemPath = null;
webkitResolveLocalFileSystemURL(src,
function(entry) {
if (video && video.src != src) return;
selectedItemFilesystemPath = entry.fullPath;
});
});
}
util.addPageLoadHandler(loadVideoPlayer);