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