00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00032
00033 #ifdef HAVE_CONFIG_H
00034 #include "autoconfig.h"
00035 #endif
00036
00037 #ifdef HAVE_LIBEXTRACTOR
00038
00039 #include <extractor.h>
00040
00041 #include "config_manager.h"
00042 #include "extractor_handler.h"
00043 #include "string_converter.h"
00044 #include "common.h"
00045 #include "tools.h"
00046 #include "rexp.h"
00047 #include "mxml/mxml.h"
00048
00049
00050 using namespace zmm;
00051 using namespace mxml;
00052
00053
00054 ExtractorHandler::ExtractorHandler() : MetadataHandler()
00055 {
00056 }
00057
00058 static EXTRACTOR_KeywordType getTagFromString(String tag)
00059 {
00060 if (tag == "EXTRACTOR_UNKNOWN")
00061 return EXTRACTOR_UNKNOWN;
00062 if (tag == "EXTRACTOR_FILENAME")
00063 return EXTRACTOR_FILENAME;
00064 if (tag == "EXTRACTOR_MIMETYPE")
00065 return EXTRACTOR_MIMETYPE;
00066 if (tag == "EXTRACTOR_TITLE")
00067 return EXTRACTOR_TITLE;
00068 if (tag == "EXTRACTOR_AUTHOR")
00069 return EXTRACTOR_AUTHOR;
00070 if (tag == "EXTRACTOR_ARTIST")
00071 return EXTRACTOR_ARTIST;
00072 if (tag == "EXTRACTOR_DESCRIPTION")
00073 return EXTRACTOR_DESCRIPTION;
00074 if (tag == "EXTRACTOR_COMMENT")
00075 return EXTRACTOR_COMMENT;
00076 if (tag == "EXTRACTOR_DATE")
00077 return EXTRACTOR_DATE;
00078 if (tag == "EXTRACTOR_PUBLISHER")
00079 return EXTRACTOR_PUBLISHER;
00080 if (tag == "EXTRACTOR_LANGUAGE")
00081 return EXTRACTOR_LANGUAGE;
00082 if (tag == "EXTRACTOR_ALBUM")
00083 return EXTRACTOR_ALBUM;
00084 if (tag == "EXTRACTOR_GENRE")
00085 return EXTRACTOR_GENRE;
00086 if (tag == "EXTRACTOR_LOCATION")
00087 return EXTRACTOR_LOCATION;
00088 if (tag == "EXTRACTOR_VERSIONNUMBER")
00089 return EXTRACTOR_VERSIONNUMBER;
00090 if (tag == "EXTRACTOR_ORGANIZATION")
00091 return EXTRACTOR_ORGANIZATION;
00092 if (tag == "EXTRACTOR_COPYRIGHT")
00093 return EXTRACTOR_COPYRIGHT;
00094 if (tag == "EXTRACTOR_SUBJECT")
00095 return EXTRACTOR_SUBJECT;
00096 if (tag == "EXTRACTOR_KEYWORDS")
00097 return EXTRACTOR_KEYWORDS;
00098 if (tag == "EXTRACTOR_CONTRIBUTOR")
00099 return EXTRACTOR_CONTRIBUTOR;
00100 if (tag == "EXTRACTOR_RESOURCE_TYPE")
00101 return EXTRACTOR_RESOURCE_TYPE;
00102 if (tag == "EXTRACTOR_FORMAT")
00103 return EXTRACTOR_FORMAT;
00104 if (tag == "EXTRACTOR_RESOURCE_IDENTIFIER")
00105 return EXTRACTOR_RESOURCE_IDENTIFIER;
00106 if (tag == "EXTRACTOR_SOURCE")
00107 return EXTRACTOR_SOURCE;
00108 if (tag == "EXTRACTOR_RELATION")
00109 return EXTRACTOR_RELATION;
00110 if (tag == "EXTRACTOR_COVERAGE")
00111 return EXTRACTOR_COVERAGE;
00112 if (tag == "EXTRACTOR_SOFTWARE")
00113 return EXTRACTOR_SOFTWARE;
00114 if (tag == "EXTRACTOR_DISCLAIMER")
00115 return EXTRACTOR_DISCLAIMER;
00116 if (tag == "EXTRACTOR_WARNING")
00117 return EXTRACTOR_WARNING;
00118 if (tag == "EXTRACTOR_TRANSLATED")
00119 return EXTRACTOR_TRANSLATED;
00120 if (tag == "EXTRACTOR_CREATION_DATE")
00121 return EXTRACTOR_CREATION_DATE;
00122 if (tag == "EXTRACTOR_MODIFICATION_DATE")
00123 return EXTRACTOR_MODIFICATION_DATE;
00124 if (tag == "EXTRACTOR_CREATOR")
00125 return EXTRACTOR_CREATOR;
00126 if (tag == "EXTRACTOR_PRODUCER")
00127 return EXTRACTOR_PRODUCER;
00128 if (tag == "EXTRACTOR_PAGE_COUNT")
00129 return EXTRACTOR_PAGE_COUNT;
00130 if (tag == "EXTRACTOR_PAGE_ORIENTATION")
00131 return EXTRACTOR_PAGE_ORIENTATION;
00132 if (tag == "EXTRACTOR_PAPER_SIZE")
00133 return EXTRACTOR_PAPER_SIZE;
00134 if (tag == "EXTRACTOR_USED_FONTS")
00135 return EXTRACTOR_USED_FONTS;
00136 if (tag == "EXTRACTOR_PAGE_ORDER")
00137 return EXTRACTOR_PAGE_ORDER;
00138 if (tag == "EXTRACTOR_CREATED_FOR")
00139 return EXTRACTOR_CREATED_FOR;
00140 if (tag == "EXTRACTOR_MAGNIFICATION")
00141 return EXTRACTOR_MAGNIFICATION;
00142 if (tag == "EXTRACTOR_RELEASE")
00143 return EXTRACTOR_RELEASE;
00144 if (tag == "EXTRACTOR_GROUP")
00145 return EXTRACTOR_GROUP;
00146 if (tag == "EXTRACTOR_SIZE")
00147 return EXTRACTOR_SIZE;
00148 if (tag == "EXTRACTOR_SUMMARY")
00149 return EXTRACTOR_SUMMARY;
00150 if (tag == "EXTRACTOR_PACKAGER")
00151 return EXTRACTOR_PACKAGER;
00152 if (tag == "EXTRACTOR_VENDOR")
00153 return EXTRACTOR_VENDOR;
00154 if (tag == "EXTRACTOR_LICENSE")
00155 return EXTRACTOR_LICENSE;
00156 if (tag == "EXTRACTOR_DISTRIBUTION")
00157 return EXTRACTOR_DISTRIBUTION;
00158 if (tag == "EXTRACTOR_BUILDHOST")
00159 return EXTRACTOR_BUILDHOST;
00160 if (tag == "EXTRACTOR_OS")
00161 return EXTRACTOR_OS;
00162 if (tag == "EXTRACTOR_DEPENDENCY")
00163 return EXTRACTOR_DEPENDENCY;
00164 if (tag == "EXTRACTOR_HASH_MD4")
00165 return EXTRACTOR_HASH_MD4;
00166 if (tag == "EXTRACTOR_HASH_MD5")
00167 return EXTRACTOR_HASH_MD5;
00168 if (tag == "EXTRACTOR_HASH_SHA0")
00169 return EXTRACTOR_HASH_SHA0;
00170 if (tag == "EXTRACTOR_HASH_SHA1")
00171 return EXTRACTOR_HASH_SHA1;
00172 if (tag == "EXTRACTOR_HASH_RMD160")
00173 return EXTRACTOR_HASH_RMD160;
00174 if (tag == "EXTRACTOR_RESOLUTION")
00175 return EXTRACTOR_RESOLUTION;
00176 if (tag == "EXTRACTOR_CATEGORY")
00177 return EXTRACTOR_CATEGORY;
00178 if (tag == "EXTRACTOR_BOOKTITLE")
00179 return EXTRACTOR_BOOKTITLE;
00180 if (tag == "EXTRACTOR_PRIORITY")
00181 return EXTRACTOR_PRIORITY;
00182 if (tag == "EXTRACTOR_CONFLICTS")
00183 return EXTRACTOR_CONFLICTS;
00184 if (tag == "EXTRACTOR_REPLACES")
00185 return EXTRACTOR_REPLACES;
00186 if (tag == "EXTRACTOR_PROVIDES")
00187 return EXTRACTOR_PROVIDES;
00188 if (tag == "EXTRACTOR_CONDUCTOR")
00189 return EXTRACTOR_CONDUCTOR;
00190 if (tag == "EXTRACTOR_INTERPRET")
00191 return EXTRACTOR_INTERPRET;
00192 if (tag == "EXTRACTOR_OWNER")
00193 return EXTRACTOR_OWNER;
00194 if (tag == "EXTRACTOR_LYRICS")
00195 return EXTRACTOR_LYRICS;
00196 if (tag == "EXTRACTOR_MEDIA_TYPE")
00197 return EXTRACTOR_MEDIA_TYPE;
00198 if (tag == "EXTRACTOR_CONTACT")
00199 return EXTRACTOR_CONTACT;
00200 if (tag == "EXTRACTOR_THUMBNAIL_DATA")
00201 return EXTRACTOR_THUMBNAIL_DATA;
00202
00203 #ifdef EXTRACTOR_GE_0_5_2
00204 if (tag == "EXTRACTOR_PUBLICATION_DATE")
00205 return EXTRACTOR_PUBLICATION_DATE;
00206 if (tag == "EXTRACTOR_CAMERA_MAKE")
00207 return EXTRACTOR_CAMERA_MAKE;
00208 if (tag == "EXTRACTOR_CAMERA_MODEL")
00209 return EXTRACTOR_CAMERA_MODEL;
00210 if (tag == "EXTRACTOR_EXPOSURE")
00211 return EXTRACTOR_EXPOSURE;
00212 if (tag == "EXTRACTOR_APERTURE")
00213 return EXTRACTOR_APERTURE;
00214 if (tag == "EXTRACTOR_EXPOSURE_BIAS")
00215 return EXTRACTOR_EXPOSURE_BIAS;
00216 if (tag == "EXTRACTOR_FLASH")
00217 return EXTRACTOR_FLASH;
00218 if (tag == "EXTRACTOR_FLASH_BIAS")
00219 return EXTRACTOR_FLASH_BIAS;
00220 if (tag == "EXTRACTOR_FOCAL_LENGTH")
00221 return EXTRACTOR_FOCAL_LENGTH;
00222 if (tag == "EXTRACTOR_FOCAL_LENGTH_35MM")
00223 return EXTRACTOR_FOCAL_LENGTH_35MM;
00224 if (tag == "EXTRACTOR_ISO_SPEED")
00225 return EXTRACTOR_ISO_SPEED;
00226 if (tag == "EXTRACTOR_EXPOSURE_MODE")
00227 return EXTRACTOR_EXPOSURE_MODE;
00228 if (tag == "EXTRACTOR_METERING_MODE")
00229 return EXTRACTOR_METERING_MODE;
00230 if (tag == "EXTRACTOR_MACRO_MODE")
00231 return EXTRACTOR_MACRO_MODE;
00232 if (tag == "EXTRACTOR_IMAGE_QUALITY")
00233 return EXTRACTOR_IMAGE_QUALITY;
00234 if (tag == "EXTRACTOR_WHITE_BALANCE")
00235 return EXTRACTOR_WHITE_BALANCE;
00236 if (tag == "EXTRACTOR_ORIENTATION")
00237 return EXTRACTOR_ORIENTATION;
00238 #endif // EXTRACTOR_GE_0_5_2
00239
00240 log_warning("Ignoring unknown libextractor tag: %s\n", tag.c_str());
00241 return EXTRACTOR_UNKNOWN;
00242 }
00243
00244 static void addMetaField(metadata_fields_t field, EXTRACTOR_KeywordList *keywords, Ref<CdsItem> item, Ref<StringConverter> sc)
00245 {
00246 String value;
00247 const char *temp = NULL;
00248
00250
00251 switch (field)
00252 {
00253 case M_TITLE:
00254 temp = EXTRACTOR_extractLast(EXTRACTOR_TITLE, keywords);
00255 break;
00256 case M_ARTIST:
00257 temp = EXTRACTOR_extractLast(EXTRACTOR_ARTIST, keywords);
00258 break;
00259 case M_ALBUM:
00260 temp = EXTRACTOR_extractLast(EXTRACTOR_ALBUM, keywords);
00261 break;
00262 case M_DATE:
00263 temp = EXTRACTOR_extractLast(EXTRACTOR_DATE, keywords);
00264 break;
00265 case M_GENRE:
00266 temp = EXTRACTOR_extractLast(EXTRACTOR_GENRE, keywords);
00267 break;
00268 case M_DESCRIPTION:
00269 temp = EXTRACTOR_extractLast(EXTRACTOR_DESCRIPTION, keywords);
00270
00271 if (temp == NULL)
00272 temp = EXTRACTOR_extractLast(EXTRACTOR_COMMENT, keywords);
00273 break;
00274 default:
00275 return;
00276 }
00277
00278 if (temp != NULL)
00279 value = temp;
00280
00281 value = trim_string(value);
00282
00283 if (string_ok(value))
00284 {
00285 item->setMetadata(MT_KEYS[field].upnp, sc->convert(value));
00286
00287 }
00288 }
00289
00290 static void addResourceField(resource_attributes_t attr, EXTRACTOR_KeywordList *keywords, Ref<CdsItem> item, Ref<StringConverter> sc)
00291 {
00292 String value;
00293 const char *temp = NULL;
00294
00295 switch (attr)
00296 {
00297 case R_RESOLUTION:
00298 temp = EXTRACTOR_extractLast(EXTRACTOR_SIZE, keywords);
00299 break;
00300
00301
00302
00303
00304 default:
00305 return;
00306 }
00307
00308 if (temp != NULL)
00309 value = temp;
00310
00311 if (string_ok(value))
00312 {
00313 item->getResource(0)->addAttribute(MetadataHandler::getResAttrName(attr), value);
00314 }
00315 }
00316
00317
00318
00319 Ref<RExp> ReAudioFormat;
00320 EXTRACTOR_ExtractorList *extractors = NULL;
00321 bool load_libraries_failed = false;
00322
00323 void ExtractorHandler::fillMetadata(Ref<CdsItem> item)
00324 {
00325 if (load_libraries_failed)
00326 return;
00327 Ref<Array<StringBase> > aux;
00328 Ref<StringConverter> sc = StringConverter::i2i();
00329
00330 if (! extractors)
00331 {
00332 extractors = EXTRACTOR_loadDefaultLibraries();
00333 if (! extractors)
00334 load_libraries_failed = true;
00335 }
00336 EXTRACTOR_KeywordList *keywords = EXTRACTOR_getKeywords(extractors, item->getLocation().c_str());
00337
00338
00339
00340 for (int i = 0; i < M_MAX; i++)
00341 addMetaField((metadata_fields_t)i, keywords, item, sc);
00342
00343 for (int i = 0; i < R_MAX; i++)
00344 addResourceField((resource_attributes_t)i, keywords, item, sc);
00345
00346 Ref<ConfigManager> cm = ConfigManager::getInstance();
00347 aux = cm->getStringArrayOption(CFG_IMPORT_LIBOPTS_EXTRACTOR_AUXDATA_TAGS_LIST);
00348 if (aux != nil)
00349 {
00350 String value;
00351 String tmp;
00352 const char *temp = NULL;
00353
00354 for (int j = 0; j < aux->size(); j++)
00355 {
00356
00357 tmp = aux->get(j);
00358 if (string_ok(tmp))
00359 {
00360 temp = EXTRACTOR_extractLast(getTagFromString(tmp), keywords);
00361 if (temp != NULL)
00362 {
00363 value = temp;
00364 if (string_ok(value))
00365 {
00366 value = sc->convert(value);
00367 item->setAuxData(tmp, value);
00368
00369 }
00370 }
00371 }
00372 }
00373 }
00374
00375 if (ReAudioFormat == nil)
00376 {
00377 ReAudioFormat = Ref<RExp>(new RExp());
00378
00379 ReAudioFormat->compile(_("([0-9]+)\\s+kbps,\\s*([0-9]+)\\s+hz,\\s*"
00380 "(([0-9]+)h)?([0-9]+)m([0-9]+)\\s(\\S+)"), "i");
00381 }
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 EXTRACTOR_freeKeywords(keywords);
00408
00409
00410
00411 }
00412
00413 Ref<IOHandler> ExtractorHandler::serveContent(Ref<CdsItem> item, int resNum, off_t *data_size)
00414 {
00415 *data_size = -1;
00416 return nil;
00417 }
00418
00419 #endif // HAVE_EXTRACTOR