Location: PHPKode > projects > Multimedia Files Scanner > getid3/getid3.lyrics3.php
<?php
/////////////////////////////////////////////////////////////////
/// getID3() by James Heinrich <hide@address.com>               //
//  available at http://getid3.sourceforge.net                ///
//            or http://www.getid3.org                        ///
/////////////////////////////////////////////////////////////////
//                                                             //
// getid3.lyrics3.php - part of getID3()                       //
// See getid3.readme.txt for more details                      //
//                                                             //
/////////////////////////////////////////////////////////////////

function getLyrics3Filepointer(&$fd, &$ThisFileInfo) {
	// http://www.volweb.cz/str/tags.htm

	fseek($fd, (0 - 128 - 9 - 6), SEEK_END); // end - ID3v1 - LYRICSEND - [Lyrics3size]
	$lyrics3_id3v1 = fread($fd, (128 + 9 + 6));
	$lyrics3lsz    = substr($lyrics3_id3v1,  0,   6); // Lyrics3size
	$lyrics3end    = substr($lyrics3_id3v1,  6,   9); // LYRICSEND or LYRICS200
	$id3v1tag      = substr($lyrics3_id3v1, 15, 128); // ID3v1

	if ($lyrics3end == 'LYRICSEND') {
		// Lyrics3 v1 and ID3v1

		$lyrics3size    = 5100;
		$lyrics3offset  = $ThisFileInfo['filesize'] - 128 - $lyrics3size;
		$lyrics3version = 1;

	} elseif ($lyrics3end == 'LYRICS200') {
		// Lyrics3 v2 and ID3v1

		// LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
		$lyrics3size    = $lyrics3lsz + 6 + strlen('LYRICS200');
		$lyrics3offset  = $ThisFileInfo['filesize'] - 128 - $lyrics3size;
		$lyrics3version = 2;

	} elseif (substr($lyrics3_id3v1, strlen($lyrics3_id3v1) - 1 - 9, 9) == 'LYRICSEND') {
		// Lyrics3 v1, no ID3v1 (I think according to Lyrics3 specs there MUST be ID3v1, but just in case :)

		$lyrics3size    = 5100;
		$lyrics3offset  = $ThisFileInfo['filesize'] - $lyrics3size;
		$lyrics3version = 1;
		$lyrics3offset  = $ThisFileInfo['filesize'] - $lyrics3size;

	} elseif (substr($lyrics3_id3v1, strlen($lyrics3_id3v1) - 1 - 9, 9) == 'LYRICS200') {
		// Lyrics3 v2, no ID3v1 (I think according to Lyrics3 specs there MUST be ID3v1, but just in case :)

		$lyrics3size    = $lyrics3lsz + 6 + strlen('LYRICS200'); // LSZ = lyrics + 'LYRICSBEGIN'; add 6-byte size field; add 'LYRICS200'
		$lyrics3offset  = $ThisFileInfo['filesize'] - $lyrics3size;
		$lyrics3version = 2;

	}

	if (isset($lyrics3offset)) {
		$ThisFileInfo['avdataend'] -= $lyrics3size;
		getLyrics3Data($ThisFileInfo, $fd, $lyrics3offset, $lyrics3version, $lyrics3size);
	}

	return true;
}

