diff options
16 files changed, 832 insertions, 86 deletions
diff --git a/Master/texmf-dist/doc/latex/media9/ChangeLog b/Master/texmf-dist/doc/latex/media9/ChangeLog index 0a9f5754844..7151a707fba 100644 --- a/Master/texmf-dist/doc/latex/media9/ChangeLog +++ b/Master/texmf-dist/doc/latex/media9/ChangeLog @@ -1,3 +1,9 @@ +2015-05-11 + * v0.52 + * New: `SlideShow.swf' (image gallery viewer for embedded and remote + live or static image files in the PNG, JPEG and GIF formats); right-click + context menu added to players APlayer.swf, VPlayer.swf, SlideShow.swf + 2015-03-11 * v0.51 * Fix: compatibility with `fixocgx' package diff --git a/Master/texmf-dist/doc/latex/media9/media9.pdf b/Master/texmf-dist/doc/latex/media9/media9.pdf Binary files differindex bdef33f20f6..60fd5f7947e 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/source/latex/media9/files/config.xml b/Master/texmf-dist/source/latex/media9/files/config.xml new file mode 100644 index 00000000000..2c7907c61f7 --- /dev/null +++ b/Master/texmf-dist/source/latex/media9/files/config.xml @@ -0,0 +1,57 @@ +<?xml version="1.0"?> +<SlideShow> + <!-- + Configuration file template for SlideShow.swf + + SlideShow.swf can display life and static PNG/JPEG/GIF image + files from remote servers or residing on the same server as the + app itself. + + Pass this file to SlideShow.swf using the `xml=<configuration + file>' FlashVar. + + **NOTE**: For security reasons of Flash Player, the configuration + file and SlideShow.swf must reside on the same web server or + be both embedded into the PDF. Different web servers or the + combination of web server location and embedding into the PDF + throws a security error. + + An image definition starts with <Img [attributes]> and ends + with </Img>. All attributes in the opening <Img [attributes]> + tag are optional: + + live="<refresh interval in [s]>" for live remote image + rot90="<integer number>" initial rotation by number*90° + + The <URL>...</URL> element is mandatory, while the <caption>...</caption> + element is not. + + An image URL, given between <URL> and </URL>, can be absolute, + that is starting with 'http://...', or relative to the location + of SlideShow.swf. See the examples. + --> + <!-- three live images; refresh interval in [s] --> + <Img live="3"> + <caption>Live remote image.</caption> + <URL>http://dev.eightbeers.org/tex/corner-icon.png</URL> + </Img> + <Img live="500"> + <caption>Aurora australis forecast (live remote image).</caption> + <URL>http://services.swpc.noaa.gov/images/aurora-forecast-southern-hemisphere.png</URL> + </Img> + <Img live="500"> + <caption>Aurora borealis forecast (live remote image).</caption> + <URL>http://services.swpc.noaa.gov/images/aurora-forecast-northern-hemisphere.png</URL> + </Img> + <!-- static image with URL relative to SlideShow.swf location --> + <Img> + <caption>CTAN lion drawing by Duane Bibby. Thanks to www.ctan.org.</caption> + <URL>files/ctan_lion_350x350.png</URL> + </Img> + <!-- static remote image --> + <Img rot90="3"> + <caption>Lion from the LaTeX project site, rotated by 3x90°. +Press `r' or `R' to change orientation.</caption> + <URL>http://latex-project.org/lib/img/lion.png</URL> + </Img> +</SlideShow> diff --git a/Master/texmf-dist/source/latex/media9/files/ctan_lion_350x350.png b/Master/texmf-dist/source/latex/media9/files/ctan_lion_350x350.png Binary files differnew file mode 100644 index 00000000000..c24d9a98f25 --- /dev/null +++ b/Master/texmf-dist/source/latex/media9/files/ctan_lion_350x350.png diff --git a/Master/texmf-dist/source/latex/media9/media9.tex b/Master/texmf-dist/source/latex/media9/media9.tex index cd41fbdc650..83ea652d847 100644 --- a/Master/texmf-dist/source/latex/media9/media9.tex +++ b/Master/texmf-dist/source/latex/media9/media9.tex @@ -9,6 +9,8 @@ \listfiles \documentclass[a4paper]{article} \frenchspacing +\usepackage[utf8]{inputenc} +\usepackage{textcomp} \usepackage[attachfiles]{media9} %\usepackage[draft]{media9} \usepackage{animate} @@ -27,7 +29,7 @@ \usepackage{menukeys} \usepackage{hyperref} \usepackage{hypcap} -\def\keywords{embed flash movie LaTeX pdf 3d include sound swf mp3 video mp4 h.264 aac flv audio multimedia streamed media rtmp YouTube animation JavaScript pdfLaTeX dvips ps2pdf dvipdfmx XeLaTeX u3d prc Adobe Reader RichMedia annotation LuaLaTeX} +\def\keywords{embed flash movie LaTeX pdf 3d include sound swf mp3 video mp4 h.264 aac slideshow image gallery flv audio multimedia streamed media rtmp YouTube animation JavaScript pdfLaTeX dvips ps2pdf dvipdfmx XeLaTeX u3d prc Adobe Reader RichMedia annotation LuaLaTeX} \hypersetup{ bookmarksnumbered,linktocpage,breaklinks, pdftitle={The media9 Package}, @@ -43,6 +45,9 @@ } \usepackage[scaled=0.85]{luximono} +%\usepackage{listings} +\usepackage{minted} + \def\XeLaTeX{X\kern-.1667em\lower.5ex\hbox{\reflectbox{E}}\kern-.125em\LaTeX} \def\pXepLaTeX{(X\kern-.1667em\lower.5ex\hbox{\reflectbox{E}})\kern-.125em\LaTeX} @@ -71,6 +76,7 @@ \def\month{#2} \def\day{#3} } +\usepackage{siunitx} \begin{document} \makeatletter @@ -93,15 +99,21 @@ This package provides an interface to embed, in the first place, interactive Fla 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/osmf.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. -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+ (\url{http://ffmpeg.org}) or \verb+avconv+ (\url{http://libav.org}) command line tools (Libav is a fork from the FFmpeg code). 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 (\verb+ffmpeg+ can be substituted with \verb+avconv+) +There is yet another player bundled with `media9'. It is a simple image gallery viewer called `SlideShow.swf' which can display collections of embedded and remote images in the PNG, JPEG and GIF file formats. Remote images are downloaded at viewing time and can be configured to be refreshed at definite time intervals. + +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+ (\url{http://ffmpeg.org}) or \verb+avconv+ (\url{http://libav.org}) command line tools (Libav is a fork from the FFmpeg code). 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 (one line; \verb+ffmpeg+ can be substituted with \verb+avconv+) +\begin{center} \begin{Verbatim} - ffmpeg -i video.avi -c:v libx264 -g 30 -r 30 video.mp4 + ffmpeg -i video.avi -vf scale="trunc(iw/2)*2:trunc(ih/2)*2" + -c:v libx264 -profile:v high -pix_fmt yuv420p -g 30 -r 30 video.mp4 \end{Verbatim} +\end{center} 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 -c:v libx264 -g 30 -r 30 video.mp4 + ffmpeg -i frame-%d.png -vf scale="trunc(iw/2)*2:trunc(ih/2)*2" + -c:v libx264 -profile:v high -pix_fmt yuv420p -g 30 -r 30 video.mp4 \end{Verbatim} -Both examples insert a key frame (option `\verb+-g+') at every second since the frame rate is set to 30 fps. +Both examples insert a key frame (option `\verb+-g+') at every second since the frame rate is set to 30 fps. The video encoder requires even pixel numbers in both dimensions which is ensured by adding `\verb+-vf scale="..."+' to the option list. \emph{Note:} `media9' package replaces the now obsolete `movie15' package. `media9' is based on the RichMedia Annotation (Annotations are the interactive elements 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 third-party plug-ins and which does not support recent media file formats. @@ -241,7 +253,7 @@ if, for a particular media player, the video source is set through ActionScript \begin{verbatim} attachfiles \end{verbatim} -If set, embedded files can be downloaded from the PDF via the `Attachments' navigation pane in the Reader. +If set, embedded files can be downloaded from the PDF via the \Acrobatmenu{ShowHideFileAttachment}{Attachments} navigation pane in the Reader. \begin{verbatim} activate=onclick | pageopen | pagevisible \end{verbatim} @@ -523,7 +535,7 @@ final See \hyperlink{draftfinal}{above}. \clearpage -\section[Embedding Flash, video and sound (with examples)]{Embedding Flash, video and sound} +\section[Embedding Flash, video and sound, image slide-shows (with examples)]{Embedding Flash, video and sound,\\ image slide-shows} A YouTube video clip, as shown in Fig.~\ref{alien}, may serve as a basic example of loading Flash content from a URL to be displayed in an embedded fashion in a PDF document. Indeed, a YouTube clip is nothing more than a small SWF file which loads a video stream and other necessary resources, such as user controls and a player skin from a remote server. It can be configured via ActionScript variables to play several videos in a row, to play a video in a loop etc. Player parameters are documented on \url{http://code.google.com/apis/youtube/player_parameters.html} and can be passed to the player using either the `\verb+flashvars+' option, as in the example, or appended to the URL string after the video ID. A question mark `\verb+?+' must be put between the video ID and the parameter string. Some of the documented parameters, such as `\verb+rel+', seem to have an effect only if they are passed as part of the URL. \begin{figure}[H] @@ -554,7 +566,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 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 open-source Apache 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. +Media files (video, sound, images) are always loaded and then played by a media player application. Four players are installed along with the `media9.sty' package file: three simple players for video (`VPlayer.swf'), sound (`APlayer.swf') and slide-shows of embedded and/or remote (live or static) image files (`SlideShow.swf'), and the fully blown third-party media player `StrobeMediaPlayback.swf' with some fixes to improve its usability. The simple players are `chromeless', that is, they do not have graphical user controls. Nevertheless, interactivity is provided through left mouse button press and release for playing, pausing, resuming playback, through the player's context menu (right-click), and through the keyboard as summarized in Table \ref{kbcontrol}. The player apps were compiled using the open-source Apache 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} @@ -565,27 +577,31 @@ The improvements of `StrobeMediaPlayback.swf' in comparision to the original ver There is no need to copy the installed players into the directory of the document source for embedding. They will be found by \LaTeX{} without taking any further action. -Like YouTube videos, media players are configured via ActionScript variables which are passed using option `\verb+flashvars+'. Table~\ref{playerparams} lists parameters available for `VPlayer.swf' and `APlayer.swf', table~\ref{smpparams} for `StrobeMediaPlayback.swf'. +Like YouTube videos, media players are configured via ActionScript variables which are passed using option `\verb+flashvars+'. Table~\ref{playerparams} lists parameters available for `VPlayer.swf', `APlayer.swf' and `SlideShow.swf', Table~\ref{smpparams} for `StrobeMediaPlayback.swf'. Playback of embedded video files is shown in Fig.~\ref{videoa}. Besides embedded files, also video streamed from remote servers via HTTP and RTMP protocols is supported, as shown in Fig.~\ref{videob}. -`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 push buttons (see Sect. \ref{mbtn}) and various trigger events. The functions and their calling convention are listed in Table~\ref{AVPlayerMethods}. From within JavaScript, these functions can be called using the `\verb+callAS+' (=~call ActionScript) method of the \verb+AnnotRichMedia+ object. As an example, a call to the `\verb+seek+' function looks like +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. In one of the sound examples, 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. + +The slide-show application `SlideShow.swf' requires a configuration file in the XML file format. It specifies the URLs from which the images will be loaded and may contain optional settings, such as image captions, refresh intervals for live images and initial rotation. The syntax is documented in the configuration file template in Fig.~\ref{SlideShowXML}. The file name of a configuration file is passed to `SlideShow.swf' using the `\verb+xml+' ActionScript variable. Note that for security reasons the configuration file and `SlideShow.swf' must reside on the same server or be both embedded into the PDF. Otherwise, a security error will be thrown by the Flash Player plugin. A slide-show example is shown in Fig.~\ref{slideshowex}. + +`VPlayer.swf', `APlayer.swf' and `SlideShow.swf' expose a number of ActionScript functions to the JavaScript engine of Adobe Reader, allowing for playback control of media through push buttons (see Sect. \ref{mbtn}) and various trigger events. The functions and their calling convention are listed in Tables~\ref{AVPlayerMethods} and~\ref{SlideShowMethods}. From within JavaScript, these functions can be called using the `\verb+callAS+' (=~call ActionScript) method of the \verb+AnnotRichMedia+ object. As an example, a call to the `\verb+seek+' function looks like \begin{verbatim} annotRM.myvideo.callAS("seek", 12.3); \end{verbatim} -and a call to the parameter-less function `\verb+pause+' like +and a call to the parameter-less function `\verb+playPause+' like \begin{verbatim} - annotRM.myvideo.callAS("pause"); + annotRM.myvideo.callAS("playPause"); \end{verbatim} Both functions calls are sent to the media inclusion that was labelled `\verb+myvideo+' using the `\verb+label+' option of \verb+\includemedia+. 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. In one of the sound examples, 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} +\begin{table}[htbp] +%\flushright \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 +\caption{Keyboard control of media players (a) `VPlayer.swf' \& `APlayer.swf', (b) `SlideShow.swf'. Players must have the focus to take effect. Click onto the players if necessary.}\label{kbcontrol} +\vspace{3ex} +(a)\\ +\begin{tabular}{rp{0.5\linewidth}}\hline keys & action\\\hline\hline \keys{\unexpanded{\makebox[2\width][c]{Space}}} & play/pause\\ \keys{Home}, \keys{End} & go to start/end\\ @@ -594,28 +610,49 @@ keys & action\\\hline\hline \keys{m} & mute/unmute\\ \keys{\ctrl+\arrowkeyleft}, \keys{\ctrl+\arrowkeydown}, \keys{\ctrl+\arrowkeyright} & (APlayer.swf only) change sound speaker balance\\\hline \end{tabular} + +\vspace{6ex} +(b)\\ +\begin{tabular}{rp{0.5\linewidth}}\hline +keys & action\\\hline\hline +\keys{\unexpanded{\makebox[2\width][c]{Space}}} & play/pause auto-cycling through slides\\ +\keys{\arrowkeyleft}, \keys{\arrowkeyright} & previous/next slide\\ +\keys{Home}, \keys{End} & go to first/last slide\\ +\keys{r}, \keys{R} & right/left rotate current slide by \SI{90}{\degree}\\\hline +\end{tabular} \end{table} -\begin{table}[bp] +\begin{table}[tp] \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} -\begin{tabular}[t]{p{0.4\linewidth}p{0.5\linewidth}}\hline +\caption{Parameters (ActionScript variables) for media players (a) `VPlayer.swf' \& `APlayer.swf', (b) `SlideShow.swf' shipping with media9. Parameters are passed as a `{\tt\&}'-separated string using `{\tt flashvars}' option.}\label{playerparams} +\vspace{3ex} +(a)\\ +\begin{tabular}[c]{p{0.4\linewidth}p{0.5\linewidth}}\hline parameter & description\\\hline\hline {\tt source=<file path or URL>} & (required) path to embedded media file (see option `{\tt addresource}'), or URL (http, rtmp) to online media file\\ {\tt autoPlay=true|false} & if {\tt=true}, automatically starts playback after activation (see option `{\tt activation})'\\ {\tt autoRewind=true|false} &(VPlayer.swf only) if {\tt=true}, automatically rewind to the first frame after playback has finished; default is `{\tt false}'\\ {\tt loop=true|false} & if {\tt=true}, media is played in a loop\\ {\tt stepping=true|false} &(VPlayer.swf only) if {\tt=true}, the video advances by roughly one frame per mouse click\\ -{\tt scaleMode=letterbox|none| \phantom{.}\hfill{}stretch|zoom} & default: {\tt stretch}; determines how to scale the video in order to fit into player\\ +{\tt scaleMode=letterbox|none| \phantom{.}\hfill{}stretch|zoom} & default: {\tt letterbox}; determines how to scale the video in order to fit into player\\ {\tt hideBar=true|false} &(APlayer.swf only) if {\tt=true}, the progress bar indicating the play position is not shown\\ {\tt volume=<value between 0.0 \phantom{.}\hfill{}and 1.0>} & sets volume of the sound\\ {\tt balance=<value between \phantom{xxxx} \phantom{.}\hfill{}-1.0 and 1.0>} & (APlayer.swf only) sets balance of sound speakers\\\hline \end{tabular} + +\vspace{6ex} +(b)\\ +\begin{tabular}[c]{p{0.4\linewidth}p{0.5\linewidth}}\hline +parameter & description\\\hline\hline +{\tt xml=<file path or URL>} & (required) path to embedded (option `{\tt addresource}') or URL of remote configuration file\\ +{\tt delay=<number>} & sets time delay in seconds for transition between slides during playback, default: \SI{5}{\second}\\ +{\tt autoPlay=true|false} & if {\tt=true}, automatically starts cycling through slides after activation (see option `{\tt activation})'\\\hline +\end{tabular} \end{table} -\begin{table}[bp] +\begin{table}%[bp] \centering -\caption{Exposed ActionScript functions of media players `VPlayer.swf' and `APlayer.swf', that can be called from within media buttons (see Sect. \ref{mbtn}) or from JavaScript using the `{\tt callAS}' method of the `{\tt AnnotRichMedia}' JavaScript object (see~\cite{jscript} for further information).}\label{AVPlayerMethods} +\caption{Exposed ActionScript functions of media players `VPlayer.swf' and `APlayer.swf' that can be called from within media buttons (see Sect. \ref{mbtn}) or from JavaScript using the `{\tt callAS}' method of the `{\tt AnnotRichMedia}' JavaScript object (see~\cite{jscript} for further information).}\label{AVPlayerMethods} \begin{tabular}[t]{lp{0.25\linewidth}p{0.5\linewidth}}\hline function & argument &description\\\hline\hline {\tt play} & number (optional) & play media, optionally starting at \emph{number} seconds offset into the media file\\ @@ -635,6 +672,23 @@ function & argument &description\\\hline\hline \end{tabular} \end{table} +\begin{table}%[bp] +\centering +\caption{Exposed ActionScript functions of slide-show player `SlideShow.swf' that can be called from within media buttons or from JavaScript.}\label{SlideShowMethods} +\begin{tabular}[t]{lp{0.21\linewidth}p{0.47\linewidth}}\hline +function & argument &description\\\hline\hline +{\tt play} & & play slide-show\\ +{\tt pause} & & pause slide-show\\ +{\tt playPause} & & toggle between play and pause\\ +{\tt setXML} & string & load another configuration file (path to file, embedded using option `{\tt addresource}', or URL)\\ +{\tt seek} & int number & go to slide `number', zero-based\\ +{\tt slideNum} & & returns current slide number, zero-based; only useful in JavaScript via `{\tt callAS}' method\\ +{\tt numSlides} & & returns total number of slides in the slide-show; only useful in JavaScript via `{\tt callAS}' method\\ +{\tt playing} & & returns boolean value `{\tt true}', if the media is currently playing, `{\tt true}' otherwise; only useful in JavaScript via `{\tt callAS}' method\\ +{\tt rotate} & int number (optional) & rotate current slide by number$\times\SI{90}{\degree}$\\\hline +\end{tabular} +\end{table} + \begin{table}[bp] \centering \caption{Parameters (ActionScript variables) for `StrobeMediaPlayback.swf' shipping with media9. Parameters are passed as a `{\tt\&}'-separated string using `{\tt flashvars}' option.}\label{smpparams} @@ -657,7 +711,7 @@ parameter & description\\\hline\hline \end{tabular} \end{table} -\begin{figure}[bp] +\begin{figure}[p] \centering \begin{Verbatim} \includemedia[ @@ -667,10 +721,10 @@ parameter & description\\\hline\hline addresource=cube.mp4, transparent, %transparent player background activate=pageopen, + passcontext, %show VPlayer's right-click menu flashvars={ source=random.mp4 &loop=true % loop video - &scaleMode=letterbox % preserve aspect ratio while scaling the video } ]{}{VPlayer.swf} @@ -694,10 +748,11 @@ parameter & description\\\hline\hline addresource=cube.mp4, transparent, %transparent player background activate=pageopen, + passcontext, %show VPlayer's right-click menu flashvars={ source=random.mp4 &loop=true % loop video - &scaleMode=letterbox % preserve aspect ratio while scaling the video + &autoPlay=true } ]{}{VPlayer.swf}\hfill} \makebox[\linewidth]{\hfill% @@ -713,7 +768,45 @@ parameter & description\\\hline\hline mediacommand=some_dice:setSource [(cube.mp4)] ]{\fbox{\strut cube.mp4}} \hfill} -\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 media control buttons. Different button faces have been defined for the Play/Pause button.}\label{videoa} +\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 media control buttons. Different button faces have been defined for the Play/Pause button. Also, playback can be contolled via the player's context (right-click) menu or the keyboard.}\label{videoa} +\end{figure} + +\begin{figure}%[bp] +\centering +%\lstinputlisting[basicstyle=\scriptsize\ttfamily,language=XML]{config.xml} +\inputminted[fontsize=\footnotesize]{xml}{test/config.xml} +\caption{Configuration file template (XML format) for `SlideShow.swf'}\label{SlideShowXML} +\end{figure} + +\makeatletter% +\def\myAcrobatmenu#1#2{\leavevmode\pdfstartlink attr{\Hy@setpdfborder\ifx\@pdfhighlight\@empty\else/H\@pdfhighlight\fi\ifx\@menubordercolor\relax\else/C[\@menubordercolor]\fi} user{/Subtype/Link\ifHy@pdfa/F4\fi/A<</S/Named/N/#1>>}\relax\Hy@colorlink\@menucolor#2\close@pdflink}\makeatother +\savebox{\COO}{\keys{\shift+}} +\savebox{\CtoC}{\keys{\unexpanded{\makebox[2\width][c]{Space}}}} +\begin{figure}[bp] +\centering +\begin{Verbatim} +\includemedia[ + width=\linewidth,height=\linewidth, + activate=pageopen, + addresource=config.xml, %embedded configuration + addresource=files/ctan_lion_350x350.png, %embedded image file + flashvars={xml=config.xml}, + passcontext %show the player's context menu +]{}{SlideShow.swf} +\end{Verbatim} +\vspace{1ex} +\makebox[\linewidth]{\hfill% +\includemedia[ +% width=0.8\linewidth,height=0.6\linewidth, + width=\linewidth,height=\linewidth, + activate=pageopen, + addresource=config.xml, %embedded configuration + addresource=files/ctan_lion_350x350.png, %embedded image file + flashvars={xml=config.xml}, + passcontext %show the player's context menu +]{}{SlideShow.swf} +\hfill} +\caption{Slide-show example with one embedded and several remote image files, some of which are live images. The listing in Fig.~\ref{SlideShowXML} is used as content of file \myAcrobatmenu{ShowHideFileAttachment}{`config.xml'}. Manually cycle forwards through the images by mouse-click or backwards by \usebox{\COO}+mouse-click. Play/pause auto-cycling through the slide-show by hitting \usebox{\CtoC}. Also, the context (right-click) menu of the player can be used.}\label{slideshowex} \end{figure} \begin{figure}[bp] @@ -743,6 +836,7 @@ parameter & description\\\hline\hline \begin{figure}[bp] %\flushright +{\small% \begin{Verbatim} \includemedia[ addresource=bird.mp3, @@ -750,48 +844,56 @@ parameter & description\\\hline\hline source=bird.mp3 &autoPlay=true }, - transparent + transparent, + passcontext %show APlayer's right-click menu ]{\color{blue}\framebox[0.4\linewidth][c]{Singing bird}}{APlayer.swf} \end{Verbatim} -\makebox[\linewidth]{a)\hfill\includemedia[ +} +\makebox[\linewidth]{(a)\hfill\includemedia[ addresource=bird.mp3, flashvars={ source=bird.mp3 &autoPlay=true }, - transparent + transparent, + passcontext %show APlayer's right-click menu ]{\color{blue}\framebox[0.5\linewidth][c]{Singing bird}}{APlayer.swf} \hfill} -\vskip 4ex\begin{Verbatim} +\vskip 4ex{\small\begin{Verbatim} \includemedia[ flashvars={ source=http://mp3.live.tv-radio.com/franceculture% /all/franceculturehautdebit.mp3 &autoPlay=true }, - transparent + transparent, + passcontext %show APlayer's right-click menu ]{\color{blue}\fbox{Listen live to Radio France Culture}}{% http://mirrors.ibiblio.org/pub/mirrors/CTAN/macros/latex/% contrib/media9/players/APlayer.swf% } \end{Verbatim} -\makebox[\linewidth]{b)\hfill\includemedia[ +} +\makebox[\linewidth]{(b)\hfill\includemedia[ flashvars={ source=http://mp3.live.tv-radio.com/franceculture/all/franceculturehautdebit.mp3 &autoPlay=true }, - transparent + transparent, + passcontext %show APlayer's right-click menu ]{\color{blue}\fbox{Listen live to Radio France Culture}}{% %APlayer.swf% %http://mirror.ctan.org/macros/latex/contrib/media9/players/APlayer.swf% http://mirrors.ibiblio.org/pub/mirrors/CTAN/macros/latex/contrib/media9/players/APlayer.swf% }\hfill} \vskip 4ex +{\small% \begin{Verbatim} \includemedia[ label=song49, flashvars={source=http://www.openbsd.org/songs/song49.mp3}, - transparent + transparent, + passcontext %show VPlayer's right-click menu ]{\color{blue}\fbox{Listen to OpenBSD 4.9 release song}}{APlayer.swf}\\ \mediabutton[ mediacommand=song49:play[(5.5)], @@ -806,14 +908,16 @@ http://mirrors.ibiblio.org/pub/mirrors/CTAN/macros/latex/contrib/media9/players/ mediacommand=song49:pause[(221)] ]{\fbox{Harmonica solo}} \end{Verbatim} +} \makebox[\linewidth]{\rule{0pt}{1.5\baselineskip}\hfill\includemedia[ label=song49, flashvars={ source=http://www.openbsd.org/songs/song49.mp3 }, - transparent + transparent, + passcontext %show VPlayer's right-click menu ]{\color{blue}\fbox{Listen to OpenBSD 4.9 release song}}{APlayer.swf}\hfill}\\ -\makebox[\linewidth]{\makebox[0pt][l]{c)}\hfill% +\makebox[\linewidth]{\makebox[0pt][l]{(c)}\hfill% \mediabutton[ mediacommand=song49:play[(5.5)], mediacommand=song49:pause[(37)] @@ -840,7 +944,8 @@ http://mirrors.ibiblio.org/pub/mirrors/CTAN/macros/latex/contrib/media9/players/ source=cube.mp4 &autoPlay=true % start playing on activation &loop=true - } + }, + passcontext %show player's right-click menu ]{\includegraphics[height=0.45\linewidth]{cubeposter}}{VPlayer9.swf} \end{Verbatim} \vspace{1ex} @@ -851,7 +956,8 @@ http://mirrors.ibiblio.org/pub/mirrors/CTAN/macros/latex/contrib/media9/players/ source=cube.mp4 &autoPlay=true %start playing on activation &loop=true - } + }, + passcontext %show player's right-click menu ]{\includegraphics[height=0.45\linewidth]{cubeposter}}{VPlayer9.swf}\hfill \vspace{2ex} \begin{Verbatim} @@ -861,7 +967,8 @@ http://mirrors.ibiblio.org/pub/mirrors/CTAN/macros/latex/contrib/media9/players/ source=bird.mp3 &autoPlay=true }, - transparent + transparent, + passcontext %show player's right-click menu ]{\color{blue}\framebox[0.4\linewidth][c]{Singing bird}}{APlayer9.swf} \end{Verbatim} \vspace{1ex} @@ -871,7 +978,8 @@ http://mirrors.ibiblio.org/pub/mirrors/CTAN/macros/latex/contrib/media9/players/ source=bird.mp3 &autoPlay=true }, - transparent + transparent, + passcontext %show player's right-click menu ]{\color{blue}\framebox[0.5\linewidth][c]{Singing bird}}{APlayer9.swf}\hfill \vspace{2ex} \caption{Video and sound examples that should run in Adobe Reader for Linux up to version \href{ftp://ftp.adobe.com/pub/adobe/reader/unix/9.x/9.4.1/}{9.4.1}. Here, players `VPlayer9.swf' and `APlayer9.swf' are used. Both are compatible with Adobe Flash Player 9 plugin that is bundled with the Reader. Also, the video player needs to be activated by mouse click (which is the default). We provide a poster image that is shown in the inactive state.}\label{ar941ex} diff --git a/Master/texmf-dist/source/latex/media9/players/APlayer.mxml b/Master/texmf-dist/source/latex/media9/players/APlayer.mxml index 30ae5de9229..9be181f2f5d 100644 --- a/Master/texmf-dist/source/latex/media9/players/APlayer.mxml +++ b/Master/texmf-dist/source/latex/media9/players/APlayer.mxml @@ -4,7 +4,7 @@ <!-- a FlashPlayer-10 compatible component for playing --> <!-- MP3 audio files and streams. --> <!-- --> -<!-- version 20140625 --> +<!-- version 20150511 --> <!-- --> <!-- --> <!-- The free Apache Flex 4 SDK is required to compile --> @@ -42,7 +42,7 @@ preinitialize="initialise(FlexGlobals.topLevelApplication.parameters);" applicationComplete="initSound();addEventListeners(); fadeTargets=new Array(playProgress, caption);" - creationComplete="initCallBacks();" + creationComplete="initCallBacks();initContext();" mouseDown="pause();setFocus();" mouseUp="play();" backgroundAlpha="0" @@ -218,7 +218,6 @@ } private function addEventListeners():void { - this.setFocus(); this.addEventListener(Event.ENTER_FRAME, onEnterFrame); this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); this.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); @@ -324,6 +323,46 @@ 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("Seek, [\u2190]/[\u2192]", true, 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; diff --git a/Master/texmf-dist/source/latex/media9/players/APlayer9.mxml b/Master/texmf-dist/source/latex/media9/players/APlayer9.mxml index 1a80f98c921..8c12fa943ab 100644 --- a/Master/texmf-dist/source/latex/media9/players/APlayer9.mxml +++ b/Master/texmf-dist/source/latex/media9/players/APlayer9.mxml @@ -4,7 +4,7 @@ <!-- a FlashPlayer-9 compatible component for playing --> <!-- MP3 audio files and streams. --> <!-- --> -<!-- version 20140625 --> +<!-- version 20150511 --> <!-- --> <!-- Copyright (C) 2012-today Alexander Grahn --> <!-- --> @@ -26,7 +26,7 @@ <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" preinitialize="initialise(Application.application.parameters);" applicationComplete="initSound();addEventListeners();" - creationComplete="initCallBacks();" + creationComplete="initCallBacks();initContext();" mouseDown="pause();setFocus();" mouseUp="play();" backgroundAlpha="0" @@ -207,7 +207,6 @@ } private function addEventListeners():void { - this.setFocus(); this.addEventListener(Event.ENTER_FRAME, onEnterFrame); this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); this.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); @@ -313,6 +312,46 @@ 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("Seek, [\u2190]/[\u2192]", true, 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; diff --git a/Master/texmf-dist/source/latex/media9/players/SlideShow.mxml b/Master/texmf-dist/source/latex/media9/players/SlideShow.mxml new file mode 100644 index 00000000000..6d7087bbc70 --- /dev/null +++ b/Master/texmf-dist/source/latex/media9/players/SlideShow.mxml @@ -0,0 +1,426 @@ +<?xml version="1.0"?> +<!-- --> +<!-- Apache Flex 4 source file of SlideShow.swf, --> +<!-- a FlashPlayer-10 compatible component for --> +<!-- JPEG/PNG/GIF slideshows. --> +<!-- --> +<!-- version 20150511 --> +<!-- --> +<!-- --> +<!-- 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, either --> +<!-- version 1.3 of this license or (at your option) any later --> +<!-- version. --> +<!-- --> +<!-- The latest version of this license is in --> +<!-- http://www.latex-project.org/lppl.txt --> +<!-- and version 1.3 or later is part of all distributions of --> +<!-- LaTeX version 2005/12/01 or later. --> +<!-- --> +<!-- 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(FlexGlobals.topLevelApplication.parameters);" + applicationComplete="initApp();" + 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; + seek(0); + if(autoPlay) play(); + } + } + + import mx.core.FlexGlobals; + [Bindable] private var delay:Number=5; + [Bindable] private var autoPlay:Boolean=false; + private var xmlfile:String; + + 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; + [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.toString()]=Img1.rotation/90; + } else { + n==0 ? Img2.rotation=0 : Img2.rotation+=90*Math.floor(n); + Img2.rotation%=360; + rotations[slideshowXML.Img[idx].URL.toString()]=Img2.rotation/90; + } + } + + private var forcedByUsr: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; + curFile=slideshowXML.Img[idx].URL.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; + } + }); + + rotations=new Object(); + timeoutTimer=new Timer(30000, 1); + timeoutTimer.addEventListener(TimerEvent.TIMER, onAnyError); + curFile=xmlfile; setXML(xmlfile); + } + + 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(caption.text==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.toString())) + curRot=rotations[slideshowXML.Img[idx].URL.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(slideshowXML.Img[idx].URL.toString()); + } + 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();" + mouseOut="if(anim.isPlaying) anim.reverse(); else anim.play(null,true);" + /> +</s:Application> diff --git a/Master/texmf-dist/source/latex/media9/players/VPlayer.mxml b/Master/texmf-dist/source/latex/media9/players/VPlayer.mxml index 7d73ce43b7d..d3ef5e17fad 100644 --- a/Master/texmf-dist/source/latex/media9/players/VPlayer.mxml +++ b/Master/texmf-dist/source/latex/media9/players/VPlayer.mxml @@ -4,7 +4,7 @@ <!-- a FlashPlayer-10 compatible component for playing --> <!-- FLV and MP4/H.264 video files and streams. --> <!-- --> -<!-- version 20140625 --> +<!-- version 20150511 --> <!-- --> <!-- --> <!-- The free Apache Flex 4 SDK is required to compile --> @@ -40,12 +40,12 @@ xmlns:s="library://ns.adobe.com/flex/spark" xmlns:mx="library://ns.adobe.com/flex/mx" preinitialize="initialise(FlexGlobals.topLevelApplication.parameters);" - creationComplete="init();" + applicationComplete="initApp();" backgroundAlpha="0" > <fx:Script> <![CDATA[ - [Bindable] private var scaleMode:String='stretch'; + [Bindable] private var scaleMode:String='letterbox'; [Bindable] private var source:String; [Bindable] private var autoPlay:Boolean=false; [Bindable] private var autoRewind:Boolean=false; @@ -249,8 +249,7 @@ return vidDisp.muted; } - private function init():void { - this.setFocus(); + private function initApp():void { this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); this.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); this.addEventListener(Event.ENTER_FRAME, onEnterFrame); @@ -267,37 +266,73 @@ 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("Seek, [\u2190]/[\u2192]", true, 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"/> + <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="{autoRewind}" loop="{loop}" - mouseDown="if(stepping){vidDisp.play();}else{vidDisp.pause();}this.setFocus();" - mouseUp="if(vidComplete) vidDisp.seek(0);if(!stepping){vidDisp.play();}" - mediaPlayerStateChange="onStateChange(event);" - complete="vidComplete=true;" - durationChange="vidDisp.seek(0);" - currentTimeChange="onCurrentTimeChange(event);" + 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)" + 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" + horizontalCenter="0" bottom="0" labelPlacement="center" + id="playProgress" alpha="0.5" + visible="false" + /> + + <s:Button alpha="0" width="100%" height="100%" + mouseDown="if(stepping){vidDisp.play();}else{vidDisp.pause();}" + mouseUp="if(vidComplete) vidDisp.seek(0);if(!stepping){vidDisp.play();}" /> </s:Application> diff --git a/Master/texmf-dist/source/latex/media9/players/VPlayer9.mxml b/Master/texmf-dist/source/latex/media9/players/VPlayer9.mxml index 02c684ffe32..7d748112a95 100644 --- a/Master/texmf-dist/source/latex/media9/players/VPlayer9.mxml +++ b/Master/texmf-dist/source/latex/media9/players/VPlayer9.mxml @@ -4,7 +4,7 @@ <!-- a FlashPlayer-9 compatible component for playing --> <!-- FLV and MP4/H.264 video files and streams. --> <!-- --> -<!-- version 20140625 --> +<!-- version 20150511 --> <!-- --> <!-- Copyright (C) 2012-today Alexander Grahn --> <!-- --> @@ -25,7 +25,7 @@ <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" preinitialize="initialise(Application.application.parameters);" - creationComplete="init();" + applicationComplete="initApp();" backgroundAlpha="0" paddingTop="0" paddingBottom="0" paddingLeft="0" paddingRight="0" @@ -38,7 +38,7 @@ [Bindable] private var loop:Boolean=false; [Bindable] private var vol:Number=0.75; [Bindable] private var stepping:Boolean=false; - [Bindable] private var letterbox:Boolean=false; + [Bindable] private var keepAspect:Boolean=true; private var vidComplete:Boolean=false; private var deltaSeek:Number; private var playheadTime:Number; @@ -52,11 +52,11 @@ 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.stepping){stepping=flashVars.stepping} - if(flashVars.scaleMode=='letterbox'){letterbox=true} + if(flashVars.autoPlay=='true') autoPlay=true; + if(flashVars.loop=='true') loop=true; + if(flashVars.volume) vol=Number(flashVars.volume); + if(flashVars.stepping) stepping=flashVars.stepping; + if(flashVars.scaleMode && flashVars.scaleMode!='letterbox') keepAspect=false; } private function onProgress(event:ProgressEvent):void { @@ -239,8 +239,7 @@ return muted; } - private function init():void { - this.setFocus(); + private function initApp():void { this.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown); this.addEventListener(KeyboardEvent.KEY_UP, onKeyUp); this.addEventListener(Event.ENTER_FRAME, onEnterFrame); @@ -257,6 +256,39 @@ 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("Seek, [\u2190]/[\u2192]", true, 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> @@ -267,12 +299,10 @@ <mx:VideoDisplay id="vidDisp" - width="100%" height="100%" maintainAspectRatio="{letterbox}" + width="100%" height="100%" maintainAspectRatio="{keepAspect}" backgroundAlpha="0" borderThickness="0" source="{source}" volume="{vol}" autoPlay="{autoPlay}" autoRewind="{loop}" - mouseDown="if(stepping){vidDisp.play();}else{vidDisp.pause();}this.setFocus();" - mouseUp="if(vidComplete) vidDisp.playheadTime=0;if(!stepping){vidDisp.play();}" stateChange="onStateChange(event);" complete="vidComplete=true;" rewind="vidDisp.play();" @@ -291,4 +321,10 @@ 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="if(stepping){vidDisp.play();}else{vidDisp.pause();}" + mouseUp="if(vidComplete) vidDisp.playheadTime=0;if(!stepping){vidDisp.play();}" + /> </mx:Application> diff --git a/Master/texmf-dist/tex/latex/media9/media9.sty b/Master/texmf-dist/tex/latex/media9/media9.sty index 5546fa06c3f..f655deaa747 100644 --- a/Master/texmf-dist/tex/latex/media9/media9.sty +++ b/Master/texmf-dist/tex/latex/media9/media9.sty @@ -43,8 +43,8 @@ \RequirePackage{atenddvi} \RequirePackage{tikz} -\def\g@mix@date@tl{2015/03/11} -\def\g@mix@version@tl{0.51} +\def\g@mix@date@tl{2015/05/11} +\def\g@mix@version@tl{0.52} \def\g@mix@liiikerneldate{2014/07/20} \def\g@mix@liiipkgdate{2014/07/20} diff --git a/Master/texmf-dist/tex/latex/media9/players/APlayer.swf b/Master/texmf-dist/tex/latex/media9/players/APlayer.swf Binary files differindex 6f1801bfacd..5c930305d35 100644 --- a/Master/texmf-dist/tex/latex/media9/players/APlayer.swf +++ b/Master/texmf-dist/tex/latex/media9/players/APlayer.swf diff --git a/Master/texmf-dist/tex/latex/media9/players/APlayer9.swf b/Master/texmf-dist/tex/latex/media9/players/APlayer9.swf Binary files differindex fccfc07adee..d224b86ebc1 100644 --- a/Master/texmf-dist/tex/latex/media9/players/APlayer9.swf +++ b/Master/texmf-dist/tex/latex/media9/players/APlayer9.swf diff --git a/Master/texmf-dist/tex/latex/media9/players/SlideShow.swf b/Master/texmf-dist/tex/latex/media9/players/SlideShow.swf Binary files differnew file mode 100644 index 00000000000..0c08a04224e --- /dev/null +++ b/Master/texmf-dist/tex/latex/media9/players/SlideShow.swf diff --git a/Master/texmf-dist/tex/latex/media9/players/VPlayer.swf b/Master/texmf-dist/tex/latex/media9/players/VPlayer.swf Binary files differindex 0bb9c638c44..0b08b429e79 100644 --- a/Master/texmf-dist/tex/latex/media9/players/VPlayer.swf +++ b/Master/texmf-dist/tex/latex/media9/players/VPlayer.swf diff --git a/Master/texmf-dist/tex/latex/media9/players/VPlayer9.swf b/Master/texmf-dist/tex/latex/media9/players/VPlayer9.swf Binary files differindex f2b23daedef..4f422ecb261 100644 --- a/Master/texmf-dist/tex/latex/media9/players/VPlayer9.swf +++ b/Master/texmf-dist/tex/latex/media9/players/VPlayer9.swf |