src/frame_render.cpp

Go to the documentation of this file.
00001 // $Id: frame_render.cpp,v 1.27 2002/07/31 13:45:18 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 #if defined HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031 
00032 
00033 
00034 //#include <string.h>
00035 #include <memory.h>
00036 #include <zlib.h>
00037 
00038 #include "tag.h"
00039 #include "frame_impl.h"
00040 #include "id3/io_decorators.h" //has "readers.h" "io_helpers.h" "utils.h"
00041 #include "io_strings.h"
00042 #include "io_helpers.h"
00043 
00044 using namespace dami;
00045 
00046 namespace 
00047 {
00048   void renderFields(ID3_Writer& writer, const ID3_FrameImpl& frame)
00049   {
00050     ID3_TextEnc enc = ID3TE_ASCII;
00051     for (ID3_FrameImpl::const_iterator fi = frame.begin(); fi != frame.end(); ++fi)
00052     {
00053       ID3_Field* fld = *fi;
00054       if (fld != NULL && fld->InScope(frame.GetSpec()))
00055       {
00056         if (fld->GetID() == ID3FN_TEXTENC)  
00057         {
00058           enc = static_cast<ID3_TextEnc>(fld->Get());  
00059           ID3D_NOTICE( "id3::v2::renderFields(): found encoding = " << enc );
00060         }
00061         else
00062         {
00063           fld->SetEncoding(enc);
00064         }
00065         fld->Render(writer);
00066       }
00067     }
00068   }
00069 }
00070   
00071 void ID3_FrameImpl::Render(ID3_Writer& writer) const
00072 {
00073   // Return immediately if we have no fields, which (usually) means we're
00074   // trying to render a frame which has been Cleared or hasn't been initialized
00075   if (!this->NumFields())
00076   {
00077     return;
00078   }
00079 
00080   ID3_FrameHeader hdr;
00081   
00082   const size_t hdr_size = hdr.Size();
00083 
00084   // 1.  Write out the field data to the buffer, with the assumption that
00085   //     we won't be decompressing, since this is the usual behavior
00086   String flds;
00087   io::StringWriter fldWriter(flds);
00088   size_t origSize = 0;
00089   if (!this->GetCompression())
00090   {
00091     renderFields(fldWriter, *this);
00092     origSize = flds.size();
00093     ID3D_NOTICE ( "ID3_FrameImpl::Render(): uncompressed fields" );
00094   }
00095   else
00096   {
00097     io::CompressedWriter cr(fldWriter);
00098     renderFields(cr, *this);
00099     cr.flush();
00100     origSize = cr.getOrigSize();
00101     ID3D_NOTICE ( "ID3_FrameImpl::Render(): compressed fields, orig size = " <<
00102                   origSize );
00103   }
00104 
00105   size_t fldSize = flds.size();
00106   ID3D_NOTICE ( "ID3_FrameImpl::Render(): field size = " << fldSize );
00107 // No need to not write empty frames, why would we not? They can be used to fill up padding space
00108 // which is even recommended in the id3 spec.
00109 //  if (fldSize == 0)
00110 //  {
00111 //    ID3D_WARNING ( "ID3_FrameImpl::Render(): no field data" );
00112 //    return;
00113 //  }
00114   
00115   // determine which flags need to be set
00116   uchar eID = this->GetEncryptionID(), gID = this->GetGroupingID();
00117   ID3_FrameID fid = this->GetID();
00118   if (fid == ID3FID_NOFRAME)
00119   {
00120     const char *tid = this->GetTextID();
00121     hdr.SetUnknownFrame(tid);
00122   }
00123   else
00124   {
00125     hdr.SetFrameID(fid);
00126   }
00127   hdr.SetEncryption(eID > 0);
00128   hdr.SetGrouping(gID > 0);
00129   hdr.SetCompression(origSize > fldSize);
00130   hdr.SetDataSize(fldSize + ((hdr.GetCompression() ? 4 : 0) + 
00131                              (hdr.GetEncryption()  ? 1 : 0) + 
00132                              (hdr.GetGrouping()    ? 1 : 0)));
00133 
00134   // write out the header
00135   hdr.Render(writer);
00136 
00137   if (fldSize != 0)
00138   {
00139     // No-man's land!  Not part of the header, not part of the data
00140     if (hdr.GetCompression())
00141     {
00142       io::writeBENumber(writer, origSize, sizeof(uint32));
00143       ID3D_NOTICE( "ID3_FrameImpl::Render(): frame is compressed, wrote origSize = " << origSize );
00144     }
00145     if (hdr.GetEncryption())
00146     {
00147       writer.writeChar(eID);
00148       ID3D_NOTICE( "ID3_FrameImpl::Render(): frame is compressed, encryption id = " << eID );
00149     }
00150     if (hdr.GetGrouping())
00151     {
00152       writer.writeChar(gID);
00153       ID3D_NOTICE( "ID3_FrameImpl::Render(): frame is compressed, grouping id = " << gID );
00154     }
00155 
00156     // Write the field data
00157     writer.writeChars(flds.data(), fldSize);
00158   }
00159   _changed = false;
00160 }
00161 

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