summaryrefslogtreecommitdiff
path: root/macros/latex/contrib/media9/players
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /macros/latex/contrib/media9/players
Initial commit
Diffstat (limited to 'macros/latex/contrib/media9/players')
-rw-r--r--macros/latex/contrib/media9/players/APlayer.mxml429
-rw-r--r--macros/latex/contrib/media9/players/APlayer.swfbin0 -> 354878 bytes
-rw-r--r--macros/latex/contrib/media9/players/APlayer9.mxml417
-rw-r--r--macros/latex/contrib/media9/players/APlayer9.swfbin0 -> 206165 bytes
-rw-r--r--macros/latex/contrib/media9/players/BSD-License32
-rw-r--r--macros/latex/contrib/media9/players/SMPfixes.patch158
-rw-r--r--macros/latex/contrib/media9/players/SlideShow.mxml482
-rw-r--r--macros/latex/contrib/media9/players/SlideShow.swfbin0 -> 326715 bytes
-rw-r--r--macros/latex/contrib/media9/players/StrobeMediaPlayback-license5
-rw-r--r--macros/latex/contrib/media9/players/StrobeMediaPlayback.swfbin0 -> 275747 bytes
-rw-r--r--macros/latex/contrib/media9/players/VPlayer.mxml338
-rw-r--r--macros/latex/contrib/media9/players/VPlayer.swfbin0 -> 483412 bytes
-rw-r--r--macros/latex/contrib/media9/players/VPlayer9.mxml318
-rw-r--r--macros/latex/contrib/media9/players/VPlayer9.swfbin0 -> 219242 bytes
14 files changed, 2179 insertions, 0 deletions
diff --git a/macros/latex/contrib/media9/players/APlayer.mxml b/macros/latex/contrib/media9/players/APlayer.mxml
new file mode 100644
index 0000000000..b03f04a4fc
--- /dev/null
+++ b/macros/latex/contrib/media9/players/APlayer.mxml
@@ -0,0 +1,429 @@
+<?xml version="1.0"?>
+<!-- -->
+<!-- Apache Flex 4 source file of APlayer.swf, -->
+<!-- a FlashPlayer-10 compatible component for playing -->
+<!-- MP3 audio files and streams. -->
+<!-- -->
+<!-- version 20150601 -->
+<!-- -->
+<!-- -->
+<!-- The free Apache Flex 4 SDK is required to compile -->
+<!-- this file. Get it from -->
+<!-- -->
+<!-- http://flex.apache.org/download-binaries.html -->
+<!-- -->
+<!-- and run -->
+<!-- -->
+<!-- mxmlc -static-link-runtime-shared-libraries APlayer.mxml -->
+<!-- -->
+<!-- on the command line. -->
+<!-- -->
+<!-- -->
+<!-- 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. -->
+<!-- -->
+
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:s="library://ns.adobe.com/flex/spark"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ preinitialize="initialise(this.parameters);"
+ applicationComplete="initSound();addEventListeners();
+ fadeTargets=new Array(playProgress, caption);"
+ creationComplete="initCallBacks();initContext();"
+ mouseDown="pause();setFocus();"
+ mouseUp="play();"
+ backgroundAlpha="0"
+>
+
+ <fx:Script>
+ <![CDATA[
+ [Bindable] private var source:String;
+ [Bindable] private var policy:String=null;
+ [Bindable] private var autoPlay:Boolean=false;
+ [Bindable] private var loop:Boolean=false;
+ [Bindable] private var vol:Number=0.75;
+ [Bindable] private var pan:Number=0;
+ [Bindable] private var hideBar:Boolean=false;
+ [Bindable] private var fadeTargets:Array;
+ [Bindable] private var txtAlign:String;
+
+ private var snd:Sound;
+ private var id3:ID3Info;
+ private var sndCh:SoundChannel;
+ private var sndTr:SoundTransform;
+ private var playResumePos:Number = 0;
+ private var pauseAtPos:Number = -1;
+ private var toBePaused:Boolean = false;
+ private var plyng:Boolean = false;
+ private var muted:Boolean = false;
+ private var lastVol:Number;
+
+ private var deltaSeek:Number;
+ private var curTime:Number;
+ private var keyPressed:Boolean=false;
+ private var mouseIsOver:Boolean=false;
+
+ private function initialise(flashVars:Object):void {
+ source=flashVars.source;
+ if(flashVars.policy) policy=flashVars.policy;
+ if(flashVars.autoPlay=='true') autoPlay=true;
+ if(flashVars.loop=='true') loop=true;
+ if(flashVars.volume) vol=Number(flashVars.volume);
+ if(flashVars.balance) pan=Number(flashVars.balance);
+ if(flashVars.hideBar=='true') hideBar=true;
+ }
+
+ import mx.controls.Alert;
+
+ private function initSound():void {
+ snd = new Sound(); id3=null;
+ sndTr = new SoundTransform(vol, pan);
+ snd.addEventListener(Event.ID3, onID3Info);
+ snd.addEventListener(IOErrorEvent.IO_ERROR, onError);
+ snd.addEventListener(ProgressEvent.PROGRESS, onProgress);
+ snd.addEventListener(Event.COMPLETE, onComplete);
+ if(policy) Security.loadPolicyFile(policy);
+ snd.load(new URLRequest(source), new SoundLoaderContext(1000, true));
+ if(autoPlay) play();
+ }
+
+ private function onMouseOver(e:MouseEvent):void {
+ mouseIsOver=true;
+ fadeEffect.end();
+ playProgress.alpha=caption.alpha=1.0;
+ }
+
+ private function onMouseOut(e:MouseEvent):void {
+ mouseIsOver=false;
+ fadeEffect.play();
+ }
+
+ private function onKeyDown(e:KeyboardEvent):void {
+ switch(e.keyCode) {
+ case 32: //space bar
+ playPause();
+ break;
+ case 36: //home
+ pause();
+ playResumePos=(0);
+ break;
+ case 35: //end
+ if(playProgress.indeterminate) break;
+ pause();
+ playResumePos=(snd.length);
+ break;
+ case 37: //<--
+ fadeEffect.end();
+ playProgress.alpha=caption.alpha=1.0;
+ if(e.ctrlKey){
+ pan=Math.max(-1,pan-0.025);
+ balance(pan);
+ break;
+ }
+ if(!keyPressed){
+ deltaSeek=Math.max(100,snd.length/10000);
+ if(plyng)
+ curTime=sndCh.position;
+ else
+ curTime=playResumePos;
+ }
+ keyPressed=true;
+ playResumePos=Math.max(0,curTime-deltaSeek);
+ if(plyng) seek(playResumePos/1000);
+ deltaSeek*=1.1;
+ break;
+ case 39: //-->
+ fadeEffect.end();
+ playProgress.alpha=caption.alpha=1.0;
+ if(e.ctrlKey){
+ pan=Math.min(1,pan+0.025);
+ balance(pan);
+ break;
+ }
+ if(!keyPressed){
+ deltaSeek=Math.max(100,snd.length/10000);
+ if(plyng)
+ curTime=sndCh.position;
+ else
+ curTime=playResumePos;
+ }
+ keyPressed=true;
+ playResumePos=Math.min(snd.length-10,curTime+deltaSeek);
+ seek(playResumePos/1000);
+ deltaSeek*=1.1;
+ break;
+ case 38:
+ vol=Math.min(1,vol+0.025);
+ volume(vol);
+ break;
+ case 40:
+ if(e.ctrlKey){
+ pan=0;
+ balance(pan);
+ break;
+ }
+ 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(100,snd.length/10000);
+ keyPressed=false;
+ if (!mouseIsOver) fadeEffect.play();
+ break;
+ }
+ }
+
+ private function formatLabel(s:Number):String {
+ s/=1000;
+ 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);
+ txtAlign="center";
+ try{
+ if(id3.songName)
+ fmtd += ' '+ String.fromCharCode(0x2014) + ' ' + id3.songName;
+ if(id3.artist) fmtd += ' | ' + id3.artist;
+ if(id3.album) fmtd += ' | ' + id3.album;
+ if(id3) txtAlign="start";
+ }catch(e:Object){}
+ return fmtd;
+ }
+
+ private function addEventListeners():void {
+ this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+ this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
+ this.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
+ this.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
+ this.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
+ }
+
+ private function setSource(s:String):void {
+ pause();
+ source=s;
+ initSound();
+ pause();seek(0);
+ }
+
+ private function loadPolicy(p:String):void {policy=p;}
+
+ private function play(p:Number=-1):void {
+ if(p>=0) seek(p);
+ if(plyng) return;
+ try{sndCh = snd.play(playResumePos, 0, sndTr);}
+ catch(e:Error){Alert.show(e.message,'Error');}
+ sndCh.addEventListener(Event.SOUND_COMPLETE, onSoundComplete);
+ plyng = true;
+ }
+
+ private function pause(p:Number=-1):void {
+ if(p>=0){pauseAtPos=p*1000;return;}
+ if(!plyng) return;
+ playResumePos = sndCh.position;
+ sndCh.stop();
+ plyng = false;
+ }
+
+ private function playPause():void {
+ if(plyng) pause(); else play();
+ }
+
+ private function seek(p:Number):void {
+ playResumePos = p*1000;
+ if(!plyng) return;
+ sndCh.stop();
+ plyng = false;
+ play();
+ }
+
+ private function rewind():void {
+ seek(0);
+ }
+
+ private function volume(v:Number):void {
+ sndTr.volume = v;
+ sndCh.soundTransform=sndTr;
+ }
+
+ private function mute():void {
+ if(muted) {
+ if(lastVol==0) lastVol=0.75;
+ volume(lastVol);
+ muted=false;
+ }
+ else {
+ lastVol = sndTr.volume
+ volume(0);
+ muted=true;
+ }
+ }
+
+ private function balance(p:Number):void {
+ sndTr.pan = p;
+ sndCh.soundTransform=sndTr;
+ }
+
+ private function currentTime():Number {
+ return sndCh.position/1000;
+ }
+
+ private function playing():Boolean {
+ return plyng;
+ }
+
+ private function duration():Number {
+ return snd.length/1000;
+ }
+
+ private function ismuted():Boolean {
+ return muted;
+ }
+
+ private function initCallBacks():void {
+ 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("balance", balance);
+ ExternalInterface.addCallback("mute", mute);
+ ExternalInterface.addCallback("setSource", setSource);
+ ExternalInterface.addCallback("loadPolicy", loadPolicy);
+ ExternalInterface.addCallback("currentTime", currentTime);
+ ExternalInterface.addCallback("duration", duration);
+ ExternalInterface.addCallback("playing", playing);
+ ExternalInterface.addCallback("muted", ismuted);
+ }
+
+ private function initContext():void {
+ this.contextMenu.hideBuiltInItems();
+
+ 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{pause();playResumePos=(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(playProgress.indeterminate) return;
+ pause();playResumePos=(snd.length);});
+
+ 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.customItems.push(
+ new ContextMenuItem("Balance, [Ctrl]+[\u2190]/[\u2193]/[\u2192]",
+ false, false, true));
+
+ this.contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT,
+ function(e:ContextMenuEvent):void{
+ itemPlayPause.caption=(plyng ? "Pause" : "Play")+", [Space]";
+ itemMute.caption=(muted ? "Unmute" : "Mute")+", [m]";}
+ );
+ }
+
+ private function onSoundComplete(e:Event):void {
+ plyng = false;
+ playResumePos = 0;
+ if(loop) play();
+ }
+
+ private function onComplete(e:Event):void {
+ playProgress.indeterminate=false;
+ }
+
+ private function onProgress(e:ProgressEvent):void {
+ playProgress.indeterminate=true;
+ }
+
+ private function onEnterFrame(e:Event):void {
+ if(!playProgress.indeterminate) {
+ if(plyng) {
+ playProgress.setProgress(sndCh.position,snd.length);
+ caption.text=formatLabel(sndCh.position);
+ } else {
+ playProgress.setProgress(playResumePos,snd.length);
+ caption.text=formatLabel(playResumePos);
+ }
+ }else{
+ if(plyng) {
+ playProgress.setProgress(Math.random(),1);
+ caption.text=formatLabel(sndCh.position);
+ } else {
+ playProgress.setProgress(snd.bytesLoaded,snd.bytesTotal);
+ caption.text=formatLabel(playResumePos);
+ }
+ }
+ if(plyng&&pauseAtPos>=0&&sndCh.position<pauseAtPos)
+ toBePaused=true;
+ if(
+ plyng&&pauseAtPos>=0&&
+ sndCh.position>=pauseAtPos&&toBePaused
+ ){
+ pause();
+ pauseAtPos=-1;
+ toBePaused=false;
+ }
+ }
+
+ private function onID3Info(e:Event):void {id3 = e.target.id3;}
+
+ private function onError(e:ErrorEvent):void {
+ Alert.show(e.type, e.text);
+ }
+ ]]>
+ </fx:Script>
+
+ <fx:Declarations>
+ <s:Fade id="fadeEffect" targets="{fadeTargets}" alphaFrom="1.0" alphaTo="0"
+ duration="2000"/>
+ </fx:Declarations>
+
+ <mx:ProgressBar width="100%" height="100%" mode="manual"
+ labelPlacement="center" label="" id="playProgress"
+ visible="{!hideBar}"
+ />
+
+ <s:Label id="caption" width="100%" height="100%" verticalCenter="0"
+ paddingTop="2" fontWeight="bold" verticalAlign="middle" visible="{!hideBar}"
+ textAlign="{txtAlign}" paddingLeft="5"
+ />
+</s:Application>
diff --git a/macros/latex/contrib/media9/players/APlayer.swf b/macros/latex/contrib/media9/players/APlayer.swf
new file mode 100644
index 0000000000..7aea76a9d8
--- /dev/null
+++ b/macros/latex/contrib/media9/players/APlayer.swf
Binary files differ
diff --git a/macros/latex/contrib/media9/players/APlayer9.mxml b/macros/latex/contrib/media9/players/APlayer9.mxml
new file mode 100644
index 0000000000..9ea40902df
--- /dev/null
+++ b/macros/latex/contrib/media9/players/APlayer9.mxml
@@ -0,0 +1,417 @@
+<?xml version="1.0"?>
+<!-- -->
+<!-- Adobe Flex 3 source file of APlayer9.swf, -->
+<!-- a FlashPlayer-9 compatible component for playing -->
+<!-- MP3 audio files and streams. -->
+<!-- -->
+<!-- version 20150601 -->
+<!-- -->
+<!-- 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="initSound();addEventListeners();"
+ creationComplete="initCallBacks();initContext();"
+ mouseDown="pause();setFocus();"
+ mouseUp="play();"
+ 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 policy:String=null;
+ [Bindable] private var autoPlay:Boolean=false;
+ [Bindable] private var loop:Boolean=false;
+ [Bindable] private var vol:Number=0.75;
+ [Bindable] private var pan:Number=0;
+ [Bindable] private var hideBar:Boolean=false;
+ [Bindable] private var txtAlign:String;
+
+ private var snd:Sound;
+ private var id3:ID3Info;
+ private var sndCh:SoundChannel;
+ private var sndTr:SoundTransform;
+ private var playResumePos:Number = 0;
+ private var pauseAtPos:Number = -1;
+ private var toBePaused:Boolean = false;
+ private var plyng:Boolean = false;
+ private var muted:Boolean = false;
+ private var lastVol:Number;
+
+ private var deltaSeek:Number;
+ private var curTime:Number;
+ private var keyPressed:Boolean=false;
+ private var mouseIsOver:Boolean=false;
+
+ import flash.external.*;
+ private function initialise(flashVars:Object):void {
+ source=flashVars.source;
+ if(flashVars.policy) policy=flashVars.policy;
+ if(flashVars.autoPlay=='true') autoPlay=true;
+ if(flashVars.loop=='true') loop=true;
+ if(flashVars.volume) vol=Number(flashVars.volume);
+ if(flashVars.balance) pan=Number(flashVars.balance);
+ if(flashVars.hideBar=='true') hideBar=true;
+ }
+
+ import mx.controls.Alert;
+
+ private function initSound():void {
+ snd = new Sound(); id3=null;
+ sndTr = new SoundTransform(vol, pan);
+ snd.addEventListener(Event.ID3, onID3Info);
+ snd.addEventListener(IOErrorEvent.IO_ERROR, onError);
+ snd.addEventListener(ProgressEvent.PROGRESS, onProgress);
+ snd.addEventListener(Event.COMPLETE, onComplete);
+ if(policy) Security.loadPolicyFile(policy);
+ snd.load(new URLRequest(source), new SoundLoaderContext(1000, true));
+ if(autoPlay) play();
+ }
+
+ private function onMouseOver(e:MouseEvent):void {
+ mouseIsOver=true;
+ fadeEffect.end();
+ playProgress.alpha=caption.alpha=1.0;
+ caption.visible=!hideBar;
+ }
+
+ private function onMouseOut(e:MouseEvent):void {
+ mouseIsOver=false;
+ fadeEffect.play();
+ }
+
+ private function onKeyDown(e:KeyboardEvent):void {
+ switch(e.keyCode) {
+ case 32: //space bar
+ playPause();
+ break;
+ case 36: //home
+ pause();
+ playResumePos=(0);
+ break;
+ case 35: //end
+ if(playProgress.indeterminate) break;
+ pause();
+ playResumePos=(snd.length);
+ break;
+ case 37: //<--
+ fadeEffect.end();
+ playProgress.alpha=caption.alpha=1.0;
+ caption.visible=!hideBar;
+ if(e.ctrlKey){
+ pan=Math.max(-1,pan-0.025);
+ balance(pan);
+ break;
+ }
+ if(!keyPressed){
+ deltaSeek=Math.max(100,snd.length/10000);
+ if(plyng)
+ curTime=sndCh.position;
+ else
+ curTime=playResumePos;
+ }
+ keyPressed=true;
+ playResumePos=Math.max(0,curTime-deltaSeek);
+ if(plyng) seek(playResumePos/1000);
+ deltaSeek*=1.1;
+ break;
+ case 39: //-->
+ fadeEffect.end();
+ playProgress.alpha=caption.alpha=1.0;
+ caption.visible=!hideBar;
+ if(e.ctrlKey){
+ pan=Math.min(1,pan+0.025);
+ balance(pan);
+ break;
+ }
+ if(!keyPressed){
+ deltaSeek=Math.max(100,snd.length/10000);
+ if(plyng)
+ curTime=sndCh.position;
+ else
+ curTime=playResumePos;
+ }
+ keyPressed=true;
+ playResumePos=Math.min(snd.length-10,curTime+deltaSeek);
+ seek(playResumePos/1000);
+ deltaSeek*=1.1;
+ break;
+ case 38:
+ vol=Math.min(1,vol+0.025);
+ volume(vol);
+ break;
+ case 40:
+ if(e.ctrlKey){
+ pan=0;
+ balance(pan);
+ break;
+ }
+ 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(100,snd.length/10000);
+ keyPressed=false;
+ if (!mouseIsOver) fadeEffect.play();
+ break;
+ }
+ }
+
+ private function formatLabel(s:Number):String {
+ s/=1000;
+ 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);
+ txtAlign="center";
+ try{
+ if(id3.songName)
+ fmtd += ' '+ String.fromCharCode(0x2014) + ' ' + id3.songName;
+ if(id3.artist) fmtd += ' | ' + id3.artist;
+ if(id3.album) fmtd += ' | ' + id3.album;
+ if(id3) txtAlign="start";
+ }catch(e:Object){}
+ return fmtd;
+ }
+
+ private function addEventListeners():void {
+ this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+ this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
+ this.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);
+ this.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
+ this.addEventListener(MouseEvent.MOUSE_OVER, onMouseOver);
+ }
+
+ private function setSource(s:String):void {
+ pause();
+ source=s;
+ initSound();
+ pause();seek(0);
+ }
+
+ private function loadPolicy(p:String):void {policy=p;}
+
+ private function play(p:Number=-1):void {
+ if(p>=0) seek(p);
+ if(plyng) return;
+ try{sndCh = snd.play(playResumePos, 0, sndTr);}
+ catch(e:Error){Alert.show(e.message,'Error');}
+ sndCh.addEventListener(Event.SOUND_COMPLETE, onSoundComplete);
+ plyng = true;
+ }
+
+ private function pause(p:Number=-1):void {
+ if(p>=0){pauseAtPos=p*1000;return;}
+ if(!plyng) return;
+ playResumePos = sndCh.position;
+ sndCh.stop();
+ plyng = false;
+ }
+
+ private function playPause():void {
+ if(plyng) pause(); else play();
+ }
+
+ private function seek(p:Number):void {
+ playResumePos = p*1000;
+ if(!plyng) return;
+ sndCh.stop();
+ plyng = false;
+ play();
+ }
+
+ private function rewind():void {
+ seek(0);
+ }
+
+ private function volume(v:Number):void {
+ sndTr.volume = v;
+ sndCh.soundTransform=sndTr;
+ }
+
+ private function mute():void {
+ if(muted) {
+ if(lastVol==0) lastVol=0.75;
+ volume(lastVol);
+ muted=false;
+ }
+ else {
+ lastVol = sndTr.volume
+ volume(0);
+ muted=true;
+ }
+ }
+
+ private function balance(p:Number):void {
+ sndTr.pan = p;
+ sndCh.soundTransform=sndTr;
+ }
+
+ private function currentTime():Number {
+ return sndCh.position/1000;
+ }
+
+ private function playing():Boolean {
+ return plyng;
+ }
+
+ private function duration():Number {
+ return snd.length/1000;
+ }
+
+ private function ismuted():Boolean {
+ return muted;
+ }
+
+ private function initCallBacks():void {
+ 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("balance", balance);
+ ExternalInterface.addCallback("mute", mute);
+ ExternalInterface.addCallback("setSource", setSource);
+ ExternalInterface.addCallback("loadPolicy", loadPolicy);
+ ExternalInterface.addCallback("currentTime", currentTime);
+ ExternalInterface.addCallback("duration", duration);
+ ExternalInterface.addCallback("playing", playing);
+ ExternalInterface.addCallback("muted", ismuted);
+ }
+
+ private function initContext():void {
+ this.contextMenu.hideBuiltInItems();
+
+ 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{pause();playResumePos=(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(playProgress.indeterminate) return;
+ pause();playResumePos=(snd.length);});
+
+ 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.customItems.push(
+ new ContextMenuItem("Balance, [Ctrl]+[\u2190]/[\u2193]/[\u2192]",
+ false, false, true));
+
+ this.contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT,
+ function(e:ContextMenuEvent):void{
+ itemPlayPause.caption=(plyng ? "Pause" : "Play")+", [Space]";
+ itemMute.caption=(muted ? "Unmute" : "Mute")+", [m]";}
+ );
+ }
+
+ private function onSoundComplete(e:Event):void {
+ plyng = false;
+ playResumePos = 0;
+ if(loop) play();
+ }
+
+ private function onComplete(e:Event):void {
+ playProgress.indeterminate=false;
+ }
+
+ private function onProgress(e:ProgressEvent):void {
+ playProgress.indeterminate=true;
+ }
+
+ private function onEnterFrame(e:Event):void {
+ if(!playProgress.indeterminate) {
+ if(plyng) {
+ playProgress.setProgress(sndCh.position,snd.length);
+ caption.text=formatLabel(sndCh.position);
+ } else {
+ playProgress.setProgress(playResumePos,snd.length);
+ caption.text=formatLabel(playResumePos);
+ }
+ }else{
+ if(plyng) {
+ playProgress.setProgress(Math.random(),1);
+ caption.text=formatLabel(sndCh.position);
+ } else {
+ playProgress.setProgress(snd.bytesLoaded,snd.bytesTotal);
+ caption.text=formatLabel(playResumePos);
+ }
+ }
+ if(plyng&&pauseAtPos>=0&&sndCh.position<pauseAtPos)
+ toBePaused=true;
+ if(
+ plyng&&pauseAtPos>=0&&
+ sndCh.position>=pauseAtPos&&toBePaused
+ ){
+ pause();
+ pauseAtPos=-1;
+ toBePaused=false;
+ }
+ }
+
+ private function onID3Info(e:Event):void {id3 = e.target.id3;}
+
+ private function onError(e:ErrorEvent):void {
+ Alert.show(e.type, e.text);
+ }
+ ]]>
+ </mx:Script>
+
+ <mx:Fade id="fadeEffect" target="{playProgress}" alphaFrom="1.0" alphaTo="0"
+ effectEnd="caption.visible=false" duration="2000"/>
+
+ <mx:ProgressBar width="100%" height="100%" mode="manual"
+ labelPlacement="center" label="" id="playProgress"
+ visible="{!hideBar}"
+ />
+
+ <mx:Label id="caption" width="100%" verticalCenter="0"
+ paddingTop="2" fontWeight="bold" visible="{!hideBar}"
+ textAlign="{txtAlign}" paddingLeft="5"
+ />
+</mx:Application>
diff --git a/macros/latex/contrib/media9/players/APlayer9.swf b/macros/latex/contrib/media9/players/APlayer9.swf
new file mode 100644
index 0000000000..eb26630025
--- /dev/null
+++ b/macros/latex/contrib/media9/players/APlayer9.swf
Binary files differ
diff --git a/macros/latex/contrib/media9/players/BSD-License b/macros/latex/contrib/media9/players/BSD-License
new file mode 100644
index 0000000000..67b0fe7164
--- /dev/null
+++ b/macros/latex/contrib/media9/players/BSD-License
@@ -0,0 +1,32 @@
+The BSD License
+
+Copyright (c) 2010, Adobe Systems Incorporated
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or
+without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+this list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+this list of conditions and the following disclaimer in the documentation
+and/or other materials provided with the distribution.
+
+* Neither the name of Adobe Systems Incorporated, nor the names of its
+contributors may be used to endorse or promote products derived from this
+software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/macros/latex/contrib/media9/players/SMPfixes.patch b/macros/latex/contrib/media9/players/SMPfixes.patch
new file mode 100644
index 0000000000..04e48f4128
--- /dev/null
+++ b/macros/latex/contrib/media9/players/SMPfixes.patch
@@ -0,0 +1,158 @@
+--- ./player/StrobeMediaPlayback/src/org/osmf/player/chrome/widgets/PlayButtonOverlay.as.orig 2012-11-14 15:48:22.000000000 +0100
++++ ./player/StrobeMediaPlayback/src/org/osmf/player/chrome/widgets/PlayButtonOverlay.as 2012-11-20 15:14:02.000000000 +0100
+@@ -98,6 +98,11 @@
+ override protected function onMouseClick(event:MouseEvent):void
+ {
+ var playable:PlayTrait = media.getTrait(MediaTraitType.PLAY) as PlayTrait;
++ var seekable:SeekTrait = media.getTrait(MediaTraitType.SEEK) as SeekTrait;
++ if(playable.playState == PlayState.STOPPED)
++ {
++ try{seekable.seek(0);}catch(e:Object){}
++ }
+ playable.play();
+ }
+
+@@ -134,4 +139,4 @@
+ /* static */
+ private static const VISIBILITY_DELAY:int = 500;
+ }
+-}
+\ No newline at end of file
++}
+--- ./player/StrobeMediaPlayback/src/org/osmf/player/chrome/widgets/Slider.as.orig 2012-11-14 15:48:22.000000000 +0100
++++ ./player/StrobeMediaPlayback/src/org/osmf/player/chrome/widgets/Slider.as 2012-11-14 15:42:53.000000000 +0100
+@@ -106,7 +106,7 @@
+ if (_enabled && _sliding == false)
+ {
+ _sliding = true;
+- stage.addEventListener(MouseEvent.MOUSE_UP, onStageExitDrag);
++ stage.addEventListener(MouseEvent.MOUSE_UP, onStageExitDrag, true);
+ updateFace(down);
+ scrubTimer.start();
+ dispatchEvent(new ScrubberEvent(ScrubberEvent.SCRUB_START));
+--- ./player/StrobeMediaPlayback/src/org/osmf/player/chrome/widgets/PlayButton.as.orig 2012-11-14 15:48:22.000000000 +0100
++++ ./player/StrobeMediaPlayback/src/org/osmf/player/chrome/widgets/PlayButton.as 2012-11-14 15:42:53.000000000 +0100
+@@ -26,6 +26,7 @@
+ import org.osmf.traits.MediaTraitType;
+ import org.osmf.traits.PlayState;
+ import org.osmf.traits.PlayTrait;
++ import org.osmf.traits.SeekTrait;
+
+ public class PlayButton extends PlayableButton
+ {
+@@ -44,6 +45,11 @@
+ override protected function onMouseClick(event:MouseEvent):void
+ {
+ var playable:PlayTrait = media.getTrait(MediaTraitType.PLAY) as PlayTrait;
++ var seekable:SeekTrait = media.getTrait(MediaTraitType.SEEK) as SeekTrait;
++ if(playable.playState == PlayState.STOPPED)
++ {
++ try{seekable.seek(0);}catch(e:Object){}
++ }
+ playable.play();
+ event.stopImmediatePropagation();
+ }
+@@ -58,4 +64,4 @@
+ }
+ }
+ }
+-}
+\ No newline at end of file
++}
+--- ./player/StrobeMediaPlayback/src/StrobeMediaPlayback.as.orig 2012-11-14 15:48:22.000000000 +0100
++++ ./player/StrobeMediaPlayback/src/StrobeMediaPlayback.as 2012-11-14 15:42:54.000000000 +0100
+@@ -52,6 +52,7 @@
+ import org.osmf.traits.MediaTraitType;
+ import org.osmf.traits.PlayState;
+ import org.osmf.traits.PlayTrait;
++ import org.osmf.traits.SeekTrait;
+ import org.osmf.utils.OSMFSettings;
+ import org.osmf.utils.OSMFStrings;
+
+@@ -152,6 +153,7 @@
+
+ player.addEventListener(TimeEvent.COMPLETE, onComplete);
+ player.addEventListener(MediaErrorEvent.MEDIA_ERROR, onMediaError);
++ player.addEventListener(MediaPlayerCapabilityChangeEvent.CAN_PLAY_CHANGE, onCanPlayChange);
+
+ // Add DRM error handler
+ var drmManager:DRMManager = DRMManager.getDRMManager();
+@@ -338,6 +340,8 @@
+ mainContainer.backgroundAlpha = 0;
+ mainContainer.addEventListener(MouseEvent.DOUBLE_CLICK, onFullScreenRequest);
+ mainContainer.addEventListener(MouseEvent.CLICK, onMainClick, false);
++ mainContainer.addEventListener(MouseEvent.MOUSE_DOWN, onMainDown, false);
++ mainContainer.addEventListener(MouseEvent.MOUSE_UP, onMainUp, false);
+ mainContainer.doubleClickEnabled = true;
+
+ addChild(mainContainer);
+@@ -415,6 +419,9 @@
+ }
+
+ player.addEventListener(PlayEvent.PLAY_STATE_CHANGE, onSetAutoHide);
++
++ controlBarContainer.addEventListener(MouseEvent.MOUSE_DOWN, onControlBarAny, false);
++ controlBarContainer.addEventListener(MouseEvent.MOUSE_UP, onControlBarAny, false);
+
+ layout();
+
+@@ -757,6 +764,38 @@
+ }
+ }
+
++ private function onMainDown(event:MouseEvent):void
++ {
++ var playable:PlayTrait = player.media.getTrait(MediaTraitType.PLAY) as PlayTrait;
++ if (playable.playState == PlayState.PLAYING)
++ {
++ playable.pause();
++ }
++ }
++
++ private function onMainUp(event:MouseEvent):void
++ {
++ var playable:PlayTrait = player.media.getTrait(MediaTraitType.PLAY) as PlayTrait;
++ var seekable:SeekTrait = player.media.getTrait(MediaTraitType.SEEK) as SeekTrait;
++ if(playable.playState == PlayState.STOPPED)
++ {
++ if(player.canSeek){seekable.seek(0);}
++ playable.play();
++ }
++ else if(playable.playState == PlayState.PAUSED)
++ {
++ playable.play();
++ }
++ }
++
++ private function onControlBarAny(event:MouseEvent):void
++ {
++ if(event.eventPhase == EventPhase.BUBBLING_PHASE)
++ {
++ event.stopImmediatePropagation();
++ }
++ }
++
+ /**
+ * Toggles full screen state.
+ */
+@@ -1036,12 +1075,20 @@
+ && configuration.endOfVideoOverlay != ""
+ && player.loop == false
+ && player.playing == false
++ && player.autoRewind == true
+ )
+ {
+ processPoster(configuration.endOfVideoOverlay);
+ }
+ }
+
++ private function onCanPlayChange(event:MediaPlayerCapabilityChangeEvent):void
++ {
++ // Make sure this event gets handled only once:
++ player.removeEventListener(event.type, arguments.callee);
++ player.play(); player.stop();
++ }
++
+ private function onMediaError(event:MediaErrorEvent):void
+ {
+ // Make sure this event gets handled only once:
diff --git a/macros/latex/contrib/media9/players/SlideShow.mxml b/macros/latex/contrib/media9/players/SlideShow.mxml
new file mode 100644
index 0000000000..c55c41fd13
--- /dev/null
+++ b/macros/latex/contrib/media9/players/SlideShow.mxml
@@ -0,0 +1,482 @@
+<?xml version="1.0"?>
+<!-- -->
+<!-- Apache Flex 4 source file of SlideShow.swf, -->
+<!-- a FlashPlayer-10 compatible component for -->
+<!-- JPEG/PNG/GIF slideshows. -->
+<!-- -->
+<!-- version 20150718 -->
+<!-- -->
+<!-- -->
+<!-- The free Apache Flex 4 SDK is required to compile -->
+<!-- this file. Get it from -->
+<!-- -->
+<!-- http://flex.apache.org/download-binaries.html -->
+<!-- -->
+<!-- and run -->
+<!-- -->
+<!-- mxmlc -static-link-runtime-shared-libraries SlideShow.mxml -->
+<!-- -->
+<!-- on the command line. -->
+<!-- -->
+<!-- -->
+<!-- Copyright (C) 2015-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. -->
+<!-- -->
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:s="library://ns.adobe.com/flex/spark"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ preinitialize="initialise(this.parameters);"
+ applicationComplete="initApp();"
+ resize="if(dynResolution){dynResolution=false;forcedByUsr=true;setImgSrc();}"
+ backgroundAlpha="0"
+>
+ <fx:Script>
+ <![CDATA[
+ import mx.managers.CursorManager;
+
+ private var slideshowXML:XML;
+ private var setXMLDone:Boolean;
+ private var isEnabled:Boolean=true;
+
+ private function setXML(s:String):void {
+ var loader:URLLoader = new URLLoader();
+ loader.addEventListener(Event.COMPLETE, onURLLoaderComplete);
+ loader.addEventListener(IOErrorEvent.IO_ERROR, onAnyError);
+ loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onAnyError);
+ isEnabled=false;
+ slideshowXML=null;
+ setXMLDone=false;
+ isIOError=true;
+ CursorManager.setBusyCursor();
+ timeoutTimer.start();
+ loader.load(new URLRequest(s));
+ }
+
+ private function onURLLoaderComplete(event:Event):void
+ {
+ CursorManager.removeBusyCursor();
+ isEnabled=true;
+ var loader:URLLoader = event.target as URLLoader;
+ if (loader != null)
+ {
+ slideshowXML = new XML(loader.data);
+ setXMLDone=true;
+ rotations=new Object();
+ seek(0);
+ if(autoPlay) play();
+ }
+ }
+
+ [Bindable] private var delay:Number=5;
+ [Bindable] private var autoPlay:Boolean=false;
+ private var xmlfile:String=null;
+
+ private function initialise(flashVars:Object):void {
+ xmlfile=flashVars.xml;
+ if(flashVars.delay){delay=flashVars.delay}
+ if(flashVars.autoPlay=='true'){autoPlay=true}
+ }
+
+ private var reloadTimer:Timer = null;
+ private var playTimer:Timer = null;
+ private var timeoutTimer:Timer;
+ private var curFile:String;
+
+ private var idx:Number=0;
+ private var urlIdx:Number=0;
+ [Bindable] private var src1:String;
+ [Bindable] private var src2:String;
+
+ private var rotations:Object;
+
+ private function rotate(n:Number=1):void {
+ if(Img1.visible){
+ n==0 ? Img1.rotation=0 : Img1.rotation+=90*Math.floor(n);
+ Img1.rotation%=360;
+ rotations[slideshowXML.Img[idx].URL[urlIdx].toString()]=
+ Img1.rotation/90;
+ } else {
+ n==0 ? Img2.rotation=0 : Img2.rotation+=90*Math.floor(n);
+ Img2.rotation%=360;
+ rotations[slideshowXML.Img[idx].URL[urlIdx].toString()]=
+ Img2.rotation/90;
+ }
+ }
+
+ import mx.collections.ArrayCollection;
+ import spark.collections.Sort;
+ import spark.collections.SortField;
+
+ private var forcedByUsr:Boolean;
+ private var dynResolution:Boolean;
+
+ private function setImgSrc():void {
+ if(reloadTimer && reloadTimer.hasEventListener(TimerEvent.TIMER)){
+ reloadTimer.removeEventListener(TimerEvent.TIMER, reloadImg);
+ reloadTimer=null;
+ }
+ if(setXMLDone && slideshowXML && (isEnabled||forcedByUsr)){
+ isEnabled=false;
+ forcedByUsr=false;
+ CursorManager.removeBusyCursor();
+ CursorManager.setBusyCursor();
+ timeoutTimer.start();
+ isIOError=true;
+
+ urlIdx=0;
+ if(slideshowXML.Img[idx].URL.length()>1){
+ var sizes:ArrayCollection = new ArrayCollection();
+ for(var i:Number=0; i<slideshowXML.Img[idx].URL.length(); i++){
+ var sizeStr:String=slideshowXML.Img[idx].URL[i].attribute("size");
+ if(sizeStr.match(/^\s*[0-9]+x[0-9]+\s*$/)){
+ var xsize:Number=Number(sizeStr.replace(/x[0-9]+/, ""));
+ var ysize:Number=Number(sizeStr.replace(/[0-9]+x/, ""));
+ sizes.addItem(
+ {size: xsize*ysize, index: i, x: xsize, y: ysize});
+ }
+ }
+ if(sizes.length>0){
+ dynResolution=true;
+ var sort:Sort = new Sort();
+ sort.fields=[new SortField("size",true,true)];
+ sizes.sort=sort;// ^--descending order
+ sizes.refresh();
+
+ urlIdx=sizes.getItemAt(0).index;
+ for(i=0; i<sizes.length; i++){
+ if(
+ sizes.getItemAt(i).x >= this.width ||
+ sizes.getItemAt(i).y >= this.height
+ ) urlIdx=sizes.getItemAt(i).index;
+ }
+ }
+ }
+
+ curFile=slideshowXML.Img[idx].URL[urlIdx].toString();
+
+ var pattern:RegExp;
+ if(slideshowXML.Img[idx].URL[urlIdx].attribute('height').length() > 0){
+ pattern = new RegExp(
+ slideshowXML.Img[idx].URL[urlIdx].attribute('height'), "g");
+ if(curFile.search(pattern)>-1){
+ dynResolution=true;
+ curFile=curFile.replace(pattern, this.height.toString());
+ }
+ }
+
+ if(slideshowXML.Img[idx].URL[urlIdx].attribute('width').length() > 0){
+ pattern = new RegExp(
+ slideshowXML.Img[idx].URL[urlIdx].attribute('width'), "g");
+ if(curFile.search(pattern)>-1){
+ dynResolution=true;
+ curFile=curFile.replace(pattern, this.width.toString());
+ }
+ }
+
+ if(Img1.visible) {
+ src2=null; src2=curFile;
+ } else {
+ src1=null; src1=curFile;
+ }
+ }
+ if(slideshowXML.Img[idx].attribute('live')>0){
+ reloadTimer=new Timer(slideshowXML.Img[idx].attribute('live')*1000,1);
+ reloadTimer.addEventListener(TimerEvent.TIMER, reloadImg);
+ reloadTimer.start();
+ }
+ }
+
+ private var isReload:Boolean;
+ private function reloadImg(e:TimerEvent):void {
+ isReload=true; setImgSrc();
+ }
+
+ private var isPlaying:Boolean=false;
+
+ private function playPause():void {
+ if(isPlaying) pause(); else play();
+ }
+
+ private function play():void {
+ if(!isPlaying && slideshowXML.Img.length()>1) {
+ if(!playTimer){
+ playTimer=new Timer(delay*1000, 0);
+ playTimer.addEventListener(TimerEvent.TIMER, nextSlide);
+ }
+ isPlaying=true;
+ playTimer.start();
+ }
+ }
+
+ private function pause():void {
+ if(isPlaying) {
+ isPlaying=false;
+ playTimer.stop();
+ }
+ }
+
+ private function nextSlide(e:Event=null):void {
+ if(!isEnabled && !forcedByUsr) return;
+ if(isPlaying) playTimer.stop();
+ var evnt:MouseEvent = e as MouseEvent;
+ if(evnt && evnt.type=="mouseUp" && evnt.shiftKey) {
+ prevSlide();
+ } else {
+ idx++;
+ if(idx==slideshowXML.Img.length()) idx=0;
+ isReload=false;
+ setImgSrc();
+ }
+ }
+
+ private function prevSlide(e:MouseEvent=null):void {
+ if(!isEnabled && !forcedByUsr) return;
+ if(isPlaying) playTimer.stop();
+ idx--;
+ if(idx<0) idx=slideshowXML.Img.length()-1;
+ isReload=false;
+ setImgSrc();
+ }
+
+ private function seek(i:Number):void {
+ if(!isEnabled && !forcedByUsr) return;
+ if(isPlaying) playTimer.stop();
+ if(i<0 || i>=slideshowXML.Img.length())
+ idx=slideshowXML.Img.length()-1;
+ else
+ idx=Math.floor(i);
+ isReload=false;
+ setImgSrc();
+ }
+
+ private function onKeyDown(e:KeyboardEvent):void {
+ forcedByUsr=true;
+ switch(e.keyCode) {
+ case 32: //space bar
+ playPause();
+ break;
+ case 36: //home
+ if(isPlaying) pause();
+ seek(0);
+ break;
+ case 35: //end
+ if(isPlaying) pause();
+ seek(-1);
+ break;
+ case 37: //<--
+ prevSlide();
+ break;
+ case 39: //-->
+ nextSlide();
+ break;
+ case 82: //`r'
+ e.shiftKey ? rotate(-1) : rotate();
+ break;
+ }
+ }
+
+ private function slideNum():Number {return idx;}
+
+ private function numSlides():Number {return slideshowXML.Img.length();}
+
+ private function playing():Boolean {return isPlaying;}
+
+ private function initApp():void {
+ this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
+ ExternalInterface.addCallback("setXML", setXML);
+ ExternalInterface.addCallback("play",
+ function():void{forcedByUsr=true;play();});
+ ExternalInterface.addCallback("pause",
+ function():void{forcedByUsr=true;pause();});
+ ExternalInterface.addCallback("playPause",
+ function():void{forcedByUsr=true;playPause();});
+ ExternalInterface.addCallback("seek",
+ function(i:Number):void{forcedByUsr=true;seek(i);});
+ ExternalInterface.addCallback("slideNum", slideNum);
+ ExternalInterface.addCallback("numSlides", numSlides);
+ ExternalInterface.addCallback("playing", playing);
+ ExternalInterface.addCallback("rotate", rotate);
+
+ var itemNextSlide:ContextMenuItem =
+ new ContextMenuItem("Next Slide, [\u2192]");
+ this.contextMenu.customItems.push(itemNextSlide);
+ itemNextSlide.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e:ContextMenuEvent):void{forcedByUsr=true;nextSlide();});
+
+ var itemPrevSlide:ContextMenuItem =
+ new ContextMenuItem("Previous Slide, [\u2190]");
+ this.contextMenu.customItems.push(itemPrevSlide);
+ itemPrevSlide.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e:ContextMenuEvent):void{forcedByUsr=true;prevSlide();});
+
+ var itemPlayPause:ContextMenuItem = new ContextMenuItem("N.N.");
+ this.contextMenu.customItems.push(itemPlayPause);
+ itemPlayPause.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e:ContextMenuEvent):void{forcedByUsr=true;playPause();});
+
+ var itemFirstSlide:ContextMenuItem =
+ new ContextMenuItem("First Slide, [Home]");
+ this.contextMenu.customItems.push(itemFirstSlide);
+ itemFirstSlide.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e:ContextMenuEvent):void{
+ forcedByUsr=true;if(isPlaying) pause();seek(0);});
+
+ var itemLastSlide:ContextMenuItem =
+ new ContextMenuItem("Last Slide, [End]");
+ this.contextMenu.customItems.push(itemLastSlide);
+ itemLastSlide.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e:ContextMenuEvent):void{
+ forcedByUsr=true;if(isPlaying) pause();seek(-1);});
+
+ var itemRotRight:ContextMenuItem =
+ new ContextMenuItem("Rotate Right, [r]");
+ this.contextMenu.customItems.push(itemRotRight);
+ itemRotRight.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e:ContextMenuEvent):void{forcedByUsr=true;rotate();});
+
+ var itemRotLeft:ContextMenuItem =
+ new ContextMenuItem("Rotate Left, [\u21e7]+[r]");
+ this.contextMenu.customItems.push(itemRotLeft);
+ itemRotLeft.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,
+ function(e:ContextMenuEvent):void{forcedByUsr=true;rotate(-1);});
+
+ this.contextMenu.addEventListener(ContextMenuEvent.MENU_SELECT,
+ function(e:ContextMenuEvent):void{
+ itemPlayPause.caption=(isPlaying ? "Pause" : "Play")+", [Space]";
+ itemPlayPause.visible=itemNextSlide.visible=itemPrevSlide.visible=
+ itemFirstSlide.visible=itemLastSlide.visible=false;
+ if(slideshowXML.Img.length()>1){
+ itemPlayPause.visible=itemNextSlide.visible=itemPrevSlide.visible=
+ itemFirstSlide.visible=itemLastSlide.visible=true;
+ }
+ });
+
+ timeoutTimer=new Timer(30000, 1);
+ timeoutTimer.addEventListener(TimerEvent.TIMER, onAnyError);
+ curFile=xmlfile; if(xmlfile) setXML(xmlfile);
+ CursorManager.hideCursor();
+ }
+
+ private var isIOError:Boolean;
+ private function onAnyError(e:Event):void {
+ if(e.type!=IOErrorEvent.IO_ERROR || setXMLDone==false){
+ isIOError=false;
+ setXMLDone=true;
+ if(Img1.visible){
+ src2=null; src2="/dev/null"
+ }else{
+ src1=null; src1="/dev/null"
+ }
+ caption.text=e.type+': '+curFile;
+ if(e.type==TimerEvent.TIMER)
+ caption.text="timeout after 30 s: "+curFile;
+ CursorManager.removeBusyCursor();
+ }else{
+ if(isIOError) caption.text=e.type+': '+curFile;
+ onImgDone(e);
+ }
+ caption.visible=true;
+ if(reloadTimer && reloadTimer.hasEventListener(TimerEvent.TIMER)){
+ reloadTimer.removeEventListener(TimerEvent.TIMER, reloadImg);
+ reloadTimer=null; isReload=false;
+ }
+ }
+
+ private function onImgDone(e:Event):void {
+ timeoutTimer.reset();
+ if(e.target==Img1){
+ Img1.visible=true;Img2.visible=false;
+ } else {
+ Img2.visible=true;Img1.visible=false;
+ }
+ if(slideshowXML.Img.length()>1){
+ slideNo.text=String(idx+1)+"/"+slideshowXML.Img.length().toString();
+ slideNo.visible=slideNo.includeInLayout=true;
+ } else {
+ slideNo.visible=slideNo.includeInLayout=false;
+ }
+ var curRot:Number=0;
+ if (rotations.hasOwnProperty(slideshowXML.Img[idx].URL[urlIdx].toString()))
+ curRot=rotations[slideshowXML.Img[idx].URL[urlIdx].toString()];
+ else
+ curRot=Number(slideshowXML.Img[idx].attribute('rot90'));
+ rotate(0);
+ if(e.type==FlexEvent.READY) {
+ rotate(curRot);
+ if(slideshowXML.Img[idx].caption.toString()!=""){
+ caption.text=slideshowXML.Img[idx].caption.toString();
+ caption.visible=true;
+ } else {
+ caption.text="";
+ caption.visible=false;
+ }
+ if(!isReload) anim.play();
+ if(slideshowXML.Img[idx].attribute('live')>0)
+ cache.removeCacheEntry(curFile);
+ }
+ CursorManager.removeBusyCursor();
+ isEnabled=true;
+ if(isPlaying && !playTimer.running) playTimer.start();
+ }
+ ]]>
+ </fx:Script>
+
+ <fx:Declarations>
+ <s:Animate id="anim" target="{grpCaption}">
+ <s:motionPaths>
+ <s:SimpleMotionPath property="bottom"
+ valueFrom="{-grpCaption.height}" valueTo="0"/>
+ </s:motionPaths>
+ </s:Animate>
+ <s:ContentCache id="cache"/>
+ </fx:Declarations>
+
+ <s:Image id="Img1" source="{src1}" visible="false"
+ width="100%" height="100%"
+ horizontalCenter="0" verticalCenter="0"
+ contentLoader="{cache}"
+ ready="onImgDone(event)"
+ ioError="onAnyError(event)"
+ securityError="onAnyError(event)"
+ smooth="true"
+ />
+
+ <s:Image id="Img2" source="{src2}" visible="true"
+ width="100%" height="100%"
+ horizontalCenter="0" verticalCenter="0"
+ contentLoader="{cache}"
+ ready="onImgDone(event)"
+ ioError="onAnyError(event)"
+ securityError="onAnyError(event)"
+ smooth="true"
+ />
+
+ <s:Group id="grpCaption" width="100%" bottom="{-grpCaption.height}">
+ <s:Label id="caption" left="0" bottom="0" visible="false"
+ paddingLeft="2" paddingBottom="2" paddingRight="2" paddingTop="4"
+ backgroundColor="0xdddddd" backgroundAlpha="0.7"
+ maxWidth="{grpCaption.width-slideNo.width}"
+ maxDisplayedLines="{-1}" lineBreak="toFit"
+ />
+ <s:Label id="slideNo" right="0" bottom="0" visible="false"
+ paddingLeft="2" paddingBottom="2" paddingRight="2" paddingTop="4"
+ backgroundColor="0xdddddd" backgroundAlpha="0.7"
+ />
+ </s:Group>
+
+ <s:Button alpha="0" width="100%" height="100%"
+ mouseUp="forcedByUsr=true;nextSlide(event);"
+ mouseOver="anim.play();CursorManager.showCursor();"
+ mouseOut="if(anim.isPlaying) anim.reverse(); else anim.play(null,true);
+ CursorManager.hideCursor();"
+ />
+</s:Application>
diff --git a/macros/latex/contrib/media9/players/SlideShow.swf b/macros/latex/contrib/media9/players/SlideShow.swf
new file mode 100644
index 0000000000..acd00c7a03
--- /dev/null
+++ b/macros/latex/contrib/media9/players/SlideShow.swf
Binary files differ
diff --git a/macros/latex/contrib/media9/players/StrobeMediaPlayback-license b/macros/latex/contrib/media9/players/StrobeMediaPlayback-license
new file mode 100644
index 0000000000..4a3d2ec8c0
--- /dev/null
+++ b/macros/latex/contrib/media9/players/StrobeMediaPlayback-license
@@ -0,0 +1,5 @@
+Strobe Media Playback is covered under the BSD Licence. See file BSD-License
+
+OSMF and NetMocker are covered under version 1.1 of the MPL Licence. You may obtain a copy of the License at http://www.mozilla.org/MPL/
+
+The font we used by the player, Playback Sans, is released under the SIL Open Font License - see file player/StrobeMediaPlayback/assets/font/PlaybackSansEULA.txt
diff --git a/macros/latex/contrib/media9/players/StrobeMediaPlayback.swf b/macros/latex/contrib/media9/players/StrobeMediaPlayback.swf
new file mode 100644
index 0000000000..58e4170588
--- /dev/null
+++ b/macros/latex/contrib/media9/players/StrobeMediaPlayback.swf
Binary files differ
diff --git a/macros/latex/contrib/media9/players/VPlayer.mxml b/macros/latex/contrib/media9/players/VPlayer.mxml
new file mode 100644
index 0000000000..347a1058eb
--- /dev/null
+++ b/macros/latex/contrib/media9/players/VPlayer.mxml
@@ -0,0 +1,338 @@
+<?xml version="1.0"?>
+<!-- -->
+<!-- Apache Flex 4 source file of VPlayer.swf, -->
+<!-- a FlashPlayer-10 compatible component for playing -->
+<!-- FLV and MP4/H.264 video files and streams. -->
+<!-- -->
+<!-- version 20180118 -->
+<!-- -->
+<!-- -->
+<!-- The free Apache Flex 4 SDK is required to compile -->
+<!-- this file. Get it from -->
+<!-- -->
+<!-- http://flex.apache.org/download-binaries.html -->
+<!-- -->
+<!-- and run -->
+<!-- -->
+<!-- mxmlc -static-link-runtime-shared-libraries VPlayer.mxml -->
+<!-- -->
+<!-- on the command line. -->
+<!-- -->
+<!-- -->
+<!-- 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. -->
+<!-- -->
+
+<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
+ xmlns:s="library://ns.adobe.com/flex/spark"
+ xmlns:mx="library://ns.adobe.com/flex/mx"
+ preinitialize="initialise(this.parameters);"
+ applicationComplete="initApp();"
+ backgroundAlpha="0"
+>
+ <fx:Script>
+ <![CDATA[
+ [Bindable] private var scaleMode:String='letterbox';
+ [Bindable] private var source:String;
+ [Bindable] private var autoPlay:Boolean=false;
+ [Bindable] private var autoRewind:Boolean=false;
+ [Bindable] private var loop:Boolean=false;
+ [Bindable] private var vol:Number=0.75;
+ private var vidComplete:Boolean=false;
+ private var deltaSeek:Number;
+ private var curTime:Number;
+ private var newPos:Number;
+ private var keyPressed:Boolean=false;
+ private var pauseAtPos:Number = -1;
+ private var toBePaused:Boolean = false;
+
+ private function initialise(flashVars:Object):void {
+ source=flashVars.source;
+ if(flashVars.autoPlay=='true'){autoPlay=true}
+ if(flashVars.autoRewind=='true'){autoRewind=true}
+ if(flashVars.loop=='true'){loop=true}
+ if(flashVars.volume){vol=Number(flashVars.volume)}
+ if(flashVars.scaleMode){scaleMode=flashVars.scaleMode}
+ }
+
+ private function onProgress(event:ProgressEvent):void {
+ if (event.bytesTotal) event.target.visible=true;
+ else event.target.visible=false;
+ }
+
+ import org.osmf.events.MediaPlayerStateChangeEvent;
+ import org.osmf.media.MediaPlayerState;
+ import mx.controls.Alert;
+ private function onStateChange(event:MediaPlayerStateChangeEvent):void {
+ vidComplete=false;
+ switch(event.state) {
+ case MediaPlayerState.PLAYBACK_ERROR: // ('playbackError')
+ Alert.show('Unable to play \''+event.target.source+'\'','Error');
+ break;
+ //case MediaPlayerState.READY:
+ // if(autoPlay) vidDisp.play();
+ // break;
+ //MediaPlayerState.BUFFERING
+ //MediaPlayerState.LOADING
+ //MediaPlayerState.PAUSED
+ //MediaPlayerState.PLAYING
+ //MediaPlayerState.UNINITIALIZED
+ }
+ }
+
+ private function onKeyDown(e:KeyboardEvent):void {
+ switch(e.keyCode) {
+ case 32: //space bar
+ playPause();
+ break;
+ case 36: //home
+ vidDisp.pause();
+ vidDisp.seek(0);
+ break;
+ case 35: //end
+ if(vidDisp.bytesTotal){
+ vidDisp.pause();
+ vidDisp.seek(vidDisp.duration-0.1);
+ }
+ break;
+ case 37: //<--
+ fadeEffect.end();
+ playProgress.alpha=0.5;
+ playProgress.visible=true;
+ if(!keyPressed){
+ deltaSeek=Math.max(1,vidDisp.duration/1000);
+ curTime=vidDisp.currentTime;
+ }
+ keyPressed=true;
+ newPos=Math.max(0,curTime-deltaSeek);
+ playProgress.setProgress(newPos,vidDisp.duration);
+ playProgress.label=formatTime(newPos);
+ vidDisp.seek(newPos);
+ deltaSeek*=1.1;
+ break;
+ case 39: //-->
+ fadeEffect.end();
+ playProgress.alpha=0.5;
+ playProgress.visible=true;
+ if(!keyPressed){
+ deltaSeek=Math.max(1,vidDisp.duration/1000);
+ curTime=vidDisp.currentTime;
+ }
+ keyPressed=true;
+ newPos=Math.min(vidDisp.duration-0.1,curTime+deltaSeek);
+ playProgress.setProgress(newPos,vidDisp.duration);
+ playProgress.label=formatTime(newPos);
+ vidDisp.seek(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.duration/1000);
+ keyPressed=false;
+ fadeEffect.play();
+ break;
+ }
+ }
+
+ private function onCurrentTimeChange(e:Event):void {
+ if(vidDisp.playing&&pauseAtPos>=0&&vidDisp.currentTime<pauseAtPos)
+ toBePaused=true;
+ if(
+ vidDisp.playing&&pauseAtPos>=0&&
+ vidDisp.currentTime>=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.seek(p);
+ }
+
+ private function rewind():void {
+ vidDisp.seek(0);
+ }
+
+ private function volume(v:Number):void {
+ vidDisp.muted=false;
+ vidDisp.volume = v;
+ }
+
+ private function mute():void {
+ if(vidDisp.muted) {
+ vidDisp.muted=false;
+ if (vidDisp.volume==0) volume(0.75);
+ }
+ else {
+ vidDisp.muted=true;
+ }
+ }
+
+ private function setSource(s:Object):void {
+ vidDisp.source = s;
+ }
+
+ 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.currentTime;
+ }
+
+ private function playing():Boolean {
+ return vidDisp.playing;
+ }
+
+ private function duration():Number {
+ return vidDisp.duration;
+ }
+
+ private function muted():Boolean {
+ return vidDisp.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", muted);
+
+ 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();vidDisp.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{vidDisp.pause();
+ vidDisp.seek(vidDisp.duration-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=(vidDisp.muted ? "Unmute" : "Mute")+", [m]";}
+ );
+ }
+ ]]>
+ </fx:Script>
+
+ <fx:Declarations>
+ <s:Fade id="fadeEffect" target="{playProgress}" alphaFrom="0.5" alphaTo="0"
+ duration="2000"/>
+ </fx:Declarations>
+
+ <!-- autoPlay setting (autoPlay="{autoPlay}") is not reliable;
+ we handle this in MediaPlayerStateChange event -->
+ <s:VideoDisplay
+ id="vidDisp"
+ width="100%" height="100%" scaleMode="{scaleMode}"
+ source="{source}" volume="{vol}"
+ autoPlay="{autoPlay}"
+ autoRewind="{autoRewind}" loop="{loop}"
+ mediaPlayerStateChange="onStateChange(event);"
+ complete="vidComplete=true;"
+ durationChange="vidDisp.seek(0);"
+ currentTimeChange="onCurrentTimeChange(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"
+ />
+
+ <s:Button alpha="0" width="100%" height="100%"
+ mouseDown="vidDisp.pause();"
+ mouseUp="if(vidComplete) vidDisp.seek(0);vidDisp.play();"
+ />
+</s:Application>
diff --git a/macros/latex/contrib/media9/players/VPlayer.swf b/macros/latex/contrib/media9/players/VPlayer.swf
new file mode 100644
index 0000000000..835c290837
--- /dev/null
+++ b/macros/latex/contrib/media9/players/VPlayer.swf
Binary files differ
diff --git a/macros/latex/contrib/media9/players/VPlayer9.mxml b/macros/latex/contrib/media9/players/VPlayer9.mxml
new file mode 100644
index 0000000000..6741267f10
--- /dev/null
+++ b/macros/latex/contrib/media9/players/VPlayer9.mxml
@@ -0,0 +1,318 @@
+<?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>
diff --git a/macros/latex/contrib/media9/players/VPlayer9.swf b/macros/latex/contrib/media9/players/VPlayer9.swf
new file mode 100644
index 0000000000..c99e5a23f4
--- /dev/null
+++ b/macros/latex/contrib/media9/players/VPlayer9.swf
Binary files differ