TYPO3 CMS  TYPO3_6-2
FlowPlayerContentObject.php
Go to the documentation of this file.
1 <?php
3 
22 
26  public $mimeTypes = array(
27  'aif' => array(
28  'audio' => 'audio/aiff'
29  ),
30  'au' => array(
31  'audio' => 'audio/x-au'
32  ),
33  'avi' => array(
34  'audio' => 'video/x-msvideo'
35  ),
36  'asf' => array(
37  'video' => 'video/x-ms-asf'
38  ),
39  'class' => array(
40  'audio' => 'application/java',
41  'video' => 'application/java'
42  ),
43  'dcr' => array(
44  'video' => 'application/x-director'
45  ),
46  'flac' => array(
47  'audio' => 'audio/flac'
48  ),
49  'flv' => array(
50  'video' => 'video/x-flv'
51  ),
52  'mp3' => array(
53  'audio' => 'audio/mpeg'
54  ),
55  'mp4' => array(
56  'video' => 'video/mp4'
57  ),
58  'oga' => array(
59  'audio' => 'audio/ogg'
60  ),
61  'ogg' => array(
62  'audio' => 'audio/ogg',
63  'video' => 'video/ogg'
64  ),
65  'ogv' => array(
66  'video' => 'video/ogg'
67  ),
68  'swa' => array(
69  'audio' => 'audio/x-m4a'
70  ),
71  'mov' => array(
72  'video' => 'video/quicktime'
73  ),
74  'm4a' => array(
75  'audio' => 'audio/mp4a-latm'
76  ),
77  'm4v' => array(
78  'video' => 'video/x-m4v'
79  ),
80  'qt' => array(
81  'video' => 'video/quicktime'
82  ),
83  'swa' => array(
84  'audio' => 'application/x-director'
85  ),
86  'swf' => array(
87  'audio' => 'application/x-shockwave-flash',
88  'video' => 'application/x-shockwave-flash'
89  ),
90  'wav' => array(
91  'audio' => 'audio/wave'
92  ),
93  'webm' => array(
94  'audio' => 'audio/webm',
95  'video' => 'video/webm'
96  ),
97  'wmv' => array(
98  'audio' => 'audio/x-ms-wmv'
99  )
100  );
101 
105  public $videoJsOptions = array(
106  // Use the browser's controls (iPhone)
107  'useBuiltInControls',
108  // Display control bar below video vs. in front of
109  'controlsBelow',
110  // Make controls visible when page loads
111  'controlsAtStart',
112  // Hide controls when not over the video
113  'controlsHiding',
114  // Will be overridden by localStorage volume if available
115  'defaultVolume',
116  // Players and order to use them
117  'playerFallbackOrder'
118  );
119 
123  public $html5TagAttributes = array(
124  'autoPlay',
125  'controls',
126  'loop',
127  'preload'
128  );
129 
134  'plugins' => array(
135  // The captions plugin
136  'captions' => array(
137  'url' => 'plugins/flowplayer.captions-3.2.10.swf',
138  // Pointer to a content plugin (see below)
139  'captionTarget' => 'content'
140  ),
141  // Configure a content plugin so that it looks good for showing captions
142  'content' => array(
143  'url' => 'plugins/flowplayer.content-3.2.9.swf',
144  'bottom' => 5,
145  'height' => 40,
146  'backgroundColor' => 'transparent',
147  'backgroundGradient' => 'none',
148  'border' => 0,
149  'textDecoration' => 'outline',
150  'style' => array(
151  'body' => array(
152  'fontSize' => 14,
153  'fontFamily' => 'Arial',
154  'textAlign' => 'center',
155  'color' => '#ffffff'
156  )
157  )
158  )
159  )
160  );
161 
165  public $flowplayerAudioConfig = array(
166  'provider' => 'audio',
167  'plugins' => array(
168  'audio' => array(
169  'url' => 'plugins/flowplayer.audio-3.2.11.swf'
170  ),
171  'controls' => array(
172  'autoHide' => FALSE,
173  'fullscreen' => FALSE
174  )
175  )
176  );
177 
182  // The controls plugin
183  'plugins' => array(
184  'controls' => NULL
185  )
186  );
187 
194  public function render($conf = array()) {
196  $pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
197  $prefix = '';
198  if ($GLOBALS['TSFE']->baseUrl) {
199  $prefix = $GLOBALS['TSFE']->baseUrl;
200  }
201  if ($GLOBALS['TSFE']->absRefPrefix) {
202  $prefix = $GLOBALS['TSFE']->absRefPrefix;
203  }
204  // Initialize content
205  $replaceElementIdString = str_replace('.', '', uniqid('mmswf', TRUE));
206  $GLOBALS['TSFE']->register['MMSWFID'] = $replaceElementIdString;
207  $layout = isset($conf['layout.']) ? $this->cObj->stdWrap($conf['layout'], $conf['layout.']) : $conf['layout'];
208  $content = str_replace('###ID###', $replaceElementIdString, $layout);
209  $type = isset($conf['type.']) ? $this->cObj->stdWrap($conf['type'], $conf['type.']) : $conf['type'];
210  $typeConf = $conf[$type . '.'];
211  // Add Flowplayer js-file
212  $pageRenderer->addJsFile(TYPO3_mainDir . 'contrib/flowplayer/flowplayer-3.2.13.min.js');
213  // Add Flowpayer css for exprss install
214  $pageRenderer->addCssFile(TYPO3_mainDir . 'contrib/flowplayer/express-install/express-install.css');
215  // Add videoJS js-file
216  $pageRenderer->addJsFile(TYPO3_mainDir . 'contrib/videojs/video-js/video.js');
217  // Add videoJS js-file
218  $pageRenderer->addJsFile(TYPO3_mainDir . 'contrib/videojs/video-js/video.js');
219  // Add videoJS css-file
220  $pageRenderer->addCssFile(TYPO3_mainDir . 'contrib/videojs/video-js/video-js.css');
221  // Add extended videoJS control bar
222  $pageRenderer->addJsFile(TYPO3_mainDir . 'contrib/videojs/video-js/controls/control-bar.js');
223  $pageRenderer->addCssFile(TYPO3_mainDir . 'contrib/videojs/video-js/controls/control-bar.css');
224  // Build Flash configuration
225  $player = isset($typeConf['player.']) ? $this->cObj->stdWrap($typeConf['player'], $typeConf['player.']) : $typeConf['player'];
226  if (!$player) {
227  $player = $prefix . TYPO3_mainDir . 'contrib/flowplayer/flowplayer-3.2.18.swf';
228  }
229  $installUrl = isset($conf['installUrl.']) ? $this->cObj->stdWrap($conf['installUrl'], $conf['installUrl.']) : $conf['installUrl'];
230  if (!$installUrl) {
231  $installUrl = $prefix . TYPO3_mainDir . 'contrib/flowplayer/expressinstall.swf';
232  }
233  $flashVersion = isset($conf['flashVersion.']) ? $this->cObj->stdWrap($conf['flashVersion'], $conf['flashVersion.']) : $conf['flashVersion'];
234  if (!$flashVersion) {
235  $flashVersion = array(9, 115);
236  }
237  $flashConfiguration = array(
238  // Flowplayer component
239  'src' => $player,
240  // Express install url
241  'expressInstall' => $installUrl,
242  // Require at least this Flash version
243  'version' => $flashVersion,
244  // Older versions will see a message
245  'onFail' => '###ONFAIL###'
246  );
247  $flashDownloadUrl = 'http://www.adobe.com/go/getflashplayer';
248  $onFail = 'function() {
249  if (!(flashembed.getVersion()[0] > 0)) {
250  var message = "<p>" + "' . $GLOBALS['TSFE']->sL('LLL:EXT:cms/locallang_ttc.xlf:media.needFlashPlugin') . '" + "</p>" + "<p>" + "<a href=\\"' . $flashDownloadUrl . '\\">' . $GLOBALS['TSFE']->sL('LLL:EXT:cms/locallang_ttc.xlf:media.downloadFlash') . '</a>" + "</p>";
251  document.getElementById("' . $replaceElementIdString . '_flash_install_info").innerHTML = "<div class=\\"message\\">" + message + "</div>";
252  }
253  }';
254  $flashConfiguration = json_encode($flashConfiguration);
255  $flashConfiguration = str_replace('"###ONFAIL###"', $onFail, $flashConfiguration);
256  $filename = isset($conf['file.']) ? $this->cObj->stdWrap($conf['file'], $conf['file.']) : $conf['file'];
257  if ($filename) {
258  if (strpos($filename, '://') !== FALSE) {
259  $conf['flashvars.']['url'] = $filename;
260  } else {
261  if ($prefix) {
262  $conf['flashvars.']['url'] = $prefix . $filename;
263  } else {
264  $conf['flashvars.']['url'] = str_repeat('../', substr_count($player, '/')) . $filename;
265  }
266  }
267  }
268  if (is_array($conf['sources'])) {
269  foreach ($conf['sources'] as $key => $source) {
270  if (strpos($source, '://') === FALSE) {
271  $conf['sources'][$key] = $prefix . $source;
272  }
273  }
274  }
275  if (is_array($conf['audioSources'])) {
276  foreach ($conf['audioSources'] as $key => $source) {
277  if (strpos($source, '://') === FALSE) {
278  $conf['audioSources'][$key] = $prefix . $source;
279  }
280  }
281  }
282  if (isset($conf['audioFallback']) && strpos($conf['audioFallback'], '://') === FALSE) {
283  $conf['audioFallback'] = $prefix . $conf['audioFallback'];
284  }
285  if (isset($conf['caption']) && strpos($conf['caption'], '://') === FALSE) {
286  $conf['caption'] = $prefix . $conf['caption'];
287  }
288  // Write calculated values in conf for the hook
289  $conf['player'] = $player ?: $filename;
290  $conf['installUrl'] = $installUrl;
291  $conf['filename'] = $conf['flashvars.']['url'];
292  $conf['prefix'] = $prefix;
293  // merge with default parameters
294  $conf['flashvars.'] = array_merge((array) $typeConf['default.']['flashvars.'], (array) $conf['flashvars.']);
295  $conf['params.'] = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.']);
296  $conf['attributes.'] = array_merge((array) $typeConf['default.']['attributes.'], (array) $conf['attributes.']);
297  $conf['embedParams'] = 'flashvars, params, attributes';
298  // Hook for manipulating the conf array, it's needed for some players like flowplayer
299  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'])) {
300  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'] as $classRef) {
302  }
303  }
304  // Flowplayer config
305  $flowplayerVideoConfig = array();
306  $flowplayerAudioConfig = array();
307  if (is_array($conf['flashvars.'])) {
308  \TYPO3\CMS\Core\Utility\GeneralUtility::remapArrayKeys($conf['flashvars.'], $typeConf['mapping.']['flashvars.']);
309  } else {
310  $conf['flashvars.'] = array();
311  }
312  $conf['videoflashvars'] = $conf['flashvars.'];
313  $conf['audioflashvars'] = $conf['flashvars.'];
314  $conf['audioflashvars']['url'] = $conf['audioFallback'];
315  // Render video sources
316  $videoSources = '';
317  if (is_array($conf['sources'])) {
318  foreach ($conf['sources'] as $source) {
320  $mimeType = $this->mimeTypes[$fileinfo['fileext']]['video'];
321  $videoSources .= '<source src="' . $source . '"' . ($mimeType ? ' type="' . $mimeType . '"' : '') . ' />' . LF;
322  }
323  }
324  // Render audio sources
325  $audioSources = '';
326  if (is_array($conf['audioSources'])) {
327  foreach ($conf['audioSources'] as $source) {
329  $mimeType = $this->mimeTypes[$fileinfo['fileext']]['audio'];
330  $audioSources .= '<source src="' . $source . '"' . ($mimeType ? ' type="' . $mimeType . '"' : '') . ' />' . LF;
331  }
332  }
333  // Configure captions
334  if ($conf['type'] === 'video' && isset($conf['caption'])) {
335  // Assemble captions track tag
336  $videoCaptions = '<track id="' . $replaceElementIdString . '_captions_track" kind="captions" src="' . $conf['caption'] . '" default="default" />' . LF;
337  // Add videoJS extension for captions
338  $pageRenderer->addJsFile(TYPO3_mainDir . 'contrib/videojs/video-js/controls/captions.js');
339  // Flowplayer captions
340  $conf['videoflashvars']['captionUrl'] = $conf['caption'];
341  // Flowplayer captions plugin configuration
342  $flowplayerVideoConfig = array_merge_recursive($flowplayerVideoConfig, $this->flowplayerCaptionsConfig);
343  }
344  // Configure flowplayer audio fallback
345  if (isset($conf['audioFallback'])) {
346  $flowplayerAudioConfig = array_merge_recursive($flowplayerAudioConfig, $this->flowplayerAudioConfig);
347  }
348  // Configure audio description
349  if ($conf['type'] == 'video') {
350  if (is_array($conf['audioSources']) && count($conf['audioSources'])) {
351  // Add videoJS audio description toggle
352  $pageRenderer->addJsFile(TYPO3_mainDir . 'contrib/videojs/video-js/controls/audio-description.js');
353  }
354  if (isset($conf['audioFallback'])) {
355  // Audio description flowplayer config (remove controls)
356  $flowplayerAudioConfig = array_merge_recursive($flowplayerAudioConfig, $this->flowplayerAudioDescriptionConfig);
357  }
358  }
359  // Assemble Flowplayer configuration
360  if (count($conf['videoflashvars'])) {
361  $flowplayerVideoConfig = array_merge_recursive($flowplayerVideoConfig, array('clip' => $conf['videoflashvars']));
362  }
363  $flowplayerVideoJsonConfig = str_replace(array('"true"', '"false"'), array('true', 'false'), json_encode($flowplayerVideoConfig));
364  if (count($conf['audioflashvars'])) {
365  $flowplayerAudioConfig = array_merge_recursive($flowplayerAudioConfig, array('clip' => $conf['audioflashvars']));
366  }
367  $flowplayerAudioJsonConfig = str_replace(array('"true"', '"false"'), array('true', 'false'), json_encode($flowplayerAudioConfig));
368  // Assemble param tags (required?)
369  if (is_array($conf['params.'])) {
370  \TYPO3\CMS\Core\Utility\GeneralUtility::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
371  }
372  $videoFlashParams = '';
373  if (is_array($conf['params.'])) {
374  foreach ($conf['params.'] as $name => $value) {
375  $videoFlashParams .= '<param name="' . $name . '" value="' . $value . '" />' . LF;
376  }
377  }
378  $audioFlashParams = $videoFlashParams;
379  // Required param tags
380  $videoFlashParams .= '<param name="movie" value="' . $player . '" />' . LF;
381  $videoFlashParams .= '<param name="flashvars" value=\'config=' . $flowplayerVideoJsonConfig . '\' />' . LF;
382  $audioFlashParams .= '<param name="movie" value="' . $player . '" />' . LF;
383  $audioFlashParams .= '<param name="flashvars" value=\'config=' . $flowplayerAudioJsonConfig . '\' />' . LF;
384  // Assemble audio/video tag attributes
385  $attributes = '';
386  if (is_array($conf['attributes.'])) {
387  \TYPO3\CMS\Core\Utility\GeneralUtility::remapArrayKeys($conf['attributes.'], $typeConf['attributes.']['params.']);
388  }
389  foreach ($this->html5TagAttributes as $attribute) {
390  if ($conf['attributes.'][$attribute] === 'true' || $conf['attributes.'][$attribute] === strToLower($attribute) || $conf['attributes.'][$attribute] === $attribute) {
391  $attributes .= strToLower($attribute) . '="' . strToLower($attribute) . '" ';
392  }
393  }
394  // Media dimensions
395  $width = isset($conf['width.']) ? $this->cObj->stdWrap($conf['width'], $conf['width.']) : $conf['width'];
396  if (!$width) {
397  $width = $conf[$type . '.']['defaultWidth'];
398  }
399  $height = isset($conf['height.']) ? $this->cObj->stdWrap($conf['height'], $conf['height.']) : $conf['height'];
400  if (!$height) {
401  $height = $conf[$type . '.']['defaultHeight'];
402  }
403  // Alternate content
404  $alternativeContent = isset($conf['alternativeContent.']) ? $this->cObj->stdWrap($conf['alternativeContent'], $conf['alternativeContent.']) : $conf['alternativeContent'];
405  // Render video
406  if ($conf['type'] === 'video') {
407  if ($conf['preferFlashOverHtml5']) {
408  // Flash with video tag fallback
409  $conf['params.']['playerFallbackOrder'] = array('flash', 'html5');
410  $flashDivContent = $videoFlashParams . LF . '<video id="' . $replaceElementIdString . '_video_js" class="video-js" ' . $attributes . 'controls="controls" mediagroup="' . $replaceElementIdString . '" width="' . $width . '" height="' . $height . '">' . LF . $videoSources . $videoCaptions . $alternativeContent . LF . '</video>' . LF;
411  $divContent = '
412  <div id="' . $replaceElementIdString . '_flash_install_info" class="flash-install-info"></div>' . LF . '<noscript>' . LF . '<object id="' . $replaceElementIdString . '_vjs_flash" type="application/x-shockwave-flash" data="' . $player . '" width="' . $width . '" height="' . $height . '">' . LF . $flashDivContent . '</object>' . LF . '</noscript>' . LF;
413  $content = str_replace('###SWFOBJECT###', '<div id="' . $replaceElementIdString . '_video" class="flashcontainer" style="width:' . $width . 'px; height:' . $height . 'px;">' . LF . $divContent . '</div>', $content);
414  } else {
415  // Video tag with Flash fallback
416  $conf['params.']['playerFallbackOrder'] = array('html5', 'flash');
417  $videoTagContent = $videoSources . $videoCaptions;
418  if (isset($conf['videoflashvars']['url'])) {
419  $videoTagContent .= '
420  <noscript>' . LF . '<object class="vjs-flash-fallback" id="' . $replaceElementIdString . '_vjs_flash_fallback" type="application/x-shockwave-flash" data="' . $player . '" width="' . $width . '" height="' . $height . '">' . LF . $videoFlashParams . LF . $alternativeContent . LF . '</object>' . LF . '</noscript>';
421  }
422  $divContent = '
423  <div id="' . $replaceElementIdString . '_flash_install_info" class="flash-install-info"></div>' . LF . '<video id="' . $replaceElementIdString . '_video_js" class="video-js" ' . $attributes . 'controls="controls" mediagroup="' . $replaceElementIdString . '" width="' . $width . '" height="' . $height . '">' . LF . $videoTagContent . '</video>';
424  $content = str_replace('###SWFOBJECT###', '<div id="' . $replaceElementIdString . '_video" class="video-js-box" style="width:' . $width . 'px; height:' . $height . 'px;">' . LF . $divContent . '</div>', $content);
425  }
426  }
427  // Render audio
428  if ($conf['type'] === 'audio' || $audioSources || isset($conf['audioFallback'])) {
429  if ($conf['preferFlashOverHtml5']) {
430  // Flash with audio tag fallback
431  $flashDivContent = $audioFlashParams . LF . '<audio id="' . $replaceElementIdString . '_audio_element"' . $attributes . ($conf['type'] === 'video' ? ' mediagroup="' . $replaceElementIdString . 'style="position:absolute;left:-10000px;"' : ' controls="controls"') . ' style="width:' . $width . 'px; height:' . $height . 'px;">' . LF . $audioSources . $alternativeContent . LF . '</audio>' . LF;
432  $divContent = ($conf['type'] === 'video' ? '' : '<div id="' . $replaceElementIdString . '_flash_install_info" class="flash-install-info"></div>' . LF) . '<noscript>' . LF . '<object id="' . $replaceElementIdString . '_audio_flash" type="application/x-shockwave-flash" data="' . $player . '" width="' . ($conf['type'] === 'video' ? 0 : $width) . '" height="' . ($conf['type'] === 'video' ? 0 : $height) . '">' . LF . $flashDivContent . '</object>' . LF . '</noscript>' . LF;
433  $audioContent = '<div id="' . $replaceElementIdString . '_audio_box" class="audio-flash-container" style="width:' . ($conf['type'] === 'video' ? 0 : $width) . 'px; height:' . ($conf['type'] === 'video' ? 0 : $height) . 'px;">' . LF . $divContent . '</div>';
434  } else {
435  // Audio tag with Flash fallback
436  $audioTagContent = $audioSources;
437  if (isset($conf['audioflashvars']['url'])) {
438  $audioTagContent .= '
439  <noscript>' . LF . '<object class="audio-flash-fallback" id="' . $replaceElementIdString . '_audio_flash" type="application/x-shockwave-flash" data="' . $player . '" width="' . $width . '" height="' . $height . '">' . LF . $audioFlashParams . LF . $alternativeContent . LF . '</object>' . LF . '</noscript>';
440  }
441  $divContent = ($conf['type'] === 'video' ? '' : '<div id="' . $replaceElementIdString . '_flash_install_info" class="flash-install-info"></div>' . LF) . '<audio id="' . $replaceElementIdString . '_audio_element" class="audio-element"' . $attributes . ($conf['type'] === 'video' ? ' mediagroup="' . $replaceElementIdString . '" style="position:absolute;left:-10000px;"' : ' controls="controls"') . '>' . LF . $audioTagContent . '</audio>' . LF . $audioSourcesEmbeddingJsScript;
442  $audioContent = '<div id="' . $replaceElementIdString . '_audio_box" class="audio-box" style="width:' . ($conf['type'] === 'video' ? 0 : $width) . 'px; height:' . ($conf['type'] === 'video' ? 0 : $height) . 'px;">' . LF . $divContent . '</div>';
443  }
444  if ($conf['type'] === 'audio') {
445  $content = str_replace('###SWFOBJECT###', $audioContent, $content);
446  } else {
447  $content .= LF . $audioContent;
448  }
449  }
450  // Assemble inline JS code
451  $videoJsSetup = '';
452  $flowplayerHandlers = '';
453  if ($conf['type'] === 'video') {
454  // Assemble videoJS options
455  $videoJsOptions = array();
456  foreach ($this->videoJsOptions as $videoJsOption) {
457  if (isset($conf['params.'][$videoJsOption])) {
458  $videoJsOptions[$videoJsOption] = $conf['params.'][$videoJsOption];
459  }
460  }
461  $videoJsOptions = count($videoJsOptions) ? json_encode($videoJsOptions) : '{}';
462  // videoJS setup and videoJS listeners for audio description synchronisation
463  if ($audioSources || isset($conf['audioFallback'])) {
464  $videoJsSetup = '
465  var ' . $replaceElementIdString . '_video = VideoJS.setup("' . $replaceElementIdString . '_video_js", ' . $videoJsOptions . ');
466  var ' . $replaceElementIdString . '_video_element = document.getElementById("' . $replaceElementIdString . '_video_js");
467  var ' . $replaceElementIdString . '_audio_element = document.getElementById("' . $replaceElementIdString . '_audio_element");
468  if (!!' . $replaceElementIdString . '_video_element && !!' . $replaceElementIdString . '_audio_element) {
469  ' . $replaceElementIdString . '_audio_element.muted = true;
470  VideoJS.addListener(' . $replaceElementIdString . '_video_element, "pause", function () { document.getElementById("' . $replaceElementIdString . '_audio_element").pause(); });
471  VideoJS.addListener(' . $replaceElementIdString . '_video_element, "play", function () { try {document.getElementById("' . $replaceElementIdString . '_audio_element").currentTime = document.getElementById("' . $replaceElementIdString . '_video_js").currentTime} catch(e) {}; document.getElementById("' . $replaceElementIdString . '_audio_element").play(); });
472  VideoJS.addListener(' . $replaceElementIdString . '_video_element, "seeked", function () { document.getElementById("' . $replaceElementIdString . '_audio_element").currentTime = document.getElementById("' . $replaceElementIdString . '_video_js").currentTime; });
473  VideoJS.addListener(' . $replaceElementIdString . '_video_element, "volumechange", function () { document.getElementById("' . $replaceElementIdString . '_audio_element").volume = document.getElementById("' . $replaceElementIdString . '_video_js").volume; });
474  }';
475  } else {
476  $videoJsSetup = '
477  var ' . $replaceElementIdString . '_video = VideoJS.setup("' . $replaceElementIdString . '_video_js", ' . $videoJsOptions . ');
478  ';
479  }
480  // Prefer Flash or fallback to Flash
481  $videoSourcesEmbedding = '';
482  // If we have a video file for Flash
483  if (isset($conf['filename'])) {
484  // If we prefer Flash
485  if ($conf['preferFlashOverHtml5']) {
486  $videoTagAssembly = '';
487  // Create "source" elements
488  if (is_array($conf['sources']) && count($conf['sources'])) {
489  foreach ($conf['sources'] as $source) {
490  $fileinfo = \TYPO3\CMS\Core\Utility\GeneralUtility::split_fileref($source);
491  $mimeType = $this->mimeTypes[$fileinfo['fileext']]['video'];
492  $videoTagAssembly .= '
493  ' . $replaceElementIdString . '_video_js.appendChild($f.extend(document.createElement("source"), {
494  src: "' . $source . '",
495  type: "' . $mimeType . '"
496  }));';
497  }
498  // Create "track" elements
499  if (isset($conf['caption'])) {
500  // Assemble captions track tag
501  // It will take a while before the captions are loaded and parsed...
502  $videoTagAssembly .= '
503  var track = document.createElement("track");
504  track.setAttribute("src", "' . $conf['caption'] . '");
505  track.setAttribute("id", "' . $replaceElementIdString . '_captions_track");
506  track.setAttribute("kind", "captions");
507  track.setAttribute("default", "default");
508  ' . $replaceElementIdString . '_video_js.appendChild(track);';
509  }
510  $videoTagAssembly .= '
511  $f.extend(' . $replaceElementIdString . '_video_js, {
512  id: "' . $replaceElementIdString . '_video_js",
513  className: "video-js",
514  controls: "controls",
515  mediagroup: "' . $replaceElementIdString . '",
516  preload: "none",
517  width: "' . $width . '",
518  height: "' . $height . '"
519  });
520  ' . $replaceElementIdString . '_video.appendChild(' . $replaceElementIdString . '_video_js);
521  ' . $replaceElementIdString . '_video.className = "video-js-box";';
522  $videoTagAssembly .= $videoJsSetup;
523  }
524  $videoSourcesEmbedding = '
525  var ' . $replaceElementIdString . '_video = document.getElementById("' . $replaceElementIdString . '_video");
526  var ' . $replaceElementIdString . '_video_js = document.createElement("video");
527  if (flashembed.getVersion()[0] > 0) {
528  // Flash is available
529  var videoPlayer = flowplayer("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ', ' . $flowplayerVideoJsonConfig . ').load();
530  videoPlayer.onBeforeUnload(function () { return false; });
531  } else if (!!' . $replaceElementIdString . '_video_js.canPlayType) {
532  // Flash is not available: fallback to videoJS if video tag is supported
533  ' . $videoTagAssembly . '
534  } else {
535  // Neither Flash nor video is available: offer to install Flash
536  flashembed("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ');
537  }';
538  } elseif (is_array($conf['sources'])) {
539  // HTML5 is the preferred rendering method
540  // Test whether the browser supports any of types of the provided sources
541  $supported = array();
542  foreach ($conf['sources'] as $source) {
543  $fileinfo = \TYPO3\CMS\Core\Utility\GeneralUtility::split_fileref($source);
544  $mimeType = $this->mimeTypes[$fileinfo['fileext']]['video'];
545  $supported[] = $replaceElementIdString . '_videoTag.canPlayType("' . $mimeType . '") != ""';
546  }
547  // Testing whether the browser supports the video tag with any of the provided source types
548  // If no support, embed flowplayer
549  $videoSourcesEmbedding = '
550  var ' . $replaceElementIdString . '_videoTag = document.createElement(\'video\');
551  var ' . $replaceElementIdString . '_video_box = document.getElementById("' . $replaceElementIdString . '_video");
552  if (' . $replaceElementIdString . '_video_box) {
553  if (!' . $replaceElementIdString . '_videoTag || !' . $replaceElementIdString . '_videoTag.canPlayType || !(' . (count($supported) ? implode(' || ', $supported) : 'false') . ')) {
554  // Avoid showing an empty video element
555  if (document.getElementById("' . $replaceElementIdString . '_video_js")) {
556  document.getElementById("' . $replaceElementIdString . '_video_js").style.display = "none";
557  }
558  if (flashembed.getVersion()[0] > 0) {
559  // Flash is available
560  var videoPlayer = flowplayer("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ', ' . $flowplayerVideoJsonConfig . ').load();
561  videoPlayer.onBeforeUnload(function () { return false; });
562  } else {
563  // Neither Flash nor video is available: offer to install Flash
564  flashembed("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ');
565  }
566  } else {' . $videoJsSetup . '
567  }
568  }';
569  }
570  }
571  }
572  // Audio fallback to Flash
573  $audioSourcesEmbedding = '';
574  // If we have an audio file for Flash
575  if (isset($conf['audioFallback'])) {
576  // If we prefer Flash in
577  if ($conf['preferFlashOverHtml5']) {
578  $audioTagAssembly = '';
579  // Create "source" elements
580  if (is_array($conf['audioSources']) && count($conf['audioSources'])) {
581  foreach ($conf['audioSources'] as $source) {
582  $fileinfo = \TYPO3\CMS\Core\Utility\GeneralUtility::split_fileref($source);
583  $mimeType = $this->mimeTypes[$fileinfo['fileext']]['audio'];
584  $audioTagAssembly .= '
585  ' . $replaceElementIdString . '_audio_element.appendChild($f.extend(document.createElement("source"), {
586  src: "' . $source . '",
587  type: "' . $mimeType . '"
588  }));';
589  }
590  $audioTagAssembly .= '
591  $f.extend(' . $replaceElementIdString . '_audio_element, {
592  id: "' . $replaceElementIdString . '_audio_element",
593  className: "audio-element",
594  controls: "' . ($conf['type'] === 'video' ? '' : 'controls') . '",
595  mediagroup: "' . $replaceElementIdString . '",
596  preload: "none",
597  width: "' . ($conf['type'] === 'video' ? 0 : $width) . 'px",
598  height: "' . ($conf['type'] === 'video' ? 0 : $height) . 'px"
599  });
600  ' . $replaceElementIdString . '_audio_box.appendChild(' . $replaceElementIdString . '_audio_element);
601  ' . $replaceElementIdString . '_audio_box.className = "audio-box";';
602  }
603  $audioSourcesEmbedding = '
604  var ' . $replaceElementIdString . '_audio_box = document.getElementById("' . $replaceElementIdString . '_audio_box");
605  var ' . $replaceElementIdString . '_audio_element = document.createElement("audio");
606  if (flashembed.getVersion()[0] > 0) {
607  // Flash is available
608  var audioPlayer = flowplayer("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ', ' . $flowplayerAudioJsonConfig . ').load();
609  audioPlayer.onBeforeUnload(function () { return false; });
610  ' . ($conf['type'] === 'video' ? 'audioPlayer.mute();' : '') . '
611  } else if (!!' . $replaceElementIdString . '_audio_element.canPlayType) {
612  // Flash is not available: fallback to audio element if audio tag is supported
613  ' . $audioTagAssembly . '
614  } else {
615  // Neither Flash nor audio is available: offer to install Flash if this is not an audio description of a video
616  ' . ($conf['type'] === 'video' ? '' : 'flashembed("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ');') . '
617  }';
618  } elseif (is_array($conf['audioSources'])) {
619  // HTML5 is the preferred rendering method
620  // Test whether the browser supports any of types of the provided sources
621  $supported = array();
622  foreach ($conf['audioSources'] as $source) {
623  $fileinfo = \TYPO3\CMS\Core\Utility\GeneralUtility::split_fileref($source);
624  $mimeType = $this->mimeTypes[$fileinfo['fileext']]['audio'];
625  $supported[] = $replaceElementIdString . '_audioTag.canPlayType("' . $mimeType . '") != ""';
626  }
627  // Testing whether the browser supports the audio tag with any of the provided source types
628  // If no support, embed flowplayer
629  $audioSourcesEmbedding = '
630  var ' . $replaceElementIdString . '_audioTag = document.createElement(\'audio\');
631  var ' . $replaceElementIdString . '_audio_box = document.getElementById("' . $replaceElementIdString . '_audio_box");
632  if (' . $replaceElementIdString . '_audio_box) {
633  if (!' . $replaceElementIdString . '_audioTag || !' . $replaceElementIdString . '_audioTag.canPlayType || !(' . (count($supported) ? implode(' || ', $supported) : 'false') . ')) {
634  // Avoid showing an empty audio element
635  if (document.getElementById("' . $replaceElementIdString . '_audio_element")) {
636  document.getElementById("' . $replaceElementIdString . '_audio_element").style.display = "none";
637  }
638  if (flashembed.getVersion()[0] > 0) {
639  var audioPlayer = flowplayer("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ', ' . $flowplayerAudioJsonConfig . ').load();
640  audioPlayer.onBeforeUnload(function () { return false; });
641  ' . ($conf['type'] === 'video' ? 'audioPlayer.mute()' : '') . '
642  } else {
643  // Neither Flash nor audio is available: offer to install Flash if this is not an audio description of a video
644  ' . ($conf['type'] === 'video' ? '' : 'flashembed("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ');') . '
645  }
646  }
647  }';
648  }
649  // Flowplayer eventHandlers for audio description synchronisation
650  $flowplayerHandlers = '';
651  if ($conf['type'] === 'video') {
652  $flowplayerHandlers = '
653  if (flashembed.getVersion()[0] > 0) {
654  // Flash is available
655  var videoPlayer = flowplayer("' . $replaceElementIdString . '_video");
656  if (videoPlayer) {
657  // Control audio description through video control bar
658  videoPlayer.onVolume(function (volume) { flowplayer("' . $replaceElementIdString . '_audio_box").setVolume(volume); });
659  videoPlayer.onMute(function () { flowplayer("' . $replaceElementIdString . '_audio_box").mute(); });
660  videoPlayer.onUnmute(function () { flowplayer("' . $replaceElementIdString . '_audio_box").unmute(); });
661  videoPlayer.onPause(function () { flowplayer("' . $replaceElementIdString . '_audio_box").pause(); });
662  videoPlayer.onResume(function () { flowplayer("' . $replaceElementIdString . '_audio_box").resume(); });
663  videoPlayer.onStart(function () { flowplayer("' . $replaceElementIdString . '_audio_box").play(); });
664  videoPlayer.onStop(function () { flowplayer("' . $replaceElementIdString . '_audio_box").stop(); });
665  videoPlayer.onSeek(function (clip, seconds) { flowplayer("' . $replaceElementIdString . '_audio_box").seek(seconds); });
666  // Mute audio description on start
667  flowplayer("' . $replaceElementIdString . '_audio_box").onStart(function () { this.mute()});
668  // Audio description toggle
669  var videoContainer = document.getElementById("' . $replaceElementIdString . '_video");
670  var buttonContainer = document.createElement("div");
671  $f.extend(buttonContainer, {
672  id: "' . $replaceElementIdString . '_audio_description_toggle",
673  className: "vjs-audio-description-control"
674  });
675  var button = document.createElement("div");
676  buttonContainer.appendChild(button);
677  buttonContainer.style.position = "relative";
678  buttonContainer.style.left = (parseInt(' . $width . ', 10)-27) + "px";
679  videoContainer.parentNode.insertBefore(buttonContainer, videoContainer.nextSibling);
680  VideoJS.addListener(buttonContainer, "click", function () {
681  var buttonContainer = document.getElementById("' . $replaceElementIdString . '_audio_description_toggle");
682  var state = buttonContainer.getAttribute("data-state");
683  if (state == "enabled") {
684  buttonContainer.setAttribute("data-state", "disabled");
685  flowplayer("' . $replaceElementIdString . '_audio_box").mute();
686  } else {
687  buttonContainer.setAttribute("data-state", "enabled");
688  flowplayer("' . $replaceElementIdString . '_audio_box").unmute();
689  }
690  });
691  }
692  }';
693  }
694  }
695  // Wrap up inline JS code
696  $jsInlineCode = $audioSourcesEmbedding . $videoSourcesEmbedding . $flowplayerHandlers;
697  if ($jsInlineCode) {
698  $jsInlineCode = 'VideoJS.DOMReady(function(){' . $jsInlineCode . LF . '});';
699  }
700  $pageRenderer->addJsInlineCode($replaceElementIdString, $jsInlineCode);
701  if (isset($conf['stdWrap.'])) {
702  $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
703  }
704  return $content;
705  }
706 
707 }
static remapArrayKeys(&$array, $mappingTable)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
static split_fileref($fileNameWithPath)
if(!defined('TYPO3_MODE')) $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_userauth.php']['logoff_pre_processing'][]