Transferred from the Adobe Open Source Subversion Repository

Revision: 5215
Author:   rfrishbe@adobe.com
Date:     2009-03-10T01:39:37.388950Z

Log Message:
-----------
Initial checkin for FxVideoDisplay.  FxVideoDisplay is the new skinnable video component in Gumbo.  VideoElement is the new chromeless video component in Gumbo.

As part of this checkin, a new swc was added to the libs directory, videoPlayer.swc, which holds the underlying FLVPlackback VideoPlayer we are using today in VideoElement.

Multi-bit rate support hasn't been added yet, the skin could use a lot of work, and work needs to be done on state/skinstate support.  Otherwise, most things should be working.

QE Notes: You can start testing :-)
Doc Notes: -
Bugs: -
Reviewer: Deepa
tests: checkintests

Modified Paths:
--------------
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/events/VideoEvent.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/Flex4Classes.as</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/libs/videoPlayer.swc</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/components/FxVideoDisplay.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/mxml-2009-manifest.xml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/graphics/VideoElement.as</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/skins/spark/FxVideoDisplayPlayPauseButtonSkin.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/build.xml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/defaults.css</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/events/MetadataEvent.as</path>
<path kind="file" action="M">/flex/sdk/trunk/build.xml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/skins/spark/FxVideoDisplayMuteButtonSkin.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/manifest.xml</path>
<path kind="dir" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark</path>
<path kind="dir" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/events</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/flex4/src/mx/skins/spark/FxVideoDisplaySkin.mxml</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1281085 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/spark/src/spark/components/VideoDisplay.as
+++ frameworks/projects/spark/src/spark/components/VideoDisplay.as
@@ -0,0 +1,884 @@
+package mx.graphics
+{
+import fl.video.MetadataEvent;
+import fl.video.VideoAlign;
+import fl.video.VideoEvent;
+import fl.video.VideoPlayer;
+import fl.video.VideoScaleMode;
+import fl.video.VideoState;
+
+import flash.display.DisplayObject;
+import flash.events.Event;
+import flash.events.ProgressEvent;
+
+import mx.core.mx_internal;
+import mx.graphics.baseClasses.GraphicElement;
+
+import spark.events.MetadataEvent;
+import spark.events.VideoEvent;
+
+//--------------------------------------
+//  Events
+//--------------------------------------
+
+/**
+ *  Dispatched when the NetConnection is closed,
+ *  whether by being timed out, by calling the close() method,
+ *  or by loading a new video stream.  This event is only dispatched
+ *  with RTMP streams, never HTTP.
+ *
+ *  @eventType spark.events.VideoEvent.CLOSE
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ */
+[Event(name="close", type="spark.events.VideoEvent")]
+
+/**
+ * Dispatched when playing completes because the player reached the end of the FLV file.
+ * The component does not dispatch the event if you call the stop() or
+ * pause() methods
+ * or click the corresponding controls.
+ *
+ *  @eventType spark.events.VideoEvent.COMPLETE
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ */
+[Event(name="complete", type="spark.events.VideoEvent")]
+
+/**
+ *  Dispatched the first time the FLV file's metadata is reached.
+ *  The event object has an info property that contains the
+ *  info object received by the NetStream.onMetaData event callback.
+ *
+ *  @eventType spark.events.MetadataEvent.METADATA_RECEIVED
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ */
+[Event(name="metadataReceived", type="spark.events.MetadataEvent")]
+
+/**
+ *  Dispatched every 0.25 seconds, or how often the underlying video
+ *  player's playheadUpdateInterval is set to, while the
+ *  video is playing.  This event is not dispatched when it is paused
+ *  or stopped, unless a seek occurs.
+ *
+ *  @eventType spark.events.VideoEvent.PLAYHEAD_UPDATE
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ */
+[Event(name="playheadUpdate", type="spark.events.VideoEvent")]
+
+/**
+ *  Indicates progress made in number of bytes downloaded. Dispatched at the frequency
+ *  specified by the underlying video player's progressInterval property, starting
+ *  when the load begins and ending when all bytes are loaded or there is a network error.
+ *  The default is every 0.25 seconds starting when load is called and ending
+ *  when all bytes are loaded or if there is a network error. Use this event to check
+ *  bytes loaded or number of bytes in the buffer.
+ *
+ *
Dispatched only for a progressive HTTP download. Indicates progress in number of
+ *  downloaded bytes. The event object has the bytesLoaded and bytesTotal
+ *  properties

+ *
+ *  @eventType flash.events.ProgressEvent.PROGRESS
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ */
+[Event(name="progress", type="flash.events.ProgressEvent")]
+
+/**
+ *  Dispatched when the video is loaded and ready to display.
+ *
+ *
This event is dispatched the first time the VideoPlayer
+ *  enters a responsive state after a new FLV is loaded
+ *  with the play() or load() method.
+ *  It is dispatched once for each FLV loaded.

+ *
+ *  @eventType spark.events.VideoEvent.READY
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ */
+[Event(name="ready", type="spark.events.VideoEvent")]
+
+//--------------------------------------
+//  Other metadata
+//--------------------------------------
+
+[DefaultProperty("source")]
+
+//[IconFile("VideoElement.png")]
+
+/**
+ *  The VideoElement class is chromeless video player that supports
+ *  progressive download, multi-bitrate, and streaming video.
+ *
+ *
FxVideoDisplay is the skinnable version.

+ *
+ *  @see mx.components.FxVideoDisplay
+ *
+ *  @langversion 3.0
+ *  @playerversion Flash 10
+ *  @playerversion AIR 1.5
+ *  @productversion Flex 4
+ */
+public class VideoElement extends GraphicElement
+{
+    /**
+     *  Constructor.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function VideoElement()
+    {
+        super();
+        VideoPlayer.iNCManagerClass = fl.video.NCManagerDynamicStream;
+        mx_internal::videoPlayer = new VideoPlayer();
+        mx_internal::videoPlayer.align = VideoAlign.CENTER;
+
+        mx_internal::videoPlayer.addEventListener(fl.video.VideoEvent.CLOSE, videoPlayer_closeHandler);
+        mx_internal::videoPlayer.addEventListener(fl.video.VideoEvent.COMPLETE, videoPlayer_completeHandler);
+        mx_internal::videoPlayer.addEventListener(fl.video.MetadataEvent.METADATA_RECEIVED, videoPlayer_metaDataReceivedHandler);
+        mx_internal::videoPlayer.addEventListener(fl.video.VideoEvent.PLAYHEAD_UPDATE, videoPlayer_playHeadUpdateHandler);
+        mx_internal::videoPlayer.addEventListener(ProgressEvent.PROGRESS, dispatchEvent);
+        mx_internal::videoPlayer.addEventListener(fl.video.VideoEvent.STATE_CHANGE, videoPlayer_stateChangeHandler);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  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:VideoPlayer;
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden properties
+    //
+    //--------------------------------------------------------------------------
+
+    // We're overriding the displayObject getters/setters and methods to make
+    // videoPlayer the DisplayObject for this video graphic element.
+
+    /**
+     *  @private
+     */
+    override public function get displayObject():DisplayObject
+    {
+        return mx_internal::videoPlayer;
+    }
+
+    /**
+     *  @private
+     */
+    override public function set displayObject(value:DisplayObject):void
+    {
+        // no-op
+    }
+
+    /**
+     *  @private
+     */
+    override public function canDrawToShared(sharedDisplayObject:DisplayObject):Boolean
+    {
+        return false;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Properties
+    //
+    //--------------------------------------------------------------------------
+
+    //----------------------------------
+    //  autoPlay
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for autoPlay property.
+     */
+    private var _autoPlay:Boolean = true;
+
+    [Inspectable(category="General", defaultValue="true")]
+
+    /**
+     *  Specifies whether the video should start playing immediately when the
+     *  source property is set.
+     *  If true, the video file immediately begins to buffer and
+     *  play.
+     *
+     *
Even if autoPlay is set to false, Flex
+     *  starts loading the video after the initialize() 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.

+     *
+     *  @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;
+
+        _isPlaying = value;
+        _autoPlay = value;
+    }
+
+    //----------------------------------
+    //  autoRewind
+    //----------------------------------
+
+    [Inspectable(category="General", defaultValue="true")]
+
+    /**
+     *  Specifies whether the FLV file should be rewound to the first frame
+     *  when play stops, either by calling the stop() method or by
+     *  reaching the end of the stream.
+     *
+     *  This property has no effect for live streaming video.
+     *
+     *  @default true
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function get autoRewind():Boolean
+    {
+        return mx_internal::videoPlayer.autoRewind;
+    }
+
+    public function set autoRewind(value:Boolean):void
+    {
+        mx_internal::videoPlayer.autoRewind = value;
+    }
+
+    //----------------------------------
+    //  isLive
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for isLive property.
+     */
+    private var _isLive:Boolean = false;
+
+    [Inspectable(category="General", defaultValue="false")]
+
+    /**
+     *  A Boolean value that is true if the video stream is live.
+     *  This property is effective only when streaming from Flash Media Server
+     *  or Flash Video Streaming Service (FVSS). The value of this
+     *  property is ignored for an HTTP download.
+     *
+     *
Set the isLive property to false when sending
+     *  a prerecorded video stream to the video player and to true
+     *  when sending real-time data such as a live broadcast.
+     *
+     *  @see #source
+     *  @see VideoPlayer#isLive
+     *  @default false
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function get isLive():Boolean
+    {
+        return _isLive;
+    }
+
+    /**
+     *  @private
+     */
+    public function set isLive(value:Boolean):void
+    {
+        _isLive = value;
+        sourceChanged = true;
+        invalidateProperties();
+    }
+
+    //----------------------------------
+    //  isMuted
+    //----------------------------------
+
+    [Inspectable(category="General", defaultValue="false")]
+
+    /**
+     *  Returns true if the video is muted, false
+     *  if the video is not muted.
+     *
+     *  @see #mute()
+     *  @see #unmute()
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function get isMuted():Boolean
+    {
+        return mutedVolume != -1;
+    }
+
+    //----------------------------------
+    //  isPlaying
+    //----------------------------------
+
+    [Inspectable(category="General")]
+
+    private var _isPlaying:Boolean = true; // initialize to same value as autoPlay
+
+    /**
+     *  Returns true if the video is playing or is attempting to play.
+     *
+     *
The video may not be currently playing, as it may be seeking
+     *  or buferring, but the video is attempting to play.

+     *
+     *  @see #play()
+     *  @see #pause()
+     *  @see #stop()
+     *  @see #autoPlay
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function get isPlaying():Boolean
+    {
+        return _isPlaying;
+    }
+
+    //----------------------------------
+    //  maintainAspectRatio
+    //----------------------------------
+
+    /**
+     *  @private
+     *  Storage for maintainAspectRatio property.
+     */
+    private var _maintainAspectRatio:Boolean = true;
+
+    [Inspectable(Category="General", defaultValue="true")]
+
+    /**
+     *  Specifies whether the control should maintain the original aspect ratio
+     *  while resizing the video.
+     *
+     *
If no width, height, or constraints are specified on the VideoElement,
+     *  this property has no effect.

+     *
+     *  @default true
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function get maintainAspectRatio():Boolean
+    {
+        return _maintainAspectRatio;
+    }
+
+    /**
+     *  @private
+     */
+    public function set maintainAspectRatio(value:Boolean):void
+    {
+        if (_maintainAspectRatio != value)
+        {
+            _maintainAspectRatio = value;
+
+            // VideoPlayer has MAINTAIN_ASPECT_RATIO, EXACT_FIT, and NO_SCALE
+            // We don't need to worry about NO_SCALE as that's just not putting
+            // an explicit width on the VideoElement.
+            if (value)
+                mx_internal::videoPlayer.scaleMode = VideoScaleMode.MAINTAIN_ASPECT_RATIO;
+            else
+                mx_internal::videoPlayer.scaleMode = VideoScaleMode.EXACT_FIT;
+
+            invalidateSize();
+            invalidateDisplayList();
+        }
+    }
+
+    //----------------------------------
+    //  playheadTime
+    //----------------------------------
+
+    [Bindable("playheadUpdate")]
+    [Inspectable(Category="General", defaultValue="0")]
+
+    /**
+     *  Playhead position, measured in seconds, since the video starting
+     *  playing.
+     *  The event object for many of the VideoPlay events include the playhead
+     *  position so that you can determine the location in the video file where
+     *  the event occurred.
+     *
+     *
Setting this property to a value in seconds performs a seek
+     *  operation.
+     *  If the video is currently playing,
+     *  it continues playing from the new playhead position.
+     *  If the video is paused, it seeks to
+     *  the new playhead position and remains paused.
+     *  If the video is stopped, it seeks to
+     *  the new playhead position and enters the paused state.
+     *  Setting this property has no effect with live video streams.

+     *
+     *
If the new playhead position is less than 0 or NaN,
+     *  the control throws an exception. If the new playhead position
+     *  is past the end of the video, or past the amount of the video file
+     *  downloaded so far, then the control still attempts the seek.

+     *
+     *
For an FLV file, setting the playheadTime property seeks
+     *  to the keyframe closest to the specified position, where
+     *  keyframes are specified in the FLV file at the time of encoding.
+     *  Therefore, you might not seek to the exact time if there
+     *  is no keyframe specified at that position.

+     *
+     *
This property throws an exception if set when no stream is
+     *  connected.  Use the stateChange event and the
+     *  connected property to determine when it is
+     *  safe to set this property.

+     *
+     *  @default 0
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function get playheadTime():Number
+    {
+        return mx_internal::videoPlayer.playheadTime;
+    }
+
+    public function set playheadTime(value:Number):void
+    {
+        mx_internal::videoPlayer.playheadTime = value;
+    }
+
+    //----------------------------------
+    //  source
+    //----------------------------------
+
+    private var _source:Object;
+    private var sourceChanged:Boolean;
+
+    [Bindable("sourceChanged")]
+    [Inspectable(category="General", defaultValue="null")]
+
+    /**
+     *  Path or URL of the video file or stream to play.  For
+     *  multi-bitrate, source can be set to an Array
+     *  of objects, where each object has a streamName and a bitRate
+     *  property.
+     *
+     *  @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
+    {
+        if (_source == value)
+            return;
+
+        _source = value;
+        sourceChanged = true;
+        dispatchEvent(new Event("sourceChanged"));
+        invalidateProperties();
+    }
+
+    //----------------------------------
+    //  totalTime
+    //----------------------------------
+
+    [Bindable("complete")]
+    [Bindable("metadataReceived")]
+    [Inspectable(Category="General", defaultValue="0")]
+
+    /**
+     *  Total time for the video feed.  -1 means that property
+     *  was not pass into play() or
+     *  we were unable to detect the total time automatically,
+     *  or have not yet.
+     *
+     *  @return The total running time of the FLV in seconds
+     *  @default 0
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function get totalTime():Number
+    {
+        return mx_internal::videoPlayer.totalTime;
+    }
+
+    //----------------------------------
+    //  volume
+    //----------------------------------
+
+    [Bindable("volumeChanged")]
+    [Inspectable(category="General", defaultValue="1.0")]
+
+    /**
+     *  The volume level, specified as an 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
+    {
+        if (mutedVolume == -1)
+            return mx_internal::videoPlayer.volume;
+        else
+            return mutedVolume;
+    }
+
+    /**
+     *  @private
+     */
+    public function set volume(value:Number):void
+    {
+        mutedVolume = -1;
+        mx_internal::videoPlayer.volume = value;
+        dispatchEvent(new Event("volumeChanged"));
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Overridden methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    override protected function commitProperties():void
+    {
+        super.commitProperties();
+
+        if (sourceChanged)
+        {
+            sourceChanged = false;
+            if (autoPlay)
+            {
+                play();
+            }
+            else
+            {
+                // TODO: should we load the video if autoPlay is false?
+                mx_internal::videoPlayer.load(source as String, NaN, isLive);
+            }
+        }
+    }
+
+    /**
+     *  @private
+     */
+    override protected function measure() : void
+    {
+        super.measure();
+
+        var vw:Number = mx_internal::videoPlayer.videoWidth;
+        var vh:Number = mx_internal::videoPlayer.videoHeight;
+
+        measuredWidth = vw;
+        measuredHeight = vh;
+
+        // 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 (_maintainAspectRatio && (bExplicitWidth || bExplicitHeight))
+        {
+            if (bExplicitWidth && !bExplicitHeight && vw > 0)
+                measuredHeight = explicitWidth * vh / vw;
+            else if (bExplicitHeight && !bExplicitWidth && vh > 0)
+                measuredWidth = explicitHeight * vw / vh;
+        }
+    }
+
+    /**
+     *  @private
+     */
+    override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void
+    {
+        super.updateDisplayList(unscaledWidth, unscaledHeight);
+
+        mx_internal::videoPlayer.width = Math.floor(unscaledWidth);
+        mx_internal::videoPlayer.height = Math.floor(unscaledHeight);
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Methods
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     *  mutedVolume tracks what the volume was before we were
+     *  muted.  If we aren't muted, mutedVolume = -1.
+     */
+    private var mutedVolume:Number = -1;
+
+    /**
+     *  Mutes the volume of the video.  The volume property will be
+     *  unaffected by this method, but the volume will be muted.  If the
+     *  volume is already muted, this method will have no effect.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function mute():void
+    {
+        if (mutedVolume != -1)
+            return;
+
+        mutedVolume = volume;
+        mx_internal::videoPlayer.volume = 0;
+    }
+
+    /**
+     *  Pauses playback without moving the playhead.
+     *  If playback is already is paused or is stopped, this method has no
+     *  effect.
+     *
+     *
To start playback again, call the play() method.

+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function pause():void
+    {
+        mx_internal::videoPlayer.pause();
+    }
+
+    /**
+     *  Causes the video to play.  Can be called while the video is
+     *  paused, stopped, or while the video is already playing.
+     *
+     *  @param startTime Time to start playing the clip from.
+     *  Pass in -1 to start at the beginning or the
+     *  current spot in the clip if paused.  Default is -1.
+     *  @param duration Duration, in seconds, to play.  Pass in -1
+     *  to automatically detect length from metadata, server
+     *  or xml.  Default is -1.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function play(startTime:Number=-1, duration:Number=-1):void
+    {
+        if (startTime != -1)
+            seek(startTime);
+
+        var source:String;
+
+        if (mx_internal::videoPlayer.state == VideoState.PAUSED)
+            source = null;
+        else
+            source = this.source as String;
+
+        mx_internal::videoPlayer.play(source, duration, isLive);
+    }
+
+    /**
+     *  Seeks to given second in video.  If video is playing,
+     *  continues playing from that point.  If video is paused, seek to
+     *  that point and remain paused.  If video is stopped, seek to
+     *  that point and enters paused state.  Has no effect with live
+     *  streams.
+     *
+     *
If time is less than 0 or NaN, throws exeption.  If time
+     *  is past the end of the stream, or past the amount of file
+     *  downloaded so far, then will attempt seek and when fails
+     *  will recover.

+     *
+     *  @param time seconds
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function seek(time:Number):void
+    {
+        if (time < 0)
+            time = 0;
+
+        mx_internal::videoPlayer.seek(time);
+    }
+
+    /**
+     *  Stops video playback.  If autoRewind is set to
+     *  true, rewinds to first frame.  If video is already
+     *  stopped, has no effect.  To start playback again, call
+     *  play().
+     *
+     *  @see #autoRewind
+     *  @see #play()
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function stop():void
+    {
+        mx_internal::videoPlayer.stop();
+    }
+
+    /**
+     *  Unmutes the volume of the video.  If the volume was muted, this
+     *  method will set the volume at its previous level.  If the
+     *  volume was not muted, this method will have no effect.
+     *
+     *  @langversion 3.0
+     *  @playerversion Flash 10
+     *  @playerversion AIR 1.5
+     *  @productversion Flex 4
+     */
+    public function unmute():void
+    {
+        if (mutedVolume == -1)
+            return;
+
+        mx_internal::videoPlayer.volume = mutedVolume;
+        mutedVolume = -1;
+    }
+
+    //--------------------------------------------------------------------------
+    //
+    //  Event handlers
+    //
+    //--------------------------------------------------------------------------
+
+    /**
+     *  @private
+     */
+    private function videoPlayer_closeHandler(event:fl.video.VideoEvent):void
+    {
+        var sparkVideoEvent:spark.events.VideoEvent = new spark.events.VideoEvent(event.type, event.bubbles, event.cancelable, event.playheadTime);
+        dispatchEvent(sparkVideoEvent);
+    }
+
+    /**
+     *  @private
+     */
+    private function videoPlayer_completeHandler(event:fl.video.VideoEvent):void
+    {
+        var sparkVideoEvent:spark.events.VideoEvent = new spark.events.VideoEvent(event.type, event.bubbles, event.cancelable, event.playheadTime);
+        dispatchEvent(sparkVideoEvent);
+    }
+
+    /**
+     *  @private
+     */
+    private function videoPlayer_metaDataReceivedHandler(event:fl.video.MetadataEvent):void
+    {
+        invalidateSize();
+        var sparkMetadataEvent:spark.events.MetadataEvent = new spark.events.MetadataEvent(event.type, event.bubbles, event.cancelable, event.info);
+        dispatchEvent(sparkMetadataEvent);
+    }
+
+    /**
+     *  @private
+     */
+    private function videoPlayer_playHeadUpdateHandler(event:fl.video.VideoEvent):void
+    {
+        var sparkVideoEvent:spark.events.VideoEvent = new spark.events.VideoEvent(event.type, event.bubbles, event.cancelable, event.playheadTime);
+        dispatchEvent(sparkVideoEvent);
+    }
+
+    /**
+     *  @private
+     */
+    private function videoPlayer_stateChangeHandler(event:fl.video.VideoEvent):void
+    {
+        switch (event.state)
+        {
+            case VideoState.PLAYING:
+                _isPlaying = true;
+                break;
+            case VideoState.PAUSED:
+            case VideoState.STOPPED:
+            case VideoState.DISCONNECTED:
+            case VideoState.CONNECTION_ERROR:
+                _isPlaying = false;
+                break;
+        }
+
+        dispatchEvent(event);
+    }
+}
+}


Transferred from the Adobe Open Source Subversion Repository

Revision: 7390
Author:   rfrishbe@adobe.com
Date:     2009-05-28T21:48:59.963797Z

Log Message:
-----------
Adding wireframe skins for VideoPlayer.

Also fixing up some other VideoPlayer bugs around fullscreen (going into normal mode wouldn't stop the timer to hide the controls correctly).  Fixed the pause() and stop() methods so that when we're not connected to a source to do nothing instead of RTEing.

Also updated the underlyign FLVPlayback control to the newest version.

Fixed some ASDoc issues in various files.

QE Notes: -
Doc Notes: -
Bugs: SDK-21435
Reviewer: Glenn
tests: checkintests

Modified Paths:
--------------
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/skins/default/VideoPlayerVolumeBarSkin.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/DataGroup.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/primitives/VideoElement.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/skins/default/VideoPlayerFullScreenButtonSkin.mxml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerScrubBarThumbSkin.mxml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerScrubBarSkin.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/wireframe/src/WireframeClasses.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/Group.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/wireframe/defaults.css</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/fl/video/DynamicStream.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/SkinnableDataContainer.as</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerSkin.mxml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerVolumeBarTrackSkin.mxml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerFullScreenFullScreenButtonSkin.mxml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerVolumeBarMuteButtonSkin.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/skins/default/VideoPlayerSkin.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/skins/default/VideoPlayerFullScreenFullScreenButtonSkin.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/fl/video/ComponentVersion.as</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/framework/src/mx/core/IVisualElementContainer.as</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerScrubBarTrackSkin.mxml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerVolumeBarSkin.mxml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerVolumeBarThumbSkin.mxml</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerFullScreenButtonSkin.mxml</path>
<path kind="file" action="M">/flex/sdk/trunk/frameworks/projects/flex4/src/spark/components/VideoPlayer.as</path>
<path kind="file" action="A">/flex/sdk/trunk/frameworks/projects/wireframe/src/spark/skins/wireframe/VideoPlayerPlayPauseButtonSkin.mxml</path>

git-svn-id: 7146a936b37d36e51ea0d66f8acbe0b8281bc7b7@1281099 13f79535-47bb-0310-9956-ffa450edef68

--- frameworks/projects/spark/src/spark/components/VideoDisplay.as
+++ frameworks/projects/spark/src/spark/components/VideoDisplay.as
@@ -811,6 +811,9 @@
      */
     public function pause():void
     {
+        if (source == null || videoPlayer.state == VideoState.CONNECTION_ERROR)
+            return;
+
         setPlaying(false);
         videoPlayer.pause();
     }
@@ -1033,6 +1036,9 @@
      */
     public function stop():void
     {
+        if (source == null || videoPlayer.state == VideoState.CONNECTION_ERROR)
+            return;
+
         setPlaying(false);
         videoPlayer.stop();
     }