Pastebin
API
tools
faq
paste
Login
Sign up
Please fix the following errors:
New Paste
Syntax Highlighting
//////////////////////////////////////////////////////////////////////////////// // // ADOBE SYSTEMS INCORPORATED // Copyright 2009 Adobe Systems Incorporated // All Rights Reserved. // // NOTICE: Adobe permits you to use, modify, and distribute this file // in accordance with the terms of the license agreement accompanying it. // /////////////////////////////////////////////////////////////////////////////// package spark.components { import flash.events.Event; import flash.geom.Point; import flash.geom.Rectangle; import flash.media.Video; import mx.core.IUIComponent; import mx.core.IVisualElement; import mx.core.UIComponent; import mx.core.mx_internal; import mx.events.FlexEvent; import mx.events.PropertyChangeEvent; import mx.resources.IResourceManager; import mx.resources.ResourceManager; import org.osmf.containers.MediaContainer; import org.osmf.elements.VideoElement; import org.osmf.events.AudioEvent; import org.osmf.events.DisplayObjectEvent; import org.osmf.events.LoadEvent; import org.osmf.events.MediaPlayerCapabilityChangeEvent; import org.osmf.events.MediaPlayerStateChangeEvent; import org.osmf.events.SeekEvent; import org.osmf.events.TimeEvent; import org.osmf.layout.HorizontalAlign; import org.osmf.layout.LayoutMetadata; import org.osmf.layout.ScaleMode; import org.osmf.layout.VerticalAlign; import org.osmf.media.DefaultMediaFactory; import org.osmf.media.MediaElement; import org.osmf.media.MediaFactory; import org.osmf.media.MediaFactoryItem; import org.osmf.media.MediaPlayer; import org.osmf.media.MediaPlayerState; import org.osmf.media.MediaResourceBase; import org.osmf.media.URLResource; import org.osmf.media.MediaType; import org.osmf.net.NetLoader; import org.osmf.net.DynamicStreamingItem; import org.osmf.net.rtmpstreaming.RTMPDynamicStreamingNetLoader; import org.osmf.net.DynamicStreamingResource; import org.osmf.net.FMSURL; import org.osmf.utils.OSMFStrings; import org.osmf.utils.URL; import spark.components.mediaClasses.DynamicStreamingVideoItem; import spark.components.mediaClasses.DynamicStreamingVideoSource; import spark.primitives.BitmapImage; use namespace mx_internal; //-------------------------------------- // Events //-------------------------------------- /** * Dispatched when the data is received as a download operation progresses. * This event is only dispatched when playing a video by downloading it * directly from a server, typically by issuing an HTTP request. * It is not displatched when playing a video from a special media server, * such as Flash Media Server. * * <p>This event may not be dispatched when the source is set to null or a playback * error occurs.</p> * * @eventType org.osmf.events.LoadEvent.BYTES_LOADED_CHANGE * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.0 * @productversion Flex 4 */ [Event(name="bytesLoadedChange",type="org.osmf.events.LoadEvent")] /** * Dispatched when the playhead reaches the duration for playable media. * * @eventType org.osmf.events.TimeEvent.COMPLETE * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.0 * @productversion Flex 4 */ [Event(name="complete", type="org.osmf.events.TimeEvent")] /** * Dispatched when the <code>currentTime</code> property of the MediaPlayer has changed. * * <p>This event may not be dispatched when the source is set to null or a playback * error occurs.</p> * * @eventType org.osmf.events.TimeEvent.CURRENT_TIME_CHANGE * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.0 * @productversion Flex 4 */ [Event(name="currentTimeChange",type="org.osmf.events.TimeEvent")] /** * Dispatched when the <code>duration</code> property of the media has changed. * * <p>This event may not be dispatched when the source is set to null or a playback * error occurs.</p> * * @eventType org.osmf.events.TimeEvent.DURATION_CHANGE * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.0 * @productversion Flex 4 */ [Event(name="durationChange", type="org.osmf.events.TimeEvent")] /** * Dispatched when the MediaPlayer's state has changed. * * @eventType org.osmf.events.MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.0 * @productversion Flex 4 */ [Event(name="mediaPlayerStateChange", type="org.osmf.events.MediaPlayerStateChangeEvent")] //-------------------------------------- // Other metadata //-------------------------------------- [DefaultProperty("source")] [ResourceBundle("osmf")] [IconFile("VideoDisplay.png")] /** * Because this component does not define a skin for the mobile theme, Adobe * recommends that you not use it in a mobile application. Alternatively, you * can define your own mobile skin for the component. For more information, * see <a href="http://help.adobe.com/en_US/Flex/4.0/UsingSDK/WS53116913-F952-4b21-831F-9DE85B647C8A.html">Spark Skinning</a>. */ [DiscouragedForProfile("mobileDevice")] /** * The VideoDisplay class is chromeless video player that supports * progressive download, multi-bitrate, and streaming video. * * <p><code>VideoDisplay</code> is the chromeless version that does not support skinning. * It is useful when you do not want the user to interact with the control.</p> * * <p><code>VideoPlayer</code> is the skinnable version.</p> * * <p>The VideoDisplay control has the following default characteristics:</p> * <table class="innertable"> * <tr> * <th>Characteristic</th> * <th>Description</th> * </tr> * <tr> * <td>Default size</td> * <td>0 pixels wide by 0 pixels high with no content, * and the width and height of the video with content</td> * </tr> * <tr> * <td>Minimum size</td> * <td>0</td> * </tr> * <tr> * <td>Maximum size</td> * <td>10000 pixels wide and 10000 pixels high</td> * </tr> * </table> * * @mxml * * <p>The <code><s:VideoDisplay></code> tag inherits all of the tag * attributes of its superclass and adds the following tag attributes:</p> * * <pre> * <s:VideoDisplay * <strong>Properties</strong> * autoDisplayFirstFrame="true" * autoPlay="true" * autoRewind="true" * loop="false" * muted="false" * pauseWhenHidden="true" * scaleMode="letterbox" * source="" * volume="1" * * <strong>Events</strong> * bytesLoadedChange="<i>No default</i>" * complete="<i>No default</i>" * currentTimeChange="<i>No default</i>" * durationChange="<i>No default</i>" * mediaPlayerStateChange="<i>No default</i>" * * /> * </pre> * * @see spark.components.VideoPlayer * * @includeExample examples/VideoDisplayExample.mxml * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public class VideoDisplay extends UIComponent { include "../core/Version.as"; //-------------------------------------------------------------------------- // // Class methods // //-------------------------------------------------------------------------- /** * @private * Set as the OSMF.resourceBundleFunction and used to look up * strings so the OSMF RTEs are localized in Flex. */ private static function getResourceString(resourceName:String, args:Array = null):String { var resourceManager:IResourceManager = ResourceManager.getInstance(); return resourceManager.getString("osmf", resourceName, args); } /** * Copied from OSMF ScaleModeUtils.getScaledSize. ScaleModeUtils became * an internal OSMF class in OSMF 1.0 so it is copied here. * * Calculates the scaled size based on the scaling algorithm. * The available width and height are the width and height of the container. * The intrinsic width and height are the width and height of the content. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion OSMF 1.0 */ private static function getScaledSize ( scaleMode:String , availableWidth:Number, availableHeight:Number , intrinsicWidth:Number, intrinsicHeight:Number ):Point { var result:Point; switch (scaleMode) { case ScaleMode.ZOOM: case ScaleMode.LETTERBOX: var availableRatio:Number = availableWidth / availableHeight; var componentRatio:Number = (intrinsicWidth || availableWidth) / (intrinsicHeight || availableHeight); if ( (scaleMode == ScaleMode.ZOOM && componentRatio < availableRatio) || (scaleMode == ScaleMode.LETTERBOX && componentRatio > availableRatio) ) { result = new Point ( availableWidth , availableWidth / componentRatio ); } else { result = new Point ( availableHeight * componentRatio , availableHeight ); } break; case ScaleMode.STRETCH: result = new Point ( availableWidth , availableHeight ); break; case ScaleMode.NONE: result = new Point ( intrinsicWidth || availableWidth , intrinsicHeight || availableHeight ); break; } return result; } //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function VideoDisplay() { super(); // create the underlying MediaPlayer class first. createUnderlyingVideoPlayer(); // added and removed event listeners to see whether we should // start or stop the video addEventListener(Event.ADDED_TO_STAGE, addedToStageHandler); addEventListener(Event.REMOVED_FROM_STAGE, removedFromStageHandler); // Set the OSMF hook used for localizing runtime error messages. // OSMF itself has English-only messages, // but higher layers like Flex can provide localized versions. OSMFStrings.resourceStringFunction = getResourceString; } //-------------------------------------------------------------------------- // // Variables // //-------------------------------------------------------------------------- /** * @private * This is the underlying VideoPlayer object. At some point in the * future, we may change to a new implementation. */ mx_internal var videoPlayer:MediaPlayer; /** * @private * This is the underlying container used to display * the underlying videoPlayer. */ mx_internal var videoContainer:MediaContainer; /** * @private * How the correct media elements are created based on the url of * the resource. */ mx_internal var mediaFactory:MediaFactory; /** * @private * Whether the video is on the display list or not */ private var _isOnDisplayList:Boolean = false; /** * @private * Whether the we should play the video when the video * becomes playable again (visible, on display list, and enabled). * This starts out as true, but when we pause the video is changePlayback(), * we set it to false. Also, when a user action occurs, like pause() or play() * or stop() is called, we set it to false as well. */ private var playTheVideoOnVisible:Boolean = true; /** * @private */ private var effectiveVisibility:Boolean = false; /** * @private */ private var effectiveVisibilityChanged:Boolean = false; /** * @private */ private var effectiveEnabled:Boolean = false; /** * @private */ private var effectiveEnabledChanged:Boolean = false; /** * @private * We do different things in the source setter based on if we * are initialized or not. */ private var initializedOnce:Boolean = false; /** * @private * Keeps track of the muted property while loading up a * video because of autoDisplayFirstFrame. */ private var beforeLoadMuted:Boolean; /** * @private * Keeps track whether we are loading up the * video because of autoDisplayFirstFrame. * * <p>In this case we are in "state1" of loading, * which means we are waiting for the READY * MediaPlayerStateChangeEvent and haven't done anything yet.</p> */ private var inLoadingState1:Boolean; /** * @private * Keeps track whether we are loading up the * video because of autoDisplayFirstFrame. * * <p>In this case we are in "state2" of loading, * which means have set videoPlayer.displayObject.visible=false * and videoPlayer.muted=true. We've also called play() and are * waiting for the DimensionChangeEvent.</p> * * <p>Note: At this point, inLoadingState1 = true as well.</p> */ private var inLoadingState2:Boolean; /** * @private * Keeps track whether we are loading up the * video because of autoDisplayFirstFrame. * * <p>In this case we are in "state3" of loading, * which means have received the DimensionChangeEvent and have called * pause() and seek(0). We are currently waiting for the * SEEK_END event, at which point we will be completely loaded up.</p> * * <p>Note: At this point, inLoadingState1 = inLoadingState2 = true.</p> */ private var inLoadingState3:Boolean; /** * @private * * Old value of videoPlayer.currentTimeUpdateInterval. We store the old * value when we are taken off the stage and pauseWhenHidden is true * (removedFromStageHandler). We restore the old value when we are added * to the stage (addedToStageHandler). The value is used in setupSource() * to turn the timers back on if they were disabled. The value if also used * to check if we should turn off the timers in videoPlayer_seekChangeHandler * and videoPlayer_currentTimeChangeHandler. * This is done to keep this component from being pinned in memory by the timer * associated the currentTimeUpdateInterval property. */ private var oldCurrentTimeUpdateInterval:Number = NaN; /** * @private * * Old value of videoPlayer.bytesLoadedUpdateInterval. We store the old * value when we are taken off the stage and pauseWhenHidden is true * (removedFromStageHandler). We restore the old value when we are added * to the stage (addedToStageHandler). The value is used in setupSource() * to turn the timers back on if they were disabled. The value if also used * to check if we should turn off the timers in videoPlayer_seekChangeHandler * and videoPlayer_currentTimeChangeHandler. * This is done to keep this component from being pinned in memory by the timer * associated the bytesLoadedUpdateInterval property. */ private var oldBytesLoadedUpdateInterval:Number = NaN; //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // autoDisplayFirstFrame //---------------------------------- /** * @private */ private var _autoDisplayFirstFrame:Boolean = true; [Inspectable(category="General", defaultValue="true")] /** * If <code>autoPlay = false</code>, then * <code>autoDisplayFirstFrame</code> controls whether the video * is loaded when the <code>source</code> is set. * If <code>autoDisplayFirstFrame</code> * is set to <code>true</code>, then the first frame of the video is * loaded and the video is sized correctly. * If <code>autoDisplayFirstFrame</code> is set to <code>false</code>, then no * connection to the source is made, the first frame is not shown, * and the video's size is not determined until someone tries to play * the video. * * <p>If <code>autoPlay = true</code>, then this flag is ignored.</p> * * @default true * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get autoDisplayFirstFrame():Boolean { return _autoDisplayFirstFrame; } /** * @private */ public function set autoDisplayFirstFrame(value:Boolean):void { _autoDisplayFirstFrame = value; } //---------------------------------- // autoPlay //---------------------------------- /** * @private */ private var _autoPlay:Boolean = true; [Inspectable(category="General", defaultValue="true")] /** * Specifies whether the video starts playing immediately when the * <code>source</code> property is set. * If <code>true</code>, the video file immediately begins to buffer and * play. * * <p>Even if <code>autoPlay</code> is set to <code>false</code>, Flex * starts loading the video after the <code>initialize()</code> method is * called. * For Flash Media Server, this means creating the stream and loading * the first frame to display. * In the case of an HTTP download, Flex starts downloading the stream * and shows the first frame.</p> * * <p>If <code>playWhenHidden</code> is set to <code>false</code>, then * <code>autoPlay</code> also affects what happens when the video * comes back on stage and is enabled and visible.</p> * * @default true * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get autoPlay():Boolean { return _autoPlay; } /** * @private (setter) */ public function set autoPlay(value:Boolean):void { if (autoPlay == value) return; _autoPlay = value; // call changePlayback() but don't immediately play or pause // based on this change to autoPlay changePlayback(false, false); } //---------------------------------- // autoRewind //---------------------------------- [Inspectable(category="General", defaultValue="true")] /** * Specifies whether the FLV file should rewind to the first frame * when play stops, either by calling the <code>stop()</code> method or by * reaching the end of the stream. * * <p>This property has no effect for live streaming video.</p> * * @default true * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get autoRewind():Boolean { return videoPlayer.autoRewind; } public function set autoRewind(value:Boolean):void { videoPlayer.autoRewind = value; } //---------------------------------- // bytesLoaded //---------------------------------- [Inspectable(Category="General", defaultValue="0")] [Bindable("bytesLoadedChange")] [Bindable("mediaPlayerStateChange")] /** * The number of bytes of data that have been downloaded into the application. * * @return The number of bytes of data that have been downloaded into the application. * @default 0 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get bytesLoaded():Number { return videoPlayer.bytesLoaded; } //---------------------------------- // bytesTotal //---------------------------------- [Inspectable(Category="General", defaultValue="0")] [Bindable("mediaPlayerStateChange")] /** * The total size in bytes of the data being downloaded into the application. * * @return The total size in bytes of the data being downloaded into the application. * @default 0 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get bytesTotal():Number { return videoPlayer.bytesTotal; } //---------------------------------- // currentTime //---------------------------------- [Inspectable(Category="General", defaultValue="0")] [Bindable("currentTimeChange")] [Bindable("mediaPlayerStateChange")] /** * Current time of the playhead, measured in seconds, * since the video starting playing. * * @default 0 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get currentTime():Number { return videoPlayer.currentTime; } //---------------------------------- // duration //---------------------------------- [Inspectable(Category="General", defaultValue="0")] [Bindable("durationChange")] [Bindable("mediaPlayerStateChange")] /** * Duration of the video's playback, in seconds * * @return The total running time of the video in seconds * @default 0 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get duration():Number { return videoPlayer.duration; } //---------------------------------- // loop //---------------------------------- [Inspectable(Category="General", defaultValue="false")] /** * Indicates whether the media should play again after playback has completed. * The <code>loop</code> property takes precedence over the <code>autoRewind</code> * property, so if loop is set to <code>true</code>, the <code>autoRewind</code> * property is ignored. * * @default false * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get loop():Boolean { return videoPlayer.loop; } /** * @private */ public function set loop(value:Boolean):void { if (loop == value) return; videoPlayer.loop = value; } //---------------------------------- // mediaPlayerState //---------------------------------- [Inspectable(category="General", defaultValue="uninitialized")] [Bindable("mediaPlayerStateChange")] /** * The current state of the video. See * org.osmf.media.MediaPlayerState for available values. * * @default uninitialized * * @see org.osmf.media.MediaPlayerState * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get mediaPlayerState():String { return videoPlayer.state; } //---------------------------------- // muted //---------------------------------- [Inspectable(category="General", defaultValue="false")] [Bindable("volumeChanged")] /** * Set to <code>true</code> to mute the video, <code>false</code> * to unmute the video. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get muted():Boolean { // if inLoadingState2, we've got to // fake the muted value if (inLoadingState2) return beforeLoadMuted; return videoPlayer.muted; } /** * @private */ public function set muted(value:Boolean):void { if (muted == value) return; // if inLoadingState2, don't change muted...just fake it if (inLoadingState2) { beforeLoadMuted = value; return; } videoPlayer.muted = value; } //---------------------------------- // pauseWhenHidden //---------------------------------- /** * @private * Storage variable for pauseWhenHidden */ private var _pauseWhenHidden:Boolean = true; [Inspectable(category="General", defaultValue="true")] /** * Controls whether the video continues to play when it is * "hidden". The video is "hidden" when either <code>visible</code> * is set to <code>false</code> on it or one of its ancestors, * or when the video is taken off * of the display list. If set to <code>true</code>, the video * pauses playback until the video is visible again. If set to * <code>false</code> the video continues to play when it is hidden. * * <p>If the video is disabled (or one of the video's parents are * disabled), the video pauses as well, but when it is re-enabled, * the video does not play again. This behavior is not controlled through * <code>pauseWhenHidden</code>; it is defined in the VideoDisplay component.</p> * * @default true * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get pauseWhenHidden():Boolean { return _pauseWhenHidden; } /** * @private */ public function set pauseWhenHidden(value:Boolean):void { if (_pauseWhenHidden == value) return; _pauseWhenHidden = value; if (_pauseWhenHidden) { addVisibilityListeners(); computeEffectiveVisibilityAndEnabled(); } else { removeVisibilityListeners(); } // call changePlayback(). If we're invisible or off the stage, // setting this to true can pause the video. However, setting it // to false should have no immediate impact. changePlayback(value, false); } //---------------------------------- // playing //---------------------------------- [Inspectable(category="General")] [Bindable("mediaPlayerStateChange")] /** * Contains <code>true</code> if the video is playing or is attempting to play. * * <p>The video may not be currently playing, as it may be seeking * or buffering, but the video is attempting to play.</p> * * @see #play() * @see #pause() * @see #stop() * @see #autoPlay * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get playing():Boolean { return videoPlayer.playing; } //---------------------------------- // scaleMode //---------------------------------- /** * @private */ private var _scaleMode:String = ScaleMode.LETTERBOX; [Inspectable(Category="General", enumeration="none,stretch,letterbox,zoom", defaultValue="letterbox")] /** * The <code>scaleMode</code> property describes different ways of * sizing the video content. * You can set <code>scaleMode</code> to * <code>"none"</code>, <code>"stretch"</code>, * <code>"letterbox"</code>, or <code>"zoom"</code>. * * <p>If no width, height, or constraints are specified on the component, * this property has no effect.</p> * * @default "letterbox" * * @see org.osmf.display.ScaleMode * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get scaleMode():String { return _scaleMode; } /** * @private */ public function set scaleMode(value:String):void { if (scaleMode == value) return; switch(value) { case ScaleMode.NONE: _scaleMode = ScaleMode.NONE; break; case ScaleMode.STRETCH: _scaleMode = ScaleMode.STRETCH; break; case ScaleMode.LETTERBOX: _scaleMode = ScaleMode.LETTERBOX; break; case ScaleMode.ZOOM: _scaleMode = ScaleMode.ZOOM; break; default: _scaleMode = ScaleMode.LETTERBOX; break; } // set scaleMode on the videoElement object if (videoPlayer.media) { var layout:LayoutMetadata = videoPlayer.media. getMetadata(LayoutMetadata.LAYOUT_NAMESPACE) as LayoutMetadata; if (layout) layout.scaleMode = _scaleMode; } invalidateSize(); invalidateDisplayList(); } //---------------------------------- // source //---------------------------------- private var _source:Object; private var sourceChanged:Boolean; [Inspectable(category="General", defaultValue="null")] [Bindable("sourceChanged")] /** * The video source. * * <p>For progressive download, the source is just a path or URL pointing * to the video file to play.</p> * * <p>For streaming (recorded streaming, live streaming, * or multi-bitrate streaming), the source property is a * DynamicStreamingVideoSource object. If you just want to play * a recorded or live streaming video with no multi-bitrate support, * you can just pass in a String URL pointing to the video * stream. However, if you do this, the streamType is assumed to be "any," * and you don't have as much control over the streaming as you would if * you used the DynamicStreamingVideoSource object.</p> * * <p>Note: Setting the source on a MediaPlayerStateChangeEvent.LOADING or a * MediaPlayerStateChangeEvent.READY is not recommended if the source was * previously set. This could cause an infinite loop or an RTE. * If you must do an operation like that, wait an additional frame to * set the source.</p> * * @see spark.components.mediaClasses.DynamicStreamingVideoSource * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get source():Object { return _source; } /** * @private (setter) */ public function set source(value:Object):void { _source = value; // if we haven't initialized, let's wait to set up the // source in commitProperties() as it is dependent on other // properties, like autoPlay and enabled, and those may not // be set yet, especially if they are set via MXML. // Otherwise, if we have initialized, let's just set up the // source immediately. This way people can change the source // and immediately call methods like seek(). if (!initializedOnce) { sourceChanged = true; invalidateProperties(); } else { setUpSource(); } dispatchEvent(new Event("sourceChanged")); } //---------------------------------- // thumbnailSource //---------------------------------- /** * @private */ private var _thumbnailSource:Object; /** * @private * Group that holds the BitmapImage for the thumbnail */ private var thumbnailGroup:Group; /** * @private * BitmapImage for the thumbnail */ private var thumbnailBitmapImage:BitmapImage; [Inspectable(Category="General")] /** * @private * Thumbnail source is an internal property used to replace the video with a thumbnail. * This is for places where we just want to load in a placeholder object for the video * and don't want to incur the extra load-time or memory of loading up the video. * * <p>Thumbnail source can take any valid source that can be passed in to * <code>spark.primitivies.BitmapImage#source</code>.</p> * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ mx_internal function get thumbnailSource():Object { return _thumbnailSource; } /** * @private */ mx_internal function set thumbnailSource(value:Object):void { if (_thumbnailSource == value) return; _thumbnailSource = value; // if we haven't initialized, let's wait to set up the // source in commitProperties() as it is dependent on other // properties, like autoPlay and enabled, and those may not // be set yet, especially if they are set via MXML. // Otherwise, if we have initialized, let's just set up the // source immediately. This way people can change the source // and immediately call methods like seek(). if (!initializedOnce) { sourceChanged = true; invalidateProperties(); } else { setUpThumbnailSource(); } } /** * @private * Sets up the thumbnail source for use. */ private function setUpThumbnailSource():void { if (thumbnailSource) { // create thumbnail group if there isn't one if (!thumbnailGroup) { thumbnailBitmapImage = new BitmapImage(); thumbnailBitmapImage.includeInLayout = false; thumbnailGroup = new Group(); // add thumbnailGroup to the display list first in case // bitmap needs to check its layoutDirection. addChild(thumbnailGroup); thumbnailGroup.clipAndEnableScrolling = true; thumbnailGroup.addElement(thumbnailBitmapImage); } // if thumbnailGroup isn't on the display list, then add it. if (!this.contains(thumbnailGroup)) addChild(thumbnailGroup); thumbnailBitmapImage.source = thumbnailSource; invalidateSize(); invalidateDisplayList(); } else { if (thumbnailGroup) { // null out the source and remove the thumbnail group if (thumbnailBitmapImage) thumbnailBitmapImage.source = null; if (this.contains(thumbnailGroup)) removeChild(thumbnailGroup); invalidateSize(); } } } //---------------------------------- // videoObject //---------------------------------- [Inspectable(category="General", defaultValue="null")] /** * The underlying flash player <code>flash.media.Video</code> object. * * <p>If the source is <code>null</code>, then there may be no * underlying <code>flash.media.Video object</code> yet. In that * case, <code>videoObject</code> returns <code>null</code>.</p> * * @default null * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get videoObject():Video { return videoPlayer.displayObject as Video; } //---------------------------------- // volume //---------------------------------- [Inspectable(category="General", defaultValue="1.0", minValue="0.0", maxValue="1.0")] [Bindable("volumeChanged")] /** * The volume level, specified as a value between 0 and 1. * * @default 1 * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function get volume():Number { return videoPlayer.volume; } /** * @private */ public function set volume(value:Number):void { if (volume == value) return; videoPlayer.volume = value; } //-------------------------------------------------------------------------- // // Overridden methods // //-------------------------------------------------------------------------- /** * @private */ override protected function commitProperties():void { super.commitProperties(); initializedOnce = true; if (effectiveVisibilityChanged || effectiveEnabledChanged) { // if either visibility of enabled changed, re-compute them here computeEffectiveVisibilityAndEnabled(); // if visibility changed and we care about it, we can // cause a play or a pause depending on our visibility var causePause:Boolean = false; var causePlay:Boolean = false; if (effectiveVisibilityChanged && pauseWhenHidden) { causePause = !effectiveVisibility; causePlay = effectiveVisibility; } // if enabled changed, we can only cause a pause. // Re-enabling a component doesn't cause a play. if (effectiveEnabledChanged) { if (!effectiveEnabled) causePause = true; } changePlayback(causePause, causePlay); effectiveVisibilityChanged = false; effectiveEnabledChanged = false; } if (sourceChanged) { sourceChanged = false; if (thumbnailSource) setUpThumbnailSource(); else setUpSource(); } } /** * @private */ override protected function measure() : void { super.measure(); var intrinsicWidth:Number; var intrinsicHeight:Number; // if showing the thumbnail, just use the thumbnail's size if (thumbnailSource && thumbnailGroup) { intrinsicWidth = thumbnailBitmapImage.getPreferredBoundsWidth(); intrinsicHeight = thumbnailBitmapImage.getPreferredBoundsHeight(); } else { // If there is no media the width/height will be NaN. // Convert it to zero for our purposes. intrinsicWidth = videoPlayer.mediaWidth; if (isNaN(intrinsicWidth)) intrinsicWidth = 0; intrinsicHeight = videoPlayer.mediaHeight; if (isNaN(intrinsicHeight)) intrinsicHeight = 0; } measuredWidth = intrinsicWidth; measuredHeight = intrinsicHeight; // Determine whether 'width' and 'height' have been set. var bExplicitWidth:Boolean = !isNaN(explicitWidth); var bExplicitHeight:Boolean = !isNaN(explicitHeight); // If only one has been set, calculate the other based on aspect ratio. if (bExplicitWidth && !bExplicitHeight && intrinsicWidth > 0) measuredHeight = explicitWidth * intrinsicHeight / intrinsicWidth; else if (bExplicitHeight && !bExplicitWidth && intrinsicHeight > 0) measuredWidth = explicitHeight * intrinsicWidth / intrinsicHeight; } /** * @private */ override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void { super.updateDisplayList(unscaledWidth, unscaledHeight); // if just showing the thumbnail, push this width/height in to the thumbnail // otherwise we'll push it in to the video object if (thumbnailSource && thumbnailGroup) { // get what the size of our image should be var newSize:Point = getScaledSize(scaleMode, unscaledWidth, unscaledHeight, thumbnailBitmapImage.getPreferredBoundsWidth(), thumbnailBitmapImage.getPreferredBoundsHeight()); // set the thumbnailGroup to be the size of the component. // set the bitmap image to be the size it should be according to OSMF thumbnailGroup.setLayoutBoundsSize(unscaledWidth, unscaledHeight); thumbnailBitmapImage.setLayoutBoundsSize(newSize.x, newSize.y); // center the thumnail image within the thumbnail group. // if it's too big to fit, the thumbnail group will crop it thumbnailBitmapImage.x = (unscaledWidth - newSize.x)/2; thumbnailBitmapImage.y = (unscaledHeight - newSize.y)/2; return; } videoContainer.width = Math.floor(unscaledWidth); videoContainer.height = Math.floor(unscaledHeight); // need to validate the gateway immediately--otherwise we may run out of synch // as they may wait a frame by default before validating (see SDK-24880) videoContainer.validateNow(); } //-------------------------------------------------------------------------- // // Methods // //-------------------------------------------------------------------------- /** * Pauses playback without moving the playhead. * If playback is already is paused or is stopped, this method has no * effect. * * <p>To start playback again, call the <code>play()</code> method.</p> * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function pause():void { // check to see if we can call methods on the video player object yet if (!videoPlayerResponsive()) return; playTheVideoOnVisible = false; // if we're loading up, then we will pause automatically, so let's // not interrupt this process // if inLoadingState1 && pausable, then let loading state handle it // if inLoadingState1 && !pausable, then let the loading state handle it // if !inLoadingState1 && pausable, then just pause // if !inLoadingState1 && !pausable, then load (if needed to show first frame) if (!inLoadingState1 && videoPlayer.canPause) videoPlayer.pause(); else if (!videoPlayer.canPause && autoDisplayFirstFrame) load(); } /** * Causes the video to play. Can be called while the video is * paused, stopped, or while the video is already playing. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function play():void { // check to see if we can call methods on the video player object yet if (!videoPlayerResponsive()) return; playTheVideoOnVisible = false; // if we're loading up, use a special method to cancel the load // and to start playing again. Otherwise, go ahead and play if (inLoadingState1) cancelLoadAndPlay(); else if (videoPlayer.canPlay) videoPlayer.play(); } /** * Seeks to given time in the video. If the video is playing, * continue playing from that point. If the video is paused, seek to * that point and remain paused. If the video is stopped, seek to * that point and enters paused state. * This method has no effect with live video streams. * * <p>If time is less than 0 or NaN, throws exception. If time * is past the end of the stream, or past the amount of file * downloaded so far, then attempts to seek and, if it fails, it then recovers.</p> * * <p>The <code>currentTime</code> property might not have the expected value * immediately after you call <code>seek()</code>. * For a progressive download, * you can seek only to a keyframe; therefore, a seek takes you to the * time of the first keyframe after the specified time.</p> * * <p><strong>Note</strong>: When streaming, a seek always goes to the precise specified * time even if the source FLV file doesn't have a keyframe there.</p> * * <p>Seeking is asynchronous, so if you call the <code>seek()</code> method, * <code>currentTime</code> does not update immediately. </p> * * @param time The seek time, in seconds. * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function seek(time:Number):void { // check to see if we can call methods on the video player object yet if (!videoPlayerResponsive()) return; // TODO (rfrishbe): could handle what to do if this gets called when loading() better. // Need to store where we want to seek to. if (videoPlayer.canSeek) videoPlayer.seek(time); } /** * Stops video playback. If <code>autoRewind</code> is set to * <code>true</code>, rewinds to first frame. If video is already * stopped, has no effect. To start playback again, call * <code>play()</code>. * * @see #autoRewind * @see #play() * * @langversion 3.0 * @playerversion Flash 10 * @playerversion AIR 1.5 * @productversion Flex 4 */ public function stop():void { // check to see if we can call methods on the video player object yet if (!videoPlayerResponsive()) return; playTheVideoOnVisible = false; // if we're loading up, then we will stop automatically, so let's // not interrupt this process // if inLoadingState1 && pausable, then let loading state handle it // if inLoadingState1 && !pausable, then let the loading state handle it // if !inLoadingState1 && pausable, then just pause // if !inLoadingState1 && !pausable, then load (if needed to show first frame) if (!inLoadingState1 && videoPlayer.canPause) videoPlayer.stop(); else if (!videoPlayer.canPause && autoDisplayFirstFrame) load(); } //-------------------------------------------------------------------------- // // Private Methods // //-------------------------------------------------------------------------- /** * @private * If the video player is responsive, then methods can be called on the underlying * video player. */ private function videoPlayerResponsive():Boolean { // can't call any methods before we've initialized if (!initializedOnce) return false; // if displaying a thumbnail, no methods can be called b/c there's no video // loaded up if (thumbnailSource) return false; // if the video player's in a bad state, we can't do anything if (videoPlayer.state == MediaPlayerState.PLAYBACK_ERROR || videoPlayer.state == MediaPlayerState.UNINITIALIZED || videoPlayer.state == MediaPlayerState.LOADING) { return false; } // if no source, return false as well if (!source) return false; // otherwise, we are in a good state and have a source, so let's go return true; } /** * @private */ private function createUnderlyingVideoPlayer():void { // create new video player videoPlayer = new MediaPlayer(); videoContainer = new MediaContainer(); videoContainer.clipChildren = true; mediaFactory = new DefaultMediaFactory(); // remove unsupport media types var unsupportedMediaTypes:Array = ["org.osmf.elements.video.dvr.dvrcast", "org.osmf.elements.image", "org.osmf.elements.swf"]; for each (var mediaType:String in unsupportedMediaTypes) { var mediaFactoryItem:MediaFactoryItem = mediaFactory.getItemById(mediaType); if (mediaFactoryItem) mediaFactory.removeItem(mediaFactoryItem); } // internal events videoPlayer.addEventListener(DisplayObjectEvent.MEDIA_SIZE_CHANGE, videoPlayer_mediaSizeChangeHandler); videoPlayer.addEventListener(AudioEvent.VOLUME_CHANGE, videoPlayer_volumeChangeHandler); videoPlayer.addEventListener(AudioEvent.MUTED_CHANGE, videoPlayer_mutedChangeHandler); // public events videoPlayer.addEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, videoPlayer_mediaPlayerStateChangeHandler); videoPlayer.addEventListener(TimeEvent.CURRENT_TIME_CHANGE, dispatchEvent); videoPlayer.addEventListener(LoadEvent.BYTES_LOADED_CHANGE, dispatchEvent); videoPlayer.addEventListener(TimeEvent.DURATION_CHANGE, videoPlayer_durationChangeHandler); videoPlayer.addEventListener(TimeEvent.COMPLETE, dispatchEvent); addChild(videoContainer); } /** * @private * Sets up the source for use. */ private function setUpSource():void { // clean up any listeners from the old source, especially if we // are in the processing of loading that video file up cleanUpSource() // if was playing a previous video, let's remove it now if (videoPlayer.media && videoContainer.containsMediaElement(videoPlayer.media)) { videoContainer.removeMediaElement(videoPlayer.media); } var videoElement:org.osmf.media.MediaElement = null; // check for 4 cases: streaming video, progressive download, // an IMediaResource, or a VideoElement. // The latter 2 are undocumented but allowed for flexibility until we // can support OSMF better after they ship OSMF 1.0. At that point, support // for a source as an IMediaResource or a VideoElement may be removed. if (source is DynamicStreamingVideoSource) { // the streaming video case. // build up a DynamicStreamingResource to pass in to OSMF var streamingSource:DynamicStreamingVideoSource = source as DynamicStreamingVideoSource; var dsr:DynamicStreamingResource; // check for two cases for host: String and URL. // Technically, we only support URL, but we secretly allow // them to send in an OSMF URL or FMSURL here to help resolve any ambiguity // around serverName vs. streamName. if (streamingSource.host is String) { dsr = new DynamicStreamingResource(streamingSource.host as String, streamingSource.streamType); } else if (streamingSource.host is URL) { dsr = new DynamicStreamingResource(URL(streamingSource.host).host, streamingSource.streamType); } if (dsr) { var n:int = streamingSource.streamItems.length; var item:DynamicStreamingVideoItem; var dsi:DynamicStreamingItem; var streamItems:Vector.<DynamicStreamingItem> = new Vector.<DynamicStreamingItem>(n); for (var i:int = 0; i < n; i++) { item = streamingSource.streamItems[i]; dsi = new DynamicStreamingItem(item.streamName, item.bitrate); streamItems[i] = dsi; } dsr.streamItems = streamItems; dsr.initialIndex = streamingSource.initialIndex; // add video type metadata so if the URL is ambiguous, OSMF will // know what type of file we're trying to connect to dsr.mediaType = MediaType.VIDEO; videoElement = new org.osmf.elements.VideoElement(dsr, new RTMPDynamicStreamingNetLoader()); } } else if (source is String && source != "") { var urlResource:URLResource = new URLResource(source as String); videoElement = mediaFactory.createMediaElement(urlResource); // If the url could not be resolved to a media element then try // telling osmf the media is a video and try again. // We do not specify the media type as video the first time, // so we can have the chance to play audio. if (videoElement == null) { urlResource.mediaType = MediaType.VIDEO; videoElement = mediaFactory.createMediaElement(urlResource); } } else if (source is MediaResourceBase) { videoElement = mediaFactory.createMediaElement(MediaResourceBase(source)); } else if (source is org.osmf.elements.VideoElement) { videoElement = source as org.osmf.elements.VideoElement; } // reset the visibilityPausedTheVideo flag playTheVideoOnVisible = true; // set up videoPlayer.autoPlay based on whether this.autoPlay is // set and whether we are visible and the other typical conditions. changePlayback(false, false); // if we're not going to autoPlay (or couldn't autoPlay because // we're hidden or for some other reason), but we need to seek // to the first frame, then we have to do this on our own // by using our load() method. if (videoElement && (!autoPlay || !shouldBePlaying) && autoDisplayFirstFrame) load(); // set videoPlayer's element to the newly constructed VideoElement // set the newly constructed videoElement's gateway to be the videoGateway videoPlayer.media = videoElement; if (videoElement) { // If we are loading a video, make sure the timers are restored in case // they had been disabled. The timers will be disabled again if we are // only loading the first frame. if (!isNaN(oldCurrentTimeUpdateInterval)) { videoPlayer.currentTimeUpdateInterval = oldCurrentTimeUpdateInterval; videoPlayer.bytesLoadedUpdateInterval = oldBytesLoadedUpdateInterval; } if (videoElement.getMetadata(LayoutMetadata.LAYOUT_NAMESPACE) == null) { var layout:LayoutMetadata = new LayoutMetadata(); layout.scaleMode = scaleMode; layout.verticalAlign = VerticalAlign.MIDDLE; layout.horizontalAlign = HorizontalAlign.CENTER; layout.percentWidth = 100; layout.percentHeight = 100; videoElement.addMetadata(LayoutMetadata.LAYOUT_NAMESPACE, layout); } if (videoElement && !videoContainer.containsMediaElement(videoElement) ) { videoContainer.addMediaElement(videoElement); } } else { // if our source is null, let's invalidateSize() here. // if it's a bad source, we'll get a playbackError and invalidate // the size down there. If it's a good source, we'll get a // dimensionChange event and invalidate the size in there. invalidateSize(); } } /** * @private * Our own internal load() method to handle the case * where autoPlay = false and autoDisplayFirstFrame = true * so that we can load up the video, figure out its size, * and show the first frame */ private function load():void { inLoadingState1 = true; // wait until we can mute, play(), pause(), and seek() before doing anything. // We should be able to do all of these operations on the READY state change event. videoPlayer.addEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, videoPlayer_mediaPlayerStateChangeHandlerForLoading); } //-------------------------------------------------------------------------- // // pauseWhenHidden: Event handlers and Private Methods // //-------------------------------------------------------------------------- /** * @private * Whether the video should be playing based on enabled, * pauseWhenHidden, whether it's on the display list, and its * effective visibility. */ private function get shouldBePlaying():Boolean { // if disabled, return false if (!effectiveEnabled) return false; // if we want to look at visibility, check to // see if we are on the display list and check out // effectiveVisibility (which looks up our parent chain // to make sure us and all of our ancestors are visible) if (pauseWhenHidden) { if (!_isOnDisplayList) return false; if (!effectiveVisibility) return false; } return true; } /** * @private * This method will pause or play the video by looking at the state of * the component and determining whether it should play or pause. This * method gets called when an important event occurs, such as * the component being added/removed from the stage, the component's * effective visibility changing, or when autoPlay is set. * * <p>Only certain events are "action events" which can cause the video * to pause or play immediately. For example, when autoPlay is set to * true/false, that shouldn't cause any immediate action, but changePlayback() * is still called so that autoPlay can be set on the underlying media player.</p> * * <p>Actions that can pause the video are: * <ul> * <li>Changes in effective enablement</li> * <li>Changes in effective visibility</li> * <li>Changes in staging (added or removed from display list)</li> * <li>Setting pauseWhenHidden = true</li> * </ul></p> * * <p>Actions that can play the video are: * <ul> * <li>Changes in effective visibility</li> * <li>Changes in staging (added or removed from display list)</li> * </ul></p> * * @param causePause Whether this action can cause a currently playing video to pause * @param causePlay Whether this action can cause a currently paused video to play */ private function changePlayback(causePause:Boolean, causePlay:Boolean):void { // if we shouldn't be playing, we pause the video. // if we come back up and should be playing, we will // start playing the video again if the video wasn't paused // by the user or developer and autoPlay is true. if (shouldBePlaying) { videoPlayer.autoPlay = autoPlay; // only play the video if visibility caused it to pause // (instead of a user or developer calling video.pause()). // Also, only play if autoPlay is true. Otherwise when // the visibility changes, we won't automatically // play the video if (causePlay && (playTheVideoOnVisible && autoPlay)) { playTheVideoOnVisible = false; // set autoplay and call play() if the // source has loaded up and it's playable if (inLoadingState1) cancelLoadAndPlay(); else if (videoPlayer.canPlay) videoPlayer.play(); } } else { // there are really three states the video player can // be in with respect to play vs. paused: // 1) playing // 2) paused // 3) loading // Here we are checking if we are playing or loading // and going to play soon (autoPlay = true) if (causePause && (playing || (videoPlayer.state == MediaPlayerState.LOADING && autoPlay))) playTheVideoOnVisible = true; // always set autoPlay to false here and // if pausable, pause the video videoPlayer.autoPlay = false; if (causePause) { // if we're loading up, then we will pause automatically, so let's // not interrupt this process // if inLoadingState1 && pausable, then let loading state handle it // if inLoadingState1 && !pausable, then let the loading state handle it // if !inLoadingState1 && pausable, then just pause // if !inLoadingState1 && !pausable, then load (if needed to show first frame) if (!inLoadingState1 && videoPlayer.canPause) videoPlayer.pause(); else if (!videoPlayer.canPause && autoDisplayFirstFrame) load(); } } } /** * @private * Cancels the load, no matter what state it's in, and starts to play(). */ private function cancelLoadAndPlay():void { if (inLoadingState1) { if (!inLoadingState2) { // first step // Don't need to do anything but set inLoadingState1 = false (done down below). // This is handled in videoPlayer_mediaPlayerStateChangeHandlerForLoading which will still // be fired and will handle calling videoPlayer.play() without the rest of the loading // junk because inLoadingState1 = false now } else if (!inLoadingState3) { // second step videoPlayer.muted = beforeLoadMuted; if (videoPlayer.displayObject) videoPlayer.displayObject.visible = true; videoPlayer.removeEventListener(TimeEvent.CURRENT_TIME_CHANGE, videoPlayer_currentTimeChangeHandler); videoPlayer.removeEventListener(MediaPlayerCapabilityChangeEvent.CAN_SEEK_CHANGE, videoPlayer_canSeekChangeHandler); } else { // third step videoPlayer.removeEventListener(SeekEvent.SEEKING_CHANGE, videoPlayer_seekChangeHandler); videoPlayer.muted = beforeLoadMuted; if (videoPlayer.displayObject) videoPlayer.displayObject.visible = true; // wasn't playing if (videoPlayer.canPlay) videoPlayer.play(); } inLoadingState1 = false; inLoadingState2 = false; inLoadingState3 = false; } } /** * @private * Cancels the load, no matter what state it's in. This is used when changing the source. */ private function cleanUpSource():void { // TODO (rfrishbe): very similar to cancelLoadAndPlay(). Should collapse it down. // always remove listener as we could be out of loadState1 but still "loading to play" videoPlayer.removeEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, videoPlayer_mediaPlayerStateChangeHandlerForLoading); if (inLoadingState1) { if (!inLoadingState2) { // first step // Just need to remove event listeners as we did above } else if (!inLoadingState3) { // second step videoPlayer.muted = beforeLoadMuted; videoPlayer.displayObject.visible = true; // going to call pause() now to stop immediately videoPlayer.pause(); } else { // third step videoPlayer.removeEventListener(SeekEvent.SEEKING_CHANGE, videoPlayer_seekChangeHandler); videoPlayer.muted = beforeLoadMuted; videoPlayer.displayObject.visible = true; // already called pause(), so don't do anything } inLoadingState1 = false; inLoadingState2 = false; inLoadingState3 = false; } } /** * @private */ private function addedToStageHandler(event:Event):void { _isOnDisplayList = true; // add listeners to current parents to see if their visibility has changed if (pauseWhenHidden) addVisibilityListeners(); addEnabledListeners(); computeEffectiveVisibilityAndEnabled(); // When added to the stage, restore some videoPlayer timers that we had // disabled when we went offstage. if (!isNaN(oldCurrentTimeUpdateInterval)) { videoPlayer.currentTimeUpdateInterval = oldCurrentTimeUpdateInterval; videoPlayer.bytesLoadedUpdateInterval = oldBytesLoadedUpdateInterval; oldCurrentTimeUpdateInterval = NaN; oldBytesLoadedUpdateInterval = NaN; } // being added to the display list will not pause the video, but // it may play the video if pauseWhenHidden = true changePlayback(false, pauseWhenHidden); } /** * @private */ private function removedFromStageHandler(event:Event):void { _isOnDisplayList = false; // remove listeners from old parents if (pauseWhenHidden) removeVisibilityListeners(); removeEnabledListeners(); // Stop the timers associated with these intervals when we go // offscreen so we are not pinned in memory. Save the old // values of the timers so we can restore them when we come // back on stage. if (pauseWhenHidden) { oldCurrentTimeUpdateInterval = videoPlayer.currentTimeUpdateInterval; oldBytesLoadedUpdateInterval = videoPlayer.bytesLoadedUpdateInterval; videoPlayer.currentTimeUpdateInterval = -1; videoPlayer.bytesLoadedUpdateInterval = -1; } // being removed from the display list will pause the video if // pauseWhenHidden = true changePlayback(pauseWhenHidden, false); } /** * @private * Add event listeners for SHOW and HIDE on all the ancestors up the parent chain. * Adding weak event listeners just to be safe. */ private function addVisibilityListeners():void { var current:IVisualElement = this; while (current) { // add visibility listeners to the parent current.addEventListener(FlexEvent.HIDE, visibilityChangedHandler, false, 0, true); current.addEventListener(FlexEvent.SHOW, visibilityChangedHandler, false, 0, true); // add listeners to the design layer too if (current.designLayer) { current.designLayer.addEventListener("layerPropertyChange", designLayer_layerPropertyChangeHandler, false, 0, true); } current = current.parent as IVisualElement; } } /** * @private * Add event listeners for "enabledChanged" event on all ancestors up the parent chain. * Adding weak event listeners just to be safe. */ private function addEnabledListeners():void { var current:IVisualElement = this; while (current) { current.addEventListener("enabledChanged", enabledChangedHandler, false, 0, true); current.addEventListener("enabledChanged", enabledChangedHandler, false, 0, true); current = current.parent as IVisualElement; } } /** * @private * Remove event listeners for SHOW and HIDE on all the ancestors up the parent chain. */ private function removeVisibilityListeners():void { var current:IVisualElement = this; while (current) { current.removeEventListener(FlexEvent.HIDE, visibilityChangedHandler, false); current.removeEventListener(FlexEvent.SHOW, visibilityChangedHandler, false); if (current.designLayer) { current.designLayer.removeEventListener("layerPropertyChange", designLayer_layerPropertyChangeHandler, false); } current = current.parent as IVisualElement; } } /** * @private * Remove event listeners for "enabledChanged" event on all ancestors up the parent chain. */ private function removeEnabledListeners():void { var current:IVisualElement = this; while (current) { current.removeEventListener("enabledChanged", enabledChangedHandler, false); current.removeEventListener("enabledChanged", enabledChangedHandler, false); current = current.parent as IVisualElement; } } /** * @private * Event call back whenever the visibility of us or one of our ancestors * changes */ private function visibilityChangedHandler(event:FlexEvent):void { effectiveVisibilityChanged = true; invalidateProperties(); } /** * @private * Event call back whenever the visibility of our designLayer or one of our parent's * designLayers change. */ private function designLayer_layerPropertyChangeHandler(event:PropertyChangeEvent):void { if (event.property == "effectiveVisibility") { effectiveVisibilityChanged = true; invalidateProperties(); } } /** * @private * Event call back whenever the enablement of us or one of our ancestors * changes */ private function enabledChangedHandler(event:Event):void { effectiveEnabledChanged = true; invalidateProperties(); } /** * @private */ private function computeEffectiveVisibilityAndEnabled():void { // start out with true visibility and enablement // then loop up parent-chain to see if any of them are false effectiveVisibility = true; effectiveEnabled = true; var current:IVisualElement = this; while (current) { if (!current.visible || (current.designLayer && !current.designLayer.effectiveVisibility)) { effectiveVisibility = false; if (!effectiveEnabled) break; } if (current is IUIComponent && !IUIComponent(current).enabled) { effectiveEnabled = false; if (!effectiveVisibility) break; } current = current.parent as IVisualElement; } } //-------------------------------------------------------------------------- // // Event handlers // //-------------------------------------------------------------------------- /** * @private */ private function videoPlayer_volumeChangeHandler(event:AudioEvent):void { dispatchEvent(new Event("volumeChanged")); } /** * @private */ private function videoPlayer_mutedChangeHandler(event:AudioEvent):void { dispatchEvent(new Event("volumeChanged")); } /** * @private * Event handler for mediaPlayerStateChange event. */ private function videoPlayer_mediaPlayerStateChangeHandler(event:MediaPlayerStateChangeEvent):void { // if the event change caused us to go in to a state where // nothing is loaded up and we've no chance of getting a // dimensionChangeEvent, then let's invalidate our size here if (event.state == MediaPlayerState.PLAYBACK_ERROR) invalidateSize(); // this is a public event, so let's re-dispatch it dispatchEvent(event); } /** * @private * Event handler for mediaPlayerStateChange event--used only * when trying to load up the video without playing it. */ private function videoPlayer_mediaPlayerStateChangeHandlerForLoading(event:MediaPlayerStateChangeEvent):void { // only come in here when we want to load the video without playing it. //trace("videoPlayer_mediaPlayerStateChangeHandlerForLoading: mediaPlayerState = " + event.state); // wait until we are ready so that we can set mute, play, pause, and seek if (event.state == MediaPlayerState.READY) { // now that we are loading up, let's remove the event listener: videoPlayer.removeEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, videoPlayer_mediaPlayerStateChangeHandlerForLoading); // if we are already playing() for some reason because someone called play(), then // we don't need to do anything. if (videoPlayer.playing) return; // if this load wasn't cancelled, then we'll do the load stuff. // otherwise, we'll just cause play(). if (inLoadingState1) { //trace("videoPlayer_mediaPlayerStateChangeHandlerForLoading: inLoadingState1"); beforeLoadMuted = videoPlayer.muted; videoPlayer.muted = true; if (videoPlayer.displayObject) videoPlayer.displayObject.visible = false; inLoadingState2 = true; } // call play(), here, then wait to call pause() and seek(0) in the // mediaSizeChangeHandler //trace("videoPlayer_mediaPlayerStateChangeHandlerForLoading: call videoPlayer.play()"); videoPlayer.play(); } } /** * @private */ private function videoPlayer_mediaSizeChangeHandler(event:DisplayObjectEvent):void { //trace("videoPlayer_mediaSizeChangeHandler"); invalidateSize(); // if we're loading up the video, then let's finish the load in here if (inLoadingState2) { //trace("videoPlayer_mediaSizeChangeHandler: inLoadingState2"); if (videoPlayer.canSeek && videoPlayer.canSeekTo(0)) { //trace("videoPlayer_mediaSizeChangeHandler: canSeek to first frame"); inLoadingState3 = true; // Don't call pause and seek inside this handler because OSMF is // not expecting us to change its HTTPStreamingState value in // HTTPNetStream.onMainTimer as a result of dispatching this // event (see SDK-27028). callLater(pauseAndSeekCallBack); } else if (duration < 0) { // Work around for negative durations - FM-1009 // We want to seek to the first frame but we can't because the // duration of the video is reported as negative. As a work around, // listen for the first time change event and then pause the video. //trace("videoPlayer_mediaSizeChangeHandler: negative duration - wait for first current time change event"); videoPlayer.addEventListener(TimeEvent.CURRENT_TIME_CHANGE, videoPlayer_currentTimeChangeHandler); } else { //trace("videoPlayer_mediaSizeChangeHandler: waiting for media to become seekable"); // wait for the media to become seekable. videoPlayer.addEventListener(MediaPlayerCapabilityChangeEvent.CAN_SEEK_CHANGE, videoPlayer_canSeekChangeHandler); } } } private function pauseAndSeekCallBack():void { // the seek(0) is asynchronous so let's add an event listener to see when it's finsished: videoPlayer.addEventListener(SeekEvent.SEEKING_CHANGE, videoPlayer_seekChangeHandler); // called play(), now call pause() and seek(0); videoPlayer.pause(); videoPlayer.seek(0); } /** * @private * Wait until the media is seekable before we call pause() and seek(). */ private function videoPlayer_canSeekChangeHandler(event:Event):void { //trace("videoPlayer_canSeekChangeHandler: seeking = " + videoPlayer.canSeek); videoPlayer.removeEventListener(MediaPlayerCapabilityChangeEvent.CAN_SEEK_CHANGE, videoPlayer_canSeekChangeHandler); if (inLoadingState2) { if (videoPlayer.canSeek && videoPlayer.canSeekTo(0)) { inLoadingState3 = true; // Don't call pause and seek inside this handler because OSMF is // not expecting us to change its HTTPStreamingState value in // HTTPNetStream.onMainTimer as a result of dispatching this // event (see SDK-27028). callLater(pauseAndSeekCallBack); } } } /** * @private * Event handler for seekEnd events. We only use this * when trying to load up the video without playing it. * This will be called after the video has loaded up and * we have finished seeking back to the first frame. */ private function videoPlayer_seekChangeHandler(event:SeekEvent):void { if (!event.seeking) { inLoadingState1 = false; inLoadingState2 = false; inLoadingState3 = false; videoPlayer.removeEventListener(SeekEvent.SEEKING_CHANGE, videoPlayer_seekChangeHandler); videoPlayer.muted = beforeLoadMuted; if (videoPlayer.displayObject) videoPlayer.displayObject.visible = true; // Disable the TimeEvents again that we had // enabled for loading a video while offstage. if (!isNaN(oldCurrentTimeUpdateInterval)) { videoPlayer.currentTimeUpdateInterval = -1; videoPlayer.bytesLoadedUpdateInterval = -1; } } } /** * @private * * Work around for negative durations - see FM-1009. * See want to seek to the first frame but can't because * the video has a negative duration. So we listen to the * current time. When we get a time change so we must be at * least the first frame so pause the video now and clean * up the load state variables. */ private function videoPlayer_currentTimeChangeHandler(event:TimeEvent):void { //trace("videoPlayer_currentTimeChangeHandler: time = " + event.time); videoPlayer.removeEventListener(TimeEvent.CURRENT_TIME_CHANGE, videoPlayer_currentTimeChangeHandler); videoPlayer.removeEventListener(MediaPlayerCapabilityChangeEvent.CAN_SEEK_CHANGE, videoPlayer_canSeekChangeHandler); videoPlayer.pause(); videoPlayer.muted = beforeLoadMuted; if (videoPlayer.displayObject) videoPlayer.displayObject.visible = true; inLoadingState1 = false; inLoadingState2 = false; inLoadingState3 = false; // Disable the TimeEvents again that we had // enabled for loading a video while offstage. if (!isNaN(oldCurrentTimeUpdateInterval)) { videoPlayer.currentTimeUpdateInterval = -1; videoPlayer.bytesLoadedUpdateInterval = -1; } } /** * @private * * Work around for negative durations - see FM-1009. * * If we get a duration event that is negative while in * inLoadingState2 is true, then listen for the first time * change event so we can pause the video. */ private function videoPlayer_durationChangeHandler(event:TimeEvent):void { //trace("videoPlayer_durationChangeHandler: time = " + event.time); dispatchEvent(event); if (inLoadingState2) { if (event.time < 0) { // Work around for negative durations - FM-1009 // We want to seek to the first frame but we can't because the // duration of the video is reported as negative. As a work around, // listen for the first time change event and then pause the video. //trace("videoPlayer_durationChangeHandler: negative duration - wait for first current time change event"); videoPlayer.addEventListener(TimeEvent.CURRENT_TIME_CHANGE, videoPlayer_currentTimeChangeHandler); } } } } }
Optional Paste Settings
Category:
None
Cryptocurrency
Cybersecurity
Fixit
Food
Gaming
Haiku
Help
History
Housing
Jokes
Legal
Money
Movies
Music
Pets
Photo
Science
Software
Source Code
Spirit
Sports
Travel
TV
Writing
Tags:
Syntax Highlighting:
None
Bash
C
C#
C++
CSS
HTML
JSON
Java
JavaScript
Lua
Markdown (PRO members only)
Objective C
PHP
Perl
Python
Ruby
Swift
4CS
6502 ACME Cross Assembler
6502 Kick Assembler
6502 TASM/64TASS
ABAP
AIMMS
ALGOL 68
APT Sources
ARM
ASM (NASM)
ASP
ActionScript
ActionScript 3
Ada
Apache Log
AppleScript
Arduino
Asymptote
AutoIt
Autohotkey
Avisynth
Awk
BASCOM AVR
BNF
BOO
Bash
Basic4GL
Batch
BibTeX
Blitz Basic
Blitz3D
BlitzMax
BrainFuck
C
C (WinAPI)
C Intermediate Language
C for Macs
C#
C++
C++ (WinAPI)
C++ (with Qt extensions)
C: Loadrunner
CAD DCL
CAD Lisp
CFDG
CMake
COBOL
CSS
Ceylon
ChaiScript
Chapel
Clojure
Clone C
Clone C++
CoffeeScript
ColdFusion
Cuesheet
D
DCL
DCPU-16
DCS
DIV
DOT
Dart
Delphi
Delphi Prism (Oxygene)
Diff
E
ECMAScript
EPC
Easytrieve
Eiffel
Email
Erlang
Euphoria
F#
FO Language
Falcon
Filemaker
Formula One
Fortran
FreeBasic
FreeSWITCH
GAMBAS
GDB
GDScript
Game Maker
Genero
Genie
GetText
Go
Godot GLSL
Groovy
GwBasic
HQ9 Plus
HTML
HTML 5
Haskell
Haxe
HicEst
IDL
INI file
INTERCAL
IO
ISPF Panel Definition
Icon
Inno Script
J
JCL
JSON
Java
Java 5
JavaScript
Julia
KSP (Kontakt Script)
KiXtart
Kotlin
LDIF
LLVM
LOL Code
LScript
Latex
Liberty BASIC
Linden Scripting
Lisp
Loco Basic
Logtalk
Lotus Formulas
Lotus Script
Lua
M68000 Assembler
MIX Assembler
MK-61/52
MPASM
MXML
MagikSF
Make
MapBasic
Markdown (PRO members only)
MatLab
Mercury
MetaPost
Modula 2
Modula 3
Motorola 68000 HiSoft Dev
MySQL
Nagios
NetRexx
Nginx
Nim
NullSoft Installer
OCaml
OCaml Brief
Oberon 2
Objeck Programming Langua
Objective C
Octave
Open Object Rexx
OpenBSD PACKET FILTER
OpenGL Shading
Openoffice BASIC
Oracle 11
Oracle 8
Oz
PARI/GP
PCRE
PHP
PHP Brief
PL/I
PL/SQL
POV-Ray
ParaSail
Pascal
Pawn
Per
Perl
Perl 6
Phix
Pic 16
Pike
Pixel Bender
PostScript
PostgreSQL
PowerBuilder
PowerShell
ProFTPd
Progress
Prolog
Properties
ProvideX
Puppet
PureBasic
PyCon
Python
Python for S60
QBasic
QML
R
RBScript
REBOL
REG
RPM Spec
Racket
Rails
Rexx
Robots
Roff Manpage
Ruby
Ruby Gnuplot
Rust
SAS
SCL
SPARK
SPARQL
SQF
SQL
SSH Config
Scala
Scheme
Scilab
SdlBasic
Smalltalk
Smarty
StandardML
StoneScript
SuperCollider
Swift
SystemVerilog
T-SQL
TCL
TeXgraph
Tera Term
TypeScript
TypoScript
UPC
Unicon
UnrealScript
Urbi
VB.NET
VBScript
VHDL
VIM
Vala
Vedit
VeriLog
Visual Pro Log
VisualBasic
VisualFoxPro
WHOIS
WhiteSpace
Winbatch
XBasic
XML
XPP
Xojo
Xorg Config
YAML
YARA
Z80 Assembler
ZXBasic
autoconf
jQuery
mIRC
newLISP
q/kdb+
thinBasic
Paste Expiration:
Never
Burn after read
10 Minutes
1 Hour
1 Day
1 Week
2 Weeks
1 Month
6 Months
1 Year
Paste Exposure:
Public
Unlisted
Private
Folder:
(members only)
Password
NEW
Enabled
Disabled
Burn after read
NEW
Paste Name / Title:
Create New Paste
Hello
Guest
Sign Up
or
Login
Sign in with Facebook
Sign in with Twitter
Sign in with Google
You are currently not logged in, this means you can not edit or delete anything you paste.
Sign Up
or
Login
Public Pastes
⭐ MAKE $50O IN 15 MIN⭐⭐ 0
JavaScript | 1 min ago | 0.31 KB
⭐ Free ETH Method ⭐⭐ A
JavaScript | 1 min ago | 0.31 KB
⭐ MAKE $90O INSTANTLY⭐⭐ 4
JavaScript | 1 min ago | 0.31 KB
⭐Crypto Exchange Profit Method⭐⭐ 9
JavaScript | 1 min ago | 0.31 KB
⭐ChangeNOW Bug (Get more on BTC swaps)⭐⭐ C
JavaScript | 1 min ago | 0.31 KB
⭐ Exploit 50O$ in 15 Minutes⭐⭐ T
JavaScript | 1 min ago | 0.31 KB
⭐ Instant Profit Mehtod ⭐ E
JavaScript | 1 min ago | 0.31 KB
⭐Swapzone Glitch (Working)⭐⭐ 1
JavaScript | 1 min ago | 0.31 KB
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the
Cookies Policy
.
OK, I Understand
Not a member of Pastebin yet?
Sign Up
, it unlocks many cool features!