% Copyright 2004--2008 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}[2008/10/08]
\RequirePackage{keyval}
\RequirePackage{ifthen}
\RequirePackage{ifpdf}
\RequirePackage{ifdraft}

\newboolean{@MXV@iiiDfeat} % enable 3D features from PDF-1.6 spec?
\setboolean{@MXV@iiiDfeat}{false}%
\newboolean{@MXV@iiid} %set to true if a 3D file is being embedded
\newboolean{@MXV@draft} %according to global setting
\newboolean{@MXV@@draft} %per inclusion setting

\ifdraft{%globally set by document class
  \setboolean{@MXV@draft}{true}%
}{%
  \setboolean{@MXV@draft}{false}%
}%

%override global setting
\DeclareOption{draft}{%
  \setboolean{@MXV@draft}{true}%
}
\DeclareOption{final}{%
  \setboolean{@MXV@draft}{false}%
}

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

\newboolean{@MXV@dvips}
\newboolean{@MXV@dvipdfmx}
\ifpdf
  \setboolean{@MXV@dvips}{true}
\else
  \setboolean{@MXV@dvips}{false}
\fi
\setboolean{@MXV@dvipdfmx}{false}

\DeclareOption{dvips}{%
  \setboolean{@MXV@dvips}{true}%
  \setboolean{@MXV@dvipdfmx}{false}%
}
\DeclareOption{dvipdfmx}{%
  \setboolean{@MXV@dvips}{false}%
  \setboolean{@MXV@dvipdfmx}{true}%
}

\DeclareOption*{%
  \PackageWarning{movie15}{Unknown option \CurrentOption}
}

\ProcessOptions*\relax

%testing for correct TeX version,
\ifpdf
 \ifnum\pdftexversion<120
   \PackageError{movie15}{%
     pdfeTeX, version >= 1.20, required
   }{%
     Install a more recent version!
   }%
 \fi
\fi

\ifx\@undefined\pdfmdfivesum
  \def\pdfmdfivesum file #1{#1}
\fi

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

\newboolean{@MXV@beamer} %set to true if beamer class has been loaded
%\newboolean{@MXV@powerdot} %the same for
\newboolean{@MXV@presentation} %used with presentation making package?
\newboolean{@MXV@hide} %contents hidden on the current slide?
\@ifclassloaded{beamer}{%
  \setboolean{@MXV@beamer}{true}%
  \setboolean{@MXV@presentation}{true}%
}{%
  \setboolean{@MXV@beamer}{false}%
  \setboolean{@MXV@presentation}{false}%
}
%\@ifclassloaded{powerdot}{%
%  \setboolean{@MXV@powerdot}{true}%
%  \setboolean{@MXV@presentation}{true}%
%}{%
%  \setboolean{@MXV@powerdot}{false}%
%  \setboolean{@MXV@presentation}{false}%
%}

\AtBeginDocument{%
  \provideboolean{Hy@colorlinks}% set by hyperref
  \ifHy@colorlinks% coloured (movieref-)link text instead of link border
    \gdef\@MXV@pdfborder{/Border [0 0 0]}%
  \else%
    \gdef\@MXV@pdfborder{}%
  \fi%
}

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

%define our own label making commands
\def\@MXV@newlabel#1#2{{%
  \expandafter\xdef\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}%
    \string\@MXV@newlabel{@#1@}{\@MXV@getlabelvalue{#1}}%
  }\@esphack%
  \ifthenelse{%
    \equal{\@MXV@getlabelvalue{#1}}{undefined}\OR%
    %double check that the value hasn't changed
    \NOT\equal{\@MXV@getlabelvalue{#1}}{\@MXV@getlabelvalue{@#1@}}%
  }{%
    \ifthenelse{\isundefined{\@MXV@warning}}{% issue warning only once, at end
      \gdef\@MXV@warning{}%                    of document
      \AtEndDocument{%
        \PackageWarningNoLine{movie15}{%
        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak
        @@ Rerun to get object references right! @@\MessageBreak
        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}%
      }%
    }{}%
  }{}%
}%
%
\ifpdf%
  %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%
  }%
\else\if@MXV@dvipdfmx%do nothing
\else%
  \PassOptionsToPackage{pdfmark}{hyperref}%
\fi\fi

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

%counter for absolute number of movie players
\newcount\@MXV@players

%counter for absolute number of movierefs
\newcount\@MXV@links

%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@autoclose}
\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}
\newboolean{@MXV@issound}

%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@autoclose}{false}%
  \setboolean{@MXV@mouse}{false}%
  \setboolean{@MXV@inline}{true}%
  \setboolean{@MXV@attachment}{true}%
  \setboolean{@MXV@externalviewer}{false}%
  \setboolean{@MXV@issound}{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}%
  \setboolean{@MXV@requirereopen}{false}%
  \ifthenelse{\boolean{@MXV@draft}}{%
    \setboolean{@MXV@@draft}{true}%
  }{%
    \setboolean{@MXV@@draft}{false}%
  }%
  %
  \gdef\@MXV@label{}% for movieref
  \gdef\@MXV@@label{}% for movieref
  \gdef\@MXV@mime{@MXV@auto}%
  \gdef\@MXV@player{}%
  \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@@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}}{%
    \setboolean{@MXV@iiid}{false}%
    \gdef\@MXV@aac{30}% aperture angle of camera
    \gdef\@MXV@roll{0}% camera roll angle
    \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}%
    \gdef\@MXV@iiidview{}%
    \gdef\@MXV@iiidtoolb{/TB false}% don't show toolbar by default
    \gdef\@MXV@iiidia{}% 3D interactive by default
    \gdef\@MXV@calc{}% camera aperture for coo and roo calculation
    \setboolean{@MXV@iiidgetview}{false}%
    \gdef\@MXV@iiidopt{}% option string to be passed to internal macro
    \setboolean{@MXV@resource}{false}%
    \gdef\@MXV@resourcetree{}% name tree of embedded 3D resources
    \xdef\@MXV@animstyle{}%
    \gdef\@MXV@iiidpalindrome{/Subtype/Linear}% forward
    \gdef\@MXV@iiidrate{}% animation speed
    \global\@MXV@iiidrepeat=-1% repeat count
    \gdef\@MXV@lights{}% default lighting scheme
    \gdef\@MXV@render{}% default render mode scheme
  }{}%
}%

