<?xml version="1.0"?>
<!--                                                               -->
<!-- Adobe Flex 3 source file of VPlayer9.swf,                     -->
<!-- a FlashPlayer-9 compatible component for playing              -->
<!-- FLV and MP4/H.264 video files and streams.                    -->
<!--                                                               -->
<!-- version 20150729                                              -->
<!--                                                               -->
<!-- Copyright (C) 2012-today  Alexander Grahn                     -->
<!--                                                               -->
<!-- This work may be distributed and/or modified under the        -->
<!-- conditions of the LaTeX Project Public License.               -->
<!--                                                               -->
<!-- The latest version of this license is in                      -->
<!--   http://www.latex-project.org/lppl.txt                       -->
<!--                                                               -->
<!-- This work has the LPPL maintenance status `maintained'.       -->
<!--                                                               -->
<!-- The current maintainer of this work is A. Grahn.              -->
<!--                                                               -->

<mx:Application
  xmlns:mx="http://www.adobe.com/2006/mxml"
  preinitialize="initialise(this.parameters);"
  applicationComplete="initApp();"
  backgroundAlpha="0"
  paddingTop="0" paddingBottom="0"
  paddingLeft="0" paddingRight="0"
  layout="absolute" clipContent="false"
>
  <mx:Script>
    <![CDATA[
      [Bindable] private var source:String;
      [Bindable] private var autoPlay:Boolean=false;
      [Bindable] private var loop:Boolean=false;
      [Bindable] private var vol:Number=0.75;
      [Bindable] private var keepAspect:Boolean=true;
      private var vidComplete:Boolean=false;
      private var deltaSeek:Number;
      private var playheadTime:Number;
      private var newPos:Number;
      private var keyPressed:Boolean=false;
      private var muted:Boolean=false;
      private var lastVolume:Number;
      private var pauseAtPos:Number = -1;
      private var toBePaused:Boolean = false;

      import flash.external.*;
      private function initialise(flashVars:Object):void {
        source=flashVars.source;
        if(flashVars.autoPlay=='true') autoPlay=true;
        if(flashVars.loop=='true') loop=true;
        if(flashVars.volume) vol=Number(flashVars.volume);
        if(flashVars.scaleMode && flashVars.scaleMode!='letterbox') keepAspect=false;
      }

      private function onProgress(event:ProgressEvent):void {
        if (event.bytesTotal) event.target.visible=true;
        else event.target.visible=false;
      }

      import mx.events.VideoEvent;
      //import flash.events.VideoEvent;
      import mx.controls.Alert;
      private function onStateChange(event:mx.events.VideoEvent):void {
        vidComplete=false;
        if(event.state=='connectionError')
          Alert.show('Unable to play \''+event.target.source+'\'','Error');
      }

      private function onKeyDown(e:KeyboardEvent):void {
        switch(e.keyCode) {
          case 32: //space bar
            playPause();
            break;
          case 36: //home
            vidDisp.pause();
            vidDisp.playheadTime=0;
            break;
          case 35: //end
            if(vidDisp.bytesTotal){
              vidDisp.pause();
              vidDisp.playheadTime=vidDisp.totalTime-0.1;
            }
            break;
          case 37: //<--
            fadeEffect.end();
            playProgress.alpha=0.5;
            playProgress.visible=true;
            if(!keyPressed){
              deltaSeek=Math.max(1,vidDisp.totalTime/1000);
              playheadTime=vidDisp.playheadTime;
            }
            keyPressed=true;
            newPos=Math.max(0,playheadTime-deltaSeek);
            playProgress.setProgress(newPos,vidDisp.totalTime);
            playProgress.label=formatTime(newPos);
            vidDisp.playheadTime=newPos;
            deltaSeek*=1.1;
            break;
          case 39: //-->
            fadeEffect.end();
            playProgress.alpha=0.5;
            playProgress.visible=true;
            if(!keyPressed){
              deltaSeek=Math.max(1,vidDisp.totalTime/1000);
              playheadTime=vidDisp.playheadTime;
            }
            keyPressed=true;
            newPos=Math.min(vidDisp.totalTime-0.1,playheadTime+deltaSeek);
            playProgress.setProgress(newPos,vidDisp.totalTime);
            playProgress.label=formatTime(newPos);
            vidDisp.playheadTime=newPos;
            deltaSeek*=1.1;
            break;
          case 38:
            vol=Math.min(1,vol+0.025);
            volume(vol);
            break;
          case 40:
            vol=Math.max(0,vol-0.025);
            volume(vol);
            break;
          default:
          if(e.charCode==109) mute(); //`m'
        }
      }

      private function onKeyUp(e:KeyboardEvent):void {
        switch(e.keyCode) {
          case 37: //<--
          case 39: //-->
            deltaSeek=Math.max(1,vidDisp.totalTime/1000);
            keyPressed=false;
            fadeEffect.play();
            break;
        }
      }

      private function onPlayheadUpdate(e:Event):void {
        if(vidDisp.playing&&pauseAtPos>=0&&vidDisp.playheadTime<pauseAtPos)
          toBePaused=true;
        if(
          vidDisp.playing&&pauseAtPos>=0&&
          vidDisp.playheadTime>=pauseAtPos&&toBePaused
        ){
          pause();
          pauseAtPos=-1;
          toBePaused=false;
        }
      }

      private function play(p:Number=-1):void {
        if(p>=0) seek(p);
        if(vidComplete){seek(0);}vidDisp.play();
      }

      private function pause(p:Number=-1):void {
        if(p>=0){pauseAtPos=p;return;}
        vidDisp.pause();
      }

      private function playPause():void {
        if(vidDisp.playing) vidDisp.pause(); else vidDisp.play();
      }

      private function seek(p:Number):void {
        vidDisp.playheadTime=p;
      }

      private function rewind():void {
        vidDisp.playheadTime=0;
      }

      private function volume(v:Number):void {
        muted=false;
        vidDisp.volume = v;
      }

      private function mute():void {
        if(muted) {
          if (lastVolume==0) volume(0.75);
          else volume(lastVolume);
        }
        else {
          muted=true;lastVolume=vidDisp.volume;vidDisp.volume=0;
        }
      }

      private function setSource(s:String):void {
        vidDisp.pause();vidDisp.source = s;
        vidDisp.play();vidDisp.pause();
        vidDisp.playheadTime=0;
      }

      private function formatTime(s:Number):String {
        var hrs:Number = Math.floor(s / 3600);
        var min:Number = Math.floor(s / 60 % 60);
        var sec:Number = Math.floor(s % 60);

        var fmtd:String='';

        if (hrs>0) fmtd = String(hrs)+':';

        if (hrs>0 && min <10) fmtd+='0';
        fmtd += String(min)+':';

        if (sec<10) fmtd+='0';
        fmtd += String(sec);

        return fmtd;
      }

      private function currentTime():Number {
        return vidDisp.playheadTime;
      }

      private function playing():Boolean {
        return vidDisp.playing;
      }

      private function duration():Number {
        return vidDisp.totalTime;
      }

      private function ismuted():Boolean {
        return muted;
      }

      private function initApp():void {
        this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
        this.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
        ExternalInterface.addCallback("play", play);
        ExternalInterface.addCallback("pause", pause);
        ExternalInterface.addCallback("playPause", playPause);
        ExternalInterface.addCallback("seek", seek);
        ExternalInterface.addCallback("rewind", rewind);
        ExternalInterface.addCallback("volume", volume);
        ExternalInterface.addCallback("mute", mute);
        ExternalInterface.addCallback("setSource", setSource);
        ExternalInterface.addCallback("currentTime", currentTime);
        ExternalInterface.addCallback("duration", duration);
        ExternalInterface.addCallback("playing", playing);
        ExternalInterface.addCallback("muted", ismuted);

        var itemPlayPause:ContextMenuItem = new ContextMenuItem("N.N.");
        this.contextMenu.customItems.push(itemPlayPause);
        itemPlayPause.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
          function(e:ContextMenuEvent):void{playPause();});

        var itemRewind:ContextMenuItem = new ContextMenuItem("Rewind, [Home]");
        this.contextMenu.customItems.push(itemRewind);
        itemRewind.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
          function(e:ContextMenuEvent):void{vidDisp.pause();seek(0);});

        var itemGotoEnd:ContextMenuItem = new ContextMenuItem("Goto End, [End]");
        this.contextMenu.customItems.push(itemGotoEnd);
        itemGotoEnd.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
          function(e:ContextMenuEvent):void{if(vidDisp.bytesTotal){
              vidDisp.pause();
              vidDisp.playheadTime=vidDisp.totalTime-0.1;}});

        var itemMute:ContextMenuItem = new ContextMenuItem("N.N.");
        this.contextMenu.customItems.push(itemMute);
        itemMute.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
          function(e:ContextMenuEvent):void{mute();});

        this.contextMenu.customItems.push(
          new ContextMenuItem("via keyboard:", true, false, true));
        this.contextMenu.customItems.push(
          new ContextMenuItem("Seek, [\u2190]/[\u2192]", false, false, true));
        this.contextMenu.customItems.push(
          new ContextMenuItem("Volume, [\u2191]/[\u2193]", false, false, true));

        this.contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT,
          function(e:ContextMenuEvent):void{
            itemPlayPause.caption=(vidDisp.playing ? "Pause" : "Play")+", [Space]";
            itemMute.caption=(muted ? "Unmute" : "Mute")+", [m]";}
        );
      }
    ]]>
  </mx:Script>

  <mx:Fade id="fadeEffect" target="{playProgress}" alphaFrom="0.5" alphaTo="0" duration="2000"
      effectEnd="playProgress.label=''"
  />

  <mx:VideoDisplay
      id="vidDisp"
      width="100%" height="100%" maintainAspectRatio="{keepAspect}"
      backgroundAlpha="0" borderThickness="0"
      source="{source}" volume="{vol}"
      autoPlay="{autoPlay}" autoRewind="{loop}"
      stateChange="onStateChange(event);"
      complete="vidComplete=true;"
      rewind="vidDisp.play();"
      playheadUpdate="onPlayheadUpdate(event);"
  />

  <mx:ProgressBar width="100%" mode="polled" source="vidDisp"
      horizontalCenter="0" bottom="0" labelPlacement="center"
      id="loadingProgress" alpha="0.5"
      complete="loadingProgress.visible=false;"
      progress="onProgress(event)"
  />

  <mx:ProgressBar width="100%" mode="manual"
      horizontalCenter="0" bottom="0" labelPlacement="center"
      id="playProgress" alpha="0.5"
      visible="false"
  />

  <mx:Button alpha="0" width="100%" height="100%" cornerRadius="0"
    paddingBottom="0" paddingLeft="0" paddingRight="0" paddingTop="0"
    mouseDown="vidDisp.pause();"
    mouseUp="if(vidComplete) vidDisp.playheadTime=0;vidDisp.play();"
  />
</mx:Application>
