Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members  

src/tag_render.cpp

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

Generated at Sat Sep 8 15:51:10 2001 for id3lib by doxygen1.2.8 written by Dimitri van Heesch, © 1997-2001