1 /*
2 
3   No-bullshit ID3v2 support
4 
5   copyright (c) 2003-2006, 2015 squell <squell@alumina.nl>
6 
7   use, modification, copying and distribution of this software is permitted
8   under the conditions described in the file 'COPYING'.
9 
10   Usage (brief?):
11 
12       void *ID3_readf(const char *fname, size_t *tagsize)
13 
14   reads ID3v2 tag from fname to memory, storing the tag size (w/o padding) in
15   *tagsize (if != NULL). returns pointer on success, NULL on failure
16   stores zero in *tagsize on failure, or non-zero value if a malformed ID3v2
17   tag caused failure.
18 
19       int ID3_writef(const char *fname, const void *buf, size_t reqsize);
20 
21   writes in-memory tag pointed to by buf to fname. returns true / false on
22   success / failure. in-memory tag needs to be zero-terminated.
23   if reqsize != 0, tries to write id3v2 tag of that size.
24   if buf is NULL or points to an empty tag, deletes tag.
25   [doesnt check consistency of fname (use ID3_readf first)!]
26 
27       void ID3_free(const void *buf)
28 
29   frees pointer obtained by ID3_readf()
30 
31       ID3VER ID3_start(ID3FRAME f, const void *buf)
32 
33   initializes frame-iterator for stepping through tag pointed to by buf
34 
35       int ID3_frame(ID3FRAME f)
36 
37   steps through a tag using iterator f. returns 0 if no more frames.
38 
39       void *ID3_put(void *dest, ID3VER version, const char ID[4], const void *src, size_t len)
40 
41   writes a frame of type ID with contents *src (size len) to the in-memory tag
42   location pointed to by dest. returns the next memory location to write the
43   next frame to. first call with ID null to perform initialization. version
44   must be 2 or 3 (for ID3v2.2 or ID3v2.3). A mixed version tag will result in
45   undefined behaviour by ID3_writef. returns dest to indicate error (no-op).
46 
47       void (*ID3_wfail)(const char *dest, const char *src)
48 
49   this function pointer gets called if the mvfile() in ID3_writef fails.
50   by default, this points to an abort.
51 
52   Example (reading a tag):
53 
54     void *buf = ID3_readf("filename",0);
55     ID3FRAME f;
56 
57     if(buf) {
58         ID3_start(frame, buf);
59         while( ID3_frame(f) )
60             ... do stuff with f->XXXX ...
61     }
62 
63   Example (writing a tag):
64 
65     char buf[10000], *out;
66     int i;
67 
68     out = ID3_put(buf, ID3_v2_3, 0, 0, 0);
69     for( .. frames to write .. )
70         out = ID3_put(out, ID3_v2_3, ..id, ..&data, ..sizeof data);
71 
72     ID3_writef("filename", buf, 0);
73 
74   Notes:
75 
76   ID3_writef() is very conservative by default: it will only rewrite the
77   MP3 file if it absolutely has to, i.e., if a tag has to be removed,
78   added, or is too small. It will not automatically rewrite MP3 files
79   to downsize ID3v2 tags (that would be silly).
80 
81 */
82 #ifndef __ZF_ID3V2_H
83 #define __ZF_ID3V2_H
84 
85 #include <stddef.h>
86 
87 #ifdef __cplusplus
88 extern "C" {                           /* whole heaps of errors otherwise */
89 #endif
90 
91 typedef struct _ID3FRAME {
92     const char *data;                     /* pointer to contents of frame */
93     unsigned long size;                   /* length of frame contents     */
94     char ID[5];                           /* ID of frame                  */
95     unsigned tag_volit  : 1;
96     unsigned file_volit : 1;
97     unsigned readonly   : 1;
98     unsigned packed     : 1;
99     unsigned encrypted  : 1;
100     unsigned grouped    : 1;
101     unsigned _rev       : 2;
102 } ID3FRAME[1];
103 
104 typedef enum {
105     ID3_v2_2 = 2,
106     ID3_v2_3 = 3
107 } ID3VER;
108 
109 extern void   *ID3_readf(const char *fname, size_t *tagsize);
110 extern int     ID3_writef(const char *fname, const void *buf, size_t reqsize);
111 extern void    ID3_free(const void *buf);
112 
113 extern ID3VER  ID3_start(ID3FRAME f, const void *buf);
114 extern int     ID3_frame(ID3FRAME f);
115 
116 extern void   *ID3_put(void *dest, ID3VER version, const char ID[4], const void *src, size_t len);
117 
118 extern void  (*ID3_wfail)(const char *srcname, const char *dstname);
119 
120 #ifdef __cplusplus
121 }
122 #endif
123 #endif
124 
125