-
Notifications
You must be signed in to change notification settings - Fork 5
/
id3v2.h
199 lines (159 loc) · 7.01 KB
/
id3v2.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#ifndef ID3V2_H
#define ID3V2_H
#include <stdio.h>
#include <stdbool.h>
//#define ID3V2PADDING 2048 // number of padding bytes at the end - maybe some tools want to have some
#define ID3V2PADDING 0 // number of padding bytes at the end - maybe some tools want to have some
#define ID3V2ERROR_NOERROR 0 // no error - all is good
#define ID3V2ERROR_FATAL -1000 // if malloc returns NULL or other worst case errors (better to exit(-1))
#define ID3V2ERROR_PATHERROR -1 // problem with the path (for example fopen failed)
#define ID3V2ERROR_NOTSUPPORTED -2
#define ID3V2ERROR_FRAMENOTFOUND -3
#define ID3V2ERROR_UNICODEERROR -4
#define ID3V2ERROR_MISFITTINGSUBID -5
#define ID3V2ERROR_WRITEERROR -6
#define ID3V2ERROR_UNEXPECTEDEOF -7
#define ID3V2ERROR_UNSUPPORTEDENCODING -8
#define ID3V2ERROR_BUFFEROVERFLOW -9
#define ID3V2HEADERFLAG_UNSYNCHRONISATION (1<<7)
#define ID3V2HEADERFLAG_EXTENDEDHEADER (1<<6)
#define ID3V2HEADERFLAG_EXPERIMENTAL (1<<5)
#define ID3V2HEADERFLAG_FOOTER (1<<4) /*indicates a footer - new in 2.4*/
// all structs are interpreted and decoded versions of the raw data
typedef struct
{
unsigned char ID[3]; // 'ID3' - no 0-byte at the end!
unsigned char version_major; // 3 \_ for ID3v2.3.0
unsigned char version_minor; // 0 /
unsigned char flags; // ID3V2HEADERFLAG_*
unsigned int origsize; // size of the ID3 infos as stored in the files header
unsigned int realsize; // sum of all read ID3 data (incl. frame-header) excluding padding bytes
// realsize will be always up to date after changing frames,
// origsize will never change
} ID3V2_HEADER;
#define ID3V230EXTHDRFLAG_CRC (1<<15)
#define ID3V240EXTHDRFLAG_UPDATE (1<<6)
#define ID3V240EXTHDRFLAG_CRC (1<<5)
#define ID3V240EXTHDRFLAG_RESTRICTED (1<<4)
typedef struct
{
unsigned int size; // keep in mind to update when changing the ext. header
unsigned int paddingsize; // ID3v2.3.0 only
bool flag_update;
bool flag_crc;
bool flag_restricted;
unsigned long crc;
unsigned long realcrc;
unsigned char restrictions;
} ID3V2_EXTHEADER;
#define ID3V230FRAMEFLAG_TagAlterPreservation (1<<15)
#define ID3V230FRAMEFLAG_FileAlterPreservation (1<<14)
#define ID3V230FRAMEFLAG_ReadOnly (1<<13)
#define ID3V230FRAMEFLAG_Compression (1<< 7)
#define ID3V230FRAMEFLAG_Encryption (1<< 6)
#define ID3V230FRAMEFLAG_GroupingIdentity (1<< 5)
#define ID3V240FRAMEFLAG_TagAlterPreservation (1<<14)
#define ID3V240FRAMEFLAG_FileAlterPreservation (1<<13)
#define ID3V240FRAMEFLAG_ReadOnly (1<<12)
#define ID3V240FRAMEFLAG_Compression (1<< 3)
#define ID3V240FRAMEFLAG_Encryption (1<< 2)
#define ID3V240FRAMEFLAG_GroupingIdentity (1<< 6)
#define ID3V240FRAMEFLAG_Unsynchronisation (1<< 1)
#define ID3V240FRAMEFLAG_DataLengthIndicator (1<< 0)
struct ID3V2_FRAME
{
unsigned int ID;
unsigned int size;
unsigned short flags; // ID3V2x0FRAMEFLAG_*
void* data; // Data of the frame
struct ID3V2_FRAME *next;
};
typedef struct ID3V2_FRAME ID3V2_FRAME;
#define ID3V2ID_TO_CHARS(i) (((i)>>24)&0xFF),(((i)>>16)&0xFF),(((i)>> 8)&0xFF),(((i)>> 0)&0xFF)
struct ID3V2_FRAMEFLAGS
{
bool TagAlterPreservation;
bool FileAlterPreservation;
bool ReadOnly;
bool Compression;
bool Encryption;
bool GroupingIdentity;
bool Unsynchronisation; // \_ ID3v2.4.0 only
bool DataLengthIndicator; // /
};
typedef struct ID3V2_FRAMEFLAGS ID3V2_FRAMEFLAGS;
int ID3V2_DecodeFrameFlags(int version, const ID3V2_FRAME *frame, ID3V2_FRAMEFLAGS *frameflags);
int ID3V2_EncodeFrameFlags(int version, ID3V2_FRAME *frame, const ID3V2_FRAMEFLAGS *frameflags);
typedef struct
{
char *path; // path of the file name
FILE *file; // file pointer
bool rawmp3; // true when there was no ID3 header in the file before
ID3V2_HEADER header; // Header of the ID3 information
ID3V2_EXTHEADER extheader; // Extended Header
ID3V2_FRAME *framelist; // List of all ID3 Frames
} ID3V2;
//////////////////////////////////////////////////////////////////////////////
extern bool OPT_PrintHeader; // print header detail while reading the ID3 tag
//////////////////////////////////////////////////////////////////////////////
// Extended Header parser
// !! Make sure id3->file points to the begin of the extended header
int ID3V2_UpdateExtendedHeader(ID3V2 *id3, bool update, bool crc, unsigned char restrictions); // Update structure
int ID3V2_RemoveExtendedHeader(ID3V2 *id3); // Clear structure
int ID3V230_ReadExtendedHeader(ID3V2 *id3);
int ID3V240_ReadExtendedHeader(ID3V2 *id3);
int ID3V230_WriteExtendedHeader(const ID3V2 *id3, FILE *file);
int ID3V240_WriteExtendedHeader(const ID3V2 *id3, FILE *file);
int ID3V230_UpdateCRC(const ID3V2 *id3, FILE *file);
int ID3V240_UpdateCRC(const ID3V2 *id3, FILE *file);
//////////////////////////////////////////////////////////////////////////////
int ID3V2_Open(ID3V2 **id3v2, const char *path, bool createtag);
/*
* Opens the file and reads all the ID3 information.
* The infos are stored in a new allocated ID3V2 struct thats address will be written
* to the id3v2 pointer and so be propergated to the user.
* The path must be an absolute path!
* if createtag is true, and the file is a mp3 file (0xFF 0xFB as magic word) a new ID3v2 Tag is generated
*
* # int error;
* # ID3V2 *id3v2 = NULL;
* # error = ID3V2_Open(&id3v2, "/tmp/test.mp3", true);
*/
int ID3V2_Close(ID3V2 *id3v2, const char *altpath, bool removetag);
/*
* After storing (recreating) the ID3v2 infos the id3v2 struct will be freed - id3v2 is no more valid after
* closing the file
* If altpath is != NULL, the data will be written to a new file, otherwise the old file gets overwritten
* The path must be absolute
* If altpath is "/dev/null" nothing will be written (even not to /dev/null) - this is readonly-mode :)
* If removetag is true, then only the audio data will be stored. The tag itself gets rejected.
*
* # error = ID3V2_Close(id3v2, NULL);
* # *id3v2 = NULL;
*/
int ID3V2_RemoveAllFrames(ID3V2 *id3v2);
/*
* Remove all frames
*/
int ID3V2_GetFrame(const ID3V2 *id3v2, unsigned int ID, size_t *size, void **data);
/*
* the size of the frame gets returned by writing to the size pointer
* for data, new memory gets allocated and a copy of the data will be created.
* If not used anymore, the user has to free the data memory
* If an error occures, do not call free on data
*
* # int size;
* # char *title;
* # error = ID3V2_GetFrame(id3v2, 'TIT2', &size, &title);
* #
* # // do something
* #
* # free(*title);
* # *title = NULL;
*/
int ID3V2_SetFrame(ID3V2 *id3v2, unsigned int ID, size_t size, const void *data);
/*
* # error = ID3V2_SetFrame(id3v2, 'TIT2', size, title);
*/
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4