void id3::v2::render(ID3_Writer& writer, const ID3_TagImpl& tag) { // There has to be at least one frame for there to be a tag... if (tag.NumFrames() == 0) { ID3D_WARNING( "id3::v2::render(): no frames to render" ); return; } ID3D_NOTICE( "id3::v2::render(): rendering" ); ID3_TagHeader hdr; hdr.SetSpec(tag.GetSpec()); hdr.SetExtended(tag.GetExtended()); hdr.SetExperimental(tag.GetExperimental()); // set up the encryption and grouping IDs // ... String frms; io::StringWriter frmWriter(frms); if (!tag.GetUnsync()) { ID3D_NOTICE( "id3::v2::render(): rendering frames" ); renderFrames(frmWriter, tag); hdr.SetUnsync(false); } else { ID3D_NOTICE( "id3::v2::render(): rendering unsynced frames" ); io::UnsyncedWriter uw(frmWriter); renderFrames(uw, tag); uw.flush(); ID3D_NOTICE( "id3::v2::render(): numsyncs = " << uw.getNumSyncs() ); hdr.SetUnsync(uw.getNumSyncs() > 0); } size_t frmSize = frms.size(); if (frmSize == 0) { ID3D_WARNING( "id3::v2::render(): rendered frame size is 0 bytes" ); return; } // zero the remainder of the buffer so that our padding bytes are zero luint nPadding = tag.PaddingSize(frmSize); ID3D_NOTICE( "id3::v2::render(): padding size = " << nPadding ); hdr.SetDataSize(frmSize + nPadding); hdr.Render(writer); writer.writeChars(frms.data(), frms.size()); for (size_t i = 0; i < nPadding; ++i) { if (writer.writeChar('\0') == ID3_Writer::END_OF_WRITER) { break; } } }
size_t ID3_TagImpl::Size() const { if (this->NumFrames() == 0) { return 0; } ID3_TagHeader hdr; hdr.SetSpec(this->GetSpec()); size_t bytesUsed = hdr.Size(); size_t frameBytes = 0; for (const_iterator cur = _frames.begin(); cur != _frames.end(); ++cur) { if (*cur) { (*cur)->SetSpec(this->GetSpec()); frameBytes += (*cur)->Size(); } } if (!frameBytes) { return 0; } bytesUsed += frameBytes; // add 30% for sync if (this->GetUnsync()) { bytesUsed += bytesUsed / 3; } bytesUsed += this->PaddingSize(bytesUsed); return bytesUsed; }