Add basic ID3v2 write support, add unit tests
git-svn-id: http://php-reader.googlecode.com/svn/trunk@64 51a70ab9-7547-0410-9469-37e369ee0574
This commit is contained in:
@@ -69,4 +69,11 @@ interface ID3_Encoding
|
||||
* @return integer
|
||||
*/
|
||||
public function getEncoding();
|
||||
|
||||
/**
|
||||
* Sets the text encoding.
|
||||
*
|
||||
* @param integer $encoding The text encoding.
|
||||
*/
|
||||
public function setEncoding($encoding);
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once("Object.php");
|
||||
require_once("ID3/Object.php");
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
@@ -96,7 +96,7 @@ final class ID3_ExtendedHeader extends ID3_Object
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
$offset = $this->_reader->offset;
|
||||
$offset = $this->_reader->getOffset();
|
||||
$this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
|
||||
$this->_reader->skip(1);
|
||||
$this->_flags = $this->_reader->readInt8();
|
||||
@@ -105,7 +105,7 @@ final class ID3_ExtendedHeader extends ID3_Object
|
||||
$this->_reader->skip(1);
|
||||
if ($this->hasFlag(self::CRC32)) {
|
||||
$this->_reader->skip(1);
|
||||
$this->_crc = Transform::getInt32BE
|
||||
$this->_crc = Transform::fromInt32BE
|
||||
(($this->_reader->read(1) << 4) &
|
||||
$this->decodeSynchsafe32($this->_reader->read(4)));
|
||||
}
|
||||
@@ -114,7 +114,7 @@ final class ID3_ExtendedHeader extends ID3_Object
|
||||
$this->_restrictions = $this->_reader->readInt8(1);
|
||||
}
|
||||
|
||||
$this->_reader->skip($this->_size - $this->_reader->offset - $offset);
|
||||
$this->_reader->skip($this->_size - $this->_reader->getOffset() - $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -133,12 +133,44 @@ final class ID3_ExtendedHeader extends ID3_Object
|
||||
*/
|
||||
public function hasFlag($flag) { return ($this->_flags & $flag) == $flag; }
|
||||
|
||||
/**
|
||||
* Returns the flags byte.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getFlags($flags) { return $this->_flags; }
|
||||
|
||||
/**
|
||||
* Sets the flags byte.
|
||||
*
|
||||
* @param integer $flags The flags byte.
|
||||
*/
|
||||
public function setFlags($flags) { $this->_flags = $flags; }
|
||||
|
||||
/**
|
||||
* Returns the CRC-32 data.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getCRC() { return $this->_crc; }
|
||||
public function getCrc()
|
||||
{
|
||||
if ($this->hasFlag(self::CRC32))
|
||||
return $this->_crc;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the CRC-32 should be generated upon tag write.
|
||||
*
|
||||
* @param boolean $useCrc Whether CRC-32 should be generated
|
||||
*/
|
||||
public function setCrc($useCrc)
|
||||
{
|
||||
if ($useCrc)
|
||||
$this->setFlags($this->getFlags() | self::CDC32);
|
||||
else
|
||||
$this->setFlags($this->getFlags() & ~self::CDC32);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the restrictions. For some applications it might be desired to
|
||||
@@ -189,4 +221,30 @@ final class ID3_ExtendedHeader extends ID3_Object
|
||||
* @return integer
|
||||
*/
|
||||
public function getRestrictions() { return $this->_restrictions; }
|
||||
|
||||
/**
|
||||
* Sets the restrictions byte. See {@link #getRestrictions} for more.
|
||||
*
|
||||
* @param integer $restrictions The restrictions byte.
|
||||
*/
|
||||
public function setRestrictions($restrictions)
|
||||
{
|
||||
$this->_restrictions = $restrictions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the header raw data.
|
||||
*
|
||||
* @todo CRC must use safesynch
|
||||
* @return string
|
||||
*/
|
||||
public function toString()
|
||||
{
|
||||
return Transform::toUInt32BE($this->encodeSynchsafe32($this->_size)) .
|
||||
Transform::toInt8(1) . Transform::toInt8($this->_flags) .
|
||||
($this->hasFlag(self::UPDATE) ? "\0" : "") .
|
||||
($this->hasFlag(self::CRC32) ? Transform::toInt8(5) . $this->_crc : "") .
|
||||
($this->hasFlag(self::RESTRICTED) ?
|
||||
Transform::toInt8(1) . Transform::toInt8($this->_restrictions) : "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once("Object.php");
|
||||
require_once("ID3/Object.php");
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
@@ -117,17 +117,17 @@ class ID3_Frame extends ID3_Object
|
||||
private $_identifier;
|
||||
|
||||
/** @var integer */
|
||||
private $_size;
|
||||
private $_size = 0;
|
||||
|
||||
/** @var integer */
|
||||
private $_flags;
|
||||
private $_flags = 0;
|
||||
|
||||
/**
|
||||
* Raw content read from the frame.
|
||||
* Raw content of the frame.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_data;
|
||||
protected $_data = "";
|
||||
|
||||
/**
|
||||
* Constructs the class with given parameters and reads object related data
|
||||
@@ -136,14 +136,18 @@ class ID3_Frame extends ID3_Object
|
||||
* @todo Only limited subset of flags are processed.
|
||||
* @param Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
public function __construct($reader = null)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
$this->_identifier = $this->_reader->readString8(4);
|
||||
$this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
|
||||
$this->_flags = $this->_reader->readUInt16BE();
|
||||
$this->_data = $this->_reader->read($this->_size);
|
||||
|
||||
if ($reader === null) {
|
||||
$this->_identifier = substr(get_class($this), -4);
|
||||
} else {
|
||||
$this->_identifier = $this->_reader->readString8(4);
|
||||
$this->_size = $this->decodeSynchsafe32($this->_reader->readUInt32BE());
|
||||
$this->_flags = $this->_reader->readUInt16BE();
|
||||
$this->_data = $this->_reader->read($this->_size);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,18 +189,35 @@ class ID3_Frame extends ID3_Object
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getFlags($flags)
|
||||
{
|
||||
return $this->_flags;
|
||||
}
|
||||
public function getFlags($flags) { return $this->_flags; }
|
||||
|
||||
/**
|
||||
* Sets the frame flags byte.
|
||||
*
|
||||
* @param string $flags The flags byte.
|
||||
*/
|
||||
public function setFlags($flags)
|
||||
public function setFlags($flags) { $this->_flags = $flags; }
|
||||
|
||||
/**
|
||||
* Sets the frame raw data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function setData($data)
|
||||
{
|
||||
$this->_flags = $flags;
|
||||
$this->_data = $data;
|
||||
$this->_size = strlen($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the frame raw data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return Transform::toString8(substr($this->_identifier, 0, 4), 4) .
|
||||
Transform::toUInt32BE($this->encodeSynchsafe32($this->_size)) .
|
||||
Transform::toUInt16BE($this->_flags) . $this->_data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,10 +59,12 @@ abstract class ID3_Frame_AbstractLink extends ID3_Frame
|
||||
*
|
||||
* @param Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
public function __construct($reader = null)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
$this->_link = preg_split("/\\x00/", $this->_data, 1);
|
||||
|
||||
if ($reader !== null)
|
||||
$this->_link = preg_split("/\\x00/", $this->_data, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,4 +73,22 @@ abstract class ID3_Frame_AbstractLink extends ID3_Frame
|
||||
* @return string
|
||||
*/
|
||||
public function getLink() { return $this->_link; }
|
||||
|
||||
/**
|
||||
* Sets the link.
|
||||
*
|
||||
* @param string $link The link.
|
||||
*/
|
||||
public function setLink($link) { $this->_link = $link; }
|
||||
|
||||
/**
|
||||
* Returns the frame raw data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$this->setData($link);
|
||||
return parent::__toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame
|
||||
implements ID3_Encoding
|
||||
{
|
||||
/** @var integer */
|
||||
private $_encoding;
|
||||
private $_encoding = ID3_Encoding::UTF8;
|
||||
|
||||
/** @var string */
|
||||
private $_text;
|
||||
@@ -64,10 +64,13 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame
|
||||
*
|
||||
* @param Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
public function __construct($reader = null)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
|
||||
if ($reader === null)
|
||||
return;
|
||||
|
||||
$this->_encoding = ord($this->_data{0});
|
||||
$this->_data = substr($this->_data, 1);
|
||||
switch ($this->_encoding) {
|
||||
@@ -91,11 +94,61 @@ abstract class ID3_Frame_AbstractText extends ID3_Frame
|
||||
* @return integer
|
||||
*/
|
||||
public function getEncoding() { return $this->_encoding; }
|
||||
|
||||
|
||||
/**
|
||||
* Sets the text encoding.
|
||||
*
|
||||
* @param integer $encoding The text encoding.
|
||||
*/
|
||||
public function setEncoding($encoding) { $this->_encoding = $encoding; };
|
||||
|
||||
/**
|
||||
* Returns the first text chunk the frame contains.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getText() { return $this->_text[0]; }
|
||||
|
||||
/**
|
||||
* Returns an array of texts the frame contains.
|
||||
*
|
||||
* @return Array
|
||||
*/
|
||||
public function getText() { return $this->_text; }
|
||||
public function getTexts() { return $this->_text; }
|
||||
|
||||
/**
|
||||
* Sets the text using given encoding.
|
||||
*
|
||||
* @param mixed $text The test string or an array of strings.
|
||||
*/
|
||||
public function setText($text, $encoding = ID3_Encoding::UTF8)
|
||||
{
|
||||
$this->_encoding = $encoding;
|
||||
$this->_text = is_array($text) ? $text : array($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the frame raw data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
$data = Transform::toInt8($this->_encoding);
|
||||
switch ($this->_encoding) {
|
||||
case self::UTF16:
|
||||
$data .= Transform::toString16(implode("\0\0", $this->_text));
|
||||
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);
|
||||
}
|
||||
$this->setData($data);
|
||||
return parent::__toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
*/
|
||||
|
||||
/**#@+ @ignore */
|
||||
require_once("Object.php");
|
||||
require_once("ID3/Object.php");
|
||||
/**#@-*/
|
||||
|
||||
/**
|
||||
@@ -72,13 +72,13 @@ final class ID3_Header extends ID3_Object
|
||||
const FOOTER = 32;
|
||||
|
||||
/** @var integer */
|
||||
private $_version;
|
||||
private $_version = 4;
|
||||
|
||||
/** @var integer */
|
||||
private $_revision;
|
||||
private $_revision = 0;
|
||||
|
||||
/** @var integer */
|
||||
private $_flags;
|
||||
private $_flags = 0;
|
||||
|
||||
/** @var integer */
|
||||
private $_size;
|
||||
@@ -89,10 +89,13 @@ final class ID3_Header extends ID3_Object
|
||||
*
|
||||
* @param Reader $reader The reader object.
|
||||
*/
|
||||
public function __construct($reader)
|
||||
public function __construct($reader = null)
|
||||
{
|
||||
parent::__construct($reader);
|
||||
|
||||
|
||||
if ($reader === null)
|
||||
return;
|
||||
|
||||
$this->_version = $this->_reader->readInt8();
|
||||
$this->_revision = $this->_reader->readInt8();
|
||||
$this->_flags = $this->_reader->readInt8();
|
||||
@@ -122,10 +125,45 @@ final class ID3_Header extends ID3_Object
|
||||
*/
|
||||
public function hasFlag($flag) { return ($this->_flags & $flag) == $flag; }
|
||||
|
||||
/**
|
||||
* Returns the flags byte.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getFlags($flags) { return $this->_flags; }
|
||||
|
||||
/**
|
||||
* Sets the flags byte.
|
||||
*
|
||||
* @param string $flags The flags byte.
|
||||
*/
|
||||
public function setFlags($flags) { $this->_flags = $flags; }
|
||||
|
||||
/**
|
||||
* Returns the tag size, excluding the header and the footer.
|
||||
*
|
||||
* @return integer
|
||||
*/
|
||||
public function getSize() { return $this->_size; }
|
||||
|
||||
/**
|
||||
* Sets the tag size, excluding the header and the footer. Called
|
||||
* automatically upon tag generation to adjust the tag size.
|
||||
*
|
||||
* @param integer $size The size of the tag, in bytes.
|
||||
*/
|
||||
public function setSize($size) { $this->_size = $size; }
|
||||
|
||||
/**
|
||||
* Returns the header/footer raw data without the identifier.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function __toString()
|
||||
{
|
||||
return Transform::toInt8($this->_version) .
|
||||
Transform::toInt8($this->_revision) .
|
||||
Transform::toInt8($this->_flags) .
|
||||
Transform::toUInt32BE($this->encodeSynchsafe32($this->_size));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,4 +59,11 @@ interface ID3_Language
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguage();
|
||||
|
||||
/**
|
||||
* Sets the text language code.
|
||||
*
|
||||
* @param string $language The text language code.
|
||||
*/
|
||||
public function setLanguage($language);
|
||||
}
|
||||
|
||||
@@ -63,4 +63,11 @@ interface ID3_Timing
|
||||
* @return integer
|
||||
*/
|
||||
public function getFormat();
|
||||
|
||||
/**
|
||||
* Sets the timing format.
|
||||
*
|
||||
* @param integer $format The timing format.
|
||||
*/
|
||||
public function setFormat($format);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user