<?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']);
}
?>