00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #if HAVE_CONFIG_H
00021 #include "config.h"
00022 #endif
00023
00024 #include "file/file.h"
00025 #include "util/bits.h"
00026 #include "util/logging.h"
00027 #include "util/macro.h"
00028 #include "util/strutl.h"
00029 #include "meta_parse.h"
00030 #include "register.h"
00031
00032 #include <stdlib.h>
00033 #include <string.h>
00034 #include <errno.h>
00035
00036 #ifdef HAVE_STRINGS_H
00037 #include <strings.h>
00038 #endif
00039
00040 #ifdef HAVE_LIBXML2
00041 #include <libxml/parser.h>
00042 #include <libxml/xmlmemory.h>
00043 #include <libxml/tree.h>
00044 #endif
00045
00046 #ifdef HAVE_LIBXML2
00047 static void _parseManifestNode(xmlNode * a_node, META_DL *disclib)
00048 {
00049 xmlNode *cur_node = NULL;
00050
00051 for (cur_node = a_node; cur_node; cur_node = cur_node->next) {
00052 if (cur_node->type == XML_ELEMENT_NODE) {
00053 if (xmlStrEqual(cur_node->parent->name, xmlCharStrdup("title"))) {
00054 if (xmlStrEqual(cur_node->name, xmlCharStrdup("name"))) {
00055 disclib->di_name = (char*)xmlStrdup(xmlNodeGetContent(cur_node));
00056 }
00057 if (xmlStrEqual(cur_node->name, xmlCharStrdup("alternative"))) {
00058 disclib->di_alternative = (char*)xmlStrdup(xmlNodeGetContent(cur_node));
00059 }
00060 if (xmlStrEqual(cur_node->name, xmlCharStrdup("numSets"))) {
00061 disclib->di_num_sets = atoi((char*)xmlNodeGetContent(cur_node));
00062 }
00063 if (xmlStrEqual(cur_node->name, xmlCharStrdup("setNumber"))) {
00064 disclib->di_set_number = atoi((char*)xmlNodeGetContent(cur_node));
00065 }
00066 }
00067 else if (xmlStrEqual(cur_node->parent->name, xmlCharStrdup("tableOfContents"))) {
00068 if (xmlStrEqual(cur_node->name, xmlCharStrdup("titleName")) && xmlGetProp(cur_node, xmlCharStrdup("titleNumber"))) {
00069 int i = disclib->toc_count;
00070 disclib->toc_count++;
00071 disclib->toc_entries = realloc(disclib->toc_entries, (disclib->toc_count*sizeof(META_TITLE)));
00072 disclib->toc_entries[i].title_number = atoi((const char*)xmlGetProp(cur_node, xmlCharStrdup("titleNumber")));
00073 disclib->toc_entries[i].title_name = (char*)xmlStrdup(xmlNodeGetContent(cur_node));
00074 }
00075 }
00076 else if (xmlStrEqual(cur_node->parent->name, xmlCharStrdup("description"))) {
00077 if (xmlStrEqual(cur_node->name, xmlCharStrdup("thumbnail")) && xmlGetProp(cur_node, xmlCharStrdup("href"))) {
00078 uint8_t i = disclib->thumb_count;
00079 disclib->thumb_count++;
00080 disclib->thumbnails = realloc(disclib->thumbnails, (disclib->thumb_count*sizeof(META_THUMBNAIL)));
00081 int len = xmlStrlen(xmlGetProp(cur_node, xmlCharStrdup("href")));
00082 disclib->thumbnails[i].path = (char*) malloc(len+1);
00083 strcpy(disclib->thumbnails[i].path, (char*) xmlGetProp(cur_node, xmlCharStrdup("href")));
00084 if (xmlGetProp(cur_node, xmlCharStrdup("size"))) {
00085 sscanf((const char*)xmlGetProp(cur_node, xmlCharStrdup("size")), "%ix%i", &disclib->thumbnails[i].xres, &disclib->thumbnails[i].yres);
00086 }
00087 else {
00088 disclib->thumbnails[i].xres = disclib->thumbnails[i].yres = -1;
00089 }
00090 }
00091 }
00092 }
00093 _parseManifestNode(cur_node->children, disclib);
00094 }
00095 }
00096
00097 static void _findMetaXMLfiles(META_ROOT *meta, const char *device_path)
00098 {
00099 BD_DIR_H *dir;
00100 BD_DIRENT ent;
00101 char *path = NULL;
00102 path = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "META" DIR_SEP "DL", device_path);
00103 dir = dir_open(path);
00104 if (dir == NULL) {
00105 BD_DEBUG(DBG_DIR, "Failed to open meta dir %s\n", path);
00106 X_FREE(path);
00107 return;
00108 }
00109 int res;
00110 for (res = dir_read(dir, &ent); !res; res = dir_read(dir, &ent)) {
00111 if (ent.d_name[0] == '.')
00112 continue;
00113 else if (ent.d_name != NULL && strncasecmp(ent.d_name, "bdmt_", 5) == 0) {
00114 uint8_t i = meta->dl_count;
00115 meta->dl_count++;
00116 meta->dl_entries = realloc(meta->dl_entries, (meta->dl_count*sizeof(META_DL)));
00117 meta->dl_entries[i].filename = str_printf("%s", ent.d_name);
00118 strncpy(meta->dl_entries[i].language_code, ent.d_name+5,3);
00119 meta->dl_entries[i].language_code[3] = '\0';
00120 str_tolower(meta->dl_entries[i].language_code);
00121 }
00122 }
00123 dir_close(dir);
00124 X_FREE(path);
00125 }
00126 #endif
00127
00128 META_ROOT *meta_parse(const char *device_path)
00129 {
00130 #ifdef HAVE_LIBXML2
00131 META_ROOT *root = calloc(1, sizeof(META_ROOT));
00132 root->dl_count = 0;
00133
00134 xmlDocPtr doc;
00135 _findMetaXMLfiles(root, device_path);
00136
00137 uint8_t i;
00138 for (i = 0; i < root->dl_count; i++) {
00139 char *base = NULL;
00140 base = str_printf("%s" DIR_SEP "BDMV" DIR_SEP "META" DIR_SEP "DL" , device_path);
00141 char *path = NULL;
00142 path = str_printf("%s" DIR_SEP "%s", base, root->dl_entries[i].filename);
00143
00144 BD_FILE_H *handle = file_open(path, "rb");
00145 if (handle == NULL) {
00146 BD_DEBUG(DBG_DIR, "Failed to open meta file (%s)\n", path);
00147 continue;
00148 }
00149
00150 file_seek(handle, 0, SEEK_END);
00151 int64_t length = file_tell(handle);
00152
00153 if (length > 0) {
00154 file_seek(handle, 0, SEEK_SET);
00155 uint8_t *data = malloc(length);
00156 int64_t size_read = file_read(handle, data, length);
00157 doc = xmlReadMemory((char*)data, size_read, base, NULL, 0);
00158 if (doc == NULL) {
00159 BD_DEBUG(DBG_DIR, "Failed to parse %s\n", path);
00160 continue;
00161 }
00162 xmlNode *root_element = NULL;
00163 root_element = xmlDocGetRootElement(doc);
00164 root->dl_entries[i].di_name = root->dl_entries[i].di_alternative = NULL;
00165 root->dl_entries[i].di_num_sets = root->dl_entries[i].di_set_number = -1;
00166 root->dl_entries[i].toc_count = root->dl_entries[i].thumb_count = 0;
00167 root->dl_entries[i].toc_entries = NULL;
00168 root->dl_entries[i].thumbnails = NULL;
00169 _parseManifestNode(root_element, &root->dl_entries[i]);
00170 xmlFreeDoc(doc);
00171 X_FREE(data);
00172 }
00173 file_close(handle);
00174 }
00175 xmlCleanupParser();
00176 return root;
00177 #else
00178 BD_DEBUG(DBG_DIR, "configured without libxml2 - can't parse meta info\n");
00179 return NULL;
00180 #endif
00181 }
00182
00183 META_DL *meta_get(META_ROOT *meta_root, const char *language_code)
00184 {
00185 unsigned i;
00186
00187 if (meta_root == NULL || meta_root->dl_count == 0) {
00188 BD_DEBUG(DBG_DIR, "meta_get not possible, no info available!\n");
00189 return NULL;
00190 }
00191
00192 if (language_code) {
00193 for (i = 0; i < meta_root->dl_count; i++) {
00194 if (strcmp(language_code, meta_root->dl_entries[i].language_code) == 0) {
00195 return &meta_root->dl_entries[i];
00196 }
00197 }
00198 BD_DEBUG(DBG_DIR, "requested disclib language '%s' not found\n", language_code);
00199 }
00200
00201 for (i = 0; i < meta_root->dl_count; i++) {
00202 if (strcmp(DEFAULT_LANGUAGE, meta_root->dl_entries[i].language_code) == 0) {
00203 BD_DEBUG(DBG_DIR, "using default disclib language '"DEFAULT_LANGUAGE"'\n");
00204 return &meta_root->dl_entries[i];
00205 }
00206 }
00207
00208 BD_DEBUG(DBG_DIR, "requested disclib language '%s' or default '"DEFAULT_LANGUAGE"' not found, using '%s' instead\n", language_code, meta_root->dl_entries[0].language_code);
00209 return &meta_root->dl_entries[0];
00210 }
00211
00212 void meta_free(META_ROOT **p)
00213 {
00214 if (p && *p)
00215 {
00216 uint8_t i;
00217 for (i = 0; i < (*p)->dl_count; i++) {
00218 uint32_t t;
00219 for (t=0; i < (*p)->dl_entries[i].toc_count; t++) {
00220 X_FREE((*p)->dl_entries[i].toc_entries[t].title_name);
00221 X_FREE((*p)->dl_entries[i].toc_entries);
00222 }
00223 for (t = 0; i < (*p)->dl_entries[i].thumb_count; t++) {
00224 X_FREE((*p)->dl_entries[i].thumbnails[t].path);
00225 X_FREE((*p)->dl_entries[i].thumbnails);
00226 }
00227 X_FREE((*p)->dl_entries[i].filename);
00228 X_FREE((*p)->dl_entries[i].di_name);
00229 X_FREE((*p)->dl_entries[i].di_alternative);
00230 }
00231 X_FREE(*p);
00232 }
00233 }