aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/id3_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/id3_extractor.c')
-rw-r--r--src/plugins/id3_extractor.c305
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
32typedef 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
43static 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
202static void
203trim (char *k)
204{
205 while ((strlen (k) > 0) && (isspace (k[strlen (k) - 1])))
206 k[strlen (k) - 1] = '\0';
207}
208
209static int
210get_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
257const char *
258EXTRACTOR_id3_options ()
259{
260 return "want-tail";
261}
262
263
264int
265EXTRACTOR_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 }
296FINISH:
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 */