% Copyright 2004 Alexander Grahn
%
% This material is subject to the LaTeX Project Public License. See
%   http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html
% for the details of that license.
%
% This package allows inclusion of multimedia content into PDF files
% following Adobe's PDF-1.5 and 1.6 specifications.
%

\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{movie15}[2005/10/13]
\RequirePackage{keyval}
\RequirePackage{ifthen}

\newboolean{@MXV@iiiDfeat}% enable 3D features from PDF-1.6 spec?
\newboolean{@MXV@iiid}%set to true if a 3D file is beeing embedded

\DeclareOption{3D}{%
  \setboolean{@MXV@iiiDfeat}{true}%
}

\DeclareOption*{\PackageWarning{movie15}{Unknown Option \CurrentOption}}
\ProcessOptions\relax

%find out which LaTeX is being used
\newboolean{@MXV@pdf}%
\ifthenelse{\isundefined{\pdfoutput}}{%
  %latex with dvips
  \setboolean{@MXV@pdf}{false}%
}{%
  \ifthenelse{\number\pdfoutput<1}{%
    %pdflatex in DVI mode
    \setboolean{@MXV@pdf}{false}%
  }{%
    %pdflatex in PDF mode
    \ifthenelse{\pdftexversion<120}{%
      \PackageError{movie15}{%
        pdfTeX/pdfLaTeX version >= 1.20 required for direct PDF output
      }{%
        Try to install a more recent version!
      }%
    }{%
      \setboolean{@MXV@pdf}{true}%
    }%
  }%
}

%for conditionals where \ifthenelse doesn't work
\gdef\@MXV@if#1{\csname if#1\endcsname}%

%maintaining a counter for absolute page number
\RequirePackage{everyshi}%
\newcount\@MXV@page%
\EveryShipout{%
  \global\advance\@MXV@page by 1%
}

%define our own label making commands
\def\@MXV@newlabel#1#2{{%
  \global\expandafter\def\csname#1\endcsname{#2}}}%

\def\@MXV@getlabelvalue#1{%
  \expandafter\ifx\csname#1\endcsname\relax%
    undefined%
  \else%
    \csname#1\endcsname%
  \fi%
}%

%macro for writing labels to external *.aux file
\def\@MXV@labeltoaux#1#2{%
  \@bsphack\protected@write\@auxout{}{%
    \string\@MXV@newlabel{#1}{#2}%
  }\@esphack%
  \ifthenelse{\equal{\@MXV@getlabelvalue{#1}}{undefined}}{%
    \ifthenelse{\isundefined{\@MXV@warning}}{%issue warning only once, at end
      \gdef\@MXV@warning{}%                                       of document
      \AtEndDocument{%
        \PackageWarningNoLine{movie15}{%
        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak
        @@ Rerun to get cross-references right! @@\MessageBreak
        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}%
      }%
    }{}%
  }{}%
}%
%
\ifthenelse{\boolean{@MXV@pdf}}{%
  %for storing pdf object numbers (must be counters)
  \newcount\@MXV@adict%
  \newcount\@MXV@aadict%
  %
  %returns pdf page object number
  \def\@MXV@pdfpageref#1{%
    \expandafter\ifx\csname#1\endcsname\relax%
      0%
    \else%
      \expandafter\pdfpageref\csname#1\endcsname\space%
    \fi%
  }%
}{%
  \PassOptionsToPackage{pdfmark}{hyperref}%
  %counter for absolute number of movierefs
  \newcount\@MXV@links
}

%counter for absolute number of inclusions,
%used for labelling each annotation
\newcount\@MXV@includes

%measuring things
%textbox
\newdimen\@MXV@width
\newdimen\@MXV@height
\newdimen\@MXV@depth
\newdimen\@MXV@totalheight
\newdimen\@MXV@@boxdepth
%for centring the textbox within display box
\newdimen\@MXV@traiselen
\newdimen\@MXV@braiselen
%for compatibility options
\newdimen\@MXV@start
\newdimen\@MXV@end

%stores textbox given as argument to text option
\newsavebox{\@MXV@textbox}

%some booleans we need
\newboolean{@MXV@autoplay}
\newboolean{@MXV@autostop}
\newboolean{@MXV@autoresume}
\newboolean{@MXV@autopause}
\newboolean{@MXV@mouse}%mouse interaction
\newboolean{@MXV@inline}%inline movie data
\newboolean{@MXV@attachment}%make embedded file extractable?
\newboolean{@MXV@externalviewer}%if true, screen annot will be removed
\newboolean{@MXV@url}
\newboolean{@MXV@boxopt}%true if text option is set
\newboolean{@MXV@textoverposter}
\newboolean{@MXV@runposter}% render poster from movie at runtime
\newboolean{@MXV@linkplay}% for \movieref command
\newboolean{@MXV@linkpause}
\newboolean{@MXV@linkresume}
\newboolean{@MXV@linkstop}
\newboolean{@MXV@linkclose}
\newboolean{@MXV@linkreset}

%macro to reset all macros and booleans
\def\@MXV@reset{%
  \setboolean{@MXV@autoplay}{false}%
  \setboolean{@MXV@autostop}{true}%
  \setboolean{@MXV@autoresume}{false}%
  \setboolean{@MXV@autopause}{false}%
  \setboolean{@MXV@mouse}{false}%
  \setboolean{@MXV@inline}{true}%
  \setboolean{@MXV@attachment}{true}%
  \setboolean{@MXV@externalviewer}{false}%
  \setboolean{@MXV@url}{false}%
  \setboolean{@MXV@boxopt}{false}%
  \setboolean{@MXV@textoverposter}{true}%
  \setboolean{@MXV@runposter}{false}%
  \setboolean{@MXV@linkplay}{true}%
  \setboolean{@MXV@linkpause}{false}%
  \setboolean{@MXV@linkresume}{false}%
  \setboolean{@MXV@linkstop}{false}%
  \setboolean{@MXV@linkclose}{false}%
  \setboolean{@MXV@linkreset}{false}%
  \gdef\@MXV@label{}% for movieref
  \gdef\@MXV@mime{@MXV@auto}%
  \gdef\@MXV@fsentry{}%
  \gdef\@MXV@repeat{}%
  \gdef\@MXV@@repeat{}%
  \gdef\@MXV@volume{100}%
  \gdef\@MXV@@volume{}%
  \gdef\@MXV@ctrls{}%
  \gdef\@MXV@@ctrls{}%
  \gdef\@MXV@palindrome{}%
  \gdef\@MXV@rate{}%
  \gdef\@MXV@startat{}%
  \gdef\@MXV@endat{}%
  \gdef\@MXV@poevent{}%
  \gdef\@MXV@pcevent{}%
  \gdef\@MXV@box##1##2##3{\raisebox{0pt}[##2][##3]{\makebox[##1]{}}}%
  \setlength{\@MXV@depth}{0pt}%
  \setlength{\@MXV@height}{0pt}%
  \setlength{\@MXV@width}{0pt}%
  \setlength{\@MXV@braiselen}{0pt}%
  \setlength{\@MXV@traiselen}{0pt}%
  \gdef\@MXV@boxdepth{}%
  \gdef\@MXV@boxheight{}%
  \gdef\@MXV@boxwidth{}%
  %
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \gdef\@MXV@aac{30}% aperture angle of camera
    \gdef\@MXV@background{}%
    \gdef\@MXV@jscriptiiidfile{}%
    \gdef\@MXV@coo{0 0 0}% centre of orbit
    \gdef\@MXV@ctoc{0 -1 0}% centre of orbit to camera vector
    \gdef\@MXV@roo{0}% radius of orbit
    \gdef\@MXV@viewsfile{}% file containing views of the 3D object
    \setboolean{@MXV@viewsprovided}{false}%
    \setboolean{@MXV@defaultviewprovided}{false}%
    %show controls for 3D content by default, otherwise the 3D model
    %would be noninteractive, i. e. would not respond to mouse events
    \setboolean{@MXV@iiidctrls}{true}%
  }{}%
}%

