1 /* id3.c
2  *
3  * ID3 manipulation tools.
4  *
5  * Tools for manipulating ID3 tags
6 */
7 
8 /*  id3tool:  An editor for ID3 tags.
9  *  Copyright (C) 1999-2002  Christopher Collins
10  *
11  * This program was authored principly by Christopher Collins (aka
12  * Crossfire).
13  *
14  * Redistribution and use in source and binary forms, with or without
15  * modification, are permitted provided that the following conditions are
16  * met:
17  *
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. The name of the author, Christopher Collins, nor any of his
24  *    aliases may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY CHRISTOPHER COLLINS ``AS IS'' AND ANY EXPRESS
28  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
29  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
30  * DISCLAIMED.  IN NO EVENT SHALL CHRISTOPHER COLLINS BE LIABLE FOR ANY
31  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38 */
39 
40 #include "config.h"
41 
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <ctype.h>
46 
47 #include "id3.h"
48 
49 struct style_s	id3_styles[] = {
50 	{0x00, "Blues"},
51 	{0x01, "Classic Rock"},
52 	{0x02, "Country"},
53 	{0x03, "Dance"},
54 	{0x04, "Disco"},
55 	{0x05, "Funk"},
56 	{0x06, "Grunge"},
57 	{0x07, "Hip-Hop"},
58 	{0x08, "Jazz"},
59 	{0x09, "Metal"},
60 	{0x0A, "New Age"},
61 	{0x0B, "Oldies"},
62 	{0x0C, "Other"},
63 	{0x0D, "Pop"},
64 	{0x0E, "R&B"},
65 	{0x0F, "Rap"},
66 	{0x10, "Reggae"},
67 	{0x11, "Rock"},
68 	{0x12, "Techno"},
69 	{0x13, "Industrial"},
70 	{0x14, "Alternative"},
71 	{0x15, "Ska"},
72 	{0x16, "Death Metal"},
73 	{0x17, "Pranks"},
74 	{0x18, "Soundtrack"},
75 	{0x19, "Euro-Techno"},
76 	{0x1A, "Ambient"},
77 	{0x1B, "Trip-Hop"},
78 	{0x1C, "Vocal"},
79 	{0x1D, "Jazz+Funk"},
80 	{0x1E, "Fusion"},
81 	{0x1F, "Trance"},
82 	{0x20, "Classical"},
83 	{0x21, "Instrumental"},
84 	{0x22, "Acid"},
85 	{0x23, "House"},
86 	{0x24, "Game"},
87 	{0x25, "Sound Clip"},
88 	{0x26, "Gospel"},
89 	{0x27, "Noise"},
90 	{0x28, "Alt. Rock"},
91 	{0x29, "Bass"},
92 	{0x2A, "Soul"},
93 	{0x2B, "Punk"},
94 	{0x2C, "Space"},
95 	{0x2D, "Meditative"},
96 	{0x2E, "Instrumental Pop"},
97 	{0x2F, "Instrumental Rock"},
98 	{0x30, "Ethnic"},
99 	{0x31, "Gothic"},
100 	{0x32, "Darkwave"},
101 	{0x33, "Techno-Industrial"},
102 	{0x34, "Electronic"},
103 	{0x35, "Pop-Folk"},
104 	{0x36, "Eurodance"},
105 	{0x37, "Dream"},
106 	{0x38, "Southern Rock"},
107 	{0x39, "Comedy"},
108 	{0x3A, "Cult"},
109 	{0x3B, "Gangsta"},
110 	{0x3C, "Top 40"},
111 	{0x3D, "Christian Rap"},
112 	{0x3E, "Pop/Funk"},
113 	{0x3F, "Jungle"},
114 	{0x40, "Native US"},
115 	{0x41, "Cabaret"},
116 	{0x42, "New Wave"},
117 	{0x43, "Psychadelic"},
118 	{0x44, "Rave"},
119 	{0x45, "Showtunes"},
120 	{0x46, "Trailer"},
121 	{0x47, "Lo-Fi"},
122 	{0x48, "Tribal"},
123 	{0x49, "Acid Punk"},
124 	{0x4A, "Acid Jazz"},
125 	{0x4B, "Polka"},
126 	{0x4C, "Retro"},
127 	{0x4D, "Musical"},
128 	{0x4E, "Rock & Roll"},
129 	{0x4F, "Hard Rock"},
130 	{0x50, "Folk"},
131 	{0x51, "Folk-Rock"},
132 	{0x52, "National Folk"},
133 	{0x53, "Swing"},
134 	{0x54, "Fast Fusion"},
135 	{0x55, "Bebob"},
136 	{0x56, "Latin"},
137 	{0x57, "Revival"},
138 	{0x58, "Celtic"},
139 	{0x59, "Bluegrass"},
140         {0x5A, "Avantgarde"},
141 	{0x5B, "Gothic Rock"},
142 	{0x5C, "Progressive Rock"},
143 	{0x5D, "Psychedelic Rock"},
144 	{0x5E, "Symphonic Rock"},
145 	{0x5F, "Slow Rock"},
146 	{0x60, "Big Band"},
147 	{0x61, "Chorus"},
148 	{0x62, "Easy Listening"},
149 	{0x63, "Acoustic"},
150 	{0x64, "Humour"},
151 	{0x65, "Speech"},
152 	{0x66, "Chanson"},
153 	{0x67, "Opera"},
154 	{0x68, "Chamber Music"},
155 	{0x69, "Sonata"},
156 	{0x6A, "Symphony"},
157 	{0x6B, "Booty Bass"},
158 	{0x6C, "Primus"},
159 	{0x6D, "Porn Groove"},
160 	{0x6E, "Satire"},
161 	{0x6F, "Slow Jam"},
162 	{0x70, "Club"},
163 	{0x71, "Tango"},
164 	{0x72, "Samba"},
165 	{0x73, "Folklore"},
166 	{0x74, "Ballad"},
167 	{0x75, "Power Ballad"},
168 	{0x76, "Rhytmic Soul"},
169 	{0x77, "Freestyle"},
170 	{0x78, "Duet"},
171 	{0x79, "Punk Rock"},
172 	{0x7A, "Drum Solo"},
173 	{0x7B, "Acapella"},
174 	{0x7C, "Euro-House"},
175 	{0x7D, "Dance Hall"},
176 	{0x7E, "Goa"},
177 	{0x7F, "Drum & Bass"},
178 	{0x80, "Club-House"},
179 	{0x81, "Hardcore"},
180 	{0x82, "Terror"},
181 	{0x83, "Indie"},
182 	{0x84, "BritPop"},
183 	{0x85, "Negerpunk"},
184 	{0x86, "Polsk Punk"},
185 	{0x87, "Beat"},
186 	{0x88, "Christian Gangsta Rap"},
187 	{0x89, "Heavy Metal"},
188 	{0x8A, "Black Metal"},
189 	{0x8B, "Crossover"},
190 	{0x8C, "Contemporary Christian"},
191 	{0x8D, "Christian Rock"},
192 	{0x8E, "Merengue"},
193 	{0x8F, "Salsa"},
194 	{0x90, "Trash Metal"},
195 	{0xFF, NULL}
196 };
197 
198 extern int
id3_readtag(FILE * fin,id3tag_t * id3tag)199 id3_readtag(FILE *fin, id3tag_t *id3tag)
200 {
201 	int	n;
202 	if (NULL == fin || NULL == id3tag) {
203 		return (-1);
204 	}
205 	fseek (fin, 0, SEEK_END);
206 	fseek (fin, ftell(fin)-128, SEEK_SET);
207 	n = fread (id3tag, 128, 1, fin);
208 	if (1 != n || strncmp(id3tag->magic, "TAG", 3)) {
209 		return (1);
210 	}
211 	return (0);
212 }
213 
214 extern int
id3_appendtag(FILE * fout,id3tag_t * id3tag)215 id3_appendtag(FILE *fout, id3tag_t *id3tag)
216 {
217 	if (NULL == fout || NULL == id3tag) {
218 		return (-1);
219 	}
220 	fseek (fout, 0, SEEK_END);
221 
222 	fwrite (id3tag, 128, 1, fout);
223 
224 	return (0);
225 }
226 
227 extern int
id3_replacetag(FILE * fout,id3tag_t * id3tag)228 id3_replacetag(FILE *fout, id3tag_t *id3tag)
229 {
230 	if (NULL == fout || NULL == id3tag) {
231 		return (-1);
232 	}
233 	fseek (fout, 0, SEEK_END);
234 	fseek (fout, ftell(fout) - 128, SEEK_SET);
235 
236 	fwrite (id3tag, 128, 1, fout);
237 
238 	return (0);
239 }
240 
241 extern void
id3_cleartag(id3tag_t * id3tag)242 id3_cleartag(id3tag_t *id3tag)
243 {
244 	if (NULL == id3tag) {
245 		return;
246 	}
247 	memset (id3tag, 0, sizeof (*id3tag));
248 	strncpy(id3tag->magic, "TAG", 3);
249 	id3tag->style = 0xFF;
250 }
251 
252 extern char *
id3_findstyle(int styleid)253 id3_findstyle(int styleid)
254 {
255 	int	ctr;
256 	for (ctr = 0; id3_styles[ctr].name != NULL; ctr++) {
257 		if (id3_styles[ctr].styleid == styleid) {
258 			return (id3_styles[ctr].name);
259 		}
260 	}
261 	return "Unknown Style";
262 }
263