Project

General

Profile

Bug #51042 » class.tslib_content_flowplayer-org.php

Bernhard Eckl, 2013-09-09 14:34

 
<?php
/***************************************************************
* Copyright notice
*
* (c) 2011-2012 Stanislas Rolland <>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
* A copy is found in the textfile GPL.txt and important notices to the license
* from the author is found in LICENSE.txt distributed with these scripts.
*
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

/**
* Contains FlowPlayer class object.
*
* @author Stanislas Rolland
*/
class tslib_content_FlowPlayer extends tslib_content_Abstract {

/**
* File extension to mime type
*/
public $mimeTypes = array(
'aif' => array(
'audio' => 'audio/aiff',
),
'au' => array(
'audio' => 'audio/x-au',
),
'avi' => array(
'audio' => 'video/x-msvideo',
),
'asf' => array(
'video' => 'video/x-ms-asf',
),
'class' => array(
'audio' => 'application/java',
'video' => 'application/java',
),
'dcr' => array(
'video' => 'application/x-director',
),
'flac' => array(
'audio' => 'audio/flac',
),
'flv' => array(
'video' => 'video/x-flv',
),
'mp3' => array(
'audio' => 'audio/mpeg',
),
'mp4' => array(
'video' => 'video/mp4',
),
'oga' => array(
'audio' => 'audio/ogg',
),
'ogg' => array(
'audio' => 'audio/ogg',
'video' => 'video/ogg',
),
'ogv' => array(
'video' => 'video/ogg',
),
'swa' => array(
'audio' => 'audio/x-m4a',
),
'mov' => array(
'video' => 'video/quicktime',
),
'm4a' => array(
'audio' => 'audio/mp4a-latm',
),
'm4v' => array(
'video' => 'video/x-m4v',
),
'qt' => array(
'video' => 'video/quicktime',
),
'swa' => array(
'audio' => 'application/x-director',
),
'swf' => array(
'audio' => 'application/x-shockwave-flash',
'video' => 'application/x-shockwave-flash',
),
'wav' => array(
'audio' => 'audio/wave',
),
'webm' => array(
'audio' => 'audio/webm',
'video' => 'video/webm',
),
'wmv' => array(
'audio' => 'audio/x-ms-wmv',
)
);

/**
* VideoJS options
*/
public $videoJsOptions = array(
// Use the browser's controls (iPhone)
'useBuiltInControls',
// Display control bar below video vs. in front of
'controlsBelow',
// Make controls visible when page loads
'controlsAtStart',
// Hide controls when not over the video
'controlsHiding',
// Will be overridden by localStorage volume if available
'defaultVolume',
// Players and order to use them
'playerFallbackOrder',
);

/**
* htlm5 tag attributes
*/
public $html5TagAttributes = array(
'autoPlay',
'controls',
'loop',
'preload',
);

/**
* Flowplayer captions plugin configuration
*/
public $flowplayerCaptionsConfig = array(
'plugins' => array(
// The captions plugin
'captions' => array(
'url' => 'flowplayer.captions-3.2.3.swf',
// Pointer to a content plugin (see below)
'captionTarget' => 'content'
),
// Configure a content plugin so that it looks good for showing captions
'content' => array(
'url' => 'flowplayer.content-3.2.0.swf',
'bottom' => 5,
'height' => 40,
'backgroundColor' => 'transparent',
'backgroundGradient' => 'none',
'border' => 0,
'textDecoration' => 'outline',
'style' => array(
'body' => array(
'fontSize' => 14,
'fontFamily' => 'Arial',
'textAlign' => 'center',
'color' => '#ffffff'
)
)
),
),
);

/**
* Flowplayer audio configuration
*/
public $flowplayerAudioConfig = array(
'provider' => 'audio',
'plugins' => array(
'audio' => array(
'url' => 'flowplayer.audio-3.2.2.swf'
),
'controls' => array(
'autoHide' => FALSE,
'fullscreen' => FALSE,
),
),
);

/**
* Flowplayer configuration for the audio description
*/
public $flowplayerAudioDescriptionConfig = array(
// The controls plugin
'plugins' => array(
'controls' => NULL,
),
);

/**
* Rendering the cObject, SWFOBJECT
*
* @param array $conf Array of TypoScript properties
* @return string Output
*/
public function render($conf = array()) {
$prefix = '';
if ($GLOBALS['TSFE']->baseUrl) {
$prefix = $GLOBALS['TSFE']->baseUrl;
}
if ($GLOBALS['TSFE']->absRefPrefix) {
$prefix = $GLOBALS['TSFE']->absRefPrefix;
}
;
// Initialize content
$replaceElementIdString = uniqid('mmswf');
$GLOBALS['TSFE']->register['MMSWFID'] = $replaceElementIdString;

$layout = isset($conf['layout.'])
? $this->cObj->stdWrap($conf['layout'], $conf['layout.'])
: $conf['layout'];
$content = str_replace('###ID###', $replaceElementIdString, $layout);

$type = isset($conf['type.'])
? $this->cObj->stdWrap($conf['type'], $conf['type.'])
: $conf['type'];
$typeConf = $conf[$type . '.'];

// Add Flowplayer js-file
$GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . 'contrib/flowplayer/example/flowplayer-3.2.6.min.js');
// Add Flowpayer css for exprss install
$GLOBALS['TSFE']->getPageRenderer()->addCssFile(TYPO3_mainDir . '../t3lib/js/flowplayer/express-install.css');
// Add videoJS js-file
$GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . 'contrib/videojs/video-js/video.js');
// Add videoJS js-file
$GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . 'contrib/videojs/video-js/video.js');
// Add videoJS css-file
$GLOBALS['TSFE']->getPageRenderer()->addCssFile(TYPO3_mainDir . 'contrib/videojs/video-js/video-js.css');
// Add extended videoJS control bar
$GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . '../t3lib/js/videojs/control-bar.js');
$GLOBALS['TSFE']->getPageRenderer()->addCssFile(TYPO3_mainDir . '../t3lib/js/videojs/control-bar.css');