%missing package error message
\def\@MXV@missing#1{%
    \PackageError{movie15}{%
      Package `#1' has not been loaded yet
  }{%
    Put the line `\protect\usepackage{#1}' somewhere after
    `\protect\usepackage{movie15}' to the preamble of your
    document!
  }%
}

%3D-need-be-enabled error message
\def\@MXV@neediiiD{%
  \PackageError{movie15}{%
    If you wish to embed 3D objects, enable the\MessageBreak
    3D feature first by passing option `3D' to movie15!\MessageBreak
    Make sure the `fp' package for fixed point calculus\MessageBreak
    is installed in your TeX system
  }{Package `fp' is available from CTAN.}%
}

%macro to guess the mime type of the media file
\def\@MXV@guessmime#1{%
  \filename@parse{#1}%
  \ifthenelse{\equal{\filename@ext}{aiff}\OR\equal{\filename@ext}{AIFF}\OR%
              \equal{\filename@ext}{aif}\OR\equal{\filename@ext}{AIF}\OR%
              \equal{\filename@ext}{aifc}\OR\equal{\filename@ext}{AIFC}}{%
    \gdef\@MXV@mime{audio/aiff}%
  }{%
  \ifthenelse{\equal{\filename@ext}{wav}\OR\equal{\filename@ext}{WAV}}{%
    \gdef\@MXV@mime{audio/wav}%
  }{%
  \ifthenelse{\equal{\filename@ext}{wma}\OR\equal{\filename@ext}{WMA}}{%
    \gdef\@MXV@mime{audio/x-ms-wma}%
  }{%
  \ifthenelse{\equal{\filename@ext}{wmv}\OR\equal{\filename@ext}{WMV}}{%
    \gdef\@MXV@mime{video/x-ms-wmv}%
  }{%
  \ifthenelse{\equal{\filename@ext}{au}\OR\equal{\filename@ext}{AU}\OR%
              \equal{\filename@ext}{snd}\OR\equal{\filename@ext}{SND}}{%
    \gdef\@MXV@mime{audio/basic}%
  }{%
  \ifthenelse{\equal{\filename@ext}{mid}\OR\equal{\filename@ext}{MID}\OR%
              \equal{\filename@ext}{rmi}\OR\equal{\filename@ext}{RMI}}{%
    \gdef\@MXV@mime{audio/midi}%
  }{%
  \ifthenelse{\equal{\filename@ext}{mov}\OR\equal{\filename@ext}{MOV}\OR%
              \equal{\filename@ext}{qt}\OR\equal{\filename@ext}{QT}}{%
    \gdef\@MXV@mime{video/quicktime}%
  }{%
  \ifthenelse{\equal{\filename@ext}{mp3}\OR\equal{\filename@ext}{MP3}\OR%
              \equal{\filename@ext}{m3u}\OR\equal{\filename@ext}{M3U}}{%
    \gdef\@MXV@mime{audio/x-mp3}%
  }{%
  \ifthenelse{\equal{\filename@ext}{mp4}\OR\equal{\filename@ext}{MP4}}{%
    \gdef\@MXV@mime{video/mp4}%
  }{%
  \ifthenelse{\equal{\filename@ext}{avi}\OR\equal{\filename@ext}{AVI}}{%
    \gdef\@MXV@mime{video/avi}%
  }{%
  \ifthenelse{\equal{\filename@ext}{mpeg}\OR\equal{\filename@ext}{MPEG}\OR%
              \equal{\filename@ext}{mpg}\OR\equal{\filename@ext}{MPG}}{%
    \gdef\@MXV@mime{video/mpeg}%
  }{%
  \ifthenelse{\equal{\filename@ext}{smil}\OR\equal{\filename@ext}{SMIL}}{%
    \gdef\@MXV@mime{application/smil}%
  }{%
  \ifthenelse{\equal{\filename@ext}{swf}\OR\equal{\filename@ext}{SWF}}{%
    \gdef\@MXV@mime{application/x-shockwave-flash}%
  }{%
  \ifthenelse{\equal{\filename@ext}{u3d}\OR\equal{\filename@ext}{U3D}}{%
    \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
      \setboolean{@MXV@iiid}{true}%
      \gdef\@MXV@mime{model/u3d}% (unofficial)
      \gdef\@MXV@iiidsubtype{U3D}%
    }{%
      \@MXV@neediiiD%
    }%
  }{%
  \ifthenelse{\equal{\filename@ext}{ra}\OR\equal{\filename@ext}{RA}\OR%
              \equal{\filename@ext}{ram}\OR\equal{\filename@ext}{RAM}\OR%
              \equal{\filename@ext}{rm}\OR\equal{\filename@ext}{RM}}{%
    \gdef\@MXV@mime{audio/x-pn-realaudio}%
  }{%
    \PackageError{movie15}{%
      I couldn't determine MIME type of file:\MessageBreak`#1':\MessageBreak
      Unknown file name extension: `\filename@ext'
    }{%
      When using media files of unknown type or with a\MessageBreak
      non-standard file name extension, the MIME type must\MessageBreak
      explicitly be specified. Try option `mimetype=<mime type>'!
    }%
  }}}}}}}}}}}}}}}%
}

