/src/Zend/Media/Asf/Object/MetadataLibrary.php

http://php-reader.googlecode.com/ · PHP · 256 lines · 142 code · 11 blank · 103 comment · 17 complexity · 52e848819e582d4b71cb21fda9fa8d6f MD5 · raw file

  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Media
  17. * @subpackage ASF
  18. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: MetadataLibrary.php 177 2010-03-09 13:13:34Z svollbehr $
  21. */
  22. /**#@+ @ignore */
  23. require_once 'Zend/Media/Asf/Object.php';
  24. /**#@-*/
  25. /**
  26. * The <i>Metadata Library Object</i> lets authors store stream-based,
  27. * language-attributed, multiply defined, and large metadata attributes in a
  28. * file.
  29. *
  30. * This object supports the same types of metadata as the
  31. * <i>{@link Zend_Media_Asf_Object_Metadata Metadata Object}</i>, as well as
  32. * attributes with language IDs, attributes that are defined more than once,
  33. * large attributes, and attributes with the GUID data type.
  34. *
  35. * @todo Implement better handling of various types of attributes
  36. * according to http://msdn.microsoft.com/en-us/library/aa384495(VS.85).aspx
  37. * @category Zend
  38. * @package Zend_Media
  39. * @subpackage ASF
  40. * @author Sven Vollbehr <sven@vollbehr.eu>
  41. * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
  42. * @license http://framework.zend.com/license/new-bsd New BSD License
  43. * @version $Id: MetadataLibrary.php 177 2010-03-09 13:13:34Z svollbehr $
  44. */
  45. final class Zend_Media_Asf_Object_MetadataLibrary extends Zend_Media_Asf_Object
  46. {
  47. /** @var Array */
  48. private $_descriptionRecords = array();
  49. /**
  50. * Constructs the class with given parameters and reads object related data
  51. * from the ASF file.
  52. *
  53. * @param Zend_Io_Reader $reader The reader object.
  54. * @param Array $options The options array.
  55. */
  56. public function __construct($reader = null, &$options = array())
  57. {
  58. parent::__construct($reader, $options);
  59. if ($reader === null) {
  60. return;
  61. }
  62. $descriptionRecordsCount = $this->_reader->readUInt16LE();
  63. for ($i = 0; $i < $descriptionRecordsCount; $i++) {
  64. $descriptionRecord = array
  65. ('languageIndex' => $this->_reader->readUInt16LE(),
  66. 'streamNumber' => $this->_reader->readUInt16LE());
  67. $nameLength = $this->_reader->readUInt16LE();
  68. $dataType = $this->_reader->readUInt16LE();
  69. $dataLength = $this->_reader->readUInt32LE();
  70. $descriptionRecord['name'] = iconv
  71. ('utf-16le', $this->getOption('encoding'),
  72. $this->_reader->readString16($nameLength));
  73. switch ($dataType) {
  74. case 0: // Unicode string
  75. $descriptionRecord['data'] = iconv
  76. ('utf-16le', $this->getOption('encoding'),
  77. $this->_reader->readString16($dataLength));
  78. break;
  79. case 1: // BYTE array
  80. $descriptionRecord['data'] =
  81. $this->_reader->read($dataLength);
  82. break;
  83. case 2: // BOOL
  84. $descriptionRecord['data'] =
  85. $this->_reader->readUInt16LE() == 1;
  86. break;
  87. case 3: // DWORD
  88. $descriptionRecord['data'] = $this->_reader->readUInt32LE();
  89. break;
  90. case 4: // QWORD
  91. $descriptionRecord['data'] = $this->_reader->readInt64LE();
  92. break;
  93. case 5: // WORD
  94. $descriptionRecord['data'] = $this->_reader->readUInt16LE();
  95. break;
  96. case 6: // GUID
  97. $descriptionRecord['data'] = $this->_reader->readGuid();
  98. break;
  99. default:
  100. break;
  101. }
  102. $this->_descriptionRecords[] = $descriptionRecord;
  103. }
  104. }
  105. /**
  106. * Returns an array of description records. Each record consists of the
  107. * following keys.
  108. *
  109. * o languageIndex -- Specifies the index into the
  110. * {@link LanguageList Language List Object} that identifies the
  111. * language of this attribute. If there is no <i>Language List
  112. * Object</i> present, this field is zero.
  113. *
  114. * o streamNumber -- Specifies whether the entry applies to a specific
  115. * digital media stream or whether it applies to the whole file. A value
  116. * of 0 in this field indicates that it applies to the whole file;
  117. * otherwise, the entry applies only to the indicated stream number.
  118. * Valid values are between 1 and 127.
  119. *
  120. * o name -- Specifies the name that identifies the attribute being
  121. * described.
  122. *
  123. * o data -- Specifies the actual metadata being stored.
  124. *
  125. * @return Array
  126. */
  127. public function getDescriptionRecords()
  128. {
  129. return $this->_descriptionRecords;
  130. }
  131. /**
  132. * Sets an array of description records. Each record must consist of the
  133. * following keys.
  134. *
  135. * o languageIndex -- Specifies the index into the <i>Language List
  136. * Object</i> that identifies the language of this attribute. If there
  137. * is no <i>Language List Object</i> present, this field is zero.
  138. *
  139. * o streamNumber -- Specifies whether the entry applies to a specific
  140. * digital media stream or whether it applies to the whole file. A value
  141. * of 0 in this field indicates that it applies to the whole file;
  142. * otherwise, the entry applies only to the indicated stream number.
  143. * Valid values are between 1 and 127.
  144. *
  145. * o name -- Specifies the name that identifies the attribute being
  146. * described.
  147. *
  148. * o data -- Specifies the actual metadata being stored.
  149. *
  150. * @return Array
  151. */
  152. public function setDescriptionRecords($descriptionRecords)
  153. {
  154. $this->_descriptionRecords = $descriptionRecords;
  155. }
  156. /**
  157. * Writes the object data.
  158. *
  159. * @param Zend_Io_Writer $writer The writer object.
  160. * @return void
  161. */
  162. public function write($writer)
  163. {
  164. require_once 'Zend/Io/StringWriter.php';
  165. $descriptionRecordsCount = count($this->_descriptionRecords);
  166. $descriptionRecordsWriter = new Zend_Io_StringWriter();
  167. for ($i = 0; $i < $descriptionRecordsCount; $i++) {
  168. $descriptionRecordsWriter
  169. ->writeUInt16LE
  170. ($this->_descriptionRecords[$i]['languageIndex'])
  171. ->writeUInt16LE
  172. ($this->_descriptionRecords[$i]['streamNumber'])
  173. ->writeUInt16LE(strlen($name = iconv
  174. ($this->getOption('encoding'), 'utf-16le',
  175. $this->_descriptionRecords[$i]['name']) . "\0\0"));
  176. if (is_string($this->_descriptionRecords[$i]['data'])) {
  177. $chunks = array();
  178. if (preg_match
  179. ("/^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{1" .
  180. "2}$/i", $this->_descriptionRecords[$i]['data'])) {
  181. $descriptionRecordsWriter
  182. ->writeUInt16LE(6)
  183. ->writeUInt32LE(16)
  184. ->write($name)
  185. ->writeGuid($this->_descriptionRecords[$i]['data']);
  186. } else {
  187. /* There is no way to distinguish byte arrays from unicode
  188. * strings and hence the need for a list of fields of type
  189. * byte array */
  190. static $byteArray = array (
  191. "W\0M\0/\0L\0y\0r\0i\0c\0s\0_\0S\0y\0n\0c\0h\0r\0o\0n\0i\0s\0e\0d\0\0\0",
  192. "W\0M\0/\0P\0i\0c\0t\0u\0r\0e\0\0\0"
  193. ); // TODO: Add to the list if you encounter one
  194. if (in_array($name, $byteArray)) {
  195. $descriptionRecordsWriter
  196. ->writeUInt16LE(1)
  197. ->writeUInt32LE
  198. (strlen($this->_descriptionRecords[$i]['data']))
  199. ->write($name)
  200. ->write($this->_descriptionRecords[$i]['data']);
  201. } else {
  202. $value = iconv
  203. ($this->getOption('encoding'), 'utf-16le',
  204. $this->_descriptionRecords[$i]['data']);
  205. $value = ($value ? $value . "\0\0" : '');
  206. $descriptionRecordsWriter
  207. ->writeUInt16LE(0)
  208. ->writeUInt32LE(strlen($value))
  209. ->write($name)
  210. ->writeString16($value);
  211. }
  212. }
  213. } else if (is_bool($this->_descriptionRecords[$i]['data'])) {
  214. $descriptionRecordsWriter
  215. ->writeUInt16LE(2)
  216. ->writeUInt32LE(2)
  217. ->write($name)
  218. ->writeUInt16LE
  219. ($this->_descriptionRecords[$i]['data'] ? 1 : 0);
  220. } else if (is_int($this->_descriptionRecords[$i]['data'])) {
  221. $descriptionRecordsWriter
  222. ->writeUInt16LE(3)
  223. ->writeUInt32LE(4)
  224. ->write($name)
  225. ->writeUInt32LE($this->_descriptionRecords[$i]['data']);
  226. } else if (is_float($this->_descriptionRecords[$i]['data'])) {
  227. $descriptionRecordsWriter
  228. ->writeUInt16LE(4)
  229. ->writeUInt32LE(8)
  230. ->write($name)
  231. ->writeInt64LE($this->_descriptionRecords[$i]['data']);
  232. } else {
  233. // Invalid value and there is nothing to be done
  234. require_once 'Zend/Media/Asf/Exception.php';
  235. throw new Zend_Media_Asf_Exception('Invalid data type');
  236. }
  237. }
  238. $this->setSize
  239. (24 /* for header */ + 2 + $descriptionRecordsWriter->getSize());
  240. $writer->writeGuid($this->getIdentifier())
  241. ->writeInt64LE($this->getSize())
  242. ->writeUInt16LE($descriptionRecordsCount)
  243. ->write($descriptionRecordsWriter->toString());
  244. }
  245. }