diff options
Diffstat (limited to 'src/plugins/id3_extractor.c')
-rw-r--r-- | src/plugins/id3_extractor.c | 305 |
1 files changed, 305 insertions, 0 deletions
diff --git a/src/plugins/id3_extractor.c b/src/plugins/id3_extractor.c new file mode 100644 index 0000000..be399e0 --- /dev/null +++ b/src/plugins/id3_extractor.c | |||
@@ -0,0 +1,305 @@ | |||
1 | /* | ||
2 | This file is part of libextractor. | ||
3 | (C) 2002, 2003, 2004, 2006, 2009, 2010 Vidyut Samanta and Christian Grothoff | ||
4 | |||
5 | libextractor is free software; you can redistribute it and/or modify | ||
6 | it under the terms of the GNU General Public License as published | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | libextractor is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with libextractor; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | |||
20 | */ | ||
21 | |||
22 | #include "platform.h" | ||
23 | #include "extractor.h" | ||
24 | #include "convert.h" | ||
25 | #include <string.h> | ||
26 | #include <stdio.h> | ||
27 | #include <sys/types.h> | ||
28 | #include <sys/stat.h> | ||
29 | #include <unistd.h> | ||
30 | #include <stdlib.h> | ||
31 | |||
32 | typedef struct | ||
33 | { | ||
34 | char *title; | ||
35 | char *artist; | ||
36 | char *album; | ||
37 | char *year; | ||
38 | char *comment; | ||
39 | const char *genre; | ||
40 | unsigned int track_number; | ||
41 | } id3tag; | ||
42 | |||
43 | static const char *const genre_names[] = { | ||
44 | gettext_noop ("Blues"), | ||
45 | gettext_noop ("Classic Rock"), | ||
46 | gettext_noop ("Country"), | ||
47 | gettext_noop ("Dance"), | ||
48 | gettext_noop ("Disco"), | ||
49 | gettext_noop ("Funk"), | ||
50 | gettext_noop ("Grunge"), | ||
51 | gettext_noop ("Hip-Hop"), | ||
52 | gettext_noop ("Jazz"), | ||
53 | gettext_noop ("Metal"), | ||
54 | gettext_noop ("New Age"), | ||
55 | gettext_noop ("Oldies"), | ||
56 | gettext_noop ("Other"), | ||
57 | gettext_noop ("Pop"), | ||
58 | gettext_noop ("R&B"), | ||
59 | gettext_noop ("Rap"), | ||
60 | gettext_noop ("Reggae"), | ||
61 | gettext_noop ("Rock"), | ||
62 | gettext_noop ("Techno"), | ||
63 | gettext_noop ("Industrial"), | ||
64 | gettext_noop ("Alternative"), | ||
65 | gettext_noop ("Ska"), | ||
66 | gettext_noop ("Death Metal"), | ||
67 | gettext_noop ("Pranks"), | ||
68 | gettext_noop ("Soundtrack"), | ||
69 | gettext_noop ("Euro-Techno"), | ||
70 | gettext_noop ("Ambient"), | ||
71 | gettext_noop ("Trip-Hop"), | ||
72 | gettext_noop ("Vocal"), | ||
73 | gettext_noop ("Jazz+Funk"), | ||
74 | gettext_noop ("Fusion"), | ||
75 | gettext_noop ("Trance"), | ||
76 | gettext_noop ("Classical"), | ||
77 | gettext_noop ("Instrumental"), | ||
78 | gettext_noop ("Acid"), | ||
79 | gettext_noop ("House"), | ||
80 | gettext_noop ("Game"), | ||
81 | gettext_noop ("Sound Clip"), | ||
82 | gettext_noop ("Gospel"), | ||
83 | gettext_noop ("Noise"), | ||
84 | gettext_noop ("Alt. Rock"), | ||
85 | gettext_noop ("Bass"), | ||
86 | gettext_noop ("Soul"), | ||
87 | gettext_noop ("Punk"), | ||
88 | gettext_noop ("Space"), | ||
89 | gettext_noop ("Meditative"), | ||
90 | gettext_noop ("Instrumental Pop"), | ||
91 | gettext_noop ("Instrumental Rock"), | ||
92 | gettext_noop ("Ethnic"), | ||
93 | gettext_noop ("Gothic"), | ||
94 | gettext_noop ("Darkwave"), | ||
95 | gettext_noop ("Techno-Industrial"), | ||
96 | gettext_noop ("Electronic"), | ||
97 | gettext_noop ("Pop-Folk"), | ||
98 | gettext_noop ("Eurodance"), | ||
99 | gettext_noop ("Dream"), | ||
100 | gettext_noop ("Southern Rock"), | ||
101 | gettext_noop ("Comedy"), | ||
102 | gettext_noop ("Cult"), | ||
103 | gettext_noop ("Gangsta Rap"), | ||
104 | gettext_noop ("Top 40"), | ||
105 | gettext_noop ("Christian Rap"), | ||
106 | gettext_noop ("Pop/Funk"), | ||
107 | gettext_noop ("Jungle"), | ||
108 | gettext_noop ("Native American"), | ||
109 | gettext_noop ("Cabaret"), | ||
110 | gettext_noop ("New Wave"), | ||
111 | gettext_noop ("Psychedelic"), | ||
112 | gettext_noop ("Rave"), | ||
113 | gettext_noop ("Showtunes"), | ||
114 | gettext_noop ("Trailer"), | ||
115 | gettext_noop ("Lo-Fi"), | ||
116 | gettext_noop ("Tribal"), | ||
117 | gettext_noop ("Acid Punk"), | ||
118 | gettext_noop ("Acid Jazz"), | ||
119 | gettext_noop ("Polka"), | ||
120 | gettext_noop ("Retro"), | ||
121 | gettext_noop ("Musical"), | ||
122 | gettext_noop ("Rock & Roll"), | ||
123 | gettext_noop ("Hard Rock"), | ||
124 | gettext_noop ("Folk"), | ||
125 | gettext_noop ("Folk/Rock"), | ||
126 | gettext_noop ("National Folk"), | ||
127 | gettext_noop ("Swing"), | ||
128 | gettext_noop ("Fast-Fusion"), | ||
129 | gettext_noop ("Bebob"), | ||
130 | gettext_noop ("Latin"), | ||
131 | gettext_noop ("Revival"), | ||
132 | gettext_noop ("Celtic"), | ||
133 | gettext_noop ("Bluegrass"), | ||
134 | gettext_noop ("Avantgarde"), | ||
135 | gettext_noop ("Gothic Rock"), | ||
136 | gettext_noop ("Progressive Rock"), | ||
137 | gettext_noop ("Psychedelic Rock"), | ||
138 | gettext_noop ("Symphonic Rock"), | ||
139 | gettext_noop ("Slow Rock"), | ||
140 | gettext_noop ("Big Band"), | ||
141 | gettext_noop ("Chorus"), | ||
142 | gettext_noop ("Easy Listening"), | ||
143 | gettext_noop ("Acoustic"), | ||
144 | gettext_noop ("Humour"), | ||
145 | gettext_noop ("Speech"), | ||
146 | gettext_noop ("Chanson"), | ||
147 | gettext_noop ("Opera"), | ||
148 | gettext_noop ("Chamber Music"), | ||
149 | gettext_noop ("Sonata"), | ||
150 | gettext_noop ("Symphony"), | ||
151 | gettext_noop ("Booty Bass"), | ||
152 | gettext_noop ("Primus"), | ||
153 | gettext_noop ("Porn Groove"), | ||
154 | gettext_noop ("Satire"), | ||
155 | gettext_noop ("Slow Jam"), | ||
156 | gettext_noop ("Club"), | ||
157 | gettext_noop ("Tango"), | ||
158 | gettext_noop ("Samba"), | ||
159 | gettext_noop ("Folklore"), | ||
160 | gettext_noop ("Ballad"), | ||
161 | gettext_noop ("Power Ballad"), | ||
162 | gettext_noop ("Rhythmic Soul"), | ||
163 | gettext_noop ("Freestyle"), | ||
164 | gettext_noop ("Duet"), | ||
165 | gettext_noop ("Punk Rock"), | ||
166 | gettext_noop ("Drum Solo"), | ||
167 | gettext_noop ("A Cappella"), | ||
168 | gettext_noop ("Euro-House"), | ||
169 | gettext_noop ("Dance Hall"), | ||
170 | gettext_noop ("Goa"), | ||
171 | gettext_noop ("Drum & Bass"), | ||
172 | gettext_noop ("Club-House"), | ||
173 | gettext_noop ("Hardcore"), | ||
174 | gettext_noop ("Terror"), | ||
175 | gettext_noop ("Indie"), | ||
176 | gettext_noop ("BritPop"), | ||
177 | gettext_noop ("Negerpunk"), | ||
178 | gettext_noop ("Polsk Punk"), | ||
179 | gettext_noop ("Beat"), | ||
180 | gettext_noop ("Christian Gangsta Rap"), | ||
181 | gettext_noop ("Heavy Metal"), | ||
182 | gettext_noop ("Black Metal"), | ||
183 | gettext_noop ("Crossover"), | ||
184 | gettext_noop ("Contemporary Christian"), | ||
185 | gettext_noop ("Christian Rock"), | ||
186 | gettext_noop ("Merengue"), | ||
187 | gettext_noop ("Salsa"), | ||
188 | gettext_noop ("Thrash Metal"), | ||
189 | gettext_noop ("Anime"), | ||
190 | gettext_noop ("JPop"), | ||
191 | gettext_noop ("Synthpop"), | ||
192 | }; | ||
193 | |||
194 | #define GENRE_NAME_COUNT \ | ||
195 | ((unsigned int)(sizeof genre_names / sizeof (const char *const))) | ||
196 | |||
197 | |||
198 | |||
199 | #define OK 0 | ||
200 | #define INVALID_ID3 1 | ||
201 | |||
202 | static void | ||
203 | trim (char *k) | ||
204 | { | ||
205 | while ((strlen (k) > 0) && (isspace (k[strlen (k) - 1]))) | ||
206 | k[strlen (k) - 1] = '\0'; | ||
207 | } | ||
208 | |||
209 | static int | ||
210 | get_id3 (const char *data, size_t size, id3tag * id3) | ||
211 | { | ||
212 | const char *pos; | ||
213 | |||
214 | if (size < 128) | ||
215 | return INVALID_ID3; | ||
216 | |||
217 | pos = &data[size - 128]; | ||
218 | if (0 != strncmp ("TAG", pos, 3)) | ||
219 | return INVALID_ID3; | ||
220 | pos += 3; | ||
221 | |||
222 | id3->title = EXTRACTOR_common_convert_to_utf8 (pos, 30, "ISO-8859-1"); | ||
223 | trim (id3->title); | ||
224 | pos += 30; | ||
225 | id3->artist = EXTRACTOR_common_convert_to_utf8 (pos, 30, "ISO-8859-1"); | ||
226 | trim (id3->artist); | ||
227 | pos += 30; | ||
228 | id3->album = EXTRACTOR_common_convert_to_utf8 (pos, 30, "ISO-8859-1"); | ||
229 | trim (id3->album); | ||
230 | pos += 30; | ||
231 | id3->year = EXTRACTOR_common_convert_to_utf8 (pos, 4, "ISO-8859-1"); | ||
232 | trim (id3->year); | ||
233 | pos += 4; | ||
234 | id3->comment = EXTRACTOR_common_convert_to_utf8 (pos, 30, "ISO-8859-1"); | ||
235 | trim (id3->comment); | ||
236 | if ( (pos[28] == '\0') && | ||
237 | (pos[29] != '\0') ) | ||
238 | { | ||
239 | /* ID3v1.1 */ | ||
240 | id3->track_number = pos[29]; | ||
241 | } | ||
242 | else | ||
243 | { | ||
244 | id3->track_number = 0; | ||
245 | } | ||
246 | pos += 30; | ||
247 | id3->genre = ""; | ||
248 | if (pos[0] < GENRE_NAME_COUNT) | ||
249 | id3->genre = dgettext (PACKAGE, genre_names[(unsigned) pos[0]]); | ||
250 | return OK; | ||
251 | } | ||
252 | |||
253 | |||
254 | #define ADD(s,t) do { if (0 != (ret = proc (proc_cls, "id3", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1))) goto FINISH; } while (0) | ||
255 | |||
256 | |||
257 | const char * | ||
258 | EXTRACTOR_id3_options () | ||
259 | { | ||
260 | return "want-tail"; | ||
261 | } | ||
262 | |||
263 | |||
264 | int | ||
265 | EXTRACTOR_id3_extract (const char *data, | ||
266 | size_t size, | ||
267 | EXTRACTOR_MetaDataProcessor proc, | ||
268 | void *proc_cls, | ||
269 | const char *options) | ||
270 | { | ||
271 | id3tag info; | ||
272 | char track[16]; | ||
273 | int ret; | ||
274 | |||
275 | fprintf (stderr, "called with %llu bytes\n", (unsigned long long) size); | ||
276 | if (OK != get_id3 (data, size, &info)) | ||
277 | return 0; | ||
278 | if (strlen (info.title) > 0) | ||
279 | ADD (info.title, EXTRACTOR_METATYPE_TITLE); | ||
280 | if (strlen (info.artist) > 0) | ||
281 | ADD (info.artist, EXTRACTOR_METATYPE_ARTIST); | ||
282 | if (strlen (info.album) > 0) | ||
283 | ADD (info.album, EXTRACTOR_METATYPE_ALBUM); | ||
284 | if (strlen (info.year) > 0) | ||
285 | ADD (info.year, EXTRACTOR_METATYPE_PUBLICATION_YEAR); | ||
286 | if (strlen (info.genre) > 0) | ||
287 | ADD (info.genre, EXTRACTOR_METATYPE_GENRE); | ||
288 | if (strlen (info.comment) > 0) | ||
289 | ADD (info.comment, EXTRACTOR_METATYPE_COMMENT); | ||
290 | if (info.track_number != 0) | ||
291 | { | ||
292 | snprintf(track, | ||
293 | sizeof(track), "%u", info.track_number); | ||
294 | ADD (track, EXTRACTOR_METATYPE_TRACK_NUMBER); | ||
295 | } | ||
296 | FINISH: | ||
297 | free (info.title); | ||
298 | free (info.year); | ||
299 | free (info.album); | ||
300 | free (info.artist); | ||
301 | free (info.comment); | ||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | /* end of id3_extractor.c */ | ||