%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#2{%
  \ifthenelse{\equal{#2}{aiff}\OR\equal{#2}{AIFF}\OR%
              \equal{#2}{aif}\OR\equal{#2}{AIF}\OR%
              \equal{#2}{aifc}\OR\equal{#2}{AIFC}}{%
    \gdef\@MXV@mime{audio/aiff}%
  }{%
  \ifthenelse{\equal{#2}{wav}\OR\equal{#2}{WAV}}{%
    \gdef\@MXV@mime{audio/wav}%
  }{%
  \ifthenelse{\equal{#2}{wma}\OR\equal{#2}{WMA}}{%
    \gdef\@MXV@mime{audio/x-ms-wma}%
  }{%
  \ifthenelse{\equal{#2}{wmv}\OR\equal{#2}{WMV}}{%
    \gdef\@MXV@mime{video/x-ms-wmv}%
  }{%
  \ifthenelse{\equal{#2}{au}\OR\equal{#2}{AU}\OR%
              \equal{#2}{snd}\OR\equal{#2}{SND}}{%
    \gdef\@MXV@mime{audio/basic}%
  }{%
  \ifthenelse{\equal{#2}{mid}\OR\equal{#2}{MID}\OR%
              \equal{#2}{rmi}\OR\equal{#2}{RMI}}{%
    \gdef\@MXV@mime{audio/midi}%
  }{%
  \ifthenelse{\equal{#2}{mov}\OR\equal{#2}{MOV}\OR%
              \equal{#2}{qt}\OR\equal{#2}{QT}}{%
    \gdef\@MXV@mime{video/quicktime}%
  }{%
  \ifthenelse{\equal{#2}{mp3}\OR\equal{#2}{MP3}\OR%
              \equal{#2}{m3u}\OR\equal{#2}{M3U}}{%
    \gdef\@MXV@mime{audio/x-mp3}%
  }{%
  \ifthenelse{\equal{#2}{mp4}\OR\equal{#2}{MP4}}{%
    \gdef\@MXV@mime{video/mp4}%
  }{%
  \ifthenelse{\equal{#2}{avi}\OR\equal{#2}{AVI}}{%
    \gdef\@MXV@mime{video/avi}%
  }{%
  \ifthenelse{\equal{#2}{gif}\OR\equal{#2}{GIF}}{%
    \gdef\@MXV@mime{image/gif}%
  }{%
  \ifthenelse{\equal{#2}{mpeg}\OR\equal{#2}{MPEG}\OR%
              \equal{#2}{mpg}\OR\equal{#2}{MPG}}{%
    \gdef\@MXV@mime{video/mpeg}%
  }{%
  \ifthenelse{\equal{#2}{smil}\OR\equal{#2}{SMIL}}{%
    \gdef\@MXV@mime{application/smil}%
  }{%
  \ifthenelse{\equal{#2}{swf}\OR\equal{#2}{SWF}}{%
    \gdef\@MXV@mime{application/x-shockwave-flash}%
  }{%
  \ifthenelse{\equal{#2}{prc}\OR\equal{#2}{PRC}}{%
    \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
      \setboolean{@MXV@iiid}{true}%
      \gdef\@MXV@mime{model/prc}% (unofficial)
      \gdef\@MXV@iiidsubtype{PRC}%
    }{%
      \@MXV@neediiiD%
    }%
  }{%
  \ifthenelse{\equal{#2}{u3d}\OR\equal{#2}{U3D}}{%
    \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
      \setboolean{@MXV@iiid}{true}%
      \gdef\@MXV@mime{model/u3d}% (unofficial)
      \gdef\@MXV@iiidsubtype{U3D}%
    }{%
      \@MXV@neediiiD%
    }%
  }{%
  \ifthenelse{\equal{#2}{ra}\OR\equal{#2}{RA}}{
    \gdef\@MXV@mime{audio/vnd.rn-realaudio}%
  }{%
  \ifthenelse{%
    \equal{#2}{rv}\OR\equal{#2}{RV}\OR
    \equal{#2}{rm}\OR\equal{#2}{RM}%
  }{%
    \gdef\@MXV@mime{application/vnd.rn-realmedia}%
  }{%
    \PackageError{movie15}{%
      I couldn't determine MIME type of file:\MessageBreak`#1':\MessageBreak
      Unknown file name extension: `#2'
    }{%
      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>'!
    }%
  }}}}}}}}}}}}}}}}}}%
}

%sets @MXV@issound boolean
\def\@MXV@@issound#1/#2:{% argument: \@MXV@mime.
   \def\@MXV@firstarg{#1}%
   \def\@MXV@audio{audio}%
   \ifx\@MXV@firstarg\@MXV@audio%
     \setboolean{@MXV@issound}{true}%
   \fi%
}

%draft box
\def\@MXV@draftbox#1#2#3#4{%width height depth filename
  \edef\@MXV@oldfboxsep{\the\fboxsep}%
  \setlength{\fboxsep}{-\fboxrule}%
  \framebox[#1][l]{%
    \vrule width 0pt height #2 depth #3%
    \edef\@tempa{#4}%
    \raisebox{\depth}[0pt][0pt]{ \ttfamily\expandafter\strip@prefix\meaning\@tempa}%
  }%
  \setlength{\fboxsep}{\@MXV@oldfboxsep}%
}

\ifthenelse{\boolean{@MXV@iiiDfeat}}{% 3D related definitions and macros
  \RequirePackage{fp}% needed for fixed point calculus
  \newread\@MXV@@viewsfile% file handle for views file
  \newcount\@MXV@viewscount%counter for number of 3D views per inclusion
  \newboolean{@MXV@viewsprovided}%3d views file provided?
  \newboolean{@MXV@iiidgetview}% print current 3D settings?
  \newboolean{@MXV@defaultviewprovided}%default 3D view provided?
  \newboolean{@MXV@resource}%3d resource file provided?
  \ifpdf\else\newcount\@MXV@rescount\fi% number of embedded resource files
  \newcount\@MXV@iiidrepeat% play count
  \newcount\@MXV@iiidoncurpage%index of 3D annot on current page
  \global\@MXV@iiidoncurpage=0%
  \gdef\@MXV@oldpage{0}% needed together with previous counter

  %macro for building the transformation matrix
  \def\@MXV@ciiwmatrix#1 #2 #3 #4 #5 #6 #7 #8 {%
    % #1,#2,#3 centre of orbit coordinates (coo)
    % #4,#5,#6 centre of orbit to camera direction vector (c2c)
    % #7 orbital radius (roo)
    % #8 camera roll (roll)
    %view vector (opposite to c2c)
    \FPupn\@MXV@viewx{#4 neg}%
    \FPupn\@MXV@viewy{#5 neg}%
    \FPupn\@MXV@viewz{#6 neg}%
    %normalize view vector
    \FPupn\@MXV@modulo{\@MXV@viewx{} copy mul %
      \@MXV@viewy{} copy mul + %
      \@MXV@viewz{} copy mul + 2 swap root%
    }%
    \FPupn\@MXV@viewx{\@MXV@viewx{} \@MXV@modulo{} div}%
    \FPupn\@MXV@viewy{\@MXV@viewy{} \@MXV@modulo{} div}%
    \FPupn\@MXV@viewz{\@MXV@viewz{} \@MXV@modulo{} div}%
    %camera roll
    \FPupn\@MXV@sinroll{#8 180.0 div \FPpi{} mul sin}%
    \FPupn\@MXV@cosroll{#8 180.0 div \FPpi{} mul cos}%
    %
    %top and bottom views
    \FPupn\@MXV@leftx{-1.0}%
    \FPupn\@MXV@lefty{0.0}%
    \FPupn\@MXV@leftz{0.0}%
    %
    \FPifneg\@MXV@viewz% top view
      %up-vector
      \FPupn\@MXV@upx{0.0}%
      \FPupn\@MXV@upy{1.0}%
      \FPupn\@MXV@upz{0.0}%
    \else% bottom view
      %up-vector
      \FPupn\@MXV@upx{0.0}%
      \FPupn\@MXV@upy{-1.0}%
      \FPupn\@MXV@upz{0.0}%
    \fi%
    \FPupn\@MXV@sumxy{\@MXV@viewx{} abs \@MXV@viewy{} abs add}%
    \FPifeq\@MXV@sumxy{0}\else% other views than top and bottom
      %up-vector = up_world - (up_world dot view) view
      \FPupn\@MXV@upx{\@MXV@viewz{} \@MXV@viewx{} mul neg}%
      \FPupn\@MXV@upy{\@MXV@viewz{} \@MXV@viewy{} mul neg}%
      \FPupn\@MXV@upz{\@MXV@viewz{} \@MXV@viewz{} mul neg 1.0 add}%
      %normalize up-vector
      \FPupn\@MXV@modulo{\@MXV@upx{} copy mul \@MXV@upy{} copy %
        mul + \@MXV@upz{} copy mul + 2 swap root}%
      \FPupn\@MXV@upx{\@MXV@upx{} \@MXV@modulo{} div}%
      \FPupn\@MXV@upy{\@MXV@upy{} \@MXV@modulo{} div}%
      \FPupn\@MXV@upz{\@MXV@upz{} \@MXV@modulo{} div}%
      %left vector = up x view
      \FPupn\@MXV@leftx{\@MXV@viewz{} \@MXV@upy{} mul %
        \@MXV@viewy{} \@MXV@upz{} mul sub}%
      \FPupn\@MXV@lefty{\@MXV@viewx{} \@MXV@upz{} mul %
        \@MXV@viewz{} \@MXV@upx{} mul sub}%
      \FPupn\@MXV@leftz{\@MXV@viewy{} \@MXV@upx{} mul %
        \@MXV@viewx{} \@MXV@upy{} mul sub}%
      %normalize left vector
      \FPupn\@MXV@modulo{\@MXV@leftx{} copy mul \@MXV@lefty{} %
        copy mul + \@MXV@leftz{} copy mul + 2 swap root}%
      \FPupn\@MXV@leftx{\@MXV@leftx{} \@MXV@modulo{} div}%
      \FPupn\@MXV@lefty{\@MXV@lefty{} \@MXV@modulo{} div}%
      \FPupn\@MXV@leftz{\@MXV@leftz{} \@MXV@modulo{} div}%
    \fi%
    %apply camera roll
    \FPupn\@MXV@leftxprime{\@MXV@leftx{} \@MXV@cosroll{} mul \@MXV@upx{} \@MXV@sinroll{} mul +}%
    \FPupn\@MXV@leftyprime{\@MXV@lefty{} \@MXV@cosroll{} mul \@MXV@upy{} \@MXV@sinroll{} mul +}%
    \FPupn\@MXV@leftzprime{\@MXV@leftz{} \@MXV@cosroll{} mul \@MXV@upz{} \@MXV@sinroll{} mul +}%
    \FPupn\@MXV@upxprime{\@MXV@upx{} \@MXV@cosroll{} mul \@MXV@leftx{} \@MXV@sinroll{} mul sub}%
    \FPupn\@MXV@upyprime{\@MXV@upy{} \@MXV@cosroll{} mul \@MXV@lefty{} \@MXV@sinroll{} mul sub}%
    \FPupn\@MXV@upzprime{\@MXV@upz{} \@MXV@cosroll{} mul \@MXV@leftz{} \@MXV@sinroll{} mul sub}%
    \FPupn\@MXV@leftx{\@MXV@leftxprime}%
    \FPupn\@MXV@lefty{\@MXV@leftyprime}%
    \FPupn\@MXV@leftz{\@MXV@leftzprime}%
    \FPupn\@MXV@upx{\@MXV@upxprime}%
    \FPupn\@MXV@upy{\@MXV@upyprime}%
    \FPupn\@MXV@upz{\@MXV@upzprime}%
    %rotation matrix
    \xdef\@MXV@matrix{\@MXV@leftx\space\@MXV@lefty\space\@MXV@leftz\space%
                      \@MXV@upx\space\@MXV@upy\space\@MXV@upz\space%
                      \@MXV@viewx\space\@MXV@viewy\space\@MXV@viewz}%
    %translation vector
    \FPupn\@MXV@roo{#7 abs}%
    \FPifeq\@MXV@roo{0}\FPupn\@MXV@roo{0.000000000000000001}\fi%
    \FPupn\@MXV@transx{#1 \@MXV@roo{} \@MXV@viewx{} mul sub}%
    \FPupn\@MXV@transy{#2 \@MXV@roo{} \@MXV@viewy{} mul sub}%
    \FPupn\@MXV@transz{#3 \@MXV@roo{} \@MXV@viewz{} mul sub}%
    %transformation matrix
    \xdef\@MXV@matrix{%
      \@MXV@matrix\space\@MXV@transx\space\@MXV@transy\space\@MXV@transz%
    }%
  }

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

  %macro for generating an array of 3D views (varray)
  \def\@MXV@buildva{%
    \global\@MXV@viewscount=0%
    \xdef\@MXV@varray{}% empty varray
    %
    %default view
    \edef\@MXV@args{\@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space\@MXV@roll\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
      \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\@MXV@roll\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
    }{}%
    %
    %make the first view in the VA array the default view, if no default one has
    %explicitly been provided, but if the VA array itself is empty too (no
    %additional views provided) use our fallback view (c2c=0 -1 0) as default
    \ifthenelse{\NOT\boolean{@MXV@defaultviewprovided}%
      \AND\boolean{@MXV@viewsprovided}}{%
      \xdef\@MXV@defaultview{/3DV /F}%
    }{%
      \xdef\@MXV@defaultview{/3DV \@MXV@defaultview}%
    }%
  }

  %following macros, including the 3D inclusion macro have driver specific
  %implementations
  \ifpdf%
    %pdfLaTeX versions
    %macro for creating 3D view object
    \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%
        \@MXV@lights%
        \@MXV@render%
      >>}\pdfrefobj\pdflastobj%
      \xdef\@MXV@@viewobj{\the\pdflastobj\space 0 R}%
    }%

    %macro for creating resource objects from 3D and image files, to be used
    %in 3D JavaScript
    \def\@MXV@addresource#1{%
      %determine file type
      \filename@parse{#1}%
      \ifthenelse{%
        \equal{\filename@ext}{u3d}\OR%
        \equal{\filename@ext}{U3D}%
      }{%
        \def\@MXV@restype{U3D}%
      }{%
        \def\@MXV@restype{image}%
      }%
      \ifthenelse{\equal{\@MXV@restype}{image}}{%
        %embed the same image file only once
        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
          \immediate\pdfximage {#1}%
          \xdef\@MXV@resourcetree{% build name tree for embedded resources
            \@MXV@resourcetree\space (#1) \the\pdflastximage\space 0 R%
          }%
          \@MXV@newlabel{\pdfmdfivesum file {#1}}{\the\pdflastximage}%
        }{%
          \xdef\@MXV@resourcetree{%
            \@MXV@resourcetree\space (#1) \@MXV@getlabelvalue{\pdfmdfivesum file {#1}}\space 0 R%
          }%
        }%
      }{%
        %embed the same 3D file only once
        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
          \pdfobj stream %
            attr {%
              /Subtype/\@MXV@restype%
            }%
            file {#1}%
          \pdfrefobj\pdflastobj%
          \xdef\@MXV@resourcetree{%
            \@MXV@resourcetree\space (#1) \the\pdflastobj\space 0 R%
          }%
          \@MXV@newlabel{\pdfmdfivesum file {#1}}{\the\pdflastobj}%
        }{%
          \xdef\@MXV@resourcetree{%
            \@MXV@resourcetree\space (#1) \@MXV@getlabelvalue{\pdfmdfivesum file {#1}}\space 0 R%
          }%
        }%
      }%
    }

    %3D inclusion macro
    \newcommand{\@MXV@includeiiid}[5][]{%
      %insert box or poster
      \@MXV@box{#2}{#3}{#4}%
      %
      \if@MXV@externalviewer\else%
        \setkeys{MXV@iiid}{#1}%process deferred options
        \ifnum\@MXV@iiidrepeat=0\else%
          \edef\@MXV@animstyle{% animation style dict
            /AN <<%
              \@MXV@iiidpalindrome\@MXV@iiidrate/PC \the\@MXV@iiidrepeat%
            >>%
          }%
        \fi%
        %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%
      \fi%
      %
      %3D stream object
      \if@MXV@inline%
        \ifthenelse{%
          \NOT\boolean{@MXV@presentation}\OR%
          \equal{\@MXV@getlabelvalue{\@MXV@label.3dstream}}{undefined}%
        }{%
          \pdfobj stream%
            attr {%
              /Subtype/\@MXV@iiidsubtype%
              \if@MXV@externalviewer\else%
                /VA [\@MXV@varray]%
                /DV/F% use first entry in VA as default view
                \@MXV@animstyle%
                \@MXV@jscriptiiid%
                \if@MXV@resource%
                  /Resources <<%
                    /Names [\@MXV@resourcetree]%
                  >>%
                \fi%
              \fi%
            }%
            file {#5}%
          \pdfrefobj\pdflastobj%
          \edef\@MXV@iiidstream{\the\pdflastobj}%
          \if@MXV@presentation%
            \@MXV@newlabel{\@MXV@label.3dstream}{\@MXV@iiidstream}%
          \fi%
        }{%
          \edef\@MXV@iiidstream{\@MXV@getlabelvalue{\@MXV@label.3dstream}}%
        }%
      \fi%
      %
      \makebox[0pt][r]{\makebox[#2][l]{%
      %insert FileAttachment annotation
      \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}%
%        since Reader 7.0.7, we cannot place a file attachment annot behind
%        the 3D annot :-(
%        \OR\boolean{@MXV@attachment}
      }{%
        \pdfannot width #2 height #3 depth #4 {%
          /Subtype /FileAttachment%
          /F 0%
          /T (\@MXV@filename)%
          /Contents (3D Object (\@MXV@mime))%
          \if@MXV@externalviewer%
            /Name/Paperclip%
            /C [1 1 1]%
          \else%
            /AP <</N<<>>/R<<>>/D<<>>>>%
          \fi%
          /FS <<%
            /F(#5)%
            /Type/Filespec%
            /EF << /F \@MXV@iiidstream\space 0 R >>%
          >>%
        }%
      }{%
        \if@MXV@url%
          %insert Link annotation, if 3D file is a URL
          \pdfannot width #2 height #3 depth #4 {%
            /Subtype /Link%
            /F 0%
            \if@MXV@externalviewer%
              \@MXV@urlattr%
            \else%
              /H /N%
              /Border [0 0 0]%
            \fi%
            /A <</URI (#5) /S/URI>>%
            /Contents (3D Object (\@MXV@mime))%
          }%
        \else%
          %else insert Launch action for local external 3D file
          \if@MXV@inline\else%
            \pdfannot width #2 height #3 depth #4 {%
              /Subtype /Link%
              /F 0%
              \if@MXV@externalviewer%
                \@MXV@runattr%
              \else%
                /H /N%
                /Border [0 0 0]%
              \fi%
              /A <<%
                /F (#5)%
                /S /Launch%
              >>%
              /Contents (3D Object (\@MXV@mime))%
            }%
          \fi%
        \fi%
      }%
      %
      \if@MXV@externalviewer\else%
        %appearance dict dummy, to be shared by all 3D annots
        \ifthenelse{\isundefined{\@MXV@apdict}}{%
          \pdfobj stream attr {/BBox [0 0 0.001 0.001]} {}\pdfrefobj\pdflastobj%
          \xdef\@MXV@apdict{/AP << /N \the\pdflastobj\space 0 R >>}%
        }{}%
        %3D reference dict
        \if@MXV@presentation%
          \ifthenelse{%
            \equal{\@MXV@getlabelvalue{\@MXV@label.3dref}}{undefined}%
          }{%
            \pdfobj {<<%
              /Type/3DRef%
              /3DD \@MXV@iiidstream\space 0 R% 3D stream object
            >>}\pdfrefobj\pdflastobj%
            \edef\@MXV@iiidstreamorref{\the\pdflastobj}%
            \@MXV@newlabel{\@MXV@label.3dref}{\the\pdflastobj}%
          }{%
            \edef\@MXV@iiidstreamorref{\@MXV@getlabelvalue{\@MXV@label.3dref}}%
          }%
        \else%
          \edef\@MXV@iiidstreamorref{\@MXV@iiidstream}%
        \fi%
        %annotation object of subtype `3D'
        \pdfannot width #2 height #3 depth #4 {%
          /Subtype/3D%
          /F 4% we cannot put F 5 here; bug in Reader; 3D annot would be
          /T (\@MXV@filename)%    disabled even if plugin were available
          /Contents (3D Object (\@MXV@mime))%
          \ifx\@MXV@@label\@empty\else%
            /NM (\@MXV@@label)%
          \fi%
          /P \@MXV@pdfpageref{@MXV@annot\the\@MXV@includes.page}%
          \@MXV@apdict% /AP <</N<<>>/R<<>>/D<<>>>> doesn't work here
          \@MXV@defaultview%
          \@MXV@iiidia%
          /3DD \@MXV@iiidstreamorref\space 0 R% 3D stream or reference object
          /3DA << \@MXV@activation\@MXV@deactivation\@MXV@iiidtoolb >>%
        }%
        %label for later annot obj number determination, to be used in
        %movieref's
        \ifx\@MXV@@label\@empty\else%
          \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\the\pdflastannot}%
          \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\the\pdflastannot}%
        \fi%
      \fi}}%
    }%
  \else\if@MXV@dvipdfmx%
    %dvipdfmx versions
    %macro for creating 3D view object
    \def\@MXV@viewobj{%
      %projection dict
      \special{pdf:obj @pdict\the\@MXV@includes_\the\@MXV@viewscount <<%
        /Subtype/P/FOV \@MXV@aac/PS/Min%
      >>}%
      %
      \special{pdf:obj @viewobj\the\@MXV@includes_\the\@MXV@viewscount <<%
        /MS/M% define the view as C2W matrix
        /CO \@MXV@roo% orbital radius
        /P @pdict\the\@MXV@includes_\the\@MXV@viewscount%
        /C2W [\@MXV@matrix]%
        /XN(\@MXV@xname)% name of the view appearing in the drop down list
        \@MXV@background%
        \@MXV@lights%
        \@MXV@render%
      >>}%
      \xdef\@MXV@@viewobj{@viewobj\the\@MXV@includes_\the\@MXV@viewscount}%
    }%

    %macro for creating resource objects from 3D and image files, to be used
    %in 3D JavaScript
    \def\@MXV@addresource#1{%
      %determine file type
      \filename@parse{#1}%
      \ifthenelse{%
        \equal{\filename@ext}{u3d}\OR%
        \equal{\filename@ext}{U3D}%
      }{%
        \def\@MXV@restype{U3D}%
      }{%
        \def\@MXV@restype{image}%
      }%
      \ifthenelse{\equal{\@MXV@restype}{image}}{%
        %embed the same image file only once
        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
          %increment counter of embedded resource files
          \global\advance\@MXV@rescount by 1%
          %create Image XObject from next raster image
          \special{pdf:image @resource\the\@MXV@rescount\space(#1)}%
          \xdef\@MXV@resourcetree{% build name tree for embedded resources
            \@MXV@resourcetree\space(#1) @resource\the\@MXV@rescount%
          }%
          \@MXV@newlabel{\pdfmdfivesum file {#1}}{@resource\the\@MXV@rescount}%
        }{%
          \xdef\@MXV@resourcetree{%
            \@MXV@resourcetree\space(#1) \@MXV@getlabelvalue{\pdfmdfivesum file {#1}}%
          }%
        }%
      }{%
        %embed the same 3D file only once
        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
          \global\advance\@MXV@rescount by 1%
          \special{pdf:fstream @resource\the\@MXV@rescount\space(#1) <<%
            /Subtype/\@MXV@restype>>}%
          \xdef\@MXV@resourcetree{%
            \@MXV@resourcetree\space(#1) @resource\the\@MXV@rescount%
          }%
          \@MXV@newlabel{\pdfmdfivesum file {#1}}{@resource\the\@MXV@rescount}%
        }{%
          \xdef\@MXV@resourcetree{%
            \@MXV@resourcetree\space(#1) \@MXV@getlabelvalue{\pdfmdfivesum file {#1}}%
          }%
        }%
      }%
    }

    %3D inclusion macro
    \newcommand{\@MXV@includeiiid}[5][]{%
      %insert box or poster
      \@MXV@box{#2}{#3}{#4}%
      %
      \if@MXV@externalviewer\else%
        \setkeys{MXV@iiid}{#1}%process deferred options
        \ifnum\@MXV@iiidrepeat=0\else%
          \edef\@MXV@animstyle{% animation style dict
            /AN <<%
              \@MXV@iiidpalindrome\@MXV@iiidrate/PC \the\@MXV@iiidrepeat%
            >>%
          }%
        \fi%
        %java script file, stream object
        \IfFileExists{\@MXV@jscriptiiidfile}{%
          \special{pdf:fstream @jscriptiiid\the\@MXV@includes\space(\@MXV@jscriptiiidfile)}%
          \xdef\@MXV@jscriptiiid{/OnInstantiate @jscriptiiid\the\@MXV@includes}%
        }{\xdef\@MXV@jscriptiiid{}}%
        %
        %build the array of 3D views
        \@MXV@buildva%
      \fi%
      %
      %3D stream object
      \if@MXV@inline%
        \ifthenelse{%
          \NOT\boolean{@MXV@presentation}\OR%
          \equal{\@MXV@getlabelvalue{\@MXV@label.3dstream}}{undefined}%
        }{%
          \special{pdf:fstream @iiiDfile\the\@MXV@includes\space(#5) <<%
            /Subtype/\@MXV@iiidsubtype%
            \if@MXV@externalviewer\else%
              /VA [\@MXV@varray]%
              /DV/F% use first entry in VA as default view
              \@MXV@animstyle%
              \@MXV@jscriptiiid%
              \if@MXV@resource%
                /Resources <</Names [\@MXV@resourcetree]>>%
              \fi%
            \fi%
          >>}%
          \edef\@MXV@iiidstream{@iiiDfile\the\@MXV@includes}%
          \if@MXV@presentation%
            \@MXV@newlabel{\@MXV@label.3dstream}{\@MXV@iiidstream}%
          \fi%
        }{%
          \edef\@MXV@iiidstream{\@MXV@getlabelvalue{\@MXV@label.3dstream}}%
        }%
      \fi%
      %
      \makebox[0pt][r]{\makebox[#2][l]{%
      %insert FileAttachment annotation
      \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}%
%        since Reader 7.0.7, we cannot place a file attachment annot behind
%        the 3D annot :-(
%        \OR\boolean{@MXV@attachment}
      }{%
        \special{pdf:annot width \the#2 height \the#3 depth \the#4 <<%
          /Subtype /FileAttachment%
          /F 0%
          /T (\@MXV@filename)%
          /Contents (3D Object (\@MXV@mime))%
          \if@MXV@externalviewer%
            /Name/Paperclip%
            /C [1 1 1]%
          \else%
            /AP <</N<<>>/R<<>>/D<<>>>>%
          \fi%
          /FS <<%
            /F(#5)%
            /Type/Filespec%
            /EF << /F \@MXV@iiidstream >>%
          >>%
        >>}%
      }{%
        \if@MXV@url%
          %insert Link annotation, if 3D file is a URL
          \special{pdf:annot width \the#2 height \the#3 depth \the#4 <<%
            /Subtype /Link%
            /F 0%
            \if@MXV@externalviewer%
              \@MXV@urlattr%
            \else%
              /H /N%
              /Border [0 0 0]%
            \fi%
            /A <</URI (#5) /S/URI>>%
            /Contents (3D Object (\@MXV@mime))%
          >>}%
        \else%
          %else insert Launch action for local external 3D file
          \if@MXV@inline\else%
            \special{pdf:annot width \the#2 height \the#3 depth \the#4 <<%
              /Subtype /Link%
              /F 0%
              \if@MXV@externalviewer%
                \@MXV@runattr%
              \else%
                /H /N%
                /Border [0 0 0]%
              \fi%
              /A <<%
                /F (#5)%
                /S /Launch%
              >>%
              /Contents (3D Object (\@MXV@mime))%
            >>}%
          \fi%
        \fi%
      }%
      %
      \if@MXV@externalviewer\else%
        %appearance dict dummy, to be shared by all 3D annots
        \ifthenelse{\isundefined{\@MXV@apdict}}{%
          \special{pdf:stream @apdict\space()<</BBox[0 0 0.001 0.001]>>}%
          \xdef\@MXV@apdict{/AP << /N @apdict >>}%
        }{}%
        %3D reference dict
        \if@MXV@presentation%
          \ifthenelse{%
            \equal{\@MXV@getlabelvalue{\@MXV@label.3dref}}{undefined}%
          }{%
            \special{pdf:obj @iiiDref\the\@MXV@includes <<%
              /Type/3DRef%
              /3DD \@MXV@iiidstream% 3D stream object
            >>}%
            \edef\@MXV@iiidstreamorref{@iiiDref\the\@MXV@includes}%
            \@MXV@newlabel{\@MXV@label.3dref}{\the\pdflastobj}%
          }{%
            \edef\@MXV@iiidstreamorref{\@MXV@getlabelvalue{\@MXV@label.3dref}}%
          }%
        \else%
          \edef\@MXV@iiidstreamorref{\@MXV@iiidstream}%
        \fi%
        %annotation object of subtype `3D'
        \special{pdf:annot @3Dannot\the\@MXV@includes\space width \the#2 height \the#3 depth \the#4 <<%
          /Subtype/3D%
          /F 4% we cannot put F 5 here; bug in Reader; 3D annot would be
          /T (\@MXV@filename)%    disabled even if plugin were available
          /Contents (3D Object (\@MXV@mime))%
          \ifx\@MXV@@label\@empty\else%
            /NM (\@MXV@@label)%
          \fi%
          /P @thispage%
          \@MXV@apdict% /AP <</N<<>>/R<<>>/D<<>>>> doesn't work here
          \@MXV@defaultview%
          \@MXV@iiidia%
          /3DD \@MXV@iiidstreamorref% 3D stream or reference object
          /3DA << \@MXV@activation\@MXV@deactivation\@MXV@iiidtoolb >>%
        >>}%
        %label for later annot obj number determination, to be used in
        %movieref's
        \ifx\@MXV@@label\@empty\else%
          \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{@3Dannot\the\@MXV@includes}%
          \@MXV@newlabel{@MXV@\@MXV@@label.annot}{@3Dannot\the\@MXV@includes}%
        \fi%
      \fi}}%
    }%
  \else%
    %dvips versions
    %macro for creating 3D view object and associated projection dict
    \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%
            \@MXV@lights%
            \@MXV@render%
          >>%
        }%
      }%
      \xdef\@MXV@@viewobj{{viewobj\the\@MXV@includes_\the\@MXV@viewscount}}%
    }%
    %
    %macro for creating resource objects from 3D and image files
    \def\@MXV@addresource#1{%
      %determine file type
      \filename@parse{#1}%
      \ifthenelse{%
        \equal{\filename@ext}{u3d}\OR%
        \equal{\filename@ext}{U3D}%
      }{%
        \def\@MXV@restype{U3D}%
      }{%
        \def\@MXV@restype{image}%
      }%
      \ifthenelse{\equal{\@MXV@restype}{image}}{%
        %embed the same image file only once
        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
          %increment counter of embedded resource files
          \global\advance\@MXV@rescount by 1%
          %create Image XObject from next raster image
          \special{ps:% read image resource from file
            [ /_objdef {resource\the\@MXV@rescount} /NI pdfmark
            save gsave
            {
              /showpage {} def
              /setpagedevice /pop load def
              newpath clip
              (#1) run
            } ?pdfmark
            0 0 1 [1 0 0 1 0 0] {} image %empty dummy, in case #1 is not
            grestore restore             %a valid image file
          }%
          \xdef\@MXV@resourcetree{% build name tree for embedded resources
            \@MXV@resourcetree\space (#1) {resource\the\@MXV@rescount}%
          }%
          \@MXV@newlabel{\pdfmdfivesum file {#1}}{resource\the\@MXV@rescount}%
        }{%
          \xdef\@MXV@resourcetree{%
            \@MXV@resourcetree\space (#1) {\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}%
          }%
        }%
      }{%
        %embed the same 3D file only once
        \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}{undefined}}{%
          \global\advance\@MXV@rescount by 1%
          \special{ps:
            [ /_objdef {resource\the\@MXV@rescount} /type/stream /OBJ pdfmark
            [ {resource\the\@MXV@rescount} <<%
                /Subtype/\@MXV@restype%
              >> /PUT pdfmark%
            [ {resource\the\@MXV@rescount} (#1) (r) file /PUT pdfmark
          }%
          \xdef\@MXV@resourcetree{%
            \@MXV@resourcetree\space (#1) {resource\the\@MXV@rescount}%
          }%
          \@MXV@newlabel{\pdfmdfivesum file {#1}}{resource\the\@MXV@rescount}%
        }{%
          \xdef\@MXV@resourcetree{%
            \@MXV@resourcetree\space (#1) {\@MXV@getlabelvalue{\pdfmdfivesum file {#1}}}%
          }%
        }%
      }%
    }
    %
    %3D inclusion macro
    \newcommand{\@MXV@includeiiid}[5][]{%
      %
      \if@MXV@externalviewer\else%
        \setkeys{MXV@iiid}{#1}%process deferred options
        \ifnum\@MXV@iiidrepeat=0\else%
          \edef\@MXV@animstyle{% animation style dict
            /AN <<%
              \@MXV@iiidpalindrome\@MXV@iiidrate/PC \the\@MXV@iiidrepeat%
            >>%
          }%
        \fi%
        %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%
            }%
          }%
          \xdef\@MXV@jscriptiiid{%
            /OnInstantiate {jscriptiiid\the\@MXV@includes}%
          }%
        }{\def\@MXV@jscriptiiid{}}%
        %
        %build the array of 3D views
        \@MXV@buildva%
      \fi%
      %
      %3D stream object
      \if@MXV@inline%
        \ifthenelse{%
          \NOT\boolean{@MXV@presentation}\OR%
          \equal{\@MXV@getlabelvalue{\@MXV@label.3dstream}}{undefined}%
        }{%
         \pdfmark{%
            pdfmark=/OBJ,%
            Raw={%
              /_objdef {iiiDfile\the\@MXV@includes}%
              /type/stream%
            }%
          }%
          \pdfmark{%
            pdfmark=/PUT,%
            Raw={%
              {iiiDfile\the\@MXV@includes} <<%
                /Subtype/\@MXV@iiidsubtype%
                \if@MXV@externalviewer\else%
                  /VA [\@MXV@varray]%
                  /DV/F% use first entry in VA as default view
                  \@MXV@animstyle%
                  \if@MXV@resource%
                    /Resources <<%
                      /Names [\@MXV@resourcetree]%
                    >>%
                  \fi%
                  \@MXV@jscriptiiid%
                \fi%
              >>%
            }%
          }%
          \pdfmark{%
            pdfmark=/PUT,%
            Raw={%
              {iiiDfile\the\@MXV@includes}%
              (#5) (r) file%
            }%
          }%
          \edef\@MXV@iiidstream{iiiDfile\the\@MXV@includes}%
          \if@MXV@presentation%
            \@MXV@newlabel{\@MXV@label.3dstream}{\@MXV@iiidstream}%
          \fi%
        }{%
          \edef\@MXV@iiidstream{\@MXV@getlabelvalue{\@MXV@label.3dstream}}%
        }%
      \fi%
      %
      %insert FileAttachment annotation
      \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}%
%        \OR\boolean{@MXV@attachment}
      }{%
        \makebox[0pt][l]{%
          \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{%
            pdfmark=/ANN,%
            Subtype=/FileAttachment,%
            Raw={%
              /F 0%
              /T (\@MXV@filename)%
              /Contents (3D Object (\@MXV@mime))%
              \if@MXV@externalviewer%
                /Name/Paperclip%
                /C [1 1 1]%
              \else%
                /AP <</N<<>>/R<<>>/D<<>>>>%
              \fi%
              /FS <<%
                /F(#5)%
                /Type/Filespec%
                /EF <</F {\@MXV@iiidstream}>>%
              >>%
            }%
          }%
        }%
      }{%
        \if@MXV@url%
          %insert Link annotation, if 3D file is a URL
          \makebox[0pt][l]{%
            \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{%
              pdfmark=/ANN,%
              Subtype=/Link,%
              Raw={%
                /F 0%
                \if@MXV@externalviewer%
                  /C [\@urlbordercolor]%
                  /H \@pdfhighlight%
                \else%
                  /H /N%
                  /Border [0 0 0]%
                \fi%
                /Action <</URI (#5) /S/URI>>%
                /Contents (3D Object (\@MXV@mime))%
              }%
            }%
          }%
        \else%
          %else insert Launch action for local external 3D file
          \if@MXV@inline\else%
            \makebox[0pt][l]{%
              \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{%
                pdfmark=/ANN,%
                Subtype=/Link,%
                Raw={%
                  /F 0%
                  \if@MXV@externalviewer%
                    /C [\@urlbordercolor]%
                    /H \@pdfhighlight%
                  \else%
                    /H /N%
                    /Border [0 0 0]%
                  \fi%
                  /Action <<%
                    /F (#5)%
                    /S /Launch%
                  >>%
                  /Contents (3D Object (\@MXV@mime))%
                }%
              }%
            }%
          \fi%
        \fi%
      }%
      \if@MXV@externalviewer%
        \phantom{\@MXV@box{#2}{#3}{#4}}%
      \else%
        %appearance dict dummy, to be shared by all 3D annots
        \ifthenelse{\isundefined{\@MXV@apdict}}{%
          \pdfmark{%
            pdfmark=/OBJ,%
            Raw={%
              /_objdef {apdict}%
              /type/stream%
            }%
          }%
          \pdfmark{%
            pdfmark=/PUT,%
            Raw={%
              {apdict}%
              ()%
            }%
          }%
          \pdfmark{%
            pdfmark=/PUT,%
            Raw={%
              {apdict}
			  <</BBox [0 0 0.001 0.001]>>
            }%
          }%
          \xdef\@MXV@apdict{/AP << /N {apdict}>>}%
        }{}%
        %3D reference dict
        \if@MXV@presentation%
          \ifthenelse{%
            \equal{\@MXV@getlabelvalue{\@MXV@label.3dref}}{undefined}%
          }{%
            \pdfmark{%
              pdfmark=/OBJ,%
              Raw={%
                /_objdef {iiiDref\the\@MXV@includes}%
                /type/dict%
              }%
            }%
            \pdfmark{%
              pdfmark=/PUT,%
              Raw={%
                {iiiDref\the\@MXV@includes} <<%
                  /Type/3DRef%
                  /3DD {\@MXV@iiidstream}% 3D stream object
                >>%
              }%
            }%
            \edef\@MXV@iiidstreamorref{iiiDref\the\@MXV@includes}%
            \@MXV@newlabel{\@MXV@label.3dref}{\@MXV@iiidstreamorref}%
          }{%
            \edef\@MXV@iiidstreamorref{\@MXV@getlabelvalue{\@MXV@label.3dref}}%
          }%
        \else%
          \edef\@MXV@iiidstreamorref{\@MXV@iiidstream}%
        \fi%
        %annotation object of subtype `3D'
        \pdfmark[\phantom{\@MXV@box{#2}{#3}{#4}}]{%
          pdfmark=/ANN,%
          Subtype=/3D,%
          Raw={%
            /_objdef {3Dannot\the\@MXV@includes}%
            /F 4%
            /T (\@MXV@filename)%
            \ifx\@MXV@@label\@empty\else%
              /NM (\@MXV@@label)%
            \fi%
            /Contents (3D Object (\@MXV@mime))%
            /P {ThisPage}%
            \@MXV@apdict% /AP <</N<<>>/R<<>>/D<<>>>> doesn't work here
            \@MXV@defaultview%
            \@MXV@iiidia%
            /3DD {\@MXV@iiidstreamorref}% 3D stream or reference object
            /3DA <<\@MXV@activation\@MXV@deactivation\@MXV@iiidtoolb>>%
          }%
        }%
        \ifx\@MXV@@label\@empty\else%
          \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}%
          \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}%
        \fi%
      \fi%
    }%
  \fi\fi%
}{}

%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.settings.privateData.paused=false;
          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.settings.privateData.paused=false;
          e.target.play();
          if(!e.target.isPlaying){%still not playing?!
            %sometimes play() fails, in particular if the movie has reached
            %its end before getting the focus; but this works:
            if(
              e.target.settings.startAt.time
              || e.target.settings.startAt.frame
              || e.target.settings.startAt.marker
              || e.target.id == 'vnd.adobe.swname:AAPL_QuickTime'
            ){
              e.target.seek(e.target.settings.startAt);
            }else{
              e.target.stop();
            }
            e.target.play();
          }
        }
        catch (e){}
      }
      \@MXV@if{#2}%
      else{%
        %media can only be paused if mouse option is set
        try{
          e.target.pause();
          e.target.settings.privateData.paused=true;
        }catch (e){}
      }
      \fi%
      \if@MXV@issound\else e.target.visible=true;\fi%
    },
    onPlay: function (e) {%
      e.target.settings.privateData.paused=false;
    },
    onPause: function (e) {%
      e.target.settings.privateData.paused=true;
    },
    afterReady: function (e) {%
      try{
        if(
          e.target.settings.startAt.time
          || e.target.settings.startAt.frame
          || e.target.settings.startAt.marker
        ){
          e.target.play();
          e.target.pause();
          e.target.stop();
          e.target.settings.privateData.paused=false;
          e.target.seek(e.target.settings.startAt);
        }
        \if@MXV@issound\else e.target.visible=true;\fi%
        \@MXV@if{#3}
          e.target.settings.privateData.paused=false;
          e.target.play();
        \fi
      }
      catch (e){}
    }
  });
}%

%output driver specific implementations of the 2D inclusion macro
\ifpdf%
  %pdfLaTeX version
  \def\@MXV@includemovie#1#2#3#4{%
    %insert box or poster
    \@MXV@box{#1}{#2}{#3}%
    %
    \if@MXV@externalviewer\else%
      %new action dict
      \pdfobj reserveobjnum%
      \@MXV@adict=\pdflastobj%
      %
      %new additional actions dict
      \pdfobj reserveobjnum%
      \@MXV@aadict=\pdflastobj%
      %
    \fi%
    %embedded file entry `/EF'
    \if@MXV@inline%
      %embed the same media file only once
      \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}{undefined}}{%
        \pdfobj stream %
          attr {%
              /Type/EmbeddedFile%
              /Subtype (\@MXV@mime)%
          }%
          file {#4}%
          \pdfrefobj\pdflastobj%
          \edef\@MXV@efentry{%
          /EF << /F \the\pdflastobj\space 0 R >>%
        }%
        \@MXV@newlabel{\pdfmdfivesum file {#4}}{\the\pdflastobj}%
      }{%
        \edef\@MXV@efentry{%
          /EF << /F \@MXV@getlabelvalue{\pdfmdfivesum file {#4}}\space 0 R >>%
        }%
      }%
    \else\def\@MXV@efentry{}\fi%
    %
    \ifthenelse{\boolean{@MXV@externalviewer}\AND\NOT\boolean{@MXV@inline}}{}{%
      %new file specification object
      \pdfobj {<<%
        /F(#4)%
        \@MXV@fsentry%
        \@MXV@efentry%
        /Type/Filespec%
      >>}\pdfrefobj\pdflastobj%
      \edef\@MXV@filespec{\the\pdflastobj}%
    }%
    %
    \makebox[0pt][r]{\makebox[#1][l]{%
    %insert FileAttachment annotation
    \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}\OR%
      \boolean{@MXV@attachment}%
    }{%
      \pdfannot width #1 height #2 depth #3 {%
        /Subtype /FileAttachment%
        /F 0%
        /T (\@MXV@filename)%
        /Contents (Media File (\@MXV@mime))%
        \if@MXV@externalviewer%
          %a coloured border, as with external links, would be much nicer
          /Name/Paperclip%
          /C [1 1 1]%
        \else%
          /AP <</N<<>>/R<<>>/D<<>>>>%
        \fi%
        /FS \@MXV@filespec\space 0 R%
      }%
    }{%
      \if@MXV@url%
        %insert Link annotation, if media file is a URL
        \pdfannot width #1 height #2 depth #3 {%
          /Subtype /Link%
          /F 0%
          \if@MXV@externalviewer%
            \@MXV@urlattr%
          \else%
            /H /N%
            /Border [0 0 0]%
          \fi%
          /A <</URI (#4) /S/URI>>%
          /Contents (Media File (\@MXV@mime))%
        }%
      \else%
        %else insert Launch action for local external media file
        \if@MXV@inline\else%
          \pdfannot width #1 height #2 depth #3 {%
            /Subtype /Link%
            /F 0%
            \if@MXV@externalviewer%
              \@MXV@runattr%
            \else%
              /H /N%
              /Border [0 0 0]%
            \fi%
            /A <<%
              /F (#4)%
              /S /Launch%
            >>%
            /Contents (Media File (\@MXV@mime))%
          }%
        \fi%
      \fi%
    }%
    %
    \if@MXV@externalviewer\else%
      %annotation object of subtype `Screen'
      \pdfannot width #1 height #2 depth #3 {%
        /Subtype /Screen%
        /Border [0 0 0]% no border (PDF-1.1)
        /BS <</S/S/W 0>>% no border (PDF-1.5)
        /F 5% disable annot if multimedia is not available
        /T (\@MXV@filename)%
        /Contents (Media File (\@MXV@mime))%
        /P \@MXV@pdfpageref{@MXV@annot\the\@MXV@includes.page} 0 R%
        /A \the\@MXV@adict\space 0 R%
        /AA \the\@MXV@aadict\space 0 R%
        /AP <</N<<>>/R<<>>/D<<>>>>%
      }\edef\@MXV@screenannot{\the\pdflastannot}%
      %label for later annot obj number determination, to be used in
      %movieref's only
      \ifx\@MXV@@label\@empty\else%
        \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\@MXV@screenannot}%
        \@MXV@newlabel{@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%
        /SP <</BE<</O 0.0>>>>%
        /P <<%
          \@MXV@player%
          /BE <<%
            /F 2%
            \@MXV@@repeat\@MXV@@volume\@MXV@@ctrls%
            /D <</S /F>>%
          >>%
        >>%
      >>}\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}%
        \@MXV@newlabel{@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%
    \fi}}%
  }%
\else\if@MXV@dvipdfmx
  %dvipdfmx version
  \def\@MXV@includemovie#1#2#3#4{%
    %insert box or poster
    \@MXV@box{#1}{#2}{#3}%
    %
    \if@MXV@externalviewer\else%
      %new action dict
      \special{pdf:obj @MXV@adict\the\@MXV@includes << >>}%
      %
      %new additional actions dict
      \special{pdf:obj @MXV@aadict\the\@MXV@includes << >>}%
      %
    \fi%
    %embedded file entry `/EF'
    \if@MXV@inline%
      %embed the same media file only once
      \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}{undefined}}{%
        \special{pdf:fstream @fstream\the\@MXV@includes\space(#4) <<%
          /Type/EmbeddedFile%
          /Subtype (\@MXV@mime)%
        >>}%
        \edef\@MXV@efentry{%
          /EF << /F @fstream\the\@MXV@includes >>%
        }%
        \@MXV@newlabel{\pdfmdfivesum file {#4}}{@fstream\the\@MXV@includes}%
      }{%
        \edef\@MXV@efentry{%
          /EF << /F \@MXV@getlabelvalue{\pdfmdfivesum file {#4}} >>%
        }%
      }%
    \else\def\@MXV@efentry{}\fi%
    %
    \ifthenelse{\boolean{@MXV@externalviewer}\AND\NOT\boolean{@MXV@inline}}{}{%
      %new file specification object
      \special{pdf:obj @filespec\the\@MXV@includes <<%
        /F(#4)%
        \@MXV@fsentry%
        \@MXV@efentry%
        /Type/Filespec%
      >>}%
      \edef\@MXV@filespec{@filespec\the\@MXV@includes}%
    }%
    %
    \makebox[0pt][r]{\makebox[#1][l]{%
    %insert FileAttachment annotation
    \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}\OR%
      \boolean{@MXV@attachment}%
    }{%
      \special{pdf:annot width \the#1 height \the#2 depth \the#3 <<%
        /Subtype /FileAttachment%
        /F 0%
        /T (\@MXV@filename)%
        /Contents (Media File (\@MXV@mime))%
        \if@MXV@externalviewer%
          %a coloured border, as with external links, would be much nicer
          /Name/Paperclip%
          /C [1 1 1]%
        \else%
          /AP <</N<<>>/R<<>>/D<<>>>>%
        \fi%
        /FS \@MXV@filespec%
      >>}%
    }{%
      \if@MXV@url%
        %insert Link annotation, if media file is a URL
        \special{pdf:annot width \the#1 height \the#2 depth \the#3 <<%
          /Subtype /Link%
          /F 0%
          \if@MXV@externalviewer%
            \@MXV@urlattr%
          \else%
            /H /N%
            /Border [0 0 0]%
          \fi%
          /A <</URI (#4) /S/URI>>%
          /Contents (Media File (\@MXV@mime))%
        >>}%
      \else%
        %else insert Launch action for local external media file
        \if@MXV@inline\else%
          \special{pdf:annot width \the#1 height \the#2 depth \the#3 <<%
            /Subtype /Link%
            /F 0%
            \if@MXV@externalviewer%
              \@MXV@runattr%
            \else%
              /H /N%
              /Border [0 0 0]%
            \fi%
            /A <<%
              /F (#4)%
              /S /Launch%
            >>%
            /Contents (Media File (\@MXV@mime))%
          >>}%
        \fi%
      \fi%
    }%
    %
    \if@MXV@externalviewer\else%
      %annotation object of subtype `Screen'
      \special{pdf:annot @screenannot\the\@MXV@includes\space width \the#1 height \the#2 depth \the#3 <<%
        /Subtype /Screen%
        /Border [0 0 0]% no border (PDF-1.1)
        /BS <</S/S/W 0>>% no border (PDF-1.5)
        /F 5% disable annot if multimedia is not available
        /T (\@MXV@filename)%
        /Contents (Media File (\@MXV@mime))%
        /P @thispage%
        /A @MXV@adict\the\@MXV@includes%
        /AA @MXV@aadict\the\@MXV@includes%
        /AP <</N<<>>/R<<>>/D<<>>>>%
      >>}%
      \edef\@MXV@screenannot{@screenannot\the\@MXV@includes}%
      %label for later annot obj number determination, to be used in
      %movieref's only
      \ifx\@MXV@@label\@empty\else%
        \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\@MXV@screenannot}%
        \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\@MXV@screenannot}%
      \fi%
      %
      %new media clip object of subtype `Media Clip Data' (/S/MCD)
      \special{pdf:obj @mediaclipdata\the\@MXV@includes <<%
        /D \@MXV@filespec%
        /P <</TF(TEMPACCESS)>>%
        /S/MCD%
        /CT (\@MXV@mime)%
      >>}%
      %
      %new rendition object of subtype `Media Rendition' (/S/MR)
      \special{pdf:obj @mediarendition\the\@MXV@includes <<%
        /C @mediaclipdata\the\@MXV@includes%
        /S/MR%
        /SP <</BE<</O 0.0>>>>%
        /P <<%
          \@MXV@player%
          /BE <<%
            /F 2%
            \@MXV@@repeat\@MXV@@volume\@MXV@@ctrls%
            /D <</S /F>>%
          >>%
        >>%
      >>}%
      \edef\@MXV@mediarendition{@mediarendition\the\@MXV@includes}%
      %label for later rendition obj number determination
      \ifx\@MXV@@label\@empty\else%
        \@MXV@labeltoaux{@MXV@\@MXV@@label.rendition}{\@MXV@mediarendition}%
        \@MXV@newlabel{@MXV@\@MXV@@label.rendition}{\@MXV@mediarendition}%
      \fi%
      %
      %action dictionary
      \special{pdf:put @MXV@adict\the\@MXV@includes <<%
        /R \@MXV@mediarendition%
        /S/Rendition%
        /OP 0% fallback if /JS doesn't work or is empty
        \@MXV@activationjsentry%
        /AN \@MXV@screenannot%
      >>}%
      %
      %create play/stop/resume/pause actions
      \special{pdf:obj @pageopenaction\the\@MXV@includes <<%
        /R \@MXV@mediarendition%
        /S/Rendition%
        \@MXV@pageopenopentry% /OP fallback if /JS doesn't work
        \@MXV@pageopenjsentry%
        /AN \@MXV@screenannot%
      >>}%
      \edef\@MXV@pageopenaction{@pageopenaction\the\@MXV@includes}%
      %
      \special{pdf:obj @pagecloseaction\the\@MXV@includes <<%
        /R \@MXV@mediarendition%
        /S/Rendition%
        \@MXV@pagecloseopentry%
        \@MXV@pageclosejsentry%
        /AN \@MXV@screenannot%
      >>}%
      \edef\@MXV@pagecloseaction{@pagecloseaction\the\@MXV@includes}%
      %
      %populate additional actions dictionary
      \special{pdf:put @MXV@aadict\the\@MXV@includes <<%
        /PO \@MXV@pageopenaction%
        /PC \@MXV@pagecloseaction%
      >>}%
    \fi}}%
  }%
\else%
  %dvips version
  \def\@MXV@includemovie#1#2#3#4{%
    %insert FileAttachment annotation
    \ifthenelse{\boolean{@MXV@inline}\AND\boolean{@MXV@externalviewer}\OR%
      \boolean{@MXV@attachment}%
    }{%
      \makebox[0pt][l]{%
        \pdfmark[\phantom{\@MXV@box{#1}{#2}{#3}}]{%
          pdfmark=/ANN,%
          Subtype=/FileAttachment,%
          Raw={%
            /F 0%
            /T (\@MXV@filename)%
            /Contents (Media File (\@MXV@mime))%
            \if@MXV@externalviewer%
              /Name/Paperclip%
              /C [1 1 1]%
            \else%
              /AP <</N<<>>/R<<>>/D<<>>>>%
            \fi%
            /FS {filespec\the\@MXV@includes}%
          }%
        }%
      }%
    }{%
      \if@MXV@url%
        %insert Link annotation, if media file is a URL
        \makebox[0pt][l]{%
          \pdfmark[\phantom{\@MXV@box{#1}{#2}{#3}}]{%
            pdfmark=/ANN,%
            Subtype=/Link,%
            Raw={%
              /F 0%
              \if@MXV@externalviewer%
                /C [\@urlbordercolor]%
                /H \@pdfhighlight%
              \else%
                /H /N%
                /Border [0 0 0]%
              \fi%
              /Action <</URI (#4) /S/URI>>%
              /Contents (Media File (\@MXV@mime))%
            }%
          }%
        }%
      \else%
        %else insert Launch action for local external media file
        \if@MXV@inline\else%
          \makebox[0pt][l]{%
            \pdfmark[\phantom{\@MXV@box{#1}{#2}{#3}}]{%
              pdfmark=/ANN,%
              Subtype=/Link,%
              Raw={%
                /F 0%
                \if@MXV@externalviewer%
                  /C [\@urlbordercolor]%
                  /H \@pdfhighlight%
                \else%
                  /H /N%
                  /Border [0 0 0]%
                \fi%
                /Action <<%
                  /F (#4)%
                  /S /Launch%
                >>%
                /Contents (Media File (\@MXV@mime))%
              }%
            }%
          }%
        \fi%
      \fi%
    }%
    %
    \if@MXV@externalviewer%
      \@MXV@box{#1}{#2}{#3}%
    \else%
      %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 (\@MXV@filename)%
          /Contents (Media File (\@MXV@mime))%
          /BS <</S/S/W 0>>% no border (PDF-1.5)
          /P {ThisPage}%
          /AA {aadict\the\@MXV@includes}%
          /AP <</N<<>>/R<<>>/D<<>>>>%
        }%
      }%
      \ifx\@MXV@@label\@empty\else%
        \@MXV@labeltoaux{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}%
        \@MXV@newlabel{@MXV@\@MXV@@label.annot}{\the\@MXV@includes}%
      \fi%
      %
      %entire action entry moved outside screen annotation
      \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%
            %screen parameters: fully transparent, hidden if audio mime type
            /SP <</BE<</O 0.0>>>>%
            /P <<%Media Play Parameters
              \@MXV@player%
              /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
          >>%
        }%
      }%
    \fi%
    %
    %new file specification object
    \ifthenelse{\boolean{@MXV@externalviewer}\AND\NOT\boolean{@MXV@inline}}{}{%
      \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'
    \if@MXV@inline%
      %embed the same media file only once
      \ifthenelse{\equal{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}{undefined}}{%
        %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%
              /Subtype(\@MXV@mime)%
            >>%
          }%
        }%
        \edef\@MXV@moviestream{fstream\the\@MXV@includes}%
        \@MXV@newlabel{\pdfmdfivesum file {#4}}{fstream\the\@MXV@includes}%
      }{%
        \edef\@MXV@moviestream{\@MXV@getlabelvalue{\pdfmdfivesum file {#4}}}%
      }%
      % put the embedded file entry into file spec object
      \pdfmark{%
        pdfmark=/PUT,%
        Raw={%
          {filespec\the\@MXV@includes} <<%
            /EF << /F {\@MXV@moviestream} >>%
          >>%
        }%
      }%
    \fi%
    %
    \if@MXV@externalviewer\else%
      %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}%
          >>%
        }%
      }%
    \fi%
  }%
\fi\fi

%definition of user command `\includemovie'
\newcommand{\includemovie}[4][]{%
  %test for hyperref package
  \ifpdf\else%
    \ifthenelse{\isundefined{\pdfmark}\AND\isundefined{\@pdfm@mark}}{\@MXV@missing{hyperref}}{}%
  \fi%
  %
  \leavevmode%
  \@MXV@reset% all macros and options
  \setkeys{MXV@user}{#1}% parse options
  %
  %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 the 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}}}%
  }%
  %
  %find out whether the contents should be hidden or not (for presentations)
  \setboolean{@MXV@hide}{false}%
%  \ifthenelse{\boolean{@MXV@powerdot}}{%
%    \ifthenelse{\boolean{pd@overlay}}{}{%
%      \ifthenelse{\pd@method=2}{}{%
%        \setboolean{@MXV@hide}{true}%
%      }%
%    }%
%  }{}%
  \ifthenelse{\boolean{@MXV@beamer}}{%
    \ifthenelse{\boolean{beamer@anotherslide}}{%
      \setboolean{@MXV@hide}{true}%
    }{}%
  }{}%
  %
  \ifthenelse{\boolean{@MXV@hide}}{%
    %insert whitespace instead of annot
    \phantom{\vrule width \@MXV@width height \@MXV@height depth \@MXV@depth}%
  }{%
    \ifthenelse{\NOT\boolean{@MXV@url}\AND\boolean{@MXV@inline}}{%
      \IfFileExists{#4}{}{%
        \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'!
        }%
      }%
    }{}%
    %
    %guess the mime type based on the filename extension
    \filename@parse{#4}%
    \ifthenelse{\equal{\@MXV@mime}{@MXV@auto}}{%
      \@MXV@guessmime{#4}{\filename@ext}}{}%
    \if\filename@ext\relax%
      \xdef\@MXV@filename{\filename@base}%
    \else%
      \xdef\@MXV@filename{\filename@base.\filename@ext}%
    \fi%
    \expandafter\@MXV@@issound\@MXV@mime:%
    %
    %if 3D object is not embedded inline we must use some external player :(
    \ifthenelse{%
      \boolean{@MXV@iiid}%
      \AND\NOT\boolean{@MXV@inline}%
    }{%
      \setboolean{@MXV@externalviewer}{true}%
    }{}%
    %
    %some link attributes (if hyperref not loaded)
    \ifthenelse{\isundefined{\@pdfborder}}{%
      \def\@MXV@urlattr{}%
      \def\@MXV@runattr{}%
    }{%
      \edef\@MXV@urlattr{%
        \if@MXV@beamer%
          /Border [1 1 1]%
        \else%
          /Border [\@pdfborder]%
        \fi%
        /C [\@urlbordercolor]%
        /H \@pdfhighlight%
      }%
      \edef\@MXV@runattr{%
        \if@MXV@beamer%
          /Border [1 1 1]%
        \else%
          /Border [\@pdfborder]%
        \fi%
        /C [\@runbordercolor]%
        /H \@pdfhighlight%
      }%
    }%
    %
    \global\advance\@MXV@includes by 1%increment counter
    %
    %label this annotation for later page number determination
    \@MXV@labeltoaux{@MXV@annot\the\@MXV@includes.page}{%
                       \noexpand\the\@MXV@page}%
    %
    %label this annotation for later annot id number determination &
    %check for multiply-defined labels
    % \@MXV@label  -->  automatic (presentation mode) or user defined label
    % \@MXV@@label = \@MXV@label (non presentation doc classes)
    % \@MXV@@label = \@MXV@label + physical page No. (presentation mode)
    \ifx\@MXV@label\@empty%
      %when used with presentation packages, annots must be labelled,
      %use the media file name, if no label provided
      \ifthenelse{\boolean{@MXV@presentation}}{%
        \xdef\@MXV@label{#4}%
      }{}%
    \fi%
    \ifx\@MXV@label\@empty\else%
      \ifthenelse{\boolean{@MXV@presentation}}{%
        %in presentation mode, the label must be extended by the physical page No.
        \xdef\@MXV@@label{\@MXV@label.\@MXV@getlabelvalue{@MXV@annot\the\@MXV@includes.page}}%
      }{%
        \xdef\@MXV@@label{\@MXV@label}%
      }%
    \fi%
    \ifx\@MXV@@label\@empty\else%
      \ifthenelse{%
        \NOT\equal{\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}{undefined}%
        \AND%
        \NOT\equal{\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}{%
                                                        \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
            @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}%
          }%
        }{}%
      }{}%
      \if@MXV@@draft%
        \@MXV@labeltoaux{@MXV@\@MXV@label.draft}{true}%
      \else%
        \@MXV@labeltoaux{@MXV@\@MXV@label.draft}{false}%
      \fi%
      \@MXV@labeltoaux{@MXV@\@MXV@@label.annotid}{\the\@MXV@includes}%
      \if@MXV@presentation\else%
        \@MXV@newlabel{@MXV@\@MXV@@label.annotid}{\the\@MXV@includes}%
      \fi%
    \fi%
    %
    \ifthenelse{\boolean{@MXV@@draft}}{}{%
    \ifthenelse{\boolean{@MXV@externalviewer}}{%
      \ifx\@MXV@label\@empty\else%
        \@MXV@labeltoaux{@MXV@\@MXV@label.externalviewer}{true}%
        \@MXV@newlabel{@MXV@\@MXV@label.externalviewer}{true}%
      \fi%
    }{%
      %what is to be put into movie link annot depends on the following
      \ifx\@MXV@label\@empty\else%
        \@MXV@labeltoaux{@MXV@\@MXV@label.externalviewer}{false}%
        \@MXV@newlabel{@MXV@\@MXV@label.externalviewer}{false}%
      \fi%
      %
      %depending on options do content specific stuff
      \ifthenelse{\boolean{@MXV@iiid}}{%
        % #### 3D ####
        \if@MXV@externalviewer\else%
          \ifthenelse{\equal{\@MXV@iiidpalindrome}{/Subtype/Oscillating}}{%
            \global\multiply\@MXV@iiidrepeat by 2%
          }{}%
          \ifthenelse{\boolean{@MXV@autoplay}\OR\boolean{@MXV@autoresume}}{%
            \def\@MXV@activation{/A/PV/AIS/L}% open 3D object, run animation
          }{%
            \if@MXV@runposter%
              \def\@MXV@activation{/A/PV/AIS/I}%open 3D obj but don't run animation
            \else%
              \def\@MXV@activation{/A/XA}% explicit activation by user
            \fi%
          }%
          \if@MXV@autostop%
            \def\@MXV@deactivation{/D/PI/DIS/I}%
          \else%
            \if@MXV@autopause%
              \def\@MXV@deactivation{/D/PI/DIS/I}%
            \else%
              \if@MXV@autoclose%
                \def\@MXV@deactivation{/D/PI/DIS/U}%
              \else%@MXV@continue
                \def\@MXV@deactivation{/D/PI/DIS/L}%
              \fi%
            \fi%
          \fi%
          %counter for 3D inclusion on current page
          \ifthenelse{%
            \equal{%
              \@MXV@getlabelvalue{@MXV@annot\the\@MXV@includes.page}%
            }{\@MXV@oldpage}%
          }{%
            \global\advance\@MXV@iiidoncurpage by 1%
          }{%
            \global\@MXV@iiidoncurpage=1%
          }%
          \xdef\@MXV@oldpage{\@MXV@getlabelvalue{%
            @MXV@annot\the\@MXV@includes.page}}%
        \fi%
        \ifx\@MXV@label\@empty\else%
          \@MXV@labeltoaux{@MXV@\@MXV@label.3D}{true}%
          \@MXV@newlabel{@MXV@\@MXV@label.3D}{true}%
          \@MXV@labeltoaux{@MXV@\@MXV@label.3Dlights}{\@MXV@lights}%
          \@MXV@newlabel{@MXV@\@MXV@label.3Dlights}{\@MXV@lights}%
          \@MXV@labeltoaux{@MXV@\@MXV@label.3Drender}{\@MXV@render}%
          \@MXV@newlabel{@MXV@\@MXV@label.3Drender}{\@MXV@render}%
        \fi%
        \ifx\@MXV@@label\@empty\else%
          \@MXV@labeltoaux{@MXV@\@MXV@@label.3Doncurpage}{\the\@MXV@iiidoncurpage}%
          \@MXV@newlabel{@MXV@\@MXV@@label.3Doncurpage}{\the\@MXV@iiidoncurpage}%
        \fi%
      }{%#### 2D ####
        %get the player ID
        \if@MXV@presentation%
          \ifthenelse{%
            \equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}}{undefined}%
          }{%
            \global\advance\@MXV@players by 1%increment counter
          }{%
            \global\@MXV@players=\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}%
          }%
          \@MXV@labeltoaux{@MXV@\@MXV@label.playerid}{\the\@MXV@players}%
          \@MXV@newlabel{@MXV@\@MXV@label.playerid}{\the\@MXV@players}%
          \edef\@MXV@currplayer{\the\@MXV@players}%
        \else%
          \ifx\@MXV@label\@empty\else%
            \@MXV@labeltoaux{@MXV@\@MXV@label.playerid}{\the\@MXV@includes}%
            \@MXV@newlabel{@MXV@\@MXV@label.playerid}{\the\@MXV@includes}%
          \fi%
          \edef\@MXV@currplayer{\the\@MXV@includes}%
        \fi%
        %
        \ifx\@MXV@startat\@empty% default start position
          \gdef\@MXV@startat{, startAt: 0}%
        \fi%
        %write player settings to aux file
        \ifx\@MXV@label\@empty\else%
          \@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}%
          \@MXV@labeltoaux{@MXV@\@MXV@label.3D}{false}%
          \@MXV@labeltoaux{@MXV@\@MXV@label.issound}{%
                    \if@MXV@issound true\else false\fi}%
          %
          \@MXV@newlabel{@MXV@\@MXV@label.mouse}{%
                       \if@MXV@mouse true\else false\fi}%
          \@MXV@newlabel{@MXV@\@MXV@label.showUI}{\@MXV@ctrls}%
          \@MXV@newlabel{@MXV@\@MXV@label.palindrome}{\@MXV@palindrome}%
          \@MXV@newlabel{@MXV@\@MXV@label.repeat}{\@MXV@repeat}%
          \@MXV@newlabel{@MXV@\@MXV@label.rate}{\@MXV@rate}%
          \@MXV@newlabel{@MXV@\@MXV@label.startAt}{\@MXV@startat}%
          \@MXV@newlabel{@MXV@\@MXV@label.endAt}{\@MXV@endat}%
          \@MXV@newlabel{@MXV@\@MXV@label.volume}{\@MXV@volume}%
          \@MXV@newlabel{@MXV@\@MXV@label.autoplay}{%
                    \if@MXV@autoplay true\else false\fi}%
          \@MXV@newlabel{@MXV@\@MXV@label.3D}{false}%
          \@MXV@newlabel{@MXV@\@MXV@label.issound}{%
                    \if@MXV@issound true\else false\fi}%
          %
        \fi%
        %
        \ifthenelse{\boolean{@MXV@autoplay}\OR\boolean{@MXV@runposter}}{%
          \xdef\@MXV@pageopenopentry{/OP 4}%
        }{%
          \if@MXV@autoresume%
            \xdef\@MXV@pageopenopentry{/OP 3}%
          \else%
            \xdef\@MXV@pageopenopentry{/OP 2}%
          \fi%
        }%
        %
        \if@MXV@autostop%
          \xdef\@MXV@pagecloseopentry{/OP 1}%
        \else%
          \if@MXV@autopause%
            \xdef\@MXV@pagecloseopentry{/OP 2}%
          \else%
            \if@MXV@autoclose%
              \xdef\@MXV@pagecloseopentry{/OP 1}%
            \else% @MXV@continue
              \xdef\@MXV@pagecloseopentry{/OP 3}%
            \fi%
          \fi%
        \fi%
        %
        %JavaScripts for playback control
        %script for page invisible event
        \if@MXV@autopause%
          \xdef\@MXV@pageclosejsentry{%
            /JS (
              try{%
                if(player\@MXV@currplayer.isPlaying){%
                  player\@MXV@currplayer.pause();
                  player\@MXV@currplayer.settings.privateData.paused=true;
                }
                focusonplayer=-1; %page change
                player\@MXV@currplayer.visible=false;
              }
              catch(e){}
            )%
          }%
        \else%
          \if@MXV@autostop%
            \xdef\@MXV@pageclosejsentry{%
              /JS (
                try{%
                  player\@MXV@currplayer.settings.privateData.paused=false;
                  %players tend to be bugged, always stop from playing state
                  if(!player\@MXV@currplayer.isPlaying){
                    player\@MXV@currplayer.play();
                  }
                  player\@MXV@currplayer.stop();
                  if(
                    player\@MXV@currplayer.settings.startAt.time
                    || player\@MXV@currplayer.settings.startAt.frame
                    || player\@MXV@currplayer.settings.startAt.marker
                    || player\@MXV@currplayer.id ==
                       'vnd.adobe.swname:AAPL_QuickTime'
                  ){
                    player\@MXV@currplayer.seek(%
                      player\@MXV@currplayer.settings.startAt);
                  }
                  focusonplayer=-1;
                  player\@MXV@currplayer.visible=false;
                }
                catch(e){}
              )%
            }%
          \else%
            \if@MXV@autoclose%
              \xdef\@MXV@pageclosejsentry{%
                /JS (
                  try{%
                    player\@MXV@currplayer.close(app.media.closeReason.general);
                    focusonplayer=-1; %page change
                    player\@MXV@currplayer.visible=false;
                  }
                  catch(e){}
                )%
              }%
            \else%
              \xdef\@MXV@pageclosejsentry{%@MXV@continue
                /JS (
                  try{%
                    focusonplayer=-1; %page change
                    player\@MXV@currplayer.visible=false;
                  }
                  catch(e){}
                )%
              }%
            \fi%
          \fi%
        \fi%
        %
        %script for activation/resume on page open event
        \xdef\@MXV@pageopenjsentry{%
          /JS (
            try{%
              if(player\@MXV@currplayer.isOpen){%
                %drag the player on the current slide (presentation mode)
                player\@MXV@currplayer.page=this.pageNum;
                %... and make it visible
                \if@MXV@issound\else player\@MXV@currplayer.visible=true;\fi%
                %
                %start or resume media which have autoplay option set;
                %also resume paused media which have autoresume option set
                \if@MXV@autoplay%
                  player\@MXV@currplayer.settings.privateData.paused=false;
                  player\@MXV@currplayer.play();
                  if(!player\@MXV@currplayer.isPlaying){% still not playing?!
                    if(
                      player\@MXV@currplayer.settings.startAt.time
                      || player\@MXV@currplayer.settings.startAt.frame
                      || player\@MXV@currplayer.settings.startAt.marker
                      || player\@MXV@currplayer.id=='vnd.adobe.swname:AAPL_QuickTime'
                    ){
                      player\@MXV@currplayer.seek(
                        player\@MXV@currplayer.settings.startAt);
                    }else{
                      player\@MXV@currplayer.stop();
                    }
                    player\@MXV@currplayer.play();
                  }
                \else%
                  \if@MXV@autoresume%
                    if(player\@MXV@currplayer.settings.privateData.paused){%
                      player\@MXV@currplayer.settings.privateData.paused=false;
                      player\@MXV@currplayer.play();
                      if(!player\@MXV@currplayer.isPlaying){%
                        if(
                          player\@MXV@currplayer.settings.startAt.time
                          || player\@MXV@currplayer.settings.startAt.frame
                          || player\@MXV@currplayer.settings.startAt.marker
                          || player\@MXV@currplayer.id ==
                             'vnd.adobe.swname:AAPL_QuickTime'
                        ){
                          player\@MXV@currplayer.seek(%
                            player\@MXV@currplayer.settings.startAt);
                        }else{
                          player\@MXV@currplayer.stop();%
                        }
                        player\@MXV@currplayer.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{\@MXV@currplayer}%
                  {\if@MXV@mouse true\else false\fi}%
                  {\if@MXV@autoplay true\else false\fi}%
                var player\@MXV@currplayer=app.media.openPlayer({%
                  settings: settings,
                  events: events
                });
              \fi%
            }%
          )
        }%
        %
        %script for normal activation by mouse click
        \xdef\@MXV@activationjsentry{%
          /JS (
            app.focusRect=true;%
            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@currplayer}{\if@MXV@mouse true\else false\fi}%
                                                                        {true}%
            var player\@MXV@currplayer=app.media.openPlayer({%
              settings: settings,
              events: events
            });
          )
        }%
      }%
    }%
    }% draft?
    %
    %insert link target, if media has been labelled
    \ifthenelse{\NOT\equal{\@MXV@@label}{}}{%
      \raisebox{\@MXV@height}{%
        \ifpdf%
          \pdfdest name {@MXV@\@MXV@@label} xyz %
        \else%
          \hypertarget{@MXV@\@MXV@@label}{}%
        \fi%
      }%
    }{}%
    %
    \ifthenelse{\boolean{@MXV@@draft}}{%
      \makebox[0pt][l]{\usebox{\@MXV@textbox}}%
      \@MXV@draftbox{\@MXV@width}{\@MXV@height}{\@MXV@depth}{#4}%
    }{%
      %insert textbox, obscured by poster
      \ifthenelse{\boolean{@MXV@boxopt}\AND\NOT\boolean{@MXV@textoverposter}}{%
          \makebox[0pt][l]{\usebox{\@MXV@textbox}}%
      }{}%
      %
      %insert annotation
      \ifthenelse{\boolean{@MXV@iiid}}{%
        \edef\@MXV@iiidopt{[\@MXV@iiidopt]}%
        \expandafter\@MXV@includeiiid\@MXV@iiidopt{\@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}\AND\boolean{@MXV@textoverposter}}{%
          \makebox[0pt][r]{\usebox{\@MXV@textbox}}%
      }{}%
    }%
  }%
}

%for remote control of media
\newcommand\movieref[3][]{%
  \ifpdf\else%
    \ifthenelse{\isundefined{\pdfmark}\AND\isundefined{\@pdfm@mark}}{\@MXV@missing{hyperref}}{}%
  \fi%
  \leavevmode%
  % save text argument
  \savebox{\@MXV@textbox}{\ifHy@colorlinks\color{\@linkcolor}\fi#3}%
  %
  %find out whether the contents should be hidden or not (for presentations)
  \setboolean{@MXV@hide}{false}%
%  \ifthenelse{\boolean{@MXV@powerdot}}{%
%    \ifthenelse{\boolean{pd@overlay}}{}{%
%      \ifthenelse{\pd@method=2}{}{%
%        \setboolean{@MXV@hide}{true}%
%      }%
%    }%
%  }{}%
  \ifthenelse{\boolean{@MXV@beamer}}{%
    \ifthenelse{\boolean{beamer@anotherslide}}{%
      \setboolean{@MXV@hide}{true}%
    }{}%
  }{}%
  %
  \ifthenelse{\boolean{@MXV@hide}}{%
    %put whitespace instead of link annot
    \phantom{\usebox{\@MXV@textbox}}%
  }{%
    \@MXV@reset%
    %
    \xdef\@MXV@label{#2}%
    %
    \global\advance\@MXV@links by 1%increment link counter
    %
    %label this link for later page number determination
    \@MXV@labeltoaux{@MXV@link\the\@MXV@links.page}{\noexpand\the\@MXV@page}%
    %
    \ifthenelse{\boolean{@MXV@presentation}}{%
      %in presentation mode the label must be extended by the physical page No.
      \xdef\@MXV@@label{\@MXV@label.\@MXV@getlabelvalue{@MXV@link\the\@MXV@links.page}}%
    }{%
      \xdef\@MXV@@label{\@MXV@label}%
    }%
    %
    %check if label is defined at all
    \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}{undefined}}{%
      \usebox{\@MXV@textbox}% write out text box
      \PackageWarning{movie15}{%
        Reference `\@MXV@label' on page \thepage \space undefined%
      }%
      \ifthenelse{\isundefined{\@MXV@undefwarning}}{%
        \gdef\@MXV@undefwarning{}%
        \AtEndDocument{%
          \PackageWarningNoLine{movie15}{%
          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\MessageBreak%
          @@ There were undefined references! @@\MessageBreak%
          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}%
        }%
      }{}%
    }{%
      \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.draft}}{true}}{%
        \setboolean{@MXV@@draft}{true}% if the screen annotation is in draft mode
      }{}%
      \if@MXV@@draft\else%
      \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.externalviewer}}{true}}{%
        \setboolean{@MXV@externalviewer}{true}%
      }{%
        \setboolean{@MXV@externalviewer}{false}%
      }%
      \if@MXV@externalviewer\else%
        %movieref used in 3D context?
        \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.3D}}{true}}{%
          \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
            \setboolean{@MXV@iiid}{true}%
          }{%
            \@MXV@neediiiD%
          }%
        }{}%
        %
        %actions completely different in 3D & 2D context
        \ifthenelse{\boolean{@MXV@iiid}}{% #### 3D ####
          %retrieve default lighting scheme
          \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Dlights}}{undefined}}{%
            \edef\@MXV@lights{}%
          }{%
            \edef\@MXV@lights{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Dlights}}%
          }%
          %retrieve default render mode
          \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Drender}}{undefined}}{%
            \edef\@MXV@render{}%
          }{%
            \edef\@MXV@render{\@MXV@getlabelvalue{@MXV@\@MXV@label.3Drender}}%
          }%
          \setkeys{MXV@user}{#1}%
          \if@MXV@defaultviewprovided% define a new view,
            %using any of the coo, c2c, roo, caa options
            \xdef\@MXV@xname{}%
            \edef\@MXV@args{\@MXV@coo\space\@MXV@ctoc\space\@MXV@roo\space\@MXV@roll\space}%
            \expandafter\@MXV@ciiwmatrix\@MXV@args% build C2W matrix
            \@MXV@viewobj% create pdf object of 3D view
            \edef\@MXV@iiidview{\@MXV@@viewobj}%
          %else use the indexed view specified by option `3Dviewindex'
          \fi%
          %
          %create JavaScript (options 3Djscript, 3Dcalculate, 3Dgetview)
          \ifthenelse{\NOT\equal{\@MXV@jscriptiiidfile}{}%
                      \OR\NOT\equal{\@MXV@calc}{}%
                      \OR\boolean{@MXV@iiidgetview}%
          }{%
            \edef\@MXV@linkjscriptiiid{%
              try{%
                %fill hash (annot3D) with refs to Annot3D objects
                annot3D['\@MXV@label']=getAnnots3D(%
                  \@MXV@getlabelvalue{%
                    @MXV@annot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}.page%
                  }-1%
                )[\@MXV@getlabelvalue{@MXV@\@MXV@@label.3Doncurpage}-1];%
                annot3D['\@MXV@label'].activated=true;%
              }catch(e){%
                try{%
                  annot3D=new Array;%
                  annot3D['\@MXV@label']=getAnnots3D(%
                    \@MXV@getlabelvalue{%
                      @MXV@annot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}.page%
                    }-1%
                  )[\@MXV@getlabelvalue{@MXV@\@MXV@@label.3Doncurpage}-1];%
                  annot3D['\@MXV@label'].activated=true;%
                }catch(e){%
                  var spc=String.fromCharCode(32);%
                  app.alert('3D' + spc + 'annotation' + spc + 'could' + spc +%
                  'not' + spc + 'be' + spc + 'activated!');%
                }%
              }%
            }%
            \if@MXV@iiidgetview%
              \edef\@MXV@linkjscriptiiid{%
                \@MXV@linkjscriptiiid
                try{
                  %JavaScript to print the camera settings of the current view
                  var camera=annot3D['\@MXV@label'].context3D.scene.cameras.getByIndex(0);%
                  var coo=camera.targetPosition;%
                  var c2c=camera.position.subtract(coo);%
                  var roo=c2c.length;%
                  c2c.normalize();%
                  %
                  %assemble result string
                  %{<coo_x> <coo_y> <coo_z>}{<c2c_x> <c2c_y> <c2c_z>}{<roo>}{<aac>}
                  var spc=String.fromCharCode(32);%
                  var res='{';%
                  var x = (Math.abs(coo.x) < 1e-18 ? 0 : coo.x);%
                  var y = (Math.abs(coo.y) < 1e-18 ? 0 : coo.y);%
                  var z = (Math.abs(coo.z) < 1e-18 ? 0 : coo.z);%
                  if(Math.sqrt(x*x + y*y + z*z) > 0){%
                    res+=util.printf('\%s' + spc + '\%s' + spc + '\%s',%
                        (Math.abs(x) < 1.001e-6 && Math.abs(x) > 0 ?%
                          util.printf('\%.18f', x): x),%
                        (Math.abs(y) < 1.001e-6 && Math.abs(y) > 0 ?%
                          util.printf('\%.18f', y): y),%
                        (Math.abs(z) < 1.001e-6 && Math.abs(z) > 0 ?%
                          util.printf('\%.18f', z): z)%
                    );%
                  }%
                  res+='}{';%
                  x = (Math.abs(c2c.x) < 1e-18 ? 0 : c2c.x);%
                  y = (Math.abs(c2c.y) < 1e-18 ? 0 : c2c.y);%
                  z = (Math.abs(c2c.z) < 1e-18 ? 0 : c2c.z);%
                  if(!(x==0 && y==-1 && z==0)){%
                    res+=util.printf('\%s' + spc + '\%s' + spc + '\%s',%
                        (Math.abs(x) < 1.001e-6 && Math.abs(x) > 0 ?%
                          util.printf('\%.18f', x): x),%
                        (Math.abs(y) < 1.001e-6 && Math.abs(y) > 0 ?%
                          util.printf('\%.18f', y): y),%
                        (Math.abs(z) < 1.001e-6 && Math.abs(z) > 0 ?%
                          util.printf('\%.18f', z): z)%
                    );%
                  }%
                  res+='}{';%
                  if(roo > 0.11e-17){%
                    res+=util.printf('\%s',%
                      (roo < 1.001e-6 ? util.printf('\%.18f', roo): roo)%
                    );%
                  }%
                  res+='}{';%
                  %determine the camera roll (camera.roll is bugged)
                  %camera up-vector from camera.up, the latter being the positional vector
                  %of the actual camera up-vector tip
                  var up = camera.up.subtract(camera.position);%
                  up.normalize();%
                  %find the camera up-vector up0, that corresponds to zero roll
                  %(Gram-Schmitt orthogonalisation)
                  var worldup=new annot3D['\@MXV@label'].context3D.Vector3();%
                  worldup.set(0,0,1);%
                  var out=c2c.scale(-1);%
                  var up0=worldup.subtract(out.scale(out.dot(worldup)));%
                  up0.normalize();%
                  var up0xup=up0.cross(up);%
                  var roll=0;%
                  if(up0xup.length>0){%
                    up0xup.normalize();%
                    var up0dotup=up.dot(up0);%
                    up0dotup=(Math.abs(up0dotup) > 1 ? Math.round(up0dotup) : up0dotup);%
                    %compute the angle between camera up and up0 vectors
                    roll=Math.acos(up0dotup)*180/Math.PI*out.dot(up0xup);%
                  }%
                  if(util.printf('\%.5f', roll)!=0){%
                    res+=util.printf('\%s', roll);%
                  }%
                  res+='}{';%
                  aac=camera.fov * 180/Math.PI;%
                  if(util.printf('\%.5f', aac)!=30){%
                    res+=util.printf('\%s',%
                      (Math.abs(aac) < 1.001e-6 ? util.printf('\%.18f', aac): aac)%
                    );%
                  }%
                  res+='}';%
                  %open pop-up displaying the result string
                  var settings={%
                    initialize: function(dialog) {%
                      dialog.load({%
                        'text': res%
                      });%
                    },%
                    description: {%
                      name: 'Current' + spc + '3D' + spc + 'Camera' + spc + 'Settings',%
                      elements: [%
                          {%
                            type: 'static_text',%
                            name: 'Add' + spc + 'the' + spc + 'following' + spc + 'line' + spc +%
                                  'to' + spc + 'a' + spc + 'file' + spc + 'of' + spc +%
                                  'predefined' + spc + 'views.' + spc +%
                                  '(See' + spc + 'option' + spc + '3Dviews!)'%
                          },%
                          {%
                            type: 'edit_text',%
                            item_id: 'text',%
                            alignment: 'align_fill',%
                            readonly: false%
                          },%
                          {%
                            type: 'ok',%
                            ok_name: 'Close'%
                          }%
                      ]%
                    }%
                  };%
                  app.execDialog(settings);%
                }catch(e){%
                    var spc=String.fromCharCode(32);%
                    app.alert('Error' + spc + 'while' + spc + 'executing' + spc +%
                    '3Dgetview:' + spc + e);%
                }%
              }%
            \fi%
            \ifx\@MXV@calc\@empty\else%
              \edef\@MXV@linkjscriptiiid{%
                \@MXV@linkjscriptiiid
                try{
%                  console.show();
%                  console.clear();
                  %constructor for doubly linked list
                  function List(){%
                    this.first_node=null;%
                    this.last_node=new Node(undefined);%
                  }%
                  List.prototype.push_back=function(x){%
                    var new_node=new Node(x);%
                    if(this.first_node==null){%
                      this.first_node=new_node;%
                      new_node.prev=null;%
                    }else{%
                      new_node.prev=this.last_node.prev;%
                      new_node.prev.next=new_node;%
                    }%
                    new_node.next=this.last_node;%
                    this.last_node.prev=new_node;%
                  };%
                  List.prototype.move_to_front=function(it){%
                    var node=it.get();%
                    if(node.next!=null && node.prev!=null){%
                      node.next.prev=node.prev;%
                      node.prev.next=node.next;%
                      node.prev=null;%
                      node.next=this.first_node;%
                      this.first_node.prev=node;%
                      this.first_node=node;%
                    }%
                  };%
                  List.prototype.begin=function(){%
                    var i=new Iterator();%
                    i.target=this.first_node;%
                    return(i);%
                  };%
                  List.prototype.end=function(){%
                    var i=new Iterator();%
                    i.target=this.last_node;%
                    return(i);%
                  };%
                  function Iterator(it){%
                    if( it!=undefined ){%
                      this.target=it.target;%
                    }else {%
                      this.target=null;%
                    }%
                  }%
                  Iterator.prototype.set=function(it){this.target=it.target;};%
                  Iterator.prototype.get=function(){return(this.target);};%
                  Iterator.prototype.deref=function(){return(this.target.data);};%
                  Iterator.prototype.incr=function(){%
                    if(this.target.next!=null){this.target=this.target.next;}%
                  };%
                  %constructor for node objects that populate the linked list
                  function Node(x){%
                    this.prev=null;%
                    this.next=null;%
                    this.data=x;%
                  }%
                  function sqr(r){return(r*r);}%helper function
                  %The following code borrows heavily from Bernd Gaertners `Miniball' software,
                  %originally written in C++, for computing the smallest enclosing ball of a
                  %set of points; see: http://www.inf.ethz.ch/personal/gaertner/miniball.html
                  function Basis(){%
                    this.m=0;%
                    this.q0=new Array(3);%
                    this.z=new Array(4);%
                    this.f=new Array(4);%
                    this.v=new Array(new Array(3), new Array(3), new Array(3), new Array(3));%
                    this.a=new Array(new Array(3), new Array(3), new Array(3), new Array(3));%
                    this.c=new Array(new Array(3), new Array(3), new Array(3), new Array(3));%
                    this.sqr_r=new Array(4);%
                    this.current_c=this.c[0];%
                    this.current_sqr_r=0;%
                    this.reset();%
                  }%
                  Basis.prototype.center=function(){return(this.current_c);};%
                  Basis.prototype.size=function(){return(this.m);};%
                  Basis.prototype.pop=function(){--this.m;};%
                  Basis.prototype.excess=function(p){%
                    var e=-this.current_sqr_r;%
                    for(var k=0;k<3;++k){%
                      e+=sqr(p[k]-this.current_c[k]);%
                    }%
                    return(e);%
                  };%
                  Basis.prototype.reset=function(){%
                    this.m=0;%
                    for(var j=0;j<3;++j){%
                      this.c[0][j]=0;%
                    }%
                    this.current_c=this.c[0];%
                    this.current_sqr_r=-1;%
                  };%
                  Basis.prototype.push=function(p){%
                    var i, j;%
                    var eps=1e-32;%
                    if(this.m==0){%
                      for(i=0;i<3;++i){%
                        this.q0[i]=p[i];%
                      }%
                      for(i=0;i<3;++i){%
                        this.c[0][i]=this.q0[i];%
                      }%
                      this.sqr_r[0]=0;%
                    }else {%
                      for(i=0;i<3;++i){%
                        this.v[this.m][i]=p[i]-this.q0[i];%
                      }%
                      for(i=1;i<this.m;++i){%
                        this.a[this.m][i]=0;%
                        for(j=0;j<3;++j){%
                          this.a[this.m][i]+=this.v[i][j]*this.v[this.m][j];%
                        }%
                        this.a[this.m][i]*=(2/this.z[i]);%
                      }%
                      for(i=1;i<this.m;++i){%
                        for(j=0;j<3;++j){%
                          this.v[this.m][j]-=this.a[this.m][i]*this.v[i][j];%
                        }%
                      }%
                      this.z[this.m]=0;%
                      for(j=0;j<3;++j){%
                        this.z[this.m]+=sqr(this.v[this.m][j]);%
                      }%
                      this.z[this.m]*=2;%
                      if(this.z[this.m]<eps*this.current_sqr_r){%
                        return(false);%
                      }%
                      var e=-this.sqr_r[this.m-1];%
                      for(i=0;i<3;++i){%
                        e+=sqr(p[i]-this.c[this.m-1][i]);%
                      }%
                      this.f[this.m]=e/this.z[this.m];%
                      for(i=0;i<3;++i){%
                        this.c[this.m][i]=this.c[this.m-1][i]+this.f[this.m]*this.v[this.m][i];%
                      }%
                      this.sqr_r[this.m]=this.sqr_r[this.m-1]+e*this.f[this.m]/2;%
                    }%
                    this.current_c=this.c[this.m];%
                    this.current_sqr_r=this.sqr_r[this.m];%
                    ++this.m;%
                    return(true);%
                  };%
                  function Miniball(){%
                    this.L=new List();%
                    this.B=new Basis();%
                    this.support_end=new Iterator();%
                  }%
                  Miniball.prototype.mtf_mb=function(it){%
                    var i=new Iterator(it);%
                    this.support_end.set(this.L.begin());%
                    if((this.B.size())==4){return;}%
                    for(var k=new Iterator(this.L.begin());k.get()!=i.get();){%
                      var j=new Iterator(k);%
                      k.incr();%
                      if(this.B.excess(j.deref()) > 0){%
                        if(this.B.push(j.deref())){%
                          this.mtf_mb(j);%
                          this.B.pop();%
                          if(this.support_end.get()==j.get()){%
                            this.support_end.incr();%
                          }%
                          this.L.move_to_front(j);%
                        }%
                      }%
                    }%
                  };%
                  Miniball.prototype.check_in=function(b){%
                    this.L.push_back(b);%
                  };%
                  Miniball.prototype.build=function(){%
                    this.B.reset();%
                    this.support_end.set(this.L.begin());%
                    this.mtf_mb(this.L.end());%
                  };%
                  Miniball.prototype.center=function(){%
                    return(this.B.center());%
                  };%
                  Miniball.prototype.radius=function(){%
                    return(Math.sqrt(this.B.current_sqr_r));%
                  };%
                  %create Miniball object
                  var mb=new Miniball();%
                  %aperture angle of the virtual camera
                  var aac=\@MXV@calc;%
                  %list of mesh nodes
                  var meshes=annot3D['\@MXV@label'].context3D.scene.meshes;%
                  %auxiliary vectors
                  var dir=new annot3D['\@MXV@label'].context3D.Vector3();%
                  var up=new annot3D['\@MXV@label'].context3D.Vector3();%
                  var corner=new annot3D['\@MXV@label'].context3D.Vector3();%
                  %auxiliary 4x4 matrix
                  var bbox4x4=new annot3D['\@MXV@label'].context3D.Matrix4x4();%
                  %iterate over all mesh nodes in the scene
                  for(i=0;i<meshes.count;i++){%
                    var mesh=meshes.getByIndex(i);%
                    %get the bbox of the mesh (local coordinates)
                    var bbox=mesh.computeBoundingBox();%
                    %local to parent transformation matrix
                    var trans=mesh.transform.transpose;%
                    %build local to world transformation matrix by recursively
                    %multiplying the parent's transf. matrix on the left
                    var parent=mesh.parent;%
                    while(parent.transform){%
                      trans=parent.transform.transpose.multiply(trans);%
                      parent=parent.parent;%
                    }%
                    %transform the local bounding box corner coordinates to
                    %world coordinates for bounding sphere determination;
                    %Matrix4x4 method transformDirection(<Vector3>) seems
                    %to be bugged, therefore we must resort to the
                    %multiply(<Matrix4x4>) method using an auxiliary matrix
                    %which contains the local bounding box corner coordinates
                    %
                    %auxiliary matrix from bbox.min coordinates
                    bbox4x4.setView(bbox.min, dir, up);%
                    %transform to world coordinates
                    bbox4x4=trans.multiply(bbox4x4.transpose);%
                    %extract the transformed coordinates
                    corner.set(bbox4x4.transpose.translation);%
                    %check-in corner position into Miniball
                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
                    %the same procedure with bbox.max
                    bbox4x4.setView(bbox.max, dir, up);%
                    bbox4x4=trans.multiply(bbox4x4.transpose);%
                    corner.set(bbox4x4.transpose.translation);%
                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
                    %and with all remaining 6 bbox corners
                    corner.set(bbox.min.x, bbox.max.y, bbox.max.z);%
                    bbox4x4.setView(corner, dir, up);%
                    bbox4x4=trans.multiply(bbox4x4.transpose);%
                    corner.set(bbox4x4.transpose.translation);%
                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
                    corner.set(bbox.min.x, bbox.min.y, bbox.max.z);%
                    bbox4x4.setView(corner, dir, up);%
                    bbox4x4=trans.multiply(bbox4x4.transpose);%
                    corner.set(bbox4x4.transpose.translation);%
                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
                    corner.set(bbox.min.x, bbox.max.y, bbox.min.z);%
                    bbox4x4.setView(corner, dir, up);%
                    bbox4x4=trans.multiply(bbox4x4.transpose);%
                    corner.set(bbox4x4.transpose.translation);%
                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
                    corner.set(bbox.max.x, bbox.min.y, bbox.min.z);%
                    bbox4x4.setView(corner, dir, up);%
                    bbox4x4=trans.multiply(bbox4x4.transpose);%
                    corner.set(bbox4x4.transpose.translation);%
                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
                    corner.set(bbox.max.x, bbox.min.y, bbox.max.z);%
                    bbox4x4.setView(corner, dir, up);%
                    bbox4x4=trans.multiply(bbox4x4.transpose);%
                    corner.set(bbox4x4.transpose.translation);%
                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
                    corner.set(bbox.max.x, bbox.max.y, bbox.min.z);%
                    bbox4x4.setView(corner, dir, up);%
                    bbox4x4=trans.multiply(bbox4x4.transpose);%
                    corner.set(bbox4x4.transpose.translation);%
                    mb.check_in(new Array(corner.x, corner.y, corner.z));%
                  }%
                  %compute the smallest enclosing bounding sphere
                  mb.build();%
                  %bounding sphere centre
                  var coo=new annot3D['\@MXV@label'].context3D.Vector3();%
                  coo.set((mb.center())[0], (mb.center())[1], (mb.center())[2]);%
                  %radius of orbit
                  var roo=mb.radius()/ Math.sin(aac * Math.PI/ 360.);%
                  %result string
                  var res='';%
                  var spc=String.fromCharCode(32);%
                  if(aac!=30){%
                    res+=util.printf('3Daac=\%s,' + spc,%
                      (Math.abs(aac) < 1.001e-6 && Math.abs(aac) > 0 ?%
                        util.printf('\%.18f', aac): aac)%
                    );%
                  }%
                  if(coo.length){%
                    res+=util.printf( '3Dcoo=\%s' + spc + '\%s' + spc + '\%s,'%
                        + spc,%
                        (Math.abs(coo.x) < 1.001e-6 && Math.abs(coo.x) > 0 ?%
                          util.printf('\%.18f', coo.x): coo.x),%
                        (Math.abs(coo.y) < 1.001e-6 && Math.abs(coo.y) > 0 ?%
                          util.printf('\%.18f', coo.y): coo.y),%
                        (Math.abs(coo.z) < 1.001e-6 && Math.abs(coo.z) > 0 ?%
                          util.printf('\%.18f', coo.z): coo.z)%
                    );%
                  }%
                  res+=util.printf(%
                    '3Droo=\%s,' + spc, (roo < 1.001e-6 ? util.printf('\%.18f', roo): roo)
                  );%
                  var settings={%
                    initialize: function(dialog){%
                      dialog.load({%
                        'text': res%
                      });%
                    },%
                    description: {%
                      name: '3D' + spc + 'Camera' + spc + 'Settings',%
                      elements: [%
                        {%
                          type: 'static_text',%
                          name: 'Copy' + spc + 'and' + spc + 'paste' + spc +%
                                'the' + spc + 'following' + spc + 'to' + spc +%
                                'the' + spc + 'option' + spc + 'list' + spc +%
                                'of' + spc + spc + '\string\\\string\\includemovie!'%
                        },%
                        {%
                          type: 'edit_text',%
                          item_id: 'text',%
                          alignment: 'align_fill',%
                          readonly: false%
                        },%
                        {%
                          type: 'ok',%
                          ok_name: 'Close'%
                        }%
                      ]%
                    }%
                  };%
                  app.execDialog(settings);%
                }catch(e){%
                    var spc=String.fromCharCode(32);%
                    app.alert('Error' + spc + 'while' + spc + 'executing' + spc +%
                    '3Dcalculate:' + spc + e);%
                }%
              }%
            \fi%
            %create stream from user provided JavaScript file
            \ifx\@MXV@jscriptiiidfile\@empty\else%
              \ifthenelse{% create only once
                \equal{\@MXV@getlabelvalue{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}}{undefined}%
              }{%
                \ifpdf%
                  \pdfobj stream file {\@MXV@jscriptiiidfile}%
                  \pdfrefobj\pdflastobj%
                  \edef\@MXV@userjscriptiiidstream{\the\pdflastobj\space 0 R}%
                  \@MXV@newlabel{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}{\the\pdflastobj}%
                \else\if@MXV@dvipdfmx
                  \special{pdf:fstream @linkuserjscriptiiid\the\@MXV@links\space(\@MXV@jscriptiiidfile)}%
                  \edef\@MXV@userjscriptiiidstream{@linkuserjscriptiid\the\@MXV@links}%
                  \@MXV@newlabel{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}{@linkuserjscriptiid\the\@MXV@links}%
                \else%
                  \pdfmark{%
                    pdfmark=/OBJ,%
                    Raw={%
                      /_objdef {linkuserjscriptiiid\the\@MXV@links}%
                      /type/stream%
                    }%
                  }%
                  \pdfmark{%
                    pdfmark=/PUT,%
                    Raw={%
                      {linkuserjscriptiiid\the\@MXV@links}%
                      (\@MXV@jscriptiiidfile) (r) file%
                    }%
                  }%
                  \edef\@MXV@userjscriptiiidstream{%
                    {linkuserjscriptiiid\the\@MXV@links}%
                  }%
                  \@MXV@newlabel{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}%
                        {linkuserjscriptiiid\the\@MXV@links}%
                \fi\fi%
              }{%
                \ifpdf%
                  \edef\@MXV@userjscriptiiidstream{%
                    \@MXV@getlabelvalue{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}\space 0 R%
                  }%
                \else%
                  \edef\@MXV@userjscriptiiidstream{%
                    {\@MXV@getlabelvalue{\pdfmdfivesum file {\@MXV@jscriptiiidfile}}}%
                  }%
                \fi%
              }%
            \fi%
            \edef\@MXV@jscriptiiidaction{%
              /Next <<%
                /S/JavaScript%
                /JS (\@MXV@linkjscriptiiid)%
                \ifx\@MXV@jscriptiiidfile\@empty\else%
                  /Next <<%
                    /S/JavaScript%
                    /JS \@MXV@userjscriptiiidstream% user provided script
                  >>%
                \fi%
              >>%
            }%
          }{\edef\@MXV@jscriptiiidaction{}}%
        }{% #### 2D ####
          \setkeys{MXV@user}{#1}%
          %retrieve original settings
          \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.mouse}}{true}}{%
            \setboolean{@MXV@mouse}{true}%
          }{%
            \setboolean{@MXV@mouse}{false}%
          }%
          \edef\@MXV@ctrls{\@MXV@getlabelvalue{@MXV@\@MXV@label.showUI}}%
          \edef\@MXV@palindrome{\@MXV@getlabelvalue{@MXV@\@MXV@label.palindrome}}%
          \edef\@MXV@repeat{\@MXV@getlabelvalue{@MXV@\@MXV@label.repeat}}%
          \edef\@MXV@rate{\@MXV@getlabelvalue{@MXV@\@MXV@label.rate}}%
          \edef\@MXV@startat{\@MXV@getlabelvalue{@MXV@\@MXV@label.startAt}}%
          \edef\@MXV@endat{\@MXV@getlabelvalue{@MXV@\@MXV@label.endAt}}%
          \edef\@MXV@volume{\@MXV@getlabelvalue{@MXV@\@MXV@label.volume}}%
          \if@MXV@linkreset\else%
            \setkeys{MXV@user}{#1}%override with new settings
          \fi%
          %
          \edef\@MXV@operation{}%
          %
          %get the player ID
          \edef\@MXV@currplayer{\@MXV@getlabelvalue{@MXV@\@MXV@label.playerid}}%
          %
          %see whether a sound inclusion is being referenced
          \ifthenelse{\equal{\@MXV@getlabelvalue{@MXV@\@MXV@label.issound}}{true}}{%
            \setboolean{@MXV@issound}{true}%
          }{%
            \setboolean{@MXV@issound}{false}%
          }%
          %
          %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@currplayer}%
                            {\if@MXV@mouse true\else false\fi}%
                            {true}%
                \if@MXV@requirereopen\else
                try{%
                  \ifx\@MXV@@startat\@empty
                    player\@MXV@currplayer.seek(%
                        player\@MXV@currplayer.settings.startAt%
                    );
                  \else
                    player\@MXV@currplayer.seek(\@MXV@@startat);
                  \fi
                  player\@MXV@currplayer.play();
                  \ifx\@MXV@@startat\@empty
                    player\@MXV@currplayer.seek(%
                        player\@MXV@currplayer.settings.startAt%
                    );
                  \else
                    player\@MXV@currplayer.seek(\@MXV@@startat);
                  \fi
                }%
                catch(e)\@charlb%
                \fi%
                  try{%
                    if(player\@MXV@currplayer.isOpen){%
                      player\@MXV@currplayer.close(%
                                            app.media.closeReason.general);
                      player\@MXV@currplayer=null;
                    }%
                  }%
                  catch(e){}%
                  %
                  try{%
                    var player\@MXV@currplayer=app.media.openPlayer({%
                      settings: settings,%
                      events: events%
                    });%
                  }%
                  catch (e){}%
                \if@MXV@requirereopen\else
                \@charrb%
                \fi%
              )%
            }%
          \fi%
          \if@MXV@linkresume% resume/pause
            \edef\@MXV@operation{%
              /OP 3%
              /JS (%
                try{%
                  \if@MXV@issound\else player\@MXV@currplayer.visible=true;\fi%
                  if(!player\@MXV@currplayer.isPlaying){%
                    player\@MXV@currplayer.settings.privateData.paused=false;
                    player\@MXV@currplayer.play();
                    if(!player\@MXV@currplayer.isPlaying){%
                      %media at end will restart from beginning
                      if(
                        player\@MXV@currplayer.settings.startAt.time
                        || player\@MXV@currplayer.settings.startAt.frame
                        || player\@MXV@currplayer.settings.startAt.marker
                        || player\@MXV@currplayer.id ==
                           'vnd.adobe.swname:AAPL_QuickTime'
                      ){
                        player\@MXV@currplayer.seek(
                          player\@MXV@currplayer.settings.startAt);
                      }else{
                        player\@MXV@currplayer.stop();
                      }
                      player\@MXV@currplayer.play();
                    }%
                  }%
                  else{%
                    player\@MXV@currplayer.pause();
                    player\@MXV@currplayer.settings.privateData.paused=true;
                  }%
                }%
                catch(e){% open new player if not yet open
                  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@currplayer}%
                              {\if@MXV@mouse true\else false\fi}%
                              {true}%
                  try{%
                    var player\@MXV@currplayer=app.media.openPlayer({%
                      settings: settings,%
                      events: events%
                    });
                  }%
                  catch (e){}%
                }%
              )%
            }%
          \fi%
          \if@MXV@linkstop%
            \edef\@MXV@operation{%
              /OP 1%
              /JS (%
                try{%
                  if(!player\@MXV@currplayer.isPlaying){%
                    player\@MXV@currplayer.settings.privateData.paused=false;
                    player\@MXV@currplayer.play();
                  }%
                  player\@MXV@currplayer.stop();
                  if(
                    player\@MXV@currplayer.settings.startAt.time
                    || player\@MXV@currplayer.settings.startAt.frame
                    || player\@MXV@currplayer.settings.startAt.marker
                    || player\@MXV@currplayer.id ==
                       'vnd.adobe.swname:AAPL_QuickTime'
                  ){
                    player\@MXV@currplayer.seek(%
                      player\@MXV@currplayer.settings.startAt);
                  }
                }%
                catch(e){}%
              )%
            }%
          \fi%
          \if@MXV@linkpause% pause/resume
            \edef\@MXV@operation{%
              /OP 2%
              /JS (%
                try{%
                  \if@MXV@issound\else player\@MXV@currplayer.visible=true;\fi%
                  if(!player\@MXV@currplayer.isPlaying){%
                    player\@MXV@currplayer.settings.privateData.paused=false;
                    player\@MXV@currplayer.play();
                    if(!player\@MXV@currplayer.isPlaying){%
                      %media at end will restart from beginning
                      if(
                        player\@MXV@currplayer.settings.startAt.time
                        || player\@MXV@currplayer.settings.startAt.frame
                        || player\@MXV@currplayer.settings.startAt.marker
                        || player\@MXV@currplayer.id ==
                           'vnd.adobe.swname:AAPL_QuickTime'
                      ){
                        player\@MXV@currplayer.seek(
                          player\@MXV@currplayer.settings.startAt);
                      }else{
                        player\@MXV@currplayer.stop();
                      }
                      player\@MXV@currplayer.play();
                    }%
                  }%
                  else{%
                    player\@MXV@currplayer.pause();
                    player\@MXV@currplayer.settings.privateData.paused=true;
                  }%
                }%
                catch(e){% open new player if not yet open
                  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@currplayer}%
                              {\if@MXV@mouse true\else false\fi}%
                              {true}%
                  try{%
                    var player\@MXV@currplayer=app.media.openPlayer({%
                      settings: settings,%
                      events: events%
                    });
                  }%
                  catch (e){}%
                }%
              )%
            }%
          \fi%
          \if@MXV@linkclose%
            \edef\@MXV@operation{%
              /OP 1%
              /JS (%
                try{%
                  player\@MXV@currplayer.close(%
                                        app.media.closeReason.general);
                  player\@MXV@currplayer=null;
                }%
                catch(e){}%
              )%
            }%
          \fi%
        }%
      \fi%
      \fi%
      %
      \ifpdf%
        \ifthenelse{\isundefined{\@pdfborder}}{%
          \def\@MXV@linkattr{}%
        }{%
          \edef\@MXV@linkattr{%
            \if@MXV@beamer%
              \@MXV@pdfborder%
            \else%
              /Border [\@pdfborder]%
            \fi%
            /C [\@linkbordercolor]%
            /H \@pdfhighlight%
          }%
        }%
        %
        \pdfstartlink%
          attr{\@MXV@linkattr}%
          user{%
            /Subtype /Link%
            /A <<%
              /S/GoTo%
              /D (@MXV@\@MXV@@label)%
              \if@MXV@@draft\else%
                \if@MXV@externalviewer\else%
                  \if@MXV@iiid%
                    \ifx\@MXV@iiidview\@empty\else%
                      /Next <<%
                        /S/GoTo3DView%
                        /TA \@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}\space 0 R%
                        /V \@MXV@iiidview%
                    \fi%
                        \@MXV@jscriptiiidaction%
                    \ifx\@MXV@iiidview\@empty\else%
                      >>%
                    \fi%
                  \else%
                    /Next <<%
                      /S/Rendition%
                      /R \@MXV@getlabelvalue{@MXV@\@MXV@@label.rendition}\space 0 R%
                      /AN \@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}\space 0 R%
                      \@MXV@operation%
                    >>%
                  \fi%
                \fi%
              \fi%
            >>%
          }%
          \usebox{\@MXV@textbox}% write out text box
        \pdfendlink%
      \else\if@MXV@dvipdfmx
        \ifthenelse{\isundefined{\@pdfborder}}{%
          \def\@MXV@linkattr{}%
        }{%
          \edef\@MXV@linkattr{%
            \if@MXV@beamer%
              \@MXV@pdfborder%
            \else%
              /Border [\@pdfborder]%
            \fi%
            /C [\@linkbordercolor]%
            /H \@pdfhighlight%
          }%
        }%
        %
        \special{pdf:bannot <<%
          \@MXV@linkattr%
          /Subtype /Link%
          /A <<%
            /S/GoTo%
            /D (@MXV@\@MXV@@label)%
            \if@MXV@@draft\else%
              \if@MXV@externalviewer\else%
                \if@MXV@iiid%
                  \ifx\@MXV@iiidview\@empty\else%
                    /Next <<%
                      /S/GoTo3DView%
                      /TA \@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}%
                      /V \@MXV@iiidview%
                  \fi%
                      \@MXV@jscriptiiidaction%
                  \ifx\@MXV@iiidview\@empty\else%
                    >>%
                  \fi%
                \else%
                  /Next <<%
                    /S/Rendition%
                    /R \@MXV@getlabelvalue{@MXV@\@MXV@@label.rendition}%
                    /AN \@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}%
                    \@MXV@operation%
                  >>%
                \fi%
              \fi%
            \fi%
          >>%
        >>}%
        \usebox{\@MXV@textbox}% write out text box
        \special{pdf:eannot}%
      \else%
        \pdfmark[{\usebox{\@MXV@textbox}}]{%
          pdfmark=/ANN,%
          Subtype=/Link,%
          Color=\@linkbordercolor,%
          AcroHighlight=\@pdfhighlight,%
          Raw={%
            \@MXV@pdfborder%
            /_objdef {linkannot\the\@MXV@links}%
            /Action <<%
              /S/GoTo%
              /D/@MXV@\@MXV@@label%
              \if@MXV@@draft\else%
                \if@MXV@externalviewer\else%
                  \if@MXV@iiid%
                    \ifx\@MXV@iiidview\@empty\else%
                      /Next <<%
                        /S/GoTo3DView%
                        /TA \@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}%
                        /V \@MXV@iiidview%
                    \fi%
                        \@MXV@jscriptiiidaction%
                    \ifx\@MXV@iiidview\@empty\else%
                      >>%
                    \fi%
                  \else%
                    /Next <<%
                      /S /Rendition%
                      /R {mediarendition\@MXV@getlabelvalue{@MXV@\@MXV@@label.annotid}}%
                      /AN {screenannot\@MXV@getlabelvalue{@MXV@\@MXV@@label.annot}}%
                      \@MXV@operation%
                    >>%
                  \fi%
                \fi%
              \fi%
            >>%
          }%
        }%
      \fi\fi%
    }%
  }%
}

%set to true for certain \movieref options, which require the media player to
%be re-opened
\newboolean{@MXV@requirereopen}

%standard keys to be processed first
%key definitions for options to \includemovie
\define@key{MXV@user}{draft}[true]{%
  \setboolean{@MXV@@draft}{#1}%
}
\define@key{MXV@user}{final}[true]{%
  \ifthenelse{\equal{#1}{true}}{%
    \setboolean{@MXV@@draft}{false}%
  }{%
    \setboolean{@MXV@@draft}{true}%
  }%
}
\define@key{MXV@user}{label}{%for use with movieref
  \gdef\@MXV@label{#1}%
}
\define@key{MXV@user}{controls}[true]{%
  \setboolean{@MXV@requirereopen}{true}%
  \xdef\@MXV@ctrls{, showUI: #1}%
  \xdef\@MXV@@ctrls{/C #1}%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \gdef\@MXV@iiidtoolb{/TB #1}%
  }{}%
}
\define@key{MXV@user}{toolbar}[true]{%
  \xdef\@MXV@ctrls{, showUI: #1}%
  \xdef\@MXV@@ctrls{/C #1}%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \gdef\@MXV@iiidtoolb{/TB #1}%
  }{}%
}
\define@key{MXV@user}{volume}{%
  \def\@MXV@@volume{/V #1}%
  \def\@MXV@volume{#1}%
  \setboolean{@MXV@requirereopen}{true}%
}
\define@key{MXV@user}{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{MXV@user}{playerid}{%
  \def\@MXV@player{%
    /PL<</MU [<</PID<</U (vnd.adobe.swname:#1)>>>>]>>%
  }%
}
\define@key{MXV@user}{autoplay}[true]{%
  \setboolean{@MXV@autoplay}{#1}%
  \if@MXV@autoplay%
    \setboolean{@MXV@autoresume}{false}%
  \fi%
}
\define@key{MXV@user}{autostop}[true]{%
  \setboolean{@MXV@autostop}{#1}%
  \if@MXV@autostop%
    \setboolean{@MXV@autopause}{false}%
  \fi%
}
\define@key{MXV@user}{autoresume}[true]{%
  \setboolean{@MXV@autoresume}{#1}%
  \if@MXV@autoresume%
    \setboolean{@MXV@autoplay}{false}%
    \setboolean{@MXV@autoclose}{false}%
  \fi%
}
\define@key{MXV@user}{autopause}[true]{%
  \setboolean{@MXV@autopause}{#1}%
  \if@MXV@autopause%
    \setboolean{@MXV@autostop}{false}%
    \setboolean{@MXV@autoclose}{false}%
  \fi%
}
\define@key{MXV@user}{autoclose}[true]{%
  \setboolean{@MXV@autoclose}{#1}%
  \if@MXV@autoclose%
    \setboolean{@MXV@autostop}{false}%
    \setboolean{@MXV@autopause}{false}%
  \fi%
}
\define@key{MXV@user}{continue}[true]{%
  \setboolean{@MXV@autostop}{false}%
  \setboolean{@MXV@autopause}{false}%
  \setboolean{@MXV@autoclose}{false}%
}
\define@key{MXV@user}{open}[true]{%
  %no longer supported; once open, media remains loaded
  %to avoid reloading when media is to be played again
}
\define@key{MXV@user}{mouse}[true]{%
  \setboolean{@MXV@mouse}{#1}%
  \setboolean{@MXV@requirereopen}{true}%
  \ifthenelse{\equal{false}{#1}\AND\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@iiidia{/3DI #1}%
  }{}%
}
\define@key{MXV@user}{palindrome}[true]{%
  \xdef\@MXV@palindrome{, palindrome: #1}%
  \setboolean{@MXV@requirereopen}{true}%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \gdef\@MXV@iiidpalindrome{/Subtype/Oscillating}%
  }{}%
}
\define@key{MXV@user}{rate}{%
  \setboolean{@MXV@requirereopen}{true}%
  \xdef\@MXV@rate{, rate: #1}%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \gdef\@MXV@iiidrate{/TM #1}%
  }{}%
}
\define@key{MXV@user}{repeat}[Infinity]{%
  \setboolean{@MXV@requirereopen}{true}%
  \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}%
  }%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \ifthenelse{\equal{#1}{Infinity}}{%
      \global\@MXV@iiidrepeat=-1%
    }{%
      \global\@MXV@iiidrepeat=#1%
    }%
  }{}%
}
\define@key{MXV@user}{startat}{%
  \xdef\@MXV@startat{, startAt: {#1}}%
  \xdef\@MXV@@startat{{#1}}%
}
\define@key{MXV@user}{endat}{%
  \setboolean{@MXV@requirereopen}{true}%
  \xdef\@MXV@endat{, endAt: {#1}}%
}
\define@key{MXV@user}{poster}[true]{%
  \ifthenelse{\equal{#1}{true}}{% option without arg
    \setboolean{@MXV@runposter}{true}%
  }{%
    \def\@MXV@box##1##2##3{%
      \ifpdf%
        \mbox{\pdfximage width ##1 height ##2 depth ##3 {#1}}%
        \pdfrefximage\pdflastximage%
      \else%
        \ifthenelse{\isundefined{\includegraphics}}{\@MXV@missing{graphics}}{}%
        \@MXV@totalheight=##2%
        \advance\@MXV@totalheight by ##3%
        \raisebox{-##3}[##2][##3]{%
          \includegraphics[%
            width=##1,height=##2,totalheight=\@MXV@totalheight,clip]{#1}%
        }%
      \fi%
    }%
  }%
}
\define@key{MXV@user}{externalviewer}[true]{%
  \setboolean{@MXV@externalviewer}{#1}%
}
\define@key{MXV@user}{inline}[true]{%
  \if@MXV@url%
    \setboolean{@MXV@inline}{false}%
  \else%
    \setboolean{@MXV@inline}{#1}%
  \fi%
  \if@MXV@inline\else%
    \setboolean{@MXV@attachment}{false}%
  \fi%
}
\define@key{MXV@user}{url}[true]{%
  \setboolean{@MXV@url}{#1}%
  \if@MXV@url%
    \setboolean{@MXV@inline}{false}%
    \setboolean{@MXV@attachment}{false}%
    \def\@MXV@fsentry{/FS /URL}%
  \fi%
}
\define@key{MXV@user}{attach}[true]{%
  \setboolean{@MXV@attachment}{#1}%
  \if@MXV@attachment%
    \setboolean{@MXV@inline}{true}%
  \fi%
}
\define@key{MXV@user}{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{MXV@user}{textoverposter}[true]{%
  \setboolean{@MXV@textoverposter}{#1}%
}
\define@key{MXV@user}{depth}{%set depth of display area
  \gdef\@MXV@boxdepth{#1}%
}
%3D specific options
\define@key{MXV@user}{3Dbg}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@background{/BG<</CS/DeviceRGB/C[#1]>>}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Djscript}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \IfFileExists{#1}{%
      \def\@MXV@jscriptiiidfile{#1}%
    }{%
      \PackageError{movie15}{Script file `#1' cannot be opened for embedding%
      }{%
        Make sure file `#1' exists and is readable!%
      }%
    }%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Dcoo}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@coo{#1}%
    \setboolean{@MXV@defaultviewprovided}{true}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Dc2c}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@ctoc{#1}%
    \setboolean{@MXV@defaultviewprovided}{true}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Droo}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@roo{#1}%
    \setboolean{@MXV@defaultviewprovided}{true}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Daac}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@aac{#1}%
    \setboolean{@MXV@defaultviewprovided}{true}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Droll}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \def\@MXV@roll{#1}%
    \setboolean{@MXV@defaultviewprovided}{true}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Dviews}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \IfFileExists{#1}{%
      \def\@MXV@viewsfile{#1}%
    }{%
      \PackageError{movie15}{3D views  file `#1' cannot be opened%
      }{%
        Make sure file `#1' exists and is readable!%
      }%
    }%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Dlights}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \gdef\@MXV@lights{/LS <</Subtype/#1>>}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Drender}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \gdef\@MXV@render{/RM <</Subtype/#1>>}%
  }{\@MXV@neediiiD}%
}
%options for \movieref command
\define@key{MXV@user}{play}[true]{%
  \setboolean{@MXV@linkplay}{#1}%
  \if@MXV@linkplay%
   \setboolean{@MXV@linkpause}{false}%
   \setboolean{@MXV@linkresume}{false}%
   \setboolean{@MXV@linkstop}{false}%
   \setboolean{@MXV@linkclose}{false}%
  \fi%
}
\define@key{MXV@user}{pause}[true]{%
  \setboolean{@MXV@linkpause}{#1}%
  \if@MXV@linkpause%
    \setboolean{@MXV@linkresume}{false}%
    \setboolean{@MXV@linkstop}{false}%
    \setboolean{@MXV@linkclose}{false}%
    \setboolean{@MXV@linkplay}{false}%
  \fi%
}
\define@key{MXV@user}{resume}[true]{%
  \setboolean{@MXV@linkresume}{#1}%
  \if@MXV@linkresume%
    \setboolean{@MXV@linkpause}{false}%
    \setboolean{@MXV@linkstop}{false}%
    \setboolean{@MXV@linkclose}{false}%
    \setboolean{@MXV@linkplay}{false}%
  \fi%
}
\define@key{MXV@user}{stop}[true]{%
  \setboolean{@MXV@linkstop}{#1}%
  \if@MXV@linkstop%
    \setboolean{@MXV@linkpause}{false}%
    \setboolean{@MXV@linkresume}{false}%
    \setboolean{@MXV@linkclose}{false}%
    \setboolean{@MXV@linkplay}{false}%
  \fi%
}
\define@key{MXV@user}{close}[true]{%
  \setboolean{@MXV@linkclose}{#1}%
  \if@MXV@linkclose%
    \setboolean{@MXV@linkpause}{false}%
    \setboolean{@MXV@linkresume}{false}%
    \setboolean{@MXV@linkstop}{false}%
    \setboolean{@MXV@linkplay}{false}%
  \fi%
}
\define@key{MXV@user}{reset}[true]{%
  \setboolean{@MXV@linkreset}{#1}%
  \if@MXV@linkreset%
    \setboolean{@MXV@requirereopen}{true}%
  \fi%
}
\define@key{MXV@user}{default}[true]{% synonyme for `reset'
  \setboolean{@MXV@linkreset}{#1}%
  \if@MXV@linkreset%
    \setboolean{@MXV@requirereopen}{true}%
  \fi%
}
\define@key{MXV@user}{3Dviewindex}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \ifthenelse{%
      \equal{#1}{F}%
      \OR\equal{#1}{L}%
      \OR\equal{#1}{N}%
      \OR\equal{#1}{P}%
      \OR\equal{#1}{D}%
    }{%
      \gdef\@MXV@iiidview{/#1}% any of F, L, N, P, D
    }{%
      \gdef\@MXV@iiidview{#1}% number (index)
    }%
    \setboolean{@MXV@defaultviewprovided}{false}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Dcalculate}[30]{%
  %calculate optimal 3D settings for roo and coo for a given aac
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \gdef\@MXV@calc{#1}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Dgetview}[true]{%
  %print current 3D camera settings
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \setboolean{@MXV@iiidgetview}{#1}%
  }{\@MXV@neediiiD}%
}
\define@key{MXV@user}{3Dresource}{%
  \ifthenelse{\boolean{@MXV@iiiDfeat}}{%
    \IfFileExists{#1}{%
      \setboolean{@MXV@resource}{true}%
      \xdef\@MXV@iiidopt{3Dresource=#1, \@MXV@iiidopt}%
    }{%
      \PackageError{movie15}{3D resource file `#1' cannot be opened%
      }{%
        Make sure file `#1' exists and is readable!%
      }%
    }%
  }{\@MXV@neediiiD}%
}

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

%options to be passed to internal macro \@MXV@includeiiid
\define@key{MXV@iiid}{3Dresource}{%
  \@MXV@addresource{#1}%
}

%compatibility macros
\providecommand\movie[3][]{%
  \ifpdf\else%
    \ifthenelse{\isundefined{\pdfmark}\AND\isundefined{\@pdfm@mark}}{\@MXV@missing{hyperref}}{}%
  \fi%
  \leavevmode%
  \@MXV@reset%
  \def\@MXV@autostart{}\def\@MXV@loop{}\def\@MXV@showcontrols{}%
  \def\@MXV@starttime{}\def\@MXV@durationtime{}%
  \setkeys{MXV@user}{#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][]{%
  \ifpdf\else%
    \ifthenelse{\isundefined{\pdfmark}\AND\isundefined{\@pdfm@mark}}{\@MXV@missing{hyperref}}{}%
  \fi%
  \leavevmode%
  \@MXV@reset%
  \def\@MXV@autostart{}\def\@MXV@loop{}\def\@MXV@showcontrols{}%
  \def\@MXV@starttime{}\def\@MXV@durationtime{}%
  \setkeys{MXV@user}{#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}%
}