// Build Flash configuration
$player = isset($typeConf['player.'])
? $this->cObj->stdWrap($typeConf['player'], $typeConf['player.'])
: $typeConf['player'];
if (!$player) {
$player = $prefix . TYPO3_mainDir . 'contrib/flowplayer/flowplayer-3.2.7.swf';
}
$installUrl = isset($conf['installUrl.'])
? $this->cObj->stdWrap($conf['installUrl'], $conf['installUrl.'])
: $conf['installUrl'];
if (!$installUrl) {
$installUrl = $prefix . TYPO3_mainDir . 'contrib/flowplayer/expressinstall.swf';
}
$flashVersion = isset($conf['flashVersion.'])
? $this->cObj->stdWrap($conf['flashVersion'], $conf['flashVersion.'])
: $conf['flashVersion'];
if (!$flashVersion) {
$flashVersion = array(9,115);
}

$flashConfiguration = array(
// Flowplayer component
'src' => $player,
// Express install url
'expressInstall' => $installUrl,
// Require at least this Flash version
'version' => $flashVersion,
// Older versions will see a message
'onFail' => '###ONFAIL###'
);
$flashDownloadUrl = 'http://www.adobe.com/go/getflashplayer';
$onFail = 'function() {
if (!(flashembed.getVersion()[0] > 0)) {
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>";
document.getElementById("' . $replaceElementIdString . '_flash_install_info").innerHTML = "<div class=\"message\">" + message + "</div>";
}
}';
$flashConfiguration = json_encode($flashConfiguration);
$flashConfiguration = str_replace('"###ONFAIL###"', $onFail, $flashConfiguration);

$filename = isset($conf['file.'])
? $this->cObj->stdWrap($conf['file'], $conf['file.'])
: $conf['file'];

if ($filename) {
if (strpos($filename, '://') !== FALSE) {
$conf['flashvars.']['url'] = $filename;
} else {
if ($prefix) {
$conf['flashvars.']['url'] = $prefix . $filename;
} else {
$conf['flashvars.']['url'] = str_repeat('../', substr_count($player, '/')) . $filename;
}
}
}
if (is_array($conf['sources'])) {
foreach ($conf['sources'] as $key => $source) {
if (strpos($source, '://') === FALSE) {
$conf['sources'][$key] = $prefix . $source;
}
}
}
if (is_array($conf['audioSources'])) {
foreach ($conf['audioSources'] as $key => $source) {
if (strpos($source, '://') === FALSE) {
$conf['audioSources'][$key] = $prefix . $source;
}
}
}
if (isset($conf['audioFallback']) && strpos($conf['audioFallback'], '://') === FALSE) {
$conf['audioFallback'] = $prefix . $conf['audioFallback'];
}
if (isset($conf['caption']) && strpos($conf['caption'], '://') === FALSE) {
$conf['caption'] = $prefix . $conf['caption'];
}

