libextractor

GNU libextractor
Log | Files | Refs | Submodules | README | LICENSE

commit af157f674ec24e79cd177e2e8be7e40fb9fb1f4f
parent 60c918a23455fa0d8da5d418c47a4e35950cade8
Author: Christian Grothoff <christian@grothoff.org>
Date:   Thu, 17 Dec 2009 14:33:32 +0000

flac

Diffstat:
Msrc/include/extractor.h | 5+++++
Msrc/main/extractor_metatypes.c | 13+++++++++++++
Msrc/plugins/Makefile.am | 21+++++++++------------
Asrc/plugins/flac_extractor.c | 376+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dsrc/plugins/flacextractor.c | 337-------------------------------------------------------------------------------
5 files changed, 403 insertions(+), 349 deletions(-)

diff --git a/src/include/extractor.h b/src/include/extractor.h @@ -266,6 +266,11 @@ enum EXTRACTOR_MetaType EXTRACTOR_METATYPE_PERFORMER = 134, EXTRACTOR_METATYPE_CONTACT_INFORMATION = 135, EXTRACTOR_METATYPE_SONG_VERSION = 136, + EXTRACTOR_METATYPE_PICTURE = 137, + EXTRACTOR_METATYPE_COVER_PICTURE = 138, + EXTRACTOR_METATYPE_CONTRIBUTOR_PICTURE = 139, + EXTRACTOR_METATYPE_EVENT_PICTURE = 140, + EXTRACTOR_METATYPE_LOGO = 141, EXTRACTOR_METATYPE_PLAY_COUNTER = 118, EXTRACTOR_METATYPE_LYRICS = 67, diff --git a/src/main/extractor_metatypes.c b/src/main/extractor_metatypes.c @@ -338,6 +338,19 @@ static const struct MetaTypeDescription meta_type_descriptions[] = { gettext_noop ("Contact information for the creator or distributor") }, { gettext_noop ("song version"), gettext_noop ("name of the version of the song (i.e. remix information)") }, + { gettext_noop ("picture"), + gettext_noop ("associated misc. picture") }, + { gettext_noop ("cover picture"), + gettext_noop ("picture of the cover of the distribution medium") }, + { gettext_noop ("contributor picture"), + gettext_noop ("picture of one of the contributors") }, + /* 140 */ + { gettext_noop ("event picture"), + gettext_noop ("picture of an associated event") }, + { gettext_noop ("logo"), + gettext_noop ("logo of an associated organization") }, + { gettext_noop (""), + gettext_noop ("") }, { gettext_noop (""), gettext_noop ("") }, { gettext_noop (""), diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am @@ -73,6 +73,7 @@ plugin_LTLIBRARIES = \ libextractor_dvi.la \ libextractor_elf.la \ $(exiv2) \ + $(flac) \ libextractor_gif.la \ libextractor_html.la \ libextractor_it.la \ @@ -126,6 +127,14 @@ libextractor_exiv2_la_LDFLAGS = \ libextractor_exiv2_la_LIBADD = \ -lexiv2 +libextractor_flac_la_SOURCES = \ + flac_extractor.c +libextractor_flac_la_LDFLAGS = \ + $(PLUGINFLAGS) +libextractor_flac_la_LIBADD = \ + -lFLAC $(flacoggflag) \ + $(LE_LIBINTL) + libextractor_gif_la_SOURCES = \ gif_extractor.c libextractor_gif_la_LDFLAGS = \ @@ -230,7 +239,6 @@ libextractor_thumbnailgtk_la_SOURCES = \ OLD_LIBS = \ - $(extraflac) \ libextractor_flv.la \ libextractor_id3v2.la \ libextractor_id3v24.la \ @@ -252,17 +260,6 @@ OLD_LIBS = \ libextractor_xm.la \ libextractor_zip.la -if HAVE_FLAC -libextractor_flac_la_SOURCES = \ - flacextractor.c -libextractor_flac_la_LDFLAGS = \ - $(PLUGINFLAGS) -libextractor_flac_la_LIBADD = \ - -lFLAC $(flacoggflag) \ - $(top_builddir)/src/main/libextractor.la \ - $(LE_LIBINTL) -endif - if HAVE_ZLIB libextractor_qt_la_SOURCES = \ qtextractor.c diff --git a/src/plugins/flac_extractor.c b/src/plugins/flac_extractor.c @@ -0,0 +1,376 @@ +/* + This file is part of libextractor. + (C) 2007, 2009 Vidyut Samanta and Christian Grothoff + + libextractor is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + libextractor is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libextractor; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + */ + +#include "platform.h" +#include "extractor.h" + +#define FLAC_HEADER "fLaC" + +#if HAVE_FLAC_ALL_H +#include <FLAC/all.h> +#else +#error You must install the libflac header files! +#endif + + +struct Context { + const char * data; + size_t size; + size_t pos; + EXTRACTOR_MetaDataProcessor proc; + void *proc_cls; + int ret; +}; + +static FLAC__StreamDecoderReadStatus +flac_read (const FLAC__StreamDecoder *decoder, + FLAC__byte buffer[], + size_t *bytes, + void *client_data) +{ + struct Context * ctx = client_data; + + if (*bytes <= 0) + return FLAC__STREAM_DECODER_READ_STATUS_ABORT; + if (*bytes > ctx->size - ctx->pos) + *bytes = ctx->size - ctx->pos; + if (*bytes == 0) + return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; + memcpy(buffer, + &ctx->data[ctx->pos], + *bytes); + ctx->pos += *bytes; + return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; +} + +static FLAC__StreamDecoderSeekStatus +flac_seek(const FLAC__StreamDecoder *decoder, + FLAC__uint64 absolute_byte_offset, void *client_data) +{ + struct Context * ctx = client_data; + + if (absolute_byte_offset > ctx->size) + return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; + ctx->pos = (size_t) absolute_byte_offset; + return FLAC__STREAM_DECODER_SEEK_STATUS_OK; +} + +static FLAC__StreamDecoderTellStatus +flac_tell(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) +{ + struct Context * ctx = client_data; + + *absolute_byte_offset = ctx->pos; + return FLAC__STREAM_DECODER_TELL_STATUS_OK; +} + +static FLAC__StreamDecoderLengthStatus +flac_length(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) +{ + struct Context * ctx = client_data; + + ctx->pos = *stream_length; + return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; +} + +static FLAC__bool +flac_eof(const FLAC__StreamDecoder *decoder, void *client_data) +{ + struct Context * ctx = client_data; + + return (ctx->pos == ctx->size) ? true : false; +} + +static FLAC__StreamDecoderWriteStatus +flac_write(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) +{ + return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; +} + +typedef struct +{ + const char *text; + enum EXTRACTOR_MetaType type; +} Matches; + +static Matches tmap[] = { + {"TITLE", EXTRACTOR_METATYPE_TITLE}, + {"VERSION", EXTRACTOR_METATYPE_SONG_VERSION}, + {"ALBUM", EXTRACTOR_METATYPE_ALBUM}, + {"ARTIST", EXTRACTOR_METATYPE_ARTIST}, + {"PERFORMER", EXTRACTOR_METATYPE_PERFORMER}, + {"COPYRIGHT", EXTRACTOR_METATYPE_COPYRIGHT}, + {"LICENSE", EXTRACTOR_METATYPE_LICENSE}, + {"ORGANIZATION", EXTRACTOR_METATYPE_ORGANIZATION}, + {"DESCRIPTION", EXTRACTOR_METATYPE_DESCRIPTION}, + {"GENRE", EXTRACTOR_METATYPE_GENRE}, + {"DATE", EXTRACTOR_METATYPE_CREATION_DATE}, + {"LOCATION", EXTRACTOR_METATYPE_LOCATION_SUBLOCATION}, + {"CONTACT", EXTRACTOR_METATYPE_CONTACT_INFORMATION}, + {"TRACKNUMBER", EXTRACTOR_METATYPE_TRACK_NUMBER}, + {"ISRC", EXTRACTOR_METATYPE_ISRC}, + {NULL, 0}, +}; + + +static char * xstrndup(const char * s, size_t n){ + char * d; + + d= malloc(n+1); + memcpy(d,s,n); + d[n]='\0'; + return d; +} + +#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) + + +static void +check(const char * type, + unsigned int type_length, + const char * value, + unsigned int value_length, + struct Context *ctx) +{ + unsigned int i; + char *tmp; + + i = 0; + while (tmap[i].text != NULL) + { + if ( (type_length == strlen(tmap[i].text)) && + (0 == strncasecmp(tmap[i].text, + type, + type_length)) ) + { + tmp = xstrndup(value, + value_length); + ADD (tmap[i].type, tmp); + free (tmp); + break; + } + i++; + } +} + + +static void +flac_metadata(const FLAC__StreamDecoder *decoder, + const FLAC__StreamMetadata *metadata, + void *client_data) +{ + struct Context * ctx = client_data; + + switch (metadata->type) + { + case FLAC__METADATA_TYPE_STREAMINFO: + { + char buf[512]; + snprintf(buf, 512, + _("%u Hz, %u channels"), + metadata->data.stream_info.sample_rate, + metadata->data.stream_info.channels); + ADD (EXTRACTOR_METATYPE_RESOURCE_TYPE, buf); + break; + } + case FLAC__METADATA_TYPE_APPLICATION: + /* FIXME: could find out generator application here: + http://flac.sourceforge.net/api/structFLAC____StreamMetadata__Application.html and + http://flac.sourceforge.net/id.html + */ + break; + case FLAC__METADATA_TYPE_VORBIS_COMMENT: + { + const FLAC__StreamMetadata_VorbisComment * vc = &metadata->data.vorbis_comment; + unsigned int count = vc->num_comments; + const FLAC__StreamMetadata_VorbisComment_Entry * entry; + const char * eq; + unsigned int len; + unsigned int ilen; + + while (count-- > 0) + { + entry = &vc->comments[count]; + eq = (const char*) entry->entry; + len = entry->length; + ilen = 0; + while ( ('=' != *eq) && (*eq != '\0') && + (ilen < len) ) + { + eq++; + ilen++; + } + if ( ('=' != *eq) || + (ilen == len) ) + break; + eq++; + check((const char*) entry->entry, + ilen, + eq, + len - ilen, + ctx); + } + break; + } + case FLAC__METADATA_TYPE_PICTURE: + { + if (ctx->ret == 0) + { + enum EXTRACTOR_MetaType type; + switch (metadata->data.picture.type) + { + case FLAC__STREAM_METADATA_PICTURE_TYPE_OTHER: + case FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON_STANDARD: + case FLAC__STREAM_METADATA_PICTURE_TYPE_FILE_ICON: + type = EXTRACTOR_METATYPE_THUMBNAIL; + break; + case FLAC__STREAM_METADATA_PICTURE_TYPE_FRONT_COVER: + case FLAC__STREAM_METADATA_PICTURE_TYPE_BACK_COVER: + type = EXTRACTOR_METATYPE_COVER_PICTURE; + break; + case FLAC__STREAM_METADATA_PICTURE_TYPE_LEAD_ARTIST: + case FLAC__STREAM_METADATA_PICTURE_TYPE_ARTIST: + case FLAC__STREAM_METADATA_PICTURE_TYPE_CONDUCTOR: + case FLAC__STREAM_METADATA_PICTURE_TYPE_BAND: + case FLAC__STREAM_METADATA_PICTURE_TYPE_COMPOSER: + case FLAC__STREAM_METADATA_PICTURE_TYPE_LYRICIST: + type = EXTRACTOR_METATYPE_CONTRIBUTOR_PICTURE; + break; + case FLAC__STREAM_METADATA_PICTURE_TYPE_RECORDING_LOCATION: + case FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_RECORDING: + case FLAC__STREAM_METADATA_PICTURE_TYPE_DURING_PERFORMANCE: + case FLAC__STREAM_METADATA_PICTURE_TYPE_VIDEO_SCREEN_CAPTURE: + type = EXTRACTOR_METATYPE_EVENT_PICTURE; + break; + case FLAC__STREAM_METADATA_PICTURE_TYPE_BAND_LOGOTYPE: + case FLAC__STREAM_METADATA_PICTURE_TYPE_PUBLISHER_LOGOTYPE: + type = EXTRACTOR_METATYPE_LOGO; + break; + case FLAC__STREAM_METADATA_PICTURE_TYPE_LEAFLET_PAGE: + case FLAC__STREAM_METADATA_PICTURE_TYPE_MEDIA: + case FLAC__STREAM_METADATA_PICTURE_TYPE_FISH: + case FLAC__STREAM_METADATA_PICTURE_TYPE_ILLUSTRATION: + default: + type = EXTRACTOR_METATYPE_PICTURE; + break; + } + ctx->ret = ctx->proc (ctx->proc_cls, + "flac", + type, + EXTRACTOR_METAFORMAT_BINARY, + metadata->data.picture.mime_type, + (const char*) metadata->data.picture.data, + metadata->data.picture.data_length); + } + break; + } + case FLAC__METADATA_TYPE_PADDING: + case FLAC__METADATA_TYPE_SEEKTABLE: + case FLAC__METADATA_TYPE_CUESHEET: + case FLAC__METADATA_TYPE_UNDEFINED: + break; + } +} + +static void +flac_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) +{ +#if 0 + fprintf(stderr, + "Got error: %u\n", status); +#endif +} + +/* mimetype = audio/flac */ +int +EXTRACTOR_flac_extract (const char *data, + size_t size, + EXTRACTOR_MetaDataProcessor proc, + void *proc_cls, + const char *options) +{ + FLAC__StreamDecoder * decoder; + struct Context le_cls; + struct Context *ctx; + + if (size < strlen(FLAC_HEADER) + sizeof (int)) + return 0; + if (0 != memcmp(FLAC_HEADER, + data, + strlen(FLAC_HEADER))) + return 0; + decoder = FLAC__stream_decoder_new(); + if (NULL == decoder) + return 0; + FLAC__stream_decoder_set_md5_checking(decoder, false); + FLAC__stream_decoder_set_metadata_ignore_all(decoder); + if (false == FLAC__stream_decoder_set_metadata_respond_all(decoder)) + { + FLAC__stream_decoder_delete(decoder); + return 0; + } + le_cls.ret = 0; + le_cls.size = size; + le_cls.data = data; + le_cls.proc = proc; + le_cls.proc_cls = proc_cls; + le_cls.pos = 0; + if (FLAC__STREAM_DECODER_INIT_STATUS_OK != + FLAC__stream_decoder_init_stream(decoder, + &flac_read, + &flac_seek, + &flac_tell, + &flac_length, + &flac_eof, + &flac_write, + &flac_metadata, + &flac_error, + &le_cls)) + { + FLAC__stream_decoder_delete(decoder); + return le_cls.ret; + } + if (FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) + { + FLAC__stream_decoder_delete(decoder); + return le_cls.ret; + } + if (! FLAC__stream_decoder_process_until_end_of_metadata(decoder)) + { + FLAC__stream_decoder_delete(decoder); + return le_cls.ret; + } + switch (FLAC__stream_decoder_get_state(decoder)) + { + case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: + case FLAC__STREAM_DECODER_READ_METADATA: + case FLAC__STREAM_DECODER_END_OF_STREAM: + case FLAC__STREAM_DECODER_READ_FRAME: + ctx = &le_cls; + ADD (EXTRACTOR_METATYPE_MIMETYPE, "audio/flac"); + break; + default: + /* not so sure... */ + break; + } + FLAC__stream_decoder_finish (decoder); + FLAC__stream_decoder_delete(decoder); + return le_cls.ret; +} diff --git a/src/plugins/flacextractor.c b/src/plugins/flacextractor.c @@ -1,337 +0,0 @@ -/* - This file is part of libextractor. - (C) 2007 Vidyut Samanta and Christian Grothoff - - libextractor is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your - option) any later version. - - libextractor is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libextractor; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. - */ - -#include "platform.h" -#include "extractor.h" - -#define FLAC_HEADER "fLaC" - -#if HAVE_FLAC_ALL_H -#include <FLAC/all.h> -#else -#error You must install the libflac header files! -#endif - -static char * xstrndup(const char * s, size_t n){ - char * d; - - d= malloc(n+1); - memcpy(d,s,n); - d[n]='\0'; - return d; -} - -static struct EXTRACTOR_Keywords * -addKeyword (EXTRACTOR_KeywordType type, - char *keyword, struct EXTRACTOR_Keywords *next) -{ - EXTRACTOR_KeywordList *result; - - if (keyword == NULL) - return next; - result = malloc (sizeof (EXTRACTOR_KeywordList)); - result->next = next; - result->keyword = keyword; - result->keywordType = type; - return result; -} - -struct Context { - const char * data; - size_t size; - struct EXTRACTOR_Keywords * prev; - size_t pos; -}; - -static FLAC__StreamDecoderReadStatus -flac_read (const FLAC__StreamDecoder *decoder, - FLAC__byte buffer[], - size_t *bytes, - void *client_data) -{ - struct Context * ctx = client_data; - - if (*bytes <= 0) - return FLAC__STREAM_DECODER_READ_STATUS_ABORT; - if (*bytes > ctx->size - ctx->pos) - *bytes = ctx->size - ctx->pos; - if (*bytes == 0) - return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM; - memcpy(buffer, - &ctx->data[ctx->pos], - *bytes); - ctx->pos += *bytes; - return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; -} - -static FLAC__StreamDecoderSeekStatus -flac_seek(const FLAC__StreamDecoder *decoder, - FLAC__uint64 absolute_byte_offset, void *client_data) -{ - struct Context * ctx = client_data; - - if (absolute_byte_offset > ctx->size) - return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR; - ctx->pos = (size_t) absolute_byte_offset; - return FLAC__STREAM_DECODER_SEEK_STATUS_OK; -} - -static FLAC__StreamDecoderTellStatus -flac_tell(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data) -{ - struct Context * ctx = client_data; - - *absolute_byte_offset = ctx->pos; - return FLAC__STREAM_DECODER_TELL_STATUS_OK; -} - -static FLAC__StreamDecoderLengthStatus -flac_length(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data) -{ - struct Context * ctx = client_data; - - ctx->pos = *stream_length; - return FLAC__STREAM_DECODER_LENGTH_STATUS_OK; -} - -static FLAC__bool -flac_eof(const FLAC__StreamDecoder *decoder, void *client_data) -{ - struct Context * ctx = client_data; - - return (ctx->pos == ctx->size) ? true : false; -} - -static FLAC__StreamDecoderWriteStatus -flac_write(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data) -{ - return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; -} - -typedef struct -{ - char *text; - EXTRACTOR_KeywordType type; -} Matches; - -static Matches tmap[] = { - {"TITLE", EXTRACTOR_TITLE}, - {"VERSION", EXTRACTOR_VERSION}, - {"ALBUM", EXTRACTOR_ALBUM}, - {"ARTIST", EXTRACTOR_ARTIST}, - {"PERFORMER", EXTRACTOR_INTERPRET}, - {"COPYRIGHT", EXTRACTOR_COPYRIGHT}, - {"LICENSE", EXTRACTOR_LICENSE}, - {"ORGANIZATION", EXTRACTOR_ORGANIZATION}, - {"DESCRIPTION", EXTRACTOR_DESCRIPTION}, - {"GENRE", EXTRACTOR_GENRE}, - {"DATE", EXTRACTOR_DATE}, - {"LOCATION", EXTRACTOR_LOCATION}, - {"CONTACT", EXTRACTOR_CONTACT}, - {"TRACKNUMBER", EXTRACTOR_TRACK_NUMBER}, - {"ISRC", EXTRACTOR_ISRC}, - {NULL, 0}, -}; - - -static EXTRACTOR_KeywordList * -check(const char * type, - unsigned int type_length, - const char * value, - unsigned int value_length, - EXTRACTOR_KeywordList * prev) -{ - unsigned int i; - i = 0; - while (tmap[i].text != NULL) - { - if ( (type_length == strlen(tmap[i].text)) && - (0 == strncasecmp(tmap[i].text, - type, - type_length)) ) - return addKeyword(tmap[i].type, - xstrndup(value, - value_length), - prev); - i++; - } - return prev; -} - -static void -flac_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data) -{ - struct Context * ctx = client_data; - - switch (metadata->type) - { - case FLAC__METADATA_TYPE_STREAMINFO: - { - char buf[512]; - snprintf(buf, 512, - _("%u Hz, %u channels"), - metadata->data.stream_info.sample_rate, - metadata->data.stream_info.channels); - ctx->prev = addKeyword(EXTRACTOR_FORMAT, - strdup(buf), - ctx->prev); - break; - } - case FLAC__METADATA_TYPE_APPLICATION: - /* FIXME: could find out generator application here: - http://flac.sourceforge.net/api/structFLAC____StreamMetadata__Application.html and - http://flac.sourceforge.net/id.html - */ - break; - case FLAC__METADATA_TYPE_VORBIS_COMMENT: - { - const FLAC__StreamMetadata_VorbisComment * vc = &metadata->data.vorbis_comment; - unsigned int count = vc->num_comments; - const FLAC__StreamMetadata_VorbisComment_Entry * entry; - const char * eq; - unsigned int len; - unsigned int ilen; - - while (count-- > 0) - { - entry = &vc->comments[count]; - eq = (const char*) entry->entry; - len = entry->length; - ilen = 0; - while ( ('=' != *eq) && (*eq != '\0') && - (ilen < len) ) - { - eq++; - ilen++; - } - if ( ('=' != *eq) || - (ilen == len) ) - break; - eq++; - ctx->prev = check((const char*) entry->entry, - ilen, - eq, - len - ilen, - ctx->prev); - } - break; - } - case FLAC__METADATA_TYPE_PICTURE: - { - FLAC__byte * data = metadata->data.picture.data; - FLAC__uint32 length = metadata->data.picture.data_length; - char * enc; - - enc = EXTRACTOR_binaryEncode(data, length); - ctx->prev = addKeyword(EXTRACTOR_THUMBNAILS, - enc, - ctx->prev); - break; - } - case FLAC__METADATA_TYPE_PADDING: - case FLAC__METADATA_TYPE_SEEKTABLE: - case FLAC__METADATA_TYPE_CUESHEET: - case FLAC__METADATA_TYPE_UNDEFINED: - break; - } -} - -static void -flac_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) -{ -#if 0 - fprintf(stderr, - "Got error: %u\n", status); -#endif -} - -/* mimetype = audio/flac */ -struct EXTRACTOR_Keywords * -libextractor_flac_extract (const char *filename, - const char *data, - size_t size, struct EXTRACTOR_Keywords *prev) -{ - FLAC__StreamDecoder * decoder; - struct Context le_cls; - - if (size < strlen(FLAC_HEADER) + sizeof (int)) - return prev; - if (0 != memcmp(FLAC_HEADER, - data, - strlen(FLAC_HEADER))) - return prev; - decoder = FLAC__stream_decoder_new(); - if (NULL == decoder) - return prev; - FLAC__stream_decoder_set_md5_checking(decoder, false); - FLAC__stream_decoder_set_metadata_ignore_all(decoder); - if (false == FLAC__stream_decoder_set_metadata_respond_all(decoder)) - { - FLAC__stream_decoder_delete(decoder); - return prev; - } - le_cls.prev = prev; - le_cls.prev = prev; - le_cls.size = size; - le_cls.data = data; - le_cls.pos = 0; - if (FLAC__STREAM_DECODER_INIT_STATUS_OK != - FLAC__stream_decoder_init_stream(decoder, - &flac_read, - &flac_seek, - &flac_tell, - &flac_length, - &flac_eof, - &flac_write, - &flac_metadata, - &flac_error, - &le_cls)) - { - FLAC__stream_decoder_delete(decoder); - return le_cls.prev; - } - if (FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA) - { - FLAC__stream_decoder_delete(decoder); - return le_cls.prev; - } - if (! FLAC__stream_decoder_process_until_end_of_metadata(decoder)) - { - FLAC__stream_decoder_delete(decoder); - return le_cls.prev; - } - switch (FLAC__stream_decoder_get_state(decoder)) - { - case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC: - case FLAC__STREAM_DECODER_READ_METADATA: - case FLAC__STREAM_DECODER_END_OF_STREAM: - case FLAC__STREAM_DECODER_READ_FRAME: - le_cls.prev = addKeyword(EXTRACTOR_MIMETYPE, - strdup("audio/flac"), - le_cls.prev); - break; - default: - /* not so sure... */ - break; - } - FLAC__stream_decoder_finish (decoder); - FLAC__stream_decoder_delete(decoder); - return le_cls.prev; -}