/**
     * Rendering the cObject, QTOBJECT
     *
     * @param array $conf Array of TypoScript properties
     * @return string Output
     */
    public function render($conf = array())
    {
        $params = $prefix = '';
        if ($GLOBALS['TSFE']->baseUrl) {
            $prefix = $GLOBALS['TSFE']->baseUrl;
        }
        if ($GLOBALS['TSFE']->absRefPrefix) {
            $prefix = $GLOBALS['TSFE']->absRefPrefix;
        }
        $type = isset($conf['type.']) ? $this->cObj->stdWrap($conf['type'], $conf['type.']) : $conf['type'];
        // If file is audio and an explicit path has not been set,
        // take path from audio fallback property
        if ($type == 'audio' && empty($conf['file'])) {
            $conf['file'] = $conf['audioFallback'];
        }
        $filename = isset($conf['file.']) ? $this->cObj->stdWrap($conf['file'], $conf['file.']) : $conf['file'];
        $typeConf = $conf[$type . '.'];
        // Add QTobject js-file
        $GLOBALS['TSFE']->getPageRenderer()->addJsFile($this->getPathToLibrary('flashmedia/qtobject/qtobject.js'));
        $replaceElementIdString = str_replace('.', '', uniqid('mmqt', TRUE));
        $GLOBALS['TSFE']->register['MMQTID'] = $replaceElementIdString;
        $qtObject = 'QTObject' . $replaceElementIdString;
        // Merge with default parameters
        $conf['params.'] = array_merge((array) $typeConf['default.']['params.'], (array) $conf['params.']);
        if (is_array($conf['params.']) && is_array($typeConf['mapping.']['params.'])) {
            ArrayUtility::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
            foreach ($conf['params.'] as $key => $value) {
                $params .= $qtObject . '.addParam("' . $key . '", "' . $value . '");' . LF;
            }
        }
        $params = ($params ? substr($params, 0, -2) : '') . LF . $qtObject . '.write("' . $replaceElementIdString . '");';
        $alternativeContent = isset($conf['alternativeContent.']) ? $this->cObj->stdWrap($conf['alternativeContent'], $conf['alternativeContent.']) : $conf['alternativeContent'];
        $layout = str_replace(array('###ID###', '###QTOBJECT###'), array($replaceElementIdString, '<div id="' . $replaceElementIdString . '">' . $alternativeContent . '</div>'), isset($conf['layout.']) ? $this->cObj->stdWrap($conf['layout'], $conf['layout.']) : $conf['layout']);
        $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'];
        }
        $fullFilename = $filename;
        // If the file name doesn't contain a scheme, prefix with appropriate data
        if (strpos($filename, '://') === FALSE && !empty($prefix)) {
            $fullFilename = $prefix . $filename;
        }
        $embed = 'var ' . $qtObject . ' = new QTObject("' . $fullFilename . '", "' . $replaceElementIdString . '", "' . $width . '", "' . $height . '");';
        $content = $layout . '
			<script type="text/javascript">
				' . $embed . '
				' . $params . '
			</script>';
        if (isset($conf['stdWrap.'])) {
            $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
        }
        return $content;
    }
    /**
     * Rendering the cObject, SWFOBJECT
     *
     * @param array $conf Array of TypoScript properties
     * @return string Output
     */
    public function render($conf = array())
    {
        /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */
        $pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
        $params = $prefix = '';
        if ($GLOBALS['TSFE']->baseUrl) {
            $prefix = $GLOBALS['TSFE']->baseUrl;
        }
        if ($GLOBALS['TSFE']->absRefPrefix) {
            $prefix = $GLOBALS['TSFE']->absRefPrefix;
        }
        // Initialize content
        $replaceElementIdString = str_replace('.', '', uniqid('mmswf', TRUE));
        $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
        $pageRenderer->addJsFile($this->getPathToLibrary('flowplayer/flowplayer-3.2.13.min.js'));
        // Add Flowpayer css for exprss install
        $pageRenderer->addCssFile($this->getPathToLibrary('flowplayer/express-install/express-install.css'));
        // Add videoJS js-file
        $pageRenderer->addJsFile($this->getPathToLibrary('videojs/video-js/video.js'));
        // Add videoJS css-file
        $pageRenderer->addCssFile($this->getPathToLibrary('videojs/video-js/video-js.css'));
        // Add extended videoJS control bar
        $pageRenderer->addJsFile($this->getPathToLibrary('videojs/video-js/controls/control-bar.js'));
        $pageRenderer->addCssFile($this->getPathToLibrary('videojs/video-js/controls/control-bar.css'));
        // Build Flash configuration
        $player = isset($typeConf['player.']) ? $this->cObj->stdWrap($typeConf['player'], $typeConf['player.']) : $typeConf['player'];
        if (!$player) {
            $player = $prefix . $this->getPathToLibrary('flowplayer/flowplayer-3.2.18.swf');
        } elseif (strpos($player, 'EXT:') === 0) {
            $player = $prefix . $GLOBALS['TSFE']->tmpl->getFileName($player);
        }
        $installUrl = isset($conf['installUrl.']) ? $this->cObj->stdWrap($conf['installUrl'], $conf['installUrl.']) : $conf['installUrl'];
        if (!$installUrl) {
            $installUrl = $prefix . $this->getPathToLibrary('flowplayer/expressinstall.swf');
        } elseif (strpos($installUrl, 'EXT:') === 0) {
            $installUrl = $prefix . $GLOBALS['TSFE']->tmpl->getFileName($installUrl);
        }
        $flashVersion = isset($conf['flashVersion.']) ? $this->cObj->stdWrap($conf['flashVersion'], $conf['flashVersion.']) : $conf['flashVersion'];
        if (!$flashVersion) {
            $flashVersion = array(9, 115);
        }
        $flashConfiguration = array('src' => $player, 'expressInstall' => $installUrl, 'version' => $flashVersion, '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 ?: $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) {
                \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($classRef, $conf, $this);
            }
        }
        // Flowplayer config
        $flowplayerVideoConfig = array();
        $flowplayerAudioConfig = array();
        if (is_array($conf['flashvars.']) && is_array($typeConf['mapping.']['flashvars.'])) {
            ArrayUtility::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 = \TYPO3\CMS\Core\Utility\GeneralUtility::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 = \TYPO3\CMS\Core\Utility\GeneralUtility::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'] . '" default>' . LF;
            // Add videoJS extension for captions
            $pageRenderer->addJsFile($this->getPathToLibrary('videojs/video-js/controls/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
                $pageRenderer->addJsFile($this->getPathToLibrary('videojs/video-js/controls/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.']) && is_array($typeConf['mapping.']['params.'])) {
            ArrayUtility::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.']) && is_array($typeConf['attributes.']['params.'])) {
            ArrayUtility::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 = \TYPO3\CMS\Core\Utility\GeneralUtility::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");
			track.setAttribute("default", "default");
			' . $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 = \TYPO3\CMS\Core\Utility\GeneralUtility::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 = \TYPO3\CMS\Core\Utility\GeneralUtility::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 = \TYPO3\CMS\Core\Utility\GeneralUtility::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 . '});';
        }
        $pageRenderer->addJsInlineCode($replaceElementIdString, $jsInlineCode);
        if (isset($conf['stdWrap.'])) {
            $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
        }
        return $content;
    }
