From b89a7ee8b956c96a1dcee995ea840feddc5d4b27 Mon Sep 17 00:00:00 2001 From: Pierre Frisch Date: Thu, 22 Dec 2011 07:25:50 -0800 Subject: First commit of Ninja to ninja-internal Signed-off-by: Valerio Virgillito --- .../montage/ui/controller/media-controller.js | 698 +++++++++++++++++++++ 1 file changed, 698 insertions(+) create mode 100755 node_modules/montage/ui/controller/media-controller.js (limited to 'node_modules/montage/ui/controller/media-controller.js') diff --git a/node_modules/montage/ui/controller/media-controller.js b/node_modules/montage/ui/controller/media-controller.js new file mode 100755 index 00000000..0663a526 --- /dev/null +++ b/node_modules/montage/ui/controller/media-controller.js @@ -0,0 +1,698 @@ +/* + This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ +/** + @module montage/ui/controller/media-controller + @requires montage/core/core + @requires montage/ui/component + @requires core/logger +*/ +var Montage = require("montage").Montage; +var Component = require("ui/component").Component; +var logger = require("core/logger").logger("mediacontroller"); +/** + @class module:montage/ui/controller/media-controller.MediaController + @classdesc Controls an audio/video media player. + @extends module:montage/core/core.Montage + + */ +var MediaController = exports.MediaController = Montage.create(Montage, /** @lends module:montage/ui/controller/media-controller.MediaController# */ { + /*----------------------------------------------------------------------------- + MARK: Constants + -----------------------------------------------------------------------------*/ + /** + Description TODO + @type {Property} + @default {Number} 0 + */ + STOPPED: { enumerable: true, value: 0, writable: false }, + /** + Description TODO + @type {Property} + @default {Number} 1 + */ + PLAYING: { enumerable: true, value: 1, writable: false }, + /** + Description TODO + @type {Property} + @default {Number} 2 + */ + PAUSED: { enumerable: true, value: 2, writable: false }, + /** + Description TODO + @type {Property} + @default {Number} 3 + */ + EMPTY: { enumerable: true, value: 3, writable: false }, +/** + Description TODO + @private +*/ + _TIMEUPDATE_FREQUENCY: { value: 0.25 }, // Don't refresh too often. + /*----------------------------------------------------------------------------- + MARK: Properties + -----------------------------------------------------------------------------*/ +/** + Description TODO + @private +*/ + _mediaElement: { + value: null, + enumerable: false + }, + /** + Description TODO + @type {Function} + @default null + */ + mediaElement: { + get : function() { + return this._mediaElement; + }, + set : function(elem) { + this._mediaElement = elem; + }, + enumerable: false + }, +/** + Description TODO + @private +*/ + _mediaSrc: { + value: null, + enumerable: false + }, +/** + Description TODO + @type {Function} + @default null + */ + mediaSrc: { + get: function() { + return this._mediaSrc; + }, + set: function(mediaSrc) { + this._mediaSrc = mediaSrc; + } + }, + /*----------------------------------------------------------------------------- + MARK: Status & Attributes + -----------------------------------------------------------------------------*/ +/** + Description TODO + @private +*/ + _status: { + enumerable: false, + value: 3 + }, + /** + Description TODO + @type {Function} + @default {Number} 3 + */ + status: { + enumerable: false, + get: function() { + return this._status; + }, + set: function(status) { + if (status !== this._status) { + this._status = status; + this._dispatchStateChangeEvent(); + } + } + }, +/** + Description TODO + @private +*/ + _position: { value:null, enumerable:false }, + +/** + Description TODO + @type {Function} + @default null + */ + position: { + set: function(time, shouldNotUpdate) { + this._position = time; + if (!shouldNotUpdate) { + this.currentTime = time; + } + }, + get: function() { + return this._position; + } + }, +/** + Description TODO + @private +*/ + _duration: { value: null, enumerable:false }, +/** + Description TODO + @type {Function} + @default null + */ + duration: { + set: function(time) { + if (isNaN(time)) { + if (logger.isDebug) { + logger.debug("MediaController:setDuration: duration is not valid"); + } + return; + } + if (logger.isDebug) { + logger.debug("MediaController:setDuration: duration=" + time); + } + this._duration = time; + }, + get: function() { + return this._duration; + } + }, + /*----------------------------------------------------------------------------- + MARK: Media Player Commands + -----------------------------------------------------------------------------*/ +/** + Description TODO + @type {Property} + @default {Boolean} true + */ + autoplay: { + enumerable: false, + value: true + }, +/** + Description TODO + @function + */ + play: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:play()"); + } + this.mediaElement.play(); + } + }, +/** + Description TODO + @function + */ + pause: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:pause()"); + } + this.mediaElement.pause(); + } + }, +/** + Description TODO + @function + @returns {Boolean} !playing (true if it is now playing) + */ + playPause: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:playPause"); + } + + var playing = (this.status === this.PLAYING); + this.playbackRate = this.mediaElement.defaultPlaybackRate; + if (playing) { + this.pause(); + } else { + this.play(); + } + return !playing; // true if it is now playing + } + }, +/** + Description TODO + @private +*/ + _playbackRate: { + value: 1, + enumerable: false + }, +/** + Description TODO + @type {Function} + @default {Number} 1 + */ + playbackRate: { + get: function() { + return this._playbackRate; + }, + set: function(playbackRate) { + if (this._playbackRate !== playbackRate) { + this._playbackRate = playbackRate; + this.mediaElement.playbackRate = this._playbackRate; + } + } + }, +/** + Description TODO + @private +*/ + _currentTime: { + value: 0, + enumerable: false + }, +/** + Description TODO + @private +*/ + _updateCurrentTime: { + value: false, + enumerable: false + }, +/** + Description TODO + @type {Function} + @default {Number} 0 + */ + currentTime: { + get: function() { + return this.mediaElement.currentTime; + }, + + set: function(currentTime) { + try { + if (isNaN(this.mediaElement.duration)) { + logger.error("MediaController:set currentTime: duration is not valid"); + return; + } + if (logger.isDebug) { + logger.debug("current time:" + this.mediaElement.currentTime + " new time is" + currentTime); + } + this.mediaElement.currentTime = currentTime; + } + catch(err) { + logger.error("MediaController:Exception in set currentTime" + this.mediaElement.currentTime); + } + } + }, +/** + Description TODO + @function + */ + rewind: { + value: function() { + if (this.status === this.PLAYING) { + if (logger.isDebug) { + logger.debug("MediaController:rewind"); + } + this.playbackRate = -4.0; + } + } + }, +/** + Description TODO + @function + */ + fastForward: { + value: function() { + if (this.status === this.PLAYING) { + if (logger.isDebug) { + logger.debug("MediaController:fastForward"); + } + this.playbackRate = 4.0; + } + } + }, +/** + Description TODO + @function + */ + stop: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:stop"); + } + + // Pause the playback + if (this.status === this.PLAYING) { + if (logger.isDebug) { + logger.debug("MediaController:stop while PLAYING: will pause"); + } + this.pause(); + } + + // Reset the status + this.status = this.STOPPED; + } + }, +/** + Description TODO + @function + */ + reset: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:reset"); + } + if (this.status !== this.STOPPED) { + this.stop(); + } + + // Clear the movie + this.mediaElement.removeAttribute('src'); + } + }, +/** + Description TODO + @function + */ + loadMedia: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:loadMedia"); + } + + this.mediaElement.src = this.mediaSrc; + this.mediaElement.load(); + } + }, +/** + Description TODO + @function + */ + toggleRepeat: { + value: function() { + this.repeat = !this.repeat; + } + }, +/** + Description TODO + @private +*/ + _repeat: { + value: false, + enumerable: false + }, +/** + Description TODO + @type {Function} + @default {Boolean} false + */ + repeat: { + get: function() { + return this._repeat; + }, + + set: function(repeat) { + if (repeat !== this._repeat) { + this._repeat = repeat; + if (repeat) { + this.mediaElement.setAttribute("loop", "true"); + } else { + this.mediaElement.removeAttribute("loop"); + } + this._dispatchStateChangeEvent(); + } + } + }, + /*----------------------------------------------------------------------------- + MARK: Volume Commands + -----------------------------------------------------------------------------*/ +/** + Description TODO + @type {Function} + @returns {Number} this.mediaElement.volume * 100 + */ + volume: { + get: function() { + return this.mediaElement.volume * 100; + }, + + set: function(vol) { + var volume = vol; + if (typeof volume === 'undefined') { + volume = 50; + } + else if (volume > 100) { + volume = 100; + } + else if (volume < 0) { + volume = 0; + } + this.mediaElement.volume = volume / 100.0; + this._dispatchStateChangeEvent(); + } + }, +/** + Description TODO + @function + */ + volumeIncrease: { + value: function() { + this.volume += 10; + } + }, +/** + Description TODO + @function + */ + volumeDecrease: { + value: function() { + this.volume -= 10; + } + }, +/** + Description TODO + @function + */ + toggleMute: { + value: function() { + this.mute = !this.mute; + } + }, +/** + Description TODO + @type {Function} + */ + mute: { + get: function() { + return this.mediaElement.muted; + }, + + set: function(muted) { + if (muted !== this.mediaElement.muted) { + this.mediaElement.muted = muted; + } + } + }, + /*----------------------------------------------------------------------------- + MARK: Event Handlers + -----------------------------------------------------------------------------*/ +/** + Description TODO + @function + @returns itself + */ + handleLoadedmetadata: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:handleLoadedmetadata: PLAYING=" + (this.status === this.PLAYING) + " duration=" + this.mediaElement.duration); + } + if (isNaN(this.mediaElement.duration)) { + if (logger.isDebug) { + logger.debug("MediaController:handleLoadedmetadata: duration is not valid"); + } + return; + } + this.duration = this.mediaElement.duration; + if (this.autoplay) { + this.play(); + } else { + this.status = this.PAUSED; + } + } + }, +/** + Description TODO + @private +*/ + _lastCurrentTime: { + writable: true, + value: 0 + }, +/** + Description TODO + @function + */ + handleTimeupdate: { + value: function() { + if (this.status !== this.STOPPED) { // A last 'timeupdate' is sent after stop() which is unwanted because it restores the last position. + var currentTime = this.mediaElement.currentTime; + if (Math.abs(this._lastCurrentTime - currentTime) >= this._TIMEUPDATE_FREQUENCY) { + this._lastCurrentTime = currentTime; + Object.getPropertyDescriptor(this, "position").set.call(this, currentTime, true); + } + } + } + }, + +/** + Description TODO + @function + */ + handlePlay: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:Play"); + } + this.status = this.PLAYING; + } + }, +/** + Description TODO + @function + */ + handlePlaying: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:handlePlaying: PLAYING"); + } + this.status = this.PLAYING; + } + }, +/** + Description TODO + @function + */ + handlePause: { + value: function() { + if (this.status !== this.STOPPED) { + if (logger.isDebug) { + logger.debug("MediaController:handlePause: PAUSED"); + } + this.status = this.PAUSED; + } + else { + if (logger.isDebug) { + logger.debug("MediaController:handlePause: STOPPED"); + } + } + } + }, +/** + Description TODO + @function + */ + handleEnded: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:handleEnded"); + } + this.status = this.STOPPED; + // If the mediaElement is not in the paused=true state + // then it won't fire a play event when you start playing again + this.mediaElement.pause(); + } + }, +/** + Description TODO + @function + */ + handleAbort: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:handleAbort: STOPPED"); + } + this.status = this.STOPPED; + } + }, +/** + Description TODO + @function + @param {Event} event TODO + */ + handleError: { + value: function(event) { + if (logger.isDebug) { + logger.debug("MediaController:handleError: STOPPED"); + } + var error = event.target.error; + + this.status = this.STOPPED; + + if (error) { + switch (error.code) { + case error.MEDIA_ERR_ABORTED: + alert("You aborted the video playback."); + break; + case error.MEDIA_ERR_NETWORK: + alert("A network error caused the video download to fail part-way."); + break; + case error.MEDIA_ERR_DECODE: + alert("The video playback was aborted due to a corruption problem or because the video used features your browser did not support."); + break; + case error.MEDIA_ERR_SRC_NOT_SUPPORTED: + if (this.mediaElement.src.length > 0) { + alert("The video at " + this.mediaElement.src + " could not be loaded, either because the server or network failed or because the format is not supported."); + } + else { + alert("No video has been selected."); + } + break; + default: + alert("An unknown error occurred."); + break; + } + } + this._isFullScreen = false; + } + }, +/** + Description TODO + @function + */ + handleEmptied: { + value: function() { + if (logger.isDebug) { + logger.debug("MediaController:handleEmptied: STOPPED"); + } + this.status = this.STOPPED; + } + }, +/** + Description TODO + @private +*/ + _dispatchStateChangeEvent: { + value: function() { + var stateEvent = window.document.createEvent("CustomEvent"); + stateEvent.initCustomEvent("mediaStateChange", true, true, null); + this.dispatchEvent(stateEvent); + } + }, +/** + Description TODO + @private +*/ + _installControlEventHandlers: { + value: function() { + this.mediaElement.addEventListener('loadedmetadata', this, false); + this.mediaElement.addEventListener('timeupdate', this, false); + this.mediaElement.addEventListener('play', this, false); + this.mediaElement.addEventListener('playing', this, false); + this.mediaElement.addEventListener('pause', this, false); + this.mediaElement.addEventListener('abort', this, false); + this.mediaElement.addEventListener('error', this, false); + this.mediaElement.addEventListener('emptied', this, false); + this.mediaElement.addEventListener('ended', this, false); + }, + enumerable: false + } + /*----------------------------------------------------------------------------- + MARK: Configuration + -----------------------------------------------------------------------------*/ + + +}); -- cgit v1.2.3