<?php if (!defined('PmWiki')) exit ();

/* 
    
	Original info:
	copyright 2009, 2010, Adam Overton
	based on code by Jon Haupt, copyright 2007-8
	which was built on code from swf.php copyright 2004 Patrick R. Michaud
	and from quicktime.php copyright 2006 Sebastian Siedentopf.
	
	This file is distributed 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.  
	
	This module enables embedding of video and audio hosted on Archive.org.
	The simplest use of any of these includes:
		(:archive.org videocode:)

	For more info on how to use this, see http://www.pmwiki.org/wiki/Cookbook/Flash

	. . .
	
	Versions:
	* 2011-02-21 - fixed FLV playback - SimpleEmbed was trying to play flv's using the audio settings instead of video settings; also created globals $ArchiveOrgAudioTypes & $ArchiveOrgVideoTypes to help archive.org figure out which player to use.
	* 2010-12-19 - added ArchiveOrgSimpleEmbed - Archive.org vids can now be embedded by simply using the URL for the file you want to include (rather than the full embed code). to disable, set $ArchiveOrgSimpleEmbed=false in config.php
	* 2010-08-29: major overhaul of the recipe, making it work with the updated version of flowplayer being used on the archive.org site: [[~overtones99]]
		** fixed ROEPattern for new archive.org player
		** %red%**important**%% the @@$ArchiveOrgPlayerDefaultParams@@ array is now broken up into several subarrays: @@basicPropertiesVideo@@, @@basicPropertiesAudio@@, @@clipProperties@@, @@controlbarProperties@@, @@autohideProperties@@, and @@canvasProperties@@; if you want to add a default property in config.php, one must now indicate which branch it's nested in, i.e. $ArchiveOrgPlayerDefaultParams['clipProperties']['autoBuffering'] = 'true';
		** use the class [@.archiveorglink@] to style the archive.org link that appears when $linkToArchiveOrg is enabled; use $linkToArchiveOrg_text to set the text.
		** hexcheck has been disabled; just remember to precede your colors with a #
		** added basename= parameter; files can either be specified via (:archive.org [mybasename/file1, mybasename/file2] ... :), or via (:archive.org [file1, file2] basename=mybasename ... :)
	* 2010-01-02 - links in the context menu for the player don't currently work, so added $linkToArchiveOrg 
		** when $linkToArchiveOrg = true; a link to the archive.org/details page automatically added directly beneath the archive.org player - this affects all players on the site, and is not specified by a user.
		** when $linkToArchiveOrg = "ROE"; a pmwiki-markup link to the archive.org/details page will be added under the player during ReplaceOnEdit - this makes it optional for the user to potentially delete the link if they don't want it.
		** $linkToArchiveOrg = false; disables this feature, both in ROE and for default feature
	* 2009-12-21 - changed default fs='true'; changed msg above list of tracks; bug with 'gloss' parameter; list of available parameters; enabled mute, time, play, stop, volume, scrubber, autoHide, bottom, ... parameters; all hex-numbers now require a preceding # - can automatically check this by setting $hexcheck_enabled = true in config; changed bgColor and bgGradient to backgroundColor & backgroundGradient; suppress tracklist printout using $trackListing_enabled = false;
	* 2009-12-20 - initial release
	
*/

# Version date
$RecipeInfo['SWFSites-ArchiveOrgPlayer']['Version'] = '2011-02-21';

### ARCHIVE.ORG
SDV($ArchiveOrgSimpleEmbed, true);
SDV($flowplayerVersion, '3.2.1');
#SDV($hexcheck_enabled, false);
SDV($linkToArchiveOrg, true);  # true - always displays a link to archive.org below the player; false disables
SDV($linkToArchiveOrg_text, "download from Archive.org"); # style using .archiveorglink in CSS
SDV($ArchiveOrgVideoTypes, "(mp4|flv|jpg|mov|ogv)");
SDV($ArchiveOrgAudioTypes, "(mp3|ogg|wav|aif|aiff)");



