00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "platform.h"
00022 #include "extractor.h"
00023
00024 #define FLAC_HEADER "fLaC"
00025
00026 #if HAVE_FLAC_ALL_H
00027 #include <FLAC/all.h>
00028 #else
00029 #error You must install the libflac header files!
00030 #endif
00031
00032 static char * xstrndup(const char * s, size_t n){
00033 char * d;
00034
00035 d= malloc(n+1);
00036 memcpy(d,s,n);
00037 d[n]='\0';
00038 return d;
00039 }
00040
00041 static struct EXTRACTOR_Keywords *
00042 addKeyword (EXTRACTOR_KeywordType type,
00043 char *keyword, struct EXTRACTOR_Keywords *next)
00044 {
00045 EXTRACTOR_KeywordList *result;
00046
00047 if (keyword == NULL)
00048 return next;
00049 result = malloc (sizeof (EXTRACTOR_KeywordList));
00050 result->next = next;
00051 result->keyword = keyword;
00052 result->keywordType = type;
00053 return result;
00054 }
00055
00056 struct Context {
00057 const char * data;
00058 size_t size;
00059 struct EXTRACTOR_Keywords * prev;
00060 size_t pos;
00061 };
00062
00063 static FLAC__StreamDecoderReadStatus
00064 flac_read (const FLAC__StreamDecoder *decoder,
00065 FLAC__byte buffer[],
00066 size_t *bytes,
00067 void *client_data)
00068 {
00069 struct Context * ctx = client_data;
00070
00071 if (*bytes <= 0)
00072 return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
00073 if (*bytes > ctx->size - ctx->pos)
00074 *bytes = ctx->size - ctx->pos;
00075 if (*bytes == 0)
00076 return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
00077 memcpy(buffer,
00078 &ctx->data[ctx->pos],
00079 *bytes);
00080 ctx->pos += *bytes;
00081 return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
00082 }
00083
00084 static FLAC__StreamDecoderSeekStatus
00085 flac_seek(const FLAC__StreamDecoder *decoder,
00086 FLAC__uint64 absolute_byte_offset, void *client_data)
00087 {
00088 struct Context * ctx = client_data;
00089
00090 if (absolute_byte_offset > ctx->size)
00091 return FLAC__STREAM_DECODER_SEEK_STATUS_ERROR;
00092 ctx->pos = (size_t) absolute_byte_offset;
00093 return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
00094 }
00095
00096 static FLAC__StreamDecoderTellStatus
00097 flac_tell(const FLAC__StreamDecoder *decoder, FLAC__uint64 *absolute_byte_offset, void *client_data)
00098 {
00099 struct Context * ctx = client_data;
00100
00101 *absolute_byte_offset = ctx->pos;
00102 return FLAC__STREAM_DECODER_TELL_STATUS_OK;
00103 }
00104
00105 static FLAC__StreamDecoderLengthStatus
00106 flac_length(const FLAC__StreamDecoder *decoder, FLAC__uint64 *stream_length, void *client_data)
00107 {
00108 struct Context * ctx = client_data;
00109
00110 ctx->pos = *stream_length;
00111 return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
00112 }
00113
00114 static FLAC__bool
00115 flac_eof(const FLAC__StreamDecoder *decoder, void *client_data)
00116 {
00117 struct Context * ctx = client_data;
00118
00119 return (ctx->pos == ctx->size) ? true : false;
00120 }
00121
00122 static FLAC__StreamDecoderWriteStatus
00123 flac_write(const FLAC__StreamDecoder *decoder, const FLAC__Frame *frame, const FLAC__int32 *const buffer[], void *client_data)
00124 {
00125 return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
00126 }
00127
00128 typedef struct
00129 {
00130 char *text;
00131 EXTRACTOR_KeywordType type;
00132 } Matches;
00133
00134 static Matches tmap[] = {
00135 {"TITLE", EXTRACTOR_TITLE},
00136 {"VERSION", EXTRACTOR_VERSION},
00137 {"ALBUM", EXTRACTOR_ALBUM},
00138 {"ARTIST", EXTRACTOR_ARTIST},
00139 {"PERFORMER", EXTRACTOR_INTERPRET},
00140 {"COPYRIGHT", EXTRACTOR_COPYRIGHT},
00141 {"LICENSE", EXTRACTOR_LICENSE},
00142 {"ORGANIZATION", EXTRACTOR_ORGANIZATION},
00143 {"DESCRIPTION", EXTRACTOR_DESCRIPTION},
00144 {"GENRE", EXTRACTOR_GENRE},
00145 {"DATE", EXTRACTOR_DATE},
00146 {"LOCATION", EXTRACTOR_LOCATION},
00147 {"CONTACT", EXTRACTOR_CONTACT},
00148 {"TRACKNUMBER", EXTRACTOR_TRACK_NUMBER},
00149 {"ISRC", EXTRACTOR_ISRC},
00150 {NULL, 0},
00151 };
00152
00153
00154 static EXTRACTOR_KeywordList *
00155 check(const char * type,
00156 unsigned int type_length,
00157 const char * value,
00158 unsigned int value_length,
00159 EXTRACTOR_KeywordList * prev)
00160 {
00161 unsigned int i;
00162 i = 0;
00163 while (tmap[i].text != NULL)
00164 {
00165 if ( (type_length == strlen(tmap[i].text)) &&
00166 (0 == strncasecmp(tmap[i].text,
00167 type,
00168 type_length)) )
00169 return addKeyword(tmap[i].type,
00170 xstrndup(value,
00171 value_length),
00172 prev);
00173 i++;
00174 }
00175 return prev;
00176 }
00177
00178 static void
00179 flac_metadata(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetadata *metadata, void *client_data)
00180 {
00181 struct Context * ctx = client_data;
00182
00183 switch (metadata->type)
00184 {
00185 case FLAC__METADATA_TYPE_STREAMINFO:
00186 {
00187 char buf[512];
00188 snprintf(buf, 512,
00189 _("%u Hz, %u channels"),
00190 metadata->data.stream_info.sample_rate,
00191 metadata->data.stream_info.channels);
00192 ctx->prev = addKeyword(EXTRACTOR_FORMAT,
00193 strdup(buf),
00194 ctx->prev);
00195 break;
00196 }
00197 case FLAC__METADATA_TYPE_APPLICATION:
00198
00199
00200
00201
00202 break;
00203 case FLAC__METADATA_TYPE_VORBIS_COMMENT:
00204 {
00205 const FLAC__StreamMetadata_VorbisComment * vc = &metadata->data.vorbis_comment;
00206 unsigned int count = vc->num_comments;
00207 const FLAC__StreamMetadata_VorbisComment_Entry * entry;
00208 const char * eq;
00209 unsigned int len;
00210 unsigned int ilen;
00211
00212 while (count-- > 0)
00213 {
00214 entry = &vc->comments[count];
00215 eq = (const char*) entry->entry;
00216 len = entry->length;
00217 ilen = 0;
00218 while ( ('=' != *eq) && (*eq != '\0') &&
00219 (ilen < len) )
00220 {
00221 eq++;
00222 ilen++;
00223 }
00224 if ( ('=' != *eq) ||
00225 (ilen == len) )
00226 break;
00227 eq++;
00228 ctx->prev = check((const char*) entry->entry,
00229 ilen,
00230 eq,
00231 len - ilen,
00232 ctx->prev);
00233 }
00234 break;
00235 }
00236 case FLAC__METADATA_TYPE_PICTURE:
00237 {
00238 FLAC__byte * data = metadata->data.picture.data;
00239 FLAC__uint32 length = metadata->data.picture.data_length;
00240 char * enc;
00241
00242 enc = EXTRACTOR_binaryEncode(data, length);
00243 ctx->prev = addKeyword(EXTRACTOR_THUMBNAILS,
00244 enc,
00245 ctx->prev);
00246 break;
00247 }
00248 case FLAC__METADATA_TYPE_PADDING:
00249 case FLAC__METADATA_TYPE_SEEKTABLE:
00250 case FLAC__METADATA_TYPE_CUESHEET:
00251 case FLAC__METADATA_TYPE_UNDEFINED:
00252 break;
00253 }
00254 }
00255
00256 static void
00257 flac_error(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
00258 {
00259 #if 0
00260 fprintf(stderr,
00261 "Got error: %u\n", status);
00262 #endif
00263 }
00264
00265
00266 struct EXTRACTOR_Keywords *
00267 libextractor_flac_extract (const char *filename,
00268 const char *data,
00269 size_t size, struct EXTRACTOR_Keywords *prev)
00270 {
00271 FLAC__StreamDecoder * decoder;
00272 struct Context le_cls;
00273
00274 if (size < strlen(FLAC_HEADER) + sizeof (int))
00275 return prev;
00276 if (0 != memcmp(FLAC_HEADER,
00277 data,
00278 strlen(FLAC_HEADER)))
00279 return prev;
00280 decoder = FLAC__stream_decoder_new();
00281 if (NULL == decoder)
00282 return prev;
00283 FLAC__stream_decoder_set_md5_checking(decoder, false);
00284 FLAC__stream_decoder_set_metadata_ignore_all(decoder);
00285 if (false == FLAC__stream_decoder_set_metadata_respond_all(decoder))
00286 {
00287 FLAC__stream_decoder_delete(decoder);
00288 return prev;
00289 }
00290 le_cls.prev = prev;
00291 le_cls.prev = prev;
00292 le_cls.size = size;
00293 le_cls.data = data;
00294 le_cls.pos = 0;
00295 if (FLAC__STREAM_DECODER_INIT_STATUS_OK !=
00296 FLAC__stream_decoder_init_stream(decoder,
00297 &flac_read,
00298 &flac_seek,
00299 &flac_tell,
00300 &flac_length,
00301 &flac_eof,
00302 &flac_write,
00303 &flac_metadata,
00304 &flac_error,
00305 &le_cls))
00306 {
00307 FLAC__stream_decoder_delete(decoder);
00308 return le_cls.prev;
00309 }
00310 if (FLAC__stream_decoder_get_state(decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
00311 {
00312 FLAC__stream_decoder_delete(decoder);
00313 return le_cls.prev;
00314 }
00315 if (! FLAC__stream_decoder_process_until_end_of_metadata(decoder))
00316 {
00317 FLAC__stream_decoder_delete(decoder);
00318 return le_cls.prev;
00319 }
00320 switch (FLAC__stream_decoder_get_state(decoder))
00321 {
00322 case FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC:
00323 case FLAC__STREAM_DECODER_READ_METADATA:
00324 case FLAC__STREAM_DECODER_END_OF_STREAM:
00325 case FLAC__STREAM_DECODER_READ_FRAME:
00326 le_cls.prev = addKeyword(EXTRACTOR_MIMETYPE,
00327 strdup("audio/flac"),
00328 le_cls.prev);
00329 break;
00330 default:
00331
00332 break;
00333 }
00334 FLAC__stream_decoder_finish (decoder);
00335 FLAC__stream_decoder_delete(decoder);
00336 return le_cls.prev;
00337 }