// Write calculated values in conf for the hook
$conf['player'] = $player ? $player : $filename;
$conf['installUrl'] = $installUrl;
$conf['filename'] = $conf['flashvars.']['url'];
$conf['prefix'] = $prefix;

// merge with default parameters
$conf['flashvars.'] = array_merge((array) $typeConf['default.']['flashvars.'], (array) $conf['flashvars.']);
$conf['params.'] = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.']);
$conf['attributes.'] = array_merge((array) $typeConf['default.']['attributes.'], (array) $conf['attributes.']);
$conf['embedParams'] = 'flashvars, params, attributes';

// Hook for manipulating the conf array, it's needed for some players like flowplayer
if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'])) {
foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/hooks/class.tx_cms_mediaitems.php']['swfParamTransform'] as $classRef) {
t3lib_div::callUserFunction($classRef, $conf, $this);
}
}

// Flowplayer config
$flowplayerVideoConfig = array();
$flowplayerAudioConfig = array();
if (is_array($conf['flashvars.'])) {
t3lib_div::remapArrayKeys($conf['flashvars.'], $typeConf['mapping.']['flashvars.']);
} else {
$conf['flashvars.'] = array();
}
$conf['videoflashvars'] = $conf['flashvars.'];
$conf['audioflashvars'] = $conf['flashvars.'];
$conf['audioflashvars']['url'] = $conf['audioFallback'];

// Render video sources
$videoSources = '';
if (is_array($conf['sources'])) {
foreach ($conf['sources'] as $source) {
$fileinfo = t3lib_div::split_fileref($source);
$mimeType = $this->mimeTypes[$fileinfo['fileext']]['video'];
$videoSources .= '<source src="' . $source . '"' . ($mimeType ? ' type="' . $mimeType . '"' : '') . ' />' . LF;
}
}

// Render audio sources
$audioSources = '';
if (is_array($conf['audioSources'])) {
foreach ($conf['audioSources'] as $source) {
$fileinfo = t3lib_div::split_fileref($source);
$mimeType = $this->mimeTypes[$fileinfo['fileext']]['audio'];
$audioSources .= '<source src="' . $source . '"' . ($mimeType ? ' type="' . $mimeType . '"' : '') . ' />' . LF;
}
}

// Configure captions
if ($conf['type'] === 'video' && isset($conf['caption'])) {
// Assemble captions track tag
$videoCaptions = '<track id="' . $replaceElementIdString . '_captions_track" kind="captions" src="' . $conf['caption'] . '"></track>' . LF;
// Add videoJS extension for captions
$GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . '../t3lib/js/videojs/captions.js');
// Flowplayer captions
$conf['videoflashvars']['captionUrl'] = $conf['caption'];
// Flowplayer captions plugin configuration
$flowplayerVideoConfig = array_merge_recursive($flowplayerVideoConfig, $this->flowplayerCaptionsConfig);
}

// Configure flowplayer audio fallback
if (isset($conf['audioFallback'])) {
$flowplayerAudioConfig = array_merge_recursive($flowplayerAudioConfig, $this->flowplayerAudioConfig);
}

// Configure audio description
if ($conf['type'] == 'video') {
if (is_array($conf['audioSources']) && count($conf['audioSources'])) {
// Add videoJS audio description toggle
$GLOBALS['TSFE']->getPageRenderer()->addJsFile(TYPO3_mainDir . '../t3lib/js/videojs/audio-description.js');
}
if (isset($conf['audioFallback'])) {
// Audio description flowplayer config (remove controls)
$flowplayerAudioConfig = array_merge_recursive($flowplayerAudioConfig, $this->flowplayerAudioDescriptionConfig);
}
}

// Assemble Flowplayer configuration
if (count($conf['videoflashvars'])) {
$flowplayerVideoConfig = array_merge_recursive($flowplayerVideoConfig, array('clip' => $conf['videoflashvars']));
}
$flowplayerVideoJsonConfig = str_replace(array('"true"', '"false"'), array('true', 'false'), json_encode($flowplayerVideoConfig));
if (count($conf['audioflashvars'])) {
$flowplayerAudioConfig = array_merge_recursive($flowplayerAudioConfig, array('clip' => $conf['audioflashvars']));
}
$flowplayerAudioJsonConfig = str_replace(array('"true"', '"false"'), array('true', 'false'), json_encode($flowplayerAudioConfig));
// Assemble param tags (required?)
if (is_array($conf['params.'])) {
t3lib_div::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
}
$videoFlashParams = '';
if (is_array($conf['params.'])) {
foreach ($conf['params.'] as $name => $value) {
$videoFlashParams .= '<param name="' . $name . '" value="' . $value . '" />' . LF;
}
}
$audioFlashParams = $videoFlashParams;