Esempio n. 3
0
 /**
  * Rename Array keys with a given mapping table
  *
  * @param array	$array Array by reference which should be remapped
  * @param array	$mappingTable Array with remap information, array/$oldKey => $newKey)
  * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8  - use ArrayUtility::remapArrayKeys() instead
  */
 public static function remapArrayKeys(&$array, $mappingTable)
 {
     static::logDeprecatedFunction();
     ArrayUtility::remapArrayKeys($array, $mappingTable);
 }
Esempio n. 4
0
 /**
  * @test
  */
 public function remapArrayKeysExchangesKeysWithGivenMapping()
 {
     $array = array('one' => 'one', 'two' => 'two', 'three' => 'three');
     $keyMapping = array('one' => '1', 'two' => '2');
     $expected = array('1' => 'one', '2' => 'two', 'three' => 'three');
     ArrayUtility::remapArrayKeys($array, $keyMapping);
     $this->assertEquals($expected, $array);
 }
    /**
     * 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;
        }
        $type = isset($conf['type.']) ? $this->cObj->stdWrap($conf['type'], $conf['type.']) : $conf['type'];
        $typeConf = $conf[$type . '.'];
        /** @var $pageRenderer \TYPO3\CMS\Core\Page\PageRenderer */
        $pageRenderer = $GLOBALS['TSFE']->getPageRenderer();
        // Add SWFobject js-file
        $pageRenderer->addJsFile($this->getPathToLibrary('flashmedia/swfobject/swfobject.js'));
        $player = isset($typeConf['player.']) ? $this->cObj->stdWrap($typeConf['player'], $typeConf['player.']) : $typeConf['player'];
        if (strpos($player, 'EXT:') === 0) {
            $player = $prefix . $GLOBALS['TSFE']->tmpl->getFileName($player);
        }
        $installUrl = isset($conf['installUrl.']) ? $this->cObj->stdWrap($conf['installUrl'], $conf['installUrl.']) : $conf['installUrl'];
        if (!$installUrl) {
            $installUrl = $prefix . $this->getPathToLibrary('flashmedia/swfobject/expressInstall.swf');
        }
        // If file is audio and an explicit path has not been set,
        // take path from audio fallback property
        if ($type == 'audio' && empty($conf['file'])) {
            $conf['file'] = $conf['audioFallback'];
        }
        $filename = isset($conf['file.']) ? $this->cObj->stdWrap($conf['file'], $conf['file.']) : $conf['file'];
        $forcePlayer = isset($conf['forcePlayer.']) ? $this->cObj->stdWrap($conf['forcePlayer'], $conf['forcePlayer.']) : $conf['forcePlayer'];
        if ($filename && $forcePlayer) {
            if (strpos($filename, '://') !== FALSE) {
                $conf['flashvars.']['file'] = $filename;
            } else {
                if ($prefix) {
                    $conf['flashvars.']['file'] = $prefix . $filename;
                } else {
                    $conf['flashvars.']['file'] = str_repeat('../', substr_count($player, '/')) . $filename;
                }
            }
        } else {
            $player = $filename;
        }
        // Write calculated values in conf for the hook
        $conf['player'] = $player;
        $conf['installUrl'] = $installUrl;
        $conf['filename'] = $filename;
        $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) {
                \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($classRef, $conf, $this);
            }
        }
        if (is_array($conf['flashvars.']) && is_array($typeConf['mapping.']['flashvars.'])) {
            ArrayUtility::remapArrayKeys($conf['flashvars.'], $typeConf['mapping.']['flashvars.']);
        }
        $flashvars = 'var flashvars = ' . (!empty($conf['flashvars.']) ? json_encode($conf['flashvars.']) : '{}') . ';';
        if (is_array($conf['params.']) && is_array($typeConf['mapping.']['params.'])) {
            ArrayUtility::remapArrayKeys($conf['params.'], $typeConf['mapping.']['params.']);
        }
        $params = 'var params = ' . (!empty($conf['params.']) ? json_encode($conf['params.']) : '{}') . ';';
        if (is_array($conf['attributes.']) && is_array($typeConf['attributes.']['params.'])) {
            ArrayUtility::remapArrayKeys($conf['attributes.'], $typeConf['attributes.']['params.']);
        }
        $attributes = 'var attributes = ' . (!empty($conf['attributes.']) ? json_encode($conf['attributes.']) : '{}') . ';';
        $flashVersion = isset($conf['flashVersion.']) ? $this->cObj->stdWrap($conf['flashVersion'], $conf['flashVersion.']) : $conf['flashVersion'];
        if (!$flashVersion) {
            $flashVersion = '9';
        }
        $replaceElementIdString = str_replace('.', '', uniqid('mmswf', TRUE));
        $GLOBALS['TSFE']->register['MMSWFID'] = $replaceElementIdString;
        $alternativeContent = isset($conf['alternativeContent.']) ? $this->cObj->stdWrap($conf['alternativeContent'], $conf['alternativeContent.']) : $conf['alternativeContent'];
        $layout = isset($conf['layout.']) ? $this->cObj->stdWrap($conf['layout'], $conf['layout.']) : $conf['layout'];
        $content = str_replace('###ID###', $replaceElementIdString, $layout);
        $content = str_replace('###SWFOBJECT###', '<div id="' . $replaceElementIdString . '">' . $alternativeContent . '</div>', $content);
        $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'];
        }
        $embed = 'swfobject.embedSWF("' . $conf['player'] . '", "' . $replaceElementIdString . '", "' . $width . '", "' . $height . '",
				"' . $flashVersion . '", "' . $installUrl . '", ' . $conf['embedParams'] . ');';
        $script = $flashvars . $params . $attributes . $embed;
        $pageRenderer->addJsInlineCode($replaceElementIdString, $script);
        if (isset($conf['stdWrap.'])) {
            $content = $this->cObj->stdWrap($content, $conf['stdWrap.']);
        }
        return $content;
    }