UNPKG

ares-ide

Version:

A browser-based code editor and UI designer for Enyo 2 projects

518 lines (475 loc) 13.6 kB
/** _enyo.Video_ is a control that allows you to play video. It is an abstraction of HTML 5 Video. Initialize a video component as follows: {kind: "Video", src: "http://www.w3schools.com/html/movie.mp4"} To play a video, call `this.$.video.play()`. To get a reference to the actual HTML 5 Video element, call `this.$.video.hasNode()`. */ enyo.kind({ name: "enyo.Video", kind: enyo.Control, published: { //* Source URL of the video file; may be relative to the application's HTML file src: "", //* Lets you specify multiple sources for the same video file sourceComponents: null, //* Source of image file to show when video isn't available poster: "", //* If true, controls for starting and stopping the video player are shown showControls: false, /** Determines how (or if) the video object is preloaded. Possible values: * "auto": Preload the video data as soon as possible. * "metadata": Preload only the video metadata. * "none": Do not preload any video data. */ preload: "metadata", //* If true, video will automatically start playing autoplay: false, /** If true, when playback is finished, video player will restart from the beginning */ loop: false, //* If true, video is stretched to fill the entire window (webOS only). fitToWindow: false, //* Video aspect ratio expressed as _width: height_ aspectRatio: null, //* Number of seconds to jump forward or backward jumpSec: 30, //* Video playback rate playbackRate: 1, //* Mapping of playback rate names to playback rate values playbackRateHash: { fastForward: ["2", "4", "8", "16"], rewind: ["-2", "-4", "-8", "-16"], slowForward: ["1/4", "1/2", "1"], slowRewind: ["-1/2", "-1"] } }, events: { //* Fires when _playbackRate_ is changed to an integer greater than 1. onFastforward: "", //* Fires when _playbackRate_ is changed to a value between 0 and 1. onSlowforward: "", //* Fires when _playbackRate_ is changed to an integer less than -1. onRewind: "", /** Fires when _playbackRate_ is changed to a value less than 0 but greater than or equal to -1. */ onSlowrewind: "", //* Fires when _jumpForward()_ is called. onJumpForward: "", //* Fires when _jumpBackward()_ is called. onJumpBackward: "", //* Fires when _playbackRate_ is set to 1. onPlay: "", //* Fires when EventData is changed. onStart: "" }, handlers: { //* Catch video _loadedmetadata_ event onloadedmetadata: "metadataLoaded", ontimeupdate: "timeupdate", onratechange: "ratechange", onplay: "_play" }, tag: "video", //* @protected _playbackRateArray: null, _speedIndex: 0, create: function() { this.inherited(arguments); this.posterChanged(); this.showControlsChanged(); this.preloadChanged(); this.autoplayChanged(); this.loopChanged(); }, rendered: function() { this.inherited(arguments); this.hookupVideoEvents(); }, posterChanged: function() { if (this.poster) { var path = enyo.path.rewrite(this.poster); this.setAttribute("poster", path); } else { this.setAttribute("poster", null); } }, showControlsChanged: function() { this.setAttribute("controls", this.showControls ? "controls" : null); }, preloadChanged: function() { this.setAttribute("preload", this.preload ? this.preload : null); }, autoplayChanged: function() { this.setAttribute("autoplay", this.autoplay ? "autoplay" : null); this._prevCommand = this.autoplay ? "play" : "pause"; }, loopChanged: function() { this.setAttribute("loop", this.loop ? "loop" : null); }, fitToWindowChanged: function() { if (!this.hasNode()) { return; } }, srcChanged: function() { // We override the inherited method from enyo.Control because // it prevents us from setting src to a falsy value. this.setAttribute("src", enyo.path.rewrite(this.src)); }, //* @public load: function() { if(this.hasNode()) { this.hasNode().load(); } }, //* Unloads the current video source, stopping all playback and buffering. unload: function() { this.set("src", ""); this.load(); }, //* Initiates playback of the media data. play: function() { if (!this.hasNode()) { return; } this._speedIndex = 0; this.setPlaybackRate(1); this.node.play(); this._prevCommand = "play"; }, //* Pauses media playback. pause: function() { if (!this.hasNode()) { return; } this._speedIndex = 0; this.setPlaybackRate(1); this.node.pause(); this._prevCommand = "pause"; }, //* Changes the playback speed via _this.selectPlaybackRate()_. fastForward: function() { var node = this.hasNode(); if (!node) { return; } switch (this._prevCommand) { case "slowForward": if (this._speedIndex == this._playbackRateArray.length - 1) { // reached to the end of array => go to fastforward this.selectPlaybackRateArray("fastForward"); this._speedIndex = 0; this._prevCommand = "fastForward"; } else { this._speedIndex = this.clampPlaybackRate(this._speedIndex+1); this._prevCommand = "slowForward"; } break; case "pause": this.selectPlaybackRateArray("slowForward"); this._speedIndex = 0; if (this.isPaused()) { node.play(); } this._prevCommand = "slowForward"; break; case "rewind": var pbNumber = this.calcNumberValueOfPlaybackRate(this.playbackRate); if (pbNumber < 0) { this.selectPlaybackRateArray("slowForward"); this._prevCommand = "slowForward"; } else { this.selectPlaybackRateArray("fastForward"); this._prevCommand = "fastForward"; } this._speedIndex = 0; break; case "fastForward": this._speedIndex = this.clampPlaybackRate(this._speedIndex+1); this._prevCommand = "fastForward"; break; default: this.selectPlaybackRateArray("fastForward"); this._speedIndex = 0; this._prevCommand = "fastForward"; break; } this.setPlaybackRate(this.selectPlaybackRate(this._speedIndex)); }, //* Changes the playback speed via _this.selectPlaybackRate()_. rewind: function() { var node = this.hasNode(); if (!node) { return; } switch (this._prevCommand) { case "slowRewind": if (this._speedIndex == this._playbackRateArray.length - 1) { // reached to the end of array => go to rewind this.selectPlaybackRateArray("rewind"); this._speedIndex = 0; this._prevCommand = "rewind"; } else { this._speedIndex = this.clampPlaybackRate(this._speedIndex+1); this._prevCommand = "slowRewind"; } break; case "pause": this.selectPlaybackRateArray("slowRewind"); this._speedIndex = 0; if (this.isPaused() && this.node.duration > this.node.currentTime) { node.play(); } this._prevCommand = "slowRewind"; break; case "rewind": this._speedIndex = this.clampPlaybackRate(this._speedIndex+1); this._prevCommand = "rewind"; break; default: this.selectPlaybackRateArray("rewind"); this._speedIndex = 0; this._prevCommand = "rewind"; break; } this.setPlaybackRate(this.selectPlaybackRate(this._speedIndex)); }, //* Jumps backward _jumpSec_ seconds from the current time. jumpBackward: function() { var node = this.hasNode(); if (!node) { return; } this.setPlaybackRate(1); node.currentTime -= this.jumpSec; this._prevCommand = "jumpBackward"; this.doJumpBackward(enyo.mixin(this.createEventData(), {jumpSize: this.jumpSec})); }, //* Jumps forward _jumpSec_ seconds from the current time. jumpForward: function() { var node = this.hasNode(); if (!node) { return; } this.setPlaybackRate(1); node.currentTime += this.jumpSec; this._prevCommand = "jumpForward"; this.doJumpForward(enyo.mixin(this.createEventData(), {jumpSize: this.jumpSec})); }, //* Jumps to beginning of media source and sets _playbackRate_ to 1. jumpToStart: function() { var node = this.hasNode(); if (!node) { return; } this.setPlaybackRate(1); node.pause(); node.currentTime = 0; this._prevCommand = "jumpToStart"; }, //* Jumps to end of media source and sets _playbackRate_ to 1. jumpToEnd: function() { var node = this.hasNode(); if (!node) { return; } this.setPlaybackRate(1); node.pause(); node.currentTime = this.node.duration; this._prevCommand = "jumpToEnd"; }, //* Sets the playback rate type (from the keys of _playBackRateHash_). selectPlaybackRateArray: function(cmd) { this._playbackRateArray = this.playbackRateHash[cmd]; }, //* Changes _playbackRate_ when initiating fast forward or rewind. clampPlaybackRate: function(index) { if (!this._playbackRateArray) { return; } return index % this._playbackRateArray.length; }, //* Returns the playback rate name for the passed-in index. selectPlaybackRate: function(index) { return this._playbackRateArray[index]; }, //* Sets _playbackRate_ according to passed-in string. setPlaybackRate: function(inPlaybackRate) { var node = this.hasNode(), pbNumber ; if (!node) { return; } // Stop rewind (if happenning) this.stopRewindJob(); // Make sure inPlaybackRate is a string this.playbackRate = inPlaybackRate = String(inPlaybackRate); pbNumber = this.calcNumberValueOfPlaybackRate(inPlaybackRate); // Set native playback rate node.playbackRate = pbNumber; if (!(enyo.platform.webos || window.PalmSystem)) { // For supporting cross browser behavior if (pbNumber < 0) { this.beginRewind(); } } }, //* Returns true if currently in paused state. isPaused: function() { return this.hasNode() ? this.hasNode().paused : true; }, //* Returns current player position in the video (in seconds). getCurrentTime: function() { return this.hasNode() ? this.hasNode().currentTime : 0; }, //* Returns buffered time range. getBufferedTimeRange: function() { return this.hasNode() ? this.hasNode().buffered : 0; }, //* Sets current player position in the video (in seconds). setCurrentTime: function(inTime) { if ((typeof inTime === 'number') && this.hasNode()) { this.node.currentTime = inTime; } }, //* Gets play duration in the video (in seconds). getDuration: function() { return this.hasNode() ? this.hasNode().duration : 0; }, //* Gets readyState (0-4). getReadyState: function() { return this.hasNode() ? this.hasNode().readyState : -1; }, //* Gets seeking status. getSeeking: function() { return this.hasNode() ? this.hasNode().seeking : -1; }, //* @protected //* Custom rewind functionality until browsers support negative playback rate beginRewind: function() { this.node.pause(); this.startRewindJob(); }, //* Calculate the time that has elapsed since _rewind: function() { var now = enyo.now(), distance = now - this.rewindBeginTime, pbRate = this.calcNumberValueOfPlaybackRate(this.playbackRate), adjustedDistance = Math.abs(distance * pbRate) / 1000, newTime = this.getCurrentTime() - adjustedDistance ; this.setCurrentTime(newTime); this.startRewindJob(); }, //* Start rewind job startRewindJob: function() { this.rewindBeginTime = enyo.now(); enyo.job(this.id + "rewind", this.bindSafely("_rewind"), 100); }, //* Stop rewind job stopRewindJob: function() { enyo.job.stop(this.id + "rewind"); }, // Calc number value of inPlaybackRate (support for fractions) calcNumberValueOfPlaybackRate: function(inPlaybackRate) { var pbArray = String(inPlaybackRate).split("/"); return (pbArray.length > 1) ? parseInt(pbArray[0], 10) / parseInt(pbArray[1], 10) : parseInt(inPlaybackRate, 10); }, //* When we get the video metadata, update _this.aspectRatio_ metadataLoaded: function(inSender, inEvent) { var node = this.hasNode(); this.setAspectRatio("none"); if (!node || !node.videoWidth || !node.videoHeight) { return; } this.setAspectRatio(node.videoWidth/node.videoHeight+":1"); inEvent = enyo.mixin(inEvent, this.createEventData()); }, timeupdate: function(inSender, inEvent) { var node = this.hasNode(); if (!node) { return; } inEvent = enyo.mixin(inEvent, this.createEventData()); }, ratechange: function(inSender, inEvent) { var node = this.hasNode(), pbNumber ; if (!node) { return; } inEvent = enyo.mixin(inEvent, this.createEventData()); pbNumber = this.calcNumberValueOfPlaybackRate(inEvent.playbackRate); if (pbNumber > 0 && pbNumber < 1) { this.doSlowforward(inEvent); } else if (pbNumber > 1) { this.doFastforward(inEvent); } else if (pbNumber < 0 && pbNumber >= -1) { this.doSlowrewind(inEvent); } else if (pbNumber < -1) { this.doRewind(inEvent); } else if (pbNumber == 1) { this.doPlay(inEvent); } }, createEventData: function() { var node = this.hasNode(); if (!node) { return {}; } if (node.currentTime === 0) { this.doStart(); } return { srcElement: node, duration: node.duration, currentTime: node.currentTime, playbackRate: this.getPlaybackRate() }; }, //* Emit _onPlay_ event (to normalize enyo-generated _onPlay_ events) _play: function(inSender, inEvent) { var node = this.hasNode(); if (!node) { return; } inEvent = enyo.mixin(inEvent, this.createEventData()); this.doPlay(inEvent); }, //* Add all html5 video events hookupVideoEvents: function() { enyo.makeBubble(this, "loadstart", "emptied", "canplaythrough", "ended", "ratechange", "progress", "stalled", "playing", "durationchange", "volumechange", "suspend", "loadedmetadata", "waiting", "timeupdate", "abort", "loadeddata", "seeking", "play", "error", "canplay", "seeked", "pause" ); } });