diff options
author | Karl Berry <karl@freefriends.org> | 2012-10-04 19:44:46 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2012-10-04 19:44:46 +0000 |
commit | 7df5247349db54617d138cb6466ba676492199fb (patch) | |
tree | 7ce7ab4da611480ebf299859eea5fdb6fc585d53 /Master/texmf-dist/doc/latex/media9 | |
parent | 44ee0abf2e2a1ed4ed69374b15a65d8c0bdadd3e (diff) |
media9 (4oct12)
git-svn-id: svn://tug.org/texlive/trunk@27879 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/doc/latex/media9')
-rw-r--r-- | Master/texmf-dist/doc/latex/media9/ChangeLog | 8 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/media9/files/cube.mp4 | bin | 295207 -> 262653 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/media9/files/players/APlayer.mxml | 376 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/media9/files/players/VPlayer.mxml | 291 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/media9/media9.pdf | bin | 1583908 -> 1601066 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/media9/media9.tex | 97 |
6 files changed, 542 insertions, 230 deletions
diff --git a/Master/texmf-dist/doc/latex/media9/ChangeLog b/Master/texmf-dist/doc/latex/media9/ChangeLog index a19252bd27d..65c5dce6542 100644 --- a/Master/texmf-dist/doc/latex/media9/ChangeLog +++ b/Master/texmf-dist/doc/latex/media9/ChangeLog @@ -1,3 +1,11 @@ +2012-10-04 + * v0.15 + * fix: error in case of multiple use of `3Dviews' option + +2012-10-02 + * v0.14 + * new: keyboard control added to VPlayer.swf and APlayer.swf + 2012-09-12 * v0.13 * fix: cross section related bug in 3Dmenu.js diff --git a/Master/texmf-dist/doc/latex/media9/files/cube.mp4 b/Master/texmf-dist/doc/latex/media9/files/cube.mp4 Binary files differindex af2cb8c0331..cbd115b2117 100644 --- a/Master/texmf-dist/doc/latex/media9/files/cube.mp4 +++ b/Master/texmf-dist/doc/latex/media9/files/cube.mp4 diff --git a/Master/texmf-dist/doc/latex/media9/files/players/APlayer.mxml b/Master/texmf-dist/doc/latex/media9/files/players/APlayer.mxml index cffab803f7e..86c62753d3b 100644 --- a/Master/texmf-dist/doc/latex/media9/files/players/APlayer.mxml +++ b/Master/texmf-dist/doc/latex/media9/files/players/APlayer.mxml @@ -4,7 +4,7 @@ <!-- a FlashPlayer-10 compatible component for playing --> <!-- MP3 audio files and streams. --> <!-- --> -<!-- version 20120425 --> +<!-- version 20121002 --> <!-- --> <!-- --> <!-- The free Adobe Flex 4 SDK is required to compile --> @@ -40,154 +40,274 @@ xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" preinitialize="initialise(FlexGlobals.topLevelApplication.parameters);" - applicationComplete="initSound();addEventListener(Event.ENTER_FRAME, onEnterFrame);" + applicationComplete="initSound();addeventlisteners();" creationComplete="initCallBacks();" - mouseDown="pause();" + mouseDown="pause();setFocus();" mouseUp="play();" > - <fx: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 balance:Number=0; - - private var snd:Sound; - private var sndCh:SoundChannel; - private var sndTr:SoundTransform; - private var playResumePosition:Number = 0; - private var playing:Boolean = false; - private var muted:Boolean = false; - private var lastVol:Number; - - import mx.core.FlexGlobals; - private function initialise(flashVars:Object):void { - source=flashVars.source; - if(flashVars.autoPlay){autoPlay=(flashVars.autoPlay=='true')} - if(flashVars.loop){loop=(flashVars.loop=='true')} - if(flashVars.volume){vol=Number(flashVars.volume)} - if(flashVars.balance){balance=Number(flashVars.balance)} - } + <fx: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 pan:Number=0; - import mx.controls.Alert; - private function initSound():void { - snd = new Sound(new URLRequest(source)); - sndTr = new SoundTransform(vol, balance); + private var snd:Sound; + private var sndCh:SoundChannel; + private var sndTr:SoundTransform; + private var playResumePosition:Number = 0; + private var playing:Boolean = false; + private var muted:Boolean = false; + private var lastVol:Number; - snd.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); - snd.addEventListener(ProgressEvent.PROGRESS, progressHandler); - snd.addEventListener(Event.COMPLETE, completeHandler); + private var deltaSeek:Number; + private var currentTime:Number; + private var keyPressed:Boolean=false; - if(autoPlay) play(); - } + import mx.core.FlexGlobals; + private function initialise(flashVars:Object):void { + source=flashVars.source; + if(flashVars.autoPlay){autoPlay=(flashVars.autoPlay=='true')} + if(flashVars.loop){loop=(flashVars.loop=='true')} + if(flashVars.volume){vol=Number(flashVars.volume)} + if(flashVars.balance){pan=Number(flashVars.balance)} + } - private function setSource(src:String):void { - pause(); - snd = new Sound(new URLRequest(src)); - if(autoPlay) play(); - } + import mx.controls.Alert; + private function initSound():void { + snd = new Sound(new URLRequest(source)); + sndTr = new SoundTransform(vol, pan); - private function play():void { - if (!playing) { - try{sndCh = snd.play(playResumePosition, 0, sndTr);} - catch(err:Error){Alert.show(err.message,'Error');} - sndCh.addEventListener(Event.SOUND_COMPLETE, sndCompleteHandler); - playing = true; - } - } + snd.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); + snd.addEventListener(ProgressEvent.PROGRESS, progressHandler); + snd.addEventListener(Event.COMPLETE, completeHandler); - private function pause():void { - if (playing) { - playResumePosition = sndCh.position; - sndCh.stop(); - playing = false; - } - } + if(autoPlay) play(); + } - private function playPause():void { - if (playing) pause(); else play(); + import flash.events.KeyboardEvent; + private function keyDnHnd(e:KeyboardEvent):void { + switch(e.keyCode) { + case 32: //space bar + playPause(); + break; + case 36: //home + pause(); + playResumePosition=(0); + break; + case 35: //end + if(playProgress.indeterminate) break; + pause(); + playResumePosition=(snd.length); + break; + case 37: //<-- + if(e.ctrlKey){ + pan=Math.max(-1,pan-0.025); + balance(pan); + break; } - - private function seek(p:Number):void { - playResumePosition = p*1000; - if (playing) { - sndCh.stop(); - playing = false; - play(); - } + if(!keyPressed){ + deltaSeek=Math.max(100,snd.length/10000); + if(playing) + currentTime=sndCh.position; + else + currentTime=playResumePosition; } - - private function rewind():void { - seek(0); + keyPressed=true; + playResumePosition=Math.max(0,currentTime-deltaSeek); + if(playing) seek(playResumePosition/1000); + deltaSeek*=1.1; + break; + case 39: //--> + if(e.ctrlKey){ + pan=Math.min(1,pan+0.025); + balance(pan); + break; } - - private function volume(v:Number):void { - sndTr.volume = v; - if (playing) { - pause(); - play(); - } + if(!keyPressed){ + deltaSeek=Math.max(100,snd.length/10000); + if(playing) + currentTime=sndCh.position; + else + currentTime=playResumePosition; } - - private function mute():void { - if(muted) { - if (lastVol==0) lastVol=0.75; - volume(lastVol); - muted=false; - } - else { - lastVol = sndTr.volume - volume(0); - muted=true; - } + keyPressed=true; + playResumePosition=Math.min(snd.length-10,currentTime+deltaSeek); + seek(playResumePosition/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 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("mute", mute); - ExternalInterface.addCallback("setSource", setSource); - } + private function keyUpHnd(e:KeyboardEvent):void { + switch(e.keyCode) { + case 37: //<-- + case 39: //--> + deltaSeek=Math.max(100,snd.length/10000); + keyPressed=false; + break; + } + } - private function sndCompleteHandler(event:Event):void { - playing = false; - playResumePosition = 0; - if(loop) play(); - } + private function formatTime(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); - private function completeHandler(event:Event):void { - playProgress.indeterminate=false; - } + var fmtd:String=''; - import flash.events.ProgressEvent; - private function progressHandler(event:ProgressEvent):void { - playProgress.indeterminate=true; - if(playing) { - playProgress.setProgress(0.5,1); - } - } + if(hrs>0) fmtd = String(hrs)+':'; - private function onEnterFrame(event:Event):void { - if(playProgress.indeterminate==false && playing) { - playProgress.setProgress(sndCh.position,snd.length); - } - } + if(hrs>0 && min <10) fmtd+='0'; + fmtd += String(min)+':'; - import flash.events.IOErrorEvent; - private function errorHandler(errorEvent:IOErrorEvent):void { - Alert.show(errorEvent.text + '\ncould not be loaded','Error'); - } - ]]> - </fx:Script> + if(sec<10) fmtd+='0'; + fmtd += String(sec); + + return fmtd; + } + + private function addeventlisteners():void { + this.setFocus(); + this.addEventListener(Event.ENTER_FRAME, onEnterFrame); + this.addEventListener(KeyboardEvent.KEY_DOWN, keyDnHnd); + this.addEventListener(KeyboardEvent.KEY_UP, keyUpHnd); + } + + private function setSource(src:String):void { + pause(); + snd = new Sound(new URLRequest(src)); + if(autoPlay) play(); + } + + private function play():void { + if(playing) return; + try{sndCh = snd.play(playResumePosition, 0, sndTr);} + catch(err:Error){Alert.show(err.message,'Error');} + sndCh.addEventListener(Event.SOUND_COMPLETE, sndCompleteHandler); + playing = true; + } + + private function pause():void { + if(!playing) return; + playResumePosition = sndCh.position; + sndCh.stop(); + playing = false; + } + + private function playPause():void { + if(playing) pause(); else play(); + } + + private function seek(p:Number):void { + playResumePosition = p*1000; + if(!playing) return; + sndCh.stop(); + playing = 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 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); + } + + private function sndCompleteHandler(event:Event):void { + playing = false; + playResumePosition = 0; + if(loop) play(); + } + + private function completeHandler(event:Event):void { + playProgress.indeterminate=false; + } + + import flash.events.ProgressEvent; + private function progressHandler(event:ProgressEvent):void { + playProgress.indeterminate=true; + } + + private function onEnterFrame(event:Event):void { + if(!playProgress.indeterminate) { + if(playing) { + playProgress.setProgress(sndCh.position,snd.length); + playProgress.label=formatTime(sndCh.position); + } else { + playProgress.setProgress(playResumePosition,snd.length); + playProgress.label=formatTime(playResumePosition); + } + }else{ + if(playing) { + playProgress.setProgress(Math.random(),1); + playProgress.label=formatTime(sndCh.position); + } else { + playProgress.setProgress(snd.bytesLoaded,snd.bytesTotal); + playProgress.label=formatTime(playResumePosition); + } + } + } + + import flash.events.IOErrorEvent; + private function errorHandler(errorEvent:IOErrorEvent):void { + Alert.show(errorEvent.text + '\ncould not be loaded','Error'); + } + ]]> + </fx:Script> - <mx:ProgressBar width="100%" mode="manual" - horizontalCenter="0" verticalCenter="0" labelPlacement="center" - label="" id="playProgress" - /> + <mx:ProgressBar width="100%" mode="manual" + horizontalCenter="0" verticalCenter="0" labelPlacement="center" + label="" id="playProgress" + /> </s:Application> diff --git a/Master/texmf-dist/doc/latex/media9/files/players/VPlayer.mxml b/Master/texmf-dist/doc/latex/media9/files/players/VPlayer.mxml index 1c71c751c08..be441e61dce 100644 --- a/Master/texmf-dist/doc/latex/media9/files/players/VPlayer.mxml +++ b/Master/texmf-dist/doc/latex/media9/files/players/VPlayer.mxml @@ -4,7 +4,7 @@ <!-- a FlashPlayer-10 compatible component for playing --> <!-- FLV and MP4/H.264 video files and streams. --> <!-- --> -<!-- version 20120425 --> +<!-- version 20121002 --> <!-- --> <!-- --> <!-- The free Adobe Flex 4 SDK is required to compile --> @@ -37,110 +37,215 @@ <!-- --> <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(FlexGlobals.topLevelApplication.parameters);" - creationComplete="initCallBacks();" + xmlns:s="library://ns.adobe.com/flex/spark" + xmlns:mx="library://ns.adobe.com/flex/mx" + preinitialize="initialise(FlexGlobals.topLevelApplication.parameters);" + creationComplete="init();" > - <fx:Script> - <![CDATA[ - [Bindable] private var scaleMode:String='stretch'; - [Bindable] private var source:String; - [Bindable] private var autoPlay:Boolean=false; - [Bindable] private var loop:Boolean=false; - [Bindable] private var vol:Number=0.75; - private var vidComplete:Boolean=false; - - import mx.core.FlexGlobals; - private function initialise(flashVars:Object):void { - source=flashVars.source; - if(flashVars.autoPlay){autoPlay=(flashVars.autoPlay=='true')} - if(flashVars.loop){loop=(flashVars.loop=='true')} - if(flashVars.volume){vol=Number(flashVars.volume)} - if(flashVars.scaleMode){scaleMode=flashVars.scaleMode} - } + <fx:Script> + <![CDATA[ + [Bindable] private var scaleMode:String='stretch'; + [Bindable] private var source:String; + [Bindable] private var autoPlay: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 currentTime:Number; + private var newPos:Number; + private var keyPressed:Boolean=false; - import flash.events.ProgressEvent; - private function progressHandler(event:ProgressEvent):void { - if (event.bytesTotal) event.target.visible=true; - else event.target.visible=false; - } + import mx.core.FlexGlobals; + private function initialise(flashVars:Object):void { + source=flashVars.source; + if(flashVars.autoPlay){autoPlay=(flashVars.autoPlay=='true')} + if(flashVars.loop){loop=(flashVars.loop=='true')} + if(flashVars.volume){vol=Number(flashVars.volume)} + if(flashVars.scaleMode){scaleMode=flashVars.scaleMode} + } - import org.osmf.events.MediaPlayerStateChangeEvent; - import mx.controls.Alert; - private function stateChangeHandler(event:MediaPlayerStateChangeEvent):void { - vidComplete=false; - if(event.state=='playbackError') - Alert.show('Unable to play \''+event.target.source+'\'','Error'); - } + import flash.events.ProgressEvent; + private function progressHandler(event:ProgressEvent):void { + if (event.bytesTotal) event.target.visible=true; + else event.target.visible=false; + } - private function play():void { - if(vidComplete){vidDisp.seek(0);}vidDisp.play(); - } + import org.osmf.events.MediaPlayerStateChangeEvent; + import mx.controls.Alert; + private function stateChangeHandler(event:MediaPlayerStateChangeEvent):void { + vidComplete=false; + if(event.state=='playbackError') + Alert.show('Unable to play \''+event.target.source+'\'','Error'); + } - private function pause():void { + import flash.events.KeyboardEvent; + private function keyDnHnd(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); } - - private function playPause():void { - if(vidDisp.playing) vidDisp.pause(); else vidDisp.play(); + break; + case 37: //<-- + fadeEffect.end(); + playProgress.alpha=0.5; + playProgress.visible=true; + if(!keyPressed){ + deltaSeek=Math.max(1,vidDisp.duration/1000); + currentTime=vidDisp.currentTime; } - - private function seek(p:Number):void { - vidDisp.seek(p); + keyPressed=true; + newPos=Math.max(0,currentTime-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); + currentTime=vidDisp.currentTime; } + keyPressed=true; + newPos=Math.min(vidDisp.duration-0.1,currentTime+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 rewind():void { - vidDisp.seek(0); - } + private function keyUpHnd(e:KeyboardEvent):void { + switch(e.keyCode) { + case 37: //<-- + case 39: //--> + deltaSeek=Math.max(1,vidDisp.duration/1000); + keyPressed=false; + fadeEffect.play(); + break; + } + } - private function volume(v:Number):void { - vidDisp.volume = v; - } + private function play():void { + if(vidComplete){vidDisp.seek(0);}vidDisp.play(); + } - private function mute():void { - if(vidDisp.muted) { - vidDisp.muted=false; - if (vidDisp.volume==0) volume(0.75); - } - else { - vidDisp.muted=true; - } - } + private function pause():void { + vidDisp.pause(); + } - private function setSource(s:Object):void { - vidDisp.source = s; - } + private function playPause():void { + if(vidDisp.playing) vidDisp.pause(); else vidDisp.play(); + } - 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("mute", mute); - ExternalInterface.addCallback("setSource", setSource); - } - ]]> - </fx:Script> - - <s:VideoDisplay - id="vidDisp" - width="100%" height="100%" scaleMode="{scaleMode}" - source="{source}" volume="{vol}" - autoPlay="{autoPlay}" autoRewind="false" loop="{loop}" - mouseDown="vidDisp.pause();" - mouseUp="if(vidComplete){vidDisp.seek(0);}vidDisp.play();" - mediaPlayerStateChange="stateChangeHandler(event);" - complete="vidComplete=true;" - durationChange="if(vidDisp.autoPlay) vidDisp.play(); else vidDisp.seek(0);" - /> - - <mx:ProgressBar width="80%" mode="polled" source="vidDisp" - horizontalCenter="0" verticalCenter="0" labelPlacement="center" - id="loadingProgress" alpha="0.5" - complete="loadingProgress.visible=false;" - progress="progressHandler(event)" - /> + 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 init():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("mute", mute); + ExternalInterface.addCallback("setSource", setSource); + this.setFocus(); + this.addEventListener(KeyboardEvent.KEY_DOWN, keyDnHnd); + this.addEventListener(KeyboardEvent.KEY_UP, keyUpHnd); + } + ]]> + </fx:Script> + + <fx:Declarations> + <s:Fade id="fadeEffect" target="{playProgress}" alphaFrom="0.5" alphaTo="0" duration="2000"/> + </fx:Declarations> + + <s:VideoDisplay + id="vidDisp" + width="100%" height="100%" scaleMode="{scaleMode}" + source="{source}" volume="{vol}" + autoPlay="{autoPlay}" autoRewind="false" loop="{loop}" + mouseDown="vidDisp.pause();this.setFocus();" + mouseUp="if(vidComplete) vidDisp.seek(0); vidDisp.play();" + mediaPlayerStateChange="stateChangeHandler(event);" + complete="vidComplete=true;" + durationChange="if(vidDisp.autoPlay) vidDisp.play(); else vidDisp.seek(0);" + /> + + <mx:ProgressBar width="100%" mode="polled" source="vidDisp" + horizontalCenter="0" bottom="0" labelPlacement="center" + id="loadingProgress" alpha="0.5" + complete="loadingProgress.visible=false;" + progress="progressHandler(event)" + /> + <mx:ProgressBar width="100%" mode="manual" + horizontalCenter="0" bottom="0" labelPlacement="center" + id="playProgress" alpha="0.5" + visible="false" + /> </s:Application> diff --git a/Master/texmf-dist/doc/latex/media9/media9.pdf b/Master/texmf-dist/doc/latex/media9/media9.pdf Binary files differindex 8255d8e7103..ea1b1ffcdbe 100644 --- a/Master/texmf-dist/doc/latex/media9/media9.pdf +++ b/Master/texmf-dist/doc/latex/media9/media9.pdf diff --git a/Master/texmf-dist/doc/latex/media9/media9.tex b/Master/texmf-dist/doc/latex/media9/media9.tex index 561327326cf..7aa2c518047 100644 --- a/Master/texmf-dist/doc/latex/media9/media9.tex +++ b/Master/texmf-dist/doc/latex/media9/media9.tex @@ -89,6 +89,16 @@ A \LaTeX{} package for embedding interactive Adobe Flash (SWF) and 3D files (Ado \section{Introduction} This package provides an interface to embed interactive Flash (SWF) and 3D objects (Adobe U3D \& PRC) as well as video and sound files or streams in the popular MP4, FLV and MP3 formats into PDF documents. Playback of multimedia files uses the built-in Flash Player of Adobe Reader and does, therefore, not depend on external plug-ins. Flash Player supports the efficient H.264 codec for video compression. +MP4/H.264 video files can be encoded from existing video files and from numbered bitmap sequences using the \verb+ffmpeg+ command line tool (\url{http://ffmpeg.org}). In order to allow for precise seeking within video files it is necessary to encode them with a sufficient number of key frames. The command line for recoding an existing video file \verb+video.avi+ into \verb+video.mp4+ reads +\begin{Verbatim} + ffmpeg -i video.avi -vcodec libx264 -x264opts keyint=25 video.mp4 +\end{Verbatim} +From a sequence \verb+frame-0.png+, \verb+frame-1.png+, ... of bitmap files, an MP4 video is produced by +\begin{Verbatim} + ffmpeg -i frame-%d.png -vcodec libx264 -x264opts keyint=25 video.mp4 +\end{Verbatim} +Both examples insert a key frame at every second. + Among the supported media types, video and sound files require an additional Flash (SWF) application for playback, which must be either embedded into the PDF or loaded at runtime from the internet. There are numerous such players, both open-source and commercial, available on the internet. One of them is the highly configurable open-source `StrobeMediaPlayback.swf'~\cite{strobe}, maintained by Adobe and hosted on \href{http://sourceforge.net/projects/smp.adobe/files/}{SourceForge.net}. Package `media9' comes with an enhanced version of `StrobeMediaPlayback.swf'. In addition, two simple players for video and audio, `VPlayer.swf' and `APlayer.swf' are included, which can be used instead. They provide sufficient functionality for playing embedded files and streamed media. \emph{Note:} `media9' package replaces the now obsolete `movie15' package. `media9' is based on the RichMedia Annotation (Annotations are the interactive parts in a document, in PDF specification parlance.), an Adobe addition to the PDF specification~\cite{supplement}, while `movie15' uses the old multimedia framework (`Screen Annotation') of pre-9 Readers which depends on external plug-ins and which does not support recent media file formats. @@ -99,7 +109,7 @@ The final PDF can be viewed in current Adobe Readers on MS Windows and other pla \section{Requirements} \begin{trivlist} -\makeatletter +\makeatletter \item l3kernel (\LaTeX{} package), version $\ge \g@mix@liiikerneldate$ \item l3packages (\LaTeX{} package), version $\ge \g@mix@liiipkgdate$ \makeatother @@ -481,7 +491,7 @@ A YouTube video clip, as shown in Fig.~\ref{alien}, may serve as a basic example \caption{A YouTube video as an example of a Flash application loaded from a URL.}\label{alien} \end{figure} -Video and sound files are always loaded and then played by a media player application. Three players are installed along with the `media9.sty' package file: two simple players, `VPlayer.swf' for video and `APlayer.swf' for sound, and a fully blown one, `StrobeMediaPlayback.swf', with some fixes to improve its usability. The simple ones are `chromeless' players, that is, they do not have user controls. Minimal interactivity for play, pause and resume is still provided via left mouse button press and release. They were compiled, using the free Adobe Flex SDK~\cite{flex}, from XML files which reside in the \verb+doc/+ folder of the package installation. For `StrobeMediaPlayback.swf', only a patch file is included, as the sources can be downloaded elsewhere. +Video and sound files are always loaded and then played by a media player application. Three players are installed along with the `media9.sty' package file: two simple players, `VPlayer.swf' for video and `APlayer.swf' for sound, and a fully blown one, `StrobeMediaPlayback.swf', with some fixes to improve its usability. The simple ones are `chromeless' players, that is, they do not have graphical user controls. Nevertheless, interactivity is provided through the keyboard, as summarized in Table \ref{kbcontrol}, and through left mouse button press and release for playing, pausing and resuming media. `VPlayer.swf' and `APlayer.swf' were compiled, using the free Adobe Flex SDK~\cite{flex}, from XML source files which reside in the \verb+doc/+ folder of the package installation. For `StrobeMediaPlayback.swf', only a patch file is included, as the sources can be downloaded elsewhere. The improvements of `StrobeMediaPlayback.swf' in comparision to the original version on SourceForge.net are \begin{itemize} @@ -498,6 +508,23 @@ Playback of embedded video files is shown in Fig.~\ref{videoa}. Besides embedded `VPlayer.swf' and `APlayer.swf' expose a number of ActionScript functions to the JavaScript engine of Adobe Reader, allowing for playback control of media through PDF interactive forms and various trigger events. The functions and their calling convention are listed in Table~\ref{AVPlayerMethods}. An example of playing and pausing a video clip and setting the video source via interactive push buttons is given in Fig.~\ref{videoa}. +Sound files and streams in the MP3 format can be played with `APlayer.swf'. Fig.~\ref{radio} contains examples of an audio live stream and a remote MP3 sound file. Instead of being embedded, the player is loaded from a CTAN mirror during runtime because an internet connection is required anyway for streaming the audio. If a local sound file is to be embedded into the PDF this would have to be done in the same way as with the video file in one of the previous examples using the `\verb+addresource+' option. +\clearpage + +\begin{table} +\centering +\caption{Keyboard control of media players `VPlayer.swf' and `APlayer.swf'. The media must have the focus to have effect. Click onto the media if necessary.}\label{kbcontrol} +\begin{tabular}[t]{rp{0.5\linewidth}}\hline +keys & action\\\hline\hline +\keys{\makebox[2\width][c]{Space}} & play/pause\\ +\keys{Home}, \keys{End} & go to start/end\\ +\keys{\arrowkeyleft}, \keys{\arrowkeyright} & seek backwards/forwards\\ +\keys{\arrowkeydown}, \keys{\arrowkeyup} & decrease/increase speaker volume\\ +\keys{m} & mute/unmute\\ +\keys{\ctrl+\arrowkeyleft}, \keys{\ctrl+\arrowkeydown}, \keys{\ctrl+\arrowkeyright} & (APlayer.swf only) change sound speaker balance\\\hline +\end{tabular} +\end{table} + \begin{table}[p] \centering \caption{Parameters (ActionScript variables) for media players `VPlayer.swf' and `APlayer.swf' shipping with media9. Parameters are passed as a `{\tt\&}'-separated string using `{\tt flashvars}' option.}\label{playerparams} @@ -515,7 +542,7 @@ parameter & description\\\hline\hline \begin{table}[p] \centering \caption{Exposed ActionScript functions of media players `VPlayer.swf' and `APlayer.swf', that can be called from JavaScript using the `{\tt callAS}' method of the `{\tt AnnotRichMedia}' JavaScript object. Calling convention: \hbox to \linewidth {\hss\tt <RMA reference>.callAS('<function>' [,'<argument>']);\hss} Function name and its argument must be given as quoted strings. See~\cite{jscript} for further information.}\label{AVPlayerMethods} -\begin{tabular}[t]{llp{0.5\linewidth}}\hline +\begin{tabular}[t]{lp{0.25\linewidth}p{0.5\linewidth}}\hline function & argument &description\\\hline\hline {\tt play} & & play media\\ {\tt pause} & & pause media\\ @@ -524,6 +551,7 @@ function & argument &description\\\hline\hline {\tt seek} & number & move the play location to a time offset from the beginning of the media; argument measured in seconds\\ {\tt rewind} & & rewind media to the beginning (without pausing it)\\ {\tt volume} & number between 0 and 1 & set volume level\\ +{\tt balance} & number between $-1$ and $+1$ & (APlayer.swf only) set speaker balance\\ {\tt mute} & & mute or unmute (toggle) the audio of the media\\\hline \end{tabular} \end{table} @@ -550,7 +578,7 @@ parameter & description\\\hline\hline \end{tabular} \end{table} -\begin{figure} +\begin{figure}[p] \centering \begin{Verbatim} \includemedia[ @@ -606,7 +634,7 @@ parameter & description\\\hline\hline \caption{Example of playing back two different embedded MP4 video files in the same video player instance. The player, `VPlayer.swf', is also embedded in the PDF. Exposed ActionScript functions `{\tt playPause}' and `{\tt setSource}' of `VPlayer.swf' (Table~\ref{AVPlayerMethods}) are used to set-up the JavaScript actions of interactive push buttons.}\label{videoa} \end{figure} -\begin{figure} +\begin{figure}[p] \centering \begin{Verbatim} \includemedia[ @@ -632,9 +660,6 @@ parameter & description\\\hline\hline \caption{Example of video streamed from an RTMP server. This example uses media player `StrobeMediaPlayBack.swf', physically embedded in the PDF.}\label{videob} \end{figure} -%\enlargethispage{2ex} -Sound files and streams in the MP3 format can be played with `APlayer.swf'. Fig.~\ref{radio} contains examples of an audio live stream and a remote MP3 sound file. Instead of being embedded, the player is loaded from a CTAN mirror during runtime because an internet connection is required anyway for streaming the audio. If a local sound file is to be embedded into the PDF this would have to be done in the same way as with the video file in one of the previous examples using the `\verb+addresource+' option. - \begin{figure}[bp] %\flushright \begin{Verbatim} @@ -710,7 +735,7 @@ By default, the virtual camera sits at the origin $(0,0,0)$ of the World, lookin Additional resource files that are needed to render the 3D scene can be embedded using the `\verb+addresource+' option. Typical resources are bitmaps and Flash files (even animated and interactive ones), to be used as materials or scene backgrounds, as well as additional 3D objects in the U3D or PRC file format. The allowed file formats of \emph{bitmapped} image files depend on the \LaTeX workflow. \LaTeX{} $\rightarrow$ \verb+dvips+ $\rightarrow$ \verb+ps2pdf+/Distiller accepts PS and EPS files; pdf\LaTeX{} accepts PNG, JPEG and JBIG2; \pXepLaTeX{} $\rightarrow$ \verb+(x)dvipdfmx+ accepts PNG and JPEG. 3D JavaScript is necessary to load these resources upon activation. 3D JavaScript files are attached using the `\verb+add3Djscript+' option. -Below, two examples of embedded 3D files are shown. The first one, Fig.~\ref{asyex} is a PRC file generated with Asymptote. Note the text labels always facing the camera thanks to the attached 3D JavaScript file `asylabels.js'. The second example, Fig.~\ref{u3dex}, demonstrates the use of a views file which defines additional named views of the 3D object. Moreover, the possibilities of the extended 3D context menu can be evaluated. They were enabled by adding the `\verb+3Dmenu+' option to \verb+\includemedia+. All part and scene rendering attributes that can be changed via the `\emph{\sffamily Part Options}' and `\emph{\sffamily Viewing Options}' menu entries, as well as a cross section to be added with the `\emph{\sffamily Cross Section}' menu entry can be saved into a new view (`\emph{\sffamily Get Current View}'). Position, orientation and scaling of individual parts and of the cross section can be changed using the keyboard (keys \keys{\arrowkeyleft}, \keys{\arrowkeyright}, \keys{\arrowkeyup}, \keys{\arrowkeydown}, \keys{X}, \keys{\shift+X}, \keys{Y}, \keys{\shift+Y}, \keys{Z}, \keys{\shift+Z}, \keys{S}, \keys{\shift+S}). +Below, several examples of embedded 3D files are shown. The first one, Fig.~\ref{asyex} is a PRC file generated with Asymptote. Note the text labels always facing the camera thanks to the attached 3D JavaScript file `asylabels.js'. The second example, Fig.~\ref{u3dex}, demonstrates the use of a views file which defines additional named views of the 3D object. Moreover, the possibilities of the extended 3D context menu can be evaluated. They were enabled by adding the `\verb+3Dmenu+' option to \verb+\includemedia+. All part and scene rendering attributes that can be changed via the `\emph{\sffamily Part Options}' and `\emph{\sffamily Viewing Options}' menu entries, as well as a cross section to be added with the `\emph{\sffamily Cross Section}' menu entry can be saved into a new view (`\emph{\sffamily Get Current View}'). Position, orientation and scaling of individual parts and of the cross section can be changed using the keyboard (keys \keys{\arrowkeyleft}, \keys{\arrowkeyright}, \keys{\arrowkeyup}, \keys{\arrowkeydown}, \keys{X}, \keys{\shift+X}, \keys{Y}, \keys{\shift+Y}, \keys{Z}, \keys{\shift+Z}, \keys{S}, \keys{\shift+S}). The third example, Fig.~\ref{u3dex2}, shows an animated 3D object. The animation itself and the functions called by pressing the controls are defined in a 3D JavaScript file attached to the model. \begin{figure}[bp] \centering @@ -795,6 +820,60 @@ Contents of `dice.vws': \caption{Embedded U3D file, based on a VRML model by Peter Whitehouse, \url{http://www.wonko.info/vrml/index.htm}; conversion to U3D was done using DeepExploration\textsuperscript{\scriptsize\textregistered}\cite{dexp}. The file `{\tt dice.vws}' provides predefined views to be selected from the 3D toolbar or by right click.}\label{u3dex} \end{figure} +\begin{figure} + \begin{Verbatim} + \includemedia[ + label=malte, + width=0.5\linewidth,height=0.5\linewidth, + activate=pageopen, + 3Dmenu, + 3Dc2c=1 1 1, + 3Dcoo=-0.001042630523443222 1.4577869224116568e-19 0.028235001489520073, + 3Droo=0.2604540212188131, + add3Djscript=malte.js + ]{}{malte.u3d} + + \PushButton[ + onclick={annotRM['malte'].context3D.cntrClockWise();} + ]{\includegraphics[height=1.44em]{boutona}} + \PushButton[ + onclick={annotRM['malte'].context3D.pause();} + ]{\includegraphics[height=1.44em]{boutonb}} + \PushButton[ + onclick={annotRM['malte'].context3D.clockWise();} + ]{\includegraphics[height=1.44em]{boutonc}} + \hspace{1em} + \PushButton[ + onclick={annotRM['malte'].context3D.slower();} + ]{\includegraphics[height=1.44em]{boutond}} + \PushButton[ + onclick={annotRM['malte'].context3D.origSpeed();} + ]{\includegraphics[height=1.44em]{boutone}} + \PushButton[ + onclick={annotRM['malte'].context3D.faster();} + ]{\includegraphics[height=1.44em]{boutonf}} + \end{Verbatim} + \centering + \includemedia[ + label=malte, + width=0.5\linewidth,height=0.5\linewidth, + activate=pageopen, + 3Dmenu, + 3Dc2c=1 1 1, + 3Dcoo=-0.001042630523443222 1.4577869224116568e-19 0.028235001489520073, + 3Droo=0.2604540212188131, + add3Djscript=malte.js + ]{}{malte.u3d} + + \PushButton[onclick={annotRM['malte'].context3D.cntrClockWise();}]{\includegraphics[height=1.44em]{boutona}} + \PushButton[onclick={annotRM['malte'].context3D.pause();}]{\includegraphics[height=1.44em]{boutonb}} + \PushButton[onclick={annotRM['malte'].context3D.clockWise();}]{\includegraphics[height=1.44em]{boutonc}} + \hspace{1em} + \PushButton[onclick={annotRM['malte'].context3D.slower();}]{\includegraphics[height=1.44em]{boutond}} + \PushButton[onclick={annotRM['malte'].context3D.origSpeed();}]{\includegraphics[height=1.44em]{boutone}} + \PushButton[onclick={annotRM['malte'].context3D.faster();}]{\includegraphics[height=1.44em]{boutonf}} + \caption{Animated U3D example of a Maltese drive contributed by Jean-Luc Chesnot. The animation is defined in the JavaScript file `{\tt malte.js}'.}\label{u3dex2} +\end{figure} \clearpage \subsection{3D quick-start guide}\label{sec:3Dtut} \begin{enumerate} |