diff options
Diffstat (limited to 'Src/id3v2')
38 files changed, 5868 insertions, 0 deletions
diff --git a/Src/id3v2/id3_dll.h b/Src/id3v2/id3_dll.h new file mode 100644 index 00000000..be41b871 --- /dev/null +++ b/Src/id3v2/id3_dll.h @@ -0,0 +1,180 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_DLLHEADERS_H +#define ID3LIB_DLLHEADERS_H + + +typedef unsigned char uchar; +typedef short signed int ssint; +typedef short unsigned int suint; +typedef long signed int lsint; +typedef long unsigned int luint; +typedef long double ldoub; +typedef long unsigned int * bitset; + + +struct ID3_VerInfo +{ +char name [ 30 ]; +luint version, + revision; +}; + + +enum ID3_TextEnc +{ + ID3TE_ASCII = 0, + ID3TE_UNICODE +}; + + +enum ID3_FieldID +{ + ID3FN_NOFIELD = 0, + ID3FN_TEXTENC, + ID3FN_TEXT, + ID3FN_URL, + ID3FN_DATA, + ID3FN_DESCRIPTION, + ID3FN_OWNER, + ID3FN_EMAIL, + ID3FN_RATING, + ID3FN_FILENAME, + ID3FN_LANGUAGE, + ID3FN_PICTURETYPE, + ID3FN_IMAGEFORMAT, + ID3FN_MIMETYPE, + ID3FN_COUNTER, + ID3FN_SYMBOL, + ID3FN_VOLUMEADJ, + ID3FN_NUMBITS, + ID3FN_VOLCHGRIGHT, + ID3FN_VOLCHGLEFT, + ID3FN_PEAKVOLRIGHT, + ID3FN_PEAKVOLLEFT, + + ID3FN_LASTFIELDID +}; + + +enum ID3_FrameID +{ + ID3FID_NOFRAME = 0, + ID3FID_ORIGALBUM, + ID3FID_PUBLISHER, + ID3FID_ENCODEDBY, + ID3FID_ENCODERSETTINGS, + ID3FID_ORIGFILENAME, + ID3FID_LANGUAGE, + ID3FID_PARTINSET, + ID3FID_DATE, + ID3FID_TIME, + ID3FID_RECORDINGDATES, + ID3FID_MEDIATYPE, + ID3FID_FILETYPE, + ID3FID_NETRADIOSTATION, + ID3FID_NETRADIOOWNER, + ID3FID_LYRICIST, + ID3FID_ORIGARTIST, + ID3FID_ORIGLYRICIST, + ID3FID_SUBTITLE, + ID3FID_MIXARTIST, + ID3FID_USERTEXT, + ID3FID_CONTENTGROUP, + ID3FID_TITLE, + ID3FID_LEADARTIST, + ID3FID_BAND, + ID3FID_ALBUM, + ID3FID_YEAR, + ID3FID_CONDUCTOR, + ID3FID_COMPOSER, + ID3FID_COPYRIGHT, + ID3FID_CONTENTTYPE, + ID3FID_TRACKNUM, + ID3FID_COMMENT, + ID3FID_WWWAUDIOFILE, + ID3FID_WWWARTIST, + ID3FID_WWWAUDIOSOURCE, + ID3FID_WWWCOMMERCIALINFO, + ID3FID_WWWCOPYRIGHT, + ID3FID_WWWPUBLISHER, + ID3FID_WWWPAYMENT, + ID3FID_WWWRADIOPAGE, + ID3FID_WWWUSER, + ID3FID_INVOLVEDPEOPLE, + ID3FID_UNSYNCEDLYRICS, + ID3FID_PICTURE, + ID3FID_GENERALOBJECT, + ID3FID_UNIQUEFILEID, + ID3FID_PLAYCOUNTER, + ID3FID_POPULARIMETER, + ID3FID_GROUPINGREG, + ID3FID_CRYPTOREG +}; + + +class ID3_Field; +class ID3_Frame; +class ID3_Tag; + + +void ID3_GetVersion ( ID3_VerInfo *info ); +// tag wrappers +ID3_Tag *ID3Tag_New ( void ); +void ID3Tag_Delete ( ID3_Tag *tag ); +void ID3Tag_Clear ( ID3_Tag *tag ); +bool ID3Tag_HasChanged ( ID3_Tag *tag ); +void ID3Tag_SetUnsync ( ID3_Tag *tag, bool unsync ); +void ID3Tag_SetExtendedHeader ( ID3_Tag *tag, bool ext ); +void ID3Tag_SetCompression ( ID3_Tag *tag, bool comp ); +void ID3Tag_SetPadding ( ID3_Tag *tag, bool pad ); +void ID3Tag_AddFrame ( ID3_Tag *tag, ID3_Frame *frame ); +void ID3Tag_AddFrames ( ID3_Tag *tag, ID3_Frame *frames, luint num ); +void ID3Tag_RemoveFrame ( ID3_Tag *tag, ID3_Frame *frame ); +void ID3Tag_Parse ( ID3_Tag *tag, uchar header[ ID3_TAGHEADERSIZE ], uchar *buffer ); +luint ID3Tag_Link ( ID3_Tag *tag, char *fileName ); +void ID3Tag_Update ( ID3_Tag *tag ); +void ID3Tag_Strip ( ID3_Tag *tag, bool v1Also ); +ID3_Frame *ID3Tag_FindFrameWithID ( ID3_Tag *tag, ID3_FrameID id ); +ID3_Frame *ID3Tag_FindFrameWithINT ( ID3_Tag *tag, ID3_FrameID id, ID3_FieldID fld, luint data ); +ID3_Frame *ID3Tag_FindFrameWithASCII ( ID3_Tag *tag, ID3_FrameID id, ID3_FieldID fld, char *data ); +ID3_Frame *ID3Tag_FindFrameWithUNICODE ( ID3_Tag *tag, ID3_FrameID id, ID3_FieldID fld, wchar_t *data ); +ID3_Frame *ID3Tag_GetFrameNum ( ID3_Tag *tag, luint num ); +luint ID3Tag_NumFrames ( ID3_Tag *tag ); +// frame wrappers +void ID3Frame_Clear ( ID3_Frame *frame ); +void ID3Frame_SetID ( ID3_Frame *frame, ID3_FrameID id ); +ID3_FrameID ID3Frame_GetID ( ID3_Frame *frame ); +ID3_Field *ID3Frame_GetField ( ID3_Frame *frame, ID3_FieldID name ); +// field wrappers +void ID3Field_Clear ( ID3_Field *field ); +luint ID3Field_Size ( ID3_Field *field ); +luint ID3Field_GetNumTextItems ( ID3_Field *field ); +void ID3Field_SetINT ( ID3_Field *field, luint data ); +luint ID3Field_GetINT ( ID3_Field *field ); +void ID3Field_SetUNICODE ( ID3_Field *field, wchar_t *string ); +luint ID3Field_GetUNICODE ( ID3_Field *field, wchar_t *buffer, luint maxChars, luint itemNum ); +void ID3Field_AddUNICODE ( ID3_Field *field, wchar_t *string ); +void ID3Field_SetASCII ( ID3_Field *field, char *string ); +luint ID3Field_GetASCII ( ID3_Field *field, char *buffer, luint maxChars, luint itemNum ); +void ID3Field_AddASCII ( ID3_Field *field, char *string ); +void ID3Field_SetBINARY ( ID3_Field *field, uchar *data, luint size ); +void ID3Field_GetBINARY ( ID3_Field *field, uchar *buffer, luint buffLength ); +void ID3Field_FromFile ( ID3_Field *field, char *fileName ); +void ID3Field_ToFile ( ID3_Field *field, char *fileName ); + + +#endif + + diff --git a/Src/id3v2/id3_dll_wrapper.cpp b/Src/id3v2/id3_dll_wrapper.cpp new file mode 100644 index 00000000..e8434410 --- /dev/null +++ b/Src/id3v2/id3_dll_wrapper.cpp @@ -0,0 +1,481 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include "id3_tag.h" + + +#ifdef __DLL + + +#include <string.h> + + +struct ID3_VerInfo +{ +char name [ 30 ]; +luint version, + revision; +}; + + + +// misc wrappers + +CDLLEXPORT +void ID3_GetVersion ( ID3_VerInfo *info ) +{ + info->version = ID3LIB_VER; + info->revision = ID3LIB_REV; + strcpy ( info->name, ID3LIB_NAME ); + + return; +} + + +// tag wrappers + +CDLLEXPORT +ID3_Tag *ID3Tag_New ( void ) +{ + return new ID3_Tag; +} + + +CDLLEXPORT +void ID3Tag_Delete ( ID3_Tag *tag ) +{ + if ( tag ) + delete tag; + + return; +} + + +CDLLEXPORT +void ID3Tag_Clear ( ID3_Tag *tag ) +{ + if ( tag ) + tag->Clear(); + + return; +} + + +CDLLEXPORT +bool ID3Tag_HasChanged ( ID3_Tag *tag ) +{ + bool changed = false; + + if ( tag ) + changed = tag->HasChanged(); + + return changed; +} + + +CDLLEXPORT +void ID3Tag_SetUnsync ( ID3_Tag *tag, bool unsync ) +{ + if ( tag ) + tag->SetUnsync ( unsync ); + + return; +} + + +CDLLEXPORT +void ID3Tag_SetExtendedHeader ( ID3_Tag *tag, bool ext ) +{ + if ( tag ) + tag->SetExtendedHeader ( ext ); + + return; +} + + +CDLLEXPORT +void ID3Tag_SetCompression ( ID3_Tag *tag, bool comp ) +{ + if ( tag ) + tag->SetCompression ( comp ); + + return; +} + + +CDLLEXPORT +void ID3Tag_SetPadding ( ID3_Tag *tag, bool pad ) +{ + if ( tag ) + tag->SetPadding ( pad ); + + return; +} + + +CDLLEXPORT +void ID3Tag_AddFrame ( ID3_Tag *tag, ID3_Frame *frame ) +{ + if ( tag ) + tag->AddFrame ( frame ); + + return; +} + + +CDLLEXPORT +void ID3Tag_AddFrames ( ID3_Tag *tag, ID3_Frame *frames, luint num ) +{ + if ( tag ) + tag->AddFrames ( frames, num ); + + return; +} + + +CDLLEXPORT +void ID3Tag_RemoveFrame ( ID3_Tag *tag, ID3_Frame *frame ) +{ + if ( tag ) + tag->RemoveFrame ( frame ); + + return; +} + + +CDLLEXPORT +void ID3Tag_Parse ( ID3_Tag *tag, uchar header[ ID3_TAGHEADERSIZE ], uchar *buffer ) +{ + if ( tag ) + tag->Parse ( header, buffer ); + + return; +} + + +CDLLEXPORT +luint ID3Tag_Link ( ID3_Tag *tag, char *fileName ) +{ + luint offset = 0; + + if ( tag ) + offset = tag->Link ( fileName ); + + return offset; +} + + +CDLLEXPORT +void ID3Tag_Update ( ID3_Tag *tag ) +{ + if ( tag ) + tag->Update(); + + return; +} + + +CDLLEXPORT +void ID3Tag_Strip ( ID3_Tag *tag, bool v1Also ) +{ + if ( tag ) + tag->Strip ( v1Also ); + + return; +} + + +CDLLEXPORT +ID3_Frame *ID3Tag_FindFrameWithID ( ID3_Tag *tag, ID3_FrameID id ) +{ + ID3_Frame *frame = NULL; + + if ( tag ) + frame = tag->Find ( id ); + + return frame; +} + + +CDLLEXPORT +ID3_Frame *ID3Tag_FindFrameWithINT ( ID3_Tag *tag, ID3_FrameID id, ID3_FieldID fld, luint data ) +{ + ID3_Frame *frame = NULL; + + if ( tag ) + frame = tag->Find ( id, fld, data ); + + return frame; +} + + +CDLLEXPORT +ID3_Frame *ID3Tag_FindFrameWithASCII ( ID3_Tag *tag, ID3_FrameID id, ID3_FieldID fld, char *data ) +{ + ID3_Frame *frame = NULL; + + if ( tag ) + frame = tag->Find ( id, fld, data ); + + return frame; +} + + +CDLLEXPORT +ID3_Frame *ID3Tag_FindFrameWithUNICODE ( ID3_Tag *tag, ID3_FrameID id, ID3_FieldID fld, wchar_t *data ) +{ + ID3_Frame *frame = NULL; + + if ( tag ) + frame = tag->Find ( id, fld, data ); + + return frame; +} + + +CDLLEXPORT +luint ID3Tag_NumFrames ( ID3_Tag *tag ) +{ + luint num = 0; + + if ( tag ) + num = tag->NumFrames(); + + return num; +} + + +CDLLEXPORT +ID3_Frame *ID3Tag_GetFrameNum ( ID3_Tag *tag, luint num ) +{ + ID3_Frame *frame = NULL; + + if ( tag ) + frame = tag->GetFrameNum ( num ); + + return frame; +} + + +// frame wrappers + +CDLLEXPORT +void ID3Frame_Clear ( ID3_Frame *frame ) +{ + if ( frame ) + frame->Clear(); + + return; +} + + +CDLLEXPORT +void ID3Frame_SetID ( ID3_Frame *frame, ID3_FrameID id ) +{ + if ( frame ) + frame->SetID ( id ); + + return; +} + + +CDLLEXPORT +ID3_FrameID ID3Frame_GetID ( ID3_Frame *frame ) +{ + ID3_FrameID id = ID3FID_NOFRAME; + + if ( frame ) + id = frame->GetID(); + + return id; +} + + +CDLLEXPORT +ID3_Field *ID3Frame_GetField ( ID3_Frame *frame, ID3_FieldID name ) +{ + ID3_Field *field = NULL; + + if ( frame ) + field = &( frame->Field ( name ) ); + + return field; +} + + +// field wrappers + + +CDLLEXPORT +void ID3Field_Clear ( ID3_Field *field ) +{ + if ( field ) + field->Clear(); + + return; +} + + +CDLLEXPORT +luint ID3Field_Size ( ID3_Field *field ) +{ + luint size = 0; + + if ( field ) + size = field->Size(); + + return size; +} + + +CDLLEXPORT +luint ID3Field_GetNumTextItems ( ID3_Field *field ) +{ + luint items = 0; + + if ( field ) + items = field->GetNumTextItems(); + + return items; +} + + +CDLLEXPORT +void ID3Field_SetINT ( ID3_Field *field, luint data ) +{ + if ( field ) + field->Set ( data ); + + return; +} + + +CDLLEXPORT +luint ID3Field_GetINT ( ID3_Field *field ) +{ + luint value = 0; + + if ( field ) + value = field->Get(); + + return value; +} + + +CDLLEXPORT +void ID3Field_SetUNICODE ( ID3_Field *field, wchar_t *string ) +{ + if ( field ) + field->Set ( string ); + + return; +} + + +CDLLEXPORT +luint ID3Field_GetUNICODE ( ID3_Field *field, wchar_t *buffer, luint maxChars, luint itemNum ) +{ + luint numChars = 0; + + if ( field ) + numChars = field->Get ( buffer, maxChars, itemNum ); + + return numChars; +} + + +CDLLEXPORT +void ID3Field_AddUNICODE ( ID3_Field *field, wchar_t *string ) +{ + if ( field ) + field->Add ( string ); + + return; +} + + +CDLLEXPORT +void ID3Field_SetASCII ( ID3_Field *field, char *string ) +{ + if ( field ) + field->Set ( string ); + + return; +} + + +CDLLEXPORT +luint ID3Field_GetASCII ( ID3_Field *field, char *buffer, luint maxChars, luint itemNum ) +{ + luint numChars = 0; + + if ( field ) + numChars = field->Get ( buffer, maxChars, itemNum ); + + return numChars; +} + + +CDLLEXPORT +void ID3Field_AddASCII ( ID3_Field *field, char *string ) +{ + if ( field ) + field->Add ( string ); + + return; +} + + +CDLLEXPORT +void ID3Field_SetBINARY ( ID3_Field *field, uchar *data, luint size ) +{ + if ( field ) + field->Set ( data, size ); + + return; +} + + +CDLLEXPORT +void ID3Field_GetBINARY ( ID3_Field *field, uchar *buffer, luint buffLength ) +{ + if ( field ) + field->Get ( buffer, buffLength ); + + return; +} + + +CDLLEXPORT +void ID3Field_FromFile ( ID3_Field *field, char *fileName ) +{ + if ( field ) + field->FromFile ( fileName ); + + return; +} + + +CDLLEXPORT +void ID3Field_ToFile ( ID3_Field *field, char *fileName ) +{ + if ( field ) + field->ToFile ( fileName ); + + return; +} + + +#endif + + diff --git a/Src/id3v2/id3_error.cpp b/Src/id3v2/id3_error.cpp new file mode 100644 index 00000000..5eb8d862 --- /dev/null +++ b/Src/id3v2/id3_error.cpp @@ -0,0 +1,67 @@ +#if 0 //JF 10.30.00 +// The authors have released ID3Lib as Public Domain(PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney(dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include <string.h> +#include "id3_error.h" + + +/*static char *ID3_ErrorDescs[] = + { + "out of memory", + "no source/dest data specified", + "no buffer specified", + "invalid frame id", + "field not found", + "unknown field type", + "tag is already attached to a file", + "invalid tag version", + "file not found", + "error in zlib compression library" + };*/ + + +ID3_Error::ID3_Error(ID3_Err code, char *file, luint line) +{ + error = code; + errLine = line; + lstrcpyn(errFile, file, 256); +} + + +ID3_Err ID3_Error::GetErrorID(void) +{ + return error; +} + + +/*char *ID3_Error::GetErrorDesc(void) +{ + return ID3_ErrorDescs[error]; +}*/ + + +char *ID3_Error::GetErrorFile(void) +{ + return errFile; +} + + +luint ID3_Error::GetErrorLine(void) +{ + return errLine; +} + + + +#endif diff --git a/Src/id3v2/id3_error.h b/Src/id3v2/id3_error.h new file mode 100644 index 00000000..b8948fc6 --- /dev/null +++ b/Src/id3v2/id3_error.h @@ -0,0 +1,61 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_ERROR_H +#define ID3LIB_ERROR_H + +#include "id3_types.h" + +enum ID3_Err +{ + ID3E_NoMemory = 0, + ID3E_NoData, + ID3E_NoBuffer, + ID3E_InvalidFrameID, + ID3E_FieldNotFound, + ID3E_UnknownFieldType, + ID3E_TagAlreadyAttached, + ID3E_InvalidTagVersion, + ID3E_NoFile, + ID3E_zlibError +}; + + +class ID3_Error +{ +public: + ID3_Err GetErrorID(void); + //char *GetErrorDesc(void); + char *GetErrorFile(void); + luint GetErrorLine(void); + + // *** PRIVATE INTERNAL DATA - DO NOT USE *** PRIVATE INTERNAL DATA - DO NOT USE *** + + ID3_Error(ID3_Err id, char *file, luint lineNum); +protected: + ID3_Err error; + luint errLine; + char errFile[256]; +}; + +#ifdef _DEBUG +//#define ID3_THROW(x) throw ID3_Error (x, __FILE__, __LINE__) +#define ID3_THROW(x) void() +#else +#define ID3_THROW(x) void() +#endif + + +#endif + + diff --git a/Src/id3v2/id3_externals.h b/Src/id3v2/id3_externals.h new file mode 100644 index 00000000..31e253c3 --- /dev/null +++ b/Src/id3v2/id3_externals.h @@ -0,0 +1,21 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_EXTERNALS_H +#define ID3LIB_EXTERNALS_H + + + +#endif + + diff --git a/Src/id3v2/id3_field.cpp b/Src/id3v2/id3_field.cpp new file mode 100644 index 00000000..4b21cb77 --- /dev/null +++ b/Src/id3v2/id3_field.cpp @@ -0,0 +1,520 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + +// improved/optimized/whatever 10/30/00 JF + +#include <windows.h> +#include <string.h> +#include "id3_field.h" + +static ID3_FieldDef ID3FD_URL[] = +{ + {ID3FN_URL, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD}, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_UserURL[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TEXTENC, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_DESCRIPTION, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL | ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_URL, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_Text[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TEXTENC, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_TEXT, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_UserText[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TEXTENC, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_DESCRIPTION, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL | ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_TEXT, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_GeneralText[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TEXTENC, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_LANGUAGE, ID3FTY_ASCIISTRING, 3, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_DESCRIPTION, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL | ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_TEXT, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_Picture[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TEXTENC, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_IMAGEFORMAT, ID3FTY_ASCIISTRING, 3, 2, 0, ID3VC_LOWER, NULL, ID3FN_NOFIELD }, + {ID3FN_MIMETYPE, ID3FTY_ASCIISTRING, -1, 3, 0, ID3VC_HIGHER, ID3FF_NULL, ID3FN_NOFIELD }, + {ID3FN_PICTURETYPE, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_DESCRIPTION, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL | ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_DATA, ID3FTY_BINARY, -1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_GEO[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TEXTENC, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_MIMETYPE, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL, ID3FN_NOFIELD }, + {ID3FN_FILENAME, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL | ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_DESCRIPTION, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL | ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_DATA, ID3FTY_BINARY, -1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_UFI[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_OWNER, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL, ID3FN_NOFIELD }, + {ID3FN_DATA, ID3FTY_BINARY, -1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + +static ID3_FieldDef ID3FD_PRIVATE[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_OWNER, ID3FTY_ASCIISTRING, -1, 3, 0, ID3VC_HIGHER, ID3FF_NULL, ID3FN_NOFIELD }, + {ID3FN_DATA, ID3FTY_BINARY, -1, 3, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_PlayCounter[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_COUNTER, ID3FTY_INTEGER, 4, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_Popularimeter[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_EMAIL, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL, ID3FN_NOFIELD }, + {ID3FN_RATING, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_COUNTER, ID3FTY_INTEGER, 4, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_Registration[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_OWNER, ID3FTY_ASCIISTRING, -1, 3, 0, ID3VC_HIGHER, ID3FF_NULL, ID3FN_NOFIELD }, + {ID3FN_SYMBOL, ID3FTY_INTEGER, 1, 3, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_DATA, ID3FTY_BINARY, -1, 3, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_InvolvedPeople[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TEXTENC, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_TEXT, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL | ID3FF_NULLDIVIDE | ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + + +static ID3_FieldDef ID3FD_Volume[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_VOLUMEADJ, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NUMBITS, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_VOLCHGRIGHT, ID3FTY_BITFIELD, -1, 2, 0, ID3VC_HIGHER, ID3FF_ADJUSTEDBY, ID3FN_NUMBITS }, + {ID3FN_VOLCHGLEFT, ID3FTY_BITFIELD, -1, 2, 0, ID3VC_HIGHER, ID3FF_ADJUSTEDBY, ID3FN_NUMBITS }, + {ID3FN_PEAKVOLRIGHT, ID3FTY_BITFIELD, -1, 2, 0, ID3VC_HIGHER, ID3FF_ADJUSTEDBY, ID3FN_NUMBITS }, + {ID3FN_PEAKVOLLEFT, ID3FTY_BITFIELD, -1, 2, 0, ID3VC_HIGHER, ID3FF_ADJUSTEDBY, ID3FN_NUMBITS }, + {ID3FN_NOFIELD } +}; + +static ID3_FieldDef ID3FD_MCDI[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_CD_TOC, ID3FTY_BINARY, -1, 3, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD}, + {ID3FN_NOFIELD } +}; + +static ID3_FieldDef ID3FD_Text_v2_4[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TEXTENC, ID3FTY_INTEGER, 1, 4, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_TEXT, ID3FTY_ASCIISTRING, -1, 4, 0, ID3VC_HIGHER, ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + +static ID3_FieldDef ID3FD_Timestamp1[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TIMESTAMP, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_DATA, ID3FTY_BINARY, -1, 3, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + +static ID3_FieldDef ID3FD_Timestamp2[] = +{ + // FIELD FIELD FIXED RENDER IF OR + // NAME TYPE LEN VER REV WHAT? FLAGS LINKED FIELD + {ID3FN_TEXTENC, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_LANGUAGE, ID3FTY_ASCIISTRING, 3, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_TIMESTAMP, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_CONTENTTYPE, ID3FTY_INTEGER, 1, 2, 0, ID3VC_HIGHER, NULL, ID3FN_NOFIELD }, + {ID3FN_DESCRIPTION, ID3FTY_ASCIISTRING, -1, 2, 0, ID3VC_HIGHER, ID3FF_NULL | ID3FF_ADJUSTENC, ID3FN_NOFIELD }, + {ID3FN_NOFIELD } +}; + +static ID3_FrameDef ID3_FrameDefs[] = +{ + //FRAME ID SHORTID LONGID PRI TAGDISCARD FILEDISCARD HANDLER FIELDDEFS + {ID3FID_ENCODEDBY, "TEN", "TENC", false, true, NULL, ID3FD_Text }, + {ID3FID_ORIGALBUM, "TOT", "TOAL", false, false, NULL, ID3FD_Text }, + {ID3FID_PUBLISHER, "TPB", "TPUB", false, false, NULL, ID3FD_Text }, + {ID3FID_ENCODERSETTINGS, "TSS", "TSSE", false, false, NULL, ID3FD_Text }, + {ID3FID_ORIGFILENAME, "TOF", "TOFN", false, false, NULL, ID3FD_Text }, + {ID3FID_LANGUAGE, "TLA", "TLAN", false, false, NULL, ID3FD_Text }, + {ID3FID_PARTINSET, "TPA", "TPOS", false, false, NULL, ID3FD_Text }, + {ID3FID_DATE, "TDA", "TDAT", false, false, NULL, ID3FD_Text }, + {ID3FID_TIME, "TIM", "TIME", false, false, NULL, ID3FD_Text }, + {ID3FID_RECORDINGDATES, "TRD", "TRDA", false, false, NULL, ID3FD_Text }, + {ID3FID_MEDIATYPE, "TMT", "TMED", false, false, NULL, ID3FD_Text }, + {ID3FID_FILETYPE, "TFT", "TFLT", false, false, NULL, ID3FD_Text }, + {ID3FID_NETRADIOSTATION, "TRN", "TRSN", false, false, NULL, ID3FD_Text }, + {ID3FID_NETRADIOOWNER, "TRO", "TRSO", false, false, NULL, ID3FD_Text }, + {ID3FID_LYRICIST, "TXT", "TEXT", false, false, NULL, ID3FD_Text }, + {ID3FID_ORIGARTIST, "TOA", "TOPE", false, false, NULL, ID3FD_Text }, + {ID3FID_ORIGLYRICIST, "TOL", "TOLY", false, false, NULL, ID3FD_Text }, + {ID3FID_CONTENTGROUP, "TT1", "TIT1", false, false, NULL, ID3FD_Text }, + {ID3FID_TITLE, "TT2", "TIT2", false, false, NULL, ID3FD_Text }, + {ID3FID_SUBTITLE, "TT3", "TIT3", false, false, NULL, ID3FD_Text }, + {ID3FID_LEADARTIST, "TP1", "TPE1", false, false, NULL, ID3FD_Text }, + {ID3FID_BAND, "TP2", "TPE2", false, false, NULL, ID3FD_Text }, + {ID3FID_CONDUCTOR, "TP3", "TPE3", false, false, NULL, ID3FD_Text }, + {ID3FID_MIXARTIST, "TP4", "TPE4", false, false, NULL, ID3FD_Text }, + {ID3FID_ALBUM, "TAL", "TALB", false, false, NULL, ID3FD_Text }, + {ID3FID_YEAR, "TYE", "TYER", false, false, NULL, ID3FD_Text }, + {ID3FID_COMPOSER, "TCM", "TCOM", false, false, NULL, ID3FD_Text }, + {ID3FID_COPYRIGHT, "TCR", "TCOP", false, false, NULL, ID3FD_Text }, + {ID3FID_PRODUCEDNOTICE, " ", "TPRO", false, false, NULL, ID3FD_Text }, + {ID3FID_CONTENTTYPE, "TCO", "TCON", false, false, NULL, ID3FD_Text }, + {ID3FID_TRACKNUM, "TRK", "TRCK", false, false, NULL, ID3FD_Text }, + {ID3FID_USERTEXT, "TXX", "TXXX", false, false, NULL, ID3FD_UserText }, + {ID3FID_COMMENT, "COM", "COMM", false, false, NULL, ID3FD_GeneralText }, + {ID3FID_TERMSOFUSE, " ", "USER", false, false, NULL, ID3FD_GeneralText }, + {ID3FID_UNSYNCEDLYRICS, "ULT", "USLT", false, false, NULL, ID3FD_GeneralText }, + {ID3FID_SYNCEDLYRICS, "SLT", "SYLT", false, false, NULL, ID3FD_Timestamp2 }, + {ID3FID_SYNCEDTEMPOCODE, "STC", "SYTC", false, false, NULL, ID3FD_Timestamp1 }, + // URL Frames + {ID3FID_WWWAUDIOFILE, "WAF", "WOAF", false, false, NULL, ID3FD_URL }, + {ID3FID_WWWARTIST, "WAR", "WOAR", false, false, NULL, ID3FD_URL }, + {ID3FID_WWWAUDIOSOURCE, "WAS", "WOAS", false, false, NULL, ID3FD_URL }, + {ID3FID_WWWCOMMERCIALINFO, "WCM", "WCOM", false, false, NULL, ID3FD_URL }, + {ID3FID_WWWCOPYRIGHT, "WCP", "WCOP", false, false, NULL, ID3FD_URL }, + {ID3FID_WWWPUBLISHER, "WPB", "WPUB", false, false, NULL, ID3FD_URL }, + {ID3FID_WWWPAYMENT, "WPY", "WPAY", false, false, NULL, ID3FD_URL }, + {ID3FID_WWWRADIOPAGE, "WRA", "WORS", false, false, NULL, ID3FD_URL }, + {ID3FID_WWWUSER, "WXX", "WXXX", false, false, NULL, ID3FD_UserURL }, + // misc frames + {ID3FID_INVOLVEDPEOPLE, "IPL", "IPLS", false, false, NULL, ID3FD_InvolvedPeople }, + {ID3FID_PICTURE, "PIC", "APIC", false, false, NULL, ID3FD_Picture }, + {ID3FID_GENERALOBJECT, "GEO", "GEOB", false, false, NULL, ID3FD_GEO }, + {ID3FID_UNIQUEFILEID, "UFI", "UFID", false, false, NULL, ID3FD_UFI }, + {ID3FID_PRIVATE, " ", "PRIV", false, false, NULL, ID3FD_PRIVATE }, + {ID3FID_PLAYCOUNTER, "CNT", "PCNT", false, false, NULL, ID3FD_PlayCounter }, + {ID3FID_POPULARIMETER, "POP", "POPM", false, false, NULL, ID3FD_Popularimeter }, + {ID3FID_CRYPTOREG, " ", "ENCR", false, false, NULL, ID3FD_Registration }, + {ID3FID_GROUPINGREG, " ", "GRID", false, false, NULL, ID3FD_Registration }, + {ID3FID_SIGNATURE, " ", "SIGN", false, false, NULL, ID3FD_Registration }, + {ID3FID_MCDI, "MCI", "MCDI", false, false, NULL, ID3FD_MCDI}, + {ID3FID_BPM, "TBP", "TBPM", false, false, NULL, ID3FD_Text}, + {ID3FID_KEY, "TKE", "TKEY", false, false, NULL, ID3FD_Text}, + {ID3FID_MOOD, " ", "TMOO", false, false, NULL, ID3FD_Text}, + {ID3FID_ISRC, "TRC", "TSRC", false, false, NULL, ID3FD_Text}, + {ID3FID_RECORDINGTIME, " ", "TDRC", false, false, NULL, ID3FD_Text}, + {ID3FID_COMPILATION, "TCP", "TCMP", false, false, NULL, ID3FD_Text}, + {ID3FID_ALBUMSORT, "TSA", "TSOA", false, false, NULL, ID3FD_Text}, + {ID3FID_ALBUMARTISTSORT, "TS2", "TSO2", false, false, NULL, ID3FD_Text}, + {ID3FID_PERFORMERSORT, "TSP", "TSOP", false, false, NULL, ID3FD_Text}, + {ID3FID_COMPOSERSORT, "TSC", "TSOC", false, false, NULL, ID3FD_Text}, + {ID3FID_TITLESORT, "TST", "TSOT", false, false, NULL, ID3FD_Text}, + {ID3FID_REPLAYGAIN, " ", "RGAD", false, false, NULL, ID3FD_UserText }, + {ID3FID_VOLUMEADJ, "RVA", "RVAD", false, false, NULL, ID3FD_Volume }, + {ID3FID_INVOLVEDPEOPLE2, " ", "TIPL", false, false, NULL, ID3FD_InvolvedPeople }, + {ID3FID_CREDITS, " ", "TMCL", false, false, NULL, ID3FD_InvolvedPeople }, + {ID3FID_ENCODINGTIME, " ", "TDEN", false, false, NULL, ID3FD_Text }, + {ID3FID_FILEOWNER, " ", "TOWN", false, false, NULL, ID3FD_Text }, + {ID3FID_LENGTH, "TLE", "TLEN", false, false, NULL, ID3FD_Text }, + {ID3FID_ORIGYEAR, "TOR", "TORY", false, false, NULL, ID3FD_Text }, + {ID3FID_ORIGRELEASETIME, " ", "TDOR", false, false, NULL, ID3FD_Text }, + {ID3FID_RELEASETIME, " ", "TDRL", false, false, NULL, ID3FD_Text }, + {ID3FID_SETSUBTITLE, " ", "TSST", false, false, NULL, ID3FD_Text }, + {ID3FID_TAGGINGTIME, " ", "TDTG", false, false, NULL, ID3FD_Text }, + {ID3FID_PLAYLISTDELAY, "TDY", "TDLY", false, false, NULL, ID3FD_Text }, + {ID3FID_PODCAST, " ", "PCST", false, false, NULL, ID3FD_Text }, + {ID3FID_PODCASTCATEGORY, " ", "TCAT", false, false, NULL, ID3FD_Text }, + {ID3FID_PODCASTDESC, " ", "TDES", false, false, NULL, ID3FD_Text }, + {ID3FID_PODCASTID, " ", "TGID", false, false, NULL, ID3FD_Text }, + {ID3FID_PODCASTURL, " ", "WFED", false, false, NULL, ID3FD_URL }, + {ID3FID_NOFRAME } +}; + +ID3_Field::ID3_Field(void) +{ + name = ID3FN_NOFIELD; + type = ID3FTY_INTEGER; + data = 0; + size = 0; + flags = 0; + //SetVersion(3,0); + version = 3; + revision = 0; + fixedLength = -1; + ioVersion = 3; + ioRevision = 0; + control = ID3VC_HIGHER; + + Clear(); +} + +ID3_Field::~ID3_Field(void) +{ + Clear(); +} + +void ID3_Field::Clear(void) +{ + if (data && type != ID3FTY_INTEGER) free(data); + + type = ID3FTY_INTEGER; + data = 0; + size = sizeof (luint); + hasChanged = true; + + return; +} + +void ID3_Field::SetVersion (uchar ver, uchar rev) +{ + if (version != ver || revision != rev) hasChanged = true; + + version = ver; + revision = rev; + + return; +} + + +bool ID3_Field::HasChanged (void) +{ + return hasChanged; +} + + +luint ID3_Field::Size(void) +{ + return BinSize (false); +} + + +luint ID3_Field::BinSize(bool withExtras) +{ + luint bytes = 0; + + if (control == ID3VC_HIGHER) + { + if (version < ioVersion || revision < ioRevision) + return 0; + } + else + { + if (version > ioVersion || revision > ioRevision) + return 0; + } + + bytes = size; + + if (withExtras) + { + if (!data && size) + { + if (flags & ID3FF_NULL) + bytes = 2; + else + bytes = 0; + } + + // if we are a Unicode string, add 2 bytes for the BOM (but + // only if there is a string to render - regardless of NULL) + if (type == ID3FTY_UNICODESTRING && data && size) bytes += 2; + + // if we are an ASCII string, divide by sizeof (wchar_t) + // because internally we store the string as Unicode, so + // the ASCII version will only be half as long + if (type == ID3FTY_UTF8STRING) + { + if (data && size) + bytes = WideCharToMultiByte(CP_UTF8, 0, (const wchar_t *)data, (int)(size/sizeof(wchar_t)), 0, 0, 0, 0); + else + bytes /= sizeof(wchar_t); + } + + if (type == ID3FTY_ASCIISTRING) + { + // TODO: this statement isn't correct (especially for double byte) + // we could use WideCharToMultiByte to determine an exact byte count + bytes /= sizeof (wchar_t); + } + } + else + { + // because it seems that the application called us via ID3_Field::Size() + // we are going to return the number of characters, not bytes, so if + // the string is Unicode, we will half the 'bytes' variable because + // Unicode strings have twice as many bytes as they do characters + if (type == ID3FTY_UNICODESTRING) + bytes /= sizeof(wchar_t); + } + + // check to see if we are within the legal limit for this field + // -1 means arbitrary length field + if (fixedLength != -1) + bytes = fixedLength; + + return bytes; +} + + +luint ID3_Field::Parse(uchar *buffer, luint posn, luint buffSize) +{ + if (control == ID3VC_HIGHER) + { + if (version < ioVersion || revision < ioRevision) + return 0; + } + else + { + if (version > ioVersion || revision > ioRevision) + return 0; + } + + switch(type) + { + case ID3FTY_INTEGER: + return ParseInteger(buffer, posn, buffSize); + case ID3FTY_BINARY: + return ParseBinary(buffer, posn, buffSize); + case ID3FTY_ASCIISTRING: + return ParseASCIIString(buffer, posn, buffSize); + case ID3FTY_UNICODESTRING: + return ParseUnicodeString(buffer, posn, buffSize); + case ID3FTY_UTF8STRING: + return ParseUTF8String(buffer, posn, buffSize); + default: + //ID3_THROW (ID3E_UnknownFieldType); + break; + } + + return 0; +} + +ID3_FrameDef *ID3_FindFrameDef(ID3_FrameID id) +{ + luint cur = 0; + while (1) + { + if (ID3_FrameDefs[cur].id == id) + return &ID3_FrameDefs[cur]; + if (ID3_FrameDefs[cur].id == ID3FID_NOFRAME) + return NULL; + cur++; + } +} + +ID3_FrameID ID3_FindFrameID(const char *id) +{ + luint cur = 0; + while (1) + { + if (ID3_FrameDefs[cur].id == ID3FID_NOFRAME) + return ID3FID_NOFRAME; + if (((strncmp(ID3_FrameDefs[cur].shortTextID, id, 3) == 0) && strlen (id) == 3) + || ((strncmp(ID3_FrameDefs[cur].longTextID, id, 4) == 0) && strlen (id) == 4)) + return ID3_FrameDefs[cur].id; + cur++; + } +} + +luint ID3_Field::Render(uchar *buffer) +{ + if (control == ID3VC_HIGHER) + { + if (version < ioVersion || revision < ioRevision) + return 0; + } + else + { + if (version > ioVersion || revision > ioRevision) + return 0; + } + + switch(type) + { + case ID3FTY_INTEGER: + return RenderInteger(buffer); + case ID3FTY_BINARY: + return RenderBinary(buffer); + case ID3FTY_ASCIISTRING: + return RenderLatinString(buffer); + case ID3FTY_UNICODESTRING: + return RenderUnicodeString(buffer); + case ID3FTY_UTF8STRING: + return RenderUTF8String(buffer); + default: + // ID3_THROW (ID3E_UnknownFieldType); + break; + } + return 0; +} + + diff --git a/Src/id3v2/id3_field.h b/Src/id3v2/id3_field.h new file mode 100644 index 00000000..0c17a761 --- /dev/null +++ b/Src/id3v2/id3_field.h @@ -0,0 +1,282 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 +// improved/optimized/whatEVER jan-08-2006 benski + +#ifndef ID3LIB_FIELD_H +#define ID3LIB_FIELD_H + + +#include <wchar.h> +#include "id3_types.h" +#include "id3_error.h" + + +// field flags +#define ID3FF_NULL (1 << 0) +#define ID3FF_NULLDIVIDE (1 << 1) +#define ID3FF_ADJUSTENC (1 << 2) +#define ID3FF_ADJUSTEDBY (1 << 3) + + +enum ID3_TextEnc +{ + ID3TE_ASCII = 0, + ID3TE_UNICODE = 1, // UTF-16 + ID3TE_UTF16_BE = 2, // UTF-16 big endian, no BOM + ID3TE_UTF8 = 3, // UTF-8 +}; + +enum ID3_FieldType +{ + ID3FTY_INTEGER = 0, + ID3FTY_BITFIELD, + ID3FTY_BINARY, + ID3FTY_ASCIISTRING, + ID3FTY_UNICODESTRING, + ID3FTY_UTF8STRING, +}; + +enum ID3_FieldID +{ + ID3FN_NOFIELD = 0, + ID3FN_TEXTENC, + ID3FN_TEXT, + ID3FN_URL, + ID3FN_DATA, + ID3FN_DESCRIPTION, + ID3FN_OWNER, + ID3FN_EMAIL, + ID3FN_RATING, + ID3FN_FILENAME, + ID3FN_LANGUAGE, + ID3FN_PICTURETYPE, + ID3FN_IMAGEFORMAT, + ID3FN_MIMETYPE, + ID3FN_TIMESTAMP, + ID3FN_CONTENTTYPE, + ID3FN_COUNTER, + ID3FN_SYMBOL, + ID3FN_VOLUMEADJ, + ID3FN_NUMBITS, + ID3FN_VOLCHGRIGHT, + ID3FN_VOLCHGLEFT, + ID3FN_PEAKVOLRIGHT, + ID3FN_PEAKVOLLEFT, + ID3FN_CD_TOC, + + ID3FN_LASTFIELDID +}; + + +enum ID3_FrameID +{ + ID3FID_NOFRAME = 0, + ID3FID_ENCODEDBY, + ID3FID_ORIGALBUM, + ID3FID_PUBLISHER, + ID3FID_ENCODERSETTINGS, + ID3FID_ORIGFILENAME, + ID3FID_LANGUAGE, + ID3FID_PARTINSET, + ID3FID_DATE, + ID3FID_TIME, + ID3FID_RECORDINGDATES, + ID3FID_MEDIATYPE, + ID3FID_FILETYPE, + ID3FID_NETRADIOSTATION, + ID3FID_NETRADIOOWNER, + ID3FID_LYRICIST, + ID3FID_ORIGARTIST, + ID3FID_ORIGLYRICIST, + ID3FID_CONTENTGROUP, + ID3FID_TITLE, + ID3FID_SUBTITLE, + ID3FID_LEADARTIST, + ID3FID_BAND, + ID3FID_CONDUCTOR, + ID3FID_MIXARTIST, + ID3FID_ALBUM, + ID3FID_YEAR, + ID3FID_COMPOSER, + ID3FID_COPYRIGHT, + ID3FID_PRODUCEDNOTICE, + ID3FID_CONTENTTYPE, + ID3FID_TRACKNUM, + ID3FID_USERTEXT, + ID3FID_COMMENT, + ID3FID_TERMSOFUSE, + ID3FID_UNSYNCEDLYRICS, + ID3FID_SYNCEDLYRICS, + ID3FID_SYNCEDTEMPOCODE, + ID3FID_WWWAUDIOFILE, + ID3FID_WWWARTIST, + ID3FID_WWWAUDIOSOURCE, + ID3FID_WWWCOMMERCIALINFO, + ID3FID_WWWCOPYRIGHT, + ID3FID_WWWPUBLISHER, + ID3FID_WWWPAYMENT, + ID3FID_WWWRADIOPAGE, + ID3FID_WWWUSER, + ID3FID_INVOLVEDPEOPLE, + ID3FID_PICTURE, + ID3FID_GENERALOBJECT, + ID3FID_UNIQUEFILEID, + ID3FID_PRIVATE, + ID3FID_PLAYCOUNTER, + ID3FID_POPULARIMETER, + ID3FID_CRYPTOREG, + ID3FID_GROUPINGREG, + ID3FID_SIGNATURE, + ID3FID_MCDI, + ID3FID_BPM, + ID3FID_KEY, + ID3FID_MOOD, + ID3FID_ISRC, + ID3FID_RECORDINGTIME, + ID3FID_COMPILATION, + ID3FID_ALBUMSORT, + ID3FID_ALBUMARTISTSORT, + ID3FID_PERFORMERSORT, + ID3FID_COMPOSERSORT, + ID3FID_TITLESORT, + ID3FID_REPLAYGAIN, + ID3FID_VOLUMEADJ, + ID3FID_INVOLVEDPEOPLE2, + ID3FID_CREDITS, + ID3FID_ENCODINGTIME, + ID3FID_FILEOWNER, + ID3FID_LENGTH, + ID3FID_ORIGYEAR, + ID3FID_ORIGRELEASETIME, + ID3FID_RELEASETIME, + ID3FID_SETSUBTITLE, + ID3FID_TAGGINGTIME, + ID3FID_PLAYLISTDELAY, + ID3FID_PODCAST, + ID3FID_PODCASTCATEGORY, + ID3FID_PODCASTDESC, + ID3FID_PODCASTID, + ID3FID_PODCASTURL, +}; + + +enum ID3_VerCtl +{ + ID3VC_HIGHER = 0, + ID3VC_LOWER +}; + + +struct ID3_FieldDef +{ + ID3_FieldID id; + ID3_FieldType type; + lsint fixedLength; + uchar version; + uchar revision; + ID3_VerCtl control; + luint flags; + ID3_FieldID linkedField; +}; + + +class ID3_Frame; + +// TODO: add minimum/maximum version & revision +struct ID3_FrameDef +{ + ID3_FrameID id; + char *shortTextID; + char *longTextID; + bool tagDiscard; + bool fileDiscard; + bool (*parseHandler)(ID3_Frame *frame); + ID3_FieldDef *fieldDefs; +}; + + +class ID3_Field +{ +public: + ID3_Field(void); + ~ID3_Field(void); + + void Clear(void); + luint Size(void); + luint GetNumTextItems(void); + // integer field functions + //ID3_Field& operator= (luint newData); + void Set(luint newData); + luint Get(void); + // Unicode string field functions + //ID3_Field& operator= (wchar_t *string); + void SetUnicode(const wchar_t *string); + luint GetUnicode(wchar_t *buffer, luint maxChars, luint itemNum = 1); + void AddUnicode(const wchar_t *string); + // ASCII string field functions + //ID3_Field& operator= (char *string); + void SetLatin(const char *string); + void SetLocal(const char *string); + void SetUTF8(const char *string); + + luint GetLocal(char *buffer, luint maxChars, luint itemNum = 1); + luint GetLatin(char *buffer, luint maxChars, luint itemNum = 1); + + void AddLocal(const char *string); + void AddLatin(const char *string); + + // binary field functions + void Set(uchar *newData, luint newSize); + void Get(uchar *buffer, luint buffLength); + + // *** PRIVATE INTERNAL DATA - DO NOT USE *** PRIVATE INTERNAL DATA - DO NOT USE *** + + luint BinSize(bool withExtras = true); + bool HasChanged(void); + void SetVersion(uchar ver, uchar rev); + luint Render(uchar *buffer); + luint Parse(uchar *buffer, luint posn, luint buffSize); + ID3_FieldID name; // the ID of this field + ID3_FieldType type; // what type is this field or should be + lsint fixedLength; // if this is positive, the length of the field is fixed + uchar ioVersion; // specific version + uchar ioRevision; // specific revision + ID3_VerCtl control; // render if ver/rev is higher, or lower than frame::version, frame::revision? + luint flags; // special field flags + uchar version; // the version being rendered/parsed + uchar revision; // the revision being rendered/parsed + bool hasChanged; // has the field changed since the last parse/render? +protected: + luint RenderInteger (uchar *buffer); + luint RenderLatinString(uchar *buffer); + luint RenderUnicodeString (uchar *buffer); + luint RenderUTF8String(uchar *buffer); + luint RenderBinary (uchar *buffer); + + luint ParseInteger (uchar *buffer, luint posn, luint buffSize); + luint ParseASCIIString (uchar *buffer, luint posn, luint buffSize); + luint ParseUnicodeString (uchar *buffer, luint posn, luint buffSize); + luint ParseUTF8String(uchar *buffer, luint posn, luint buffSize); + luint ParseBinary (uchar *buffer, luint posn, luint buffSize); + + uchar *data; + luint size; +}; + + +ID3_FrameDef *ID3_FindFrameDef (ID3_FrameID id); +ID3_FrameID ID3_FindFrameID(const char *id); + + +#endif + + diff --git a/Src/id3v2/id3_field_binary.cpp b/Src/id3v2/id3_field_binary.cpp new file mode 100644 index 00000000..47c51be6 --- /dev/null +++ b/Src/id3v2/id3_field_binary.cpp @@ -0,0 +1,83 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 +// improved/optimized/whatever 10/30/00 JF + +#include <windows.h> +#include <stdio.h> +#include <memory.h> +#include "id3_field.h" + +void ID3_Field::Set(uchar *newData, luint newSize) +{ + Clear(); + + if (newSize) + { + if (newSize == 4294967295/*-1*/) + { + ID3_THROW(ID3E_NoMemory); + return; + } + + if (!(data = (unsigned char *)calloc(newSize, sizeof(unsigned char)))) + { + ID3_THROW(ID3E_NoMemory); + } + else + { + memcpy (data, newData, newSize); + size = newSize; + + type = ID3FTY_BINARY; + hasChanged = true; + } + } + + return; +} + +void ID3_Field::Get(uchar *buffer, luint buffLength) +{ + if (data && size && buffLength && buffer) + { + luint actualBytes = MIN(buffLength, size); + memcpy(buffer, data, actualBytes); + } +} + +luint ID3_Field::ParseBinary (uchar *buffer, luint posn, luint buffSize) +{ + luint bytesUsed = 0; + + bytesUsed = buffSize - posn; + + if (fixedLength != -1) + bytesUsed = MIN (fixedLength, bytesUsed); + + Set(&buffer[ posn ], bytesUsed); + + hasChanged = false; + + return bytesUsed; +} + +luint ID3_Field::RenderBinary (uchar *buffer) +{ + luint bytesUsed = 0; + + bytesUsed = BinSize(); + memcpy(buffer, data, bytesUsed); + + hasChanged = false; + + return bytesUsed; +}
\ No newline at end of file diff --git a/Src/id3v2/id3_field_integer.cpp b/Src/id3v2/id3_field_integer.cpp new file mode 100644 index 00000000..41f06d97 --- /dev/null +++ b/Src/id3v2/id3_field_integer.cpp @@ -0,0 +1,81 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 +// improved/optimized/whatever 10/30/00 JF +// improved/optimized/whatEVER jan-08-2006 benski + +#include "id3_field.h" + +#if 0 // taking out operators +ID3_Field& ID3_Field::operator=(luint newData) +{ + Set(newData); + + return *this; +} +#endif + + +void ID3_Field::Set(luint newData) +{ + Clear(); + + data = reinterpret_cast<uchar *>(newData); + size = sizeof(luint); + type = ID3FTY_INTEGER; + hasChanged = true; +} + + +luint ID3_Field::Get(void) +{ + return (luint) data; +} + + +luint ID3_Field::ParseInteger(uchar *buffer, luint posn, luint buffSize) +{ + luint bytesUsed = 0; + + if(buffer && buffSize) + { + luint i; + luint temp = 0; + + bytesUsed = 4; + + if(fixedLength != -1) + bytesUsed = MIN(fixedLength, bytesUsed); + + for(i = 0; i < bytesUsed; i++) + temp |=(buffer[ posn + i ] <<(((bytesUsed - i) - 1) * 8)); + + Set(temp); + hasChanged = false; + } + + return bytesUsed; +} + + +luint ID3_Field::RenderInteger(uchar *buffer) +{ + luint bytesUsed = 0; + luint length = BinSize(); + + for(luint i = 0; i < length; i++) + buffer[ i ] = (uchar)((((luint) data) >>(((length - i) - 1) * 8)) & 0xFF); + + bytesUsed = length; + hasChanged = false; + + return bytesUsed; +} diff --git a/Src/id3v2/id3_field_string_ascii.cpp b/Src/id3v2/id3_field_string_ascii.cpp new file mode 100644 index 00000000..cee76348 --- /dev/null +++ b/Src/id3v2/id3_field_string_ascii.cpp @@ -0,0 +1,239 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + +// improved/optimized/whatever 10/30/00 JF +// improved/optimized/whatEVER jan-08-2006 benski + +#include <stdlib.h> +#include "id3_field.h" +#include "id3_misc_support.h" +#include "../nu/AutoWide.h" +#include "../Plugins/Input/in_mp3/config.h" // TODO: cut + + +// the ::Set() function for ASCII + +void ID3_Field::SetLocal(const char *newString) +{ + if (newString) + { + Clear(); + AutoWide temp(newString); + SetUnicode(temp); + if (!(flags & ID3FF_ADJUSTENC)) + type = ID3FTY_ASCIISTRING; + } +} + +void ID3_Field::SetLatin(const char *newString) +{ + if (newString) + { + Clear(); + AutoWide temp(newString, 28591); // ISO-8859-1 code page + SetUnicode(temp); + type = ID3FTY_ASCIISTRING; + } + + return; +} + +void ID3_Field::SetUTF8(const char *newString) +{ + if (newString) + { + Clear(); + AutoWide temp(newString, CP_UTF8); + SetUnicode(temp); + } + + return; +} + +// the ::Get() function for ASCII + +luint ID3_Field::GetLocal(char *buffer, luint maxLength, luint itemNum) +{ + luint bytesUsed = 0; + wchar_t *temp; + + if (temp = (wchar_t*)calloc(maxLength, sizeof(wchar_t))) + { + if (GetUnicode(temp, maxLength, itemNum)) + { + bytesUsed = ID3_UnicodeToLocal(buffer, temp, maxLength); + } + + free(temp); + } + else + ID3_THROW (ID3E_NoMemory); + + return bytesUsed; +} + + +void ID3_Field::AddLocal(const char *newString) +{ + if (newString) + { + AutoWide temp(newString); + AddUnicode(temp); + } + +} + +void ID3_Field::AddLatin(const char *newString) +{ + if (newString) + { + AutoWide temp(newString, 28591); + AddUnicode(temp); + + type = ID3FTY_ASCIISTRING; + } +} + +luint ID3_Field::ParseASCIIString(uchar *buffer, luint posn, luint buffSize) +{ + luint bytesUsed = 0; + + if (fixedLength != -1) + bytesUsed = fixedLength; + else + { + if (flags & ID3FF_NULL) + while ((posn + bytesUsed) < buffSize && buffer[posn + bytesUsed] != 0) + bytesUsed++; + else + bytesUsed = buffSize - posn; + } + + if (bytesUsed > 0xffff) // keep it sane, yo (64kb string max should be good) + { + hasChanged=false; + return 0; + } + if (bytesUsed) + { + char *temp = NULL; + if (temp = (char*)calloc(bytesUsed + 1, sizeof(char))) + { + memcpy(temp, &buffer[posn], bytesUsed); + temp[bytesUsed] = 0; + + if (config_read_mode == READ_LOCAL) // benski> I added a config option to deal with old tags + SetLocal(temp); + else + SetLatin(temp); + + if (!(flags & ID3FF_ADJUSTENC)) + type = ID3FTY_ASCIISTRING; + free(temp); + } + else + ID3_THROW (ID3E_NoMemory); + } + + if (flags & ID3FF_NULL) + bytesUsed++; + + hasChanged = false; + + return bytesUsed; +} + +luint ID3_Field::ParseUTF8String(uchar *buffer, luint posn, luint buffSize) +{ + luint bytesUsed = 0; + + if (fixedLength != -1) + bytesUsed = fixedLength; + else + { + if (flags & ID3FF_NULL) + while ((posn + bytesUsed) < buffSize && buffer[posn + bytesUsed] != 0) + bytesUsed++; + else + bytesUsed = buffSize - posn; + } + + if (bytesUsed > 0xffff) // keep it sane, yo (64kb string max should be good) + { + hasChanged=false; + return 0; + } + if (bytesUsed) + { + char *temp = NULL; + if (temp = (char*)calloc(bytesUsed + 1, sizeof(char))) + { + memcpy (temp, &buffer[posn], bytesUsed); + temp[bytesUsed] = 0; + + SetUTF8(temp); + + free(temp); + } + else + ID3_THROW (ID3E_NoMemory); + } + + if (flags & ID3FF_NULL) + bytesUsed++; + + hasChanged = false; + + return bytesUsed; +} + + +luint ID3_Field::RenderLatinString(uchar *buffer) +{ + luint bytesUsed = 0; + + buffer[0] = 0; + bytesUsed = BinSize(); + + if (data && size) + { + luint i; + + // benski> I added a config option for whether to use "broken" local system encoding mode + if (config_write_mode == WRITE_LATIN) + ID3_UnicodeToLatin( (char*)buffer, (const wchar_t *) data, bytesUsed, (int)bytesUsed); + else + ID3_UnicodeToLocal( (char*)buffer, (const wchar_t *) data, bytesUsed, bytesUsed); + + for (i = 0;i < bytesUsed; i++) + { + if (buffer[i] == 1) + { + char sub = '/'; + + if (flags & ID3FF_NULLDIVIDE) + sub = '\0'; + + buffer[i] = sub; + } + } + } + + if (bytesUsed == 1 && flags & ID3FF_NULL) + buffer[0] = 0; + + hasChanged = false; + + return bytesUsed; +} + + diff --git a/Src/id3v2/id3_field_string_unicode.cpp b/Src/id3v2/id3_field_string_unicode.cpp new file mode 100644 index 00000000..4e84943d --- /dev/null +++ b/Src/id3v2/id3_field_string_unicode.cpp @@ -0,0 +1,338 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + +// improved/optimized/whatever 10/30/00 JF +// improved/optimized/whatEVER jan-08-2006 benski + +#include <wchar.h> +#include <string.h> +#include <stdlib.h> +#include "id3_field.h" +#include <windows.h> +#include "../Plugins/Input/in_mp3/config.h" // TODO: cut +#include "id3_misc_support.h" + +// this function is another way of using Set() +#if 0 +ID3_Field &ID3_Field::operator=(wchar_t *string) +{ + Set(string); + + return *this; +} +#endif + + +// this is Set() + +void ID3_Field::SetUnicode(const wchar_t *string) +{ + luint bytesUsed = lstrlenW(string); + + // we can simply increment the + // bytesUsed count here because + // we just pilfer the NULL which is + // present in the string which was + // passed to us + if (flags & ID3FF_NULL) + bytesUsed++; + + // doubling the bytesUsed because + // Unicode is twice the size of ASCII + bytesUsed *= sizeof (wchar_t); + + Set ((uchar *) string, bytesUsed); + + type = ID3FTY_UNICODESTRING; + hasChanged = true; +} + + +void ID3_Field::AddUnicode(const wchar_t *string) +{ + if (!data) + SetUnicode(string); + else + { + wchar_t *temp; + luint newLen; + lsint nullOffset = 0; + + // if there is a NULL in this string, set this offset + // so that we ignore it in string size calculations + if (flags & ID3FF_NULL) + nullOffset = -1; + + // +1 is for the NULL at the end and the + // other +1 is for the list divider + newLen = 1 + (size / sizeof (wchar_t)) + lstrlenW(string) + 1 + nullOffset; + + // I use the value 1 as a divider because then I + // can change it to either a '/' or a NULL at render + // time. This allows easy use of these functions + // for text lists or in the IPLS frame + + if (temp = (wchar_t*)calloc(newLen, sizeof(wchar_t))) + { + lstrcpyW(temp, (wchar_t *) data); + temp[(size / sizeof (wchar_t)) + nullOffset] = L'\001'; + lstrcpyW (&temp[(size / sizeof (wchar_t)) + 1 + nullOffset], string); + + SetUnicode(temp); + + free(temp); + } + else + ID3_THROW (ID3E_NoMemory); + } + + return; +} + + +// this is Get() + +luint ID3_Field::GetUnicode(wchar_t *buffer, luint maxChars, luint itemNum) +{ + luint charsUsed = 0; + + // check to see if there is a string in the frame + // to copy before we even try + if (data) + { + lsint nullOffset = 0; + + if (flags & ID3FF_NULL) + nullOffset = -1; + + // first we must find which element + // is being sought to make sure it + // exists before we try to get it + if (itemNum <= GetNumTextItems() && itemNum > 0) + { + wchar_t *source = (wchar_t *) data; + luint posn = 0; + luint sourceLen = 0; + luint curItemNum = 1; + luint mx= (size / sizeof (wchar_t)) + nullOffset; + + // now we find that element and set the souvre pointer + while (posn<mx && curItemNum < itemNum) + { + while (posn<mx && *source != L'\001' && *source != L'\0') + { + source++; + posn++; + } + + source++; + posn++; + curItemNum++; + } + + if(posn>=mx) return 0; + + // now that we are positioned at the first character + // of the string we want, find the end of it + while (posn<mx && source[sourceLen] != L'\001' && source[sourceLen] != L'\0') + { + sourceLen++; + posn++; + } + + if (maxChars) // JF + { + // we subtract 1 here so we have + // room for the NULL terminator + //maxChars--; // CT + + if (buffer) + { + luint actualChars = MIN (maxChars-1, sourceLen); + + wcsncpy (buffer, source, actualChars); + buffer[actualChars] = L'\0'; + charsUsed = actualChars; + } + else + ID3_THROW (ID3E_NoBuffer); + } + } + } + + return charsUsed; +} + + +luint ID3_Field::GetNumTextItems (void) +{ + luint numItems = 0; + + if (data) + { + luint posn = 0; + + numItems++; + + while (posn < size) + if (data[posn++] == L'\001') + numItems++; + } + + return numItems; +} + + +luint ID3_Field::ParseUnicodeString (uchar *buffer, luint posn, luint buffSize) +{ + luint bytesUsed = 0; + wchar_t *temp = NULL; + + if (fixedLength != -1) + bytesUsed = fixedLength; + else + { + if (flags & ID3FF_NULL) + while ((posn + bytesUsed) < buffSize && + ! (buffer[posn + bytesUsed] == 0 && buffer[posn + bytesUsed + 1] == 0)) + bytesUsed += 2; + else + bytesUsed = buffSize - posn; + } + + if (bytesUsed > 0x8ffff) + { + hasChanged = false; + return 0; + } + + if (bytesUsed) + { + if (temp = (wchar_t*)calloc(((bytesUsed / sizeof (wchar_t)) + 1), sizeof(wchar_t))) + { + luint loc = 0; + + memcpy (temp, &buffer[posn], bytesUsed); + temp[bytesUsed / sizeof (wchar_t)] = 0; + + // if there is a BOM, skip past it and check to see if we + // need to swap the byte order around + if (temp[0] == 0xFEFF || temp[0] == 0xFFFE) + { + loc++; + + // if we need to swap the byte order + if (temp[0] != 0xFEFF) + { + int mylen=(int) lstrlenW(temp); + for (int i = loc; i < mylen; i++) + temp[i] = ((temp[i] >> 8) & 0xFF) | (((temp[i]) & 0xFF) << 8); + } + } + + SetUnicode(&temp[loc]); + + free(temp); + } + else + ID3_THROW (ID3E_NoMemory); + } + + if (flags & ID3FF_NULL) + bytesUsed += 2; + + hasChanged = false; + + return bytesUsed; +} + + +luint ID3_Field::RenderUnicodeString(uchar *buffer) +{ + luint bytesUsed = 0; + + bytesUsed = BinSize(); + + if (data && size && bytesUsed >= sizeof (wchar_t)) + { + wchar_t *ourString = (wchar_t *) &buffer[sizeof(wchar_t)]; + + // we render at sizeof (wchar_t) bytes into the buffer + // because we make room for the Unicode BOM + memcpy (&buffer[sizeof (wchar_t)], (uchar *) data, bytesUsed - sizeof (wchar_t)); + + // now we convert the internal dividers to what they + // are supposed to be + size_t numChars = bytesUsed / sizeof (wchar_t); + for (size_t i = 0; i != numChars-1; i++) + if (ourString[i] == 1) + { + wchar_t sub = L'/'; + + if (flags & ID3FF_NULLDIVIDE) + sub = L'\0'; + + ourString[i] = sub; + } + } + + if (bytesUsed) + { + // render the BOM + wchar_t *BOM = (wchar_t *) buffer; + BOM[0] = 0xFEFF; + } + + if (bytesUsed == 2 && (flags & ID3FF_NULL)) + buffer[0] = buffer[1] = 0; + + hasChanged = false; + + return bytesUsed; +} + +luint ID3_Field::RenderUTF8String(uchar *buffer) +{ + luint bytesUsed = 0; + + buffer[0] = 0; + bytesUsed = BinSize(); + + if (data && size) + { + luint i; + + ID3_UnicodeToUTF8( (char*)buffer, (const wchar_t *) data, bytesUsed, bytesUsed); + + for (i = 0;i < bytesUsed; i++) + { + if (buffer[i] == 1) + { + char sub = '/'; + + if (flags & ID3FF_NULLDIVIDE) + sub = '\0'; + + buffer[i] = sub; + } + } + } + + if (bytesUsed == 1 && flags & ID3FF_NULL) + buffer[0] = 0; + + hasChanged = false; + + return bytesUsed; +} + + diff --git a/Src/id3v2/id3_frame.cpp b/Src/id3v2/id3_frame.cpp new file mode 100644 index 00000000..dd22f43b --- /dev/null +++ b/Src/id3v2/id3_frame.cpp @@ -0,0 +1,273 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 +// improved/optimized/whatever 10/30/00 JF + + +#include <string.h> +#include "id3_tag.h" + + +ID3_Frame::ID3_Frame(ID3_FrameID id) +{ + luint lwordsForFields = 0; + + version = ID3_TAGVERSION; + revision = ID3_TAGREVISION; + numFields = 0; + fields = NULL; + groupingID[0] = 0; + encryptionID[0] = 0; + compression = false; + + lwordsForFields = (((luint) ID3FN_LASTFIELDID) - 1) / (sizeof (luint) * 8); + + if ((((luint) ID3FN_LASTFIELDID) - 1) % (sizeof (luint) * 8) != 0) + lwordsForFields++; + + if (fieldBits = (bitset)calloc(lwordsForFields, sizeof(*fieldBits))) + { + for (luint i = 0; i < lwordsForFields; i++) + fieldBits[i] = 0; + } + else + ID3_THROW (ID3E_NoMemory); + + SetID (id); +} + + +ID3_Frame::~ID3_Frame (void) +{ + Clear(); + + if (fieldBits) + free(fieldBits); +} + + +void ID3_Frame::Clear (void) +{ + if (numFields && fields) + { + for (luint i = 0; i < numFields; i++) + delete fields[i]; + + free(fields); + + fields = NULL; + numFields = 0; + hasChanged = true; + } + + return ; +} + + +void ID3_Frame::SetID (ID3_FrameID id) +{ + ID3_FrameDef *info; + + Clear(); + + if (id != ID3FID_NOFRAME) + { + if (info = ID3_FindFrameDef (id)) + { + frameID = id; + + numFields = 0; + + while (info->fieldDefs[numFields].id != ID3FN_NOFIELD) + numFields++; + + if ((fields = (ID3_Field **)calloc(numFields, sizeof(ID3_Field*))) == NULL) + ID3_THROW (ID3E_NoMemory); + else + { + for (luint i = 0; i < numFields; i++) + { + if ((fields[i] = new ID3_Field) == NULL) + ID3_THROW (ID3E_NoMemory); + else + { + fields[i]->name = info->fieldDefs[i].id; + fields[i]->type = info->fieldDefs[i].type; + fields[i]->fixedLength = info->fieldDefs[i].fixedLength; + fields[i]->ioVersion = info->fieldDefs[i].version; + fields[i]->ioRevision = info->fieldDefs[i].revision; + fields[i]->control = info->fieldDefs[i].control; + fields[i]->flags = info->fieldDefs[i].flags; + + // tell the frame that this field is present + BS_SET (fieldBits, fields[i]->name); + } + } + + hasChanged = true; + } + } + else + ID3_THROW (ID3E_InvalidFrameID); + } + + return ; +} + + +ID3_FrameID ID3_Frame::GetID (void) +{ + return frameID; +} + + +void ID3_Frame::SetVersion (uchar ver, uchar rev) +{ + if (version != ver || revision != rev) + hasChanged = true; + + version = ver; + revision = rev; + + return ; +} + + +lsint ID3_Frame::FindField (ID3_FieldID fieldName) +{ + if (BS_ISSET (fieldBits, fieldName)) + { + lsint num = 0; + while (num < (lsint) numFields) + { + if (fields[num]->name == fieldName) return num; + num++; + } + return -1; + } + return 0; +} + + +ID3_Field& ID3_Frame::Field (ID3_FieldID fieldName) +{ + luint fieldNum = FindField (fieldName); + + if (fieldNum == -1) + ID3_THROW (ID3E_FieldNotFound); + + return *fields[fieldNum]; +} + + +void ID3_Frame::UpdateFieldDeps (void) +{ + for (luint i = 0; i < numFields; i++) + { + if (fields[i]->flags & ID3FF_ADJUSTEDBY) + { + switch (fields[i]->type) + { + case ID3FTY_BITFIELD: + { + //luint value = 0; + + // now find the field on which this + // field is dependent and get a copy + // of the value of that field. + // then adjust the fixedLength of this + // field to that value / 8. + } + break; + } + } + } + + return ; +} + + +void ID3_Frame::UpdateStringTypes(void) +{ + for (luint i = 0; i < numFields; i++) + { + if (fields[i]->flags & ID3FF_ADJUSTENC) + { + ID3_TextEnc enc; + ID3_FieldType newType; + + enc = (ID3_TextEnc) Field(ID3FN_TEXTENC).Get(); + + switch (enc) + { + case ID3TE_ASCII: + newType = ID3FTY_ASCIISTRING; + break; + + case ID3TE_UNICODE: + newType = ID3FTY_UNICODESTRING; + break; + + case ID3TE_UTF8: + newType = ID3FTY_UTF8STRING; + break; + + default: + newType = ID3FTY_ASCIISTRING; + break; + } + + fields[i]->type = newType; + } + } +} + + +luint ID3_Frame::Size(void) +{ + luint bytesUsed = 0; + ID3_FrameHeader header; + + header.SetVersion (version, revision); + bytesUsed = header.Size(); + + if (strlen (encryptionID)) + bytesUsed++; + + if (strlen (groupingID)) + bytesUsed++; + + // this call is to tell the string fields + // what they should be rendered/parsed as + // (ASCII or Unicode) + UpdateStringTypes(); + + for (luint i = 0; i < numFields; i++) + { + fields[i]->SetVersion (version, revision); + bytesUsed += fields[i]->BinSize(); + } + + return bytesUsed; +} + + +bool ID3_Frame::HasChanged (void) +{ + if (hasChanged) return hasChanged; + + for (luint i = 0; i < numFields; i++) + { + bool changed = fields[i]->HasChanged(); + if (changed) return changed; + } + return 0; +} diff --git a/Src/id3v2/id3_frame.h b/Src/id3v2/id3_frame.h new file mode 100644 index 00000000..ca40caf1 --- /dev/null +++ b/Src/id3v2/id3_frame.h @@ -0,0 +1,55 @@ +// The authors have released ID3Lib as Public Domain(PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney(dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + +#pragma once + +#include "id3_types.h" +#include "id3_field.h" +#include "id3_header_frame.h" + + +class ID3_Frame +{ +public: + ID3_Frame(ID3_FrameID id = ID3FID_NOFRAME); + ~ID3_Frame(void); + + void Clear(void); + void SetID(ID3_FrameID id); + ID3_FrameID GetID(void); + ID3_Field& Field(ID3_FieldID name); + + // *** PRIVATE INTERNAL DATA - DO NOT USE *** PRIVATE INTERNAL DATA - DO NOT USE *** + + bool HasChanged(void); + void SetVersion(uchar ver, uchar rev); + void Parse(uchar *buffer, luint size); + luint Size(void); + luint Render(uchar *buffer); + char encryptionID[256]; // the encryption method with which this frame is encrypted + char groupingID[256]; // the group to which this frame belongs + bool compression; // should we try to compress? + bool hasChanged; // has the frame changed since the last parse/render? + bitset fieldBits; // which fields are present? + ID3_FrameID frameID; // what frame are we? + +protected: + void UpdateStringTypes(void); + void UpdateFieldDeps(void); + lsint FindField(ID3_FieldID name); + uchar version; // what version tag? + uchar revision; // what revision tag? + luint numFields; // how many fields are in this frame? + ID3_Field **fields; // an array of field object pointers +}; + + diff --git a/Src/id3v2/id3_frame_parse.cpp b/Src/id3v2/id3_frame_parse.cpp new file mode 100644 index 00000000..5d2107e6 --- /dev/null +++ b/Src/id3v2/id3_frame_parse.cpp @@ -0,0 +1,40 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include "id3_frame.h" + + +void ID3_Frame::Parse(uchar *buffer, luint size) +{ + luint i; + luint posn = 0; + + for (i = 0; i < numFields; i++) + { + fields[i]->SetVersion (version, revision); + posn += fields[i]->Parse (buffer, posn, size); + + // if we just parsed a TEXTENC field, we'd + // better tell the rest of the concerned string + // fields in the frame what they are expected to + // parse (ASCII or Unicode) + if (fields[i]->name == ID3FN_TEXTENC) + UpdateStringTypes(); + } + + hasChanged = false; + + return; +} + + diff --git a/Src/id3v2/id3_frame_render.cpp b/Src/id3v2/id3_frame_render.cpp new file mode 100644 index 00000000..acc2cdbf --- /dev/null +++ b/Src/id3v2/id3_frame_render.cpp @@ -0,0 +1,178 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +// improved/optimized/whatever 10/30/00 JF + +#include <string.h> +#include <memory.h> +#include "id3_tag.h" +#include "id3_misc_support.h" + + +luint ID3_Frame::Render (uchar *buffer) +{ + luint bytesUsed = 0; + + ID3_FrameHeader header; + ID3_FrameDef *info; + luint flags; + luint extras = 0; + + header.SetVersion (version, revision); + bytesUsed += header.Size(); + + // here is where we include things like + // grouping IDs and crypto IDs + if (strlen (encryptionID)) + { + buffer[bytesUsed] = encryptionID[0]; + bytesUsed++, extras++; + } + + if (strlen (groupingID)) + { + buffer[bytesUsed] = groupingID[0]; + bytesUsed++, extras++; + } + + /* + if (version < 4) + { + // benski> set any UTF8 strings read from id3v2.4 to UTF-16, + // so we can write with id3v2.3 + for (luint i = 0; i < numFields; i++) + { + if (fields[i]->flags & ID3FF_ADJUSTENC) + { + ID3_TextEnc enc= (ID3_TextEnc) Field(ID3FN_TEXTENC).Get(); + + if (enc == ID3TE_UTF8 || enc == ID3TE_UTF16_BE) + Field(ID3FN_TEXTENC).Set(ID3TE_UNICODE); + } + } + } + */ + + // this call is to tell the string fields + // what they should be rendered/parsed as + // (ASCII or Unicode) + UpdateStringTypes(); + + for (luint i = 0; i < numFields; i++) + { + fields[i]->SetVersion (version, revision); + bytesUsed += fields[i]->Render (&buffer[bytesUsed]); + } + + // if we can compress frames individually and we + // have been asked to compress the frames + /* + if (compression && version >= 3) + { + luint newFrameSize; + uchar *newTemp; + bytesUsed -= header.Size(); + newFrameSize = bytesUsed + (bytesUsed / 10) + 12; + if (newTemp = new uchar[newFrameSize]) + { + if (compress (newTemp, &newFrameSize, &buffer[header.Size() + extras], bytesUsed - extras) == Z_OK) + { + // if the compression actually saves space + if ((newFrameSize + sizeof (luint)) < bytesUsed) + { + luint posn; + int i; + + posn = header.Size(); + extras += sizeof (luint); + + memcpy (&buffer[posn + sizeof (luint)], newTemp, newFrameSize); + + for (i = 0; i < sizeof (luint); i++) + buffer[posn + i] = (uchar) ((bytesUsed >> ((sizeof (luint) - i - 1) * 8)) & 0xFF); + + bytesUsed = newFrameSize + sizeof (luint); + didCompress = true; + } + } + else + ID3_THROW (ID3E_zlibError); + + bytesUsed += header.Size(); + + delete[] newTemp; + } + else + ID3_THROW (ID3E_NoMemory); + } + */ + + // perform any encryption here + /* if (strlen (encryptionID)) + { + }*/ + + // determine which flags need to be set + if (info = ID3_FindFrameDef (frameID)) + { + bool didCompress = false; + flags = 0; + + if (version == 4) + { + if (info->tagDiscard) + flags |= ID3FL_TAGALTER_2_4; + + if (info->fileDiscard) + flags |= ID3FL_FILEALTER_2_4; + + if (didCompress) + flags |= ID3FL_COMPRESSION_2_4; + + if (strlen (encryptionID)) + flags |= ID3FL_ENCRYPTION_2_4; + + if (strlen (groupingID)) + flags |= ID3FL_GROUPING_2_4; + } + else + { + if (info->tagDiscard) + flags |= ID3FL_TAGALTER_2_3; + + if (info->fileDiscard) + flags |= ID3FL_FILEALTER_2_3; + + if (didCompress) + flags |= ID3FL_COMPRESSION_2_3; + + if (strlen (encryptionID)) + flags |= ID3FL_ENCRYPTION_2_3; + + if (strlen (groupingID)) + flags |= ID3FL_GROUPING_2_3; + } + } + else + ID3_THROW (ID3E_InvalidFrameID); + + header.SetFrameID(frameID); + header.SetFlags(flags); + header.SetDataSize(bytesUsed - header.Size()); + header.Render(buffer); + hasChanged = false; + + return bytesUsed; +} + + diff --git a/Src/id3v2/id3_header.cpp b/Src/id3v2/id3_header.cpp new file mode 100644 index 00000000..7da3592e --- /dev/null +++ b/Src/id3v2/id3_header.cpp @@ -0,0 +1,98 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include <string.h> +#include <memory.h> +#include "id3_header.h" +#include "id3_error.h" + + +static ID3_HeaderInfo ID3_VersionInfo[4][3] = +{ + // SIZEOF SIZEOF SIZEOF EXT EXT EXPERIM + // VER REV FRID FRSZ FRFL HEADER SIZE BIT + { + { 2, 0, 3, 3, 0, false, 0, false }, + { 2, 1, 3, 3, 0, true, 8, true }, + {0,}, + }, + { + { 3, 0, 4, 4, 2, false, 10, false }, + {0,}, + }, + { + { 4, 0, 4, 4, 2, false, 10, false }, + {0,}, + }, + { 0 } +}; + +ID3_HeaderInfo *ID3_LookupHeaderInfo(uchar ver, uchar rev) +{ + ID3_HeaderInfo *info = NULL; + size_t v=0,r=0; + + while (ID3_VersionInfo[v][0].version != 0) + { + r=0; + if (ID3_VersionInfo[v][0].version == ver) + { + while (ID3_VersionInfo[v][r].version != 0) + { + if (ID3_VersionInfo[v][r].revision == rev) + { + goto found; + } + else + r++; + } + // later revision. still backwards compat so we'll stick with it. + r--; + goto found; + } + else + v++; + } +found: + + if (ID3_VersionInfo[v][r].version != 0) + info = &ID3_VersionInfo[v][r]; + + return info; +} + +ID3_Header::ID3_Header(void) +{ + SetVersion(ID3_TAGVERSION, ID3_TAGREVISION); + dataSize = 0; + flags = 0; +} + +void ID3_Header::SetVersion(uchar ver, uchar rev) +{ + version = ver; + revision = rev; + info = ID3_LookupHeaderInfo(version, revision); +} + +void ID3_Header::SetDataSize(luint newSize) +{ + dataSize = newSize; +} + +void ID3_Header::SetFlags(luint newFlags) +{ + flags = newFlags; +} + + diff --git a/Src/id3v2/id3_header.h b/Src/id3v2/id3_header.h new file mode 100644 index 00000000..18252c8e --- /dev/null +++ b/Src/id3v2/id3_header.h @@ -0,0 +1,80 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_HEADER_H +#define ID3LIB_HEADER_H + +#include "id3_types.h" + +#define MIN_ID3_TAGVERSION 2 +#define MAX_ID3_TAGVERSION 4 +#define ID3_TAGVERSION (3) +#define ID3_TAGREVISION (0) + +struct ID3_HeaderInfo +{ + unsigned __int8 version; + unsigned __int8 revision; + unsigned __int8 frameIDBytes; + unsigned __int8 frameSizeBytes; + unsigned __int8 frameFlagsBytes; + bool hasExtHeader; + luint extHeaderBytes; + bool setExpBit; +}; + +struct ID3_Quirks +{ + ID3_Quirks() : id3v2_4_itunes_bug(false) {} + bool id3v2_4_itunes_bug; // itunes doesn't write syncsafe values for 2.4 +}; + +class ID3_Header +{ +public: + ID3_Header (void); + + void SetVersion(uchar ver, uchar rev); + void SetDataSize(luint newSize); + void SetFlags(luint newFlags); + void SetQuirks(ID3_Quirks &_quirks) + { + quirks=_quirks; + } + + ID3_Quirks &GetQuirks() + { + return quirks; + } + + virtual luint Size(void) = 0; + virtual luint Render(unsigned __int8 *buffer) = 0; + + // *** PRIVATE INTERNAL DATA - DO NOT USE *** PRIVATE INTERNAL DATA - DO NOT USE *** + +protected: + unsigned __int8 version; // which version? + unsigned __int8 revision; // which revision? + luint dataSize; // how big is the data? + luint flags; // tag flags + ID3_HeaderInfo *info; // the info about this version of the headers + ID3_Quirks quirks; +}; + + +ID3_HeaderInfo *ID3_LookupHeaderInfo (uchar ver, uchar rev); + + +#endif + + diff --git a/Src/id3v2/id3_header_frame.cpp b/Src/id3v2/id3_header_frame.cpp new file mode 100644 index 00000000..4f7379bc --- /dev/null +++ b/Src/id3v2/id3_header_frame.cpp @@ -0,0 +1,181 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include <string.h> +#include <memory.h> +#include "id3_header_frame.h" +#include "id3_error.h" + +bool ID3_FrameAttr::HasDataLength(int version) +{ + if (version == 4) + return !!(flags & ID3FL_DATA_LENGTH_2_4); + else + return 0; +} + +bool ID3_FrameAttr::HasCompression(int version) +{ + if (version == 4) + return !!(flags & ID3FL_COMPRESSION_2_4); + else + return !!(flags & ID3FL_COMPRESSION_2_3); +} + +bool ID3_FrameAttr::HasEncryption(int version) +{ + if (version == 4) + return !!(flags & ID3FL_ENCRYPTION_2_4); + else + return !!(flags & ID3FL_ENCRYPTION_2_3); +} + +bool ID3_FrameAttr::HasGrouping(int version) +{ + if (version == 4) + return !!(flags & ID3FL_GROUPING_2_4); + else + return !!(flags & ID3FL_GROUPING_2_3); +} + +bool ID3_FrameAttr::HasUnsync(int version) +{ + if (version == 4) + return !!(flags & ID3FL_UNSYNC_2_4); + else + return false; +} + +void ID3_FrameAttr::ClearUnSync(int version) +{ + if (version == 4) + flags&= ~ID3FL_UNSYNC_2_4; +} + +void ID3_FrameAttr::SetFlags(luint _flags) +{ + flags = _flags; +} + +void ID3_FrameHeader::SetFrameID (ID3_FrameID id) +{ + frameID = id; +} + +luint ID3_FrameHeader::Size(void) +{ + if (!info) + return 0; + return info->frameIDBytes + info->frameSizeBytes + info->frameFlagsBytes; +} + +// TODO: benski> we should make a return value of 0 mean 'error' +luint ID3_FrameHeader::GetFrameInfo(ID3_FrameAttr &attr, const uchar *buffer, size_t remSize) +{ + luint posn = 0; + luint i = 0, bpos = 4; + + // verify that the text is all between A-Z and 0-9 (for TALB and TIT2, etc) + for (i = 0; i < 4; i++) + { + if (!((buffer[i] >= '0' && buffer[i] <= '9') || (buffer[i] >= 'A' && buffer[i] <= 'Z'))) + { + // TODO: benski> return an error here + // this helps us to get ID3v2.2 PIC frames without + // breaking others since it's not null-terminated! + bpos = i; + } + } + + memcpy(attr.textID, (char *) buffer, (bpos > 0 && bpos <= 4 ? bpos : 4)); + if (bpos == 3) attr.textID[3] = 0; + attr.textID[4] = 0; + + posn += info->frameIDBytes; + + attr.size = 0; + + for (i = 0; i < info->frameSizeBytes; i++) + attr.size |= buffer[posn + i] << ((info->frameSizeBytes - 1 - i) * 8); + + if (version == 4) // 2.4 uses syncsafe sizes + { + // many programs write non-syncsafe sizes anyway (iTunes is the biggest culprit) + // so we'll try to detect it. unfortunately this isn't foolproof + int mask = attr.size & 0x80808080; + if (!quirks.id3v2_4_itunes_bug // make sure we've havn't previously identified that this tag has a problem + && mask == 0) // if none of the 'reserved' bits are set + { + attr.size = int28().setFromFile(attr.size).get(); // convert to syncsafe value + } + else + { + // benski> cut for now. this can't be trusted because it applies on subsequent re-parses but not anything before this + // quirks.id3v2_4_itunes_bug = true; // mark that the tag has a problem + } + // TODO: it'd be nice to look ahead into the buffer and make sure that our calculated size + // lets us land on the start of a new frame + // although that isn't foolproof either (non-standard fields, etc) + } + posn += info->frameSizeBytes; + + luint flags=0; + flags = 0; + + for (i = 0; i < info->frameFlagsBytes; i++) + flags |= buffer[ posn + i ] << ((info->frameFlagsBytes - 1 - i) * 8); + + attr.SetFlags(flags); + + posn += info->frameFlagsBytes; + + return posn; +} + +luint ID3_FrameHeader::Render(uchar *buffer) +{ + luint bytesUsed = 0; + ID3_FrameDef *frameDef = NULL; + char *textID = NULL; + luint i; + + if (frameDef = ID3_FindFrameDef(frameID)) + { + if (info->frameIDBytes < strlen (frameDef->longTextID)) + textID = frameDef->shortTextID; + else + textID = frameDef->longTextID; + } + else + ID3_THROW (ID3E_InvalidFrameID); + + memcpy (&buffer[ bytesUsed ], (uchar *) textID, info->frameIDBytes); + bytesUsed += info->frameIDBytes; + + for (i = 0; i < info->frameSizeBytes; i++) + { + if (version==4) // 2.4 uses syncsafe sizes + buffer[ bytesUsed + i ] = (uchar) ((dataSize >> ((info->frameSizeBytes - i - 1) * 7)) & 0x7F); + else + buffer[ bytesUsed + i ] = (uchar) ((dataSize >> ((info->frameSizeBytes - i - 1) * 8)) & 0xFF); + } + + bytesUsed += info->frameSizeBytes; + + for (i = 0; i < info->frameFlagsBytes; i++) + buffer[ bytesUsed + i ] = (uchar) ((flags >> ((info->frameFlagsBytes - i - 1) * 8)) & 0xFF); + + bytesUsed += info->frameFlagsBytes; + + return bytesUsed; +}
\ No newline at end of file diff --git a/Src/id3v2/id3_header_frame.h b/Src/id3v2/id3_header_frame.h new file mode 100644 index 00000000..809c7bcc --- /dev/null +++ b/Src/id3v2/id3_header_frame.h @@ -0,0 +1,81 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_HEADER_FRAME_H +#define ID3LIB_HEADER_FRAME_H + + +#include "id3_types.h" +#include "id3_header.h" +#include "id3_header_tag.h" +#include "id3_field.h" + + +#define ID3FL_TAGALTER_2_3 (1 << 15) +#define ID3FL_FILEALTER_2_3 (1 << 14) +#define ID3FL_SIGNED_2_3 (1 << 13) + +#define ID3FL_COMPRESSION_2_3 (1 << 7) +#define ID3FL_ENCRYPTION_2_3 (1 << 6) +#define ID3FL_GROUPING_2_3 (1 << 5) + +#define ID3FL_TAGALTER_2_4 (1 << 14) +#define ID3FL_FILEALTER_2_4 (1 << 13) +#define ID3FL_SIGNED_2_4 (1 << 12) + +#define ID3FL_COMPRESSION_2_4 (1 << 3) +#define ID3FL_ENCRYPTION_2_4 (1 << 2) +#define ID3FL_GROUPING_2_4 (1 << 6) +#define ID3FL_UNSYNC_2_4 (1 << 1) + +#define ID3FL_DATA_LENGTH_2_4 (1 << 0) + +struct ID3_FrameAttr +{ + ID3_FrameAttr(void) : size(0), flags(0) { memset(&textID, 0, sizeof(textID)); } + ~ID3_FrameAttr(void) {} + + char textID[5]; + luint size; + +public: + void ClearUnSync(int version); + void SetFlags(luint _flags); + bool HasCompression(int version); + bool HasDataLength(int version); + bool HasEncryption(int version); + bool HasGrouping(int version); + bool HasUnsync(int version); +private: + luint flags; +}; + + +class ID3_FrameHeader : public ID3_Header +{ +public: + virtual luint Size(void); + void SetFrameID(ID3_FrameID id); + luint GetFrameInfo(ID3_FrameAttr &attr, const uchar *buffer, size_t remSize); + virtual luint Render(uchar *buffer); + + // *** PRIVATE INTERNAL DATA - DO NOT USE *** PRIVATE INTERNAL DATA - DO NOT USE *** + +protected: + ID3_FrameID frameID; // which frame are we the header for? +}; + + +#endif + + diff --git a/Src/id3v2/id3_header_tag.cpp b/Src/id3v2/id3_header_tag.cpp new file mode 100644 index 00000000..252cf2be --- /dev/null +++ b/Src/id3v2/id3_header_tag.cpp @@ -0,0 +1,86 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + +#include <string.h> +#include <memory.h> +#include "id3_header_tag.h" +#include "id3_error.h" + +// Analyses a buffer to determine if we have a valid ID3v2 tag header. +// If so, return the number of bytes (starting _after_ the header) to +// read so we get all of the tag + +lsint ID3_IsTagHeader(uchar header[ID3_TAGHEADERSIZE]) +{ + if (!memcmp ("ID3", header, 3) && header[3] <= MAX_ID3_TAGVERSION) + { + int28 temp(&header[6]); + return (int)temp.get(); + } + + return -1; +} + + +luint ID3_TagHeader::Size(void) +{ + luint bytesUsed = ID3_TAGHEADERSIZE; + + if (info && info->hasExtHeader) + bytesUsed += info->extHeaderBytes + sizeof (luint); + + return bytesUsed; +} + + +luint ID3_TagHeader::Render(uchar *buffer) +{ + luint bytesUsed = 0; + + memcpy (&buffer[bytesUsed], (uchar *) ID3_TAGID, strlen (ID3_TAGID)); + bytesUsed += strlen (ID3_TAGID); + + buffer[bytesUsed++] = version; + buffer[bytesUsed++] = revision; + + // do the automatic flags + if (info->setExpBit) + flags |= ID3HF_EXPERIMENTAL; + + if (info->hasExtHeader) + flags |= ID3HF_EXTENDEDHEADER; + + // set the flags byte in the header + buffer[bytesUsed++] = (uchar) (flags & 0xFF); + + int28 temp = (uint32_t)dataSize; + + for (luint i = 0; i < sizeof (luint); i++) + buffer[bytesUsed++] = temp[i]; + + // now we render the extended header + if (info->hasExtHeader) + { + luint i; + + for (i = 0; i < sizeof (luint); i++) + buffer[bytesUsed + i] = (uchar) ((info->extHeaderBytes >> ((sizeof (luint) - i - 1) * 8)) & 0xFF); + + bytesUsed += i; + } + + bytesUsed = Size(); + + return bytesUsed; +} + + diff --git a/Src/id3v2/id3_header_tag.h b/Src/id3v2/id3_header_tag.h new file mode 100644 index 00000000..04e87691 --- /dev/null +++ b/Src/id3v2/id3_header_tag.h @@ -0,0 +1,48 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_HEADER_TAG_H +#define ID3LIB_HEADER_TAG_H + + +#include "id3_types.h" +#include "id3_header.h" + + +#define ID3_TAGID "ID3" +#define ID3_TAGHEADERSIZE (10) + + +#define ID3HF_UNSYNC (1 << 7) +#define ID3HF_EXTENDEDHEADER (1 << 6) +#define ID3HF_EXPERIMENTAL (1 << 5) +#define ID3HF_FOOTER (1 << 4) // id3v2.4 + +#define ID3HF_2_3_MASK (ID3HF_UNSYNC | ID3HF_EXTENDEDHEADER | ID3HF_EXPERIMENTAL) +#define ID3HF_2_4_MASK (ID3HF_UNSYNC | ID3HF_EXTENDEDHEADER | ID3HF_EXPERIMENTAL | ID3HF_FOOTER) + + +class ID3_TagHeader : public ID3_Header +{ +public: +virtual luint Size(void); +virtual luint Render(uchar *buffer); +}; + + +lsint ID3_IsTagHeader(uchar header[ID3_TAGHEADERSIZE]); + + +#endif + + diff --git a/Src/id3v2/id3_int28.cpp b/Src/id3v2/id3_int28.cpp new file mode 100644 index 00000000..ed714a72 --- /dev/null +++ b/Src/id3v2/id3_int28.cpp @@ -0,0 +1,62 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// Mon Nov 23 18:34:01 1998 + + +#include "id3_int28.h" +#include <bfc/platform/types.h> + +int28::int28(uint32_t val) +{ + set ( val ); +} + + +int28::int28(const uchar *val) +{ + for ( int i = 0; i < sizeof ( uint32_t ); i++ ) + value[ i ] = val[ i ]; +} + + +void int28::set(uint32_t val) +{ + for ( int i = 0; i < sizeof ( uint32_t ); i++ ) + value[ sizeof ( uint32_t ) - 1 - i ] = (uint8_t) ( ( val >> ( i * 7 ) ) & 127 ) & 0xFF; + + return; +} + +int28 &int28::setFromFile(uint32_t val) +{ + for ( int i = 0; i < sizeof ( uint32_t ); i++ ) + value[sizeof(uint32_t) - 1 - i] = (uint8_t) (val >>(i*8)) & 0xFF; + + return *this; +} + + +luint int28::get ( void ) +{ + luint newSize = 0L; + uchar bytes [ 4 ]; + + bytes[ 3 ] = value[ 3 ] | ( ( value[ 2 ] & 1 ) << 7 ); + bytes[ 2 ] = ( ( value[ 2 ] >> 1 ) & 63 ) | ( ( value[ 1 ] & 3 ) << 6 ); + bytes[ 1 ] = ( ( value[ 1 ] >> 2 ) & 31 ) | ( ( value[ 0 ] & 7 ) << 5 ); + bytes[ 0 ] = ( ( value[ 0 ] >> 3 ) & 15 ); + + newSize = bytes[ 3 ] | ( (luint) bytes[ 2 ] << 8 ) | ( (luint) bytes[ 1 ] << 16 ) | ( (luint) bytes[ 0 ] << 24 ); + + return newSize; +} + + +uchar int28::operator[] ( luint posn ) +{ + return value[ posn ]; +} + diff --git a/Src/id3v2/id3_int28.h b/Src/id3v2/id3_int28.h new file mode 100644 index 00000000..ab1cb51c --- /dev/null +++ b/Src/id3v2/id3_int28.h @@ -0,0 +1,41 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_TYPES_28BITINT_H +#define ID3LIB_TYPES_28BITINT_H + + +#include "id3_types.h" + + +class int28 +{ +public: + int28( uint32_t val = 0 ); // used for int32 -> int28 conversion + int28( const uchar *val ); // used for int28 -> int32 conversion + int28 &setFromFile(uint32_t val); // used for int28 -> int32 conversion + +uchar operator[] ( size_t posn ); +luint get ( void ); + +// *** PRIVATE INTERNAL DATA - DO NOT USE *** PRIVATE INTERNAL DATA - DO NOT USE *** + +protected: +void set ( uint32_t val ); +uchar value[ sizeof ( luint ) ]; // the integer stored as a uchar array +}; + + +#endif + + diff --git a/Src/id3v2/id3_misc_support.cpp b/Src/id3v2/id3_misc_support.cpp new file mode 100644 index 00000000..75be26c8 --- /dev/null +++ b/Src/id3v2/id3_misc_support.cpp @@ -0,0 +1,175 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include "id3_misc_support.h" + + +int ID3_UnicodeToLatin(char *latin, const wchar_t *unicode, luint len, int inLen) +{ + if (unicode && latin && len) + return WideCharToMultiByte(28591, 0, unicode, inLen/*-1*/, latin, len, NULL, NULL) - 1; + else if (latin && len) + latin[0]=0; + return 0; +} + +int ID3_UnicodeToLocal(char *local, const wchar_t *unicode, luint len, int inLen) +{ + if (unicode && local && len) + return WideCharToMultiByte(CP_ACP, 0, unicode, inLen/*-1*/, local, len, NULL, NULL)-1; + else if (local && len) + local[0]=0; + return 0; +} + +int ID3_UnicodeToUTF8(char *local, const wchar_t *unicode, luint len, int inLen) +{ + if (unicode && local && len) + return WideCharToMultiByte(CP_UTF8, 0, unicode, inLen/*-1*/, local, len, NULL, NULL)-1; + else if (local && len) + local[0]=0; + return 0; +} + +void ID3_AddArtist(ID3_Tag *tag, char *text) +{ + if (tag->Find(ID3FID_LEADARTIST ) == NULL && + tag->Find (ID3FID_BAND ) == NULL && + tag->Find (ID3FID_CONDUCTOR ) == NULL && + tag->Find (ID3FID_COMPOSER ) == NULL && + text && text[0]) + { + ID3_Frame *artistFrame=new ID3_Frame; + artistFrame->SetID(ID3FID_LEADARTIST); + artistFrame->Field(ID3FN_TEXT).SetLocal(text); + tag->AddFrame(artistFrame, true); + } + + return; +} + +void ID3_AddArtist_Latin(ID3_Tag *tag, char *text) +{ + if (tag->Find (ID3FID_LEADARTIST ) == NULL && + tag->Find (ID3FID_BAND ) == NULL && + tag->Find (ID3FID_CONDUCTOR ) == NULL && + tag->Find (ID3FID_COMPOSER ) == NULL && + text && text[0]) + { + ID3_Frame *artistFrame= new ID3_Frame; + + artistFrame->SetID (ID3FID_LEADARTIST); + artistFrame->Field(ID3FN_TEXT).SetLatin(text); + tag->AddFrame (artistFrame, true ); + + } + + return; +} + + + +void ID3_AddAlbum(ID3_Tag *tag, char *text) +{ + if (tag->Find (ID3FID_ALBUM ) == NULL && strlen (text ) > 0 ) + { + ID3_Frame *albumFrame; + + if (albumFrame = new ID3_Frame ) + { + albumFrame->SetID (ID3FID_ALBUM ); + + albumFrame->Field(ID3FN_TEXT).SetLocal(text); + tag->AddFrame (albumFrame, true ); + } + else + ID3_THROW (ID3E_NoMemory ); + } + + return; +} + +void ID3_AddAlbum_Latin(ID3_Tag *tag, char *text) +{ + if (tag->Find(ID3FID_ALBUM) == NULL + && text && text[0]) + { + ID3_Frame *albumFrame = new ID3_Frame; + + albumFrame->SetID (ID3FID_ALBUM ); + + albumFrame->Field(ID3FN_TEXT).SetLocal(text); + tag->AddFrame (albumFrame, true ); + + } + + return; +} + +void ID3_AddTitle(ID3_Tag *tag, char *text) +{ + if (tag->Find(ID3FID_TITLE) == NULL + && text && text[0]) + { + ID3_Frame *titleFrame; + + if (titleFrame = new ID3_Frame) + { + titleFrame->SetID(ID3FID_TITLE); + titleFrame->Field(ID3FN_TEXT).SetLocal(text); + tag->AddFrame (titleFrame, true ); + } + else + ID3_THROW(ID3E_NoMemory); + } + + return; +} + +void ID3_AddTitle_Latin(ID3_Tag *tag, char *text) +{ + if (tag->Find(ID3FID_TITLE) == NULL + && text && text[0]) + { + ID3_Frame *titleFrame= new ID3_Frame; + + titleFrame->SetID(ID3FID_TITLE); + titleFrame->Field(ID3FN_TEXT).SetLatin(text); + tag->AddFrame(titleFrame, true); + } + + return; +} + + +void ID3_AddLyrics(ID3_Tag *tag, char *text) +{ + if (tag->Find (ID3FID_UNSYNCEDLYRICS ) == NULL && strlen (text ) > 0 ) + { + ID3_Frame *lyricsFrame; + + if (lyricsFrame = new ID3_Frame ) + { + lyricsFrame->SetID (ID3FID_UNSYNCEDLYRICS ); + lyricsFrame->Field(ID3FN_LANGUAGE).SetLatin("eng"); + lyricsFrame->Field(ID3FN_TEXT ).SetLocal(text); + tag->AddFrame (lyricsFrame, true ); + } + else + ID3_THROW (ID3E_NoMemory ); + } + + return; +} + + diff --git a/Src/id3v2/id3_misc_support.h b/Src/id3v2/id3_misc_support.h new file mode 100644 index 00000000..a17ebfea --- /dev/null +++ b/Src/id3v2/id3_misc_support.h @@ -0,0 +1,39 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_MISC_SUPPORT_H +#define ID3LIB_MISC_SUPPORT_H + + +#include <wchar.h> +#include <string.h> +#include "id3_types.h" +#include "id3_tag.h" + + +// in 'id3_misc_support.cpp' +void ID3_AddTitle(ID3_Tag *tag, char *text); +void ID3_AddTitle_Latin(ID3_Tag *tag, char *text); +void ID3_AddArtist(ID3_Tag *tag, char *text); +void ID3_AddArtist_Latin(ID3_Tag *tag, char *text); +void ID3_AddAlbum(ID3_Tag *tag, char *text); +void ID3_AddAlbum_Latin(ID3_Tag *tag, char *text); +void ID3_AddLyrics(ID3_Tag *tag, char *text); + +int ID3_UnicodeToLocal(char *local, const wchar_t *unicode, luint len, int inLen=-1); +int ID3_UnicodeToLatin(char *latin, const wchar_t *unicode, luint len, int inLen=-1); +int ID3_UnicodeToUTF8(char *latin, const wchar_t *unicode, luint len, int inLen=-1); + +#endif + + diff --git a/Src/id3v2/id3_tag.cpp b/Src/id3v2/id3_tag.cpp new file mode 100644 index 00000000..1fa1bcd2 --- /dev/null +++ b/Src/id3v2/id3_tag.cpp @@ -0,0 +1,316 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include "id3_tag.h" + + +luint ID3_Tag::instances = 0; + + +ID3_Tag &operator << (ID3_Tag& tag, ID3_Frame& frame) +{ + tag.AddFrame (&frame); + + return tag; +} + + +ID3_Tag &operator << (ID3_Tag& tag, ID3_Frame *frame) +{ + tag.AddFrame (frame); + + return tag; +} + + +ID3_Tag::ID3_Tag() +{ + syncBuffer=0; + forcedPadding=0; + SetupTag(); + + instances++; +} + +void ID3_Tag::ForcePading(luint _padding) +{ + forcedPadding=_padding; +} + +void ID3_Tag::SetupTag() +{ + version = ID3_TAGVERSION; + revision = ID3_TAGREVISION; + frameList = NULL; + binaryList = NULL; + findCursor = NULL; + syncOn = false; + compression = false; + padding = true; + extendedHeader = false; + globalUnsync = false; + + + Clear(); + + + + return ; +} + + +ID3_Tag::~ID3_Tag(void) +{ + + Clear(); + + instances--; + + if (instances == 0) + {}} + + +void ID3_Tag::Clear(void) +{ + if (frameList) + { + ClearList (frameList); + frameList = NULL; + } + + if (binaryList) + { + ClearList (binaryList); + binaryList = NULL; + } + + + findCursor = NULL; + hasChanged = true; + + free(syncBuffer); + syncBuffer=0; + + return ; +} + + +void ID3_Tag::DeleteElem(ID3_Elem *cur) +{ + if (cur) + { + if (cur->tagOwns) + { + if (cur->frame) + { + delete cur->frame; + cur->frame = NULL; + } + + if (cur->binary) + { + free(cur->binary); + cur->binary = NULL; + cur->binarySize=0; + } + } + + findCursor = NULL; + hasChanged = true; + + free(cur); + } + + return ; +} + + +void ID3_Tag::ClearList(ID3_Elem *list) +{ + ID3_Elem *cur = list; + + while (cur) + { + ID3_Elem *next; + + next = cur->next; + DeleteElem (cur); + cur = next; + } + + return ; +} + + +void ID3_Tag::AddFrame(ID3_Frame *newFrame, bool freeWhenDone) +{ + ID3_Elem *elem; + + if (newFrame) + { + if (elem = (ID3_Elem *)calloc(1, sizeof(ID3_Elem))) + { + elem->next = frameList; + elem->frame = newFrame; + elem->binary = NULL; + elem->binarySize = 0; + elem->tagOwns = freeWhenDone; + + frameList = elem; + findCursor = NULL; + + hasChanged = true; + } + else + ID3_THROW (ID3E_NoMemory); + } + else + ID3_THROW (ID3E_NoData); + + return ; +} + +void ID3_Tag::RemoveFrame(ID3_Frame *frame) +{ + ID3_Elem *elem = NULL; + + if (elem = Find (frame)) + RemoveFromList (elem, &frameList); + + return ; +} + + +void ID3_Tag::RemoveFromList (ID3_Elem *which, ID3_Elem **list) +{ + ID3_Elem *cur = *list; + + if (cur == which) + { + *list = which->next; + DeleteElem (which); + } + else + { + while (cur) + { + if (cur->next == which) + { + cur->next = which->next; + DeleteElem (which); + break; + } + else + cur = cur->next; + } + } + + return ; +} + + +bool ID3_Tag::HasChanged (void) +{ + bool changed = hasChanged; + + if (! changed) + { + ID3_Elem *cur = frameList; + + while (cur) + { + if (cur->frame) + changed = cur->frame->HasChanged(); + + if (changed) + break; + else + cur = cur->next; + } + } + + return changed; +} + + +void ID3_Tag::SetVersion(uchar ver, uchar rev) +{ + if (version != ver || revision != rev) + hasChanged = true; + + version = ver; + revision = rev; + + return ; +} + + +void ID3_Tag::SetUnsync(bool newSync) +{ + if (syncOn != newSync) + hasChanged = true; + + syncOn = newSync; + + return ; +} + +void ID3_Tag::SetExtendedHeader(bool ext) +{ + if (extendedHeader != ext) + hasChanged = true; + + extendedHeader = ext; + + return ; +} + + +void ID3_Tag::SetCompression (bool comp) +{ + if (compression != comp) + hasChanged = true; + + compression = comp; + + return ; +} + + +void ID3_Tag::SetPadding (bool pad) +{ + if (padding != pad) + hasChanged = true; + + padding = pad; + + return ; +} + + +luint ID3_Tag::NumFrames (void) +{ + luint numFrames = 0; + ID3_Elem *cur = frameList; + + while (cur) + { + numFrames++; + + cur = cur->next; + } + + return numFrames; +} + + diff --git a/Src/id3v2/id3_tag.h b/Src/id3v2/id3_tag.h new file mode 100644 index 00000000..cb219297 --- /dev/null +++ b/Src/id3v2/id3_tag.h @@ -0,0 +1,111 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_TAG_H +#define ID3LIB_TAG_H + +#include <windows.h> +#include <wchar.h> +#include <stdio.h> +#include "id3_types.h" +#include "id3_frame.h" +#include "id3_header_frame.h" +#include "id3_header_tag.h" +#include "id3_version.h" + + +// for file buffers etc +#define BUFF_SIZE (65536) + + +struct ID3_Elem +{ + ID3_Elem *next; + ID3_Frame *frame; + uchar *binary; + size_t binarySize; + bool tagOwns; +}; + +class ID3_Tag +{ +public: + ID3_Tag(); + ~ID3_Tag(void); + + void Clear(void); + bool HasChanged(void); + void SetUnsync(bool newSync); + void SetExtendedHeader(bool ext); + void SetCompression(bool comp); + void SetPadding(bool pad); + void ForcePading(luint _padding); + void AddFrame(ID3_Frame *newFrame, bool freeWhenDone = false); + void RemoveFrame(ID3_Frame *oldFrame); + luint Render(uchar *buffer); + luint Size(void); + void Parse(const uchar header[ID3_TAGHEADERSIZE], const uchar *buffer); + ID3_Frame *Find(ID3_FrameID id); + ID3_Frame *Find(ID3_FrameID id, ID3_FieldID fld, luint data); + ID3_Frame *Find(ID3_FrameID id, ID3_FieldID fld, const wchar_t *data); + ID3_Frame *Find(ID3_FrameID id, ID3_FieldID fld, const char *data); + luint NumFrames(void); + ID3_Frame *GetFrameNum(luint num); + ID3_Frame *operator[] (luint num); + + // *** PRIVATE INTERNAL DATA - DO NOT USE *** PRIVATE INTERNAL DATA - DO NOT USE *** + + void SetupTag(); + void SetVersion(uchar ver, uchar rev); + void ClearList(ID3_Elem *list); + void DeleteElem(ID3_Elem *cur); + void AddBinary(const uchar *buffer, luint size); + void ExpandBinaries(const uchar *buffer, luint size); + void ProcessBinaries(ID3_FrameID whichFrame = ID3FID_NOFRAME, bool attach = true); // this default means all frames + void RemoveFromList(ID3_Elem *which, ID3_Elem **list); + ID3_Elem *GetLastElem(ID3_Elem *list); + ID3_Elem *Find(ID3_Frame *frame); + luint PaddingSize(luint curSize); + void RenderExtHeader(uchar *buffer); + + luint GetUnSyncSize (uchar *buffer, luint size); + void UnSync (uchar *destData, luint destSize, uchar *sourceData, luint sourceSize); + luint ReSync (uchar *binarySourceData, luint sourceSize); + uchar version; // what version tag? + uchar revision; // what revision tag? + ID3_Elem *frameList; // the list of known frames currently attached to this tag + ID3_Elem *binaryList; // the list of yet-to-be-parsed frames currently attached to this tag + ID3_Elem *findCursor; // on which element in the frameList are we currently positioned? + bool syncOn; // should we unsync this tag when rendering? + bool compression; // should we compress frames when rendering? + bool padding; // add padding to tags? + bool extendedHeader; // create an extended header when rendering? + bool hasChanged; // has the tag changed since the last parse or render? + //FILE *fileHandle; // a handle to the file we are linked to + luint forcedPadding; + + bool globalUnsync; // did the header indicate that all frames are unsync'd? + static luint instances; // how many ID3_Tag objects are floating around in this app? + + ID3_Quirks quirks; + uchar *syncBuffer; // so we don't destroy someone else's data when we unsynchronize +}; + + +ID3_Tag& operator<< (ID3_Tag& tag, ID3_Frame& frame); +ID3_Tag& operator<< (ID3_Tag& tag, ID3_Frame *frame); + + +#endif + + diff --git a/Src/id3v2/id3_tag_file.cpp b/Src/id3v2/id3_tag_file.cpp new file mode 100644 index 00000000..984be30e --- /dev/null +++ b/Src/id3v2/id3_tag_file.cpp @@ -0,0 +1,18 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + +#include <windows.h> + +#include <string.h> +#include "id3_tag.h" + + diff --git a/Src/id3v2/id3_tag_find.cpp b/Src/id3v2/id3_tag_find.cpp new file mode 100644 index 00000000..8b342bf6 --- /dev/null +++ b/Src/id3v2/id3_tag_find.cpp @@ -0,0 +1,199 @@ +// The authors have released ID3Lib as Public Domain(PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney(dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 +// improved/optimized/whatEVER jan-08-2006 benski + +#include "id3_tag.h" +#include "id3_misc_support.h" +#include "../nu/AutoWide.h" + +ID3_Elem *ID3_Tag::Find(ID3_Frame *frame) +{ + ID3_Elem *cur = frameList; + + while(cur) + { + if (cur->frame == frame) + return cur; + cur = cur->next; + } + + return NULL; +} + + +ID3_Frame *ID3_Tag::Find(ID3_FrameID id) +{ + ID3_Elem *cur = findCursor; + + if (cur == NULL) + findCursor = cur = frameList; + + while(cur) + { + if (cur->frame && cur->frame->GetID() == id) + { + findCursor = cur->next; + return cur->frame; + } + cur = cur->next; + + if (cur == NULL) cur = frameList; + if (cur == findCursor) break; + } + + return NULL; +} + +ID3_Frame *ID3_Tag::Find(ID3_FrameID id, ID3_FieldID fld, const wchar_t *data) +{ + ID3_Elem *cur = findCursor; + + if (cur == NULL) + findCursor = cur = frameList; + + while(cur) + { + if (cur->frame && cur->frame->GetID() == id) + { + if (data && /*lstrlenW(data) &&*/ BS_ISSET(cur->frame->fieldBits, fld)) + { + wchar_t *buffer; + luint size; + + size = cur->frame->Field(fld).BinSize(); + + if (buffer =(wchar_t*)calloc(size, sizeof(wchar_t))) + { + buffer[0]=0; + cur->frame->Field(fld).GetUnicode(buffer, size); + + if (wcscmp(buffer, data) == 0) + { + free(buffer); + findCursor = cur->next; + return cur->frame; + } + + free(buffer); + } + } + } + cur = cur->next; + + if (cur == NULL) cur = frameList; + + if (cur == findCursor) break; + } + + return NULL; +} + + + +ID3_Frame *ID3_Tag::Find(ID3_FrameID id, ID3_FieldID fld, const char *data) +{ + ID3_Elem *cur = findCursor; + + if (cur == NULL) + findCursor = cur = frameList; + + while(cur) + { + if (cur->frame && cur->frame->GetID() == id) + { + if (data && /*lstrlenW(data) &&*/ BS_ISSET(cur->frame->fieldBits, fld)) + { + char *buffer; + luint size; + + size = cur->frame->Field(fld).BinSize(); + + if (buffer =(char*)calloc(size, sizeof(char))) + { + buffer[0]=0; + cur->frame->Field(fld).GetLocal(buffer, size); + + if (strcmp(buffer, data) == 0) + { + free(buffer); + findCursor = cur->next; + return cur->frame; + } + + free(buffer); + } + } + } + cur = cur->next; + + if (cur == NULL) cur = frameList; + + if (cur == findCursor) break; + } + + return NULL; +} + + + +ID3_Frame *ID3_Tag::Find(ID3_FrameID id, ID3_FieldID fld, luint data) +{ + ID3_Elem *cur = findCursor; + + if (cur == NULL) + findCursor = cur = frameList; + + while(cur) + { + if (cur->frame &&(cur->frame->GetID() == id)) + { + if (cur->frame->Field(fld).Get() == data) + { + findCursor=cur->next; + return cur->frame; + } + } + cur = cur->next; + + if (cur == NULL) cur = frameList; + if (cur == findCursor) break; + } + + return NULL; +} + + +ID3_Frame *ID3_Tag::GetFrameNum(luint num) +{ + luint curNum=0; + ID3_Elem *cur = frameList; + + while(cur) + { + if (num == curNum) + { + return cur->frame; + } + curNum++; + cur = cur->next; + } + + return 0; +} + + +ID3_Frame *ID3_Tag::operator[](luint num) +{ + return GetFrameNum(num); +} + + diff --git a/Src/id3v2/id3_tag_parse.cpp b/Src/id3v2/id3_tag_parse.cpp new file mode 100644 index 00000000..77734bcf --- /dev/null +++ b/Src/id3v2/id3_tag_parse.cpp @@ -0,0 +1,449 @@ +// The authors have released ID3Lib as Public Domain(PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney(dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include <windows.h> +#include <stdio.h> +#include <string.h> +#include <memory.h> +#include "id3_tag.h" +#include "../Plugins/Input/in_mp3/LAMEinfo.h" +#include <assert.h> +#include "zlib.h" + +ID3_Elem *ID3_Tag::GetLastElem(ID3_Elem *list) +{ + ID3_Elem *last = list; + + while (last && last->next) + last = last->next; + + return last; +} + +void ID3_Tag::AddBinary(const uchar *buffer, luint size) +{ + uchar *newBin; + + if (size > 0) + { + if (newBin = (uchar*)calloc(size, sizeof(uchar))) + { + ID3_Elem * elem; + + memcpy(newBin, buffer, size); + + if (elem = (ID3_Elem*)calloc(1, sizeof(ID3_Elem))) + { + elem->next = NULL; + elem->frame = NULL; + elem->binary = newBin; + elem->binarySize = size; + elem->tagOwns = true; + + ID3_Elem * lastElem = GetLastElem(binaryList); + + if (lastElem) + lastElem->next = elem; + else + binaryList = elem; + } + else + { + free(newBin); + ID3_THROW(ID3E_NoMemory); + } + } + else + ID3_THROW(ID3E_NoMemory); + } + else + ID3_THROW(ID3E_NoData); + + return ; +} + +void ID3_Tag::ExpandBinaries(const uchar *buffer, luint size) +{ + ID3_FrameAttr attr; + ID3_FrameHeader frHeader; + luint posn = 0; + + while (posn < (size - 6) && buffer[posn] != 0) + { + //luint newBinSize; + + frHeader.SetVersion(version, revision); + frHeader.SetQuirks(quirks); + + posn += frHeader.GetFrameInfo(attr, &buffer[posn], size); + //newBinSize = frHeader.Size() + attr.size; + + if ((posn + attr.size) > (size)) + { + ID3_THROW(ID3E_NoMemory); + return ; + } + + quirks=frHeader.GetQuirks(); + + // firstly, let's check to see if we are parsing a CDM. If so, + // let's expanded it out now. + if (strcmp(attr.textID, "CDM") == 0) + { + // if the method was zlib + if (buffer[posn] == 'z') + { + unsigned long expandedSize = 0; + uchar *expBin; + + expandedSize |= buffer[posn + 1] << 24; + expandedSize |= buffer[posn + 2] << 16; + expandedSize |= buffer[posn + 3] << 8; + expandedSize |= buffer[posn + 4]; + + if (expBin = (uchar*)calloc(expandedSize, sizeof(uchar))) + { + uncompress(expBin, &expandedSize, &buffer[posn + 1 + sizeof(luint)], (uLong)(attr.size - sizeof(luint) - 1)); + + ExpandBinaries(expBin, expandedSize); + + posn += attr.size; + + free(expBin); + } + } + } + else + { + AddBinary(&buffer[posn - frHeader.Size()], attr.size + frHeader.Size()); + posn += attr.size; + } + } + + return ; +} + +void ID3_Tag::ProcessBinaries(ID3_FrameID whichFrame, bool attach) +{ + ID3_FrameAttr attr; + ID3_FrameHeader frHeader; + ID3_Elem *cur = binaryList; + + frHeader.SetVersion(version, revision); + frHeader.SetQuirks(quirks); + while (cur && cur->binary) + { + ID3_FrameID id; + ID3_Frame *frame; + luint posn; + luint extras = 0; + unsigned long expandedSize = 0; + //uchar groupingID = 0; + //uchar encryptionID = 0; + + posn = frHeader.GetFrameInfo(attr, cur->binary, cur->binarySize); + assert(attr.size + frHeader.Size() == cur->binarySize); + uint32_t data_length = 0; + if (attr.HasDataLength(version)) + { + data_length = 0; + + for (int i = 0; i < 4; i++) + data_length |= cur->binary[posn + i] << ((data_length - 1 - i) * 8); + + // size of Re-sync'd data. we'll just ignore for now + data_length = int28().setFromFile(data_length).get(); + //attr.size = data_length; + posn+=4; + extras+=4; + } + + if (attr.HasCompression(version)) + { + if (attr.HasDataLength(version)) + expandedSize = data_length; + else + { + expandedSize |= cur->binary[posn + 0] << 24; + expandedSize |= cur->binary[posn + 1] << 16; + expandedSize |= cur->binary[posn + 2] << 8; + expandedSize |= cur->binary[posn + 3]; + + extras += sizeof(luint); + posn+=4; + } + } + + if (attr.HasEncryption(version)) + { + //encryptionID = cur->binary[posn]; + posn++, extras++; + } + + if (attr.HasGrouping(version)) + { + //groupingID = cur->binary[posn]; + posn++, extras++; + } + + id = ID3_FindFrameID(attr.textID); + + if ((id == whichFrame || whichFrame == ID3FID_NOFRAME) && id != ID3FID_NOFRAME) + { + uchar *expBin; + bool useExpBin = false; + luint frameSize= attr.size - extras; + + if (attr.HasUnsync(version) // if the per-frame unsync flag is set + && !globalUnsync) // but make sure we didn't already unsync the whole file + { + frameSize=ReSync(&cur->binary[posn], attr.size - 10) + extras; + } + + if (attr.HasCompression(version)) + { + if (!(expBin = (uchar*)calloc(expandedSize, sizeof(uchar)))) + ID3_THROW(ID3E_NoMemory); + + if (expBin) + { + int x = uncompress(expBin, &expandedSize, &cur->binary[posn], frameSize); + if (x == 0/*Z_OK*/) + { + useExpBin = true; + } + else + { + free(expBin); + expBin=0; + } + } + + } + + if (!(frame = new ID3_Frame)) + ID3_THROW(ID3E_NoMemory); + + ID3_Elem *elem; + + frame->SetVersion(version, revision); + frame->SetID(id); + + if (useExpBin) + { + frame->Parse(expBin, expandedSize); + free(expBin); + } + else + frame->Parse(&cur->binary[posn], frameSize); + + // here is where we call a special handler + // for this frame type if one is specified + // in the frame definition + { + ID3_FrameDef *frameInfo; + + frameInfo = ID3_FindFrameDef(id); + + if (frameInfo && frameInfo->parseHandler) + attach = frameInfo->parseHandler(frame); + } + + // if, after all is said and done, we + // are still supposed to attach our + // newly parsed frame to the tag, do so + if (attach) + { + if (!(elem = (ID3_Elem *)calloc(1, sizeof(ID3_Elem)))) + ID3_THROW(ID3E_NoMemory); + + elem->next = NULL; + elem->frame = frame; + elem->binary = NULL; + elem->binarySize=0; + elem->tagOwns = true; + + ID3_Elem * lastElem = GetLastElem(frameList); + + if (lastElem) + lastElem->next = elem; + else + frameList = elem; + } + else + { + // if not, delete it + delete frame; + } + + ID3_Elem *temp = cur; + cur = cur->next; + + RemoveFromList(temp, &binaryList); + } + else + { + cur = cur->next; + } + } + + return ; +} + + +void ID3_Tag::Parse(const uchar header[ID3_TAGHEADERSIZE], const uchar *buffer) +{ + luint tagSize = 0; + int28 temp = &header[6]; + luint posn = 0; + uchar prevVer = version; + uchar prevRev = revision; + + Clear(); + + tagSize = temp.get(); + + SetVersion(header[3], header[4]); + + // make sure we understand this version + if (version > MAX_ID3_TAGVERSION || version < MIN_ID3_TAGVERSION) + return; + + globalUnsync = !!(header[5] & ID3HF_UNSYNC); + if (globalUnsync) + { + assert(syncBuffer==0); + syncBuffer = (uchar *)calloc(tagSize, sizeof(uchar)); + memcpy(syncBuffer, buffer, tagSize); + buffer=syncBuffer; + tagSize = ReSync(syncBuffer, tagSize); + } + + + // okay, if we are 2.01, then let's skip over the + // extended header for now because I am lazy + if (version == 2 && revision == 1) + if (header[5] & ID3HF_EXTENDEDHEADER) + { + luint extSize = 0; + + extSize |= buffer[0] << 24; + extSize |= buffer[1] << 16; + extSize |= buffer[2] << 8; + extSize |= buffer[3] << 0; + + posn = extSize + sizeof(luint); + } + + // okay, if we are 3.00, then let's actually + // parse the extended header(for now, we skip + // it because we are lazy) + if (version == 3 && revision == 0) + { + // according to id3v2.3 specs section 3.1 + // "All the other flags should be cleared. If one of these undefined flags are set that might mean that the tag is not readable for a parser that does not know the flags function." + if (header[5] & ~ID3HF_2_3_MASK) + { + // TODO: benski> is this the best way to show an error? + Clear(); + return; + } + + if (header[5] & ID3HF_EXTENDEDHEADER) + { + luint extSize = 0; + + extSize |= buffer[0] << 24; + extSize |= buffer[1] << 16; + extSize |= buffer[2] << 8; + extSize |= buffer[3] << 0; + + posn = extSize + sizeof(luint); + } + } + + // id3v2.4 + if (version == 4 && revision == 0) + { + // according to id3v2.4 specs section 3.1 + // "All the other flags MUST be cleared. If one of these undefined flags + // are set, the tag might not be readable for a parser that does not + // know the flags function." + if (header[5] & ~ID3HF_2_4_MASK) + { + // TODO: benski> is this the best way to show an error? + Clear(); + return; + } + + if (header[5] & ID3HF_EXTENDEDHEADER) + { + luint extSize = 0; + + extSize |= buffer[0] << 24; + extSize |= buffer[1] << 16; + extSize |= buffer[2] << 8; + extSize |= buffer[3] << 0; + + posn = extSize + sizeof(luint); + } + } + + if (posn >= tagSize) + { + // TODO: benski> is this the best way to show an error? + Clear(); + return; + } + + // this call will convert the binary data block(tag) + // into a linked list of binary frames + ExpandBinaries(&buffer[posn], tagSize-posn); + + // let's parse the CRYPTO frames + // the 'false' parameter means "don't + // attach the frame to the tag when + // processed". This is because we have + // installed a parsing handler for the + // crypto reg frame. This is a default + // parameter - if the frame type has a + // custom parsing handler, that handler + // will tell ID3Lib whether to attach + // or not. + ProcessBinaries(ID3FID_CRYPTOREG, false); + + // let's parse the GROUPING frames + // the 'false' parameter means "don't + // attach the frame to the tag when + // processed". This is because we have + // installed a parsing handler for the + // crypto reg frame. This is a default + // parameter - if the frame type has a + // custom parsing handler, that handler + // will tell ID3Lib whether to attach + // or not. + ProcessBinaries(ID3FID_GROUPINGREG, false); + + // let's parse the rest of the binaries + ProcessBinaries(); + + // upgrade older tags to our preferred revision + if (prevVer > version || (prevVer == version && prevRev > revision)) + SetVersion(prevVer, prevRev); + + // set the flag which says that the tag hasn't changed + hasChanged = false; + + return ; +} + diff --git a/Src/id3v2/id3_tag_parse_lyrics3.cpp b/Src/id3v2/id3_tag_parse_lyrics3.cpp new file mode 100644 index 00000000..0ed3f839 --- /dev/null +++ b/Src/id3v2/id3_tag_parse_lyrics3.cpp @@ -0,0 +1,244 @@ +// The authors have released ID3Lib as Public Domain(PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney(dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <memory.h> +#include "id3_tag.h" +#include "id3_misc_support.h" + +/* +luint ID3_CRLFtoLF( char *buffer, luint size) +{ + luint newSize = 0; + char *dest = buffer; + char *source = buffer; + + if ( buffer && size) + { + while ( source < ( buffer + size)) + { + if ( *source == 0x0D) + source++; + else + *dest++ = *source++; + } + + newSize = dest - buffer; + } + else + ID3_THROW( ID3E_NoData); + + return newSize; +} +*/ +/* +luint ID3_StripTimeStamps( char *buffer, luint size) +{ + luint newSize = 0; + char *dest = buffer; + char *source = buffer; + + if ( buffer && size) + { + while ( source < ( buffer + size)) + { + if ( *source == '[') + source += 7; + else + *dest++ = *source++; + } + + newSize = dest - buffer; + } + else + ID3_THROW( ID3E_NoData); + + return newSize; +} +*/ +/* +void ID3_Tag::ParseLyrics3( void) +{ + if (file_handle != INVALID_HANDLE_VALUE) + { + uchar buffer[ 18 ]; + DWORD dw; + + SetFilePointer(file_handle, -143, NULL, FILE_END); + ReadFile(file_handle, buffer, 18, &dw, NULL); + + // first check for an ID3v1 tag + if ( memcmp( &buffer[ 15 ], "TAG", 3) == 0) + { + if ( memcmp( &buffer[ 6 ], "LYRICSEND", 9) == 0) + { + // we have a Lyrics3 v1.00 tag + } + else if ( memcmp( &buffer[ 6 ], "LYRICS200", 9) == 0) + { + // we have a Lyrics3 v2.00 tag + luint lyricsSize; + + buffer[ 6 ] = 0; + int intSize = atoi((char *) buffer); + + if (intSize > 0) + lyricsSize = intSize; + else + return; + + SetFilePointer(file_handle, -143 - lyricsSize, NULL, FILE_END); + ReadFile(file_handle, buffer, 11, &dw, NULL); + + if ( memcmp( buffer, "LYRICSBEGIN", 11) == 0) + { + hasL3Tag = true; + + luint bytesToRead = lyricsSize - 11; + uchar *buff2; + + extraBytes += lyricsSize + 9 + 6; + + if ( buff2 = (uchar*)malloc(bytesToRead)) + { + luint posn = 0; + bool stampsUsed = false; + + ReadFile(file_handle, buff2, bytesToRead, &dw, NULL); + + while ( posn < bytesToRead) + { + uchar fid[ 4 ]; + uchar sizeT[ 6 ]; + luint size; + + fid[ 3 ] = 0; + sizeT[ 5 ] = 0; + + memcpy( fid, &buff2[ posn ], 3); + memcpy( sizeT, &buff2[ posn + 3 ], 5); + int intSize = atoi((char *)sizeT); + if (intSize>0) + { + size = intSize; + } + else + { + free(buff2); + return; + } + + // the IND field + if ( strcmp((char *) fid, "IND") == 0) + { + if ( buff2[ posn + 8 + 1 ] == '1') + stampsUsed = true; + } + + // the TITLE field + if ( strcmp((char *) fid, "ETT") == 0) + { + char *text; + + if ( text = (char*)malloc(size + 1)) + { + text[ size ] = 0; + memcpy( text, &buff2[ posn + 8 ], size); + + ID3_AddTitle( this, text); + + free(text); + } + else + ID3_THROW( ID3E_NoMemory); + } + + // the ARTIST field + if ( strcmp((char *) fid, "EAR") == 0) + { + char *text; + + if ( text = (char*)malloc(size + 1)) + { + text[ size ] = 0; + memcpy( text, &buff2[ posn + 8 ], size); + + ID3_AddArtist( this, text); + + free(text); + } + else + ID3_THROW( ID3E_NoMemory); + } + + // the ALBUM field + if ( strcmp((char *) fid, "EAL") == 0) + { + char *text; + + if ( text = (char*)malloc(size + 1)) + { + text[ size ] = 0; + memcpy( text, &buff2[ posn + 8 ], size); + + ID3_AddAlbum( this, text); + + free(text); + } + else + ID3_THROW( ID3E_NoMemory); + } + + // the LYRICS field + if ( strcmp((char *) fid, "LYR") == 0) + { + char *text; + luint newSize; + + newSize = ID3_CRLFtoLF((char *) & buff2[ posn + 8 ], size); + + if ( stampsUsed) + newSize = ID3_StripTimeStamps((char *) & buff2[ posn + 8 ], newSize); + + if ( text = (char*)malloc(newSize + 1)) + { + text[ newSize ] = 0; + + memcpy( text, &buff2[ posn + 8 ], newSize); + + ID3_AddLyrics( this, text); + + free(text); + } + else + ID3_THROW( ID3E_NoMemory); + } + + posn += size + 8; + } + + free(buff2); + } + } + } + } + } + else + ID3_THROW( ID3E_NoData); + + return ; +} +*/ + diff --git a/Src/id3v2/id3_tag_parse_v1.cpp b/Src/id3v2/id3_tag_parse_v1.cpp new file mode 100644 index 00000000..09a0f083 --- /dev/null +++ b/Src/id3v2/id3_tag_parse_v1.cpp @@ -0,0 +1,22 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include <stdio.h> +#include <string.h> +#include <memory.h> +#include "id3_tag.h" +#include "id3_misc_support.h" + + + + diff --git a/Src/id3v2/id3_tag_render.cpp b/Src/id3v2/id3_tag_render.cpp new file mode 100644 index 00000000..3e30167f --- /dev/null +++ b/Src/id3v2/id3_tag_render.cpp @@ -0,0 +1,151 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include <string.h> +#include <memory.h> +#include "id3_tag.h" +#include "id3_misc_support.h" +#include <windows.h> + + + +luint ID3_Tag::Render( uchar *buffer ) +{ + luint bytesUsed = 0; + + ID3_Elem *cur = frameList; + ID3_TagHeader header; + + if (version > ID3_TAGVERSION || (version == ID3_TAGVERSION && revision > ID3_TAGREVISION)) + SetVersion(version, revision); + else + SetVersion ( ID3_TAGVERSION, ID3_TAGREVISION ); + + header.SetVersion ( version, revision ); + bytesUsed += header.Size(); + + // set up the encryption and grouping IDs + + while (cur) + { + if (cur->frame) + { + cur->frame->compression = compression; + cur->frame->SetVersion ( version, revision ); + bytesUsed += cur->frame->Render(&buffer[bytesUsed]); + } + + cur = cur->next; + } + + if (syncOn) + { + luint newTagSize; + + newTagSize = GetUnSyncSize ( &buffer[ header.Size() ], bytesUsed - header.Size() ); + + if ( newTagSize > 0 && ( newTagSize + header.Size() ) > bytesUsed ) + { + uchar *tempz; + if ( tempz = (uchar*)calloc(newTagSize, sizeof(uchar)) ) + { + UnSync ( tempz, newTagSize, &buffer[ header.Size() ], bytesUsed - header.Size() ); + header.SetFlags ( ID3HF_UNSYNC ); + + memcpy ( &buffer[ header.Size() ], tempz, newTagSize ); + bytesUsed = newTagSize + header.Size(); + free(tempz); + } + else + ID3_THROW ( ID3E_NoMemory ); + } + } + + // zero the remainder of the buffer so that our + // padding bytes are zero + luint paddingSize = PaddingSize(bytesUsed); + for ( luint i = 0; i < paddingSize; i++ ) + buffer[ bytesUsed + i ] = 0; + + bytesUsed += paddingSize; + + header.SetDataSize ( bytesUsed - header.Size() ); + header.Render ( buffer ); + + // set the flag which says that the tag hasn't changed + hasChanged = false; + + return bytesUsed; +} + + + +luint ID3_Tag::Size( void ) +{ + luint bytesUsed = 0; + ID3_Elem *cur = frameList; + ID3_TagHeader header; + + header.SetVersion(version, revision); + bytesUsed += header.Size(); + + while (cur) + { + if (cur->frame) + { + cur->frame->SetVersion ( version, revision ); + bytesUsed += cur->frame->Size(); + } + + cur = cur->next; + } + + // add 30% for sync + if (syncOn) + bytesUsed += bytesUsed / 3; + + bytesUsed += PaddingSize(bytesUsed); + + return bytesUsed; +} + + +void ID3_Tag::RenderExtHeader ( uchar *buffer ) +{ + if ( version == 3 && revision == 0 ) + { + } + + return; +} + +#define ID3_PADMULTIPLE ( 2048 ) +#define ID3_PADMAX ( 4096 ) + +luint ID3_Tag::PaddingSize(luint curSize) +{ + luint newSize = 0; + + // if padding is switched off + if (!padding) + return 0; + + if (forcedPadding) + return forcedPadding; + else + newSize = ( ( curSize / ID3_PADMULTIPLE ) + 1 ) * ID3_PADMULTIPLE; + + return newSize - curSize; +} + + diff --git a/Src/id3v2/id3_tag_sync.cpp b/Src/id3v2/id3_tag_sync.cpp new file mode 100644 index 00000000..75aef393 --- /dev/null +++ b/Src/id3v2/id3_tag_sync.cpp @@ -0,0 +1,123 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#include "id3_tag.h" + + +// To be used when reading an ID3v2-tag +// Transforms all FF 00 sequences into FF + +luint ID3_Tag::ReSync(uchar *binarySourceData, luint sourceSize) +{ + uchar *source, *dest; + uchar temp; + luint destinationSize; + + source = binarySourceData; + destinationSize = sourceSize; + + while (source < binarySourceData + sourceSize) + { + temp = *source++; + + if (temp == 0xFF && source < binarySourceData + sourceSize) + { + if ((temp = *source++) == 0x00) + destinationSize--; + } + } + + dest = source = binarySourceData; + + while ((source < binarySourceData + sourceSize) && (dest < binarySourceData + sourceSize)) + { + *dest++ = temp = *source++; + + if (temp == 0xFF && source < binarySourceData + sourceSize) + { + if ((temp = *source++) != 0x00 && dest < binarySourceData + sourceSize) + * dest++ = temp; + } + } + + for (luint cl=destinationSize;cl<sourceSize;cl++) + binarySourceData[cl]=0; + + return destinationSize; +} + + +// How big will the tag be after we unsync? + +luint ID3_Tag::GetUnSyncSize(uchar *buffer, luint size) +{ + luint extraSize = 0; + uchar *source = buffer; + + // Determine the size needed for the destination data + while (source < buffer + size) + { + uchar temp = *source++; + + if (temp == 0xFF) + { + // last byte? + if (source == (buffer + size)) + extraSize++; + else + { + temp = *source; + + if (((temp & 0xE0) == 0xE0) || (temp == 0)) + extraSize++; + } + } + } + + return extraSize + size; +} + + +// To be used when writing an ID3v2-tag +// Transforms: +// 11111111 111xxxxx -> 11111111 00000000 111xxxxx +// 11111111 00000000 -> 11111111 00000000 00000000 +// 11111111 <EOF> -> 11111111 00000000 <EOF> + +void ID3_Tag::UnSync(uchar *destData, luint destSize, uchar *sourceData, luint sourceSize) +{ + uchar *source = sourceData; + uchar *dest = destData; + + // Now do the real transformation + while (source < sourceData + sourceSize) + { + uchar temp = *dest++ = *source++; + + if (temp == 0xFF) + { + // last byte? + if (source == (sourceData + sourceSize)) + *dest++ = 0; + else + { + temp = *source; + + if (((temp & 0xE0) == 0xE0) || (temp == 0)) + *dest++ = 0; + } + } + } + + return ; +}
\ No newline at end of file diff --git a/Src/id3v2/id3_types.h b/Src/id3v2/id3_types.h new file mode 100644 index 00000000..aae48644 --- /dev/null +++ b/Src/id3v2/id3_types.h @@ -0,0 +1,58 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_TYPES_H +#define ID3LIB_TYPES_H + + +#include <wchar.h> +#include <bfc/platform/types.h> + + +typedef unsigned char uchar; +typedef short signed int ssint; +typedef short unsigned int suint; +typedef long signed int lsint; +typedef size_t luint; +typedef long double ldoub; +typedef long unsigned int * bitset; + +#define BS_SET(v,x) ( (v)[ (x) / ( sizeof ( luint ) * 8 ) ] |= ( 1 << ( (x) % ( sizeof ( luint ) * 8 ) ) ) ) +#define BS_CLEAR(v,x) ( (v)[ (x) / ( sizeof ( luint ) * 8 ) ] &= ~( 1 << ( (x) % ( sizeof ( luint ) * 8 ) ) ) ) +#define BS_ISSET(v,x) ( (v)[ (x) / ( sizeof ( luint ) * 8 ) ] & ( 1 << ( (x) % ( sizeof ( luint ) * 8 ) ) ) ) + +#ifndef NULL +#define NULL (0L) +#endif + +#ifndef MIN +inline lsint MIN ( lsint x, lsint y ) +{ + return x < y ? x : y; +} +#endif + +#ifndef MAX +inline lsint MAX ( lsint x, lsint y ) +{ + return x > y ? x : y; +} +#endif + +// include other abstract types here because they +// may depend on the types defined above +#include "id3_int28.h" + +#endif + + diff --git a/Src/id3v2/id3_version.h b/Src/id3v2/id3_version.h new file mode 100644 index 00000000..03d9a7ee --- /dev/null +++ b/Src/id3v2/id3_version.h @@ -0,0 +1,28 @@ +// The authors have released ID3Lib as Public Domain (PD) and claim no copyright, +// patent or other intellectual property protection in this work. This means that +// it may be modified, redistributed and used in commercial and non-commercial +// software and hardware without restrictions. ID3Lib is distributed on an "AS IS" +// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. +// +// The ID3Lib authors encourage improvements and optimisations to be sent to the +// ID3Lib coordinator, currently Dirk Mahoney (dirk@id3.org). Approved +// submissions may be altered, and will be included and released under these terms. +// +// Mon Nov 23 18:34:01 1998 + + +#ifndef ID3LIB_VERSION_H +#define ID3LIB_VERSION_H + + +#define ID3LIB_NAME "ID3Lib" +#define ID3LIB_VERSION "v3.05a" +#define ID3LIB_VER ( 3 ) +#define ID3LIB_REV ( 5 ) +#define ID3LIB_DATE "Mon Nov 23 18:34:01 1998" +#define ID3LIB_VERSTRING ID3LIB_NAME " " ID3LIB_VERSION " " ID3LIB_DATE + + +#endif + + diff --git a/Src/id3v2/id3v2.vcxproj b/Src/id3v2/id3v2.vcxproj new file mode 100644 index 00000000..1ec49196 --- /dev/null +++ b/Src/id3v2/id3v2.vcxproj @@ -0,0 +1,242 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup Label="ProjectConfigurations"> + <ProjectConfiguration Include="Debug|Win32"> + <Configuration>Debug</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Debug|x64"> + <Configuration>Debug</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|Win32"> + <Configuration>Release</Configuration> + <Platform>Win32</Platform> + </ProjectConfiguration> + <ProjectConfiguration Include="Release|x64"> + <Configuration>Release</Configuration> + <Platform>x64</Platform> + </ProjectConfiguration> + </ItemGroup> + <PropertyGroup Label="Globals"> + <ProjectGuid>{0C7AAFA2-2A78-4B91-99A3-3E866B484ADB}</ProjectGuid> + <RootNamespace>id3v2</RootNamespace> + <WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> + <ConfigurationType>StaticLibrary</ConfigurationType> + <PlatformToolset>v142</PlatformToolset> + <CharacterSet>Unicode</CharacterSet> + </PropertyGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> + <ImportGroup Label="ExtensionSettings"> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> + </ImportGroup> + <PropertyGroup Label="UserMacros" /> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <IncludePath>$(IncludePath)</IncludePath> + <LibraryPath>$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <LinkIncremental>true</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + <IncludePath>$(IncludePath)</IncludePath> + <LibraryPath>$(LibraryPath)</LibraryPath> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <LinkIncremental>false</LinkIncremental> + <OutDir>$(PlatformShortName)_$(Configuration)\</OutDir> + <IntDir>$(PlatformShortName)_$(Configuration)\</IntDir> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + <VcpkgConfiguration>Debug</VcpkgConfiguration> + </PropertyGroup> + <PropertyGroup Label="Vcpkg" Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <VcpkgInstalledDir> + </VcpkgInstalledDir> + <VcpkgUseStatic>false</VcpkgUseStatic> + <VcpkgTriplet>x86-windows-static-md</VcpkgTriplet> + </PropertyGroup> + <PropertyGroup Label="Vcpkg"> + <VcpkgEnableManifest>false</VcpkgEnableManifest> + </PropertyGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <DisableSpecificWarnings>4267;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> + <ClCompile> + <Optimization>Disabled</Optimization> + <AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;_DEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <MinimalRebuild>false</MinimalRebuild> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks> + <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>ProgramDatabase</DebugInformationFormat> + <DisableSpecificWarnings>4267;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> + <ClCompile> + <Optimization>MinSpace</Optimization> + <FavorSizeOrSpeed>Size</FavorSizeOrSpeed> + <AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary> + <BufferSecurityCheck>false</BufferSecurityCheck> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <DisableSpecificWarnings>4267;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Lib> + </ItemDefinitionGroup> + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> + <ClCompile> + <Optimization>MinSpace</Optimization> + <FavorSizeOrSpeed>Size</FavorSizeOrSpeed> + <AdditionalIncludeDirectories>../Wasabi;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN64;NDEBUG;_LIB;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <StringPooling>true</StringPooling> + <MultiProcessorCompilation>true</MultiProcessorCompilation> + <RuntimeLibrary>MultiThreaded</RuntimeLibrary> + <BufferSecurityCheck>false</BufferSecurityCheck> + <TreatWChar_tAsBuiltInType>true</TreatWChar_tAsBuiltInType> + <ForceConformanceInForLoopScope>true</ForceConformanceInForLoopScope> + <WarningLevel>Level3</WarningLevel> + <DebugInformationFormat>None</DebugInformationFormat> + <DisableSpecificWarnings>4267;%(DisableSpecificWarnings)</DisableSpecificWarnings> + <ProgramDataBaseFileName>$(IntDir)$(TargetName).pdb</ProgramDataBaseFileName> + </ClCompile> + <Lib> + <OutputFile>$(OutDir)$(TargetName)$(TargetExt)</OutputFile> + <AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> + </Lib> + </ItemDefinitionGroup> + <ItemGroup> + <ClCompile Include="id3_error.cpp" /> + <ClCompile Include="id3_field.cpp" /> + <ClCompile Include="id3_field_binary.cpp" /> + <ClCompile Include="id3_field_integer.cpp" /> + <ClCompile Include="id3_field_string_ascii.cpp" /> + <ClCompile Include="id3_field_string_unicode.cpp" /> + <ClCompile Include="id3_frame.cpp" /> + <ClCompile Include="id3_frame_parse.cpp" /> + <ClCompile Include="id3_frame_render.cpp" /> + <ClCompile Include="id3_header.cpp" /> + <ClCompile Include="id3_header_frame.cpp" /> + <ClCompile Include="id3_header_tag.cpp" /> + <ClCompile Include="id3_int28.cpp" /> + <ClCompile Include="id3_misc_support.cpp" /> + <ClCompile Include="id3_tag.cpp" /> + <ClCompile Include="id3_tag_file.cpp" /> + <ClCompile Include="id3_tag_find.cpp" /> + <ClCompile Include="id3_tag_parse.cpp" /> + <ClCompile Include="id3_tag_render.cpp" /> + <ClCompile Include="id3_tag_sync.cpp" /> + </ItemGroup> + <ItemGroup> + <ClInclude Include="id3_dll.h" /> + <ClInclude Include="id3_error.h" /> + <ClInclude Include="id3_externals.h" /> + <ClInclude Include="id3_field.h" /> + <ClInclude Include="id3_frame.h" /> + <ClInclude Include="id3_header.h" /> + <ClInclude Include="id3_header_frame.h" /> + <ClInclude Include="id3_header_tag.h" /> + <ClInclude Include="id3_int28.h" /> + <ClInclude Include="id3_misc_support.h" /> + <ClInclude Include="id3_tag.h" /> + <ClInclude Include="id3_types.h" /> + <ClInclude Include="id3_version.h" /> + </ItemGroup> + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> + <ImportGroup Label="ExtensionTargets"> + </ImportGroup> +</Project>
\ No newline at end of file diff --git a/Src/id3v2/id3v2.vcxproj.filters b/Src/id3v2/id3v2.vcxproj.filters new file mode 100644 index 00000000..460a1942 --- /dev/null +++ b/Src/id3v2/id3v2.vcxproj.filters @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <ItemGroup> + <ClCompile Include="id3_tag_sync.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_tag_render.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_tag_parse.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_tag_find.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_tag_file.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_tag.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_misc_support.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_int28.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_header_tag.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_header_frame.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_header.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_frame_render.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_frame_parse.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_frame.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_field_string_ascii.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_field_string_unicode.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_field_integer.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_field_binary.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_field.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + <ClCompile Include="id3_error.cpp"> + <Filter>Source Files</Filter> + </ClCompile> + </ItemGroup> + <ItemGroup> + <ClInclude Include="id3_dll.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_error.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_externals.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_field.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_frame.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_header.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_header_frame.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_header_tag.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_int28.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_misc_support.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_tag.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_types.h"> + <Filter>Header Files</Filter> + </ClInclude> + <ClInclude Include="id3_version.h"> + <Filter>Header Files</Filter> + </ClInclude> + </ItemGroup> + <ItemGroup> + <Filter Include="Header Files"> + <UniqueIdentifier>{46ade71f-4fd9-4b0f-892b-56a821313b48}</UniqueIdentifier> + </Filter> + <Filter Include="Ressource Files"> + <UniqueIdentifier>{eba6dadd-5cbf-4fe4-873d-c7937c58f6fc}</UniqueIdentifier> + </Filter> + <Filter Include="Source Files"> + <UniqueIdentifier>{5bc6abde-bd55-40fa-88a7-043a118989c6}</UniqueIdentifier> + </Filter> + </ItemGroup> +</Project>
\ No newline at end of file |