/** * Writes the tag data. * * @param HausDesign_Io_Writer $writer The writer object. * @return void */ private function _writeData($writer) { $this->clearOption('unsynchronisation'); $buffer = new HausDesign_Io_StringWriter(); foreach ($this->_frames as $frames) { foreach ($frames as $frame) { $frame->write($buffer); } } $frameData = $buffer->toString(); $frameDataLength = strlen($frameData); $paddingLength = 0; // ID3v2.4.0 supports frame level unsynchronisation while // ID3v2.3.0 supports only tag level unsynchronisation. if ($this->getOption('version', 4) < 4 && $this->getOption('compat', false) !== true) { $frameData = $this->_encodeUnsynchronisation($frameData); if (($len = strlen($frameData)) != $frameDataLength) { $frameDataLength = $len; $this->_header->setFlags($this->_header->getFlags() | HausDesign_Media_Id3_Header::UNSYNCHRONISATION); } else { $this->_header->setFlags($this->_header->getFlags() & ~HausDesign_Media_Id3_Header::UNSYNCHRONISATION); } } // The tag padding is calculated as follows. If the tag can be written // in the space of the previous tag, the remaining space is used for // padding. If there is no previous tag or the new tag is bigger than // the space taken by the previous tag, the padding is a constant // 4096 bytes. if ($this->hasFooter() === false) { if ($this->_reader !== null && $frameDataLength < $this->_header->getSize()) { $paddingLength = $this->_header->getSize() - $frameDataLength; } else { $paddingLength = 4096; } } /* ID3v2.4.0 CRC calculated w/ padding */ if ($this->getOption('version', 4) >= 4) { $frameData = str_pad($frameData, $frameDataLength += $paddingLength, ""); } $extendedHeaderData = ''; $extendedHeaderDataLength = 0; if ($this->hasExtendedHeader()) { $this->_extendedHeader->setPadding($paddingLength); if ($this->_extendedHeader->hasFlag(HausDesign_Media_Id3_ExtendedHeader::CRC32)) { $crc = crc32($frameData); if ($crc & 0x80000000) { $crc = -(($crc ^ 0xffffffff) + 1); } $this->_extendedHeader->setCrc($crc); } $buffer = new HausDesign_Io_StringWriter(); $this->_extendedHeader->write($buffer); $extendedHeaderData = $buffer->toString(); $extendedHeaderDataLength = strlen($extendedHeaderData); } /* ID3v2.3.0 CRC calculated w/o padding */ if ($this->getOption('version', 4) < 4) { $frameData = str_pad($frameData, $frameDataLength += $paddingLength, ""); } $this->_header->setSize($extendedHeaderDataLength + $frameDataLength); $writer->write('ID3'); $this->_header->write($writer); $writer->write($extendedHeaderData); $writer->write($frameData); if ($this->hasFooter()) { $writer->write('3DI'); $this->_footer->write($writer); } }
/** * Writes the frame data with the header. * * @param HausDesign_Io_Writer $writer The writer object. * @return void */ public function write($writer) { /* ID3v2.3.0 Flags; convert from 2.4.0 format */ if ($this->getOption('version', 4) < 4) { $flags = 0; if ($this->hasFlag(self::DISCARD_ON_TAGCHANGE)) { $flags = $flags | 0x8000; } if ($this->hasFlag(self::DISCARD_ON_FILECHANGE)) { $flags = $flags | 0x4000; } if ($this->hasFlag(self::READ_ONLY)) { $flags = $flags | 0x2000; } if ($this->hasFlag(self::COMPRESSION)) { $flags = $flags | 0x80; } if ($this->hasFlag(self::ENCRYPTION)) { $flags = $flags | 0x40; } if ($this->hasFlag(self::GROUPING_IDENTITY)) { $flags = $flags | 0x20; } } else { $flags = $this->_flags; } $this->_writeData($buffer = new HausDesign_Io_StringWriter()); $data = $buffer->toString(); $size = $this->_size = strlen($data); // ID3v2.4.0 supports frame level unsynchronisation. The corresponding // option is set to true when any of the frames use the // unsynchronisation scheme. The usage is denoted by // HausDesign_Media_Id3_Header flag that is set accordingly upon file write. if ($this->getOption('version', 4) >= 4) { $data = $this->_encodeUnsynchronisation($data); if (($dataLength = strlen($data)) != $size) { $size = 4 + $dataLength; $flags |= self::DATA_LENGTH_INDICATOR | self::UNSYNCHRONISATION; $this->setOption('unsynchronisation', true); } else { $flags &= ~(self::DATA_LENGTH_INDICATOR | self::UNSYNCHRONISATION); } } $writer->writeString8(substr($this->_identifier, 0, 4), 4, " ")->writeUInt32BE($this->getOption('version', 4) < 4 ? $size : $this->_encodeSynchsafe32($size))->writeUInt16BE($flags); if (($flags & self::DATA_LENGTH_INDICATOR) == self::DATA_LENGTH_INDICATOR) { $writer->writeUInt32BE($this->getOption('version', 4) < 4 ? $this->_size : $this->_encodeSynchsafe32($this->_size)); } $writer->write($data); }
/** * Writes the header data. * * @param HausDesign_Io_Writer $writer The writer object. * @return void */ public function write($writer) { /* ID3v2.3.0 ExtendedHeader */ if ($this->getOption('version', 4) < 4) { $writer->writeUInt32BE($this->_size)->writeUInt16BE($this->hasFlag(self::CRC32) ? 0x8000 : 0)->writeUInt32BE($this->_padding); if ($this->hasFlag(self::CRC32)) { $writer->writeUInt32BE($this->_crc); } } else { $writer->writeUInt32BE($this->_encodeSynchsafe32($this->_size))->writeInt8(1)->writeInt8($this->_flags); if ($this->hasFlag(self::UPDATE)) { $writer->write(""); } if ($this->hasFlag(self::CRC32)) { $writer->writeInt8(5)->writeInt8($this->_crc & 0xf0000000 >> 28 & 0xf)->writeUInt32BE($this->_encodeSynchsafe32($this->_crc)); } if ($this->hasFlag(self::RESTRICTED)) { $writer->writeInt8(1)->writeInt8($this->_restrictions); } } }
/** * Writes the frame raw data without the header. * * @param HausDesign_Io_Writer $writer The writer object. * @return void */ protected function _writeData($writer) { $writer->writeUInt8($this->_encoding)->write($this->_language); switch ($this->_encoding) { case self::UTF16LE: $writer->writeString16($this->_text, HausDesign_Io_Writer::LITTLE_ENDIAN_ORDER); break; case self::UTF16: // break intentionally omitted // break intentionally omitted case self::UTF16BE: // break intentionally omitted // break intentionally omitted default: $writer->write($this->_text); break; } }
/** * Writes the frame raw data without the header. * * @param HausDesign_Io_Writer $writer The writer object. * @return void */ protected function _writeData($writer) { $writer->write($this->_link); }
/** * Writes the frame raw data without the header. * * @param HausDesign_Io_Writer $writer The writer object. * @return void */ protected function _writeData($writer) { $writer->writeUInt8($this->_encoding); switch ($this->_encoding) { case self::UTF16LE: $writer->writeString16($this->_description, HausDesign_Io_Writer::LITTLE_ENDIAN_ORDER, 1); break; case self::UTF16: // break intentionally omitted // break intentionally omitted case self::UTF16BE: $writer->writeString16($this->_description, null, 1); break; default: $writer->writeString8($this->_description, 1); break; } $writer->write($this->_link); }
/** * Writes the frame raw data without the header. * * @param HausDesign_Io_Writer $writer The writer object. * @return void */ protected function _writeData($writer) { $writer->writeUInt8($this->_encoding); switch ($this->_encoding) { case self::UTF16LE: $count = count($this->_text); for ($i = 0; $i < $count; $i++) { $writer->writeString16($text, HausDesign_Io_Writer::LITTLE_ENDIAN_ORDER, $i == $count ? null : 1); } break; case self::UTF16: // break intentionally omitted // break intentionally omitted case self::UTF16BE: $writer->write(implode("", $this->_text)); break; default: $writer->write(implode("", $this->_text)); break; } }
/** * Writes the frame raw data without the header. * * @param HausDesign_Io_Writer $writer The writer object. * @return void */ protected function _writeData($writer) { $tmp = new HausDesign_Io_StringWriter(); $tmp->writeUInt32BE($this->_bufferSize); $writer->write(substr($tmp->toString(), 1, 3))->writeInt8($this->_infoFlags)->writeInt32BE($this->_offset); }