SDVA($ArchiveOrgPlayerDefaultParams, array(
	'basicPropertiesVideo' => array(
		'width' => '640'
		,'height' => '506'
		,'scale' => '1'
		,'fs' => 'true'
		,'basename' => ''	# i.e. http://www.archive.org/basename/, or just 'basename'
	)
	,'basicPropertiesAudio' => array(
		'width' => '350'
		,'height' => '26'
		,'fs' => 'true'
		,'basename' => ''	# i.e. http://www.archive.org/basename/, or just 'basename'
	)
	,'clipProperties' => array(
		# CLIP PROPERTIES - http://static.flowplayer.org/documentation/configuration/clips.html
		'accelerated' => ''
		,'autoBuffering' => 'false'	# player begins automatically loading the file
		,'autoplay' => 'false'
		,'baseUrl' => ''			# different depending on whether it's audio or video - supplied by recipe
		,'bufferLength' => ''
		,'connectionProvider' => ''
		,'cuepointMultiplier' => ''
		,'cuepoints' => ''
		,'controls' => ''
		,'duration' => ''		# how long until playback ceases - (default: 0)
		,'extension' => ''
		,'fadeInSpeed' => ''		# fade-in, in milliseconds - (default: 1000)
		,'fadeOutSpeed' => ''	# fade-out, in milliseconds - (default: 1000)
		,'image' => ''
		,'linkUrl' => ''		# link to a url when user clicks on video window
		,'linkWindow' => ''	# window to open new url in (_self, _blank, _parent, _top)
		,'live' => ''
		,'metaData' => ''
		,'originalUrl' => ''
		,'position' => ''
		,'playlist' => ''
		,'provider' => ''			# different depending on whether it's audio or video - supplied by recipe
		,'scaling' => ''			# different depending on whether it's audio or video - supplied by recipe
		,'seekableOnBegin' => ''
		,'start' => ''		# start position, in seconds - (default: 0)
		,'url' => ''
		,'urlResolvers' => ''

	)
	,'controlbarProperties' => array(
		# CONTROLBAR PROPERTIES - http://flowplayer.org/plugins/flash/controlbar.html
		# empty values ('') from here on out will use the FlowPlayer defaults unless specified

		# MAIN OPTIONAL CONTROLS (not including playlist or fullscreen)
		'controls' => ''		# if 'null' or 'false', controls will not appear at all
		,'all' => ''		# show or hide all btns - true shows all, false, allows for enabling one-button-at-a-time
		,'time' => ''		# show or hide the time
		,'timeColor' => ''
		,'timeBgColor' => ''
		,'timeBgHeightRatio' => ''
		,'timeBorder' => ''
		,'timeBorderColor' => ''
		,'timeBorderWidth' => ''
		,'timeFontSize' => '9'
		,'timeSeparator' => ''
		,'durationColor' => ''
		,'play' => ''		# show or hide the play btn
		,'stop' => ''		# show or hide the stop btn
		,'mute' => 'false'		# show or hide the mute button
		,'playlist' => ''
		,'fastBackward' => ''
		,'fastForward' => ''
		,'slowBackward' => ''
		,'slowForward' => ''
		,'fullscreen' => ''
		,'volume' => ''		# show or hide the volume slider
		,'volumeColor' => ''
		,'volumeSliderColor' => ''
		,'volumeSliderGradient' => ''	# vals: none, low, medium or high; or an array: [0.2, 1.0]
		,'volumeSliderHeightRatio' => ''
		,'volumeBarHeightRatio' => ''
		,'volumeBorder' => ''
		,'volumeBorderWidth' => ''
		,'volumeBorderColor' => ''
		,'scrubber' => ''		# show or hide the time scrubber
		,'scrubberHeightRatio' => '0.6'
		,'scrubberBarHeightRatio' => ''
		,'progressColor' => ''
		,'progressGradient' => ''	# vals: none, low, medium or high; or an array: [0.2, 1.0]
		,'bufferColor' => ''	# a hex value: i.e. #777777
		,'bufferGradient' => ''	# vals: none, low, medium or high; or an array: [0.2, 1.0]
		,'sliderColor' => ''
		,'sliderGradient' => ''	# vals: none, low, medium or high; or an array: [0.2, 1.0]
		,'sliderBorder' => ''
		,'sliderBorderWidth' => ''
		,'sliderBorderColor' => ''
		,'buttonColor' => ''
		,'buttonOverColor' => ''
		# AUTO HIDE CONTROLS
		,'autoHide' => ''		# values: 'always', 'never', 'fullscreen', false -- see below for more values
		# POSITION CONTROLS
		,'bottom' => ''	# bottom position of the player controls, measured in pixels from the bottom
		,'top' => ''		# top position of the player controls, measured in pixels from the top
		,'ctrlHeight' => '26'	# height of controls
		,'ctrlWidth' => ''		# width of controls
		# AESTHETICS
		,'opacity' => ''		# opacity of controls (decimal value between 0-1)
		,'borderRadius' => ''		# rounding of the controller's edges (default is no rounding)
		,'gloss' => ''
		,'backgroundColor' => '#000000'
		,'backgroundGradient' => ''  # more info: http://flowplayer.org/documentation/configuration/plugins.html#styling-properties
	)
	,'autohideProperties' => array(
		# AUTOHIDE PROPERTIES - part of controlbar properties - http://flowplayer.org/plugins/flash/controlbar.html	
		'enabled' => ''
		,'fullscreenOnly' => 'true'
		,'hideDelay' => ''
		,'hideDuration' => ''
		,'hideStyle' => ''
		,'mouseOutDelay' => ''	
	)
	,'canvasProperties' => array(
		# CANVAS PROPERTIES - part of controlbar properties - http://flowplayer.org/documentation/configuration/plugins.html#display-properties
		'background' => ''	# shorthand for setting all canvas properties as once, i.e.: 
			# format: backgroundImage backgroundRepeat left top.
			# example: url(/my/image.jpg) no-repeat 100 30.
		,'backgroundColor' => '#000000'
		,'backgroundGradient' => 'none'
		,'backgroundImage' => ''	# i.e  'url(/img/demos/helloworld.jpg)'
		,'backgroundRepeat' => ''
		,'border' => ''
		,'borderRadius' => ''
		,'display' => ''
	)
));



