<?xml version="1.0"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:accessibility="flash.accessibility.*"
xmlns:controls="com.modernista.mx.controls.*"
xmlns:videoClasses="com.modernista.mx.controls.videoClasses.*"
viewSourceURL="srcview/index.html"
applicationComplete="init()"
width="100%"
height="100%"
layout="absolute"
autoLayout="true"
backgroundGradientColors="[0,0]"
focusIn="handleFocusIn(FocusEvent(event))"
focusOut="handleFocusOut(FocusEvent(event))">
<mx:Script>
<![CDATA[
import com.modernista.mx.controls.videoClasses.CaptionChangeEvent;
import com.modernista.mx.controls.videoClasses.CaptionTargetEvent;
import com.modernista.mx.controls.videoClasses.VideoDisplayCaptioning;
import com.modernista.swffocus.SWFFocus;
import flash.display.StageDisplayState;
import flash.events.TimerEvent;
import flash.utils.Timer;
import mx.core.mx_internal;
import mx.events.VideoEvent;
use namespace mx_internal;
private var _seekBarScrubTolerance:Number;
private var _seekBarTimer:Timer;
private var _lastScrubPos:Number;
private var _playAfterScrub:Boolean;
public static const SEEK_BAR_INTERVAL_DEFAULT:Number = 250;
public static const SEEK_BAR_SCRUB_TOLERANCE_DEFAULT:Number = 5;
public var textStrokeFilter:GlowFilter = new GlowFilter(0,0.5,2,2,10,2);
public var dispState:String;
private var _videoSource:String = "assets/flv/This-Is-Not-a-Photograph.flv"
public function get videoSource():String {
return _videoSource;
}
public function set videoSource(p_videoSource:String):void {
if(p_videoSource == _videoSource){
return;
}
_videoSource = p_videoSource;
if(videoDisplay){
videoDisplay.source = _videoSource;
}
}
private var _captionsSource:String = "assets/flv/This-Is-Not-a-Photograph.xml"
public function get captionsSource():String {
return _captionsSource;
}
public function set captionsSource(p_captionsSource:String):void {
if(p_captionsSource == _captionsSource){
return;
}
_captionsSource = p_captionsSource;
videoDisplayCaptioning.source = _captionsSource;
}
private function init():void {
SWFFocus.init(Application.application.stage as Stage);
Application.application.stage.addEventListener(Event.RESIZE, resizeHandler, false, 0, true);
videoDisplayCaptioning.addEventListener(CaptionTargetEvent.CAPTION_TARGET_CREATED, captionTargetCreatedHandler, false, 0, true);
Application.application.stage.addEventListener(FullScreenEvent.FULL_SCREEN, fullScreenHandler);
dispState = Application.application.stage.displayState;
_seekBarScrubTolerance = SEEK_BAR_SCRUB_TOLERANCE_DEFAULT;
_seekBarTimer = new Timer(SEEK_BAR_INTERVAL_DEFAULT);
_seekBarTimer.addEventListener(flash.events.TimerEvent.TIMER, seekBarListener);
var flashvars:Object = Application.application.loaderInfo.parameters;
for(var i:String in flashvars){
var key:String = i;
var value:* = flashvars[key];
switch(key.toLowerCase()){
case "source" :
case "videosource" :
case "s1" :
videoSource = value;
continue;
break;
case "captionssource" :
case "timedtext" :
case "s7" :
captionsSource = value;
continue;
break;
case "s2" :
videoDisplay.autoPlay = Boolean(value == "playing");
if(videoDisplay.source != ""
&& !Accessibility.active){
videoDisplay.play();
}
continue;
break;
}
if(videoDisplay.hasOwnProperty(key)){
if(value == "true" || value == "false"){
value = Boolean(value);
}
if(!isNaN(parseFloat(value))){
value = parseFloat(value);
}
videoDisplay[key] = value;
if(key == "autoPlay" && value==true){
if(videoDisplay.source != ""
&& !Accessibility.active){
videoDisplay.play();
}
}
}
}
if(videoDisplay.source != _videoSource){
videoDisplay.close();
videoDisplay.source = _videoSource;
videoDisplay.load();
}
if(videoDisplayCaptioning.source != _captionsSource){
videoDisplayCaptioning.source = _captionsSource;
}
showControls();
}
private function captionTargetCreatedHandler(event:CaptionTargetEvent):void {
var captionTarget:DisplayObject = VideoDisplayCaptioning(event.target).captionTarget;
if(captionTarget is TextField){
videoDisplayCaptioning.autoLayout = false;
var captionTargetWrapper:Sprite = new Sprite();
captionTarget.parent.addChild(captionTargetWrapper);
captionTargetWrapper.addChild(captionTarget);
captionTarget.visible = videoDisplayCaptioning.showCaptions;
captionTarget.x = 5;
captionTarget.y = videoDisplay.videoHeight-5-captionTarget.height;
captionTarget.width = videoDisplay.videoWidth - 10;
TextField(captionTarget).background = false;
TextField(captionTarget).selectable = false;
TextField(captionTarget).gridFitType = GridFitType.PIXEL;
TextField(captionTarget).antiAliasType = AntiAliasType.ADVANCED;
TextField(captionTarget).embedFonts = true;
var gf:GlowFilter = new GlowFilter(0,1,2,2,10,3);
var dsf:DropShadowFilter = new DropShadowFilter(1,90,0,0.5,4,4,1);
captionTarget.filters = [textStrokeFilter, dsf];
}
}
private function playPauseClickHandler(event:MouseEvent = null):void{
if(videoDisplay.playing){
videoDisplay.pause();
playPauseButton.selected = false;
} else if(!videoDisplay.playing){
videoDisplay.play();
playPauseButton.selected = true;
}
}
private function stopClickHandler(event:MouseEvent = null):void{
videoDisplay.stop();
playheadUpdateHandler();
playPauseButton.selected = false;
showControls();
}
private function videoTimeConvert(myTime:Number):String{
var date:Date = new Date(myTime*1000);
return (myTime>3600) ? this.dateFormatterHours.format(date) : this.dateFormatter.format(date);
}
private var _isPlaying:Boolean = false;
private function seekBar_thumbPress():void {
videoDisplay.removeEventListener(VideoEvent.PLAYHEAD_UPDATE, playheadUpdateHandler);
if (videoDisplay.playing) {
_playAfterScrub = true;
}
_seekBarTimer.start();
videoDisplay.pause();
this.videoDisplayCaptioning.removeOldCaptions(NaN);
if(this.videoDisplayCaptioning.showCaptions){
this.videoDisplayCaptioning.displayCaptionNow();
adjustCaptionTargetPosition();
}
}
private function seekBar_thumbRelease():void {
seekBarListener(null);
if(_playAfterScrub){
videoDisplay.play();
_playAfterScrub = false;
}
videoDisplayCaptioning.removeOldCaptions(NaN);
if(videoDisplayCaptioning.showCaptions){
videoDisplayCaptioning.displayCaptionNow();
adjustCaptionTargetPosition();
}
}
private function playheadUpdateHandler(event:VideoEvent=null):void {
if ( !isNaN(videoDisplay.totalTime) &&
(videoDisplay.state != "seeking") ) {
event = VideoEvent(event);
seekBar.value=videoDisplay.playheadTime;
}
stopButton.enabled = (videoDisplay.playheadTime>0);
adjustCaptionTargetPosition();
}
private function rewindHandler(e:VideoEvent=null):void {
stopClickHandler();
}
private function captionChangeHandler(e:CaptionChangeEvent=null):void {
adjustCaptionTargetPosition();
}
private function resizeHandler(e:Event=null):void {
videoControls.percentWidth=100;
videoControls.setConstraintValue("bottom",0);
adjustCaptionTargetPosition();
}
private function adjustCaptionTargetPosition():void {
if (videoDisplayCaptioning.captionTarget == null || videoDisplay == null) return;
if(videoDisplayCaptioning.captionTarget && videoDisplayCaptioning.showCaptions){
var captionTarget:DisplayObject = videoDisplayCaptioning.captionTarget;
captionTarget.visible = videoDisplayCaptioning.showCaptions;
var scaling:Number = videoDisplay.videoPlayer.width/videoDisplay.videoPlayer.videoWidth;
if(captionTarget.parent.scaleX!=scaling) captionTarget.parent.scaleX = captionTarget.parent.scaleY = scaling;
captionTarget.y = videoDisplay.videoHeight-5-captionTarget.height;
var newPoint:Point = videoDisplay.videoPlayer.localToGlobal(new Point(0, 0));
var newRect:Rectangle = new Rectangle(newPoint.x, newPoint.y, videoDisplay.videoPlayer.width, videoDisplay.videoPlayer.height);
newPoint = videoDisplay.globalToLocal( newPoint );
captionTarget.parent.x = newPoint.x;
captionTarget.parent.y = newPoint.y;
newPoint = videoControls.localToGlobal(new Point(0,0));
var controlsRect:Rectangle = new Rectangle(newPoint.x, newPoint.y, videoControls.width, videoControls.height);
if (captionTarget.parent != null && controlsRect.intersects(newRect)) {
captionTarget.parent.y -= controlsRect.intersection(newRect).height;
}
var gf:GlowFilter = new GlowFilter(0,1,2*scaling,2*scaling,10,3);
var dsf:DropShadowFilter = new DropShadowFilter(1*scaling,90,0,0.8,4,4,1);
captionTarget.filters = [textStrokeFilter, dsf];
}
}
private function showControls():void {
if(slideOut.isPlaying){
slideOut.stop();
}
if(!slideIn.isPlaying && videoControls.alpha!=1) {
slideIn.play([videoControls]);
}
adjustCaptionTargetPosition();
}
private function hideControls():void {
if(this.videoDisplay.state=="stopped"){
return;
}
if(slideIn.isPlaying){
slideIn.stop();
}
if(!slideOut.isPlaying && videoControls.alpha!=0) {
slideOut.play([videoControls]);
}
adjustCaptionTargetPosition();
}
private function fullScreenHandler(evt:FullScreenEvent):void {
slideOut.stop();
slideIn.stop();
dispState = Application.application.stage.displayState + " (fullScreen=" + evt.fullScreen.toString() + ")";
if (evt.fullScreen) {
fullScreenButton.selected = true;
} else {
fullScreenButton.selected = false;
}
Application.application.invalidateSize();
videoControls.percentWidth=100;
videoControls.setConstraintValue("bottom",0);
adjustCaptionTargetPosition();
}
private function toggleFullScreen():void {
try {
slideOut.stop();
slideIn.stop();
switch (Application.application.stage.displayState) {
case StageDisplayState.FULL_SCREEN:
Application.application.stage.displayState = StageDisplayState.NORMAL;
break;
default:
Application.application.stage.displayState = StageDisplayState.FULL_SCREEN;
break;
}
videoControls.percentWidth=100;
videoControls.setConstraintValue("bottom",0);
} catch (err:SecurityError) {
}
}
private function toggleCaptions():void {
this.videoDisplayCaptioning.showCaptions = captionButton.selected;
if(videoDisplayCaptioning.captionTarget){
videoDisplayCaptioning.captionTarget.visible = videoDisplayCaptioning.showCaptions;
}
}
private var mute:Boolean = false;
private function muteHandler(event:MouseEvent=null):void{
if (!mute) {
videoDisplay.volume = 0;
mute = true;
muteButton.selected = true;
fadeOutVolumeSlider.play([volumeSlider]);
}
else{
videoDisplay.volume = this.volumeSlider.value/100;
mute = false;
muteButton.selected = false;
if(muteButton.getFocus()==muteButton){
fadeInVolumeSlider.play([volumeSlider]);
}
}
}
private function handleFocusIn(event:FocusEvent):void {
showControls();
}
private function handleFocusOut(event:FocusEvent):void {
var pt:Point = this.localToGlobal(new Point(mouseY,mouseY));
pt = canvasWrapper.globalToLocal(pt);
if(!canvasWrapper.hitTestPoint(pt.x,pt.y)){
hideControls();
}
}
private function handleVolumeFocusEvent(event:FocusEvent=null):void {
switch(event.type){
case FocusEvent.FOCUS_IN:
if(fadeOutVolumeSlider.isPlaying){
fadeOutVolumeSlider.stop();
}
if(!fadeInVolumeSlider.isPlaying && volumeSlider.alpha!=1 && !mute){
fadeInVolumeSlider.play([volumeSlider]);
}
break;
case FocusEvent.FOCUS_OUT:
if(event.relatedObject!=volumeSlider && event.relatedObject != muteButton){
if(fadeInVolumeSlider.isPlaying){
fadeInVolumeSlider.stop();
}
if(!fadeOutVolumeSlider.isPlaying && volumeSlider.alpha!=0){
fadeOutVolumeSlider.play([volumeSlider]);
}
}
break;
}
}
private function handleVolumeMouseEvent(event:MouseEvent=null):void {
switch(event.type){
case MouseEvent.ROLL_OVER:
if(fadeOutVolumeSlider.isPlaying){
fadeOutVolumeSlider.stop();
}
if(!fadeInVolumeSlider.isPlaying && volumeSlider.alpha!=1 && !mute){
fadeInVolumeSlider.play([volumeSlider]);
}
break;
case MouseEvent.ROLL_OUT:
if(event.relatedObject!=volumeSlider && event.relatedObject != muteButton){
if(fadeInVolumeSlider.isPlaying){
fadeInVolumeSlider.stop();
}
if(!fadeOutVolumeSlider.isPlaying && volumeSlider.alpha!=0){
fadeOutVolumeSlider.play([volumeSlider]);
}
}
break;
}
}
private function seekBarListener(e:TimerEvent):void {
var scrubPos:Number = seekBar.value;
if (e == null) {
_seekBarTimer.stop();
if (scrubPos != _lastScrubPos) {
videoDisplay.playheadTime = seekBar.value;
}
videoDisplay.addEventListener(VideoEvent.PLAYHEAD_UPDATE, playheadUpdateHandler);
if (_playAfterScrub) {
videoDisplay.play();
}
} else if (videoDisplay.state == "seeking") {
} else if ( _seekBarScrubTolerance <= 0 ||
Math.abs(scrubPos - _lastScrubPos) > _seekBarScrubTolerance ||
scrubPos < _seekBarScrubTolerance ||
scrubPos > (100 - _seekBarScrubTolerance) ) {
if (scrubPos != _lastScrubPos) {
_lastScrubPos = scrubPos;
videoDisplay.playheadTime = seekBar.value;
}
}
}
]]>
</mx:Script>
<mx:Style source="css/TimedTextAppStyles.css" />
<mx:DateFormatter id="dateFormatter" formatString="NN:SS" />
<mx:DateFormatter id="dateFormatterHours" formatString="HH:NN:SS" />
<accessibility:AccessibilityProperties id="timeAcc" name="Playhead Time" />
<accessibility:AccessibilityProperties id="timeRemainingAcc" name="Time Remaining" />
<accessibility:AccessibilityProperties id="seekBarAcc" name="Seek Bar" />
<accessibility:AccessibilityProperties id="volumeAcc" name="Volume" />
<mx:Canvas id="canvasWrapper" height="100%" width="100%" autoLayout="true" rollOver="showControls()" rollOut="hideControls()">
<controls:VideoDisplayPlus width="100%" height="100%" id="videoDisplay"
cuePointManagerClass="mx.controls.videoClasses.CuePointManager"
autoPlay="false"
smoothing="true"
playheadUpdateInterval="16"
playheadUpdate="playheadUpdateHandler(event)" rewind="rewindHandler(event)"
resize="resizeHandler(event)" volume="{(muteButton.selected) ? 0 : volumeSlider.value/100}" />
<videoClasses:VideoDisplayCaptioning
id="videoDisplayCaptioning"
captionChange="captionChangeHandler(CaptionChangeEvent(event))"
autoLayout="false"
showCaptions="true" />
<mx:HBox autoLayout="true" id="videoControls" blendMode="layer" styleName="videoControls" width="{canvasWrapper.width}" height="1" maxHeight="72" minHeight="1" alpha="0" bottom="0" paddingBottom="0" paddingRight="10" paddingLeft="10" horizontalScrollPolicy="off" verticalScrollPolicy="off" horizontalGap="0" verticalAlign="middle">
<mx:Button id="playPauseButton"
styleName="playPauseButton"
label="{(playPauseButton.selected) ? 'Pause' : 'Play'}"
tabIndex="1"
buttonMode="true"
width="51"
height="50"
labelPlacement="bottom"
click="playPauseClickHandler(event)"
toggle="true"
selected="false" />
<mx:Button id="stopButton"
styleName="stopButton"
label="Stop"
tabIndex="2"
buttonMode="{videoDisplay.playheadTime>0}"
width="51"
height="50"
labelPlacement="bottom"
enabled="{videoDisplay.playheadTime>0}"
click="stopClickHandler(event)" />
<mx:HBox width="100%" height="100%" minWidth="0" verticalAlign="middle" clipContent="true" horizontalScrollPolicy="off" verticalScrollPolicy="off">
<mx:Spacer width="-10" />
<mx:Label
text="Playhead Time"
tabIndex="3"
width="1"
truncateToFit="false" />
<mx:Label id="time"
styleName="timeLabelStyle"
text="{videoTimeConvert(videoDisplay.playheadTime)}"
tabIndex="4"
filters="{new Array(textStrokeFilter)}"
width="56" />
<mx:Spacer width="-40" />
<mx:HSlider id="seekBar"
styleName="seekBar"
buttonMode="true"
tabIndex="5"
accessibilityProperties="{seekBarAcc}"
width="100%"
minimum="{0}"
maximum="{videoDisplay.totalTime}"
allowTrackClick="true"
liveDragging="false"
dataTipOffset="2"
dataTipFormatFunction="videoTimeConvert"
showTrackHighlight="false"
thumbPress="seekBar_thumbPress()"
thumbRelease="seekBar_thumbRelease()"
mouseDown="seekBar_thumbPress()"
change="seekBar_thumbRelease()"
sliderThumbClass="com.modernista.mx.controls.skins.StyledSliderThumb" />
<mx:Spacer width="-60" />
<mx:Label
text="Time Remaining"
tabIndex="6"
width="1"
truncateToFit="false" />
<mx:Text id="timeRemaining"
text="{'-'+videoTimeConvert(videoDisplay.totalTime-videoDisplay.playheadTime)}"
tabIndex="7"
styleName="timeLabelStyle"
filters="{new Array(textStrokeFilter)}"
width="66" />
</mx:HBox>
<mx:Button id="captionButton"
styleName="captionButton"
label="{(captionButton.selected) ? 'Hide Captions' : 'Show Captions'}"
tabIndex="8"
buttonMode="true"
width="51"
height="50"
labelPlacement="bottom"
click="toggleCaptions()"
toggle="true"
selected="true" />
<mx:Button id="muteButton"
styleName="muteButton"
label="{(muteButton.selected) ? 'Unmute Audio' : 'Mute Audio'}"
tabIndex="9"
buttonMode="true"
width="51"
height="50"
labelPlacement="bottom"
click="muteHandler(event)"
toggle="true"
selected="false"
focusIn="handleVolumeFocusEvent(FocusEvent(event))"
focusOut="handleVolumeFocusEvent(FocusEvent(event))"
rollOver="handleVolumeMouseEvent(MouseEvent(event))"
rollOut="handleVolumeMouseEvent(MouseEvent(event))" />
<mx:Button id="fullScreenButton"
styleName="fullScreenButton"
label="{(fullScreenButton.selected) ? 'Exit Full Screen' : 'Full Screen'}"
tabIndex="11"
buttonMode="true"
width="51"
height="50"
labelPlacement="bottom"
click="toggleFullScreen()"
toggle="true"
selected="false" />
</mx:HBox>
<controls:PreVolumeSlider id="volumeSlider"
styleName="volumeSlider"
tabIndex="10"
accessibilityProperties="{volumeAcc}"
buttonMode="true"
bottom="{muteButton.height+volumeSlider.height+11}"
x="{Math.min(width-volumeSlider.width, muteButton.x+(muteButton.width-volumeSlider.width)/2)}"
value="70"
minimum="0"
maximum="100"
snapInterval="10"
alpha="0"
focusIn="handleVolumeFocusEvent(FocusEvent(event))"
focusOut="handleVolumeFocusEvent(FocusEvent(event))"
rollOver="handleVolumeMouseEvent(MouseEvent(event))"
rollOut="handleVolumeMouseEvent(MouseEvent(event))"
mouseEnabled="{!muteButton.selected}"
enabled="{!muteButton.selected}"
tabEnabled="{!muteButton.selected}"
focusEnabled="{!muteButton.selected}" />
</mx:Canvas>
<mx:Parallel id="slideOut" startDelay="1000">
<mx:Resize heightTo="1" />
<mx:Move yTo="{videoDisplay.y+ videoDisplay.height-1}" />
<mx:Fade alphaTo="0" />
</mx:Parallel>
<mx:Parallel id="slideIn" startDelay="0">
<mx:Resize heightTo="72" />
<mx:Move yTo="{videoDisplay.y+ videoDisplay.height-72}" />
<mx:Fade alphaTo="1" />
</mx:Parallel>
<mx:Fade id="fadeInVolumeSlider" target="volumeSlider" alphaTo="1" startDelay="500" effectStart="fadeOutVolumeSlider.stop(); fadeInVolumeSlider.stop();">
</mx:Fade>
<mx:Fade id="fadeOutVolumeSlider" target="volumeSlider" alphaTo="0" startDelay="1000" effectStart="fadeOutVolumeSlider.stop(); fadeInVolumeSlider.stop();">
</mx:Fade>
</mx:Application>