// Required param tags
$videoFlashParams .= '<param name="movie" value="' . $player . '" />' . LF;
$videoFlashParams .= '<param name="flashvars" value=\'config=' . $flowplayerVideoJsonConfig . '\' />' . LF;
$audioFlashParams .= '<param name="movie" value="' . $player . '" />' . LF;
$audioFlashParams .= '<param name="flashvars" value=\'config=' . $flowplayerAudioJsonConfig . '\' />' . LF;

// Assemble audio/video tag attributes
$attributes = '';
if (is_array($conf['attributes.'])) {
t3lib_div::remapArrayKeys($conf['attributes.'], $typeConf['attributes.']['params.']);
}
foreach ($this->html5TagAttributes as $attribute) {
if ($conf['attributes.'][$attribute] === 'true' || $conf['attributes.'][$attribute] === strToLower($attribute) || $conf['attributes.'][$attribute] === $attribute) {
$attributes .= strToLower($attribute) . '="' . strToLower($attribute) . '" ';
}
}

// Media dimensions
$width = isset($conf['width.'])
? $this->cObj->stdWrap($conf['width'], $conf['width.'])
: $conf['width'];
if (!$width) {
$width = $conf[$type . '.']['defaultWidth'];
}

$height = isset($conf['height.'])
? $this->cObj->stdWrap($conf['height'], $conf['height.'])
: $conf['height'];
if (!$height) {
$height = $conf[$type . '.']['defaultHeight'];
}

// Alternate content
$alternativeContent = isset($conf['alternativeContent.'])
? $this->cObj->stdWrap($conf['alternativeContent'], $conf['alternativeContent.'])
: $conf['alternativeContent'];

// Render video
if ($conf['type'] === 'video') {
if ($conf['preferFlashOverHtml5']) {
// Flash with video tag fallback
$conf['params.']['playerFallbackOrder'] = array('flash', 'html5');
$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;
$divContent = '
<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;
$content = str_replace('###SWFOBJECT###', '<div id="' . $replaceElementIdString . '_video" class="flashcontainer" style="width:' . $width . 'px; height:' . $height . 'px;">' . LF . $divContent . '</div>', $content);
} else {
// Video tag with Flash fallback
$conf['params.']['playerFallbackOrder'] = array('html5', 'flash');
$videoTagContent = $videoSources . $videoCaptions;
if (isset($conf['videoflashvars']['url'])) {
$videoTagContent .= '
<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>';
}
$divContent = '
<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>';
$content = str_replace('###SWFOBJECT###', '<div id="' . $replaceElementIdString . '_video" class="video-js-box" style="width:' . $width . 'px; height:' . $height . 'px;">' . LF . $divContent . '</div>', $content);
}
}
// Render audio
if ($conf['type'] === 'audio' || $audioSources || isset($conf['audioFallback'])) {
if ($conf['preferFlashOverHtml5']) {
// Flash with audio tag fallback
$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;
$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;
$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>';
} else {
// Audio tag with Flash fallback
$audioTagContent = $audioSources;
if (isset($conf['audioflashvars']['url'])) {
$audioTagContent .= '
<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>';
}
$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;
$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>';
}
if ($conf['type'] === 'audio') {
$content = str_replace('###SWFOBJECT###', $audioContent, $content);
} else {
$content .= LF . $audioContent;
}
}