#####################
# EMBED (:ARCHIVE.ORG:)
### (:archive.org videocode params:)
Markup('archive.org', '<img', "/\\(:archive\.org\\s+([^\\s]+)\\s*(.*):\\)/e", "ShowArchiveOrgPlayer('$1','$2')");


# SIMPLE EMBED: ARCHIVE.ORG
## embed archive.org by simply pasting the url of the file you want to embed, i.e.: http://www.archive.org/download/Beating.blinkingForBassDrumsAndBreaths/bbbassdrums-interchange2-2004-06-11_512kb.mp4
## unfortunately you cannot just paste the main url for the page, since most archive.org pages have several files to choose from in different formats to embed...
## automatically embeds using the default parameters
## set ____ to true if you want to convert to PmWiki youtube markup

if($ArchiveOrgSimpleEmbed) {
	$ArchiveOrgSimplePattern = '/(`?)(http:\\/\\/(www\\.)?archive\\.org\\/download\\/([^\\s]+))/e';
	$ArchiveOrgSimpleFunc = "'$4','',array('$1','$2')";
	Markup('ArchiveOrgSIMPLE', '<img', $ArchiveOrgSimplePattern, "ShowArchiveOrgPlayer($ArchiveOrgSimpleFunc)");
		
}
######################




#########

