From 809bf588854eed84fec4f5b1d99632d9bad304ed Mon Sep 17 00:00:00 2001 From: svollbehr Date: Wed, 30 Jul 2008 14:56:47 +0000 Subject: [PATCH] Fix bugs and apply new code as described in issue 11 git-svn-id: http://php-reader.googlecode.com/svn/trunk@105 51a70ab9-7547-0410-9469-37e369ee0574 --- src/ID3/Encoding.php | 4 +- src/ID3/ExtendedHeader.php | 6 +- src/ID3/Frame/AENC.php | 13 +- src/ID3/Frame/APIC.php | 55 ++++-- src/ID3/Frame/AbstractLink.php | 3 +- src/ID3/Frame/AbstractText.php | 22 ++- src/ID3/Frame/COMM.php | 45 +++-- src/ID3/Frame/COMR.php | 65 +++--- src/ID3/Frame/ENCR.php | 7 +- src/ID3/Frame/EQU2.php | 28 +-- src/ID3/Frame/EQUA.php | 26 ++- src/ID3/Frame/ETCO.php | 19 +- src/ID3/Frame/GEOB.php | 41 ++-- src/ID3/Frame/GRID.php | 11 +- src/ID3/Frame/IPLS.php | 58 +++--- src/ID3/Frame/LINK.php | 3 +- src/ID3/Frame/OWNE.php | 15 +- src/ID3/Frame/PCNT.php | 7 +- src/ID3/Frame/POPM.php | 49 ++--- src/ID3/Frame/POSS.php | 13 +- src/ID3/Frame/PRIV.php | 10 +- src/ID3/Frame/RBUF.php | 38 ++-- src/ID3/Frame/RVA2.php | 92 +++++---- src/ID3/Frame/RVAD.php | 172 ++++++++++------ src/ID3/Frame/RVRB.php | 41 ++-- src/ID3/Frame/SIGN.php | 5 +- src/ID3/Frame/SYLT.php | 117 +++++++---- src/ID3/Frame/SYTC.php | 54 +++-- src/ID3/Frame/TXXX.php | 30 +-- src/ID3/Frame/USER.php | 35 ++-- src/ID3/Frame/USLT.php | 46 +++-- src/ID3/Frame/WXXX.php | 25 +-- src/ID3/Object.php | 54 ++++- src/Transform.php | 348 ++++++++++++++++++++++++--------- 34 files changed, 1002 insertions(+), 555 deletions(-) diff --git a/src/ID3/Encoding.php b/src/ID3/Encoding.php index ad512b4..06fa1ae 100644 --- a/src/ID3/Encoding.php +++ b/src/ID3/Encoding.php @@ -54,8 +54,8 @@ interface ID3_Encoding /** The UTF-16 Unicode encoding with BOM. */ const UTF16 = 1; - /** The UTF-16 Unicode encoding with BOM. */ - const UTF16LE = 1; + /** The UTF-16LE Unicode encoding without BOM. */ + const UTF16LE = 4; /** The UTF-16BE Unicode encoding without BOM. */ const UTF16BE = 2; diff --git a/src/ID3/ExtendedHeader.php b/src/ID3/ExtendedHeader.php index dc54a42..d1e1d73 100644 --- a/src/ID3/ExtendedHeader.php +++ b/src/ID3/ExtendedHeader.php @@ -47,6 +47,7 @@ require_once("ID3/Object.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -114,7 +115,7 @@ final class ID3_ExtendedHeader extends ID3_Object return; $offset = $this->_reader->getOffset(); - $this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE()); + $this->_size = $this->_reader->readUInt32BE(); /* ID3v2.3.0 ExtendedHeader */ if ($this->getOption("version", 4) < 4) { @@ -127,6 +128,7 @@ final class ID3_ExtendedHeader extends ID3_Object /* ID3v2.4.0 ExtendedHeader */ else { + $this->_size = $this->decodeSynchsafe32($this->_size); $this->_reader->skip(1); $this->_flags = $this->_reader->readInt8(); if ($this->hasFlag(self::UPDATE)) @@ -313,7 +315,7 @@ final class ID3_ExtendedHeader extends ID3_Object ($this->hasFlag(self::UPDATE) ? "\0" : "") . ($this->hasFlag(self::CRC32) ? Transform::toInt8(5) . Transform::toInt8($this->_crc & 0xf0000000 >> 28 & 0xf /*eq >>> 28*/) . - Transform::toUInt32BE(encodeSynchsafe32($this->_crc)) : "") . + Transform::toUInt32BE($this->encodeSynchsafe32($this->_crc)) : "") . ($this->hasFlag(self::RESTRICTED) ? Transform::toInt8(1) . Transform::toInt8($this->_restrictions) : ""); } diff --git a/src/ID3/Frame/AENC.php b/src/ID3/Frame/AENC.php index 8e9b7af..2364338 100644 --- a/src/ID3/Frame/AENC.php +++ b/src/ID3/Frame/AENC.php @@ -53,6 +53,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -83,10 +84,10 @@ final class ID3_Frame_AENC extends ID3_Frame if ($reader === null) return; - - list($this->_owner, $this->_data) = preg_split("/\\x00/", $this->_data, 2); - $this->_previewStart = substr($this->_data, 0, 2); - $this->_previewLength = substr($this->_data, 2, 2); + + list($this->_owner, $this->_data) = $this->explodeString8($this->_data, 2); + $this->_previewStart = Transform::fromUInt16BE(substr($this->_data, 0, 2)); + $this->_previewLength = Transform::fromUInt16BE(substr($this->_data, 2, 2)); $this->_encryptionInfo = substr($this->_data, 4); } @@ -163,8 +164,8 @@ final class ID3_Frame_AENC extends ID3_Frame public function __toString() { $this->setData - ($this->_owner . "\0" . Transform::toInt16BE($this->_previewStart) . - Transform::toInt16BE($this->_previewLength) . $this->_encryptionInfo); + ($this->_owner . "\0" . Transform::toUInt16BE($this->_previewStart) . + Transform::toUInt16BE($this->_previewLength) . $this->_encryptionInfo); return parent::__toString(); } } diff --git a/src/ID3/Frame/APIC.php b/src/ID3/Frame/APIC.php index 4b01912..f28b476 100644 --- a/src/ID3/Frame/APIC.php +++ b/src/ID3/Frame/APIC.php @@ -56,6 +56,7 @@ require_once("ID3/Encoding.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -93,6 +94,9 @@ final class ID3_Frame_APIC extends ID3_Frame /** @var string */ private $_imageData; + /** @var integer */ + private $_imageSize = 0; + /** * Constructs the class with given parameters and parses object related data. * @@ -106,27 +110,29 @@ final class ID3_Frame_APIC extends ID3_Frame if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); $this->_mimeType = substr ($this->_data, 1, ($pos = strpos($this->_data, "\0", 1)) - 1); - $this->_imageType = Transform::fromInt8($this->_data[$pos++]); - $this->_data = substr($this->_data, $pos); + $this->_imageType = Transform::fromUInt8($this->_data[++$pos]); + $this->_data = substr($this->_data, $pos + 1); switch ($this->_encoding) { case self::UTF16: - list ($this->_description, $this->_data) = - preg_split("/\\x00\\x00/", $this->_data, 2); + list ($this->_description, $this->_imageData) = + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16($this->_description); break; case self::UTF16BE: - list ($this->_description, $this->_data) = - preg_split("/\\x00\\x00/", $this->_data, 2); + list ($this->_description, $this->_imageData) = + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16BE($this->_description); break; default: - list ($this->_description, $this->_data) = - preg_split("/\\x00/", $this->_data, 2); + list ($this->_description, $this->_imageData) = + $this->explodeString8($this->_data, 2); } + + $this->_imageSize = strlen($this->_imageData); } /** @@ -197,14 +203,26 @@ final class ID3_Frame_APIC extends ID3_Frame * * @return string */ - public function getData() { return $this->_imageData; } + public function getImageData() { return $this->_imageData; } /** - * Sets the embedded image data. + * Sets the embedded image data. Also updates the image size field to + * correspond the new data. * * @param string $imageData The image data. */ - public function setData($imageData) { $this->_imageData = $imageData; } + public function setImageData($imageData) + { + $this->_imageData = $imageData; + $this->_imageSize = strlen($imageData); + } + + /** + * Returns the size of the embedded image data. + * + * @return integer + */ + public function getImageSize() { return $this->_imageSize; } /** * Returns the frame raw data. @@ -213,18 +231,19 @@ final class ID3_Frame_APIC extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding) . $this->_mimeType . "\0" . - Transform::toInt8($this->_imageType); + $data = Transform::toUInt8($this->_encoding) . $this->_mimeType . "\0" . + Transform::toUInt8($this->_imageType); switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_description) . "\0\0"; + case self::UTF16LE: + $data .= Transform::toString16 + ($this->_description, $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER) . + "\0\0"; break; case self::UTF16BE: $data .= Transform::toString16BE($this->_description) . "\0\0"; break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_description) . "\0\0"; - break; default: $data .= $this->_description . "\0"; } diff --git a/src/ID3/Frame/AbstractLink.php b/src/ID3/Frame/AbstractLink.php index c8f8b93..2596357 100644 --- a/src/ID3/Frame/AbstractLink.php +++ b/src/ID3/Frame/AbstractLink.php @@ -45,6 +45,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -65,7 +66,7 @@ abstract class ID3_Frame_AbstractLink extends ID3_Frame parent::__construct($reader, $options); if ($reader !== null) - $this->_link = implode(preg_split("/\\x00/", $this->_data, 1), ""); + $this->_link = implode($this->explodeString8($this->_data, 1), ""); } /** diff --git a/src/ID3/Frame/AbstractText.php b/src/ID3/Frame/AbstractText.php index 98ca2fd..94c922b 100644 --- a/src/ID3/Frame/AbstractText.php +++ b/src/ID3/Frame/AbstractText.php @@ -46,6 +46,7 @@ require_once("ID3/Encoding.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -80,20 +81,20 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); $this->_data = substr($this->_data, 1); switch ($this->_encoding) { case self::UTF16: $this->_text = - preg_split("/\\x00\\x00/", Transform::fromString16($this->_data)); + $this->explodeString16(Transform::fromString16($this->_data)); break; case self::UTF16BE: $this->_text = - preg_split("/\\x00\\x00/", Transform::fromString16BE($this->_data)); + $this->explodeString16(Transform::fromString16BE($this->_data)); break; default: $this->_text = - preg_split("/\\x00/", Transform::fromString8($this->_data)); + $this->explodeString8(Transform::fromString8($this->_data)); } } @@ -146,17 +147,20 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding); + $data = Transform::toUInt8($this->_encoding); switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16(implode("\0\0", $this->_text)); + case self::UTF16LE: + $array = $this->_text; + foreach ($array as &$text) + $text = Transform::toString16($str); + $data .= Transform::toString16 + (implode("\0\0", $array), $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER); break; case self::UTF16BE: $data .= Transform::toString16BE(implode("\0\0", $this->_text)); break; - case self::UTF16LE: - $data .= Transform::toString16LE(implode("\0\0", $this->_text)); - break; default: $data .= implode("\0", $this->_text); } diff --git a/src/ID3/Frame/COMM.php b/src/ID3/Frame/COMM.php index 468b591..fda5bd9 100644 --- a/src/ID3/Frame/COMM.php +++ b/src/ID3/Frame/COMM.php @@ -53,6 +53,7 @@ require_once("ID3/Exception.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -64,7 +65,7 @@ final class ID3_Frame_COMM extends ID3_Frame private $_encoding = ID3_Encoding::UTF8; /** @var string */ - private $_language = "eng"; + private $_language = "und"; /** @var string */ private $_description; @@ -85,26 +86,28 @@ final class ID3_Frame_COMM extends ID3_Frame if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); $this->_language = substr($this->_data, 1, 3); + if ($this->_language == "XXX") + $this->_language = "und"; $this->_data = substr($this->_data, 4); switch ($this->_encoding) { case self::UTF16: list ($this->_description, $this->_text) = - preg_split("/\\x00\\x00/", $this->_data, 2); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16($this->_description); $this->_text = Transform::fromString16($this->_text); break; case self::UTF16BE: list ($this->_description, $this->_text) = - preg_split("/\\x00\\x00/", $this->_data, 2); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16BE($this->_description); $this->_text = Transform::fromString16BE($this->_text); break; default: list ($this->_description, $this->_text) = - preg_split("/\\x00/", $this->_data, 2); + $this->explodeString8($this->_data, 2); $this->_description = Transform::fromString8($this->_description); $this->_text = Transform::fromString8($this->_text); } @@ -140,7 +143,12 @@ final class ID3_Frame_COMM extends ID3_Frame * @see ID3_Language * @param string $language The language code. */ - public function setLanguage($language) { $this->_language = $language; } + public function setLanguage($language) + { + if ($language == "XXX") + $language = "und"; + $this->_language = substr($language, 0, 3); + } /** * Returns the short content description. @@ -162,9 +170,9 @@ final class ID3_Frame_COMM extends ID3_Frame { $this->_description = $description; if ($language !== false) - $this->_language = $language; + $this->setLanguage($language); if ($encoding !== false) - $this->_encoding = $encoding; + $this->setEncoding($encoding); } /** @@ -186,9 +194,9 @@ final class ID3_Frame_COMM extends ID3_Frame { $this->_text = $text; if ($language !== false) - $this->_language = $language; + $this->setLanguage($language); if ($encoding !== false) - $this->_encoding = $encoding; + $this->setEncoding($encoding); } /** @@ -198,19 +206,18 @@ final class ID3_Frame_COMM extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding) . $this->_language; + $data = Transform::toUInt8($this->_encoding) . $this->_language; switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_description) . "\0\0" . - Transform::toString16($this->_text); + case self::UTF16LE: + $order = $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER; + $data .= Transform::toString16($this->_description, $order) . "\0\0" . + Transform::toString16($this->_text, $order); break; case self::UTF16BE: - $data .= Transform::toString16BE($this->_description) . "\0\0" . - Transform::toString16BE($this->_text); - break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_description) . "\0\0" . - Transform::toString16LE($this->_text); + $data .= Transform::toString16BE + ($this->_description . "\0\0" . $this->_text); break; default: $data .= $this->_description . "\0" . $this->_text; diff --git a/src/ID3/Frame/COMR.php b/src/ID3/Frame/COMR.php index 2d57278..84762c0 100644 --- a/src/ID3/Frame/COMR.php +++ b/src/ID3/Frame/COMR.php @@ -52,6 +52,7 @@ require_once("ID3/Encoding.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -100,6 +101,9 @@ final class ID3_Frame_COMR extends ID3_Frame /** @var string */ private $_imageData; + /** @var integer */ + private $_imageSize = 0; + /** * Constructs the class with given parameters and parses object related data. * @@ -113,33 +117,33 @@ final class ID3_Frame_COMR extends ID3_Frame if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); list($pricing, $this->_data) = - preg_split("/\\x00/", substr($this->_data, 1), 2); + $this->explodeString8(substr($this->_data, 1), 2); $this->_currency = substr($pricing, 0, 3); $this->_price = substr($pricing, 3); $this->_date = substr($this->_data, 0, 8); list($this->_contact, $this->_data) = - preg_split("/\\x00/", substr($this->_data, 8), 2); - $this->_delivery = Transform::fromInt8($this->_data[0]); + $this->explodeString8(substr($this->_data, 8), 2); + $this->_delivery = Transform::fromUInt8($this->_data[0]); $this->_data = substr($this->_data, 1); switch ($this->_encoding) { case self::UTF16: list ($this->_seller, $this->_description, $this->_data) = - preg_split("/\\x00\\x00/", $this->_data, 3); + $this->explodeString16($this->_data, 3); $this->_seller = Transform::fromString16($this->_seller); $this->_description = Transform::fromString16($this->_description); break; case self::UTF16BE: list ($this->_seller, $this->_description, $this->_data) = - preg_split("/\\x00\\x00/", $this->_data, 3); + $this->explodeString16($this->_data, 3); $this->_seller = Transform::fromString16BE($this->_seller); $this->_description = Transform::fromString16BE($this->_description); break; default: list ($this->_seller, $this->_description, $this->_data) = - preg_split("/\\x00/", $this->_data, 3); + $this->explodeString8($this->_data, 3); $this->_seller = Transform::fromString8($this->_seller); $this->_description = Transform::fromString8($this->_description); } @@ -148,7 +152,9 @@ final class ID3_Frame_COMR extends ID3_Frame return; list($this->_mimeType, $this->_imageData) = - preg_split("/\\x00/", $this->_imageData, 2); + $this->explodeString8($this->_data, 2); + + $this->_imageSize = strlen($this->_imageData); } /** @@ -211,7 +217,7 @@ final class ID3_Frame_COMR extends ID3_Frame * * @return string */ - public function getDate() { return $this->_price; } + public function getDate() { return $this->_date; } /** * Sets the date describing for how long the price is valid for. The date must @@ -313,14 +319,26 @@ final class ID3_Frame_COMR extends ID3_Frame * * @return string */ - public function getData() { return $this->_imageData; } + public function getImageData() { return $this->_imageData; } /** - * Sets the embedded image data. + * Sets the embedded image data. Also updates the image size to correspond the + * new data. * * @param string $imageData The image data. */ - public function setData($imageData) { $this->_imageData = $imageData; } + public function setImageData($imageData) + { + $this->_imageData = $imageData; + $this->_imageSize = strlen($imageData); + } + + /** + * Returns the size of the embedded image data. + * + * @return integer + */ + public function getImageSize() { return $this->_imageSize; } /** * Returns the frame raw data. @@ -329,28 +347,27 @@ final class ID3_Frame_COMR extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding) . $this->_price . "\0" . - $this->_date . $this->_contact . "\0" . - Transform::toInt8($this->_delivery); + $data = Transform::toUInt8($this->_encoding) . $this->_currency . + $this->_price . "\0" . $this->_date . $this->_contact . "\0" . + Transform::toUInt8($this->_delivery); switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_seller) . "\0\0" . - Transform::toString16($this->_description) . "\0\0"; + case self::UTF16LE: + $order = $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER; + $data .= Transform::toString16($this->_seller, $order) . "\0\0" . + Transform::toString16($this->_description, $order) . "\0\0"; break; case self::UTF16BE: - $data .= Transform::toString16BE($this->_seller) . "\0\0"; - Transform::toString16($this->_description) . "\0\0"; - break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_seller) . "\0\0"; - Transform::toString16($this->_description) . "\0\0"; + $data .= Transform::toString16BE + ($this->_seller . "\0\0" . $this->_description . "\0\0"); break; default: $data .= $this->_seller . "\0" . $this->_description . "\0"; } parent::setData ($data . ($this->_mimeType ? - $this->_mimeType . "\0" . $this->_imageData : 0)); + $this->_mimeType . "\0" . $this->_imageData : "")); return parent::__toString(); } } diff --git a/src/ID3/Frame/ENCR.php b/src/ID3/Frame/ENCR.php index 13f290d..6eba403 100644 --- a/src/ID3/Frame/ENCR.php +++ b/src/ID3/Frame/ENCR.php @@ -62,6 +62,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -90,7 +91,7 @@ final class ID3_Frame_ENCR extends ID3_Frame if ($reader === null) return; - list($this->_owner, $this->_data) = preg_split("/\\x00/", $this->_data, 2); + list($this->_owner, $this->_data) = $this->explodeString8($this->_data, 2); $this->_method = Transform::fromInt8($this->_data[0]); $this->_encryptionData = substr($this->_data, 1); } @@ -128,14 +129,14 @@ final class ID3_Frame_ENCR extends ID3_Frame * * @return string */ - public function getData() { return $this->_encryptionData; } + public function getEncryptionData() { return $this->_encryptionData; } /** * Sets the encryption data. * * @param string $encryptionData The encryption data string. */ - public function setData($encryptionData) + public function setEncryptionData($encryptionData) { $this->_encryptionData = $encryptionData; } diff --git a/src/ID3/Frame/EQU2.php b/src/ID3/Frame/EQU2.php index 73da81c..153e2af 100644 --- a/src/ID3/Frame/EQU2.php +++ b/src/ID3/Frame/EQU2.php @@ -49,6 +49,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -93,13 +94,13 @@ final class ID3_Frame_EQU2 extends ID3_Frame $this->_interpolation = Transform::fromInt8($this->_data[0]); list ($this->_device, $this->_data) = - preg_split("/\\x00/", substr($this->_data, 1), 2); + $this->explodeString8(substr($this->_data, 1), 2); - for ($i = 0; $i < strlen($this->_data); $i += 8) + for ($i = 0; $i < strlen($this->_data); $i += 4) $this->_adjustments - [Transform::fromInt16BE(substr($this->_data, $i, 2)) / 2] = - Transform::fromInt16BE(substr($this->_data, $i + 2, 2)) / 512; - sort($this->_adjustments); + [(int)(Transform::fromUInt16BE(substr($this->_data, $i, 2)) / 2)] = + Transform::fromInt16BE(substr($this->_data, $i + 2, 2)) / 512.0; + ksort($this->_adjustments); } /** @@ -149,7 +150,7 @@ final class ID3_Frame_EQU2 extends ID3_Frame /** * Adds a volume adjustment setting for given frequency. The frequency can - * have a value from 0 to 32767 Hz, and the adjustment +/- 64 dB with a + * have a value from 0 to 32767 Hz, and the adjustment +/- 64 dB with a * precision of 0.001953125 dB. * * @param integer $frequency The frequency, in hertz. @@ -157,23 +158,22 @@ final class ID3_Frame_EQU2 extends ID3_Frame */ public function addAdjustment($frequency, $adjustment) { - $this->_adjustments[$frequency * 2] = $adjustment * 512; - sort($this->_adjustments); + $this->_adjustments[$frequency] = $adjustment; + ksort($this->_adjustments); } /** * Sets the adjustments array. The array must have frequencies as keys and * their corresponding adjustments as values. The frequency can have a value - * from 0 to 32767 Hz, and the adjustment +/- 64 dB with a precision of + * from 0 to 32767 Hz, and the adjustment +/- 64 dB with a precision of * 0.001953125 dB. One frequency should only be described once in the frame. * * @param Array $adjustments The adjustments array. */ public function setAdjustments($adjustments) { - foreach ($adjustments as $frequency => $adjustment) - $this->_adjustments[$frequency * 2] = $adjustment * 512; - sort($this->_adjustments); + $this->_adjustments = $adjustments; + ksort($this->_adjustments); } /** @@ -185,8 +185,8 @@ final class ID3_Frame_EQU2 extends ID3_Frame { $data = Transform::toInt8($this->_interpolation) . $this->_device . "\0"; foreach ($this->_adjustments as $frequency => $adjustment) - $data .= - Transform::toInt16BE($frequency) . Transform::toInt16BE($adjustment); + $data .= Transform::toUInt16BE($frequency * 2) . + Transform::toInt16BE($adjustment * 512); $this->setData($data); return parent::__toString(); } diff --git a/src/ID3/Frame/EQUA.php b/src/ID3/Frame/EQUA.php index ee882c0..7d9f221 100644 --- a/src/ID3/Frame/EQUA.php +++ b/src/ID3/Frame/EQUA.php @@ -48,6 +48,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -71,14 +72,19 @@ final class ID3_Frame_EQUA extends ID3_Frame if ($reader === null) return; - $adjustmentBits = Transform::fromInt8($this->_data[0]); //16 + $adjustmentBits = Transform::fromInt8($this->_data[0]); + if ($adjustmentBits <= 8 || $adjustmentBits > 16) + throw new ID3_Exception + ("Unsupported adjustment bit size of: " . $adjustmentBits); + for ($i = 1; $i < strlen($this->_data); $i += 4) { - $frequency = Transform::fromInt16BE(substr($this->_data, $i, 2)); + $frequency = Transform::fromUInt16BE(substr($this->_data, $i, 2)); $this->_adjustments[($frequency & 0x7fff)] = - ($frequency & 0x2000) == 0x2000 ? - Transform::fromInt16BE(substr($this->_data, $j + 2, 2)) : - -Transform::fromInt16BE(substr($this->_data, $j + 2, 2)); + ($frequency & 0x8000) == 0x8000 ? + Transform::fromUInt16BE(substr($this->_data, $i + 2, 2)) : + -Transform::fromUInt16BE(substr($this->_data, $i + 2, 2)); } + ksort($this->_adjustments); } /** @@ -99,8 +105,9 @@ final class ID3_Frame_EQUA extends ID3_Frame public function addAdjustment($frequency, $adjustment) { $this->_adjustments[$frequency] = $adjustment; + ksort($this->_adjustments); } - + /** * Sets the adjustments array. The array must have frequencies as keys and * their corresponding adjustments as values. The frequency can have a value @@ -112,6 +119,7 @@ final class ID3_Frame_EQUA extends ID3_Frame public function setAdjustments($adjustments) { $this->_adjustments = $adjustments; + ksort($this->_adjustments); } /** @@ -123,9 +131,9 @@ final class ID3_Frame_EQUA extends ID3_Frame { $data = Transform::toInt8(16); foreach ($this->_adjustments as $frequency => $adjustment) - $data .= Transform::toInt16BE - ($adjustment > 0 ? $frequency | 0x2000 : $frequency & ~0x2000) . - Transform::toInt16BE(abs($adjustment)); + $data .= Transform::toUInt16BE + ($adjustment > 0 ? $frequency | 0x8000 : $frequency & ~0x8000) . + Transform::toUInt16BE(abs($adjustment)); $this->setData($data); return parent::__toString(); } diff --git a/src/ID3/Frame/ETCO.php b/src/ID3/Frame/ETCO.php index 1cc6eb0..bfce399 100644 --- a/src/ID3/Frame/ETCO.php +++ b/src/ID3/Frame/ETCO.php @@ -57,6 +57,7 @@ require_once("ID3/Timing.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -85,7 +86,7 @@ final class ID3_Frame_ETCO extends ID3_Frame "One more byte of events follows"); /** @var integer */ - private $_format = 1; + private $_format = ID3_Timing::MPEG_FRAMES; /** @var Array */ private $_events = array(); @@ -103,14 +104,14 @@ final class ID3_Frame_ETCO extends ID3_Frame if ($reader === null) return; - $this->_format = Transform::fromInt8($this->_data[0]); + $this->_format = Transform::fromUInt8($this->_data[0]); for ($i = 1; $i < $this->getSize(); $i += 5) { - $this->_events[Transform::fromInt32BE(substr($this->_data, $i + 1, 4))] = - $data = Transform::fromInt8($this->_data[$i]); + $this->_events[Transform::fromUInt32BE(substr($this->_data, $i + 1, 4))] = + $data = Transform::fromUInt8($this->_data[$i]); if ($data == 0xff) break; } - sort($this->_events); + ksort($this->_events); } /** @@ -145,9 +146,10 @@ final class ID3_Frame_ETCO extends ID3_Frame */ public function setEvents($events, $format = false) { - $this->_events = events; + $this->_events = $events; if ($format !== false) $this->_format = $format; + ksort($this->_events); } /** @@ -157,10 +159,9 @@ final class ID3_Frame_ETCO extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_format); - sort($this->_events); + $data = Transform::toUInt8($this->_format); foreach ($this->_events as $timestamp => $type) - $data .= Transform::toInt8($type) . Transform::toInt32BE($timestamp); + $data .= Transform::toUInt8($type) . Transform::toUInt32BE($timestamp); $this->setData($data); return parent::__toString(); } diff --git a/src/ID3/Frame/GEOB.php b/src/ID3/Frame/GEOB.php index b46a17d..97433d2 100644 --- a/src/ID3/Frame/GEOB.php +++ b/src/ID3/Frame/GEOB.php @@ -47,6 +47,7 @@ require_once("ID3/Encoding.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -82,27 +83,27 @@ final class ID3_Frame_GEOB extends ID3_Frame if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); $this->_mimeType = substr ($this->_data, 1, ($pos = strpos($this->_data, "\0", 1)) - 1); - $this->_data = substr($this->_data, $pos); + $this->_data = substr($this->_data, $pos + 1); switch ($this->_encoding) { case self::UTF16: - list ($this->_filename, $this->_description, $this->_data) = - preg_split("/\\x00\\x00/", $this->_data, 3); + list ($this->_filename, $this->_description, $this->_objectData) = + $this->explodeString16($this->_data, 3); $this->_filename = Transform::fromString16($this->_filename); $this->_description = Transform::fromString16($this->_description); break; case self::UTF16BE: - list ($this->_filename, $this->_description, $this->_data) = - preg_split("/\\x00\\x00/", $this->_data, 3); + list ($this->_filename, $this->_description, $this->_objectData) = + $this->explodeString16($this->_data, 3); $this->_filename = Transform::fromString16BE($this->_filename); $this->_description = Transform::fromString16BE($this->_description); break; default: - list ($this->_filename, $this->_description, $this->_data) = - preg_split("/\\x00/", $this->_data, 3); + list ($this->_filename, $this->_description, $this->_objectData) = + $this->explodeString8($this->_data, 3); $this->_filename = Transform::fromString8($this->_filename); $this->_description = Transform::fromString8($this->_description); } @@ -184,14 +185,17 @@ final class ID3_Frame_GEOB extends ID3_Frame * * @return string */ - public function getData() { return $this->_objectData; } + public function getObjectData() { return $this->_objectData; } /** * Sets the embedded object binary data. * * @param string $objectData The object data. */ - public function setData($objectData) { $this->_objectData = $objectData; } + public function setObjectData($objectData) + { + $this->_objectData = $objectData; + } /** * Returns the frame raw data. @@ -200,19 +204,18 @@ final class ID3_Frame_GEOB extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding) . $this->_mimeType . "\0"; + $data = Transform::toUInt8($this->_encoding) . $this->_mimeType . "\0"; switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_filename) . "\0\0" . - Transform::toString16($this->_description) . "\0\0"; + case self::UTF16LE: + $order = $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER; + $data .= Transform::toString16($this->_filename, $order) . "\0\0" . + Transform::toString16($this->_description, $order) . "\0\0"; break; case self::UTF16BE: - $data .= Transform::toString16BE($this->_filename) . "\0\0" . - Transform::toString16BE($this->_description) . "\0\0"; - break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_filename) . "\0\0" . - Transform::toString16LE($this->_description) . "\0\0"; + $data .= Transform::toString16BE + ($this->_filename . "\0\0" . $this->_description . "\0\0"); break; default: $data .= $this->_filename . "\0" . $this->_description . "\0"; diff --git a/src/ID3/Frame/GRID.php b/src/ID3/Frame/GRID.php index 23f4624..18aa8ec 100644 --- a/src/ID3/Frame/GRID.php +++ b/src/ID3/Frame/GRID.php @@ -61,6 +61,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -89,8 +90,8 @@ final class ID3_Frame_GRID extends ID3_Frame if ($reader === null) return; - list($this->_owner, $this->_data) = preg_split("/\\x00/", $this->_data, 2); - $this->_group = Transform::fromInt8($this->_data[0]); + list($this->_owner, $this->_data) = $this->explodeString8($this->_data, 2); + $this->_group = Transform::fromUInt8($this->_data[0]); $this->_groupData = substr($this->_data, 1); } @@ -127,14 +128,14 @@ final class ID3_Frame_GRID extends ID3_Frame * * @return string */ - public function getData() { return $this->_groupData; } + public function getGroupData() { return $this->_groupData; } /** * Sets the group dependent data. * * @param string $groupData The data. */ - public function setData($groupData) { $this->_groupData = $groupData; } + public function setGroupData($groupData) { $this->_groupData = $groupData; } /** * Returns the frame raw data. @@ -144,7 +145,7 @@ final class ID3_Frame_GRID extends ID3_Frame public function __toString() { parent::setData - ($this->_owner . "\0" . Transform::toInt8($this->_group) . + ($this->_owner . "\0" . Transform::toUInt8($this->_group) . $this->_groupData); return parent::__toString(); } diff --git a/src/ID3/Frame/IPLS.php b/src/ID3/Frame/IPLS.php index 726da1a..0b6146a 100644 --- a/src/ID3/Frame/IPLS.php +++ b/src/ID3/Frame/IPLS.php @@ -49,6 +49,7 @@ require_once("ID3/Encoding.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -59,10 +60,10 @@ final class ID3_Frame_IPLS extends ID3_Frame { /** @var integer */ private $_encoding = ID3_Encoding::UTF8; - + /** @var Array */ private $_people = array(); - + /** * Constructs the class with given parameters and parses object related data. * @@ -72,71 +73,75 @@ final class ID3_Frame_IPLS extends ID3_Frame public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - + if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); - $data = array(); + $this->_encoding = Transform::fromUInt8($this->_data[0]); + $data = substr($this->_data, 1); + $order = Transform::MACHINE_ENDIAN_ORDER; switch ($this->_encoding) { case self::UTF16: - $data = preg_split - ("/\\x00\\x00/", Transform::fromString16($this->_data)); + $data = $this->explodeString16($data); + foreach ($data as &$str) + $str = Transform::fromString16($str, $order); break; case self::UTF16BE: - $data = preg_split - ("/\\x00\\x00/", Transform::fromString16BE($this->_data)); + $data = $this->explodeString16($data); + foreach ($data as &$str) + $str = Transform::fromString16BE($str); break; default: - $data = preg_split("/\\x00/", $this->_data); + $data = $this->explodeString8($data); } - for ($i = 0; $i < count($data); $i+=2) + + for ($i = 0; $i < count($data) - 1; $i += 2) $this->_people[] = array($data[$i] => @$data[$i + 1]); } - + /** * Returns the text encoding. - * + * * @return integer */ public function getEncoding() { return $this->_encoding; } /** * Sets the text encoding. - * + * * @see ID3_Encoding * @param integer $encoding The text encoding. */ public function setEncoding($encoding) { $this->_encoding = $encoding; } - + /** * Returns the involved people list as an array. For each person, the array * contains an entry, which too is an associate array with involvement as its * key and involvee as its value. - * + * * @return Array */ public function getPeople() { return $this->_people; } - + /** * Adds a person with his involvement. - * + * * @return string */ public function addPerson($involvement, $person) { $this->_people[] = array($involvement => $person); } - + /** * Sets the involved people list array. For each person, the array must * contain an associate array with involvement as its key and involvee as its * value. - * + * * @param Array $people The involved people list. */ public function setPeople($people) { $this->_people = $people; } - + /** * Returns the frame raw data. * @@ -144,19 +149,20 @@ final class ID3_Frame_IPLS extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding); + $data = Transform::toUInt8($this->_encoding); + $order = $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER; foreach ($this->_people as $entry) { foreach ($entry as $key => $val) { switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($key . "\0\0" . $val . "\0\0"); + case self::UTF16LE: + $data .= Transform::toString16($key, $order) . "\0\0" . + Transform::toString16($val, $order) . "\0\0"; break; case self::UTF16BE: $data .= Transform::toString16BE($key . "\0\0" . $val . "\0\0"); break; - case self::UTF16LE: - $data .= Transform::toString16LE($key . "\0\0" . $val . "\0\0"); - break; default: $data .= $key . "\0" . $val . "\0"; } diff --git a/src/ID3/Frame/LINK.php b/src/ID3/Frame/LINK.php index 4ead92d..becd1fd 100644 --- a/src/ID3/Frame/LINK.php +++ b/src/ID3/Frame/LINK.php @@ -79,6 +79,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -109,7 +110,7 @@ final class ID3_Frame_LINK extends ID3_Frame $this->_target = substr($this->_data, 0, 4); list($this->_url, $this->_qualifier) = - preg_split("/\\x00/", substr($this->_data, 4), 2); + $this->explodeString8(substr($this->_data, 4), 2); } /** diff --git a/src/ID3/Frame/OWNE.php b/src/ID3/Frame/OWNE.php index 75f1702..2c08e60 100644 --- a/src/ID3/Frame/OWNE.php +++ b/src/ID3/Frame/OWNE.php @@ -50,6 +50,7 @@ require_once("ID3/Encoding.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -85,9 +86,9 @@ final class ID3_Frame_OWNE extends ID3_Frame if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); list($tmp, $this->_data) = - preg_split("/\\x00/", substr($this->_data, 1), 2); + $this->explodeString8(substr($this->_data, 1), 2); $this->_currency = substr($tmp, 0, 3); $this->_price = substr($tmp, 3); $this->_date = substr($this->_data, 0, 8); @@ -197,18 +198,18 @@ final class ID3_Frame_OWNE extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding) . $this->_currency . + $data = Transform::toUInt8($this->_encoding) . $this->_currency . $this->_price . "\0" . $this->_date; switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_seller); + case self::UTF16LE: + $data .= Transform::toString16 + ($this->_seller, $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER); break; case self::UTF16BE: $data .= Transform::toString16BE($this->_seller); break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_seller); - break; default: $data .= $this->_seller; } diff --git a/src/ID3/Frame/PCNT.php b/src/ID3/Frame/PCNT.php index 95f17ba..93ec7b8 100644 --- a/src/ID3/Frame/PCNT.php +++ b/src/ID3/Frame/PCNT.php @@ -47,6 +47,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -70,7 +71,7 @@ final class ID3_Frame_PCNT extends ID3_Frame return; if (strlen($this->_data) > 4) - $this->_counter = Transform::fromInt64BE($this->_data); + $this->_counter = Transform::fromInt64BE($this->_data); // UInt64 else $this->_counter = Transform::fromUInt32BE($this->_data); } @@ -103,8 +104,8 @@ final class ID3_Frame_PCNT extends ID3_Frame { $this->setData ($this->_counter > 4294967295 ? - Transform::toInt64BE($this->_counter) : - Transform::toInt32BE($this->_counter)); + Transform::toInt64BE($this->_counter) : // UInt64 + Transform::toUInt32BE($this->_counter)); return parent::__toString(); } } diff --git a/src/ID3/Frame/POPM.php b/src/ID3/Frame/POPM.php index dec60bb..6e0d42c 100644 --- a/src/ID3/Frame/POPM.php +++ b/src/ID3/Frame/POPM.php @@ -58,6 +58,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -66,13 +67,13 @@ final class ID3_Frame_POPM extends ID3_Frame { /** @var string */ private $_owner; - + /** @var integer */ private $_rating = 0; - + /** @var integer */ private $_counter = 0; - + /** * Constructs the class with given parameters and parses object related data. * @@ -82,67 +83,67 @@ final class ID3_Frame_POPM extends ID3_Frame public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - + if ($reader === null) return; - list($this->_owner, $this->_data) = preg_split("/\\x00/", $this->_data, 2); - $this->_rating = Transform::fromInt8($this->_data[0]); + list($this->_owner, $this->_data) = $this->explodeString8($this->_data, 2); + $this->_rating = Transform::fromUInt8($this->_data[0]); $this->_data = substr($this->_data, 1); - + if (strlen($this->_data) > 4) - $this->_counter = Transform::fromInt64BE($this->_data); + $this->_counter = Transform::fromInt64BE($this->_data); // UInt64 else if (strlen($this->_data) > 0) $this->_counter = Transform::fromUInt32BE($this->_data); } - + /** * Returns the owner identifier string. - * + * * @return string */ public function getOwner() { return $this->_owner; } - + /** * Sets the owner identifier string. - * + * * @param string $owner The owner identifier string. */ public function setOwner($owner) { return $this->_owner = $owner; } - + /** * Returns the user rating. - * + * * @return integer */ public function getRating() { return $this->_rating; } - + /** * Sets the user rating. - * + * * @param integer $rating The user rating. */ public function setRating($rating) { $this->_rating = $rating; } - + /** * Returns the counter. - * + * * @return integer */ public function getCounter() { return $this->_counter; } - + /** * Adds counter by one. */ public function addCounter() { $this->_counter++; } - + /** * Sets the counter value. - * + * * @param integer $counter The counter value. */ public function setCounter($counter) { $this->_counter = $counter; } - + /** * Returns the frame raw data. * @@ -152,9 +153,9 @@ final class ID3_Frame_POPM extends ID3_Frame { $this->setData ($this->_owner . "\0" . Transform::toInt8($this->_rating) . - ($this->_counter > 4294967295 ? + ($this->_counter > 0xffffffff ? Transform::toInt64BE($this->_counter) : - ($this->_counter > 0 ? Transform::toInt32BE($this->_counter) : 0))); + ($this->_counter > 0 ? Transform::toUInt32BE($this->_counter) : 0))); return parent::__toString(); } } diff --git a/src/ID3/Frame/POSS.php b/src/ID3/Frame/POSS.php index 7bdd4d6..3fd9b78 100644 --- a/src/ID3/Frame/POSS.php +++ b/src/ID3/Frame/POSS.php @@ -49,6 +49,7 @@ require_once("ID3/Timing.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -57,9 +58,9 @@ final class ID3_Frame_POSS extends ID3_Frame implements ID3_Timing { /** @var integer */ - private $_format = 1; + private $_format = ID3_Timing::MPEG_FRAMES; - /** @var string */ + /** @var integer */ private $_position; /** @@ -74,8 +75,8 @@ final class ID3_Frame_POSS extends ID3_Frame if ($reader === null) return; - - $this->_format = Transform::fromInt8($this->_data[0]); + + $this->_format = Transform::fromUInt8($this->_data[0]); $this->_position = Transform::fromUInt32BE(substr($this->_data, 1, 4)); } @@ -124,8 +125,8 @@ final class ID3_Frame_POSS extends ID3_Frame public function __toString() { $this->setData - (Transform::toInt8($this->_format) . - Transform::toUInt32($this->_position)); + (Transform::toUInt8($this->_format) . + Transform::toUInt32BE($this->_position)); return parent::__toString(); } } diff --git a/src/ID3/Frame/PRIV.php b/src/ID3/Frame/PRIV.php index 7d95d3b..bcfd0ce 100644 --- a/src/ID3/Frame/PRIV.php +++ b/src/ID3/Frame/PRIV.php @@ -52,6 +52,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -78,7 +79,7 @@ final class ID3_Frame_PRIV extends ID3_Frame return; list($this->_owner, $this->_privateData) = - preg_split("/\\x00/", $this->_data, 2); + $this->explodeString8($this->_data, 2); } /** @@ -100,14 +101,17 @@ final class ID3_Frame_PRIV extends ID3_Frame * * @return string */ - public function getData() { return $this->_privateData; } + public function getPrivateData() { return $this->_privateData; } /** * Sets the private binary data associated with the frame. * * @param string $privateData The private binary data string. */ - public function setData($privateData) { $this->_privateData = $privateData; } + public function setPrivateData($privateData) + { + $this->_privateData = $privateData; + } /** * Returns the frame raw data. diff --git a/src/ID3/Frame/RBUF.php b/src/ID3/Frame/RBUF.php index a0b7829..d8648b6 100644 --- a/src/ID3/Frame/RBUF.php +++ b/src/ID3/Frame/RBUF.php @@ -66,6 +66,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -79,13 +80,13 @@ final class ID3_Frame_RBUF extends ID3_Frame const EMBEDDED = 0x1; /** @var integer */ - private $_size; + private $_bufferSize; /** @var integer */ - private $_flags; + private $_infoFlags; /** @var integer */ - private $_offset; + private $_offset = 0; /** * Constructs the class with given parameters and parses object related data. @@ -99,10 +100,12 @@ final class ID3_Frame_RBUF extends ID3_Frame if ($reader === null) return; - - $this->_size = Transform::fromInt32BE(substr($this->_data, 0, 3)); - $this->_flags = Transform::fromInt8($this->_data[3]); - $this->_offset = Transform::fromInt32BE(substr($this->_data, 4, 4)); + + $this->_bufferSize = + Transform::fromUInt32BE("\0" . substr($this->_data, 0, 3)); + $this->_infoFlags = Transform::fromInt8($this->_data[3]); + if ($this->getSize() > 4) + $this->_offset = Transform::fromInt32BE(substr($this->_data, 4, 4)); } /** @@ -110,14 +113,17 @@ final class ID3_Frame_RBUF extends ID3_Frame * * @return integer */ - public function getSize() { return $this->_size; } + public function getBufferSize() { return $this->_bufferSize; } /** * Sets the buffer size. * * @param integer $size The buffer size. */ - public function setSize($size) { $this->_size = $size; } + public function setBufferSize($bufferSize) + { + $this->_bufferSize = $bufferSize; + } /** * Checks whether or not the flag is set. Returns true if the flag @@ -126,21 +132,24 @@ final class ID3_Frame_RBUF extends ID3_Frame * @param integer $flag The flag to query. * @return boolean */ - public function hasFlag($flag) { return ($this->_flags & $flag) == $flag; } + public function hasInfoFlag($flag) + { + return ($this->_infoFlags & $flag) == $flag; + } /** * Returns the flags byte. * * @return integer */ - public function getFlags($flags) { return $this->_flags; } + public function getInfoFlags() { return $this->_infoFlags; } /** * Sets the flags byte. * * @param string $flags The flags byte. */ - public function setFlags($flags) { $this->_flags = $flags; } + public function setInfoFlags($infoFlags) { $this->_infoFlags = $infoFlags; } /** * Returns the offset to next tag. @@ -164,8 +173,9 @@ final class ID3_Frame_RBUF extends ID3_Frame public function __toString() { $this->setData - (substr(Transform::toInt32BE($this->_size) << 8, 0, 3) . - Transform::toInt8($this->_flags) . Transform::toInt32BE($this->_offset)); + (substr(Transform::toUInt32BE($this->_bufferSize), 1, 3) . + Transform::toInt8($this->_infoFlags) . + Transform::toInt32BE($this->_offset)); return parent::__toString(); } } diff --git a/src/ID3/Frame/RVA2.php b/src/ID3/Frame/RVA2.php index 6d62360..7a84742 100644 --- a/src/ID3/Frame/RVA2.php +++ b/src/ID3/Frame/RVA2.php @@ -57,6 +57,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -64,6 +65,29 @@ require_once("ID3/Frame.php"); */ final class ID3_Frame_RVA2 extends ID3_Frame { + /** + * The channel type key. + * + * @see $types + * @var string + */ + const channelType = "channelType"; + + /** + * The volume adjustment key. Adjustments are +/- 64 dB with a precision of + * 0.001953125 dB. + * + * @var string + */ + const volumeAdjustment = "volumeAdjustment"; + + /** + * The peak volume key. + * + * @var string + */ + const peakVolume = "peakVolume"; + /** * The list of channel types. * @@ -72,13 +96,13 @@ final class ID3_Frame_RVA2 extends ID3_Frame public static $types = array ("Other", "Master volume", "Front right", "Front left", "Back right", "Back left", "Front centre", "Back centre", "Subwoofer"); - + /** @var string */ private $_device; - + /** @var Array */ private $_adjustments; - + /** * Constructs the class with given parameters and parses object related data. * @@ -88,45 +112,43 @@ final class ID3_Frame_RVA2 extends ID3_Frame public function __construct($reader = null, &$options = array()) { parent::__construct($reader, $options); - + if ($reader === null) return; - + list ($this->_device, $this->_data) = - preg_split("/\\x00/", $this->_data, 2); - + $this->explodeString8($this->_data, 2); + for ($i = $j = 0; $i < 9; $i++) { $this->_adjustments[$i] = array - ("channelType" => Transform::fromInt8($this->_data[$j++]), - "volumeAdjustment" => - Transform::fromInt16BE(substr($this->_data, $j++, 2))); - $bitsInPeak = Transform::fromInt8($this->_data[(++$j)++]); + (self::channelType => Transform::fromInt8($this->_data[$j++]), + self::volumeAdjustment => + Transform::fromInt16BE(substr($this->_data, $j++, 2)) / 512.0); + $j++; + $bitsInPeak = Transform::fromInt8($this->_data[$j++]); $bytesInPeak = $bitsInPeak > 0 ? ceil($bitsInPeak / 8) : 0; switch ($bytesInPeak) { case 8: case 7: case 6: case 5: - $this->_adjustments[$i]["peakVolume"] = + $this->_adjustments[$i][self::peakVolume] = Transform::fromInt64BE(substr($this->_data, $j, $bytesInPeak)); - $j += $bytesInPeak; break; case 4: case 3: - $this->_adjustments[$i]["peakVolume"] = + $this->_adjustments[$i][self::peakVolume] = Transform::fromUInt32BE(substr($this->_data, $j, $bytesInPeak)); - $j += $bytesInPeak; break; case 2: - $this->_adjustments[$i]["peakVolume"] = + $this->_adjustments[$i][self::peakVolume] = Transform::fromUInt16BE(substr($this->_data, $j, $bytesInPeak)); - $j += $bytesInPeak; break; case 1: - $this->_adjustments[$i]["peakVolume"] = - Transform::fromInt8(substr($this->_data, $j, $bytesInPeak)); - $j += $bytesInPeak; + $this->_adjustments[$i][self::peakVolume] = + Transform::fromUInt8(substr($this->_data, $j, $bytesInPeak)); } + $j += $bytesInPeak; } } @@ -136,35 +158,35 @@ final class ID3_Frame_RVA2 extends ID3_Frame * @return string */ public function getDevice() { return $this->_device; } - + /** * Sets the device where the adjustments should apply. * * @param string $device The device. */ public function setDevice($device) { $this->_device = $device; } - + /** * Returns the array containing volume adjustments for each channel. Volume * adjustments are arrays themselves containing the following keys: * channelType, volumeAdjustment, peakVolume. - * + * * @return Array */ public function getAdjustments() { return $this->_adjustments; } - + /** * Sets the array of volume adjustments for each channel. Each volume * adjustment is an array too containing the following keys: channelType, * volumeAdjustment, peakVolume. - * + * * @param Array $adjustments The volume adjustments array. */ public function setAdjustments($adjustments) { $this->_adjustments = $adjustments; } - + /** * Returns the frame raw data. * @@ -174,20 +196,20 @@ final class ID3_Frame_RVA2 extends ID3_Frame { $data = $this->_device . "\0"; foreach ($this->_adjustments as $channel) { - $data .= Transform::toInt8($channel["channelType"]) . - Transform::toInt16BE($channel["volumeAdjustment"]); - if ($channel["peakVolume"] < 255) + $data .= Transform::toInt8($channel[self::channelType]) . + Transform::toInt16BE($channel[self::volumeAdjustment] * 512); + if (abs($channel[self::peakVolume]) <= 0xff) $data .= Transform::toInt8(8) . - Transform::toInt8($channel["peakVolume"]); - else if ($channel["peakVolume"] < 65535) + Transform::toUInt8($channel[self::peakVolume]); + else if (abs($channel[self::peakVolume]) <= 0xffff) $data .= Transform::toInt8(16) . - Transform::toUInt16BE($channel["peakVolume"]); - else if ($channel["peakVolume"] < 4294967295) + Transform::toUInt16BE($channel[self::peakVolume]); + else if (abs($channel[self::peakVolume]) <= 0xffffffff) $data .= Transform::toInt8(32) . - Transform::toUInt32BE($channel["peakVolume"]); + Transform::toUInt32BE($channel[self::peakVolume]); else $data .= Transform::toInt8(64) . - Transform::toUInt64BE($channel["peakVolume"]); + Transform::toInt64BE($channel[self::peakVolume]); // UInt64 } $this->setData($data); return parent::__toString(); diff --git a/src/ID3/Frame/RVAD.php b/src/ID3/Frame/RVAD.php index 08ca4d4..36b8452 100644 --- a/src/ID3/Frame/RVAD.php +++ b/src/ID3/Frame/RVAD.php @@ -53,6 +53,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -60,6 +61,46 @@ require_once("ID3/Frame.php"); */ final class ID3_Frame_RVAD extends ID3_Frame { + /* The required keys. */ + + /** @var string */ + const right = "right"; + + /** @var string */ + const left = "left"; + + /** @var string */ + const peakRight = "peakRight"; + + /** @var string */ + const peakLeft = "peakLeft"; + + /* The optional keys. */ + + /** @var string */ + const rightBack = "rightBack"; + + /** @var string */ + const leftBack = "leftBack"; + + /** @var string */ + const peakRightBack = "peakRightBack"; + + /** @var string */ + const peakLeftBack = "peakLeftBack"; + + /** @var string */ + const center = "center"; + + /** @var string */ + const peakCenter = "peakCenter"; + + /** @var string */ + const bass = "bass"; + + /** @var string */ + const peakBass = "peakBass"; + /** @var Array */ private $_adjustments; @@ -77,56 +118,59 @@ final class ID3_Frame_RVAD extends ID3_Frame return; $flags = Transform::fromInt8($this->_data[0]); - $descriptionBits = Transform::fromInt8($this->_data[0]); //16 + $descriptionBits = Transform::fromInt8($this->_data[1]); + if ($descriptionBits <= 8 || $descriptionBits > 16) + throw new ID3_Exception + ("Unsupported description bit size of: " . $descriptionBits); - $this->_adjustments["right"] = - ($flags & 0x20) == 0x20 ? - Transform::fromUInt16BE(substr($this->_data, 0, 2)) : - -Transform::fromUInt16BE(substr($this->_data, 0, 2)); - $this->_adjustments["left"] = - ($flags & 0x10) == 0x10 ? + $this->_adjustments[self::right] = + ($flags & 0x1) == 0x1 ? Transform::fromUInt16BE(substr($this->_data, 2, 2)) : -Transform::fromUInt16BE(substr($this->_data, 2, 2)); - $this->_adjustments["peakRight"] = - Transform::fromUInt16BE(substr($this->_data, 4, 2)); - $this->_adjustments["peakLeft"] = + $this->_adjustments[self::left] = + ($flags & 0x2) == 0x2 ? + Transform::fromUInt16BE(substr($this->_data, 4, 2)) : + -Transform::fromUInt16BE(substr($this->_data, 4, 2)); + $this->_adjustments[self::peakRight] = Transform::fromUInt16BE(substr($this->_data, 6, 2)); + $this->_adjustments[self::peakLeft] = + Transform::fromUInt16BE(substr($this->_data, 8, 2)); - if ($this->getSize() <= 8) + if ($this->getSize() <= 10) return; - $this->_adjustments["rightBack"] = - ($flags & 0x8) == 0x8 ? - Transform::fromUInt16BE(substr($this->_data, 8, 2)) : - -Transform::fromUInt16BE(substr($this->_data, 8, 2)); - $this->_adjustments["leftBack"] = + $this->_adjustments[self::rightBack] = ($flags & 0x4) == 0x4 ? Transform::fromUInt16BE(substr($this->_data, 10, 2)) : -Transform::fromUInt16BE(substr($this->_data, 10, 2)); - $this->_adjustments["peakRightBack"] = - Transform::fromUInt16BE(substr($this->_data, 12, 2)); - $this->_adjustments["peakLeftBack"] = + $this->_adjustments[self::leftBack] = + ($flags & 0x8) == 0x8 ? + Transform::fromUInt16BE(substr($this->_data, 12, 2)) : + -Transform::fromUInt16BE(substr($this->_data, 12, 2)); + $this->_adjustments[self::peakRightBack] = Transform::fromUInt16BE(substr($this->_data, 14, 2)); + $this->_adjustments[self::peakLeftBack] = + Transform::fromUInt16BE(substr($this->_data, 16, 2)); - if ($this->getSize() <= 16) + if ($this->getSize() <= 18) return; - $this->_adjustments["center"] = - ($flags & 0x2) == 0x2 ? - Transform::fromUInt16BE(substr($this->_data, 16, 2)) : - -Transform::fromUInt16BE(substr($this->_data, 16, 2)); - $this->_adjustments["peakCenter"] = - Transform::fromUInt16BE(substr($this->_data, 18, 2)); + $this->_adjustments[self::center] = + ($flags & 0x10) == 0x10 ? + Transform::fromUInt16BE(substr($this->_data, 18, 2)) : + -Transform::fromUInt16BE(substr($this->_data, 18, 2)); + $this->_adjustments[self::peakCenter] = + Transform::fromUInt16BE(substr($this->_data, 20, 2)); - if ($this->getSize() <= 20) + if ($this->getSize() <= 22) return; - $this->_adjustments["bass"] = - ($flags & 0x1) == 0x1 ? - Transform::fromUInt16BE(substr($this->_data, 20, 2)) : - -Transform::fromUInt16BE(substr($this->_data, 20, 2)); - $this->_adjustments["peakBass"] = - Transform::fromUInt16BE(substr($this->_data, 22, 2)); + $this->_adjustments[self::bass] = + ($flags & 0x20) == 0x20 ? + Transform::fromUInt16BE(substr($this->_data, 22, 2)) : + -Transform::fromUInt16BE(substr($this->_data, 22, 2)); + $this->_adjustments[self::peakBass] = + Transform::fromUInt16BE(substr($this->_data, 24, 2)); } /** @@ -160,47 +204,47 @@ final class ID3_Frame_RVAD extends ID3_Frame public function __toString() { $flags = 0; - if ($this->_adjustments["right"] > 0) - $flags = $flags | 0x20; - if ($this->_adjustments["left"] > 0) - $flags = $flags | 0x10; + if ($this->_adjustments[self::right] > 0) + $flags = $flags | 0x1; + if ($this->_adjustments[self::left] > 0) + $flags = $flags | 0x2; $data = Transform::toInt8(16) . - Transform::toUInt16BE(abs($this->_adjustments["right"])) . - Transform::toUInt16BE(abs($this->_adjustments["left"])) . - Transform::toUInt16BE(abs($this->_adjustments["peakRight"])) . - Transform::toUInt16BE(abs($this->_adjustments["peakLeft"])); + Transform::toUInt16BE(abs($this->_adjustments[self::right])) . + Transform::toUInt16BE(abs($this->_adjustments[self::left])) . + Transform::toUInt16BE(abs($this->_adjustments[self::peakRight])) . + Transform::toUInt16BE(abs($this->_adjustments[self::peakLeft])); - if (isset($this->_adjustments["rightBack"]) && - isset($this->_adjustments["leftBack"]) && - isset($this->_adjustments["peakRightBack"]) && - isset($this->_adjustments["peakLeftBack"])) { - if ($this->_adjustments["rightBack"] > 0) - $flags = $flags | 0x8; - if ($this->_adjustments["leftBack"] > 0) + if (isset($this->_adjustments[self::rightBack]) && + isset($this->_adjustments[self::leftBack]) && + isset($this->_adjustments[self::peakRightBack]) && + isset($this->_adjustments[self::peakLeftBack])) { + if ($this->_adjustments[self::rightBack] > 0) $flags = $flags | 0x4; + if ($this->_adjustments[self::leftBack] > 0) + $flags = $flags | 0x8; $data .= - Transform::toUInt16BE(abs($this->_adjustments["rightBack"])) . - Transform::toUInt16BE(abs($this->_adjustments["leftBack"])) . - Transform::toUInt16BE(abs($this->_adjustments["peakRightBack"])) . - Transform::toUInt16BE(abs($this->_adjustments["peakLeftBack"])); + Transform::toUInt16BE(abs($this->_adjustments[self::rightBack])) . + Transform::toUInt16BE(abs($this->_adjustments[self::leftBack])) . + Transform::toUInt16BE(abs($this->_adjustments[self::peakRightBack])) . + Transform::toUInt16BE(abs($this->_adjustments[self::peakLeftBack])); } - if (isset($this->_adjustments["center"]) && - isset($this->_adjustments["peakCenter"])) { - if ($this->_adjustments["center"] > 0) - $flags = $flags | 0x2; + if (isset($this->_adjustments[self::center]) && + isset($this->_adjustments[self::peakCenter])) { + if ($this->_adjustments[self::center] > 0) + $flags = $flags | 0x10; $data .= - Transform::toUInt16BE(abs($this->_adjustments["center"])) . - Transform::toUInt16BE(abs($this->_adjustments["peakCenter"])); + Transform::toUInt16BE(abs($this->_adjustments[self::center])) . + Transform::toUInt16BE(abs($this->_adjustments[self::peakCenter])); } - if (isset($this->_adjustments["bass"]) && - isset($this->_adjustments["peakBass"])) { - if ($this->_adjustments["bass"] > 0) - $flags = $flags | 0x1; + if (isset($this->_adjustments[self::bass]) && + isset($this->_adjustments[self::peakBass])) { + if ($this->_adjustments[self::bass] > 0) + $flags = $flags | 0x20; $data .= - Transform::toUInt16BE(abs($this->_adjustments["bass"])) . - Transform::toUInt16BE(abs($this->_adjustments["peakBass"])); + Transform::toUInt16BE(abs($this->_adjustments[self::bass])) . + Transform::toUInt16BE(abs($this->_adjustments[self::peakBass])); } $this->setData(Transform::toInt8($flags) . $data); return parent::__toString(); diff --git a/src/ID3/Frame/RVRB.php b/src/ID3/Frame/RVRB.php index 7c7733f..68b5492 100644 --- a/src/ID3/Frame/RVRB.php +++ b/src/ID3/Frame/RVRB.php @@ -59,6 +59,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -108,16 +109,16 @@ final class ID3_Frame_RVRB extends ID3_Frame if ($reader === null) return; - $this->_reverbLeft = Transform::fromInt16BE(substr($this->_data, 0, 2)); - $this->_reverbRight = Transform::fromInt16BE(substr($this->_data, 2, 2)); - $this->_reverbBouncesLeft = Transform::fromInt8($this->_data[4]); - $this->_reverbBouncesRight = Transform::fromInt8($this->_data[5]); - $this->_reverbFeedbackLtoL = Transform::fromInt8($this->_data[6]); - $this->_reverbFeedbackLtoR = Transform::fromInt8($this->_data[7]); - $this->_reverbFeedbackRtoR = Transform::fromInt8($this->_data[8]); - $this->_reverbFeedbackRtoL = Transform::fromInt8($this->_data[9]); - $this->_premixLtoR = Transform::fromInt8($this->_data[10]); - $this->_premixRtoL = Transform::fromInt8($this->_data[11]); + $this->_reverbLeft = Transform::fromUInt16BE(substr($this->_data, 0, 2)); + $this->_reverbRight = Transform::fromUInt16BE(substr($this->_data, 2, 2)); + $this->_reverbBouncesLeft = Transform::fromUInt8($this->_data[4]); + $this->_reverbBouncesRight = Transform::fromUInt8($this->_data[5]); + $this->_reverbFeedbackLtoL = Transform::fromUInt8($this->_data[6]); + $this->_reverbFeedbackLtoR = Transform::fromUInt8($this->_data[7]); + $this->_reverbFeedbackRtoR = Transform::fromUInt8($this->_data[8]); + $this->_reverbFeedbackRtoL = Transform::fromUInt8($this->_data[9]); + $this->_premixLtoR = Transform::fromUInt8($this->_data[10]); + $this->_premixRtoL = Transform::fromUInt8($this->_data[11]); } /** @@ -298,16 +299,16 @@ final class ID3_Frame_RVRB extends ID3_Frame public function __toString() { $this->setData - (Transform::toInt16BE($this->_reverbLeft) . - Transform::toInt16BE($this->_reverbRight) . - Transform::toInt8($this->_reverbBouncesLeft) . - Transform::toInt8($this->_reverbBouncesRight) . - Transform::toInt8($this->_reverbFeedbackLtoL) . - Transform::toInt8($this->_reverbFeedbackLtoR) . - Transform::toInt8($this->_reverbFeedbackRtoR) . - Transform::toInt8($this->_reverbFeedbackRtoL) . - Transform::toInt8($this->_premixLtoR) . - Transform::toInt8($this->_premixRtoL)); + (Transform::toUInt16BE($this->_reverbLeft) . + Transform::toUInt16BE($this->_reverbRight) . + Transform::toUInt8($this->_reverbBouncesLeft) . + Transform::toUInt8($this->_reverbBouncesRight) . + Transform::toUInt8($this->_reverbFeedbackLtoL) . + Transform::toUInt8($this->_reverbFeedbackLtoR) . + Transform::toUInt8($this->_reverbFeedbackRtoR) . + Transform::toUInt8($this->_reverbFeedbackRtoL) . + Transform::toUInt8($this->_premixLtoR) . + Transform::toUInt8($this->_premixRtoL)); return parent::__toString(); } } diff --git a/src/ID3/Frame/SIGN.php b/src/ID3/Frame/SIGN.php index 60c37be..f5481d7 100644 --- a/src/ID3/Frame/SIGN.php +++ b/src/ID3/Frame/SIGN.php @@ -50,6 +50,7 @@ require_once("ID3/Frame.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -76,7 +77,7 @@ final class ID3_Frame_SIGN extends ID3_Frame if ($reader === null) return; - $this->_group = substr($this->_data, 0, 1); + $this->_group = Transform::fromUInt8(substr($this->_data, 0, 1)); $this->_signature = substr($this->_data, 1); } @@ -115,7 +116,7 @@ final class ID3_Frame_SIGN extends ID3_Frame */ public function __toString() { - $this->setData(Transform::toInt8($this->_group) . $this->_signature); + $this->setData(Transform::toUInt8($this->_group) . $this->_signature); return parent::__toString(); } } diff --git a/src/ID3/Frame/SYLT.php b/src/ID3/Frame/SYLT.php index d618fd1..4286df3 100644 --- a/src/ID3/Frame/SYLT.php +++ b/src/ID3/Frame/SYLT.php @@ -51,10 +51,10 @@ require_once("ID3/Timing.php"); * There may be more than one SYLT frame in each tag, but only one with the * same language and content descriptor. * - * @todo The data could be parsed further; data samples needed * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -68,17 +68,17 @@ final class ID3_Frame_SYLT extends ID3_Frame * @var Array */ public static $types = array - ("Other", "Lyrics", "Text transcription", "Movement/Part name", "Eevents", + ("Other", "Lyrics", "Text transcription", "Movement/Part name", "Events", "Chord", "Trivia", "URLs to webpages", "URLs to images"); /** @var integer */ private $_encoding = ID3_Encoding::UTF8; /** @var string */ - private $_language = "eng"; + private $_language = "und"; /** @var integer */ - private $_format = 1; + private $_format = ID3_Timing::MPEG_FRAMES; /** @var integer */ private $_type = 0; @@ -87,7 +87,7 @@ final class ID3_Frame_SYLT extends ID3_Frame private $_description; /** @var Array */ - private $_text; + private $_events = array(); /** * Constructs the class with given parameters and parses object related data. @@ -102,30 +102,53 @@ final class ID3_Frame_SYLT extends ID3_Frame if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); $this->_language = substr($this->_data, 1, 3); - $this->_format = Transform::fromInt8($this->_data[3]); - $this->_type = Transform::fromInt8($this->_data[4]); - $this->_data = substr($this->_data, 5); + if ($this->_language == "XXX") + $this->_language = "und"; + $this->_format = Transform::fromUInt8($this->_data[4]); + $this->_type = Transform::fromUInt8($this->_data[5]); + $this->_data = substr($this->_data, 6); switch ($this->_encoding) { case self::UTF16: list($this->_description, $this->_data) = - preg_split("/\\x00\\x00/", $this->_data, 2); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16($this->_description); break; case self::UTF16BE: list($this->_description, $this->_data) = - preg_split("/\\x00\\x00/", $this->_data, 2); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16BE($this->_description); break; default: list($this->_description, $this->_data) = - preg_split("/\\x00/", $this->_data, 2); + $this->explodeString8($this->_data, 2); $this->_description = Transform::fromString8($this->_description); } - $this->_text = $this->_data; // FIXME: Better parsing of data + while (strlen($this->_data) > 0) { + switch ($this->_encoding) { + case self::UTF16: + list($syllable, $this->_data) = + $this->explodeString16($this->_data, 2); + $syllable = Transform::fromString16($syllable); + break; + case self::UTF16BE: + list($syllable, $this->_data) = + $this->explodeString16($this->_data, 2); + $syllable = Transform::fromString16BE($syllable); + break; + default: + list($syllable, $this->_data) = + $this->explodeString8($this->_data, 2); + $syllable = Transform::fromString8($syllable); + } + $this->_events[Transform::fromUInt32BE(substr($this->_data, 0, 4))] = + $syllable; + $this->_data = substr($this->_data, 4); + } + ksort($this->_events); } /** @@ -147,7 +170,6 @@ final class ID3_Frame_SYLT extends ID3_Frame * Returns the language code as specified in the * {@link http://www.loc.gov/standards/iso639-2/ ISO-639-2} standard. * - * @see ID3_Language#ISO_639_2 * @return string */ public function getLanguage() { return $this->_language; } @@ -159,7 +181,12 @@ final class ID3_Frame_SYLT extends ID3_Frame * @see ID3_Language * @param string $language The language code. */ - public function setLanguage($language) { $this->_language = $language; } + public function setLanguage($language) + { + if ($language == "XXX") + $language = "und"; + $this->_language = substr($language, 0, 3); + } /** * Returns the timing format. @@ -210,33 +237,34 @@ final class ID3_Frame_SYLT extends ID3_Frame { $this->_description = $description; if ($language !== false) - $this->_language = $language; + $this->setLanguage($language); if ($encoding !== false) - $this->_encoding = $encoding; + $this->setEncoding($encoding); } /** - * Returns the texts with their timestamps. + * Returns the syllable events with their timestamps. * * @return Array */ - public function getText() { return $this->_text; } + public function getEvents() { return $this->_events; } /** - * Sets the text using given encoding. The text language and encoding must be - * that of the description text. + * Sets the syllable events with their timestamps using given encoding. + * The text language and encoding must be that of the description text. * - * @param mixed $text The test string. + * @param Array $text The test string. * @param string $language The language code. * @param integer $encoding The text encoding. */ - public function setText($text, $language = false, $encoding = false) + public function setEvents($events, $language = false, $encoding = false) { - $this->_text = $text; + $this->_events = $events; if ($language !== false) - $this->_language = $language; + $this->setLanguage($language); if ($encoding !== false) - $this->_encoding = $encoding; + $this->setEncoding($encoding); + ksort($this->_events); } /** @@ -246,23 +274,38 @@ final class ID3_Frame_SYLT extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding) . $this->_language . - Transform::toInt8($this->_format) . Transform::toInt8($this->_type); + $data = Transform::toUInt8($this->_encoding) . $this->_language . + Transform::toUInt8($this->_format) . Transform::toUInt8($this->_type); switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_description) . "\0\0" . - Transform::toString16($this->_text); + case self::UTF16LE: + $data .= Transform::toString16 + ($this->_description, $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER) . + "\0\0"; break; case self::UTF16BE: - $data .= Transform::toString16BE($this->_description) . "\0\0" . - Transform::toString16BE($this->_text); - break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_description) . "\0\0" . - Transform::toString16LE($this->_text); + $data .= Transform::toString16BE($this->_description) . "\0\0"; break; default: - $data .= $this->_description . "\0" . $this->_text; + $data .= $this->_description . "\0"; + } + foreach ($this->_events as $timestamp => $syllable) { + switch ($this->_encoding) { + case self::UTF16: + case self::UTF16LE: + $data .= Transform::toString16 + ($syllable, $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER) . + "\0\0"; + break; + case self::UTF16BE: + $data .= Transform::toString16BE($syllable) . "\0\0"; + break; + default: + $data .= $syllable . "\0"; + } + $data .= Transform::toUInt32BE($timestamp); } $this->setData($data); return parent::__toString(); diff --git a/src/ID3/Frame/SYTC.php b/src/ID3/Frame/SYTC.php index c937ff8..f58cbed 100644 --- a/src/ID3/Frame/SYTC.php +++ b/src/ID3/Frame/SYTC.php @@ -62,6 +62,7 @@ require_once("ID3/Timing.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -69,11 +70,17 @@ require_once("ID3/Timing.php"); final class ID3_Frame_SYTC extends ID3_Frame implements ID3_Timing { - /** @var integer */ - private $_format = 1; + /** Describes a beat-free time period. */ + const BEAT_FREE = 0x00; - /** @var string */ - private $_tempoData; + /** Indicate one single beat-stroke followed by a beat-free period. */ + const SINGLE_BEAT = 0x01; + + /** @var integer */ + private $_format = ID3_Timing::MPEG_FRAMES; + + /** @var Array */ + private $_events = array(); /** * Constructs the class with given parameters and parses object related data. @@ -88,8 +95,17 @@ final class ID3_Frame_SYTC extends ID3_Frame if ($reader === null) return; - $this->_format = Transform::fromInt8($this->_data[0]); - $this->_tempoData = substr($this->_data, 1); // FIXME: Better parsing of data + $offset = 0; + $this->_format = Transform::fromUInt8($this->_data[$offset++]); + while ($offset < strlen($this->_data)) { + $tempo = Transform::fromUInt8($this->_data[$offset++]); + if ($tempo == 0xFF) + $tempo += Transform::fromUInt8($this->_data[$offset++]); + $this->_events + [Transform::fromUInt32BE(substr($this->_data, $offset, 4))] = $tempo; + $offset += 4; + } + ksort($this->_events); } /** @@ -108,18 +124,22 @@ final class ID3_Frame_SYTC extends ID3_Frame public function setFormat($format) { $this->_format = $format; } /** - * Returns the tempo data. + * Returns the time-bpm tempo events. * - * @return string + * @return Array */ - public function getData() { return $this->_tempoData; } + public function getEvents() { return $this->_events; } /** - * Sets the tempo data. + * Sets the time-bpm tempo events. * - * @param string $data The data string. + * @param Array $events The time-bpm tempo events. */ - public function setData($tempoData) { $this->_tempoData = $tempoData; } + public function setEvents($events) + { + $this->_events = $events; + ksort($this->_events); + } /** * Returns the frame raw data. @@ -128,7 +148,15 @@ final class ID3_Frame_SYTC extends ID3_Frame */ public function __toString() { - parent::setData(Transform::toInt8($this->_format) . $this->_tempoData); + $data = Transform::toUInt8($this->_format); + foreach ($this->_events as $timestamp => $tempo) { + if ($tempo >= 0xff) + $data .= Transform::toUInt8(0xff) . Transform::toUInt8($tempo - 0xff); + else + $data .= Transform::toUInt8($tempo); + $data .= Transform::toUInt32BE($timestamp); + } + parent::setData($data); return parent::__toString(); } } diff --git a/src/ID3/Frame/TXXX.php b/src/ID3/Frame/TXXX.php index 9c2a2b0..e90f670 100644 --- a/src/ID3/Frame/TXXX.php +++ b/src/ID3/Frame/TXXX.php @@ -52,6 +52,7 @@ require_once("ID3/Frame/AbstractText.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -69,24 +70,30 @@ final class ID3_Frame_TXXX extends ID3_Frame_AbstractText */ public function __construct($reader = null, &$options = array()) { - parent::__construct($reader, $options); + ID3_Frame::__construct($reader, $options); + + if ($reader === null) + return; + + $this->_encoding = Transform::fromUInt8($this->_data[0]); + $this->_data = substr($this->_data, 1); switch ($this->_encoding) { case self::UTF16: list($this->_description, $this->_text) = - preg_split("/\\x00\\x00/", $this->_data); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16($this->_description); $this->_text = array(Transform::fromString16($this->_text)); break; case self::UTF16BE: list($this->_description, $this->_text) = - preg_split("/\\x00\\x00/", $this->_data); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16BE($this->_description); $this->_text = array(Transform::fromString16BE($this->_text)); break; default: list($this->_description, $this->_text) = - preg_split("/\\x00/", $this->_data); + $this->explodeString8($this->_data, 2); $this->_text = array($this->_text); } } @@ -118,25 +125,24 @@ final class ID3_Frame_TXXX extends ID3_Frame_AbstractText */ public function __toString() { - $data = Transform::toInt8($this->_encoding); + $data = Transform::toUInt8($this->_encoding); switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_description) . "\0\0" . - Transform::toString16($this->_text[0]); + case self::UTF16LE: + $order = $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER; + $data .= Transform::toString16($this->_description, $order) . "\0\0" . + Transform::toString16($this->_text[0], $order); break; case self::UTF16BE: $data .= Transform::toString16BE($this->_description) . "\0\0" . Transform::toString16BE($this->_text[0]); break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_description) . "\0\0" . - Transform::toString16LE($this->_text[0]); - break; default: $data .= $this->_description . "\0" . $this->_text[0]; } $this->setData($data); - return parent::__toString(); + return ID3_Frame::__toString(); } } diff --git a/src/ID3/Frame/USER.php b/src/ID3/Frame/USER.php index 596eb4e..4f92c8d 100644 --- a/src/ID3/Frame/USER.php +++ b/src/ID3/Frame/USER.php @@ -51,6 +51,7 @@ require_once("ID3/Language.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -62,7 +63,7 @@ final class ID3_Frame_USER extends ID3_Frame private $_encoding = ID3_Encoding::UTF8; /** @var string */ - private $_language = "eng"; + private $_language = "und"; /** @var string */ private $_text; @@ -71,16 +72,19 @@ final class ID3_Frame_USER extends ID3_Frame * Constructs the class with given parameters and parses object related data. * * @param Reader $reader The reader object. + * @param Array $options The options array. */ - public function __construct($reader = null) + public function __construct($reader = null, &$options = array()) { - parent::__construct($reader); + parent::__construct($reader, $options); if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); $this->_language = substr($this->_data, 1, 3); + if ($this->_language == "XXX") + $this->_language = "und"; $this->_data = substr($this->_data, 4); switch ($this->_encoding) { @@ -125,7 +129,12 @@ final class ID3_Frame_USER extends ID3_Frame * @see ID3_Language * @param string $language The language code. */ - public function setLanguage($language) { $this->_language = $language; } + public function setLanguage($language) + { + if ($language == "XXX") + $language = "und"; + $this->_language = substr($language, 0, 3); + } /** * Returns the text. @@ -143,11 +152,11 @@ final class ID3_Frame_USER extends ID3_Frame */ public function setText($text, $language = false, $encoding = false) { - $this->_text = $text; + $this->_text = $text; if ($language !== false) - $this->_language = $language; + $this->setLanguage($language); if ($encoding !== false) - $this->_encoding = $encoding; + $this->setEncoding($encoding); } /** @@ -157,17 +166,17 @@ final class ID3_Frame_USER extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding) . $this->_language; + $data = Transform::toUInt8($this->_encoding) . $this->_language; switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_text); + case self::UTF16LE: + $data .= Transform::toString16 + ($this->_text, $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER); break; case self::UTF16BE: $data .= Transform::toString16BE($this->_text); break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_text); - break; default: $data .= $this->_text; } diff --git a/src/ID3/Frame/USLT.php b/src/ID3/Frame/USLT.php index 21c5c4a..77ff267 100644 --- a/src/ID3/Frame/USLT.php +++ b/src/ID3/Frame/USLT.php @@ -50,6 +50,7 @@ require_once("ID3/Language.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -61,7 +62,7 @@ final class ID3_Frame_USLT extends ID3_Frame private $_encoding = ID3_Encoding::UTF8; /** @var string */ - private $_language = "eng"; + private $_language = "und"; /** @var string */ private $_description; @@ -73,34 +74,37 @@ final class ID3_Frame_USLT extends ID3_Frame * Constructs the class with given parameters and parses object related data. * * @param Reader $reader The reader object. + * @param Array $options The options array. */ - public function __construct($reader = null) + public function __construct($reader = null, &$options = array()) { - parent::__construct($reader); + parent::__construct($reader, $options); if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); $this->_language = substr($this->_data, 1, 3); + if ($this->_language == "XXX") + $this->_language = "und"; $this->_data = substr($this->_data, 4); switch ($this->_encoding) { case self::UTF16: list ($this->_description, $this->_text) = - preg_split("/\\x00\\x00/", $this->_data, 2); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16($this->_description); $this->_text = Transform::fromString16($this->_text); break; case self::UTF16BE: list ($this->_description, $this->_text) = - preg_split("/\\x00\\x00/", $this->_data, 2); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16BE($this->_description); $this->_text = Transform::fromString16BE($this->_text); break; default: list ($this->_description, $this->_text) = - preg_split("/\\x00/", $this->_data, 2); + $this->explodeString8($this->_data, 2); $this->_description = Transform::fromString8($this->_description); $this->_text = Transform::fromString8($this->_text); } @@ -136,7 +140,12 @@ final class ID3_Frame_USLT extends ID3_Frame * @see ID3_Language * @param string $language The language code. */ - public function setLanguage($language) { $this->_language = $language; } + public function setLanguage($language) + { + if ($language == "XXX") + $language = "und"; + $this->_language = substr($language, 0, 3); + } /** * Returns the short content description. @@ -158,9 +167,9 @@ final class ID3_Frame_USLT extends ID3_Frame { $this->_description = $description; if ($language !== false) - $this->_language = $language; + $this->setLanguage($language); if ($encoding !== false) - $this->_encoding = $encoding; + $this->setEncoding($encoding); } /** @@ -182,9 +191,9 @@ final class ID3_Frame_USLT extends ID3_Frame { $this->_text = $text; if ($language !== false) - $this->_language = $language; + $this->setLanguage($language); if ($encoding !== false) - $this->_encoding = $encoding; + $this->setEncoding($encoding); } /** @@ -194,20 +203,19 @@ final class ID3_Frame_USLT extends ID3_Frame */ public function __toString() { - $data = Transform::toInt8($this->_encoding) . $this->_language; + $data = Transform::toUInt8($this->_encoding) . $this->_language; switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_description) . "\0\0" . - Transform::toString16($this->_text); + case self::UTF16LE: + $order = $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER; + $data .= Transform::toString16($this->_description, $order) . "\0\0" . + Transform::toString16($this->_text, $order); break; case self::UTF16BE: $data .= Transform::toString16BE($this->_description) . "\0\0" . Transform::toString16BE($this->_text); break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_description) . "\0\0" . - Transform::toString16LE($this->_text); - break; default: $data .= $this->_description . "\0" . $this->_text; } diff --git a/src/ID3/Frame/WXXX.php b/src/ID3/Frame/WXXX.php index 0fc739b..50a198b 100644 --- a/src/ID3/Frame/WXXX.php +++ b/src/ID3/Frame/WXXX.php @@ -50,6 +50,7 @@ require_once("ID3/Encoding.php"); * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -71,30 +72,31 @@ final class ID3_Frame_WXXX extends ID3_Frame_AbstractLink */ public function __construct($reader = null, &$options = array()) { - parent::__construct($reader, $options); + ID3_Frame::__construct($reader, $options); if ($reader === null) return; - $this->_encoding = Transform::fromInt8($this->_data[0]); + $this->_encoding = Transform::fromUInt8($this->_data[0]); $this->_data = substr($this->_data, 1); switch ($this->_encoding) { case self::UTF16: list($this->_description, $this->_link) = - preg_split("/\\x00\\x00/", $this->_data, 2); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16($this->_description); break; case self::UTF16BE: list($this->_description, $this->_link) = - preg_split("/\\x00\\x00/", $this->_data, 2); + $this->explodeString16($this->_data, 2); $this->_description = Transform::fromString16BE($this->_description); break; default: list($this->_description, $this->_link) = - preg_split("/\\x00/", $this->_data); + $this->explodeString8($this->_data, 2); break; } + $this->_link = implode($this->explodeString8($this->_link, 1), ""); } /** @@ -139,21 +141,22 @@ final class ID3_Frame_WXXX extends ID3_Frame_AbstractLink */ public function __toString() { - $data = Transform::toInt8($this->_encoding); + $data = Transform::toUInt8($this->_encoding); switch ($this->_encoding) { case self::UTF16: - $data .= Transform::toString16($this->_description) . "\0\0"; + case self::UTF16LE: + $data .= Transform::toString16 + ($this->_description, $this->_encoding == self::UTF16 ? + Transform::MACHINE_ENDIAN_ORDER : Transform::LITTLE_ENDIAN_ORDER) . + "\0\0"; break; case self::UTF16BE: $data .= Transform::toString16BE($this->_description) . "\0\0"; break; - case self::UTF16LE: - $data .= Transform::toString16LE($this->_description) . "\0\0"); - break; default: $data .= $this->_description . "\0"; } $this->setData($data . $this->_link); - return parent::__toString(); + return ID3_Frame::__toString(); } } diff --git a/src/ID3/Object.php b/src/ID3/Object.php index 487059f..59adde7 100644 --- a/src/ID3/Object.php +++ b/src/ID3/Object.php @@ -41,6 +41,7 @@ * @package php-reader * @subpackage ID3 * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -151,12 +152,8 @@ abstract class ID3_Object */ protected function encodeSynchsafe32($val) { - if (!isset($this->_options["version"]) || $this->_options["version"] >= 4) { - for ($i = 0, $mask = 0xffffff00; $i < 4; $i++, $mask <<= 8) - $val = ($val << 1 & $mask) | ($val << 1 & ~$mask) >> 1; - return $val & 0x7fffffff; - } - return $val; + return ($val & 0x7f) | ($val & 0x3f80) << 1 | + ($val & 0x1fc000) << 2 | ($val & 0xfe00000) << 3; } /** @@ -167,9 +164,46 @@ abstract class ID3_Object */ protected function decodeSynchsafe32($val) { - if (!isset($this->_options["version"]) || $this->_options["version"] >= 4) - for ($i = 0, $mask = 0xff000000; $i < 3; $i++, $mask >>= 8) - $val = ($val & $mask) >> 1 | ($val & ~$mask); - return $val; + return ($val & 0x7f) | ($val & 0x7f00) >> 1 | + ($val & 0x7f0000) >> 2 | ($val & 0x7f000000) >> 3; + } + + /** + * Splits UTF-16 formatted binary data up according to null terminators + * residing in the string, up to a given limit. + * + * @param string $value The input string. + * @return Array + */ + protected function explodeString16($value, $limit = null) + { + $i = 0; + $array = array(); + while (count($array) < $limit - 1 || $limit === null) { + $start = $i; + do { + $i = strpos($value, "\x00\x00", $i); + if ($i === false) { + $array[] = substr($value, $start); + return $array; + } + } while ($i & 0x1 != 0 && $i++); // make sure its aligned + $array[] = substr($value, $start, $i - $start); + $i += 2; + } + $array[] = substr($value, $i); + return $array; + } + + /** + * Splits UTF-8 or ISO-8859-1 formatted binary data according to null + * terminators residing in the string, up to a given limit. + * + * @param string $value The input string. + * @return Array + */ + protected function explodeString8($value, $limit = null) + { + return preg_split("/\\x00/", $value, $limit); } } diff --git a/src/Transform.php b/src/Transform.php index 56bb3c2..bab345e 100644 --- a/src/Transform.php +++ b/src/Transform.php @@ -4,7 +4,7 @@ * * Copyright (c) 2006-2008 The PHP Reader Project Workgroup. All rights * reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * @@ -37,9 +37,10 @@ /** * An utility class to perform simple byte transformations on data. - * + * * @package php-reader * @author Sven Vollbehr + * @author Ryan Butterfield * @copyright Copyright (c) 2006-2008 The PHP Reader Project Workgroup * @license http://code.google.com/p/php-reader/wiki/License New BSD License * @version $Rev$ @@ -50,12 +51,32 @@ final class Transform const MACHINE_ENDIAN_ORDER = 0; const LITTLE_ENDIAN_ORDER = 1; const BIG_ENDIAN_ORDER = 2; - + /** * Default private constructor for a static class. */ private function __construct() {} + /** + * Returns whether the current machine endian order is little endian. + * + * @return boolean + */ + public static function isLittleEndian() + { + return self::fromInt32("\x01\x00\x00\x00") == 1; + } + + /** + * Returns whether the current machine endian order is big endian. + * + * @return boolean + */ + public static function isBigEndian() + { + return self::fromInt32("\x00\x00\x00\x01") == 1; + } + /** * Returns 64-bit float as little-endian ordered binary data string. * @@ -66,7 +87,7 @@ final class Transform { return pack("V*", $value & 0xffffffff, $value / (0xffffffff+1)); } - + /** * Returns little-endian ordered binary data as 64-bit float. PHP does not * support 64-bit integers as the long integer is of 32-bits but using @@ -82,7 +103,7 @@ final class Transform return ($hihi * (0xffff+1) + $hilo) * (0xffffffff+1) + ($lohi * (0xffff+1) + $lolo); } - + /** * Returns 64-bit float as big-endian ordered binary data string. * @@ -93,7 +114,7 @@ final class Transform { return pack("N*", $value / (0xffffffff+1), $value & 0xffffffff); } - + /** * Returns big-endian ordered binary data as 64-bit float. PHP does not * support 64-bit integers as the long integer is of 32-bits but using @@ -109,7 +130,7 @@ final class Transform return ($hihi * (0xffff+1) + $hilo) * (0xffffffff+1) + ($lohi * (0xffff+1) + $lolo); } - + /** * Returns signed 32-bit integer as machine-endian ordered binary data. * @@ -120,10 +141,10 @@ final class Transform { return pack("l*", $value); } - + /** * Returns machine-endian ordered binary data as signed 32-bit integer. - * + * * @param string $value The binary data string. * @return integer */ @@ -132,7 +153,7 @@ final class Transform list(, $int) = unpack("l*", $value); return $int; } - + /** * Returns signed 32-bit integer as little-endian ordered binary data. * @@ -141,26 +162,26 @@ final class Transform */ public static function toInt32LE($value) { - if (self::fromInt32("\x00\x00\x00\x01") == 1) + if (self::isBigEndian()) return strrev(self::toInt32($value)); - else + else return self::toInt32($value); } - + /** * Returns little-endian ordered binary data as signed 32-bit integer. - * + * * @param string $value The binary data string. * @return integer */ public static function fromInt32LE($value) { - if (self::fromInt32("\x00\x00\x00\x01") == 1) + if (self::isBigEndian()) return self::fromInt32(strrev($value)); else return self::fromInt32($value); } - + /** * Returns signed 32-bit integer as big-endian ordered binary data. * @@ -169,26 +190,26 @@ final class Transform */ public static function toInt32BE($value) { - if (self::fromInt32("\x00\x00\x00\x01") == 1) + if (self::isBigEndian()) return self::toInt32($value); - else + else return strrev(self::toInt32($value)); } - + /** * Returns big-endian ordered binary data as signed 32-bit integer. - * + * * @param string $value The binary data string. * @return integer */ public static function fromInt32BE($value) { - if (self::fromInt32("\x00\x00\x00\x01") == 1) + if (self::isBigEndian()) return self::fromInt32($value); else return self::fromInt32(strrev($value)); } - + /** * Returns unsigned 32-bit integer as little-endian ordered binary data. * @@ -199,7 +220,7 @@ final class Transform { return pack("V*", $value); } - + /** * Returns little-endian ordered binary data as unsigned 32-bit integer. * @@ -208,10 +229,15 @@ final class Transform */ public static function fromUInt32LE($value) { - list(, $lo, $hi) = unpack("v*", $value); - return $hi * (0xffff+1) + $lo; // eq $hi << 16 | $lo + if (PHP_INT_SIZE < 8) { + list(, $lo, $hi) = unpack("v*", $value); + return $hi * (0xffff+1) + $lo; // eq $hi << 16 | $lo + } else { + list(, $int) = unpack("V*", $value); + return $int; + } } - + /** * Returns unsigned 32-bit integer as big-endian ordered binary data. * @@ -222,7 +248,7 @@ final class Transform { return pack("N*", $value); } - + /** * Returns big-endian ordered binary data as unsigned 32-bit integer. * @@ -231,10 +257,15 @@ final class Transform */ public static function fromUInt32BE($value) { - list(, $hi, $lo) = unpack("n*", $value); - return $hi * (0xffff+1) + $lo; // eq $hi << 16 | $lo + if (PHP_INT_SIZE < 8) { + list(, $hi, $lo) = unpack("n*", $value); + return $hi * (0xffff+1) + $lo; // eq $hi << 16 | $lo + } else { + list(, $int) = unpack("N*", $value); + return $int; + } } - + /** * Returns signed 16-bit integer as machine endian ordered binary data. * @@ -245,7 +276,7 @@ final class Transform { return pack("s*", $value); } - + /** * Returns machine endian ordered binary data as signed 16-bit integer. * @@ -257,7 +288,7 @@ final class Transform list(, $int) = unpack("s*", $value); return $int; } - + /** * Returns signed 16-bit integer as little-endian ordered binary data. * @@ -266,12 +297,12 @@ final class Transform */ public static function toInt16LE($value) { - if (self::fromInt16("\x00\x01") == 1) + if (self::isBigEndian()) return strrev(self::toInt16($value)); - else + else return self::toInt16($value); } - + /** * Returns little-endian ordered binary data as signed 16-bit integer. * @@ -280,12 +311,12 @@ final class Transform */ public static function fromInt16LE($value) { - if (self::fromInt16("\x00\x01") == 1) + if (self::isBigEndian()) return self::fromInt16(strrev($value)); else return self::fromInt16($value); } - + /** * Returns signed 16-bit integer as big-endian ordered binary data. * @@ -294,12 +325,12 @@ final class Transform */ public static function toInt16BE($value) { - if (self::fromInt16("\x00\x01") == 1) + if (self::isBigEndian()) return self::toInt16($value); - else + else return strrev(self::toInt16($value)); } - + /** * Returns big-endian ordered binary data as signed 16-bit integer. * @@ -308,26 +339,27 @@ final class Transform */ public static function fromInt16BE($value) { - if (self::fromInt16("\x00\x01") == 1) + if (self::isBigEndian()) return self::fromInt16($value); else return self::fromInt16(strrev($value)); } - + /** * Returns machine endian ordered binary data as unsigned 16-bit integer. - * + * * @param string $value The binary data string. * @param integer $order The byte order of the binary data string. * @return integer */ private static function fromUInt16($value, $order = self::MACHINE_ENDIAN_ORDER) { - list(, $int) = unpack(($order == 2 ? "n" : - ($order == 1 ? "v" : "S")) . "*", $value); + list(, $int) = unpack + (($order == self::BIG_ENDIAN_ORDER ? "n" : + ($order == self::LITTLE_ENDIAN_ORDER ? "v" : "S")) . "*", $value); return $int; } - + /** * Returns unsigned 16-bit integer as little-endian ordered binary data. * @@ -338,10 +370,10 @@ final class Transform { return pack("v*", $value); } - + /** * Returns little-endian ordered binary data as unsigned 16-bit integer. - * + * * @param string $value The binary data string. * @return integer */ @@ -349,7 +381,7 @@ final class Transform { return self::fromUInt16($value, self::LITTLE_ENDIAN_ORDER); } - + /** * Returns unsigned 16-bit integer as big-endian ordered binary data. * @@ -360,10 +392,10 @@ final class Transform { return pack("n*", $value); } - + /** * Returns big-endian ordered binary data as unsigned 16-bit integer. - * + * * @param string $value The binary data string. * @return integer */ @@ -371,32 +403,135 @@ final class Transform { return self::fromUInt16($value, self::BIG_ENDIAN_ORDER); } - + /** - * Returns binary data as 8-bit integer. - * + * Returns an 8-bit integer as binary data. + * * @param integer $value The input value. * @return integer */ public static function toInt8($value) { - return chr($value); + return pack("c*", $value); } - + /** * Returns binary data as 8-bit integer. - * + * * @param string $value The binary data string. * @return integer */ public static function fromInt8($value) { - return ord($value); + list(, $int) = unpack("c*", $value); + return $int; + } + + /** + * Returns an unsigned 8-bit integer as binary data. + * + * @param integer $value The input value. + * @return integer + */ + public static function toUInt8($value) + { + return pack("C*", $value); + } + + /** + * Returns binary data as an unsigned 8-bit integer. + * + * @param string $value The binary data string. + * @return integer + */ + public static function fromUInt8($value) + { + list(, $int) = unpack("C*", $value); + return $int; + } + + /** + * Returns a floating point number as machine endian ordered binary data. + * + * @param float $value The input value. + * @return string + */ + public static function toFloat($value) + { + return pack("f*", $value); + } + + /** + * Returns machine endian ordered binary data as a floating point number. + * + * @param string $value The binary data string. + * @return float + */ + public static function fromFloat($value) + { + list(, $float) = unpack("f*", $value); + return $float; + } + + /** + * Returns a floating point number as little-endian ordered binary data. + * + * @param float $value The input value. + * @return string + */ + public static function toFloatLE($value) + { + if (self::isBigEndian()) + return strrev(self::toFloat($value)); + else + return self::toFloat($value); + } + + /** + * Returns little-endian ordered binary data as a floating point number. + * + * @param string $value The binary data string. + * @return float + */ + public static function fromFloatLE($value) + { + if (self::isBigEndian()) + return self::fromFloat(strrev($value)); + else + return self::fromFloat($value); + } + + /** + * Returns a floating point number as big-endian ordered binary data. + * + * @param float $value The input value. + * @return string + */ + public static function toFloatBE($value) + { + if (self::isBigEndian()) + return self::toFloat($value); + else + return strrev(self::toFloat($value)); + } + + /** + * Returns big-endian ordered binary data as a float point number. + * + * @param string $value The binary data string. + * @return float + */ + public static function fromFloatBE($value) + { + if (self::isBigEndian()) + return self::fromFloat($value); + else + return self::fromFloat(strrev($value)); } /** * Returns string as binary data padded to given length with zeros. - * + * * @param string $value The input value. * @return string */ @@ -415,10 +550,11 @@ final class Transform { return rtrim($value, "\0"); } - + /** - * Returns machine-ordered multibyte string as machine-endian ordered binary - * data + * Returns machine-ordered multibyte string as UTF-16 defined-order binary + * data. The byte order is stored using a byte order mask (BOM) in the binary + * data string. * * @param string $value The input value. * @param integer $order The byte order of the binary data string. @@ -426,29 +562,44 @@ final class Transform */ public static function toString16($value, $order = self::MACHINE_ENDIAN_ORDER) { - $string = ""; + $format = $order == self::BIG_ENDIAN_ORDER ? "n" : + ($order == self::LITTLE_ENDIAN_ORDER ? "v" : "S"); + $string = pack($format, 0xfeff); foreach (unpack("S*", $value) as $char) - $string .= - pack(($order == 2 ? "n" : ($order == 1 ? "v" : "S")), $char); + $string .= pack($format, $char); return $string; } /** * Returns UTF-16 formatted binary data as machine-ordered multibyte string. * The byte order is determined from the byte order mark included in the - * binary data string. + * binary data string. The order parameter is updated if a BOM is found. * * @param string $value The binary data string. + * @param integer $order The endian to decode using if no BOM was found. * @return string */ - public static function fromString16($value) + public static function fromString16 + ($value, &$order = self::MACHINE_ENDIAN_ORDER) { - if ($value[0] == 0xfe && $value[1] = 0xff) - return self::fromString16BE(substr($value, 2)); - else - return self::fromString16LE(substr($value, 2)); + if (strlen($value) < 2) + return ""; + + if (ord($value[0]) == 0xfe && ord($value[1]) == 0xff) { + $order = self::BIG_ENDIAN_ORDER; + return self::fromString16BE(substr($value, 2)); + } + else if (ord($value[0]) == 0xff && ord($value[1]) == 0xfe) { + $order = self::LITTLE_ENDIAN_ORDER; + return self::fromString16LE(substr($value, 2)); + } + else if ($order == self::BIG_ENDIAN_ORDER || + ($order == self::MACHINE_ENDIAN_ORDER && self::isBigEndian())) + return self::fromString16BE($value); + else + return self::fromString16LE($value); } - + /** * Returns machine-ordered multibyte string as little-endian ordered binary * data. @@ -458,12 +609,15 @@ final class Transform */ public static function toString16LE($value) { - return self::toString16($value, self::LITTLE_ENDIAN_ORDER); + $string = ""; + foreach (unpack("S*", $value) as $char) + $string .= pack("v", $char); + return $string; } - + /** * Returns little-endian ordered binary data as machine ordered multibyte - * string. + * string. Removes terminating zero. * * @param string $value The binary data string. * @return string @@ -476,7 +630,7 @@ final class Transform $string .= pack("S", $char); return $string; } - + /** * Returns machine ordered multibyte string as big-endian ordered binary data. * @@ -485,12 +639,16 @@ final class Transform */ public static function toString16BE($value) { - return self::toString16($value, self::BIG_ENDIAN_ORDER); + $string = ""; + foreach (unpack("S*", $value) as $char) + $string .= pack("n", $char); + return $string; } - + /** * Returns big-endian ordered binary data as machine ordered multibyte string. - * + * Removes terminating zero. + * * @param string $value The binary data string. * @return string */ @@ -502,10 +660,10 @@ final class Transform $string .= pack("S", $char); return $string; } - + /** * Returns hexadecimal string having high nibble first as binary data. - * + * * @param string $value The input value. * @return string */ @@ -513,22 +671,22 @@ final class Transform { return pack("H*", $value); } - + /** * Returns binary data as hexadecimal string having high nibble first. - * + * * @param string $value The binary data string. * @return string */ public static function fromHHex($value) { list($hex) = unpack("H*0", $value); - return $hex; + return $hex; } - + /** * Returns hexadecimal string having low nibble first as binary data. - * + * * @param string $value The input value. * @return string */ @@ -536,23 +694,23 @@ final class Transform { return pack("h*", $value); } - + /** * Returns binary data as hexadecimal string having low nibble first. - * + * * @param string $value The binary data string. * @return string */ public static function fromLHex($value) { list($hex) = unpack("h*0", $value); - return $hex; + return $hex; } - + /** * Returns big-endian ordered hexadecimal GUID string as little-endian ordered * binary data string. - * + * * @param string $value The input value. * @return string */ @@ -563,11 +721,11 @@ final class Transform ("V1v2N2", hexdec($C[0]), hexdec($C[1]), hexdec($C[2]), hexdec($C[3] . substr($C[4], 0, 4)), hexdec(substr($C[4], 4))); } - + /** * Returns the little-endian ordered binary data as big-endian ordered * hexadecimal GUID string. - * + * * @param string $value The binary data string. * @return string */ @@ -576,11 +734,11 @@ final class Transform $C = @unpack("V1V/v2v/N2N", $value); list($hex) = @unpack("H*0", pack ("NnnNN", $C["V"], $C["v1"], $C["v2"], $C["N1"], $C["N2"])); - + /* Fixes a bug in PHP versions earlier than Jan 25 2006 */ if (implode("", unpack("H*", pack("H*", "a"))) == "a00") $hex = substr($hex, 0, -1); - + return preg_replace ("/^(.{8})(.{4})(.{4})(.{4})/", "\\1-\\2-\\3-\\4-", $hex); }