// Assemble inline JS code
$videoJsSetup = '';
$flowplayerHandlers = '';
if ($conf['type'] === 'video') {
// Assemble videoJS options
$videoJsOptions = array();
foreach ($this->videoJsOptions as $videoJsOption) {
if (isset($conf['params.'][$videoJsOption])) {
$videoJsOptions[$videoJsOption] = $conf['params.'][$videoJsOption];
}
}
$videoJsOptions = count($videoJsOptions) ? json_encode($videoJsOptions) : '{}';

// videoJS setup and videoJS listeners for audio description synchronisation
if ($audioSources || isset($conf['audioFallback'])) {
$videoJsSetup = '
var ' . $replaceElementIdString . '_video = VideoJS.setup("' . $replaceElementIdString . '_video_js", ' . $videoJsOptions . ');
var ' . $replaceElementIdString . '_video_element = document.getElementById("' . $replaceElementIdString . '_video_js");
var ' . $replaceElementIdString . '_audio_element = document.getElementById("' . $replaceElementIdString . '_audio_element");
if (!!' . $replaceElementIdString . '_video_element && !!' . $replaceElementIdString . '_audio_element) {
' . $replaceElementIdString . '_audio_element.muted = true;
VideoJS.addListener(' . $replaceElementIdString . '_video_element, "pause", function () { document.getElementById("' . $replaceElementIdString . '_audio_element").pause(); });
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(); });
VideoJS.addListener(' . $replaceElementIdString . '_video_element, "seeked", function () { document.getElementById("' . $replaceElementIdString . '_audio_element").currentTime = document.getElementById("' . $replaceElementIdString . '_video_js").currentTime; });
VideoJS.addListener(' . $replaceElementIdString . '_video_element, "volumechange", function () { document.getElementById("' . $replaceElementIdString . '_audio_element").volume = document.getElementById("' . $replaceElementIdString . '_video_js").volume; });
}';
} else {
$videoJsSetup = '
var ' . $replaceElementIdString . '_video = VideoJS.setup("' . $replaceElementIdString . '_video_js", ' . $videoJsOptions . ');
';
}
// Prefer Flash or fallback to Flash
$videoSourcesEmbedding = '';
// If we have a video file for Flash
if (isset($conf['filename'])) {
// If we prefer Flash
if ($conf['preferFlashOverHtml5']) {
$videoTagAssembly = '';
// Create "source" elements
if (is_array($conf['sources']) && count($conf['sources'])) {
foreach ($conf['sources'] as $source) {
$fileinfo = t3lib_div::split_fileref($source);
$mimeType = $this->mimeTypes[$fileinfo['fileext']]['video'];
$videoTagAssembly .= '
' . $replaceElementIdString . '_video_js.appendChild($f.extend(document.createElement("source"), {
src: "' . $source . '",
type: "' . $mimeType . '"
}));';
}
// Create "track" elements
if (isset($conf['caption'])) {
// Assemble captions track tag
// It will take a while before the captions are loaded and parsed...
$videoTagAssembly .= '
var track = document.createElement("track");
track.setAttribute("src", "' . $conf['caption'] . '");
track.setAttribute("id", "' . $replaceElementIdString . '_captions_track");
track.setAttribute("kind", "captions");
' . $replaceElementIdString . '_video_js.appendChild(track);';
}
$videoTagAssembly .= '
$f.extend(' . $replaceElementIdString . '_video_js, {
id: "' . $replaceElementIdString . '_video_js",
className: "video-js",
controls: "controls",
mediagroup: "' . $replaceElementIdString . '",
preload: "none",
width: "' . $width . '",
height: "' . $height. '"
});
' . $replaceElementIdString . '_video.appendChild(' . $replaceElementIdString . '_video_js);
' . $replaceElementIdString . '_video.className = "video-js-box";';
$videoTagAssembly .= $videoJsSetup;
}
$videoSourcesEmbedding = '
var ' . $replaceElementIdString . '_video = document.getElementById("' . $replaceElementIdString . '_video");
var ' . $replaceElementIdString . '_video_js = document.createElement("video");
if (flashembed.getVersion()[0] > 0) {
// Flash is available
var videoPlayer = flowplayer("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ', ' . $flowplayerVideoJsonConfig . ').load();
videoPlayer.onBeforeUnload(function () { return false; });
} else if (!!' . $replaceElementIdString . '_video_js.canPlayType) {
// Flash is not available: fallback to videoJS if video tag is supported
' . $videoTagAssembly . '
} else {
// Neither Flash nor video is available: offer to install Flash
flashembed("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ');
}';
} elseif (is_array($conf['sources'])) {
// HTML5 is the preferred rendering method
// Test whether the browser supports any of types of the provided sources
$supported = array();
foreach ($conf['sources'] as $source) {
$fileinfo = t3lib_div::split_fileref($source);
$mimeType = $this->mimeTypes[$fileinfo['fileext']]['video'];
$supported[] = $replaceElementIdString . '_videoTag.canPlayType("' . $mimeType . '") != ""';
}
// Testing whether the browser supports the video tag with any of the provided source types
// If no support, embed flowplayer
$videoSourcesEmbedding = '
var ' . $replaceElementIdString . '_videoTag = document.createElement(\'video\');
var ' . $replaceElementIdString . '_video_box = document.getElementById("' . $replaceElementIdString . '_video");
if (' . $replaceElementIdString . '_video_box) {
if (!' . $replaceElementIdString . '_videoTag || !' . $replaceElementIdString . '_videoTag.canPlayType || !(' . (count($supported) ? implode( ' || ', $supported) : 'false') . ')) {
// Avoid showing an empty video element
if (document.getElementById("' . $replaceElementIdString . '_video_js")) {
document.getElementById("' . $replaceElementIdString . '_video_js").style.display = "none";
}
if (flashembed.getVersion()[0] > 0) {
// Flash is available
var videoPlayer = flowplayer("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ', ' . $flowplayerVideoJsonConfig . ').load();
videoPlayer.onBeforeUnload(function () { return false; });
} else {
// Neither Flash nor video is available: offer to install Flash
flashembed("' . $replaceElementIdString . '_video", ' . $flashConfiguration . ');
}
} else {' . $videoJsSetup . '
}
}';
}
}
}
// Audio fallback to Flash
$audioSourcesEmbedding = '';
// If we have an audio file for Flash
if (isset($conf['audioFallback'])) {
// If we prefer Flash in
if ($conf['preferFlashOverHtml5']) {
$audioTagAssembly = '';
// Create "source" elements
if (is_array($conf['audioSources']) && count($conf['audioSources'])) {
foreach ($conf['audioSources'] as $source) {
$fileinfo = t3lib_div::split_fileref($source);
$mimeType = $this->mimeTypes[$fileinfo['fileext']]['audio'];
$audioTagAssembly .= '
' . $replaceElementIdString . '_audio_element.appendChild($f.extend(document.createElement("source"), {
src: "' . $source . '",
type: "' . $mimeType . '"
}));';
}
$audioTagAssembly .= '
$f.extend(' . $replaceElementIdString . '_audio_element, {
id: "' . $replaceElementIdString . '_audio_element",
className: "audio-element",
controls: "' . ($conf['type'] === 'video' ? '' : 'controls') . '",
mediagroup: "' . $replaceElementIdString . '",
preload: "none",
width: "' . ($conf['type'] === 'video' ? 0 : $width) . 'px",
height: "' . ($conf['type'] === 'video' ? 0 : $height) . 'px"
});
' . $replaceElementIdString . '_audio_box.appendChild(' . $replaceElementIdString . '_audio_element);
' . $replaceElementIdString . '_audio_box.className = "audio-box";';
}
$audioSourcesEmbedding = '
var ' . $replaceElementIdString . '_audio_box = document.getElementById("' . $replaceElementIdString . '_audio_box");
var ' . $replaceElementIdString . '_audio_element = document.createElement("audio");
if (flashembed.getVersion()[0] > 0) {
// Flash is available
var audioPlayer = flowplayer("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ', ' . $flowplayerAudioJsonConfig . ').load();
audioPlayer.onBeforeUnload(function () { return false; });
' . ($conf['type'] === 'video' ? 'audioPlayer.mute();' : '') . '
} else if (!!' . $replaceElementIdString . '_audio_element.canPlayType) {
// Flash is not available: fallback to audio element if audio tag is supported
' . $audioTagAssembly . '
} else {
// Neither Flash nor audio is available: offer to install Flash if this is not an audio description of a video
' . ($conf['type'] === 'video' ? '' : 'flashembed("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ');') . '
}';
} elseif (is_array($conf['audioSources'])) {
// HTML5 is the preferred rendering method
// Test whether the browser supports any of types of the provided sources
$supported = array();
foreach ($conf['audioSources'] as $source) {
$fileinfo = t3lib_div::split_fileref($source);
$mimeType = $this->mimeTypes[$fileinfo['fileext']]['audio'];
$supported[] = $replaceElementIdString . '_audioTag.canPlayType("' . $mimeType . '") != ""';
}
// Testing whether the browser supports the audio tag with any of the provided source types
// If no support, embed flowplayer
$audioSourcesEmbedding = '
var ' . $replaceElementIdString . '_audioTag = document.createElement(\'audio\');
var ' . $replaceElementIdString . '_audio_box = document.getElementById("' . $replaceElementIdString . '_audio_box");
if (' . $replaceElementIdString . '_audio_box) {
if (!' . $replaceElementIdString . '_audioTag || !' . $replaceElementIdString . '_audioTag.canPlayType || !(' . (count($supported) ? implode( ' || ', $supported) : 'false') . ')) {
// Avoid showing an empty audio element
if (document.getElementById("' . $replaceElementIdString . '_audio_element")) {
document.getElementById("' . $replaceElementIdString . '_audio_element").style.display = "none";
}
if (flashembed.getVersion()[0] > 0) {
var audioPlayer = flowplayer("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ', ' . $flowplayerAudioJsonConfig . ').load();
audioPlayer.onBeforeUnload(function () { return false; });
' . ($conf['type'] === 'video' ? 'audioPlayer.mute()' : '') . '
} else {
// Neither Flash nor audio is available: offer to install Flash if this is not an audio description of a video
' . ($conf['type'] === 'video' ? '' : 'flashembed("' . $replaceElementIdString . '_audio_box", ' . $flashConfiguration . ');') . '
}
}
}';
}
// Flowplayer eventHandlers for audio description synchronisation
$flowplayerHandlers = '';
if ($conf['type'] === 'video') {
$flowplayerHandlers = '
if (flashembed.getVersion()[0] > 0) {
// Flash is available
var videoPlayer = flowplayer("' . $replaceElementIdString . '_video");
if (videoPlayer) {
// Control audio description through video control bar
videoPlayer.onVolume(function (volume) { flowplayer("' . $replaceElementIdString . '_audio_box").setVolume(volume); });
videoPlayer.onMute(function () { flowplayer("' . $replaceElementIdString . '_audio_box").mute(); });
videoPlayer.onUnmute(function () { flowplayer("' . $replaceElementIdString . '_audio_box").unmute(); });
videoPlayer.onPause(function () { flowplayer("' . $replaceElementIdString . '_audio_box").pause(); });
videoPlayer.onResume(function () { flowplayer("' . $replaceElementIdString . '_audio_box").resume(); });
videoPlayer.onStart(function () { flowplayer("' . $replaceElementIdString . '_audio_box").play(); });
videoPlayer.onStop(function () { flowplayer("' . $replaceElementIdString . '_audio_box").stop(); });
videoPlayer.onSeek(function (clip, seconds) { flowplayer("' . $replaceElementIdString . '_audio_box").seek(seconds); });
// Mute audio description on start
flowplayer("' . $replaceElementIdString . '_audio_box").onStart(function () { this.mute()});
// Audio description toggle
var videoContainer = document.getElementById("' . $replaceElementIdString . '_video");
var buttonContainer = document.createElement("div");
$f.extend(buttonContainer, {
id: "' . $replaceElementIdString . '_audio_description_toggle",
className: "vjs-audio-description-control"
});
var button = document.createElement("div");
buttonContainer.appendChild(button);
buttonContainer.style.position = "relative";
buttonContainer.style.left = (parseInt(' . $width . ', 10)-27) + "px";
videoContainer.parentNode.insertBefore(buttonContainer, videoContainer.nextSibling);
VideoJS.addListener(buttonContainer, "click", function () {
var buttonContainer = document.getElementById("' . $replaceElementIdString . '_audio_description_toggle");
var state = buttonContainer.getAttribute("data-state");
if (state == "enabled") {
buttonContainer.setAttribute("data-state", "disabled");
flowplayer("' . $replaceElementIdString . '_audio_box").mute();
} else {
buttonContainer.setAttribute("data-state", "enabled");
flowplayer("' . $replaceElementIdString . '_audio_box").unmute();
}
});
}
}';
}
}
// Wrap up inline JS code
$jsInlineCode = $audioSourcesEmbedding .
$videoSourcesEmbedding .
$flowplayerHandlers;
if ($jsInlineCode) {
$jsInlineCode = 'VideoJS.DOMReady(function(){' .
$jsInlineCode . LF .
'});';
}
$GLOBALS['TSFE']->getPageRenderer()->addJsInlineCode($replaceElementIdString, $jsInlineCode);

if (isset($conf['stdWrap.'])) {
$content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
}

return $content;
}
}

if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/content/class.tslib_content_flowplayer.php'])) {
include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/content/class.tslib_content_flowplayer.php']);
}
?>
(3-3/5)