# ROEPatterns - ARCHIVE.ORG EMBED CONVERSION
# Converts pasted ArchiveOrgPlayer embed code into valid pmwiki (:archive.org:) code
SDV($ArchiveOrgPlayerROEenabled, true);
if ($ArchiveOrgPlayerROEenabled) {
	$ROEPatterns['!<object.*archive\.org/flow/flowplayer.*</object>!ie'] = "ArchiveOrgPlayerROE(PSS('$0'))";
	SDV($trackListing_enabled, true);
	function ArchiveOrgPlayerROE($videocode) {
		global $ArchiveOrgPlayerDefaultParams, $trackListing_enabled;

		# get basename
		preg_match("#'baseUrl':'http://www.archive.org/download/([^/]+)/'#", $videocode, $basename);
		$basename = $basename[1];

		# get filename(s)
		$files = preg_match("#'playlist':\[([^\]]+)\]#", $videocode, $matches);
		$files = str_replace(array("'",'{','}','url:'),'',$matches[1]);
		$filenamesArray = explode(",",$files);
		
		foreach($filenamesArray as $item) {
			if (!preg_match('#(format=|:)#',$item)) {
				$filenamesArrayReduced[] .= $item;
			}
		}
		$count = count($filenamesArrayReduced);
		
		if ($count==0) { return $videocode; }
		elseif ($count==1) {
			# return only 1 filename, no brackets
			$filenames = "$basename/".$filenamesArrayReduced[0];
		} elseif ($count>1) {
			$playlist = true;
			# return list of [filenames]  (in brackets separated by commas)
			$filenames = "[".implode(",",$filenamesArrayReduced)."]";
			$filenames .= " basename=$basename";	# append basename=basename for playlists
			## NOTE: The playlist function works, however, the list of tracks won't show up in this version - flowplayer has to be implemented slightly differently. The tracks, however, can be reached individually via the << and >> buttons.
			## For now, the track listing is spit out automatically in the ROEPattern in case it's helpful, and in order to make it clear that indeed it's a playlist
			foreach($filenamesArrayReduced as $key => $val) {
				$trackListing .= "# %newwin%[[http://www.archive.org/download/$basename/$val | $val]]\n";
			}
		}

		# type: audio or video?
		$typeZ = mediaType($filenamesArrayReduced[0]);
		$type = $typeZ[1]; $ext = $typeZ[0];

		preg_match('#width="\d+" height="\d+"#',$videocode,$matches);
		$dimensions = str_replace('"','',$matches[0]);
		#echo $dimensions; break;

		# output -- pop in filenames & parameters
		if($type=="video") $out = "(:archive.org $filenames $dimensions scale=".$ArchiveOrgPlayerDefaultParams['basicPropertiesVideo']['scale'].":)";
		else $out = "(:archive.org $filenames $dimensions:)";	# no scale for audio		
				
		# output -- adds tracklisting
		if ($trackListing && $trackListing_enabled && $playlist) {
			# spit out track listing if there are tracks
			$out .= "\n\nuse the << and >> buttons to navigate the playlist. here's a list of the tracks included in this playlist:\n$trackListing";
		}
		return $out;
	}
}


#######

