aboutsummaryrefslogtreecommitdiff
path: root/src/plugins/flac_extractor.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/flac_extractor.c')
-rw-r--r--src/plugins/flac_extractor.c498
1 files changed, 298 insertions, 200 deletions
diff --git a/src/plugins/flac_extractor.c b/src/plugins/flac_extractor.c
index 0b99a33..8b4ac9a 100644
--- a/src/plugins/flac_extractor.c
+++ b/src/plugins/flac_extractor.c
@@ -1,10 +1,10 @@
1/* 1/*
2 This file is part of libextractor. 2 This file is part of libextractor.
3 (C) 2007, 2009 Vidyut Samanta and Christian Grothoff 3 (C) 2007, 2009, 2012 Vidyut Samanta and Christian Grothoff
4 4
5 libextractor is free software; you can redistribute it and/or modify 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 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 7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version. 8 option) any later version.
9 9
10 libextractor is distributed in the hope that it will be useful, but 10 libextractor is distributed in the hope that it will be useful, but
@@ -18,99 +18,185 @@
18 Boston, MA 02111-1307, USA. 18 Boston, MA 02111-1307, USA.
19 */ 19 */
20 20
21/**
22 * @file plugins/flac_extractor.c
23 * @brief plugin to support FLAC files
24 * @author Christian Grothoff
25 */
21#include "platform.h" 26#include "platform.h"
22#include "extractor.h" 27#include "extractor.h"
28#include <FLAC/all.h>
23 29
30
31/**
32 * Bytes each FLAC file must begin with (not used, but we might
33 * choose to add this back in the future to improve performance
34 * for non-ogg files).
35 */
24#define FLAC_HEADER "fLaC" 36#define FLAC_HEADER "fLaC"
25 37
26#if HAVE_FLAC_ALL_H
27#include <FLAC/all.h>
28#else
29#error You must install the libflac header files!
30#endif
31
32
33struct Context {
34 const char * data;
35 size_t size;
36 size_t pos;
37 EXTRACTOR_MetaDataProcessor proc;
38 void *proc_cls;
39 int ret;
40};
41 38
39/**
40 * Custom read function for flac.
41 *
42 * @param decoder unused
43 * @param buffer where to write the data
44 * @param bytes how many bytes to read, set to how many bytes were read
45 * @param client_data our 'struct EXTRACTOR_ExtractContxt*'
46 * @return status code (error, end-of-file or success)
47 */
42static FLAC__StreamDecoderReadStatus 48static FLAC__StreamDecoderReadStatus
43flac_read (const FLAC__StreamDecoder *decoder, 49flac_read (const FLAC__StreamDecoder *decoder,
44 FLAC__byte buffer[], 50 FLAC__byte buffer[],
45 size_t *bytes, 51 size_t *bytes,
46 void *client_data) 52 void *client_data)
47{ 53{
48 struct Context * ctx = client_data; 54 struct EXTRACTOR_ExtractContext *ec = client_data;
49 55 void *data;
50 if (*bytes <= 0) 56 ssize_t ret;
57
58 data = NULL;
59 ret = ec->read (ec->cls,
60 &data,
61 *bytes);
62 if (-1 == ret)
51 return FLAC__STREAM_DECODER_READ_STATUS_ABORT; 63 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
52 if (*bytes > ctx->size - ctx->pos) 64 if (0 == ret)
53 *bytes = ctx->size - ctx->pos; 65 {
54 if (*bytes == 0) 66 errno = 0;
55 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; 67 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
56 memcpy(buffer, 68 }
57 &ctx->data[ctx->pos], 69 memcpy (buffer, data, ret);
58 *bytes); 70 *bytes = ret;
59 ctx->pos += *bytes; 71 errno = 0;
60 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; 72 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
61} 73}
62 74
75
76/**
77 * Seek to a particular position in the file.
78 *
79 * @param decoder unused
80 * @param absolute_byte_offset where to seek
81 * @param client_data the 'struct EXTRACTOR_ExtractContext'
82 * @return status code (error or success)
83 */
63static FLAC__StreamDecoderSeekStatus 84static FLAC__StreamDecoderSeekStatus
64flac_seek(const FLAC__StreamDecoder *decoder, 85flac_seek (const FLAC__StreamDecoder *decoder,
65 FLAC__uint64 absolute_byte_offset, void *client_data) 86 FLAC__uint64 absolute_byte_offset,
87 void *client_data)
66{ 88{
67 struct Context * ctx = client_data; 89 struct EXTRACTOR_ExtractContext *ec = client_data;
68 90
69 if (absolute_byte_offset > ctx->size) 91 if (absolute_byte_offset !=
92 ec->seek (ec->cls, (int64_t) absolute_byte_offset, SEEK_SET))
70 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; 93 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
71 ctx->pos = (size_t) absolute_byte_offset;
72 return FLAC__STREAM_DECODER_SEEK_STATUS_OK; 94 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
73} 95}
74 96
97
98/**
99 * Tell FLAC about our current position in the file.
100 *
101 * @param decoder unused
102 * @param absolute_byte_offset location to store the current offset
103 * @param client_data the 'struct EXTRACTOR_ExtractContext'
104 * @return status code (error or success)
105 */
75static FLAC__StreamDecoderTellStatus 106static FLAC__StreamDecoderTellStatus
76flac_tell(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) 107flac_tell (const FLAC__StreamDecoder *decoder,
108 FLAC__uint64 *absolute_byte_offset,
109 void *client_data)
77{ 110{
78 struct Context * ctx = client_data; 111 struct EXTRACTOR_ExtractContext *ec = client_data;
79 112
80 *absolute_byte_offset = ctx->pos; 113 *absolute_byte_offset = ec->seek (ec->cls,
114 0,
115 SEEK_CUR);
81 return FLAC__STREAM_DECODER_TELL_STATUS_OK; 116 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
82} 117}
83 118
119
120/**
121 * Tell FLAC the size of the file.
122 *
123 * @param decoder unused
124 * @param stream_length where to store the file size
125 * @param client_data the 'struct EXTRACTOR_ExtractContext'
126 * @return true at EOF, false if not
127 */
84static FLAC__StreamDecoderLengthStatus 128static FLAC__StreamDecoderLengthStatus
85flac_length(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) 129flac_length (const FLAC__StreamDecoder *decoder,
130 FLAC__uint64 *stream_length,
131 void *client_data)
86{ 132{
87 struct Context * ctx = client_data; 133 struct EXTRACTOR_ExtractContext *ec = client_data;
88 134
89 ctx->pos = *stream_length; 135 *stream_length = ec->get_size (ec->cls);
90 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; 136 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
91} 137}
92 138
139
140/**
141 * Tell FLAC if we are at the end of the file.
142 *
143 * @param decoder unused
144 * @param absolute_byte_offset location to store the current offset
145 * @param client_data the 'struct EXTRACTOR_ExtractContext'
146 * @return true at EOF, false if not
147 */
93static FLAC__bool 148static FLAC__bool
94flac_eof(const FLAC__StreamDecoder *decoder, void *client_data) 149flac_eof (const FLAC__StreamDecoder *decoder,
150 void *client_data)
95{ 151{
96 struct Context * ctx = client_data; 152 struct EXTRACTOR_ExtractContext *ec = client_data;
97 153
98 return (ctx->pos == ctx->size) ? true : false; 154 return (ec->get_size (ec->cls) ==
155 ec->seek (ec->cls, 0, SEEK_CUR)) ? true : false;
99} 156}
100 157
158
159/**
160 * FLAC wants to write. Always succeeds but does nothing.
161 *
162 * @param decoder unused
163 * @param frame unused
164 * @param buffer unused
165 * @param client_data the 'struct EXTRACTOR_ExtractContext'
166 * @return always claims success
167 */
101static FLAC__StreamDecoderWriteStatus 168static FLAC__StreamDecoderWriteStatus
102flac_write(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) 169flac_write (const FLAC__StreamDecoder *decoder,
170 const FLAC__Frame *frame,
171 const FLAC__int32 *const buffer[],
172 void *client_data)
103{ 173{
104 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; 174 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
105} 175}
106 176
107typedef struct 177
178/**
179 * A mapping from FLAC meta data strings to extractor types.
180 */
181struct Matches
108{ 182{
183 /**
184 * FLAC Meta data description text.
185 */
109 const char *text; 186 const char *text;
187
188 /**
189 * Corresponding LE type.
190 */
110 enum EXTRACTOR_MetaType type; 191 enum EXTRACTOR_MetaType type;
111} Matches; 192};
112 193
113static Matches tmap[] = { 194
195/**
196 * Mapping of FLAC meta data description texts to LE types.
197 * NULL-terminated.
198 */
199static struct Matches tmap[] = {
114 {"TITLE", EXTRACTOR_METATYPE_TITLE}, 200 {"TITLE", EXTRACTOR_METATYPE_TITLE},
115 {"VERSION", EXTRACTOR_METATYPE_SONG_VERSION}, 201 {"VERSION", EXTRACTOR_METATYPE_SONG_VERSION},
116 {"ALBUM", EXTRACTOR_METATYPE_ALBUM}, 202 {"ALBUM", EXTRACTOR_METATYPE_ALBUM},
@@ -126,72 +212,97 @@ static Matches tmap[] = {
126 {"CONTACT", EXTRACTOR_METATYPE_CONTACT_INFORMATION}, 212 {"CONTACT", EXTRACTOR_METATYPE_CONTACT_INFORMATION},
127 {"TRACKNUMBER", EXTRACTOR_METATYPE_TRACK_NUMBER}, 213 {"TRACKNUMBER", EXTRACTOR_METATYPE_TRACK_NUMBER},
128 {"ISRC", EXTRACTOR_METATYPE_ISRC}, 214 {"ISRC", EXTRACTOR_METATYPE_ISRC},
129 {NULL, 0}, 215 {NULL, 0}
130}; 216};
131 217
132 218
133static char * xstrndup(const char * s, size_t n){ 219/**
220 * FIXME.
221 */
222#define ADD (t,s) do { if (ctx->ret == 0) ctx->ret = ctx->proc (ctx->proc_cls, "flac", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1); } while (0)
223
224
225/**
226 * Create 0-terminated version of n-character string.
227 *
228 * @param s input string (non 0-terminated)
229 * @param n number of bytes in 's'
230 * @return NULL on error, otherwise 0-terminated version of 's'
231 */
232static char *
233xstrndup (const char *s,
234 size_t n)
235{
134 char * d; 236 char * d;
135 237
136 d= malloc(n+1); 238 if (NULL == (d = malloc(n+1)))
137 if (d == NULL)
138 return NULL; 239 return NULL;
139 memcpy(d,s,n); 240 memcpy (d, s, n);
140 d[n]='\0'; 241 d[n] = '\0';
141 return d; 242 return d;
142} 243}
143 244
144#define ADD(t,s) do { if (ctx->ret == 0) ctx->ret = ctx->proc (ctx->proc_cls, "flac", t, EXTRACTOR_METAFORMAT_UTF8, "text/plain", s, strlen(s)+1); } while (0)
145
146 245
246/**
247 * FIXME.
248 */
147static void 249static void
148check(const char * type, 250check (const char *type,
149 unsigned int type_length, 251 unsigned int type_length,
150 const char * value, 252 const char *value,
151 unsigned int value_length, 253 unsigned int value_length,
152 struct Context *ctx) 254 struct EXTRACTOR_ExtractContext *ec)
153{ 255{
154 unsigned int i; 256 unsigned int i;
155 char *tmp; 257 char *tmp;
156 258
157 i = 0; 259 for (i=0; NULL != tmap[i].text; i++)
158 while (tmap[i].text != NULL)
159 { 260 {
160 if ( (type_length == strlen(tmap[i].text)) && 261 if ( (type_length != strlen (tmap[i].text)) ||
161 (0 == strncasecmp(tmap[i].text, 262 (0 != strncasecmp (tmap[i].text,
162 type, 263 type,
163 type_length)) ) 264 type_length)) )
164 { 265 continue;
165 tmp = xstrndup(value, 266 if (NULL ==
166 value_length); 267 (tmp = xstrndup (value,
167 if (tmp != NULL) 268 value_length)))
168 { 269 continue;
169 ADD (tmap[i].type, tmp); 270 ADD (tmap[i].type, tmp);
170 free (tmp); 271 free (tmp);
171 }
172 break;
173 }
174 i++;
175 } 272 }
176} 273}
177 274
178 275
276/**
277 * Function called whenever FLAC finds meta data.
278 *
279 * @param decoder unused
280 * @param metadata meta data that was found
281 * @param client_data the 'struct EXTRACTOR_ExtractContext'
282 */
179static void 283static void
180flac_metadata(const FLAC__StreamDecoder *decoder, 284flac_metadata (const FLAC__StreamDecoder *decoder,
181 const FLAC__StreamMetadata *metadata, 285 const FLAC__StreamMetadata *metadata,
182 void *client_data) 286 void *client_data)
183{ 287{
184 struct Context * ctx = client_data; 288 struct EXTRACTOR_ExtractContext *ec = client_data;
289 enum EXTRACTOR_MetaType type;
290 const FLAC__StreamMetadata_VorbisComment * vc;
291 unsigned int count;
292 const FLAC__StreamMetadata_VorbisComment_Entry * entry;
293 const char * eq;
294 unsigned int len;
295 unsigned int ilen;
185 296
186 switch (metadata->type) 297 switch (metadata->type)
187 { 298 {
188 case FLAC__METADATA_TYPE_STREAMINFO: 299 case FLAC__METADATA_TYPE_STREAMINFO:
189 { 300 {
190 char buf[512]; 301 char buf[512];
191 snprintf(buf, 512, 302 snprintf (buf, sizeof (buf),
192 _("%u Hz, %u channels"), 303 _("%u Hz, %u channels"),
193 metadata->data.stream_info.sample_rate, 304 metadata->data.stream_info.sample_rate,
194 metadata->data.stream_info.channels); 305 metadata->data.stream_info.channels);
195 ADD (EXTRACTOR_METATYPE_RESOURCE_TYPE, buf); 306 ADD (EXTRACTOR_METATYPE_RESOURCE_TYPE, buf);
196 break; 307 break;
197 } 308 }
@@ -203,13 +314,8 @@ flac_metadata(const FLAC__StreamDecoder *decoder,
203 break; 314 break;
204 case FLAC__METADATA_TYPE_VORBIS_COMMENT: 315 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
205 { 316 {
206 const FLAC__StreamMetadata_VorbisComment * vc = &metadata->data.vorbis_comment; 317 vc = &metadata->data.vorbis_comment;
207 unsigned int count = vc->num_comments; 318 count = vc->num_comments;
208 const FLAC__StreamMetadata_VorbisComment_Entry * entry;
209 const char * eq;
210 unsigned int len;
211 unsigned int ilen;
212
213 while (count-- > 0) 319 while (count-- > 0)
214 { 320 {
215 entry = &vc->comments[count]; 321 entry = &vc->comments[count];
@@ -226,64 +332,62 @@ flac_metadata(const FLAC__StreamDecoder *decoder,
226 (ilen == len) ) 332 (ilen == len) )
227 break; 333 break;
228 eq++; 334 eq++;
229 check((const char*) entry->entry, 335 check ((const char*) entry->entry,
230 ilen, 336 ilen,
231 eq, 337 eq,
232 len - ilen, 338 len - ilen,
233 ctx); 339 ctx);
234 } 340 }
235 break; 341 break;
236 } 342 }
237 case FLAC__METADATA_TYPE_PICTURE: 343 case FLAC__METADATA_TYPE_PICTURE:
238 { 344 {
239 if (ctx->ret == 0) 345 if (0 != ctx->ret)
346 break;
347 switch (metadata->data.picture.type)
240 { 348 {
241 enum EXTRACTOR_MetaType type; 349 case FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER:
242 switch (metadata->data.picture.type) 350 case FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD:
243 { 351 case FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON:
244 case FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER: 352 type = EXTRACTOR_METATYPE_THUMBNAIL;
245 case FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD: 353 break;
246 case FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON: 354 case FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER:
247 type = EXTRACTOR_METATYPE_THUMBNAIL; 355 case FLAC__STREAM_METADATA_PICTURE_TYPE_BACK_COVER:
248 break; 356 type = EXTRACTOR_METATYPE_COVER_PICTURE;
249 case FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER: 357 break;
250 case FLAC__STREAM_METADATA_PICTURE_TYPE_BACK_COVER: 358 case FLAC__STREAM_METADATA_PICTURE_TYPE_LEAD_ARTIST:
251 type = EXTRACTOR_METATYPE_COVER_PICTURE; 359 case FLAC__STREAM_METADATA_PICTURE_TYPE_ARTIST:
252 break; 360 case FLAC__STREAM_METADATA_PICTURE_TYPE_CONDUCTOR:
253 case FLAC__STREAM_METADATA_PICTURE_TYPE_LEAD_ARTIST: 361 case FLAC__STREAM_METADATA_PICTURE_TYPE_BAND:
254 case FLAC__STREAM_METADATA_PICTURE_TYPE_ARTIST: 362 case FLAC__STREAM_METADATA_PICTURE_TYPE_COMPOSER:
255 case FLAC__STREAM_METADATA_PICTURE_TYPE_CONDUCTOR: 363 case FLAC__STREAM_METADATA_PICTURE_TYPE_LYRICIST:
256 case FLAC__STREAM_METADATA_PICTURE_TYPE_BAND: 364 type = EXTRACTOR_METATYPE_CONTRIBUTOR_PICTURE;
257 case FLAC__STREAM_METADATA_PICTURE_TYPE_COMPOSER: 365 break;
258 case FLAC__STREAM_METADATA_PICTURE_TYPE_LYRICIST: 366 case FLAC__STREAM_METADATA_PICTURE_TYPE_RECORDING_LOCATION:
259 type = EXTRACTOR_METATYPE_CONTRIBUTOR_PICTURE; 367 case FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_RECORDING:
260 break; 368 case FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_PERFORMANCE:
261 case FLAC__STREAM_METADATA_PICTURE_TYPE_RECORDING_LOCATION: 369 case FLAC__STREAM_METADATA_PICTURE_TYPE_VIDEO_SCREEN_CAPTURE:
262 case FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_RECORDING: 370 type = EXTRACTOR_METATYPE_EVENT_PICTURE;
263 case FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_PERFORMANCE: 371 break;
264 case FLAC__STREAM_METADATA_PICTURE_TYPE_VIDEO_SCREEN_CAPTURE: 372 case FLAC__STREAM_METADATA_PICTURE_TYPE_BAND_LOGOTYPE:
265 type = EXTRACTOR_METATYPE_EVENT_PICTURE; 373 case FLAC__STREAM_METADATA_PICTURE_TYPE_PUBLISHER_LOGOTYPE:
266 break; 374 type = EXTRACTOR_METATYPE_LOGO;
267 case FLAC__STREAM_METADATA_PICTURE_TYPE_BAND_LOGOTYPE: 375 break;
268 case FLAC__STREAM_METADATA_PICTURE_TYPE_PUBLISHER_LOGOTYPE: 376 case FLAC__STREAM_METADATA_PICTURE_TYPE_LEAFLET_PAGE:
269 type = EXTRACTOR_METATYPE_LOGO; 377 case FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA:
270 break; 378 case FLAC__STREAM_METADATA_PICTURE_TYPE_FISH:
271 case FLAC__STREAM_METADATA_PICTURE_TYPE_LEAFLET_PAGE: 379 case FLAC__STREAM_METADATA_PICTURE_TYPE_ILLUSTRATION:
272 case FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA: 380 default:
273 case FLAC__STREAM_METADATA_PICTURE_TYPE_FISH: 381 type = EXTRACTOR_METATYPE_PICTURE;
274 case FLAC__STREAM_METADATA_PICTURE_TYPE_ILLUSTRATION: 382 break;
275 default:
276 type = EXTRACTOR_METATYPE_PICTURE;
277 break;
278 }
279 ctx->ret = ctx->proc (ctx->proc_cls,
280 "flac",
281 type,
282 EXTRACTOR_METAFORMAT_BINARY,
283 metadata->data.picture.mime_type,
284 (const char*) metadata->data.picture.data,
285 metadata->data.picture.data_length);
286 } 383 }
384 ec->proc (ec->cls,
385 "flac",
386 type,
387 EXTRACTOR_METAFORMAT_BINARY,
388 metadata->data.picture.mime_type,
389 (const char*) metadata->data.picture.data,
390 metadata->data.picture.data_length))
287 break; 391 break;
288 } 392 }
289 case FLAC__METADATA_TYPE_PADDING: 393 case FLAC__METADATA_TYPE_PADDING:
@@ -294,81 +398,73 @@ flac_metadata(const FLAC__StreamDecoder *decoder,
294 } 398 }
295} 399}
296 400
401
402/**
403 * Function called whenever FLAC decoder has trouble. Does nothing.
404 *
405 * @param decoder the decoder handle
406 * @param status type of the error
407 * @param client_data our 'struct EXTRACTOR_ExtractContext'
408 */
297static void 409static void
298flac_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) 410flac_error (const FLAC__StreamDecoder *decoder,
411 FLAC__StreamDecoderErrorStatus status,
412 void *client_data)
299{ 413{
300#if 0 414 /* ignore errors */
301 fprintf(stderr,
302 "Got error: %u\n", status);
303#endif
304} 415}
305 416
306/* mimetype = audio/flac */ 417
307int 418/**
308EXTRACTOR_flac_extract (const char *data, 419 * Main entry method for the 'audio/flac' extraction plugin.
309 size_t size, 420 *
310 EXTRACTOR_MetaDataProcessor proc, 421 * @param ec extraction context provided to the plugin
311 void *proc_cls, 422 */
312 const char *options) 423void
424EXTRACTOR_flac_extract_method (struct EXTRACTOR_ExtractContext *ec)
313{ 425{
314 FLAC__StreamDecoder * decoder; 426 FLAC__StreamDecoder * decoder;
315 struct Context le_cls; 427
316 struct Context *ctx; 428 if (NULL == (decoder = FLAC__stream_decoder_new ()))
317 429 return;
318 if (size < strlen(FLAC_HEADER) + sizeof (int)) 430 FLAC__stream_decoder_set_md5_checking (decoder, false);
319 return 0; 431 FLAC__stream_decoder_set_metadata_ignore_all (decoder);
320 if (0 != memcmp(FLAC_HEADER, 432 if (false == FLAC__stream_decoder_set_metadata_respond_all (decoder))
321 data,
322 strlen(FLAC_HEADER)))
323 return 0;
324 decoder = FLAC__stream_decoder_new();
325 if (NULL == decoder)
326 return 0;
327 FLAC__stream_decoder_set_md5_checking(decoder, false);
328 FLAC__stream_decoder_set_metadata_ignore_all(decoder);
329 if (false == FLAC__stream_decoder_set_metadata_respond_all(decoder))
330 { 433 {
331 FLAC__stream_decoder_delete(decoder); 434 FLAC__stream_decoder_delete (decoder);
332 return 0; 435 return;
333 } 436 }
334 le_cls.ret = 0;
335 le_cls.size = size;
336 le_cls.data = data;
337 le_cls.proc = proc;
338 le_cls.proc_cls = proc_cls;
339 le_cls.pos = 0;
340 if (FLAC__STREAM_DECODER_INIT_STATUS_OK != 437 if (FLAC__STREAM_DECODER_INIT_STATUS_OK !=
341 FLAC__stream_decoder_init_stream(decoder, 438 FLAC__stream_decoder_init_stream (decoder,
342 &flac_read, 439 &flac_read,
343 &flac_seek, 440 &flac_seek,
344 &flac_tell, 441 &flac_tell,
345 &flac_length, 442 &flac_length,
346 &flac_eof, 443 &flac_eof,
347 &flac_write, 444 &flac_write,
348 &flac_metadata, 445 &flac_metadata,
349 &flac_error, 446 &flac_error,
350 &le_cls)) 447 ec))
351 { 448 {
352 FLAC__stream_decoder_delete(decoder); 449 FLAC__stream_decoder_delete (decoder);
353 return le_cls.ret; 450 return;
354 } 451 }
355 if (FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) 452 if (FLAC__STREAM_DECODER_SEARCH_FOR_METADATA != FLAC__stream_decoder_get_state(decoder))
356 { 453 {
357 FLAC__stream_decoder_delete(decoder); 454 FLAC__stream_decoder_delete (decoder);
358 return le_cls.ret; 455 return;
359 } 456 }
360 if (! FLAC__stream_decoder_process_until_end_of_metadata(decoder)) 457 if (! FLAC__stream_decoder_process_until_end_of_metadata(decoder))
361 { 458 {
362 FLAC__stream_decoder_delete(decoder); 459 FLAC__stream_decoder_delete (decoder);
363 return le_cls.ret; 460 return;
364 } 461 }
365 switch (FLAC__stream_decoder_get_state(decoder)) 462 switch (FLAC__stream_decoder_get_state (decoder))
366 { 463 {
367 case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: 464 case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
368 case FLAC__STREAM_DECODER_READ_METADATA: 465 case FLAC__STREAM_DECODER_READ_METADATA:
369 case FLAC__STREAM_DECODER_END_OF_STREAM: 466 case FLAC__STREAM_DECODER_END_OF_STREAM:
370 case FLAC__STREAM_DECODER_READ_FRAME: 467 case FLAC__STREAM_DECODER_READ_FRAME:
371 ctx = &le_cls;
372 ADD (EXTRACTOR_METATYPE_MIMETYPE, "audio/flac"); 468 ADD (EXTRACTOR_METATYPE_MIMETYPE, "audio/flac");
373 break; 469 break;
374 default: 470 default:
@@ -376,6 +472,8 @@ EXTRACTOR_flac_extract (const char *data,
376 break; 472 break;
377 } 473 }
378 FLAC__stream_decoder_finish (decoder); 474 FLAC__stream_decoder_finish (decoder);
379 FLAC__stream_decoder_delete(decoder); 475 FLAC__stream_decoder_delete (decoder);
380 return le_cls.ret;
381} 476}
477
478/* end of flac_extractor.c */
479