1//////////////////////////////////////////////////////////////////////////////// 2// 3// ADOBE SYSTEMS INCORPORATED 4// Copyright 2009 Adobe Systems Incorporated 5// All Rights Reserved. 6// 7// NOTICE: Adobe permits you to use, modify, and distribute this file 8// in accordance with the terms of the license agreement accompanying it. 9// 10//////////////////////////////////////////////////////////////////////////////// 11 12package spark.components 13{ 14 15import flash.display.DisplayObject; 16import flash.display.StageDisplayState; 17import flash.events.Event; 18import flash.events.FullScreenEvent; 19import flash.events.KeyboardEvent; 20import flash.events.MouseEvent; 21import flash.events.TimerEvent; 22import flash.geom.Rectangle; 23import flash.media.Video; 24import flash.system.ApplicationDomain; 25import flash.utils.Timer; 26 27import mx.core.FlexGlobals; 28import mx.core.IVisualElementContainer; 29import mx.core.mx_internal; 30import mx.events.FlexEvent; 31import mx.managers.PopUpManager; 32import mx.utils.BitFlagUtil; 33 34import org.osmf.events.LoadEvent; 35import org.osmf.events.MediaPlayerStateChangeEvent; 36import org.osmf.events.TimeEvent; 37import org.osmf.media.MediaPlayerState; 38 39import spark.components.mediaClasses.MuteButton; 40import spark.components.mediaClasses.ScrubBar; 41import spark.components.mediaClasses.VolumeBar; 42import spark.components.supportClasses.ButtonBase; 43import spark.components.supportClasses.SkinnableComponent; 44import spark.components.supportClasses.ToggleButtonBase; 45import spark.core.IDisplayText; 46import spark.events.TrackBaseEvent; 47 48use namespace mx_internal; 49 50//-------------------------------------- 51// Events 52//-------------------------------------- 53 54/** 55 * Dispatched when the data is received as a download operation progresses. 56 * This event is only dispatched when playing a video by downloading it 57 * directly from a server, typically by issuing an HTTP request. 58 * It is not displatched when playing a video from a special media server, 59 * such as Flash Media Server. 60 * 61 * <p>This event may not be dispatched when the source is set to null or a playback 62 * error occurs.</p> 63 * 64 * @eventType org.osmf.events.LoadEvent.BYTES_LOADED_CHANGE 65 * 66 * @langversion 3.0 67 * @playerversion Flash 10 68 * @playerversion AIR 1.0 69 * @productversion Flex 4 70 */ 71[Event(name="bytesLoadedChange",type="org.osmf.events.LoadEvent")] 72 73/** 74 * Dispatched when the playhead reaches the duration for playable media. 75 * 76 * @eventType org.osmf.events.TimeEvent.COMPLETE 77 * 78 * @langversion 3.0 79 * @playerversion Flash 10 80 * @playerversion AIR 1.0 81 * @productversion Flex 4 82 */ 83[Event(name="complete", type="org.osmf.events.TimeEvent")] 84 85/** 86 * Dispatched when the <code>currentTime</code> property of the MediaPlayer has changed. 87 * 88 * <p>This event may not be dispatched when the source is set to null or a playback 89 * error occurs.</p> 90 * 91 * @eventType org.osmf.events.TimeEvent.CURRENT_TIME_CHANGE 92 * 93 * @langversion 3.0 94 * @playerversion Flash 10 95 * @playerversion AIR 1.0 96 * @productversion Flex 4 97 */ 98[Event(name="currentTimeChange",type="org.osmf.events.TimeEvent")] 99 100/** 101 * Dispatched when the <code>duration</code> property of the media has changed. 102 * 103 * <p>This event may not be dispatched when the source is set to null or a playback 104 * error occurs.</p> 105 * 106 * @eventType org.osmf.events.TimeEvent.DURATION_CHANGE 107 * 108 * @langversion 3.0 109 * @playerversion Flash 10 110 * @playerversion AIR 1.0 111 * @productversion Flex 4 112 */ 113[Event(name="durationChange", type="org.osmf.events.TimeEvent")] 114 115/** 116 * Dispatched when the MediaPlayer's state has changed. 117 * 118 * @eventType org.osmf.events.MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE 119 * 120 * @langversion 3.0 121 * @playerversion Flash 10 122 * @playerversion AIR 1.0 123 * @productversion Flex 4 124 */ 125[Event(name="mediaPlayerStateChange", type="org.osmf.events.MediaPlayerStateChangeEvent")] 126 127//-------------------------------------- 128// Styles 129//-------------------------------------- 130 131include "../styles/metadata/BasicInheritingTextStyles.as"; 132 133/** 134 * Controls the visibility of the drop shadow for this component. 135 * 136 * @default true 137 * 138 * @langversion 3.0 139 * @playerversion Flash 10 140 * @playerversion AIR 1.5 141 * @productversion Flex 4 142 */ 143[Style(name="dropShadowVisible", type="Boolean", inherit="no", theme="spark")] 144 145/** 146 * The time, in milli-seconds, to wait in fullscreen mode with no user-interaction 147 * before hiding the video playback controls. 148 * 149 * <p>If set to <code>Infinity</code>, then the playback controls will not 150 * be hidden in fullscreen mode. Changing this value while already in 151 * fullscreen mode has no effect.</p> 152 * 153 * @default 3000 154 * 155 * @langversion 3.0 156 * @playerversion Flash 10 157 * @playerversion AIR 1.5 158 * @productversion Flex 4 159 */ 160[Style(name="fullScreenHideControlsDelay", type="Number", format="Time", inherit="no")] 161 162/** 163 * @copy spark.components.supportClasses.GroupBase#style:symbolColor 164 * 165 * @langversion 3.0 166 * @playerversion Flash 10 167 * @playerversion AIR 1.5 168 * @productversion Flex 4 169 */ 170[Style(name="symbolColor", type="uint", format="Color", inherit="yes", theme="spark")] 171 172//-------------------------------------- 173// SkinStates 174//-------------------------------------- 175 176/** 177 * Uninitialized state of the VideoPlayer. 178 * The Video Player has been constructed at this point, 179 * but the source has not been set and no connection 180 * attempt is in progress. 181 * 182 * @langversion 3.0 183 * @playerversion Flash 10 184 * @playerversion AIR 1.5 185 * @productversion Flex 4 186 */ 187[SkinState("uninitialized")] 188 189/** 190 * Loading state of the VideoPlayer. 191 * The VideoPlayer is loading or connecting to the source. 192 * 193 * @langversion 3.0 194 * @playerversion Flash 10 195 * @playerversion AIR 1.5 196 * @productversion Flex 4 197 */ 198[SkinState("loading")] 199 200/** 201 * Ready state of the VideoPlayer. 202 * The video is ready to be played. 203 * 204 * @langversion 3.0 205 * @playerversion Flash 10 206 * @playerversion AIR 1.5 207 * @productversion Flex 4 208 */ 209[SkinState("ready")] 210 211/** 212 * Playing state of the VideoPlayer 213 * 214 * @langversion 3.0 215 * @playerversion Flash 10 216 * @playerversion AIR 1.5 217 * @productversion Flex 4 218 */ 219[SkinState("playing")] 220 221/** 222 * Paused state of the VideoPlayer 223 * 224 * @langversion 3.0 225 * @playerversion Flash 10 226 * @playerversion AIR 1.5 227 * @productversion Flex 4 228 */ 229[SkinState("paused")] 230 231/** 232 * Buffering state of the VideoPlayer 233 * 234 * @langversion 3.0 235 * @playerversion Flash 10 236 * @playerversion AIR 1.5 237 * @productversion Flex 4 238 */ 239[SkinState("buffering")] 240 241/** 242 * Playback Error state of the VideoPlayer. 243 * An error was encountered while trying to play the video. 244 * 245 * @langversion 3.0 246 * @playerversion Flash 10 247 * @playerversion AIR 1.5 248 * @productversion Flex 4 249 */ 250[SkinState("playbackError")] 251 252/** 253 * Disabled state of the VideoPlayer 254 * 255 * @langversion 3.0 256 * @playerversion Flash 10 257 * @playerversion AIR 1.5 258 * @productversion Flex 4 259 */ 260[SkinState("disabled")] 261 262/** 263 * Uninitialized state of the VideoPlayer when 264 * in full screen mode. 265 * The Video Player has been constructed at this point, 266 * but the source has not been set and no connection 267 * attempt is in progress. 268 * 269 * @langversion 3.0 270 * @playerversion Flash 10 271 * @playerversion AIR 1.5 272 * @productversion Flex 4 273 */ 274[SkinState("uninitializedAndFullScreen")] 275 276/** 277 * Loading state of the VideoPlayer when 278 * in full screen mode. 279 * The VideoPlayer is loading or connecting to the source. 280 * 281 * @langversion 3.0 282 * @playerversion Flash 10 283 * @playerversion AIR 1.5 284 * @productversion Flex 4 285 */ 286[SkinState("loadingAndFullScreen")] 287 288/** 289 * Ready state of the VideoPlayer when 290 * in full screen mode. The video is ready to be played. 291 * 292 * @langversion 3.0 293 * @playerversion Flash 10 294 * @playerversion AIR 1.5 295 * @productversion Flex 4 296 */ 297[SkinState("readyAndFullScreen")] 298 299/** 300 * Playing state of the VideoPlayer when 301 * in full screen mode. 302 * 303 * @langversion 3.0 304 * @playerversion Flash 10 305 * @playerversion AIR 1.5 306 * @productversion Flex 4 307 */ 308[SkinState("playingAndFullScreen")] 309 310/** 311 * Paused state of the VideoPlayer when 312 * in full screen mode. 313 * 314 * @langversion 3.0 315 * @playerversion Flash 10 316 * @playerversion AIR 1.5 317 * @productversion Flex 4 318 */ 319[SkinState("pausedAndFullScreen")] 320 321/** 322 * Buffering state of the VideoPlayer when 323 * in full screen mode. 324 * 325 * @langversion 3.0 326 * @playerversion Flash 10 327 * @playerversion AIR 1.5 328 * @productversion Flex 4 329 */ 330[SkinState("bufferingAndFullScreen")] 331 332/** 333 * Playback Error state of the VideoPlayer when 334 * in full screen mode. 335 * An error was encountered while trying to play the video. 336 * 337 * @langversion 3.0 338 * @playerversion Flash 10 339 * @playerversion AIR 1.5 340 * @productversion Flex 4 341 */ 342[SkinState("playbackErrorAndFullScreen")] 343 344/** 345 * Disabled state of the VideoPlayer when 346 * in full screen mode. 347 * 348 * @langversion 3.0 349 * @playerversion Flash 10 350 * @playerversion AIR 1.5 351 * @productversion Flex 4 352 */ 353[SkinState("disabledAndFullScreen")] 354 355//-------------------------------------- 356// Excluded APIs 357//-------------------------------------- 358 359[Exclude(name="focusBlendMode", kind="style")] 360[Exclude(name="focusThickness", kind="style")] 361 362//-------------------------------------- 363// Other metadata 364//-------------------------------------- 365 366[AccessibilityClass(implementation="spark.accessibility.VideoPlayerAccImpl")] 367 368[DefaultProperty("source")] 369 370[IconFile("VideoPlayer.png")] 371 372/** 373 * Because this component does not define a skin for the mobile theme, Adobe 374 * recommends that you not use it in a mobile application. Alternatively, you 375 * can define your own mobile skin for the component. For more information, 376 * see <a href="http://help.adobe.com/en_US/flex/mobileapps/WS19f279b149e7481c698e85712b3011fe73-8000.html">Basics of mobile skinning</a>. 377 */ 378[DiscouragedForProfile("mobileDevice")] 379 380/** 381 * The VideoPlayer control is a skinnable video player that supports 382 * progressive download, multi-bitrate streaming, and streaming video. 383 * It supports playback of FLV and F4v files. The VideoPlayer control 384 * contains a full-featured UI for controlling video playback. 385 * 386 * <p><code>VideoDisplay</code> is the chromeless version that does not support skinning. 387 * It is useful when you do not want the user to interact with the control.</p> 388 * 389 * <p>The VideoPlayer control has the following default characteristics:</p> 390 * <table class="innertable"> 391 * <tr> 392 * <th>Characteristic</th> 393 * <th>Description</th> 394 * </tr> 395 * <tr> 396 * <td>Default size</td> 397 * <td>263 pixels wide by 184 pixels high</td> 398 * </tr> 399 * <tr> 400 * <td>Minimum size</td> 401 * <td>0</td> 402 * </tr> 403 * <tr> 404 * <td>Maximum size</td> 405 * <td>10000 pixels wide and 10000 pixels high</td> 406 * </tr> 407 * <tr> 408 * <td>Default skin class</td> 409 * <td>spark.skins.spark.VideoPlayerSkin</td> 410 * </tr> 411 * </table> 412 * 413 * @see spark.components.VideoDisplay 414 * @see spark.skins.spark.VideoPlayerSkin 415 * @see spark.skins.spark.mediaClasses.fullScreen.FullScreenButtonSkin 416 * @see spark.skins.spark.mediaClasses.fullScreen.MuteButtonSkin 417 * @see spark.skins.spark.mediaClasses.fullScreen.PlayPauseButtonSkin 418 * @see spark.skins.spark.mediaClasses.fullScreen.ScrubBarSkin 419 * @see spark.skins.spark.mediaClasses.fullScreen.ScrubBarThumbSkin 420 * @see spark.skins.spark.mediaClasses.fullScreen.ScrubBarTrackSkin 421 * @see spark.skins.spark.mediaClasses.fullScreen.VolumeBarSkin 422 * @see spark.skins.spark.mediaClasses.fullScreen.VolumeBarThumbSkin 423 * @see spark.skins.spark.mediaClasses.fullScreen.VolumeBarTrackSkin 424 * @see spark.skins.spark.mediaClasses.normal.FullScreenButtonSkin 425 * @see spark.skins.spark.mediaClasses.normal.MuteButtonSkin 426 * @see spark.skins.spark.mediaClasses.normal.PlayPauseButtonSkin 427 * @see spark.skins.spark.mediaClasses.normal.ScrubBarSkin 428 * @see spark.skins.spark.mediaClasses.normal.ScrubBarThumbSkin 429 * @see spark.skins.spark.mediaClasses.normal.ScrubBarTrackSkin 430 * @see spark.skins.spark.mediaClasses.normal.VolumeBarSkin 431 * @see spark.skins.spark.mediaClasses.normal.VolumeBarThumbSkin 432 * @see spark.skins.spark.mediaClasses.normal.VolumeBarTrackSkin 433 * 434 * @mxml 435 * 436 * <p>The <code><s:VideoPlayer></code> tag inherits all of the tag 437 * attributes of its superclass and adds the following tag attributes:</p> 438 * 439 * <pre> 440 * <s:VideoPlayer 441 442 * <strong>Properties</strong> 443 * autoDisplayFirstFrame="true" 444 * autoPlay="true" 445 * autoRewind="true" 446 * loop="false" 447 * muted="false" 448 * pauseWhenHidden="true" 449 * scaleMode="letterbox" 450 * source="" 451 * volume="1" 452 * 453 * <strong>Events</strong> 454 * bytesLoadedChange="<i>No default</i>" 455 * complete="<i>No default</i>" 456 * currentTimeChange="<i>No default</i>" 457 * durationChange="<i>No default</i>" 458 * mediaPlayerStateChange="<i>No default</i>" 459 * 460 * 461 * <strong>Styles</strong> 462 * alignmentBaseline="baseline" 463 * baselineShift="0" 464 * cffHinting="0.0" 465 * color="0x000000" 466 * digitCase="default" 467 * digitWidth="default" 468 * direction="ltr" 469 * dominantBaseline="auto" 470 * dropShadowVisible="true" 471 * fontFamily="Arial" 472 * fontLookup="device" 473 * fontSize="12" 474 * fontStyle="normal" 475 * fontWeight="normal" 476 * justificationRule="auto" 477 * justificationStyle="auto" 478 * kerning="false" 479 * ligatureLevel="common" 480 * lineHeight="120%" 481 * lineThrough="false%" 482 * locale="en" 483 * renderingMode="cff" 484 * textAlign="start" 485 * textAlignLast="start" 486 * textAlpha="1" 487 * textDecoration="start" 488 * textJustify="interWord" 489 * trackingLeft="0" 490 * trackingRight="00" 491 * typographicCase="default" 492 * /> 493 * </pre> 494 * 495 * @includeExample examples/VideoPlayerExample.mxml 496 * 497 * @langversion 3.0 498 * @playerversion Flash 10 499 * @playerversion AIR 1.5 500 * @productversion Flex 4 501 */ 502public class VideoPlayer extends SkinnableComponent 503{ 504 include "../core/Version.as"; 505 506 //-------------------------------------------------------------------------- 507 // 508 // Class constants 509 // 510 //-------------------------------------------------------------------------- 511 512 /** 513 * @private 514 */ 515 private static const AUTO_DISPLAY_FIRST_FRAME_PROPERTY_FLAG:uint = 1 << 0; 516 517 /** 518 * @private 519 */ 520 private static const AUTO_PLAY_PROPERTY_FLAG:uint = 1 << 1; 521 522 /** 523 * @private 524 */ 525 private static const AUTO_REWIND_PROPERTY_FLAG:uint = 1 << 2; 526 527 /** 528 * @private 529 */ 530 private static const LOOP_PROPERTY_FLAG:uint = 1 << 3; 531 532 /** 533 * @private 534 */ 535 private static const SCALE_MODE_PROPERTY_FLAG:uint = 1 << 4; 536 537 /** 538 * @private 539 */ 540 private static const MUTED_PROPERTY_FLAG:uint = 1 << 5; 541 542 /** 543 * @private 544 */ 545 private static const SOURCE_PROPERTY_FLAG:uint = 1 << 6; 546 547 /** 548 * @private 549 */ 550 private static const VOLUME_PROPERTY_FLAG:uint = 1 << 7; 551 552 /** 553 * @private 554 */ 555 private static const PAUSE_WHEN_HIDDEN_PROPERTY_FLAG:uint = 1 << 8; 556 557 /** 558 * @private 559 */ 560 private static const THUMBNAIL_SOURCE_PROPERTY_FLAG:uint = 1 << 9; 561 562 563 //-------------------------------------------------------------------------- 564 // 565 // Class properties 566 // 567 //-------------------------------------------------------------------------- 568 569 /** 570 * @private 571 */ 572 private static var _screenClass:Class; 573 574 /** 575 * @private 576 */ 577 private static var checkedForScreenClass:Boolean; 578 579 /** 580 * @private 581 */ 582 private static function get screenClass():Class 583 { 584 if (!checkedForScreenClass) 585 { 586 checkedForScreenClass = true; 587 588 if (ApplicationDomain.currentDomain. 589 hasDefinition("flash.display::Screen")) 590 { 591 _screenClass = Class(ApplicationDomain.currentDomain. 592 getDefinition("flash.display::Screen")); 593 } 594 } 595 596 return _screenClass; 597 } 598 599 //-------------------------------------------------------------------------- 600 // 601 // Class mixins 602 // 603 //-------------------------------------------------------------------------- 604 605 /** 606 * @private 607 * Placeholder for mixin by VideoPlayerAccImpl. 608 */ 609 mx_internal static var createAccessibilityImplementation:Function; 610 611 //-------------------------------------------------------------------------- 612 // 613 // Constructor 614 // 615 //-------------------------------------------------------------------------- 616 617 /** 618 * Constructor. 619 * 620 * @langversion 3.0 621 * @playerversion Flash 10 622 * @playerversion AIR 1.5 623 * @productversion Flex 4 624 */ 625 public function VideoPlayer() 626 { 627 super(); 628 } 629 630 //-------------------------------------------------------------------------- 631 // 632 // Skin Parts 633 // 634 //-------------------------------------------------------------------------- 635 636 [SkinPart(required="true")] 637 638 /** 639 * A required skin part that defines the VideoDisplay. 640 * 641 * @langversion 3.0 642 * @playerversion Flash 10 643 * @playerversion AIR 1.5 644 * @productversion Flex 4 645 */ 646 public var videoDisplay:VideoDisplay; 647 648 [SkinPart(required="false")] 649 650 /** 651 * An optional skin part to display the current value of <code>codecurrentTime</code>. 652 * 653 * @langversion 3.0 654 * @playerversion Flash 10 655 * @playerversion AIR 1.5 656 * @productversion Flex 4 657 */ 658 public var currentTimeDisplay:IDisplayText; 659 660 [SkinPart(required="false")] 661 662 /** 663 * An optional skin part for a button to toggle fullscreen mode. 664 * 665 * @langversion 3.0 666 * @playerversion Flash 10 667 * @playerversion AIR 1.5 668 * @productversion Flex 4 669 */ 670 public var fullScreenButton:ButtonBase; 671 672 [SkinPart(required="false")] 673 674 /** 675 * An optional skin part for the mute button. The mute 676 * button has both a <code>muted</code> property and a 677 * <code>volume</code> property. 678 * 679 * @langversion 3.0 680 * @playerversion Flash 10 681 * @playerversion AIR 1.5 682 * @productversion Flex 4 683 */ 684 public var muteButton:MuteButton; 685 686 [SkinPart(required="false")] 687 688 /** 689 * An optional skin part for the pause button. 690 * 691 * @langversion 3.0 692 * @playerversion Flash 10 693 * @playerversion AIR 1.5 694 * @productversion Flex 4 695 */ 696 public var pauseButton:ButtonBase; 697 698 [SkinPart(required="false")] 699 700 /** 701 * An optional skin part for the play button. 702 * 703 * @langversion 3.0 704 * @playerversion Flash 10 705 * @playerversion AIR 1.5 706 * @productversion Flex 4 707 */ 708 public var playButton:ButtonBase; 709 710 [SkinPart(required="false")] 711 712 /** 713 * An optional skin part for all of the player controls. 714 * This skin is used to determine what to hide when the player is in full screen 715 * mode and there has been no user interaction. 716 * 717 * @langversion 3.0 718 * @playerversion Flash 10 719 * @playerversion AIR 1.5 720 * @productversion Flex 4 721 */ 722 public var playerControls:DisplayObject; 723 724 [SkinPart(required="false")] 725 726 /** 727 * An optional skin part for a play/pause button. When the 728 * video is playing, the <code>selected</code> property is set to 729 * <code>true</code>. When the video is paused or stopped, 730 * the <code>selected</code> property is set to <code>false</code>. 731 * 732 * @langversion 3.0 733 * @playerversion Flash 10 734 * @playerversion AIR 1.5 735 * @productversion Flex 4 736 */ 737 public var playPauseButton:ToggleButtonBase; 738 739 [SkinPart(required="false")] 740 741 /** 742 * An optional skin part for the scrub bar (the 743 * timeline). 744 * 745 * @langversion 3.0 746 * @playerversion Flash 10 747 * @playerversion AIR 1.5 748 * @productversion Flex 4 749 */ 750 public var scrubBar:ScrubBar; 751 752 [SkinPart(required="false")] 753 754 /** 755 * An optional skin part for the stop button. 756 * 757 * @langversion 3.0 758 * @playerversion Flash 10 759 * @playerversion AIR 1.5 760 * @productversion Flex 4 761 */ 762 public var stopButton:ButtonBase; 763 764 [SkinPart(required="false")] 765 766 /** 767 * An optional skin part to display the duration. 768 * 769 * @langversion 3.0 770 * @playerversion Flash 10 771 * @playerversion AIR 1.5 772 * @productversion Flex 4 773 */ 774 public var durationDisplay:IDisplayText; 775 776 [SkinPart(required="false")] 777 778 /** 779 * An optional skin part for the volume control. 780 * 781 * @langversion 3.0 782 * @playerversion Flash 10 783 * @playerversion AIR 1.5 784 * @productversion Flex 4 785 */ 786 public var volumeBar:VolumeBar; 787 788 //-------------------------------------------------------------------------- 789 // 790 // Variables 791 // 792 //-------------------------------------------------------------------------- 793 794 /** 795 * @private 796 * Several properties are proxied to videoDisplay. However, when videoDisplay 797 * is not around, we need to store values set on VideoPlayer. This object 798 * stores those values. If videoDisplay is around, the values are stored 799 * on the videoDisplay directly. However, we need to know what values 800 * have been set by the developer on the VideoPlayer (versus set on 801 * the videoDisplay or defaults of the videoDisplay) as those are values 802 * we want to carry around if the videoDisplay changes (via a new skin). 803 * In order to store this info effeciently, videoDisplayProperties becomes 804 * a uint to store a series of BitFlags. These bits represent whether a 805 * property has been explicitely set on this VideoPlayer. When the 806 * contentGroup is not around, videoDisplayProperties is a typeless 807 * object to store these proxied properties. When videoDisplay is around, 808 * videoDisplayProperties stores booleans as to whether these properties 809 * have been explicitely set or not. 810 */ 811 private var videoDisplayProperties:Object = {}; 812 813 /** 814 * @private 815 * The value of the pauseWhenHidden property before exiting 816 * fullScreen. We need to store it away here so we can 817 * restore it at commitProperties() time because of an AIR 818 * Mac bug. 819 */ 820 private var exitingFullScreenPauseWhenHidden:Boolean; 821 822 /** 823 * @private 824 * Whether the pauseWhenHidden property needs to be updated. 825 */ 826 private var needsToUpdatePauseWhenHidden:Boolean = false; 827 828 //-------------------------------------------------------------------------- 829 // 830 // Properties 831 // 832 //-------------------------------------------------------------------------- 833 834 //---------------------------------- 835 // autoDisplayFirstFrame 836 //---------------------------------- 837 838 [Inspectable(category="General", defaultValue="true")] 839 840 /** 841 * @copy spark.components.VideoDisplay#autoDisplayFirstFrame 842 * 843 * @default true 844 * 845 * @langversion 3.0 846 * @playerversion Flash 10 847 * @playerversion AIR 1.5 848 * @productversion Flex 4 849 */ 850 public function get autoDisplayFirstFrame():Boolean 851 { 852 if (videoDisplay) 853 { 854 return videoDisplay.autoDisplayFirstFrame; 855 } 856 else 857 { 858 var v:* = videoDisplayProperties.autoDisplayFirstFrame; 859 return (v === undefined) ? true : v; 860 } 861 } 862 863 /** 864 * @private 865 */ 866 public function set autoDisplayFirstFrame(value:Boolean):void 867 { 868 if (videoDisplay) 869 { 870 videoDisplay.autoDisplayFirstFrame = value; 871 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 872 AUTO_DISPLAY_FIRST_FRAME_PROPERTY_FLAG, true); 873 } 874 else 875 { 876 videoDisplayProperties.autoDisplayFirstFrame = value; 877 } 878 } 879 880 //---------------------------------- 881 // autoPlay 882 //---------------------------------- 883 884 [Inspectable(category="General", defaultValue="true")] 885 886 /** 887 * @copy spark.components.VideoDisplay#autoPlay 888 * 889 * @default true 890 * 891 * @langversion 3.0 892 * @playerversion Flash 10 893 * @playerversion AIR 1.5 894 * @productversion Flex 4 895 */ 896 public function get autoPlay():Boolean 897 { 898 if (videoDisplay) 899 { 900 return videoDisplay.autoPlay; 901 } 902 else 903 { 904 var v:* = videoDisplayProperties.autoPlay; 905 return (v === undefined) ? true : v; 906 } 907 } 908 909 /** 910 * @private 911 */ 912 public function set autoPlay(value:Boolean):void 913 { 914 if (videoDisplay) 915 { 916 videoDisplay.autoPlay = value; 917 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 918 AUTO_PLAY_PROPERTY_FLAG, true); 919 } 920 else 921 { 922 videoDisplayProperties.autoPlay = value; 923 } 924 } 925 926 //---------------------------------- 927 // autoRewind 928 //---------------------------------- 929 930 [Inspectable(category="General", defaultValue="true")] 931 932 /** 933 * @copy spark.components.VideoDisplay#autoRewind 934 * 935 * @default true 936 * 937 * @langversion 3.0 938 * @playerversion Flash 10 939 * @playerversion AIR 1.5 940 * @productversion Flex 4 941 */ 942 public function get autoRewind():Boolean 943 { 944 if (videoDisplay) 945 { 946 return videoDisplay.autoRewind; 947 } 948 else 949 { 950 var v:* = videoDisplayProperties.autoRewind; 951 return (v === undefined) ? true : v; 952 } 953 } 954 955 /** 956 * @private 957 */ 958 public function set autoRewind(value:Boolean):void 959 { 960 if (videoDisplay) 961 { 962 videoDisplay.autoRewind = value; 963 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 964 AUTO_REWIND_PROPERTY_FLAG, true); 965 } 966 else 967 { 968 videoDisplayProperties.autoRewind = value; 969 } 970 } 971 972 //---------------------------------- 973 // bytesLoaded 974 //---------------------------------- 975 976 [Inspectable(Category="General", defaultValue="0")] 977 [Bindable("bytesLoadedChange")] 978 [Bindable("mediaPlayerStateChange")] 979 980 /** 981 * @copy spark.components.VideoDisplay#bytesLoaded 982 * 983 * @default 0 984 * 985 * @langversion 3.0 986 * @playerversion Flash 10 987 * @playerversion AIR 1.5 988 * @productversion Flex 4 989 */ 990 public function get bytesLoaded():Number 991 { 992 if (videoDisplay) 993 return videoDisplay.bytesLoaded; 994 else 995 return 0; 996 } 997 998 //---------------------------------- 999 // bytesTotal 1000 //---------------------------------- 1001 1002 [Inspectable(Category="General", defaultValue="0")] 1003 [Bindable("mediaPlayerStateChange")] 1004 1005 /** 1006 * @copy spark.components.VideoDisplay#bytesTotal 1007 * 1008 * @default 0 1009 * 1010 * @langversion 3.0 1011 * @playerversion Flash 10 1012 * @playerversion AIR 1.5 1013 * @productversion Flex 4 1014 */ 1015 public function get bytesTotal():Number 1016 { 1017 if (videoDisplay) 1018 return videoDisplay.bytesTotal; 1019 else 1020 return 0; 1021 } 1022 1023 //---------------------------------- 1024 // currentTime 1025 //---------------------------------- 1026 1027 [Inspectable(Category="General", defaultValue="0")] 1028 [Bindable("currentTimeChange")] 1029 [Bindable("mediaPlayerStateChange")] 1030 1031 /** 1032 * @copy spark.components.VideoDisplay#currentTime 1033 * 1034 * @default 0 1035 * 1036 * @langversion 3.0 1037 * @playerversion Flash 10 1038 * @playerversion AIR 1.5 1039 * @productversion Flex 4 1040 */ 1041 public function get currentTime():Number 1042 { 1043 if (videoDisplay) 1044 return videoDisplay.currentTime; 1045 else 1046 return 0; 1047 } 1048 1049 //---------------------------------- 1050 // duration 1051 //---------------------------------- 1052 1053 [Inspectable(Category="General", defaultValue="0")] 1054 [Bindable("durationChange")] 1055 [Bindable("mediaPlayerStateChange")] 1056 1057 /** 1058 * @copy spark.components.VideoDisplay#duration 1059 * 1060 * @default 0 1061 * 1062 * @langversion 3.0 1063 * @playerversion Flash 10 1064 * @playerversion AIR 1.5 1065 * @productversion Flex 4 1066 */ 1067 public function get duration():Number 1068 { 1069 if (videoDisplay) 1070 return videoDisplay.duration; 1071 else 1072 return 0; 1073 } 1074 1075 //---------------------------------- 1076 // loop 1077 //---------------------------------- 1078 1079 [Inspectable(Category="General", defaultValue="false")] 1080 1081 /** 1082 * @copy spark.components.VideoDisplay#loop 1083 * 1084 * @default false 1085 * 1086 * @langversion 3.0 1087 * @playerversion Flash 10 1088 * @playerversion AIR 1.5 1089 * @productversion Flex 4 1090 */ 1091 public function get loop():Boolean 1092 { 1093 if (videoDisplay) 1094 { 1095 return videoDisplay.loop; 1096 } 1097 else 1098 { 1099 var v:* = videoDisplayProperties.loop; 1100 return (v === undefined) ? false : v; 1101 } 1102 } 1103 1104 /** 1105 * @private 1106 */ 1107 public function set loop(value:Boolean):void 1108 { 1109 if (videoDisplay) 1110 { 1111 videoDisplay.loop = value; 1112 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 1113 LOOP_PROPERTY_FLAG, true); 1114 } 1115 else 1116 { 1117 videoDisplayProperties.loop = value; 1118 } 1119 } 1120 1121 //---------------------------------- 1122 // mediaPlayerState 1123 //---------------------------------- 1124 1125 [Inspectable(category="General", defaultValue="uninitialized")] 1126 [Bindable("mediaPlayerStateChange")] 1127 1128 /** 1129 * @copy spark.components.VideoDisplay#mediaPlayerState 1130 * 1131 * @default uninitialized 1132 * 1133 * @see org.osmf.media.MediaPlayerState 1134 * 1135 * @langversion 3.0 1136 * @playerversion Flash 10 1137 * @playerversion AIR 1.5 1138 * @productversion Flex 4 1139 */ 1140 public function get mediaPlayerState():String 1141 { 1142 if (videoDisplay) 1143 return videoDisplay.mediaPlayerState; 1144 else 1145 return MediaPlayerState.UNINITIALIZED; 1146 } 1147 1148 //---------------------------------- 1149 // muted 1150 //---------------------------------- 1151 1152 [Inspectable(category="General", defaultValue="false")] 1153 [Bindable("volumeChanged")] 1154 1155 /** 1156 * @copy spark.components.VideoDisplay#muted 1157 * 1158 * @default false 1159 * 1160 * @langversion 3.0 1161 * @playerversion Flash 10 1162 * @playerversion AIR 1.5 1163 * @productversion Flex 4 1164 */ 1165 public function get muted():Boolean 1166 { 1167 if (videoDisplay) 1168 { 1169 return videoDisplay.muted; 1170 } 1171 else 1172 { 1173 var v:* = videoDisplayProperties.muted; 1174 return (v === undefined) ? false : v; 1175 } 1176 } 1177 1178 /** 1179 * @private 1180 */ 1181 public function set muted(value:Boolean):void 1182 { 1183 if (videoDisplay) 1184 { 1185 videoDisplay.muted = value; 1186 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 1187 MUTED_PROPERTY_FLAG, true); 1188 } 1189 else 1190 { 1191 videoDisplayProperties.muted = value; 1192 } 1193 1194 if (volumeBar) 1195 volumeBar.muted = value; 1196 if (muteButton) 1197 muteButton.muted = value; 1198 } 1199 1200 //---------------------------------- 1201 // pauseWhenHidden 1202 //---------------------------------- 1203 1204 [Inspectable(category="General", defaultValue="true")] 1205 1206 /** 1207 * @copy spark.components.VideoDisplay#pauseWhenHidden 1208 * 1209 * @default true 1210 * 1211 * @langversion 3.0 1212 * @playerversion Flash 10 1213 * @playerversion AIR 1.5 1214 * @productversion Flex 4 1215 */ 1216 public function get pauseWhenHidden():Boolean 1217 { 1218 if (needsToUpdatePauseWhenHidden) 1219 { 1220 return exitingFullScreenPauseWhenHidden; 1221 } 1222 else if (videoDisplay) 1223 { 1224 return videoDisplay.pauseWhenHidden; 1225 } 1226 else 1227 { 1228 var v:* = videoDisplayProperties.pauseWhenHidden; 1229 return (v === undefined) ? false : v; 1230 } 1231 } 1232 1233 /** 1234 * @private 1235 */ 1236 public function set pauseWhenHidden(value:Boolean):void 1237 { 1238 if (needsToUpdatePauseWhenHidden) 1239 { 1240 exitingFullScreenPauseWhenHidden = value; 1241 } 1242 else if (videoDisplay) 1243 { 1244 videoDisplay.pauseWhenHidden = value; 1245 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 1246 PAUSE_WHEN_HIDDEN_PROPERTY_FLAG, true); 1247 } 1248 else 1249 { 1250 videoDisplayProperties.pauseWhenHidden = value; 1251 } 1252 } 1253 1254 //---------------------------------- 1255 // playing 1256 //---------------------------------- 1257 1258 [Inspectable(category="General")] 1259 [Bindable("mediaPlayerStateChange")] 1260 1261 /** 1262 * @copy spark.components.VideoDisplay#playing 1263 * 1264 * @langversion 3.0 1265 * @playerversion Flash 10 1266 * @playerversion AIR 1.5 1267 * @productversion Flex 4 1268 */ 1269 public function get playing():Boolean 1270 { 1271 if (videoDisplay) 1272 return videoDisplay.playing; 1273 else 1274 return false; 1275 } 1276 1277 //---------------------------------- 1278 // scaleMode 1279 //---------------------------------- 1280 1281 [Inspectable(Category="General", enumeration="none,stretch,letterbox,zoom", defaultValue="letterbox")] 1282 1283 /** 1284 * @copy spark.components.VideoDisplay#scaleMode 1285 * 1286 * @default "letterbox" 1287 * 1288 * @see org.osmf.display.ScaleMode 1289 * 1290 * @langversion 3.0 1291 * @playerversion Flash 10 1292 * @playerversion AIR 1.5 1293 * @productversion Flex 4 1294 */ 1295 public function get scaleMode():String 1296 { 1297 if (videoDisplay) 1298 { 1299 return videoDisplay.scaleMode; 1300 } 1301 else 1302 { 1303 var v:* = videoDisplayProperties.scaleMode; 1304 return (v === undefined) ? "letterbox" : v; 1305 } 1306 } 1307 1308 /** 1309 * @private 1310 */ 1311 public function set scaleMode(value:String):void 1312 { 1313 if (videoDisplay) 1314 { 1315 videoDisplay.scaleMode = value; 1316 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 1317 SCALE_MODE_PROPERTY_FLAG, true); 1318 } 1319 else 1320 { 1321 videoDisplayProperties.scaleMode = value; 1322 } 1323 } 1324 1325 //---------------------------------- 1326 // source 1327 //---------------------------------- 1328 1329 [Inspectable(category="General", defaultValue="null")] 1330 [Bindable("sourceChanged")] 1331 1332 /** 1333 * @copy spark.components.VideoDisplay#source 1334 * 1335 * @default null 1336 * 1337 * @langversion 3.0 1338 * @playerversion Flash 10 1339 * @playerversion AIR 1.5 1340 * @productversion Flex 4 1341 */ 1342 public function get source():Object 1343 { 1344 if (videoDisplay) 1345 { 1346 return videoDisplay.source; 1347 } 1348 else 1349 { 1350 var v:* = videoDisplayProperties.source; 1351 return (v === undefined) ? null : v; 1352 } 1353 } 1354 1355 /** 1356 * @private 1357 */ 1358 public function set source(value:Object):void 1359 { 1360 if (videoDisplay) 1361 { 1362 videoDisplay.source = value; 1363 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 1364 SOURCE_PROPERTY_FLAG, true); 1365 } 1366 else 1367 { 1368 videoDisplayProperties.source = value; 1369 } 1370 } 1371 1372 //---------------------------------- 1373 // thumbnailSource 1374 //---------------------------------- 1375 1376 [Inspectable(category="General")] 1377 1378 /** 1379 * @private 1380 * @copy spark.components.VideoDisplay#thumbnailSource 1381 * 1382 * @langversion 3.0 1383 * @playerversion Flash 10 1384 * @playerversion AIR 1.5 1385 * @productversion Flex 4 1386 */ 1387 mx_internal function get thumbnailSource():Object 1388 { 1389 if (videoDisplay) 1390 { 1391 return videoDisplay.thumbnailSource; 1392 } 1393 else 1394 { 1395 var v:* = videoDisplayProperties.thumbnailSource; 1396 return (v === undefined) ? null : v; 1397 } 1398 } 1399 1400 /** 1401 * @private 1402 */ 1403 mx_internal function set thumbnailSource(value:Object):void 1404 { 1405 if (videoDisplay) 1406 { 1407 videoDisplay.thumbnailSource = value; 1408 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 1409 THUMBNAIL_SOURCE_PROPERTY_FLAG, true); 1410 } 1411 else 1412 { 1413 videoDisplayProperties.thumbnailSource = value; 1414 } 1415 } 1416 1417 //---------------------------------- 1418 // videoObject 1419 //---------------------------------- 1420 1421 [Inspectable(category="General", defaultValue="null")] 1422 1423 /** 1424 * @copy spark.components.VideoDisplay#videoObject 1425 * 1426 * @default null 1427 * 1428 * @langversion 3.0 1429 * @playerversion Flash 10 1430 * @playerversion AIR 1.5 1431 * @productversion Flex 4 1432 */ 1433 public function get videoObject():Video 1434 { 1435 if (videoDisplay) 1436 return videoDisplay.videoObject; 1437 else 1438 return null; 1439 } 1440 1441 //---------------------------------- 1442 // volume 1443 //---------------------------------- 1444 1445 [Inspectable(category="General", defaultValue="1.0", minValue="0.0", maxValue="1.0")] 1446 [Bindable("volumeChanged")] 1447 1448 /** 1449 * @copy spark.components.VideoDisplay#volume 1450 * 1451 * @default 1 1452 * 1453 * @langversion 3.0 1454 * @playerversion Flash 10 1455 * @playerversion AIR 1.5 1456 * @productversion Flex 4 1457 */ 1458 public function get volume():Number 1459 { 1460 if (videoDisplay) 1461 { 1462 return videoDisplay.volume; 1463 } 1464 else 1465 { 1466 var v:* = videoDisplayProperties.volume; 1467 return (v === undefined) ? 1 : v; 1468 } 1469 } 1470 1471 /** 1472 * @private 1473 */ 1474 public function set volume(value:Number):void 1475 { 1476 if (videoDisplay) 1477 { 1478 videoDisplay.volume = value; 1479 videoDisplayProperties = BitFlagUtil.update(videoDisplayProperties as uint, 1480 VOLUME_PROPERTY_FLAG, true); 1481 } 1482 else 1483 { 1484 videoDisplayProperties.volume = value; 1485 } 1486 1487 if (volumeBar) 1488 volumeBar.value = value; 1489 } 1490 1491 //-------------------------------------------------------------------------- 1492 // 1493 // Overridden methods 1494 // 1495 //-------------------------------------------------------------------------- 1496 1497 /** 1498 * @private 1499 */ 1500 override protected function initializeAccessibility():void 1501 { 1502 if (VideoPlayer.createAccessibilityImplementation != null) 1503 VideoPlayer.createAccessibilityImplementation(this); 1504 } 1505 1506 /** 1507 * @private 1508 */ 1509 override protected function getCurrentSkinState():String 1510 { 1511 if (!videoDisplay || !videoDisplay.videoPlayer) 1512 return null; 1513 1514 var state:String = videoDisplay.videoPlayer.state; 1515 1516 // now that we have our video player's current state (atleast the one we care about) 1517 // and that we've set the previous state to something we care about, let's figure 1518 // out our skin's state 1519 1520 if (!enabled) 1521 state="disabled" 1522 1523 if (fullScreen) 1524 return state + "AndFullScreen"; 1525 1526 return state; 1527 } 1528 1529 /** 1530 * @private 1531 */ 1532 override protected function partAdded(partName:String, instance:Object):void 1533 { 1534 super.partAdded(partName, instance); 1535 1536 if (instance == videoDisplay) 1537 { 1538 videoDisplay.addEventListener(TimeEvent.CURRENT_TIME_CHANGE, videoDisplay_currentTimeChangeHandler); 1539 videoDisplay.addEventListener(LoadEvent.BYTES_LOADED_CHANGE, videoDisplay_bytesLoadedChangeHandler); 1540 videoDisplay.addEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, videoDisplay_mediaPlayerStateChangeHandler); 1541 videoDisplay.addEventListener(TimeEvent.DURATION_CHANGE, videoDisplay_durationChangeHandler); 1542 videoDisplay.addEventListener(TimeEvent.COMPLETE, dispatchEvent); 1543 1544 // just strictly for binding purposes 1545 videoDisplay.addEventListener("sourceChanged", dispatchEvent); 1546 videoDisplay.addEventListener("volumeChanged", videoDisplay_volumeChangedHandler); 1547 1548 // copy proxied values from videoProperties (if set) to video 1549 1550 var newVideoProperties:uint = 0; 1551 1552 if (videoDisplayProperties.source !== undefined) 1553 { 1554 videoDisplay.source = videoDisplayProperties.source; 1555 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1556 SOURCE_PROPERTY_FLAG, true); 1557 } 1558 1559 if (videoDisplayProperties.autoPlay !== undefined) 1560 { 1561 videoDisplay.autoPlay = videoDisplayProperties.autoPlay; 1562 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1563 AUTO_PLAY_PROPERTY_FLAG, true); 1564 } 1565 1566 if (videoDisplayProperties.volume !== undefined) 1567 { 1568 videoDisplay.volume = videoDisplayProperties.volume; 1569 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1570 VOLUME_PROPERTY_FLAG, true); 1571 } 1572 1573 if (videoDisplayProperties.autoRewind !== undefined) 1574 { 1575 videoDisplay.autoRewind = videoDisplayProperties.autoRewind; 1576 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1577 AUTO_REWIND_PROPERTY_FLAG, true); 1578 } 1579 1580 if (videoDisplayProperties.loop !== undefined) 1581 { 1582 videoDisplay.loop = videoDisplayProperties.loop; 1583 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1584 LOOP_PROPERTY_FLAG, true); 1585 } 1586 1587 if (videoDisplayProperties.scaleMode !== undefined) 1588 { 1589 videoDisplay.scaleMode = videoDisplayProperties.scaleMode; 1590 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1591 SCALE_MODE_PROPERTY_FLAG, true); 1592 } 1593 1594 if (videoDisplayProperties.muted !== undefined) 1595 { 1596 videoDisplay.muted = videoDisplayProperties.muted; 1597 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1598 MUTED_PROPERTY_FLAG, true); 1599 } 1600 1601 if (videoDisplayProperties.pauseWhenHidden !== undefined) 1602 { 1603 videoDisplay.pauseWhenHidden = videoDisplayProperties.pauseWhenHidden; 1604 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1605 PAUSE_WHEN_HIDDEN_PROPERTY_FLAG, true); 1606 } 1607 1608 if (videoDisplayProperties.autoDisplayFirstFrame !== undefined) 1609 { 1610 videoDisplay.autoDisplayFirstFrame = videoDisplayProperties.autoDisplayFirstFrame; 1611 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1612 AUTO_DISPLAY_FIRST_FRAME_PROPERTY_FLAG, true); 1613 } 1614 1615 if (videoDisplayProperties.thumbnailSource !== undefined) 1616 { 1617 videoDisplay.thumbnailSource = videoDisplayProperties.thumbnailSource; 1618 newVideoProperties = BitFlagUtil.update(newVideoProperties as uint, 1619 THUMBNAIL_SOURCE_PROPERTY_FLAG, true); 1620 } 1621 1622 // these are state properties just carried over from an old video element 1623 if (videoDisplayProperties.currentTime !== undefined || 1624 videoDisplayProperties.playing !== undefined) 1625 { 1626 videoDisplay_updateCompleteHandlerProperties = { 1627 autoPlay: videoDisplay.autoPlay, 1628 playing: videoDisplayProperties.playing, 1629 currentTime: videoDisplayProperties.currentTime}; 1630 1631 // so the videoDisplay doesn't start playing...we'll handle it instead in 1632 // videoDisplay_updateCompleteHandler 1633 videoDisplay.autoPlay = false; 1634 1635 videoDisplay.addEventListener(FlexEvent.UPDATE_COMPLETE, videoDisplay_updateCompleteHandler); 1636 } 1637 1638 videoDisplayProperties = newVideoProperties; 1639 1640 if (volumeBar) 1641 { 1642 volumeBar.value = videoDisplay.volume; 1643 volumeBar.muted = videoDisplay.muted; 1644 } 1645 1646 if (muteButton) 1647 { 1648 muteButton.volume = videoDisplay.volume; 1649 muteButton.muted = videoDisplay.muted; 1650 } 1651 1652 if (scrubBar) 1653 updateScrubBar(); 1654 1655 if (currentTimeDisplay) 1656 updateCurrentTime(); 1657 1658 if (durationDisplay) 1659 updateDuration(); 1660 } 1661 else if (instance == playButton) 1662 { 1663 playButton.addEventListener(MouseEvent.CLICK, playButton_clickHandler); 1664 } 1665 else if (instance == pauseButton) 1666 { 1667 pauseButton.addEventListener(MouseEvent.CLICK, pauseButton_clickHandler); 1668 } 1669 else if (instance == playPauseButton) 1670 { 1671 playPauseButton.addEventListener(MouseEvent.CLICK, playPauseButton_clickHandler); 1672 } 1673 else if (instance == stopButton) 1674 { 1675 stopButton.addEventListener(MouseEvent.CLICK, stopButton_clickHandler); 1676 } 1677 else if (instance == muteButton) 1678 { 1679 if (videoDisplay) 1680 { 1681 muteButton.muted = muted; 1682 muteButton.volume = volume; 1683 } 1684 1685 muteButton.addEventListener(FlexEvent.MUTED_CHANGE, muteButton_mutedChangeHandler); 1686 } 1687 else if (instance == volumeBar) 1688 { 1689 volumeBar.minimum = 0; 1690 volumeBar.maximum = 1; 1691 if (videoDisplay) 1692 { 1693 volumeBar.value = volume; 1694 volumeBar.muted = muted; 1695 } 1696 1697 volumeBar.addEventListener(Event.CHANGE, volumeBar_changeHandler); 1698 volumeBar.addEventListener(FlexEvent.MUTED_CHANGE, volumeBar_mutedChangeHandler); 1699 } 1700 else if (instance == scrubBar) 1701 { 1702 if (videoDisplay) 1703 updateScrubBar(); 1704 1705 // add thumbPress and thumbRelease so we pause the video while dragging 1706 scrubBar.addEventListener(TrackBaseEvent.THUMB_PRESS, scrubBar_thumbPressHandler); 1707 scrubBar.addEventListener(TrackBaseEvent.THUMB_RELEASE, scrubBar_thumbReleaseHandler); 1708 1709 // add change to actually seek() when the change is complete 1710 scrubBar.addEventListener(Event.CHANGE, scrubBar_changeHandler); 1711 1712 // add changeEnd and changeStart so we don't update the scrubbar's value 1713 // while the scrubbar is moving around due to an animation 1714 scrubBar.addEventListener(FlexEvent.CHANGE_END, scrubBar_changeEndHandler); 1715 scrubBar.addEventListener(FlexEvent.CHANGE_START, scrubBar_changeStartHandler); 1716 } 1717 else if (instance == fullScreenButton) 1718 { 1719 fullScreenButton.addEventListener(MouseEvent.CLICK, fullScreenButton_clickHandler); 1720 } 1721 else if (instance == currentTimeDisplay) 1722 { 1723 if (videoDisplay) 1724 updateCurrentTime(); 1725 } 1726 else if (instance == durationDisplay) 1727 { 1728 if (videoDisplay) 1729 updateDuration(); 1730 } 1731 } 1732 1733 /** 1734 * @private 1735 * Holds the state of the video element when the skin is being swapped out. 1736 * This is so the new videoDisplay can load up and start playing 1737 * where it left off. 1738 */ 1739 private var videoDisplay_updateCompleteHandlerProperties:Object; 1740 1741 /** 1742 * @private 1743 * We only listen for the updateComplete event on the videoDisplay when 1744 * a skin has been swapped. This is so we can push the old videoDisplay's 1745 * state in to the new object, and we can start playing the video 1746 * where it left off. 1747 */ 1748 private function videoDisplay_updateCompleteHandler(event:FlexEvent):void 1749 { 1750 if (videoDisplay_updateCompleteHandlerProperties.autoPlay) 1751 videoDisplay.autoPlay = true; 1752 1753 if (videoDisplay_updateCompleteHandlerProperties.currentTime !== undefined) 1754 videoDisplay.seek(videoDisplay_updateCompleteHandlerProperties.currentTime); 1755 1756 if (videoDisplay_updateCompleteHandlerProperties.playing) 1757 videoDisplay.play(); 1758 1759 videoDisplay_updateCompleteHandlerProperties = null; 1760 videoDisplay.removeEventListener(FlexEvent.UPDATE_COMPLETE, videoDisplay_updateCompleteHandler); 1761 } 1762 1763 /** 1764 * @private 1765 */ 1766 override protected function partRemoved(partName:String, instance:Object):void 1767 { 1768 super.partRemoved(partName, instance); 1769 1770 if (instance == videoDisplay) 1771 { 1772 // validate before doing anything with the videoDisplay. 1773 // This is so if the video element hasn't been validated, it won't start playing. 1774 // plus this way we'll get a valid currentTime and all those other properties 1775 // we are interested in. 1776 videoDisplay.validateNow(); 1777 1778 // copy proxied values from video (if explicitely set) to videoProperties 1779 1780 var newVideoProperties:Object = {}; 1781 1782 if (BitFlagUtil.isSet(videoDisplayProperties as uint, SOURCE_PROPERTY_FLAG)) 1783 newVideoProperties.source = videoDisplay.source; 1784 1785 if (BitFlagUtil.isSet(videoDisplayProperties as uint, AUTO_PLAY_PROPERTY_FLAG)) 1786 newVideoProperties.autoPlay = videoDisplay.autoPlay; 1787 1788 if (BitFlagUtil.isSet(videoDisplayProperties as uint, VOLUME_PROPERTY_FLAG)) 1789 newVideoProperties.volume = videoDisplay.volume; 1790 1791 if (BitFlagUtil.isSet(videoDisplayProperties as uint, AUTO_REWIND_PROPERTY_FLAG)) 1792 newVideoProperties.autoRewind = videoDisplay.autoRewind; 1793 1794 if (BitFlagUtil.isSet(videoDisplayProperties as uint, LOOP_PROPERTY_FLAG)) 1795 newVideoProperties.loop = videoDisplay.loop; 1796 1797 if (BitFlagUtil.isSet(videoDisplayProperties as uint, SCALE_MODE_PROPERTY_FLAG)) 1798 newVideoProperties.scaleMode = videoDisplay.scaleMode; 1799 1800 if (BitFlagUtil.isSet(videoDisplayProperties as uint, MUTED_PROPERTY_FLAG)) 1801 newVideoProperties.muted = videoDisplay.muted; 1802 1803 if (BitFlagUtil.isSet(videoDisplayProperties as uint, PAUSE_WHEN_HIDDEN_PROPERTY_FLAG)) 1804 newVideoProperties.pauseWhenHidden = videoDisplay.pauseWhenHidden; 1805 1806 if (BitFlagUtil.isSet(videoDisplayProperties as uint, AUTO_DISPLAY_FIRST_FRAME_PROPERTY_FLAG)) 1807 newVideoProperties.autoDisplayFirstFrame = videoDisplay.autoDisplayFirstFrame; 1808 1809 if (BitFlagUtil.isSet(videoDisplayProperties as uint, THUMBNAIL_SOURCE_PROPERTY_FLAG)) 1810 newVideoProperties.thumbnailSource = videoDisplay.thumbnailSource; 1811 1812 // push our current state (where we were in the video and whether we were playing) 1813 // so that the new skin gets these as well 1814 newVideoProperties.currentTime = videoDisplay.currentTime; 1815 newVideoProperties.playing = videoDisplay.playing; 1816 1817 videoDisplay.stop(); 1818 1819 videoDisplayProperties = newVideoProperties; 1820 1821 videoDisplay.removeEventListener(TimeEvent.CURRENT_TIME_CHANGE, videoDisplay_currentTimeChangeHandler); 1822 videoDisplay.removeEventListener(LoadEvent.BYTES_LOADED_CHANGE, videoDisplay_bytesLoadedChangeHandler); 1823 videoDisplay.removeEventListener(MediaPlayerStateChangeEvent.MEDIA_PLAYER_STATE_CHANGE, videoDisplay_mediaPlayerStateChangeHandler); 1824 videoDisplay.removeEventListener(TimeEvent.DURATION_CHANGE, videoDisplay_durationChangeHandler); 1825 videoDisplay.removeEventListener(TimeEvent.COMPLETE, dispatchEvent); 1826 1827 // just strictly for binding purposes 1828 videoDisplay.removeEventListener("sourceChanged", dispatchEvent); 1829 videoDisplay.removeEventListener("volumeChanged", videoDisplay_volumeChangedHandler); 1830 } 1831 else if (instance == playButton) 1832 { 1833 playButton.removeEventListener(MouseEvent.CLICK, playButton_clickHandler); 1834 } 1835 else if (instance == pauseButton) 1836 { 1837 pauseButton.removeEventListener(MouseEvent.CLICK, pauseButton_clickHandler); 1838 } 1839 else if (instance == playPauseButton) 1840 { 1841 playPauseButton.removeEventListener(MouseEvent.CLICK, playPauseButton_clickHandler); 1842 } 1843 else if (instance == stopButton) 1844 { 1845 stopButton.removeEventListener(MouseEvent.CLICK, stopButton_clickHandler); 1846 } 1847 else if (instance == muteButton) 1848 { 1849 playButton.removeEventListener(FlexEvent.MUTED_CHANGE, muteButton_mutedChangeHandler); 1850 } 1851 else if (instance == volumeBar) 1852 { 1853 volumeBar.removeEventListener(Event.CHANGE, volumeBar_changeHandler); 1854 volumeBar.removeEventListener(FlexEvent.MUTED_CHANGE, volumeBar_mutedChangeHandler); 1855 } 1856 else if (instance == scrubBar) 1857 { 1858 scrubBar.removeEventListener(TrackBaseEvent.THUMB_PRESS, scrubBar_thumbPressHandler); 1859 scrubBar.removeEventListener(TrackBaseEvent.THUMB_RELEASE, scrubBar_thumbReleaseHandler); 1860 scrubBar.removeEventListener(Event.CHANGE, scrubBar_changeHandler); 1861 scrubBar.removeEventListener(FlexEvent.CHANGE_END, scrubBar_changeEndHandler); 1862 scrubBar.removeEventListener(FlexEvent.CHANGE_START, scrubBar_changeStartHandler); 1863 } 1864 else if (instance == fullScreenButton) 1865 { 1866 fullScreenButton.removeEventListener(MouseEvent.CLICK, fullScreenButton_clickHandler); 1867 } 1868 } 1869 1870 /** 1871 * @private 1872 */ 1873 override protected function commitProperties():void 1874 { 1875 super.commitProperties(); 1876 1877 // if coming from full screen mode, we reset the 1878 // pauseWhenHidden property here because of an AIR bug 1879 // that requires us to defer it. 1880 if (needsToUpdatePauseWhenHidden) 1881 { 1882 needsToUpdatePauseWhenHidden = false; 1883 pauseWhenHidden = exitingFullScreenPauseWhenHidden; 1884 } 1885 } 1886 1887 //-------------------------------------------------------------------------- 1888 // 1889 // Methods 1890 // 1891 //-------------------------------------------------------------------------- 1892 1893 /** 1894 * @throws TypeError If the skin hasn't been loaded and there is no videoDisplay. 1895 * 1896 * @copy spark.components.VideoDisplay#pause() 1897 * 1898 * 1899 * @langversion 3.0 1900 * @playerversion Flash 10 1901 * @playerversion AIR 1.5 1902 * @productversion Flex 4 1903 */ 1904 public function pause():void 1905 { 1906 videoDisplay.pause(); 1907 } 1908 1909 /** 1910 * @copy spark.components.VideoDisplay#play() 1911 * 1912 * @throws TypeError if the skin hasn't been loaded up yet 1913 * and there's no videoDisplay. 1914 * 1915 * @langversion 3.0 1916 * @playerversion Flash 10 1917 * @playerversion AIR 1.5 1918 * @productversion Flex 4 1919 */ 1920 public function play():void 1921 { 1922 //trace("play"); 1923 videoDisplay.play(); 1924 } 1925 1926 /** 1927 * @copy spark.components.VideoDisplay#seek() 1928 * 1929 * @throws TypeError if the skin hasn't been loaded up yet 1930 * and there's no videoDisplay. 1931 * 1932 * @langversion 3.0 1933 * @playerversion Flash 10 1934 * @playerversion AIR 1.5 1935 * @productversion Flex 4 1936 */ 1937 public function seek(time:Number):void 1938 { 1939 videoDisplay.seek(time); 1940 } 1941 1942 /** 1943 * @copy spark.components.VideoDisplay#stop() 1944 * 1945 * @throws TypeError if the skin hasn't been loaded up yet 1946 * and there's no videoDisplay. 1947 * 1948 * @langversion 3.0 1949 * @playerversion Flash 10 1950 * @playerversion AIR 1.5 1951 * @productversion Flex 4 1952 */ 1953 public function stop():void 1954 { 1955 videoDisplay.stop(); 1956 } 1957 1958 /** 1959 * @private 1960 */ 1961 private function updateScrubBar():void 1962 { 1963 if (!videoDisplay) 1964 return; 1965 1966 if (!scrubBarMouseCaptured && !scrubBarChanging) 1967 { 1968 scrubBar.minimum = 0; 1969 scrubBar.maximum = videoDisplay.duration; 1970 scrubBar.value = videoDisplay.currentTime; 1971 } 1972 1973 // if streaming, then we pretend to have everything in view 1974 // if progressive, then look at the bytesLoaded and bytesTotal 1975 if (!videoDisplay.videoPlayer.canLoad) 1976 scrubBar.loadedRangeEnd = videoDisplay.duration; 1977 else if (videoDisplay.bytesTotal == 0) 1978 scrubBar.loadedRangeEnd = 0; 1979 else 1980 scrubBar.loadedRangeEnd = (videoDisplay.bytesLoaded/videoDisplay.bytesTotal)*videoDisplay.duration; 1981 } 1982 1983 /** 1984 * @private 1985 */ 1986 private function updateDuration():void 1987 { 1988 durationDisplay.text = formatTimeValue(duration); 1989 } 1990 1991 /** 1992 * Formats a time value, specified in seconds, into a String that 1993 * gets used for <code>currentTime</code> and the <code>duration</code>. 1994 * 1995 * @param value Value in seconds of the time to format. 1996 * 1997 * @return Formatted time value. 1998 * 1999 * @langversion 3.0 2000 * @playerversion Flash 10 2001 * @playerversion AIR 2.5 2002 * @productversion Flex 4.5 2003 */ 2004 protected function formatTimeValue(value:Number):String 2005 { 2006 // default format: hours:minutes:seconds 2007 value = Math.round(value); 2008 2009 var hours:uint = Math.floor(value/3600) % 24; 2010 var minutes:uint = Math.floor(value/60) % 60; 2011 var seconds:uint = value % 60; 2012 2013 var result:String = ""; 2014 if (hours != 0) 2015 result = hours + ":"; 2016 2017 if (result && minutes < 10) 2018 result += "0" + minutes + ":"; 2019 else 2020 result += minutes + ":"; 2021 2022 if (seconds < 10) 2023 result += "0" + seconds; 2024 else 2025 result += seconds; 2026 2027 return result; 2028 } 2029 2030 /** 2031 * @private 2032 */ 2033 private function updateCurrentTime():void 2034 { 2035 currentTimeDisplay.text = formatTimeValue(currentTime); 2036 } 2037 2038 /** 2039 * @private 2040 * Returns the screen bounds. 2041 * If we are on the AIR Player, we need to work around AIR Player bug #2503351 2042 * We check if the flash.display.Screen class is defined. If so, then 2043 * we are running on the AIR Player and can access this API. 2044 */ 2045 mx_internal function getScreenBounds():Rectangle 2046 { 2047 var resultRect:Rectangle = new Rectangle(0, 0, stage.fullScreenWidth, stage.fullScreenHeight); 2048 2049 if (screenClass) 2050 { 2051 // Get the screen where the application resides 2052 try 2053 { 2054 var nativeWindowBounds:Rectangle = stage["nativeWindow"]["bounds"]; 2055 var currentScreen:Object = screenClass["getScreensForRectangle"](nativeWindowBounds)[0]; 2056 2057 // Return the bounds of that screen 2058 resultRect = currentScreen["bounds"]; 2059 } 2060 catch (e:Error) 2061 { 2062 } 2063 } 2064 2065 return resultRect; 2066 } 2067 2068 //-------------------------------------------------------------------------- 2069 // 2070 // Event handlers 2071 // 2072 //-------------------------------------------------------------------------- 2073 2074 /** 2075 * @private 2076 */ 2077 private function videoDisplay_currentTimeChangeHandler(event:TimeEvent):void 2078 { 2079 if (scrubBar) 2080 updateScrubBar(); 2081 2082 if (currentTimeDisplay) 2083 updateCurrentTime(); 2084 2085 dispatchEvent(event); 2086 } 2087 2088 /** 2089 * @private 2090 */ 2091 private function videoDisplay_bytesLoadedChangeHandler(event:LoadEvent):void 2092 { 2093 if (scrubBar) 2094 updateScrubBar(); 2095 2096 dispatchEvent(event); 2097 } 2098 2099 /** 2100 * @private 2101 */ 2102 private function videoDisplay_mediaPlayerStateChangeHandler(event:MediaPlayerStateChangeEvent):void 2103 { 2104 invalidateSkinState(); 2105 2106 if (scrubBar) 2107 updateScrubBar(); 2108 2109 if (durationDisplay) 2110 updateDuration(); 2111 2112 if (currentTimeDisplay) 2113 updateCurrentTime(); 2114 2115 if (playPauseButton) 2116 playPauseButton.selected = playing; 2117 2118 //trace("mediaPlayerStateChangeHandler " + event + " state = " + event.state + " playing = " + playing); 2119 2120 dispatchEvent(event); 2121 } 2122 2123 /** 2124 * @private 2125 */ 2126 private function videoDisplay_durationChangeHandler(event:TimeEvent):void 2127 { 2128 if (scrubBar) 2129 updateScrubBar(); 2130 2131 if (durationDisplay) 2132 updateDuration(); 2133 2134 dispatchEvent(event); 2135 } 2136 2137 /** 2138 * @private 2139 */ 2140 private function videoDisplay_volumeChangedHandler(event:Event):void 2141 { 2142 if (volumeBar) 2143 { 2144 volumeBar.value = volume; 2145 volumeBar.muted = muted; 2146 } 2147 2148 if (muteButton) 2149 { 2150 muteButton.muted = muted; 2151 muteButton.volume = volume; 2152 } 2153 2154 dispatchEvent(event); 2155 } 2156 2157 /** 2158 * @private 2159 * Indicates whether we are in the full screen state or not. 2160 * We use this when determining our current skin state. 2161 */ 2162 private var fullScreen:Boolean = false; 2163 2164 /** 2165 * @private 2166 * Holds a list of properties for the "video player state" that will 2167 * be restored when going out of fullScreen mode. 2168 */ 2169 private var beforeFullScreenInfo:Object; 2170 2171 /** 2172 * @private 2173 * Timer, which waits for 3 seconds by default to hide the 2174 * playback controls. If there's interaction by the user, then 2175 * these playback controls are show again, and the timer will reset 2176 * and start the countdown. 2177 */ 2178 private var fullScreenHideControlTimer:Timer; 2179 2180 /** 2181 * @private 2182 */ 2183 private function fullScreenButton_clickHandler(event:MouseEvent):void 2184 { 2185 if (!fullScreen) 2186 { 2187 // check to make sure we can go into fullscreen mode 2188 if (!systemManager.getTopLevelRoot()) 2189 return; 2190 2191 var screenBounds:Rectangle = getScreenBounds(); 2192 2193 fullScreen = true; 2194 2195 // need it to go into full screen state for the skin 2196 invalidateSkinState(); 2197 2198 // keep track of pauseWhenHidden b/c we will set it to false temporarily 2199 // so that the video does not pause when we reparent it to the top 2200 // level application 2201 var oldPauseWhenHidden:Boolean = pauseWhenHidden; 2202 2203 // let's get it off of our layout system so it doesn't interfere with 2204 // the sizing and positioning. Then let's resize it to be 2205 // the full size of our screen. Then let's position it off-screen so 2206 // there are no other elements in the way. 2207 beforeFullScreenInfo = {parent: this.parent, 2208 x: this.x, 2209 y: this.y, 2210 explicitWidth: this.explicitWidth, 2211 explicitHeight: this.explicitHeight, 2212 percentWidth: this.percentWidth, 2213 percentHeight: this.percentHeight, 2214 isPopUp: this.isPopUp}; 2215 2216 pauseWhenHidden = false; 2217 2218 if (!isPopUp) 2219 { 2220 // remove from old parent 2221 if (parent is IVisualElementContainer) 2222 { 2223 var ivec:IVisualElementContainer = IVisualElementContainer(parent); 2224 beforeFullScreenInfo.childIndex = ivec.getElementIndex(this); 2225 ivec.removeElement(this); 2226 } 2227 else 2228 { 2229 beforeFullScreenInfo.childIndex = parent.getChildIndex(this); 2230 parent.removeChild(this); 2231 } 2232 2233 // add as a popup 2234 PopUpManager.addPopUp(this, FlexGlobals.topLevelApplication as DisplayObject, false, null, moduleFactory); 2235 } 2236 2237 // Resize the component to be the full screen of the stage. 2238 // Push the component at (0,0). It should be on top of everything 2239 // at this point because it was added as a popup 2240 setLayoutBoundsSize(screenBounds.width, screenBounds.height, true); 2241 // set the explicit width/height to make sure this value sticks regardless 2242 // of any other code or layout passes. Calling setLayoutBoundsSize() before hand 2243 // allows us to use postLayout width/height. 2244 // Setting explictWidth/Height sets percentWidth/Height to NaN. 2245 this.explicitWidth = width; 2246 this.explicitHeight = height; 2247 setLayoutBoundsPosition(0, 0, true); 2248 2249 // this is for video performance reasons, but sometimes the videoObject isn't there 2250 // if the source is null 2251 if (videoDisplay.videoObject) 2252 { 2253 beforeFullScreenInfo.smoothing = videoDisplay.videoObject.smoothing; 2254 beforeFullScreenInfo.deblocking = videoDisplay.videoObject.deblocking; 2255 videoDisplay.videoObject.smoothing = false; 2256 videoDisplay.videoObject.deblocking = 0; 2257 } 2258 2259 this.validateNow(); 2260 2261 systemManager.stage.addEventListener(FullScreenEvent.FULL_SCREEN, fullScreenEventHandler); 2262 2263 // TODO (rfrishbe): Should we make this FULL_SCREEN_INTERACTIVE if in AIR? 2264 systemManager.stage.displayState = StageDisplayState.FULL_SCREEN; 2265 2266 pauseWhenHidden = oldPauseWhenHidden; 2267 2268 var fullScreenHideControlsDelay:Number = getStyle("fullScreenHideControlsDelay"); 2269 2270 if (fullScreenHideControlsDelay == 0) 2271 { 2272 playerControls.visible = false; 2273 2274 if (volumeBar) 2275 volumeBar.closeDropDown(true); 2276 } 2277 else if (fullScreenHideControlsDelay < Infinity) 2278 { 2279 // start timer for detecting for mouse movements/clicks to hide the controls 2280 fullScreenHideControlTimer = new Timer(fullScreenHideControlsDelay, 1); 2281 fullScreenHideControlTimer.addEventListener(TimerEvent.TIMER_COMPLETE, 2282 fullScreenHideControlTimer_timerCompleteHandler, false, 0, true); 2283 2284 // use stage or systemManager? 2285 systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_DOWN, resetFullScreenHideControlTimer); 2286 systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_MOVE, resetFullScreenHideControlTimer); 2287 systemManager.getSandboxRoot().addEventListener(MouseEvent.MOUSE_WHEEL, resetFullScreenHideControlTimer); 2288 2289 // keyboard events don't happen when in fullScreen mode, but could be in fullScreen and interactive mode 2290 systemManager.getSandboxRoot().addEventListener(KeyboardEvent.KEY_DOWN, resetFullScreenHideControlTimer); 2291 2292 fullScreenHideControlTimer.start(); 2293 } 2294 } 2295 else 2296 { 2297 systemManager.stage.displayState = StageDisplayState.NORMAL; 2298 } 2299 } 2300 2301 /** 2302 * @private 2303 * After waiting a certain time perdiod, we hide the controls if no 2304 * user-interaction has occurred on-screen. 2305 */ 2306 private function fullScreenHideControlTimer_timerCompleteHandler(event:TimerEvent):void 2307 { 2308 playerControls.visible = false; 2309 2310 if (volumeBar) 2311 volumeBar.closeDropDown(true); 2312 } 2313 2314 /** 2315 * @private 2316 * Handles when mouse interaction happens, and we are in the fullscreen mode. This 2317 * resets the fullScreenHideControlTimer. 2318 */ 2319 private function resetFullScreenHideControlTimer(event:Event):void 2320 { 2321 playerControls.visible = true; 2322 2323 if (fullScreenHideControlTimer) 2324 { 2325 fullScreenHideControlTimer.reset(); 2326 fullScreenHideControlTimer.start(); 2327 } 2328 else 2329 { 2330 fullScreenHideControlTimer = new Timer(getStyle("fullScreenHideControlsDelay"), 1); 2331 fullScreenHideControlTimer.addEventListener(TimerEvent.TIMER_COMPLETE, 2332 fullScreenHideControlTimer_timerCompleteHandler, false, 0, true); 2333 } 2334 } 2335 2336 /** 2337 * @private 2338 * Handles when coming out the full screen mode 2339 */ 2340 private function fullScreenEventHandler(event:FullScreenEvent):void 2341 { 2342 // going in to full screen is handled by the 2343 // fullScreenButton_clickHandler 2344 if (event.fullScreen) 2345 return; 2346 2347 // keep track of pauseWhenHidden b/c we will set it to false temporarily 2348 // so that the video does not pause when we reparent it to the top 2349 // level application 2350 exitingFullScreenPauseWhenHidden = pauseWhenHidden; 2351 pauseWhenHidden = false; 2352 2353 // set the fullScreen variable back to false and remove this event listener 2354 fullScreen = false; 2355 systemManager.stage.removeEventListener(FullScreenEvent.FULL_SCREEN, fullScreenEventHandler); 2356 2357 // remove the event listeners to hide the controls 2358 systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_DOWN, resetFullScreenHideControlTimer); 2359 systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_MOVE, resetFullScreenHideControlTimer); 2360 systemManager.getSandboxRoot().removeEventListener(MouseEvent.MOUSE_WHEEL, resetFullScreenHideControlTimer); 2361 systemManager.getSandboxRoot().removeEventListener(KeyboardEvent.KEY_DOWN, resetFullScreenHideControlTimer); 2362 2363 if (fullScreenHideControlTimer) 2364 { 2365 fullScreenHideControlTimer.stop(); 2366 fullScreenHideControlTimer = null; 2367 } 2368 2369 // make the controls visible no matter what 2370 playerControls.visible = true; 2371 2372 // reset it so we're re-included in the layout 2373 this.x = beforeFullScreenInfo.x; 2374 this.y = beforeFullScreenInfo.y; 2375 this.explicitWidth = beforeFullScreenInfo.explicitWidth; 2376 this.explicitHeight = beforeFullScreenInfo.explicitHeight; 2377 this.percentWidth = beforeFullScreenInfo.percentWidth; 2378 this.percentHeight = beforeFullScreenInfo.percentHeight; 2379 2380 // sometimes there's no video object currently or there might not've been a 2381 // video object when we went in to fullScreen mode. There may be no videoObject 2382 // if the source hasn't been set. 2383 if (videoDisplay.videoObject && beforeFullScreenInfo.smoothing !== undefined) 2384 { 2385 videoDisplay.videoObject.smoothing = beforeFullScreenInfo.smoothing; 2386 videoDisplay.videoObject.deblocking = beforeFullScreenInfo.deblocking; 2387 } 2388 2389 if (!beforeFullScreenInfo.isPopUp) 2390 { 2391 // remove from top level application: 2392 PopUpManager.removePopUp(this); 2393 2394 // add back to original parent 2395 if (beforeFullScreenInfo.parent is IVisualElementContainer) 2396 beforeFullScreenInfo.parent.addElementAt(this, beforeFullScreenInfo.childIndex); 2397 else 2398 beforeFullScreenInfo.parent.addChildAt(this, beforeFullScreenInfo.childIndex); 2399 } 2400 2401 // want to update pauseWhenHidden, but can't do it here 2402 // b/c the AIR window thinks it's invisible at this point 2403 // if we're on a Mac (a bug), so let's just defer this check 2404 // to commitProperties(). 2405 if (exitingFullScreenPauseWhenHidden) 2406 { 2407 // if we need to set it back to true 2408 needsToUpdatePauseWhenHidden = true; 2409 invalidateProperties(); 2410 } 2411 2412 beforeFullScreenInfo = null; 2413 2414 invalidateSkinState(); 2415 invalidateSize(); 2416 invalidateDisplayList(); 2417 } 2418 2419 /** 2420 * @private 2421 */ 2422 private function playButton_clickHandler(event:MouseEvent):void 2423 { 2424 if (!playing) 2425 play(); 2426 } 2427 2428 /** 2429 * @private 2430 */ 2431 private function pauseButton_clickHandler(event:MouseEvent):void 2432 { 2433 pause(); 2434 } 2435 2436 /** 2437 * @private 2438 */ 2439 private function stopButton_clickHandler(event:MouseEvent):void 2440 { 2441 stop(); 2442 } 2443 2444 /** 2445 * @private 2446 */ 2447 private function playPauseButton_clickHandler(event:MouseEvent):void 2448 { 2449 if (playing) 2450 pause(); 2451 else 2452 play(); 2453 2454 // need to synch up to what we've actually got because sometimes 2455 // the play() didn't actually play() because there's no source 2456 // or we're in an error state 2457 playPauseButton.selected = playing; 2458 } 2459 2460 /** 2461 * @private 2462 */ 2463 private function muteButton_mutedChangeHandler(event:FlexEvent):void 2464 { 2465 muted = muteButton.muted; 2466 } 2467 2468 /** 2469 * @private 2470 */ 2471 private function volumeBar_changeHandler(event:Event):void 2472 { 2473 if (volume != volumeBar.value) 2474 volume = volumeBar.value; 2475 } 2476 2477 /** 2478 * @private 2479 */ 2480 private function volumeBar_mutedChangeHandler(event:FlexEvent):void 2481 { 2482 if (muted != volumeBar.muted) 2483 muted = volumeBar.muted; 2484 } 2485 2486 /** 2487 * @private 2488 * When someone is holding the scrubBar, we don't want to update the 2489 * range's value--for this time period, we'll let the user completely 2490 * control the range. 2491 */ 2492 private var scrubBarMouseCaptured:Boolean; 2493 2494 /** 2495 * @private 2496 * We pause the video when dragging the thumb for the scrub bar. This 2497 * stores whether we were paused or not. 2498 */ 2499 private var wasPlayingBeforeSeeking:Boolean; 2500 2501 /** 2502 * @private 2503 * We are in the process of changing the timestamp 2504 */ 2505 private var scrubBarChanging:Boolean; 2506 2507 /** 2508 * @private 2509 */ 2510 private function scrubBar_changeStartHandler(event:Event):void 2511 { 2512 scrubBarChanging = true; 2513 } 2514 2515 /** 2516 * @private 2517 */ 2518 private function scrubBar_thumbPressHandler(event:TrackBaseEvent):void 2519 { 2520 scrubBarMouseCaptured = true; 2521 if (playing) 2522 { 2523 pause(); 2524 wasPlayingBeforeSeeking = true; 2525 } 2526 } 2527 2528 /** 2529 * @private 2530 */ 2531 private function scrubBar_thumbReleaseHandler(event:TrackBaseEvent):void 2532 { 2533 scrubBarMouseCaptured = false; 2534 if (wasPlayingBeforeSeeking) 2535 { 2536 play(); 2537 wasPlayingBeforeSeeking = false; 2538 } 2539 } 2540 2541 /** 2542 * @private 2543 */ 2544 private function scrubBar_changeHandler(event:Event):void 2545 { 2546 seek(scrubBar.value); 2547 } 2548 2549 /** 2550 * @private 2551 */ 2552 private function scrubBar_changeEndHandler(event:Event):void 2553 { 2554 scrubBarChanging = false; 2555 } 2556} 2557} 2558