Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include <memory.h>
00029 #include "tag_impl.h"
00030 #include "helpers.h"
00031 #include "writers.h"
00032 #include "id3/io_decorators.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
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
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
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
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
00197 if (! _is_padded)
00198 {
00199 return 0;
00200 }
00201
00202
00203
00204
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
00217
00218
00219 tempSize = ((tempSize / ID3_PADMULTIPLE) + 1) * ID3_PADMULTIPLE;
00220
00221
00222 newSize = tempSize - ID3_GetDataSize(*this) - this->GetAppendedBytes () -
00223 ID3_TagHeader::SIZE;
00224 }
00225
00226 return newSize - curSize;
00227 }
00228