function ShowArchiveOrgPlayer($id, $args, $escape='') {
	global $ArchiveOrgPlayerDefaultParams, $hexcheck_enabled, $linkToArchiveOrg, $linkToArchiveOrg_text, $flowplayerVersion;	

	# escape SIMPLE EMBED if url is preceded by a `, ex.: `http://...
	if($escape[0]=="`") return $escape[1];
	
	# get args
	$args = ParseArgs($args);

	# determine type: video or audio
	list($ext, $type) = mediaType($id);
	
	# remove unnecessary video or audio properties from the defaultParamsArray
	# must do _local version of DefaultParams, or else flowplayers on the same page will mistakenly share params...
	if($type=="video") {
		$basicPropertiesKey = 'basicPropertiesVideo';
		# if video, remove 'basicPropertiesAudio' from the defaultParams array
		$ArchiveOrgPlayerDefaultParams_local = array_diff_key($ArchiveOrgPlayerDefaultParams, array('basicPropertiesAudio'=>''));
	} else {
		$basicPropertiesKey = 'basicPropertiesAudio';
		# if video, remove 'basicPropertiesAudio' from the defaultParams array
		$ArchiveOrgPlayerDefaultParams_local = array_diff_key($ArchiveOrgPlayerDefaultParams, array('basicPropertiesVideo'=>''));
	}

	# compare user-args with default-args of each array - update default-args if given
	foreach($ArchiveOrgPlayerDefaultParams_local as $defaultArrayKey => &$defaultArrayN) {
		# intersect - lists keys in arg1 that are present in arg2
		$keysToUpdate = array_intersect_key($args, $defaultArrayN);
		#echo "<br />";
		# update these keys
		if($keysToUpdate) $defaultArrayN = array_merge($defaultArrayN, $keysToUpdate);
	}

	# organize default properties - quick vars
	$ArchiveOrg_BasicProperties = $ArchiveOrgPlayerDefaultParams_local[$basicPropertiesKey];
	$ArchiveOrg_ControlBarProperties = $ArchiveOrgPlayerDefaultParams_local['controlbarProperties'];
	$ArchiveOrg_AutoHideProperties = $ArchiveOrgPlayerDefaultParams_local['autohideProperties'];
	$ArchiveOrg_ClipProperties = $ArchiveOrgPlayerDefaultParams_local['clipProperties'];
	$ArchiveOrg_CanvasProperties = $ArchiveOrgPlayerDefaultParams_local['canvasProperties'];
	
	# is it a playlist? for a playlist, the $id looks like '[file1, file2, ...]' rather than 'file'
	if (strpos($id,"[")===0) {
		# playlist present: [$id]
		$playlist_enabled = true;
		$playlist_array = explode(",",str_replace(array("[","]"),'',$id));
	}

	# get basename ... and filename (if it's a single file)
	if($playlist_enabled) 
		# look at the first file in a playlist to determine the basename
		preg_match("#^(http://(www\.)?archive\.org/download/)?(.*)$#", $playlist_array[0], $matches);
	else
		preg_match("#^(http://(www\.)?archive\.org/download/)?(.*)$#", $id, $matches);
	$idClean = $matches[3];
	#echo $idClean; break;
	if(strpos($idClean, "/")) 
		# if basename is provided via the first file in the form 'baseName/filename', then...
		list($idBaseName,$idFileName) = explode("/",$idClean);
	else {
		# if not provided in the first filename, then use the 'baseName' parameter
		$idBaseName = $ArchiveOrg_BasicProperties['basename'];
		$idFileName = $idClean; # not really necessary
		# error
		if (!$idBaseName) return Keep("Archive.org: Sorry - you need to provide a basename via a) basename=<i>mybasename</i>, or b) <i>basename</i>/filename");
	}

	# define width & height
	## one can supply a 'scale' default different than '1', but it's not suggested, as it could be confusing to users
	$width = $ArchiveOrg_BasicProperties['width'];
	$height = $ArchiveOrg_BasicProperties['height'];

	if(!$width) {
		if($type=="video") $width = $ArchiveOrgPlayerDefaultParams_local['defaultVideoWidth'];
		else  $width = $ArchiveOrgPlayerDefaultParams_local['defaultAudioWidth'];
	}
	if(!$height) {
		if($type=="video") $height = $ArchiveOrgPlayerDefaultParams_local['defaultVideoHeight'];
		else  $height = $ArchiveOrgPlayerDefaultParams_local['defaultAudioHeight'];
	}

	# apply scaling to video (but not to audio)
	if($type=="video") {
		$scale = $ArchiveOrg_BasicProperties['scale'];
		$width *= $scale;
		$height *= $scale;
	}
	
	$autoplay = $ArchiveOrg_ClipProperties['autoplay'];
	if($autoplay=="1") $autoplay = "true";
	elseif($autoplay=="0") $autoplay = "false";

	if ($type=="audio") $fullscreen = "false"; # don't allow fullscreen for audio
	elseif ($type=="video") {
		$fullscreen = $ArchiveOrg_BasicProperties['fs'];
		if($fullscreen=="1") $fullscreen = "true";
		elseif($fullscreen=="0") $fullscreen = "false";
	}
	
	# format playlist
	## NOTE: The playlist function works, however, the list of tracks won't show up in this version - flowplayer has to be implemented slightly differently. The tracks, however, can be reached individually via the << and >> buttons.
	## For now, the track listing is spit out automatically in the ROEPattern in case it's helpful...
	$playlistAudioFmt = "{'url':'FILENAME','autoPlay':true}";
	#$playlistVideoFmt = "{'url':'FILENAME','autoPlay':true,'accelerated':true,'scaling':'fit','provider':'h264streaming'}";
	$playlistVideoFmt = "{'url':'FILENAME','autoPlay':true}";
	if ($type=="audio") $playlistFmt = $playlistAudioFmt;
	else $playlistFmt = $playlistVideoFmt;
	if ($playlist_enabled) {
		# create playlist
		foreach($playlist_array as $key => $fn) {
			# remove basename/ from $fn
			if(strpos($fn,"/")) $fn = preg_replace('#^[^/]+/#','',$fn);
			#echo "$fn<br />";
			if ($key>0) $playlist .= ",'$fn'";
			# 1st should have autoplay set to the current autoplay setting, and have no comma at the front
			else {
				$thisExt = mediaType($fn); $thisExt = $thisExt[0];
				if ($thisExt=="jpg") { # for jpg, autoplay should always be true (so leave it alone)
					$playlist .= str_replace("FILENAME",$fn,$playlistFmt);
				} else { # videofiles get default autoplay, (except the 1st one after a jpg)
					$playlist .= str_replace(array("FILENAME","'autoPlay':true"),array($fn,"'autoPlay':$autoplay"),$playlistFmt);
				}
			}
		}
	# NO PLAYLIST - SINGLE FILE
	} else {
		$playlist = str_replace(array("FILENAME","'autoPlay':true"),array($idFileName,"'autoPlay':$autoplay"),$playlistFmt);
	}

	# PLAYLIST THUMBNAIL -- add a thumbnail to the front of a video playlist
	if($type=="video") $playlist = "'format=Thumbnail?.jpg',$playlist";
	

/*	# Hex-Number Check - previous version of this recipe didn't prepend color values with a '#' - this will check for the # and prepend it if missing
	if($hexcheck_enabled) {
		foreach($args as $key => &$val) {
			//echo $key." - ".$val; # prelim values
			# only check keys with Color in the name
			if(strpos($key,"Color")) {
				if(strlen($val)>0 && strpos($val,"#")!==0)
					$val = '#'.$val;
			}
			//echo " - fixed: $val."<br />"; # subsequent values
		}
	}
*/


	#### Output
	# <OBJECT>
	$out = "<object ";
	$dimensions = 'width="'.$width.'" height="'.$height.'"';
	$out .= $dimensions;
	$out .= " classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\">\n";
	$out .= "<param value='true' name='allowfullscreen'/>\n";
	$out .= "<param value='always' name='allowscriptaccess'/>\n";
	$out .= "<param value='high' name='quality'/>\n";
	$out .= "<param value='true' name='cachebusting'/>\n";
	$out .= "<param value='#000000' name='bgcolor'/>\n";
	$out .= "<param name='movie' value='http://www.archive.org/flow/flowplayer.commercial-$flowplayerVersion.swf' />\n";

	# last <PARAM> - this is NOT the same as the <embed> section below - it has mostly the same, but slightly different values
	$out .= "<param value=\"config={";
		$key = "'key':'#\$aa4baff94a9bdcafce8',";
		$out .= $key;

		# <PARAM>  PLAYLIST
		$playlistParam .= "\n   'playlist':[$playlist],";
		$out .= $playlistParam;

		# <PARAM> CLIPS: for more info - http://static.flowplayer.org/documentation/configuration/clips.html
		## haven't included all of them...
		$clip = "\n   'clip':{";
			# REQUIRED CLIP PROPERTIES
			$ArchiveOrg_ClipProperties['baseUrl'] = "http://www.archive.org/download/$idBaseName/";
			if ($type=="video") { # only video receives these two params
				$ArchiveOrg_ClipProperties['scaling'] = 'fit';
				$ArchiveOrg_ClipProperties['provider'] = 'h264streaming';
			}
				
			# OPTIONAL CLIP PROPERTIES
			# see: http://static.flowplayer.org/documentation/configuration/clips.html
			# compare $ArchiveOrg_ClipProperties to user's args - only use ones included by user or listed with default
			$i=0;
			if(count($ArchiveOrg_ClipProperties)) { # don't execute unless there are actually some properties to add
				foreach($ArchiveOrg_ClipProperties as $item => $val) {
					#echo "$item - $val<br />";
					# all items should have a leading comma, except the first
					if (strlen($val)>0) {
						if($i>0) $clip .= ",";
						$clip .= "'$item':";
						# booleans and numbers should be without apostrophes
						if(preg_match('#^(\d+|\d+\.\d+)$#',$val) || $val==="true" || $val==="false" || $val==="null") {
							#echo "$item - ".$val."<br />";
							# boolean = clean
							$clip .= $val;
						} else {
							#echo "$item - ".$args[$item]."<br />";
							# non-boolean = 'wrapped'
							$clip .= "'".$val."'";
						}
						$i++;
					}
				}
			}
		$clip .= "},";
		$out .= $clip;
		

		# <PARAM> CANVAS
		$i=0;
		if(count($ArchiveOrg_CanvasProperties)) { # don't execute unless there are actually some properties to add
			foreach($ArchiveOrg_CanvasProperties as $item => $val) {
				# all items should have a leading comma, except the first
				if (strlen($val)>0) {
					if($i>0) $canvas .= ",";
					$canvas .= "'$item':";
					# booleans and numbers should be without apostrophes
					if(preg_match('#^(\d+|\d+\.\d+)$#',$val) || $val==="true" || $val==="false" || $val==="null") {
						# boolean = clean
						$canvas .= $val;
					} else {
						# non-boolean = 'wrapped'
						$canvas .= "'".$val."'";
					}
					$i++;
				}
			}
		}
		$canvas = "\n   'canvas':{".$canvas."},";
		$out .= $canvas;


		# <PARAM> PLUGINS
		$out .= "\n   'plugins':{";
		
			# <PARAM> CONTROLS (CONTROLBAR)
			# enable Controlbar
			## more info: http://flowplayer.org/plugins/flash/controlbar.html
			if($args['controls']=='null' || $args['controls']=='false') 
				$controls .= "\n   'controls':null"; 
			else { 
				$controls .= "\n   'controls':{";
				# REQUIRED CONTROLBAR PROPERTIES
				## args not provided will end up using the FlowPlayer defaults
				## note that some values require "quotes", but true/false/null items must be left without quotes
				if ($playlist_enabled) $controls .= "'playlist':true";  # first argument - no comma preceding
					else $controls .= "'playlist':false";
				if ($type=="audio") {
					# AUDIO CONTROLBAR STUFF
					$ArchiveOrg_ControlBarProperties['fullscreen'] = 'false';
					if(strlen($ArchiveOrg_ControlBarProperties['top'])==0) $ArchiveOrg_ControlBarProperties['top'] = '0';
				} else {
					# VIDEO CONTROLBAR STUFF
					$ArchiveOrg_ControlBarProperties['fullscreen'] = $fullscreen;
				}
				
				
				# AUTOHIDE PROPERTIES -- these should be included in the controlbar properties below
				# see: http://static.flowplayer.org/documentation/configuration/clips.html
				$i=0;
				if($ArchiveOrg_ControlBarProperties['autoHide'] != 'false' && count($ArchiveOrg_AutoHideProperties)) { # don't execute unless there are actually some properties to add
					foreach($ArchiveOrg_AutoHideProperties as $item => $val) {
						# all items should have a leading comma, except the first
						if (strlen($val)>0) {
							if($i>0) $autoHide .= ",";
							$autoHide .= "'$item':";
							# booleans and numbers should be without apostrophes
							if(preg_match('#^(\d+|\d+\.\d+)$#',$val) || $val==="true" || $val==="false" || $val==="null") {
								# boolean = clean
								$autoHide .= $val;
							} else {
								# non-boolean = 'wrapped'
								$autoHide .= "'".$val."'";
							}
							$i++;
						}
					}
				}
				if($autoHide) $autoHide = ",'autoHide':{".$autoHide."}";
				# autoHide should be placed inside the controlbar properties bracket below
				
				
				# OPTIONAL CONTROLBAR PROPERTIES
				# compare $ArchiveOrgPlayerDefaultParams_local['controlbarProperties'] to user's args - only use ones included by user or listed with default
				if(count($ArchiveOrg_ControlBarProperties)) { # don't execute unless there are actually some properties to add
					foreach($ArchiveOrg_ControlBarProperties as $item => $val) {
						# all items should have a leading comma, even the first
						switch($item) {
							# height & width must be differentiated by calling ctrlHeight & ctrlWidth
							case ($item=='ctrlHeight' || $item=='ctrlHeight'):
								if($item=="ctrlHeight")
									if (strlen($val)>0) $controls .= ",'height':".$val;
								elseif($item=="ctrlWidth")
									if (strlen($val)>0) $controls .= ",'width':".$val;
								break;
								
							default:  # most controls will receive this treatment
								# booleans and numbers should be without apostrophes
								if (strlen($val)>0) {
									if(preg_match('#^(\d+|\d+\.\d+)$#',$val) || $val==="true" || $val==="false" || $val==="null")
										$controls .= ",'$item':".$val; # no apostrophes for numbers
										else
										$controls .= ",'$item':'".$val."'";  # with apostrophes
								}
								break;
						}
					}
				}
				# add autoHide before closing controlbar bracket
				$controls .= $autoHide;
				$controls .= '},';
			}
			$out .= $controls;
			
			# <PARAM> AUDIO OR H264
			if ($type=="video") {
				# VIDEO
				$av = "'h264streaming':{'url':'http://www.archive.org/flow/flowplayer.pseudostreaming-$flowplayerVersion.swf'}";
			} else { 
				# AUDIO
				$av = "'audio':{'url':'http://www.archive.org/flow/flowplayer.audio-$flowplayerVersion-dev.swf'}";
			}
			$out .= $av;
			
			
			# experiment - share button
			#$viral = "\n   ,'viral':{'url':'flowplayer.viralvideos-3.0.0.swf','share':{'description':'Boys and girls in the playground'}";
			#$viral = "\n   ,'viral':{'url':'http://releases.flowplayer.org/flowplayer.viralvideos/flowplayer.viralvideos-3.2.2.swf','share':{'description':'test msg'}";
			#$out .= $viral;
			
		$out .= "},";	# end of PLUGINS
			# <PARAM> CONTEXTMENU
			$contextMenu .= "'contextMenu':[{},'-','Flowplayer v$flowplayerVersion']}";
			$out .= $contextMenu;
	$out .= '" name="flashvars"/>';



	# <EMBED> BLOCK
	$out .= '<embed src="http://www.archive.org/flow/flowplayer.commercial-'.$flowplayerVersion.'.swf" type="application/x-shockwave-flash" '.$dimensions.' allowfullscreen="true" allowscriptaccess="always" cachebusting="true" bgcolor="#000000" quality="high" flashvars="config={';
	$out .= $key;
	# <EMBED> PLAYLIST
	$out .= $playlistParam;
	#"'playlist':['format=Thumbnail?.jpg',{'autoPlay':false,'url':'forpianos4.12.05.ipw_forVimeo_4000kb_1080x720_512kb.mp4'}],'
	# <EMBED> CLIPS
	$out .= $clip;
	# <EMBED> CANVAS
	$out .= $canvas;
	# <EMBED> PLUGINS
	$out .= "\n   'plugins':{";
	# <EMBED> CONTROLS
	$out .= $controls;
	# <EMBED> H264 OR AUDIO
	$out .= $av;
	# <EMBED> VIRAL - experimental
	#$out .= $viral;
	# <EMBED> END PLUGINS
	$out .= "},";
	# <EMBED> CONTEXTMENU
	$out .= $contextMenu;
	$out .= '">';

	$out .= "\n</embed></object>";


	# LINK TO ARCHIVE.ORG PAGE AND FILES
	if ($linkToArchiveOrg===true || $linkToArchiveOrg==="true") {
		$out .= '<br /><span style=\'font-size:83%\'><a href="http://www.archive.org/details/'.$idBaseName.'" class="urllink archiveorglink" target="_blank">'.$linkToArchiveOrg_text.'</a></span>';
	}

      return Keep($out);
}



function mediaType($filename) {
	global $ArchiveOrgVideoTypes, $ArchiveOrgAudioTypes;
	# determine type: video or audio
	$ext = end(explode(".",str_replace(array("[","]"),'',$filename)));
	if (preg_match("#$ArchiveOrgAudioTypes#",$ext)) $type = "audio";
	# include jpg as a video b/c archive.org often uses .jpg still as a the first item in a playlist
	elseif (preg_match("#$ArchiveOrgVideoTypes#",$ext)) $type = "video";	
	return array($ext, $type);
}