function getLyrics3Data(&$ThisFileInfo, &$fd, $endoffset, $version, $length) {
	// http://www.volweb.cz/str/tags.htm

	fseek($fd, $endoffset, SEEK_SET);
	$rawdata = fread($fd, $length);

	if (substr($rawdata, 0, 11) != 'LYRICSBEGIN') {
		if (strpos($rawdata, 'LYRICSBEGIN') !== false) {

			$ThisFileInfo['warning'] .= "\n".'"LYRICSBEGIN" expected at '.$endoffset.' but actually found at '.($endoffset + strpos($rawdata, 'LYRICSBEGIN')).' - this is invalid for Lyrics3 v'.$version;
			$rawdata = substr($rawdata, strpos($rawdata, 'LYRICSBEGIN'));
			$length = strlen($rawdata);

		} else {

			$ThisFileInfo['error'] .= "\n".'"LYRICSBEGIN" expected at '.$endoffset.' but found "'.substr($rawdata, 0, 11).'" instead';
			return false;

		}

	}

	switch ($version) {

		case 1:
			if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICSEND') {
				$ThisFileInfo['lyrics3']['raw']['lyrics3version'] = $version;
				$ThisFileInfo['lyrics3']['raw']['lyrics3tagsize'] = $length;
				$ThisFileInfo['lyrics3']['raw']['LYR'] = trim(substr($rawdata, 11, strlen($rawdata) - 11 - 9));
				Lyrics3LyricsTimestampParse($ThisFileInfo);
			} else {
				$ThisFileInfo['error'] .= "\n".'"LYRICSEND" expected at '.(ftell($fd) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
			}
			break;

		case 2:
			if (substr($rawdata, strlen($rawdata) - 9, 9) == 'LYRICS200') {
				$ThisFileInfo['lyrics3']['raw']['lyrics3version'] = $version;
				$ThisFileInfo['lyrics3']['raw']['lyrics3tagsize'] = $length;
				$ThisFileInfo['lyrics3']['raw']['unparsed'] = substr($rawdata, 11, strlen($rawdata) - 11 - 9 - 6); // LYRICSBEGIN + LYRICS200 + LSZ
				$rawdata = $ThisFileInfo['lyrics3']['raw']['unparsed'];
				while (strlen($rawdata) > 0) {
					$fieldname = substr($rawdata, 0, 3);
					$fieldsize = (int) substr($rawdata, 3, 5);
					$ThisFileInfo['lyrics3']['raw']["$fieldname"] = substr($rawdata, 8, $fieldsize);
					$rawdata = substr($rawdata, 3 + 5 + $fieldsize);
				}

				if (isset($ThisFileInfo['lyrics3']['raw']['IND'])) {
					$i = 0;
					$flagnames = array('lyrics', 'timestamps', 'inhibitrandom');
					foreach ($flagnames as $flagname) {
						if (strlen($ThisFileInfo['lyrics3']['raw']['IND']) > ++$i) {
							$ThisFileInfo['lyrics3']['flags']["$flagname"] = IntString2Bool(substr($ThisFileInfo['lyrics3']['raw']['IND'], $i, 1));
						}
					}
				}

				$fieldnametranslation = array('ETT'=>'title', 'EAR'=>'artist', 'EAL'=>'album', 'INF'=>'comment', 'AUT'=>'author');
				foreach ($fieldnametranslation as $key => $value) {
					if (isset($ThisFileInfo['lyrics3']['raw']["$key"])) {
						$ThisFileInfo['lyrics3']['comments']["$value"] = $ThisFileInfo['lyrics3']['raw']["$key"];
					}
				}
				if (!empty($ThisFileInfo['lyrics3']['comments'])) {
					CopyFormatCommentsToRootComments($ThisFileInfo['lyrics3']['comments'], $ThisFileInfo, true, false, false);
				}

				if (isset($ThisFileInfo['lyrics3']['raw']['IMG'])) {
					$imagestrings = explode("\r\n", $ThisFileInfo['lyrics3']['raw']['IMG']);
					foreach ($imagestrings as $key => $imagestring) {
						if (strpos($imagestring, '||') !== false) {
							$imagearray = explode('||', $imagestring);
							$ThisFileInfo['lyrics3']['images']["$key"]['filename']     = $imagearray[0];
							$ThisFileInfo['lyrics3']['images']["$key"]['description']  = $imagearray[1];
							$ThisFileInfo['lyrics3']['images']["$key"]['timestamp']    = Lyrics3Timestamp2Seconds($imagearray[2]);
						}
					}
				}
				if (isset($ThisFileInfo['lyrics3']['raw']['LYR'])) {
					Lyrics3LyricsTimestampParse($ThisFileInfo);
				}
			} else {
				$ThisFileInfo['error'] .= "\n".'"LYRICS200" expected at '.(ftell($fd) - 11 + $length - 9).' but found "'.substr($rawdata, strlen($rawdata) - 9, 9).'" instead';
			}
			break;

		default:
			$ThisFileInfo['error'] .= "\n".'Cannot process Lyrics3 version '.$version.' (only v1 and v2)';
			break;
	}

	if (isset($ThisFileInfo['lyrics3'])) {
		$ThisFileInfo['tags'][] = 'lyrics3';
	}
	return true;
}

function Lyrics3Timestamp2Seconds($rawtimestamp) {
	if (ereg('^\\[([0-9]{2}):([0-9]{2})\\]$', $rawtimestamp, $regs)) {
		return (int) (($regs[1] * 60) + $regs[2]);
	}
	return false;
}

function Lyrics3LyricsTimestampParse(&$ThisFileInfo) {
	$lyricsarray = explode("\r\n", $ThisFileInfo['lyrics3']['raw']['LYR']);
	foreach ($lyricsarray as $key => $lyricline) {
		$regs = array();
		unset($thislinetimestamps);
		while (ereg('^(\\[[0-9]{2}:[0-9]{2}\\])', $lyricline, $regs)) {
			$thislinetimestamps[] = Lyrics3Timestamp2Seconds($regs[0]);
			$lyricline = str_replace($regs[0], '', $lyricline);
		}
		$notimestamplyricsarray["$key"] = $lyricline;
		if (isset($thislinetimestamps) && is_array($thislinetimestamps)) {
			sort($thislinetimestamps);
			foreach ($thislinetimestamps as $timestampkey => $timestamp) {
				if (isset($ThisFileInfo['lyrics3']['synchedlyrics'][$timestamp])) {
					// timestamps only have a 1-second resolution, it's possible that multiple lines
					// could have the same timestamp, if so, append
					$ThisFileInfo['lyrics3']['synchedlyrics'][$timestamp] .= "\r\n".$lyricline;
				} else {
					$ThisFileInfo['lyrics3']['synchedlyrics'][$timestamp] = $lyricline;
				}
			}
		}
	}
	$ThisFileInfo['lyrics3']['unsynchedlyrics'] = implode("\r\n", $notimestamplyricsarray);
	if (isset($ThisFileInfo['lyrics3']['synchedlyrics']) && is_array($ThisFileInfo['lyrics3']['synchedlyrics'])) {
		ksort($ThisFileInfo['lyrics3']['synchedlyrics']);
	}
	return true;
}

?>
Return current item: Multimedia Files Scanner