PageRenderTime 31ms CodeModel.GetById 13ms app.highlight 12ms RepoModel.GetById 1ms app.codeStats 1ms

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