\ifthenelse{\boolean{@MXV@iiiDfeat}}{% 3D related definitions and macros
  \RequirePackage{fp}% needed for fixed point calculus
  \newcount\@MXV@viewscount%counter for number of 3D views per inclusion
  \newboolean{@MXV@viewsprovided}%3d views file provided?
  \newboolean{@MXV@iiidctrls}% show controls?
  \newboolean{@MXV@defaultviewprovided}%default 3D view provided?

  %macro to compute the transformation matrix
  \def\@MXV@ciiwmatrix#1 #2 #3 #4 #5 #6 #7 {%
    % #1,#2,#3 centre of orbit coordinates (coo)
    % #4,#5,#6 centre of orbit to camera direction vector (c2c)
    % #7 orbital radius (roo)
    %
    %view vector (opposite to c2c)
    \def\@MXV@viewx{-#4}\def\@MXV@viewy{-#5}\def\@MXV@viewz{-#6}%
    %
    %normalize view vector
    \FPupn\@MXV@modulo{\@MXV@viewx{} \@MXV@viewx{} mul
      \@MXV@viewy{} \@MXV@viewy{} mul +
      \@MXV@viewz{} \@MXV@viewz{} mul + 2 swap root
    }%
    \FPupn\@MXV@viewx{\@MXV@viewx{} \@MXV@modulo{} div}%
    \FPtrunc\@MXV@viewx\@MXV@viewx{12}%
    \FPupn\@MXV@viewy{\@MXV@viewy{} \@MXV@modulo{} div}%
    \FPtrunc\@MXV@viewy\@MXV@viewy{12}%
    \FPupn\@MXV@viewz{\@MXV@viewz{} \@MXV@modulo{} div}%
    %
    %top and bottom views (@MXV@viewx == @MXV@viewy == 0) need special treatment
    \FPupn\@MXV@sumxy{\@MXV@viewx{} abs \@MXV@viewy{} abs add}%
    \FPifeq\@MXV@sumxy{0}%
      %slightly incline the view vector,
      %otherwise top and bottom views snap at 180 degrees around z-axis
      \def\@MXV@viewy{0.000000001}%
    \else%
    \fi%
    %
    %rotational axis vector (cross product of [0 0 1] & view vector)
    \def\@MXV@rotx{-\@MXV@viewy}\def\@MXV@roty{\@MXV@viewx}%
    %
    %sin of enclosed angle between [0 0 1] & view vector (from cross product)
    \FPupn\@MXV@rotsin{\@MXV@rotx{} \@MXV@rotx{} mul \@MXV@roty{} \@MXV@roty{} %
      mul + 2 swap root}%
    %
    %cos of enclosed angle between [0 0 1] & view vector (from dot product)
    \def\@MXV@rotcos{\@MXV@viewz}%
    \FPupn\@MXV@onerotcos{1 \@MXV@rotcos{} sub}% 1 - rotcos
    %
    %now we have to normalize the rot vector
    \FPupn\@MXV@rotx{\@MXV@rotx{} \@MXV@rotsin{} div}%
    \FPupn\@MXV@roty{\@MXV@roty{} \@MXV@rotsin{} div}%
    %
    %build the transformation matrix (right handed system)
    \FPupn\@MXV@element{\@MXV@rotx{} \@MXV@rotx{} mul \@MXV@onerotcos{} mul %
      \@MXV@rotcos{} add -1 mul}%
    \xdef\@MXV@matrix{\@MXV@element}%
    \FPupn\@MXV@element{%
      \@MXV@rotx{} \@MXV@roty{} mul \@MXV@onerotcos{} mul -1 mul}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
    \FPupn\@MXV@element{\@MXV@roty{} \@MXV@rotsin{} mul}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
    \FPupn\@MXV@element{\@MXV@rotx{} \@MXV@roty{} mul \@MXV@onerotcos{} mul}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
    \FPupn\@MXV@element{\@MXV@roty{} \@MXV@roty{} mul \@MXV@onerotcos{} mul %
      \@MXV@rotcos{} add}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
    \FPupn\@MXV@element{\@MXV@rotx{} \@MXV@rotsin{} mul}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
    \FPupn\@MXV@element{\@MXV@roty{} \@MXV@rotsin{} mul}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
    \FPupn\@MXV@element{\@MXV@rotx{} \@MXV@rotsin{} mul -1 mul}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@rotcos}%
    \FPupn\@MXV@element{\@MXV@viewx{} #7 abs mul -1 mul #1 add}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
    \FPupn\@MXV@element{\@MXV@viewy{} #7 abs mul -1 mul #2 add}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
    \FPupn\@MXV@element{\@MXV@viewz{} #7 abs mul -1 mul #3 add}%
    \xdef\@MXV@matrix{\@MXV@matrix\space\@MXV@element}%
  }

  %macro for parsing one line of 3D views file
  \newcommand{\@MXV@parseline}[5][]{%
    \xdef\@MXV@xname{#1}% name of the view (optional)
    \xdef\@MXV@coo{#2}%
    \xdef\@MXV@ctoc{#3}%
    \xdef\@MXV@roo{#4}%
    \xdef\@MXV@aac{#5}%
  }

  %macro for generating an array of 3D views (varray)
  \def\@MXV@buildva{%
    \ifthenelse{\boolean{@MXV@defaultviewprovided}}{%
      \global\@MXV@viewscount=1%
    }{%
      \global\@MXV@viewscount=0%
    }%
    \xdef\@MXV@varray{}% empty varray
    %
    %default view
    \edef\@MXV@args{\@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space}%
    \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix
    \xdef\@MXV@xname{Default}%
    \@MXV@viewobj% create pdf object of 3D view
    \edef\@MXV@defaultview{\@MXV@@viewobj}%
    %
    %read out 3D views file
    \IfFileExists{\@MXV@viewsfile}{%
      \edef\@MXV@endlinechar{\the\endlinechar}%
      \endlinechar=-1% suppress trailing space at input line end
      \edef\@MXV@coo{}\edef\@MXV@ctoc{}\edef\@MXV@roo{}%
      \newread\@MXV@@viewsfile%
      \openin\@MXV@@viewsfile=\@MXV@viewsfile%
      \loop%
        \read\@MXV@@viewsfile to \@MXV@inputline%
      \if\@MXV@inputline\relax\else%
        \expandafter\@MXV@parseline\@MXV@inputline%
        \edef\@MXV@args{\@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space}%
        \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix
        \global\advance\@MXV@viewscount by 1%
        \ifthenelse{\equal{\@MXV@xname}{}}{%
          \xdef\@MXV@xname{View \the\@MXV@viewscount}%
        }{}%
        \@MXV@viewobj% create pdf object of 3D view
        %append current view obj ref to VA array
        \xdef\@MXV@varray{\@MXV@varray\space\@MXV@@viewobj}%
        \setboolean{@MXV@viewsprovided}{true}%
      \repeat%
      \closein\@MXV@@viewsfile%
      \endlinechar=\@MXV@endlinechar% reset endlinechar
    }{}%
    %
    %prepend default view obj ref to VA array, if
    %explicitly given or no additional views from views file available
    \ifthenelse{\boolean{@MXV@defaultviewprovided}\OR%
    \NOT\boolean{@MXV@viewsprovided}}{%
      \xdef\@MXV@varray{\@MXV@defaultview\@MXV@varray}%
    }{}%
  }

  %following macros, including the 3D inclusion macro have driver specific
  %implementations
  \ifthenelse{\boolean{@MXV@pdf}}{%
    %pdflatex versions
    %macro for creating 3D view object
    \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
      \def\@MXV@viewobj{%
        %projection dict
        \pdfobj {<</Subtype/P/FOV \@MXV@aac/PS/Min>>}%
        \pdfrefobj\pdflastobj%
        %
        \pdfobj {<<%
          /MS/M% define the view as C2W matrix
          /CO \@MXV@roo% orbital radius
          /P \the\pdflastobj\space 0 R%
          /C2W [\@MXV@matrix]%
          /XN(\@MXV@xname)% name of the view appearing in the drop down list
          \@MXV@background%
        >>}\pdfrefobj\pdflastobj%
        \xdef\@MXV@@viewobj{\the\pdflastobj\space 0 R}%
      }%
    }{}

    %3D inclusion macro
    \def\@MXV@includeiiid#1#2#3#4{%
      %insert box or poster
      \@MXV@box{#1}{#2}{#3}%
      %
      \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
        %java script file, stream object
        \IfFileExists{\@MXV@jscriptiiidfile}{%
          \pdfobj stream file {\@MXV@jscriptiiidfile}%
          \pdfrefobj\pdflastobj%
          \xdef\@MXV@jscriptiiid{/OnInstantiate \the\pdflastobj\space 0 R}%
        }{\xdef\@MXV@jscriptiiid{}}%
        %
        %build the array of 3D views
        \@MXV@buildva%
      }{}%
      %
      %3D stream object, 3D files are always embedded inline
      \IfFileExists{#4}{%
        \pdfobj stream%
          attr {%
            /Subtype/\@MXV@iiidsubtype%
            /VA [\@MXV@varray]%
            /DV/F% use first entry in VA as default view
            \@MXV@jscriptiiid%
          }%
          file {#4}%
        \pdfrefobj\pdflastobj%
        %
        %insert FileAttachment annotation
        \ifthenelse{\boolean{@MXV@attachment}}{%
          \pdfannot width -#1 height #2 depth #3 {%
            /Subtype /FileAttachment%
            /F 0%
            /T (#4)
            /Contents (3D Object (\@MXV@mime))%
            /AP <</N<<>>/R<<>>/D<<>>>>%
            /FS <<%
              /F(#4)%
              /Type/Filespec%
              /EF << /F \the\pdflastobj\space 0 R >>%
            >>%
          }%
        }{}%
        %
      }{%
        \PackageError{movie15}{%
          File `#4' cannot be opened for embedding.\MessageBreak
          3D files are always embedded inline and must be readable
        }{%
          Make sure file `#4' exists and is readable!
        }%
      }%
      %
      %new annotation object of subtype `3D'%
      \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
        \pdfannot width -#1 height #2 depth #3 {%
          /Subtype/3D%
          /F 4% we cannot put F 5 here; bug in Reader; 3D annot would be
          /T (#4)%                disabled even if plugin were available
          /Contents (3D Object (\@MXV@mime))%
          /P \@MXV@pdfpageref{@MXV@player\the\@MXV@includes.page} 0 R%
          \@MXV@apdict%
          /3DI \if@MXV@iiidctrls true\else false\fi%
          /3DD \the\pdflastobj\space 0 R% 3D stream object
          /3DA << \@MXV@activation\@MXV@deactivation >>%
        }%
      }{}%
    }%
  }{%
    %dvips versions
    %macro for creating 3D view object and associated projection dict
    \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
      \def\@MXV@viewobj{%
        %projection dict
        \pdfmark{%
          pdfmark=/OBJ,%
          Raw={%
            /_objdef {pdict\the\@MXV@includes_\the\@MXV@viewscount}%
            /type/dict%
          }%
        }%
        \pdfmark{%
          pdfmark=/PUT,%
          Raw={%
            {pdict\the\@MXV@includes_\the\@MXV@viewscount} <<%
              /Subtype/P/FOV \@MXV@aac/PS/Min%
            >>%
          }%
        }%
        %
        \pdfmark{%
          pdfmark=/OBJ,%
          Raw={%
            /type/dict%
            /_objdef {viewobj\the\@MXV@includes_\the\@MXV@viewscount}%
          }%
        }%
        \pdfmark{%
          pdfmark=/PUT,%
          Raw={%
            {viewobj\the\@MXV@includes_\the\@MXV@viewscount} <<%
              /MS/M%
              /CO \@MXV@roo%
              /P {pdict\the\@MXV@includes_\the\@MXV@viewscount}%
              /C2W[\@MXV@matrix]%
              /XN(\@MXV@xname)%
              \@MXV@background%
            >>%
          }%
        }%
        \xdef\@MXV@@viewobj{{viewobj\the\@MXV@includes_\the\@MXV@viewscount}}%
      }%
    }{}%
    %
    %3D inclusion macro
    \def\@MXV@includeiiid#1#2#3#4{%
      \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
        %java script file, stream object
        \IfFileExists{\@MXV@jscriptiiidfile}{%
          \pdfmark{%
            pdfmark=/OBJ,%
            Raw={%
              /_objdef {jscriptiiid\the\@MXV@includes}%
              /type/stream%
            }%
          }%
          \pdfmark{%
            pdfmark=/PUT,%
            Raw={%
              {jscriptiiid\the\@MXV@includes}%
              (\@MXV@jscriptiiidfile) (r) file%
            }%
          }%
          \def\@MXV@jscriptiiid{/OnInstantiate {jscriptiiid\the\@MXV@includes}}%
        }{\def\@MXV@jscriptiiid{}}%
        %
        %build the array of 3D views
        \@MXV@buildva%
      }{}%
      %
      %3D stream object, 3D files are always embedded inline
      \IfFileExists{#4}{%
        \pdfmark{%
          pdfmark=/OBJ,%
          Raw={%
            /_objdef {iiiDfile\the\@MXV@includes}%
            /type/stream%
          }%
        }%
        \pdfmark{%
          pdfmark=/PUT,%
          Raw={%
            {iiiDfile\the\@MXV@includes} <<%
              /Subtype/\@MXV@iiidsubtype%
              /VA [\@MXV@varray]%
              /DV/F%
              \@MXV@jscriptiiid%
            >>%
          }%
        }%
        \pdfmark{%
          pdfmark=/PUT,%
          Raw={%
            {iiiDfile\the\@MXV@includes}%
            (#4) (r) file%
          }%
        }%
      }{%
        \PackageError{movie15}{%
          File `#4' cannot be opened for embedding.\MessageBreak
          3D files are always embedded inline and must be readable
        }{%
          Make sure file `#4' exists and is readable!
        }%
      }%
      %
      %insert FileAttachment annotation
      \ifthenelse{\boolean{@MXV@attachment}}{%
        \makebox[0pt][l]{%
          \pdfmark[\@MXV@box{#1}{#2}{#3}]{%
            pdfmark=/ANN,%
            Subtype=/FileAttachment,%
            Raw={%
              /F 0%
              /T (#4)
              /Contents (3D Object (\@MXV@mime))%
              /AP <</N<<>>/R<<>>/D<<>>>>%
              /FS <<%
                /F(#4)%
                /Type/Filespec%
                /EF <</F {iiiDfile\the\@MXV@includes}>>%
              >>%
            }%
          }%
        }%
      }{}%
      %annotation object of subtype `3D'
      \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
        \pdfmark[\@MXV@box{#1}{#2}{#3}]{%
          pdfmark=/ANN,%
          Subtype=/3D,%
          Raw={%
            /F 4%
            /T (#4)
            /Contents (3D Object (\@MXV@mime))%
            /P {ThisPage}%
            \@MXV@apdict%
            /3DI \if@MXV@iiidctrls true\else false\fi%
            /3DD {iiiDfile\the\@MXV@includes}%
            /3DA << \@MXV@activation\@MXV@deactivation >>%
          }%
        }%
      }{}%
    }%
  }%
}{}

%settings for newly opened media players
\def\@MXV@settings#1#2#3#4#5#6#7{%
  var settings = {%
    privateData: {%
      paused: false
    },
    autoPlay: false,
    visible: false,
    volume: #7
    #1% showUI (controls)
    #2% palindrome
    #3% repeat
    #4% rate
    #5% startAt
    #6% endAt
  };
}

%JavaScript event handler routines for 2D media activation
\def\@MXV@events#1#2#3{% #1: playerid, #2: mouse?, #3: autoplay?
  var events = new app.media.Events({%
    %on focus change from one movie to another, events are fired in the
    %following order: (1) onBlur, (2) onFocus, (3) afterBlur, (4) afterFocus
    onBlur: function (e) {%
      if(focusonplayer > 0){%
        focusonplayer = 0;
      }
    },
    afterBlur: function (e) {%
      %only resume if we click outside of any media
      if(focusonplayer == 0){%
        try{e.target.play();}catch(e){}
      }
    },
    onFocus: function (e) {%
      focusonplayer = #1;
    },
    afterFocus: function (e) {%
      if(!e.target.isPlaying){%play on click if paused
        try{
          e.target.play();
          if(!e.target.isPlaying){%still not playing?!
            %sometimes play() fails, in particular if the movie has reached
            %its end while having the focus; but this works:
            e.target.seek(e.target.settings.startAt);
            e.target.play();
          }
        }
        catch (e){}
      }
      \@MXV@if{#2}%
      else{%
        %media can only be paused if mouse option is set
        try{e.target.pause();}catch (e){}
      }
      \fi%
      e.target.visible = true;
    },
    onPlay: function (e) {%
      e.target.settings.privateData.paused = false;
    },
    onPause: function (e) {%
      e.target.settings.privateData.paused = true;
    },
    afterReady: function (e) {%
      try{
        e.target.play();
        e.target.pause();
        e.target.stop();
        e.target.settings.privateData.paused = false;
        e.target.seek(e.target.settings.startAt);
        e.target.visible = true;
        \@MXV@if{#3} e.target.play();\fi
      }
      catch (e){}
    }
  });
}%

%output driver specific implementations of the 2D inclusion macro
\ifthenelse{\boolean{@MXV@pdf}}{%
  %pdfLaTeX version
  \def\@MXV@includemovie#1#2#3#4{%
    %insert box or poster
    \@MXV@box{#1}{#2}{#3}%
    %
    \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
      %new action dict
      \pdfobj reserveobjnum%
      \@MXV@adict=\pdflastobj%
      %
      %new additional actions dict
      \pdfobj reserveobjnum%
      \@MXV@aadict=\pdflastobj%
      %
    }{}%
    %embedded file entry `/EF'
    \ifthenelse{\boolean{@MXV@inline}}{%
      \IfFileExists{#4}{%
        \pdfobj stream file {#4}%
        \pdfrefobj\pdflastobj%
        \edef\@MXV@efentry{%
          /EF << /F \the\pdflastobj\space 0 R >>%
        }%
      }{%
        \PackageError{movie15}{%
          File `#4' cannot be opened for embedding.\MessageBreak
          Did you forget to set option `url' or `inline=false'?
        }{%
          Try any of the options `url' or `inline=false'!
        }%
      }%
    }{\def\@MXV@efentry{}}%
    %
    %new file specification object
    \pdfobj {<<%
      /F(#4)%
      \@MXV@fsentry%
      \@MXV@efentry%
      /Type/Filespec%
    >>}\pdfrefobj\pdflastobj%
    \edef\@MXV@filespec{\the\pdflastobj}%
    %
    %insert FileAttachment annotation
    \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@attachment}}{%
      \pdfannot width -#1 height #2 depth #3 {%
        /Subtype /FileAttachment%
        /F 0%
        /T (#4)
        /Contents (Media File (\@MXV@mime))%
        /AP <</N<<>>/R<<>>/D<<>>>>%
        /FS \@MXV@filespec\space 0 R%
      }%
    }{}%
    %
    \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
      %new annotation object of subtype `Screen'%
      \pdfannot width -#1 height #2 depth #3 {%
        /Subtype /Screen%
        /Border [0 0 0]% no border (PDF-1.1)
        /BS <</Type/Border/S/S/W 0>>% no border (PDF-1.5)
        /F 5% disable annot if multimedia is not available
        /T (#4)
        /Contents (Media File (\@MXV@mime))%
        /P \@MXV@pdfpageref{@MXV@player\the\@MXV@includes.page} 0 R%
        /A \the\@MXV@adict\space 0 R%
        /AA \the\@MXV@aadict\space 0 R%
        \@MXV@apdict%
      }\edef\@MXV@screenannot{\the\pdflastannot}%
      %label for later annot obj number determination
      \ifx\@MXV@label\@empty\else%
        \@MXV@labeltoaux{@MXV@\@MXV@label.annot}{\@MXV@screenannot}%
      \fi%
      %
      %new media clip object of subtype `Media Clip Data' (/S/MCD)
      \pdfobj {<<%
        /D \@MXV@filespec\space 0 R%
        /P <</TF(TEMPACCESS)>>%
        /S/MCD%
        /CT (\@MXV@mime)%
      >>}\pdfrefobj\pdflastobj%
      %
      %new rendition object of subtype `Media Rendition' (/S/MR)
      \pdfobj {<<%
        /C \the\pdflastobj\space 0 R%
        /S/MR%
        /P <<%
          /BE <<%
            /F 2%
            \@MXV@@repeat\@MXV@@volume\@MXV@@ctrls%
            /D <</S /F>>%movie remains opened
          >>%
        >>%
      >>}\edef\@MXV@mediarendition{\the\pdflastobj}\pdfrefobj\pdflastobj%
      %label for later rendition obj number determination
      \ifx\@MXV@label\@empty\else%
        \@MXV@labeltoaux{@MXV@\@MXV@label.rendition}{\@MXV@mediarendition}%
      \fi%
      %
      %action dictionary
      \pdfobj useobjnum \@MXV@adict {<<%
        /R \@MXV@mediarendition\space 0 R%
        /S/Rendition%
        /OP 0% fallback if /JS doesn't work or is empty
        \@MXV@activationjsentry%
        /AN \@MXV@screenannot\space 0 R%
      >>}\pdfrefobj\pdflastobj%
      %
      %create play/stop/resume/pause actions
      \pdfobj {<<%
        /R \@MXV@mediarendition\space 0 R%
        /S/Rendition%
        \@MXV@pageopenopentry% /OP fallback if /JS doesn't work
        \@MXV@pageopenjsentry%
        /AN \@MXV@screenannot\space 0 R%
      >>}\edef\@MXV@pageopenaction{\the\pdflastobj}\pdfrefobj\pdflastobj%
      %
      \pdfobj {<<%
        /R \@MXV@mediarendition\space 0 R%
        /S/Rendition%
        \@MXV@pagecloseopentry%
        \@MXV@pageclosejsentry%
        /AN \@MXV@screenannot\space 0 R%
      >>}\edef\@MXV@pagecloseaction{\the\pdflastobj}\pdfrefobj\pdflastobj%
      %
      %populate additional actions dictionary
      \pdfobj useobjnum \@MXV@aadict {<<%
        /PO \@MXV@pageopenaction\space 0 R%
        /PC \@MXV@pagecloseaction\space 0 R%
      >>}\pdfrefobj\pdflastobj%
    }{}%
  }%
}{%
  %dvips version
  \def\@MXV@includemovie#1#2#3#4{%
    %insert FileAttachment annotation
    \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@attachment}}{%
      \makebox[0pt][l]{%
        \pdfmark[\@MXV@box{#1}{#2}{#3}]{%
          pdfmark=/ANN,%
          Subtype=/FileAttachment,%
          Raw={%
            /F 0%
            /T (#4)
            /Contents (Media File (\@MXV@mime))%
            /AP <</N<<>>/R<<>>/D<<>>>>%
            /FS {filespec\the\@MXV@includes}%
          }%
        }%
      }%
    }{}%
    %
    \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
      %new annotation object of subtype `Screen'%
      \pdfmark[\@MXV@box{#1}{#2}{#3}]{%
        pdfmark=/ANN,%
        Subtype=/Screen,%
        Border={0 0 0},%
        Raw={%
          /_objdef {screenannot\the\@MXV@includes}%
          /F 5%
          /T (#4)
          /Contents (Media File (\@MXV@mime))%
          /BS <</W 0/Type/Border/S/S>>%
          /P {ThisPage}%
          /AA {aadict\the\@MXV@includes}%
          \@MXV@apdict%
        }%
      }%
      %
      %entire action entry moved outside screen annotation
      %to workaround a ghostscript bug
      \pdfmark{%
        pdfmark=/PUT,%
        Raw={%
          {screenannot\the\@MXV@includes} <<%
            /A <<%
              /R {mediarendition\the\@MXV@includes}%
              /S/Rendition%
              /OP 0% fallback, if /JS doesn't work or is empty
              \@MXV@activationjsentry%
              /AN {screenannot\the\@MXV@includes}%
            >>%
          >>%
        }%
      }%
      %
      %new rendition object of subtype `Media Rendition' (/S/MR)
      \pdfmark{%
        pdfmark=/OBJ,%
        Raw={%
          /type/dict%
          /_objdef {mediarendition\the\@MXV@includes}%
        }%
      }%
      \pdfmark{%
        pdfmark=/PUT,%
        Raw={%
          {mediarendition\the\@MXV@includes} <<%
            /C {mediaclipdata\the\@MXV@includes}%
            /S/MR%
            /P <<%Media Play Parameters
              /BE <<%Parameters need only be honored by the player in
                  %the best effort sense
                /F 2%scale media's width and height to fit the
                   %annotation rectangle
                \@MXV@@repeat\@MXV@@volume\@MXV@@ctrls%
                /D <</S /F>>%movie remains opened
              >>%
            >>%
          >>%
        }%
      }%
      %
      %new media clip object of subtype `Media Clip Data' (/S/MCD)
      \pdfmark{%
        pdfmark=/OBJ,%
        Raw={%
          /_objdef {mediaclipdata\the\@MXV@includes}%
          /type/dict%
        }%
      }%
      \pdfmark{%
        pdfmark=/PUT,%
        Raw={%
          {mediaclipdata\the\@MXV@includes} <<%
            /D {filespec\the\@MXV@includes}%
            /P <</TF(TEMPACCESS)>>%
            /S/MCD%
            /CT (\@MXV@mime)% mime type
          >>%
        }%
      }%
    }{}%
    %
    %new file specification object
    \pdfmark{%
      pdfmark=/OBJ,%
      Raw={%
        /_objdef {filespec\the\@MXV@includes}%
        /type/dict%
      }%
    }%
    \pdfmark{%
      pdfmark=/PUT,%
      Raw={%
        {filespec\the\@MXV@includes} <<%
          \@MXV@fsentry
          /F(#4)% file name
          /Type/Filespec%
        >>%
      }%
    }%
    %
    %embedded file entry `/EF'
    \ifthenelse{\boolean{@MXV@inline}}{%
      \IfFileExists{#4}{%
        %new stream object
        \pdfmark{%
          pdfmark=/OBJ,%
          Raw={%
            /_objdef {fstream\the\@MXV@includes}%
            /type/stream%
          }%
        }%
        \pdfmark{%
          pdfmark=/PUT,%
          Raw={%
            {fstream\the\@MXV@includes}%
            (#4) (r) file% read in file contents
          }%
        }%
        \pdfmark{%
          pdfmark=/PUT,%
          Raw={%
            {fstream\the\@MXV@includes} <<%
              /Type/EmbeddedFile%
            >>%
          }%
        }%
        % put the embedded file entry into file spec object
        \pdfmark{%
          pdfmark=/PUT,%
          Raw={%
            {filespec\the\@MXV@includes} <<%
              /EF << /F {fstream\the\@MXV@includes} >>%
            >>%
          }%
        }%
      }{%
        \PackageError{movie15}{%
          File `#4' cannot be opened for embedding.\MessageBreak
          Did you forget to set option `url' or `inline=false'?
        }{%
          Try any of the options `url' or `inline=false'!
        }%
      }%
    }{}%
    %
    \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
      %create actions for page open/close events
      \pdfmark{%
        pdfmark=/OBJ,%
        Raw={%
          /_objdef {pageopenaction\the\@MXV@includes}%
          /type/dict%
        }%
      }%
      \pdfmark{%
        pdfmark=/PUT,%
        Raw={%
          {pageopenaction\the\@MXV@includes} <<%
            /R {mediarendition\the\@MXV@includes}%
            /S/Rendition%
            \@MXV@pageopenopentry% /OP fallback, if /JS doesn't work
            \@MXV@pageopenjsentry%
            /AN {screenannot\the\@MXV@includes}%
          >>%
        }%
      }%
      \pdfmark{%
        pdfmark=/OBJ,%
        Raw={%
          /_objdef {pagecloseaction\the\@MXV@includes}%
          /type/dict%
        }%
      }%
      \pdfmark{%
        pdfmark=/PUT,%
        Raw={%
          {pagecloseaction\the\@MXV@includes} <<%
            /R {mediarendition\the\@MXV@includes}%
            /S/Rendition%
            \@MXV@pagecloseopentry%
            \@MXV@pageclosejsentry%
            /AN {screenannot\the\@MXV@includes}%
          >>%
        }%
      }%
      %
      %create and populate additional actions dictionary, always add entries
      %for page open/close events
      \pdfmark{%
        pdfmark=/OBJ,%
        Raw={%
          /type/dict%
          /_objdef {aadict\the\@MXV@includes}%
        }%
      }%
      %
      \pdfmark{%
        pdfmark=/PUT,%
        Raw={%
          {aadict\the\@MXV@includes} <<%
            /PO {pageopenaction\the\@MXV@includes}%
            /PC {pagecloseaction\the\@MXV@includes}%
          >>%
        }%
      }%
    }{}%
  }%
}

%definition of user command `\includemovie'
\newcommand{\includemovie}[4][]{%
  \leavevmode%
  \global\advance\@MXV@includes by 1%increment counter
  \@MXV@reset% all macros and options
  \setkeys{movie15}{#1}% parse options
  %guess the mime type based on the filename extension
  \ifthenelse{\equal{\@MXV@mime}{@MXV@auto}}{\@MXV@guessmime{#4}}{}%
  %
  \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
    %label this annotation for later page number determination (if pdfLaTeX or
    %                                                if `label' option is set)
    \ifthenelse{\boolean{@MXV@pdf}\OR\NOT\equal{\@MXV@label}{}}{%
      \@MXV@labeltoaux{@MXV@player\the\@MXV@includes.page}{%
                                     \noexpand\the\@MXV@page}%
    }{}%
    %
    %test for hyperref package
    \ifthenelse{\NOT\boolean{@MXV@pdf}\AND\isundefined{\pdfmark}}{%
      \@MXV@missing{hyperref}%
    }{}%
    %
    %depending on options do content specific settings
    \ifthenelse{\boolean{@MXV@iiiDfeat}\AND\boolean{@MXV@iiid}}{%
      % #### 3D ####
      \ifthenelse{\boolean{@MXV@autoplay}\OR\boolean{@MXV@autoresume}}{%
        \def\@MXV@activation{/A/PV/AIS/L}% open 3D object, run animation
      }{%
        \ifthenelse{\boolean{@MXV@runposter}}{%
          \def\@MXV@activation{/A/PV/AIS/I}%open 3D obj but don't run animation
        }{%
          \def\@MXV@activation{/A/XA}% explicit activation by user
        }%
      }%
      \ifthenelse{\boolean{@MXV@autostop}}{%
        \def\@MXV@deactivation{/D/PI/DIS/U}%
      }{%
        \ifthenelse{\boolean{@MXV@autopause}}{%
          \def\@MXV@deactivation{/D/PI/DIS/I}%
        }{%@MXV@continue
          \def\@MXV@deactivation{/D/PI/DIS/L}%
        }%
      }%
    }{%#### 2D ####
      \ifx\@MXV@startat\@empty% default start position
        \gdef\@MXV@startat{, startAt: 0}%
      \fi%
      %label this annotation for later player id number determination (pdftex &
      %dvips) + write player settings to aux file
      \ifx\@MXV@label\@empty\else%
        %check for multiply-defined labels first
        \ifthenelse{%
          \NOT\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}}{undefined}%
          \AND%
          \NOT\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}}{%
                                                          \the\@MXV@includes}%
        }{%
          \PackageWarning{movie15}{%
            Label `\@MXV@label' multiply defined%
          }%
          \ifthenelse{\isundefined{\@MXV@multiwarning}}{%
            \gdef\@MXV@multiwarning{}%
            \AtEndDocument{%
              \PackageWarningNoLine{movie15}{%
              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak
              @@ There were multiply-defined labels! @@\MessageBreak
              @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}%
            }%
          }{}%
        }{}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.playerid}{\the\@MXV@includes}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.mouse}{%
                     \if@MXV@mouse true\else false\fi}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.showUI}{\@MXV@ctrls}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.palindrome}{\@MXV@palindrome}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.repeat}{\@MXV@repeat}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.rate}{\@MXV@rate}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.startAt}{\@MXV@startat}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.endAt}{\@MXV@endat}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.volume}{\@MXV@volume}%
        \@MXV@labeltoaux{@MXV@\@MXV@label.autoplay}{%
                  \if@MXV@autoplay true\else false\fi}%
      \fi%
      %
      \ifthenelse{\boolean{@MXV@autoplay}\OR\boolean{@MXV@runposter}}{%
        \xdef\@MXV@pageopenopentry{/OP 4}%
      }{%
        \ifthenelse{\boolean{@MXV@autoresume}}{%
          \xdef\@MXV@pageopenopentry{/OP 3}%
        }{%
          \xdef\@MXV@pageopenopentry{/OP 2}%
        }%
      }%
      %
      \ifthenelse{\boolean{@MXV@autostop}}{%
        \xdef\@MXV@pagecloseopentry{/OP 1}%
      }{%
        \ifthenelse{\boolean{@MXV@autopause}}{%
          \xdef\@MXV@pagecloseopentry{/OP 2}%
        }{% @MXV@continue
          \xdef\@MXV@pagecloseopentry{/OP 3}%
        }%
      }%
      %
      %JavaScripts for playback control
      %script for page invisible event
      \ifthenelse{\boolean{@MXV@autopause}}{%
        \xdef\@MXV@pageclosejsentry{%
          /JS (
            try{%
              if(player\the\@MXV@includes.isPlaying){%
                player\the\@MXV@includes.pause();
              }
              focusonplayer = -1; %page change
              player\the\@MXV@includes.visible = false;
            }
            catch(e){}
          )%
        }%
      }{%
        \ifthenelse{\boolean{@MXV@autostop}}{%
          \xdef\@MXV@pageclosejsentry{%
            /JS (
              try{%
                %players tend to be buggy, always stop from playing state
                if(!player\the\@MXV@includes.isPlaying){
                  player\the\@MXV@includes.play();
                }
                player\the\@MXV@includes.stop();
                player\the\@MXV@includes.seek(%
                                   player\the\@MXV@includes.settings.startAt);
                focusonplayer = -1;
                player\the\@MXV@includes.visible = false;
              }
              catch(e){}
            )%
          }%
        }{%
          \xdef\@MXV@pageclosejsentry{%@MXV@continue
            /JS (
              try{%
                focusonplayer = -1; %page change
                player\the\@MXV@includes.visible = false;
              }
              catch(e){}
            )%
          }%
        }%
      }%
      %
      %script for activation/resume on page open event
      \xdef\@MXV@pageopenjsentry{%
        /JS (
          try{%
            if(player\the\@MXV@includes.isOpen){%
              player\the\@MXV@includes.visible = true;
              %
              %start or resume media which have autoplay option set;
              %also resume paused media which have autoresume option set
              \if@MXV@autoplay%
                player\the\@MXV@includes.play();
                if(!player\the\@MXV@includes.isPlaying){% still not playing?!
                  player\the\@MXV@includes.seek(%
                                     player\the\@MXV@includes.settings.startAt);
                  player\the\@MXV@includes.play();
                }
              \else%
                \if@MXV@autoresume%
                  if(player\the\@MXV@includes.settings.privateData.paused){%
                    player\the\@MXV@includes.play();
                    if(!player\the\@MXV@includes.isPlaying){%
                      player\the\@MXV@includes.seek(%
                                     player\the\@MXV@includes.settings.startAt);
                      player\the\@MXV@includes.play();
                    }
                  }
                \fi%
              \fi%
            }
            else{%
              throw "isClosed";%
            }
          }
          catch(e){%
            \@MXV@if{\if@MXV@autoplay true\else\if@MXV@runposter true\else %
                                                                 false\fi\fi}%
              if(focusonplayer == undefined){%
                var focusonplayer = 0; %shared by all annots
              }
              \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}%
                   {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}%
              \@MXV@events{\the\@MXV@includes}%
                {\if@MXV@mouse true\else false\fi}%
                {\if@MXV@autoplay true\else false\fi}%
              var player\the\@MXV@includes\space = app.media.openPlayer({%
                settings: settings,
                events: events
              });
            \fi%
          }
        )
      }%
      %
      %script for normal activation by mouse click
      \xdef\@MXV@activationjsentry{%
        /JS (
          if(focusonplayer == undefined){%
            var focusonplayer = 0; %shared by all annots
          }
          \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}%
               {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}%
          \@MXV@events{\the\@MXV@includes}{\if@MXV@mouse true\else false\fi}%
                                                                      {true}%
          var player\the\@MXV@includes\space = app.media.openPlayer({%
            settings: settings,
            events: events
          });
        )
      }%
    }%
  }{}%
  %
  %total height of text
  \@MXV@totalheight=\@MXV@height%
  \advance\@MXV@totalheight by \@MXV@depth%
  %traiselen = distance at which text is to be raised to centre it vertically
  %braiselen = vertical centre of media box (auxiliary measure)
  \@MXV@traiselen=0.5\@MXV@height%
  \advance\@MXV@traiselen by -0.5\@MXV@depth%
  %
  \ifthenelse{\equal{#3}{}}{% no height argument
    \@MXV@braiselen=0.5\@MXV@height%
  }{%override height of text, height argument given
    \@MXV@braiselen=#3%
    \@MXV@braiselen=0.5\@MXV@braiselen%
    \setlength{\@MXV@height}{#3}%
  }%
  %
  \ifthenelse{\equal{\@MXV@boxdepth}{}}{% no depth option given
    \ifthenelse{\lengthtest{\@MXV@totalheight>\@MXV@height}}{%
      %depth of text only taken into account, if its total height
      %is smaller than the height of the display box
      \advance\@MXV@braiselen by -0.5\@MXV@depth%
    }{%
      \@MXV@depth=0pt%
    }%
  }{%override depth of text, depth option given
    \setlength{\@MXV@@boxdepth}{\@MXV@boxdepth}%
    \advance\@MXV@braiselen by -0.5\@MXV@@boxdepth%
    \setlength{\@MXV@depth}{\@MXV@boxdepth}%
  }%
  %finally centre text vertically
  \ifthenelse{\NOT\equal{#3}{}\OR\NOT\equal{\@MXV@boxdepth}{}}{%
    \advance\@MXV@traiselen by -\@MXV@braiselen%
    \@MXV@traiselen=-\@MXV@traiselen%
    \savebox{\@MXV@textbox}{\raisebox{\@MXV@traiselen}[0pt][0pt]{%
      \usebox{\@MXV@textbox}}}%
  }{}%
  \ifthenelse{\equal{#2}{}}{}{%override horiz. dimension of text
    \setlength{\@MXV@width}{#2}%
    %centre text horizontally
    \savebox{\@MXV@textbox}{\makebox[\@MXV@width][c]{\usebox{\@MXV@textbox}}}%
  }%
  %
  %insert textbox, obscured by poster
  \ifthenelse{\boolean{@MXV@boxopt}}{%
    \ifthenelse{\boolean{@MXV@textoverposter}}{}{%
      \makebox[0pt][l]{\usebox{\@MXV@textbox}}%
    }%
  }{}%
  %
  %appearance dict dummy, to be shared by all 2D and 3D annots
  \ifthenelse{\NOT\boolean{@MXV@externalviewer}}{%
    \ifthenelse{\isundefined{\@MXV@apdict}}{%
      \ifthenelse{\boolean{@MXV@pdf}}{%
        \pdfobj stream {}\pdfrefobj\pdflastobj%
        \xdef\@MXV@apdict{/AP << /N \the\pdflastobj\space 0 R >>}%
      }{%
        \pdfmark{%
          pdfmark=/OBJ,%
          Raw={%
            /_objdef {apdict}%
            /type/stream%
          }%
        }%
        \pdfmark{%
          pdfmark=/PUT,%
          Raw={%
            {apdict}%
            ()%
          }%
        }%
        \xdef\@MXV@apdict{/AP << /N {apdict}>>}%
      }%
    }{}%
  }{}%
  %
  %insert annotation
  \ifthenelse{\boolean{@MXV@externalviewer}\AND\NOT\boolean{@MXV@inline}}{%
    \ifthenelse{\isundefined{\href}}{%
      \@MXV@missing{hyperref}%
    }{}%
    \ifthenelse{\boolean{@MXV@url}}{%
      \href{#4}{\@MXV@box{\@MXV@width}{\@MXV@height}{\@MXV@depth}}%
    }{%
      \IfFileExists{#4}{%
        \href{run:#4}{\@MXV@box{\@MXV@width}{\@MXV@height}{\@MXV@depth}}%
      }{%
        \AtEndDocument{%
          \PackageWarning{movie15}{%
            File: `#4'\MessageBreak
            could not be found in the current directory.\MessageBreak
            Maybe it is a URL and you simply forgot to set\MessageBreak
            option `url'
          }%
        }%
      }%
    }%
  }{%
    \ifthenelse{\boolean{@MXV@iiiDfeat}\AND\boolean{@MXV@iiid}}{%
      \@MXV@includeiiid{\@MXV@width}{\@MXV@height}{\@MXV@depth}{#4}%
    }{%
      \@MXV@includemovie{\@MXV@width}{\@MXV@height}{\@MXV@depth}{#4}%
    }%
  }%
  %
  %insert textbox, overprinting the poster
  \ifthenelse{\boolean{@MXV@boxopt}}{%
    \ifthenelse{\boolean{@MXV@textoverposter}}{%
      \makebox[0pt][r]{\usebox{\@MXV@textbox}}%
    }{}%
  }{}%
}

%for remote control of media
\newcommand\movieref[3][]{%
  \leavevmode%
  %
  \@MXV@reset%
  %
  %check if label is defined at all
  \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@#2.playerid}}{undefined}}{%
    \PackageWarning{movie15}{%
      Reference `#2' on page \thepage \space undefined%
    }%
    \ifthenelse{\isundefined{\@MXV@undefwarning}}{%
      \gdef\@MXV@undefwarning{}%
      \AtEndDocument{%
        \PackageWarningNoLine{movie15}{%
        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak
        @@ There were undefined references! @@\MessageBreak
        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}%
      }%
    }{}%
  }{}%
  %
  %retrieve original settings
  \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@#2.mouse}}{true}}{%
    \setboolean{@MXV@mouse}{true}%
  }{%
    \setboolean{@MXV@mouse}{false}%
  }%
  \edef\@MXV@ctrls{\@MXV@getlabelvalue{@MXV@#2.showUI}}%
  \edef\@MXV@palindrome{\@MXV@getlabelvalue{@MXV@#2.palindrome}}%
  \edef\@MXV@repeat{\@MXV@getlabelvalue{@MXV@#2.repeat}}%
  \edef\@MXV@rate{\@MXV@getlabelvalue{@MXV@#2.rate}}%
  \edef\@MXV@startat{\@MXV@getlabelvalue{@MXV@#2.startAt}}%
  \edef\@MXV@endat{\@MXV@getlabelvalue{@MXV@#2.endAt}}%
  \edef\@MXV@volume{\@MXV@getlabelvalue{@MXV@#2.volume}}%
  \setkeys{movie15}{#1}%override with new settings
  %
  %get page number
  \edef\@MXV@playerpage{\@MXV@getlabelvalue{@MXV@player\@MXV@getlabelvalue{@MXV@#2.playerid}.page}}%
  %
  \edef\@MXV@operation{}%
  %create /OP and /JS entries
  \if@MXV@linkplay
    \edef\@MXV@operation{%
      /OP 0%
      /JS (
        if(focusonplayer == undefined){%
          var focusonplayer = 0; %shared by all annots
        }
        \@MXV@settings{\@MXV@ctrls}{\@MXV@palindrome}{\@MXV@repeat}%
             {\@MXV@rate}{\@MXV@startat}{\@MXV@endat}{\@MXV@volume}%
        \@MXV@events{\@MXV@getlabelvalue{@MXV@#2.playerid}}%
                   {\if@MXV@mouse true\else false\fi}{true}%
        try{
          if(player\@MXV@getlabelvalue{@MXV@#2.playerid}.isOpen){%
            player\@MXV@getlabelvalue{@MXV@#2.playerid}.close(%
                                  app.media.closeReason.general);
            player\@MXV@getlabelvalue{@MXV@#2.playerid}\space = null;
          }
        }
        catch(e){}
        %
        this.pageNum = \@MXV@playerpage -1;%zero based
        %
        try{
          var player\@MXV@getlabelvalue{@MXV@#2.playerid}\space = %
                                            app.media.openPlayer({%
            settings: settings,
            events: events
          });
        }
        catch (e){}
      )
    }%
  \fi%
  \if@MXV@linkresume% resume/pause
    \edef\@MXV@operation{%
      /OP 3%
      /JS (
        try{%
          this.pageNum = \@MXV@playerpage - 1;
          player\@MXV@getlabelvalue{@MXV@#2.playerid}.visible = true;
          if(!player\@MXV@getlabelvalue{@MXV@#2.playerid}.isPlaying){%
            player\@MXV@getlabelvalue{@MXV@#2.playerid}.play();
            if(!player\@MXV@getlabelvalue{@MXV@#2.playerid}.isPlaying){%
              %media at end will restart
              player\@MXV@getlabelvalue{@MXV@#2.playerid}.seek(%
                player\@MXV@getlabelvalue{@MXV@#2.playerid}.settings.startAt);
              player\@MXV@getlabelvalue{@MXV@#2.playerid}.play();
            }
          }
          else{%
            player\@MXV@getlabelvalue{@MXV@#2.playerid}.pause();
          }
        }
        catch(e){}%
      )
    }%
  \fi%
  \if@MXV@linkstop%
    \edef\@MXV@operation{%
      /OP 1%
      /JS (
        try{%
          if(!player\@MXV@getlabelvalue{@MXV@#2.playerid}.isPlaying){
            player\@MXV@getlabelvalue{@MXV@#2.playerid}.play();
          }
          player\@MXV@getlabelvalue{@MXV@#2.playerid}.stop();
          player\@MXV@getlabelvalue{@MXV@#2.playerid}.seek(%
                 player\@MXV@getlabelvalue{@MXV@#2.playerid}.settings.startAt);
        }
        catch(e){}
        this.pageNum = \@MXV@playerpage - 1;
      )%
    }%
  \fi%
  \if@MXV@linkpause% pause/resume
    \edef\@MXV@operation{%
      /OP 2%
      /JS (
        this.pageNum = \@MXV@playerpage - 1;
        try{%
          player\@MXV@getlabelvalue{@MXV@#2.playerid}.visible = true;
          if(!player\@MXV@getlabelvalue{@MXV@#2.playerid}.isPlaying){%
            player\@MXV@getlabelvalue{@MXV@#2.playerid}.play();
            if(!player\@MXV@getlabelvalue{@MXV@#2.playerid}.isPlaying){%
              %media at end will restart
              player\@MXV@getlabelvalue{@MXV@#2.playerid}.seek(%
                player\@MXV@getlabelvalue{@MXV@#2.playerid}.settings.startAt);
              player\@MXV@getlabelvalue{@MXV@#2.playerid}.play();
            }
          }
          else{%
            player\@MXV@getlabelvalue{@MXV@#2.playerid}.pause();
          }
        }
        catch(e){}%
      )
    }%
  \fi%
  \if@MXV@linkclose%
    \edef\@MXV@operation{%
      /OP 1%
      /JS (
        try{%
          player\@MXV@getlabelvalue{@MXV@#2.playerid}.close(%
                                app.media.closeReason.general);
          player\@MXV@getlabelvalue{@MXV@#2.playerid}\space = null;
        }
        catch(e){}
        this.pageNum = \@MXV@playerpage - 1;
      )%
    }%
  \fi%
  \if@MXV@linkreset% reset to orig. settings
    %retrieve original settings
    \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@#2.mouse}}{true}}{%
      \setboolean{@MXV@mouse}{true}%
    }{%
      \setboolean{@MXV@mouse}{false}%
    }%
    \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@#2.autoplay}}{true}}{%
      \setboolean{@MXV@autoplay}{true}%
    }{%
      \setboolean{@MXV@autoplay}{false}%
    }%
    %
    \edef\@MXV@operation{%
      /OP 0%
      /JS (
        if(focusonplayer == undefined){%
          var focusonplayer = 0; %shared by all annots
        }
        \@MXV@settings{\@MXV@getlabelvalue{@MXV@#2.showUI}}%
                      {\@MXV@getlabelvalue{@MXV@#2.palindrome}}%
                      {\@MXV@getlabelvalue{@MXV@#2.repeat}}%
                      {\@MXV@getlabelvalue{@MXV@#2.rate}}%
                      {\@MXV@getlabelvalue{@MXV@#2.startAt}}%
                      {\@MXV@getlabelvalue{@MXV@#2.endAt}}%
                      {\@MXV@getlabelvalue{@MXV@#2.volume}}%
        \@MXV@events{\@MXV@getlabelvalue{@MXV@#2.playerid}}%
                    {\if@MXV@mouse true\else false\fi}%
                    {\if@MXV@autoplay true\else false\fi}%
        try{
          if(player\@MXV@getlabelvalue{@MXV@#2.playerid}.isOpen){%
            player\@MXV@getlabelvalue{@MXV@#2.playerid}.close(%
                                    app.media.closeReason.general);
            player\@MXV@getlabelvalue{@MXV@#2.playerid}\space = null;
          }
        }
        catch(e){}
        %
        this.pageNum = \@MXV@playerpage - 1;
        %
        try{
          var player\@MXV@getlabelvalue{@MXV@#2.playerid}\space = %
                                            app.media.openPlayer({%
            settings: settings,
            events: events
          });
        }
        catch (e){}
      )
    }%
  \fi%
  %
  \savebox{\@MXV@textbox}{#3}% save text argument
  \ifthenelse{\boolean{@MXV@pdf}}{%
    \pdfstartlink%
      attr{
        \ifx\@pdfborder\@empty\else%
          /Border [\@pdfborder]%
        \fi%
        \ifx\@linkbordercolor\@empty%
          /C [1 0 0]% hyperref default
        \else%
          /C [\@linkbordercolor]%
        \fi%
        \ifx\@pdfhighlight\@empty\else%
          /H \@pdfhighlight%
        \fi%
      }%
      user{%
        /Subtype /Link%
        /A <<%
          /S /Rendition%
          /R \@MXV@getlabelvalue{@MXV@#2.rendition}\space 0 R%
          /AN \@MXV@getlabelvalue{@MXV@#2.annot}\space 0 R%
          \@MXV@operation%
        >>%
      }%
    \usebox{\@MXV@textbox}% write out text box
    \pdfendlink%
  }{%
    \advance\@MXV@links by 1%increment counter
    \pdfmark[{\usebox{\@MXV@textbox}}]{%
      pdfmark=/ANN,%
      Subtype=/Link,%
      %ghostscript bug leads to wrong border width in final PDF
%      Border=\@pdfborder,
      Color=\@linkbordercolor,%
      AcroHighlight=\@pdfhighlight,%
      Raw={%
        /_objdef {linkannot\the\@MXV@links}%
      }%
    }%
    %
    %entire action entry moved outside screen annotation
    %to workaround a ghostscript bug
    \pdfmark{%
      pdfmark=/PUT,%
      Raw={%
        {linkannot\the\@MXV@links} <<%
          /A <<%
            /S /Rendition%
            /R {mediarendition\@MXV@getlabelvalue{@MXV@#2.playerid}}%
            /AN {screenannot\@MXV@getlabelvalue{@MXV@#2.playerid}}%
            \@MXV@operation%
          >>%
        >>%
      }%
    }%
  }%
}

%key definitions for options to \includemovie
\define@key{movie15}{label}{%for use with movieref
  \gdef\@MXV@label{#1}%
}
\define@key{movie15}{controls}[true]{%
  \xdef\@MXV@ctrls{, showUI: #1}%
  \xdef\@MXV@@ctrls{/C #1}%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \setboolean{@MXV@iiidctrls}{#1}%
  }{}%
}
\define@key{movie15}{volume}{%
  \def\@MXV@@volume{/V #1}%
  \def\@MXV@volume{#1}%
}
\define@key{movie15}{mimetype}{%
  \ifthenelse{\equal{#1}{model/u3d}}{%
    \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
      \setboolean{@MXV@iiid}{true}%
      \xdef\@MXV@iiidsubtype{U3D}%
    }{\@MXV@neediiiD}%
  }{}%
  \def\@MXV@mime{#1}%
}
\define@key{movie15}{autoplay}[true]{%
  \setboolean{@MXV@autoplay}{#1}%
  \ifthenelse{\boolean{@MXV@autoplay}}{%
    \setboolean{@MXV@autoresume}{false}%
  }{}%
}
\define@key{movie15}{autostop}[true]{%
  \setboolean{@MXV@autostop}{#1}%
  \ifthenelse{\boolean{@MXV@autostop}}{%
    \setboolean{@MXV@autopause}{false}%
  }{}%
}
\define@key{movie15}{autoresume}[true]{%
  \setboolean{@MXV@autoresume}{#1}%
  \ifthenelse{\boolean{@MXV@autoresume}}{%
    \setboolean{@MXV@autoplay}{false}%
  }{}%
}
\define@key{movie15}{autopause}[true]{%
  \setboolean{@MXV@autopause}{#1}%
  \ifthenelse{\boolean{@MXV@autopause}}{%
    \setboolean{@MXV@autostop}{false}%
  }{}%
}
\define@key{movie15}{continue}[true]{%
  \setboolean{@MXV@autostop}{false}%
  \setboolean{@MXV@autopause}{false}%
}
\define@key{movie15}{open}[true]{%
  %no longer supported; once open, media remains loaded
  %to avoid reloading when media is to be played again
}
\define@key{movie15}{mouse}[true]{%
  \setboolean{@MXV@mouse}{#1}%
}
\define@key{movie15}{palindrome}[true]{%
  \xdef\@MXV@palindrome{, palindrome: #1}%
}
\define@key{movie15}{rate}{%
  \xdef\@MXV@rate{, rate: #1}%
}
\define@key{movie15}{repeat}[Infinity]{%
  \ifthenelse{%
    \equal{#1}{Infinity}\OR%
    \equal{#1}{0}%
  }{%
    \xdef\@MXV@repeat{, repeat: Infinity}%
    \xdef\@MXV@@repeat{/RC 0}%
  }{%
    \xdef\@MXV@repeat{, repeat: #1}%
    \xdef\@MXV@@repeat{/RC #1}%
  }%
}
\define@key{movie15}{startat}{%
  \xdef\@MXV@startat{, startAt: {#1}}%
}
\define@key{movie15}{endat}{%
  \xdef\@MXV@endat{, endAt: {#1}}%
}
\define@key{movie15}{poster}[true]{%
  \ifthenelse{\equal{#1}{true}}{% option without arg
    \setboolean{@MXV@runposter}{true}%
  }{%
    \def\@MXV@box##1##2##3{%
      \ifthenelse{\boolean{@MXV@pdf}}{%
        \mbox{\pdfximage width ##1 height ##2 depth ##3 {#1}}%
        \pdfrefximage\pdflastximage%
      }{%
        \ifthenelse{\isundefined{\includegraphics}}{%
          \@MXV@missing{graphicx}%
        }{%
          \@MXV@totalheight=##2%
          \advance\@MXV@totalheight by ##3%
          \raisebox{-##3}[##2][##3]{%
            \includegraphics[%
              width=##1,height=##2,totalheight=\@MXV@totalheight,clip]{#1}%
          }%
        }%
      }%
    }%
  }%
}
\define@key{movie15}{externalviewer}[true]{%
  \setboolean{@MXV@externalviewer}{#1}%
}
\define@key{movie15}{inline}[true]{%
  \ifthenelse{\boolean{@MXV@url}}{%
    \setboolean{@MXV@inline}{false}%
  }{%
    \setboolean{@MXV@inline}{#1}%
  }%
  \ifthenelse{\boolean{@MXV@inline}}{}{%
    \setboolean{@MXV@attachment}{false}%
  }%
}
\define@key{movie15}{url}[true]{%
  \setboolean{@MXV@url}{#1}%
  \ifthenelse{\boolean{@MXV@url}}{%
    \setboolean{@MXV@inline}{false}%
    \def\@MXV@fsentry{/FS /URL}%
  }{}%
}
\define@key{movie15}{attach}[true]{%
  \setboolean{@MXV@attachment}{#1}%
  \ifthenelse{\boolean{@MXV@attachment}}{%
    \setboolean{@MXV@inline}{true}%
  }{}%
}
\define@key{movie15}{text}{%
  \setboolean{@MXV@boxopt}{true}%
  \savebox{\@MXV@textbox}{#1}%
  \@MXV@width=\wd\@MXV@textbox%
  \@MXV@height=\ht\@MXV@textbox%
  \@MXV@depth=\dp\@MXV@textbox%
}
\define@key{movie15}{textoverposter}[true]{%
  \setboolean{@MXV@textoverposter}{#1}%
}
\define@key{movie15}{depth}{%set depth of display area
  \gdef\@MXV@boxdepth{#1}%
}
%3D specific options
\define@key{movie15}{3Dbg}{%
  \def\@MXV@background{/BG<</CS/DeviceRGB/C[#1]>>}%
}
\define@key{movie15}{3Djscript}{%
  \IfFileExists{#1}{%
    \def\@MXV@jscriptiiidfile{#1}%
  }{%
    \PackageError{movie15}{Script file `#1' cannot be opened for embedding%
    }{%
      Make sure file `#1' exists and is readable!%
    }%
  }%
}
\define@key{movie15}{3Dcoo}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@coo{#1}%
    \setboolean{@MXV@defaultviewprovided}{true}%
  }{\@MXV@neediiiD}%
}
\define@key{movie15}{3Dc2c}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@ctoc{#1}%
    \setboolean{@MXV@defaultviewprovided}{true}%
  }{\@MXV@neediiiD}%
}
\define@key{movie15}{3Droo}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@roo{#1}%
    \setboolean{@MXV@defaultviewprovided}{true}%
  }{\@MXV@neediiiD}%
}
\define@key{movie15}{3Daac}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@aac{#1}%
    \setboolean{@MXV@defaultviewprovided}{true}%
  }{\@MXV@neediiiD}%
}
\define@key{movie15}{3Dviews}{%
  \IfFileExists{#1}{%
    \def\@MXV@viewsfile{#1}%
  }{%
    \PackageError{movie15}{3D views  file `#1' cannot be opened%
    }{%
      Make sure file `#1' exists and is readable!%
    }%
  }%
}
%options for \movieref command
\define@key{movie15}{play}[true]{%
  \setboolean{@MXV@linkplay}{#1}%
  \ifthenelse{\boolean{@MXV@linkplay}}{%
   \setboolean{@MXV@linkpause}{false}%
   \setboolean{@MXV@linkresume}{false}%
   \setboolean{@MXV@linkstop}{false}%
   \setboolean{@MXV@linkclose}{false}%
   \setboolean{@MXV@linkreset}{false}%
  }{}%
}
\define@key{movie15}{pause}[true]{%
  \setboolean{@MXV@linkpause}{#1}%
  \ifthenelse{\boolean{@MXV@linkpause}}{%
    \setboolean{@MXV@linkresume}{false}%
    \setboolean{@MXV@linkstop}{false}%
    \setboolean{@MXV@linkclose}{false}%
    \setboolean{@MXV@linkreset}{false}%
    \setboolean{@MXV@linkplay}{false}%
  }{}%
}
\define@key{movie15}{resume}[true]{%
  \setboolean{@MXV@linkresume}{#1}%
  \ifthenelse{\boolean{@MXV@linkresume}}{%
    \setboolean{@MXV@linkpause}{false}%
    \setboolean{@MXV@linkstop}{false}%
    \setboolean{@MXV@linkclose}{false}%
    \setboolean{@MXV@linkreset}{false}%
    \setboolean{@MXV@linkplay}{false}%
  }{}%
}
\define@key{movie15}{stop}[true]{%
  \setboolean{@MXV@linkstop}{#1}%
  \ifthenelse{\boolean{@MXV@linkstop}}{%
    \setboolean{@MXV@linkpause}{false}%
    \setboolean{@MXV@linkresume}{false}%
    \setboolean{@MXV@linkclose}{false}%
    \setboolean{@MXV@linkreset}{false}%
    \setboolean{@MXV@linkplay}{false}%
  }{}%
}
\define@key{movie15}{close}[true]{%
  \setboolean{@MXV@linkclose}{#1}%
  \ifthenelse{\boolean{@MXV@linkclose}}{%
    \setboolean{@MXV@linkpause}{false}%
    \setboolean{@MXV@linkresume}{false}%
    \setboolean{@MXV@linkstop}{false}%
    \setboolean{@MXV@linkreset}{false}%
    \setboolean{@MXV@linkplay}{false}%
  }{}%
}
\define@key{movie15}{reset}[true]{%
  \setboolean{@MXV@linkreset}{#1}%
  \ifthenelse{\boolean{@MXV@linkreset}}{%
    \setboolean{@MXV@linkpause}{false}%
    \setboolean{@MXV@linkresume}{false}%
    \setboolean{@MXV@linkstop}{false}%
    \setboolean{@MXV@linkclose}{false}%
    \setboolean{@MXV@linkplay}{false}%
  }{}%
}

%compatibility macros
\newcommand\movie[3][]{%
  \leavevmode%
  \@MXV@reset%
  \def\@MXV@autostart{}\def\@MXV@loop{}\def\@MXV@showcontrols{}%
  \def\@MXV@starttime{}\def\@MXV@durationtime{}%
  \setkeys{movie15}{#1}%
  %
  %sanity checks
  \if@MXV@boxopt%
    \PackageError{movie15}{%
      Option `text' cannot be used with command `\string\movie'.\MessageBreak
      Instead, put text into the 1st argument of `\string\movie'
    }{}%
  \fi%
  %
  \ifx\@MXV@durationtime\@empty\else\ifx\@MXV@startat\@empty\else%
    \PackageError{movie15}{%
      Options `startat' and `duration' cannot be used\MessageBreak
      together.\MessageBreak
      Possible combinations are `startat'/`endat',\MessageBreak
      `start'/`endat' or `start'/`duration'
    }{}%
  \fi\fi%
  %
  %option list
  \edef\@MXV@movieoptions{#1\@MXV@autostart\@MXV@loop\@MXV@showcontrols}%
  %
  %determine playback section
  \ifx\@MXV@starttime\@empty\else%
    \edef\@MXV@movieoptions{\@MXV@movieoptions, %
                                            startat=time:\strip@pt\@MXV@start}%
  \fi%
  \ifx\@MXV@durationtime\@empty\else%
    \advance\@MXV@end by \@MXV@start%
    \edef\@MXV@movieoptions{\@MXV@movieoptions, %
                                                endat=time:\strip@pt\@MXV@end}%
  \fi%
  %
  %text option from 2nd argument
  \savebox{\@MXV@textbox}{#2}%
  \edef\@MXV@movieoptions{[\@MXV@movieoptions, text={\noexpand\usebox{%
                                            \noexpand\@MXV@textbox}}]}%
  \expandafter\includemovie\@MXV@movieoptions{\@MXV@boxwidth}{\@MXV@boxheight}%
                                                                          {#3}%
}

\newcommand\hyperlinkmovie[3][]{%
  \leavevmode%
  \@MXV@reset%
  \def\@MXV@autostart{}\def\@MXV@loop{}\def\@MXV@showcontrols{}%
  \def\@MXV@starttime{}\def\@MXV@durationtime{}%
  \setkeys{movie15}{#1}%
  %
  %sanity check
  \ifx\@MXV@durationtime\@empty\else\ifx\@MXV@startat\@empty\else%
    \PackageError{movie15}{%
      Options `startat' and `duration' cannot be used\MessageBreak
      together.\MessageBreak
      Possible combinations are `startat'/`endat',\MessageBreak
      `start'/`endat' or `start'/`duration'
    }{}%
  \fi\fi%
  %
  %option list
  \edef\@MXV@movieoptions{#1\@MXV@autostart\@MXV@loop\@MXV@showcontrols}%
  %
  %determine playback section
  \ifx\@MXV@starttime\@empty\else%
    \edef\@MXV@movieoptions{\@MXV@movieoptions, %
                                            startat=time:\strip@pt\@MXV@start}%
  \fi%
  \ifx\@MXV@durationtime\@empty\else%
    \advance\@MXV@end by \@MXV@start%
    \edef\@MXV@movieoptions{\@MXV@movieoptions, %
                                                endat=time:\strip@pt\@MXV@end}%
  \fi%
  %
  \edef\@MXV@movieoptions{[\@MXV@movieoptions]}%
  \expandafter\movieref\@MXV@movieoptions{#2}{#3}%
}

%compatibility options for \movie and \hyperlinkmovie commands
\define@key{movie15}{borderwidth}{%
  %ignored; acroread doesn't draw borders around screen annots anyway
}
\define@key{movie15}{height}{%set height of display area
  \gdef\@MXV@boxheight{#1}%
}
\define@key{movie15}{width}{%set width of display area
  \gdef\@MXV@boxwidth{#1}%
}
\define@key{movie15}{autostart}[true]{%
  \xdef\@MXV@autostart{, autoplay=#1}%
}
\define@key{movie15}{loop}[Infinity]{%
  \xdef\@MXV@loop{, repeat=#1}%
}
\define@key{movie15}{once}[]{%
  \xdef\@MXV@loop{, repeat=1}%
}
\define@key{movie15}{showcontrols}[true]{%
  \xdef\@MXV@showcontrols{, controls=#1}%
}
\define@key{movie15}{start}{%
  \gdef\@MXV@starttime##1s{%
    \global\@MXV@start=##1pt%
  }%
  \@MXV@starttime #1%
}
\define@key{movie15}{duration}{%
  \gdef\@MXV@durationtime##1s{%
    \global\@MXV@end=##1pt%
  }%
  \@MXV@durationtime #1%
}
