src/tag_render.cpp

Go to the documentation of this file.
00001 // $Id: tag_render.cpp,v 1.44 2002/07/31 13:20:49 t1mpy Exp $
00002 
00003 // id3lib: a C++ library for creating and manipulating id3v1/v2 tags
00004 // Copyright 1999, 2000  Scott Thomas Haug
00005 // Copyright 2002  Thijmen Klok (thijmen@id3lib.org)
00006 
00007 // This library is free software; you can redistribute it and/or modify it
00008 // under the terms of the GNU Library General Public License as published by
00009 // the Free Software Foundation; either version 2 of the License, or (at your
00010 // option) any later version.
00011 //
00012 // This library is distributed in the hope that it will be useful, but WITHOUT
00013 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
00015 // License for more details.
00016 //
00017 // You should have received a copy of the GNU Library General Public License
00018 // along with this library; if not, write to the Free Software Foundation,
00019 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00020 
00021 // The id3lib authors encourage improvements and optimisations to be sent to
00022 // the id3lib coordinator.  Please see the README file for details on where to
00023 // send such submissions.  See the AUTHORS file for a list of people who have
00024 // contributed to id3lib.  See the ChangeLog file for a list of changes to
00025 // id3lib.  These files are distributed with id3lib at
00026 // http://download.sourceforge.net/id3lib/
00027 
00028 #include <memory.h>
00029 #include "tag_impl.h" //has <stdio.h> "tag.h" "header_tag.h" "frame.h" "field.h" "spec.h" "id3lib_strings.h" "utils.h"
00030 #include "helpers.h"
00031 #include "writers.h"
00032 #include "id3/io_decorators.h" //has "readers.h" "io_helpers.h" "utils.h"
00033 #include "io_helpers.h"
00034 #include "io_strings.h"
00035 
00036 #if defined HAVE_SYS_PARAM_H
00037 #include <sys/param.h>
00038 #endif
00039 
00040 using namespace dami;
00041 
00042 void id3::v1::render(ID3_Writer& writer, const ID3_TagImpl& tag)
00043 {
00044   writer.writeChars("TAG", 3);
00045   
00046   io::writeTrailingSpaces(writer, id3::v2::getTitle(tag),  ID3_V1_LEN_TITLE);
00047   io::writeTrailingSpaces(writer, id3::v2::getArtist(tag), ID3_V1_LEN_ARTIST);
00048   io::writeTrailingSpaces(writer, id3::v2::getAlbum(tag),  ID3_V1_LEN_ALBUM);
00049   io::writeTrailingSpaces(writer, id3::v2::getYear(tag),   ID3_V1_LEN_YEAR);
00050   
00051   size_t track = id3::v2::getTrackNum(tag);
00052   String comment = id3::v2::getV1Comment(tag);
00053   if (track > 0)
00054   {
00055     io::writeTrailingSpaces(writer, comment, ID3_V1_LEN_COMMENT - 2);
00056     writer.writeChar('\0');
00057     writer.writeChar((char) track);
00058   }
00059   else
00060   {
00061     io::writeTrailingSpaces(writer, comment, ID3_V1_LEN_COMMENT);
00062   }
00063   writer.writeChar((char) id3::v2::getGenreNum(tag));
00064 }
00065 
00066 namespace
00067 {
00068   void renderFrames(ID3_Writer& writer, const ID3_TagImpl& tag)
00069   {
00070     for (ID3_TagImpl::const_iterator iter = tag.begin(); iter != tag.end(); ++iter)
00071     {
00072       const ID3_Frame* frame = *iter;
00073       if (frame) frame->Render(writer);
00074     }
00075   }
00076 }
00077 
00078 void id3::v2::render(ID3_Writer& writer, const ID3_TagImpl& tag)
00079 {
00080   // There has to be at least one frame for there to be a tag...
00081   if (tag.NumFrames() == 0)
00082   {
00083     ID3D_WARNING( "id3::v2::render(): no frames to render" );
00084     return;
00085   }
00086   
00087   ID3D_NOTICE( "id3::v2::render(): rendering" );
00088   ID3_TagHeader hdr;
00089   hdr.SetSpec(tag.GetSpec());
00090   hdr.SetExtended(tag.GetExtended());
00091   hdr.SetExperimental(tag.GetExperimental());
00092   hdr.SetFooter(tag.GetFooter());
00093     
00094   // set up the encryption and grouping IDs
00095 
00096   // ...
00097   String frms;
00098   io::StringWriter frmWriter(frms);
00099   if (!tag.GetUnsync())
00100   {
00101     ID3D_NOTICE( "id3::v2::render(): rendering frames" );
00102     renderFrames(frmWriter, tag);
00103     hdr.SetUnsync(false);
00104   }
00105   else
00106   {
00107     ID3D_NOTICE( "id3::v2::render(): rendering unsynced frames" );
00108     io::UnsyncedWriter uw(frmWriter);
00109     renderFrames(uw, tag);
00110     uw.flush();
00111     ID3D_NOTICE( "id3::v2::render(): numsyncs = " << uw.getNumSyncs() );
00112     hdr.SetUnsync(uw.getNumSyncs() > 0);
00113   }
00114   size_t frmSize = frms.size();
00115   if (frmSize == 0)
00116   {
00117     ID3D_WARNING( "id3::v2::render(): rendered frame size is 0 bytes" );
00118     return;
00119   }
00120   
00121   // zero the remainder of the buffer so that our padding bytes are zero
00122   luint nPadding = tag.PaddingSize(frmSize);
00123   ID3D_NOTICE( "id3::v2::render(): padding size = " << nPadding );
00124   
00125   hdr.SetDataSize(frmSize + tag.GetExtendedBytes() + nPadding);
00126   
00127   hdr.Render(writer);
00128 
00129   writer.writeChars(frms.data(), frms.size());
00130 
00131   for (size_t i = 0; i < nPadding; ++i)
00132   {
00133     if (writer.writeChar('\0') == ID3_Writer::END_OF_WRITER)
00134     {
00135       break;
00136     }
00137   }
00138 }
00139 
00140 size_t ID3_TagImpl::Size() const
00141 {
00142   if (this->NumFrames() == 0)
00143   {
00144     return 0;
00145   }
00146   ID3_TagHeader hdr;
00147 
00148   hdr.SetSpec(this->GetSpec());
00149   size_t bytesUsed = hdr.Size();
00150   
00151   size_t frameBytes = 0;
00152   for (const_iterator cur = _frames.begin(); cur != _frames.end(); ++cur)
00153   {
00154     if (*cur)
00155     {
00156       (*cur)->SetSpec(this->GetSpec());
00157       frameBytes += (*cur)->Size();
00158     }
00159   }
00160   
00161   if (!frameBytes)
00162   {
00163     return 0;
00164   }
00165   
00166   bytesUsed += frameBytes;
00167   // add 30% for sync
00168   if (this->GetUnsync())
00169   {
00170     bytesUsed += bytesUsed / 3;
00171   }
00172     
00173   bytesUsed += this->PaddingSize(bytesUsed);
00174   return bytesUsed;
00175 }
00176 
00177 
00178 void ID3_TagImpl::RenderExtHeader(uchar *buffer)
00179 {
00180   if (this->GetSpec() == ID3V2_3_0)
00181   {
00182   }
00183   
00184   return ;
00185 }
00186 
00187 
00188 #define ID3_PADMULTIPLE (2048)
00189 #define ID3_PADMAX  (4096)
00190 
00191 
00192 size_t ID3_TagImpl::PaddingSize(size_t curSize) const
00193 {
00194   luint newSize = 0;
00195   
00196   // if padding is switched off
00197   if (! _is_padded)
00198   {
00199     return 0;
00200   }
00201     
00202   // if the old tag was large enough to hold the new tag, then we will simply
00203   // pad out the difference - that way the new tag can be written without
00204   // shuffling the rest of the song file around
00205   if ((this->GetPrependedBytes()-ID3_TagHeader::SIZE > 0) &&
00206       (this->GetPrependedBytes()-ID3_TagHeader::SIZE >= curSize) && 
00207       (this->GetPrependedBytes()-ID3_TagHeader::SIZE - curSize) < ID3_PADMAX)
00208   {
00209     newSize = this->GetPrependedBytes()-ID3_TagHeader::SIZE;
00210   }
00211   else
00212   {
00213     luint tempSize = curSize + ID3_GetDataSize(*this) +
00214                      this->GetAppendedBytes() + ID3_TagHeader::SIZE;
00215     
00216     // this method of automatic padding rounds the COMPLETE FILE up to the
00217     // nearest 2K.  If the file will already be an even multiple of 2K (with
00218     // the tag included) then we just add another 2K of padding
00219     tempSize = ((tempSize / ID3_PADMULTIPLE) + 1) * ID3_PADMULTIPLE;
00220     
00221     // the size of the new tag is the new filesize minus the audio data
00222     newSize = tempSize - ID3_GetDataSize(*this) - this->GetAppendedBytes () -
00223               ID3_TagHeader::SIZE;
00224   }
00225   
00226   return newSize - curSize;
00227 }
00228 

Generated on Mon Aug 20 17:48:46 2007 for id3lib by  doxygen 1.5.2