static void parseUnknown(u_char *data) { struct descr_component *dc = (struct descr_component *) data; char buf[256]; int len = GetDescriptorLength(data); strncpy(buf, (char *) &dc->data, len); buf[len] = '\0'; //printf("\t<!-- unknown id=\"%x\" len=\"%d\" value=\"%s\" -->\n", GetDescriptorTag(data), len, buf); }
/* Check that program has at least a title as is required by xmltv.dtd. {{{ */ static bool validateDescription(void *data, size_t len) { void *p; for (p = data; p < data + len; p += DESCR_GEN_LEN + GetDescriptorLength(p)) { struct descr_gen *desc = p; if (GetDescriptorTag(desc) == 0x4D) { struct descr_short_event *evtdesc = p; // make sure that title isn't empty if (evtdesc->event_name_length) return true; } } return false; } /*}}}*/
/* Parse 0x4E Extended Event Descriptor. {{{ */ void parseLongEventDescription(void *data) { assert(GetDescriptorTag(data) == 0x4E); struct descr_extended_event *levt = data; char dsc[256]; bool non_empty = (levt->descriptor_number || levt->last_descriptor_number || levt->length_of_items || levt->data[0]); if (non_empty && levt->descriptor_number == 0) printf("\t<desc lang=\"%s\">", xmllang(&levt->lang_code1)); void *p = &levt->data; void *data_end = data + DESCR_GEN_LEN + GetDescriptorLength(data); while (p < (void *)levt->data + levt->length_of_items) { struct item_extended_event *name = p; int name_len = name->item_description_length; assert(p + ITEM_EXTENDED_EVENT_LEN + name_len < data_end); assert(name_len < sizeof(dsc)); memcpy(dsc, (char *)&name->data, name_len); dsc[name_len] = '\0'; printf("%s: ", xmlify(dsc)); p += ITEM_EXTENDED_EVENT_LEN + name_len; struct item_extended_event *value = p; int value_len = value->item_description_length; assert(p + ITEM_EXTENDED_EVENT_LEN + value_len < data_end); assert(value_len < sizeof(dsc)); memcpy(dsc, (char *)&value->data, value_len); dsc[value_len] = '\0'; printf("%s; ", xmlify(dsc)); p += ITEM_EXTENDED_EVENT_LEN + value_len; } struct item_extended_event *text = p; int len = text->item_description_length; if (non_empty && len) { assert(len < sizeof(dsc)); memcpy(dsc, (char *)&text->data, len); dsc[len] = '\0'; printf("%s", xmlify(dsc)); } //printf("/%d/%d/%s", levt->descriptor_number, levt->last_descriptor_number, xmlify(dsc)); if (non_empty && levt->descriptor_number == levt->last_descriptor_number) printf("</desc>\n"); } /*}}}*/
/* * Parse 0x4E Extended Event Descriptor */ static void parseLongEventDescription(void *data) { assert(GetDescriptorTag(data) == 0x4E); struct descr_extended_event *levt = CastExtendedEventDescriptor(data); char dsc[256]; bool non_empty = (levt->descriptor_number || levt->last_descriptor_number || levt->length_of_items || levt->data[0]); if (non_empty && levt->descriptor_number == 0) printf("\t<desc lang=\"%s\">", lookup_language(&levt->lang_code1)); u_char *p = (u_char *) &levt->data; u_char *data_end = (u_char *) (CastExtendedEventDescriptor(data) + DESCR_GEN_LEN + GetDescriptorLength(data)); while (p < (u_char *) levt->data + levt->length_of_items) { struct item_extended_event *name = (struct item_extended_event *) p; int name_len = name->item_description_length; assert(p + ITEM_EXTENDED_EVENT_LEN + name_len < data_end); strncpy(dsc, (char *) &name->data, name_len); dsc[name_len] = '\0'; printf("%s: ", convert_text(dsc)); p += ITEM_EXTENDED_EVENT_LEN + name_len; struct item_extended_event *value = (struct item_extended_event *) p; int value_len = value->item_description_length; assert(p + ITEM_EXTENDED_EVENT_LEN + value_len < data_end); strncpy(dsc, (char *) &value->data, value_len); dsc[value_len] = '\0'; printf("%s; ", convert_text(dsc)); p += ITEM_EXTENDED_EVENT_LEN + value_len; } struct item_extended_event *text = (struct item_extended_event *) p; int len = text->item_description_length; if (non_empty && len) { strncpy(dsc, (char *) &text->data, len); dsc[len] = '\0'; printf("%s", convert_text(dsc)); } //printf("/%d/%d/%s", levt->descriptor_number, levt->last_descriptor_number, convert_text(dsc)); if (non_empty && levt->descriptor_number == levt->last_descriptor_number) printf("</desc>\n"); }
/* * Parse Descriptor * Tags should be output in this order: * * 'title', 'sub-title', 'desc', 'credits', 'date', 'category', 'language', * 'orig-language', 'length', 'icon', 'url', 'country', 'episode-num', * 'video', 'audio', 'previously-shown', 'premiere', 'last-chance', * 'new', 'subtitles', 'rating', 'star-rating' */ static void parseDescription(u_char *data, size_t len) { int round, pds = 0; bool notupscaled = true; bool audiosubtitle = false; for (round = 0; round < 8; round++) { int seen = 0; // no title/language/video/audio/subtitles seen in this round u_char *p; for (p = data; p < (u_char *) (data + len); p += DESCR_GEN_LEN + GetDescriptorLength(p)) { struct descr_gen *desc = (struct descr_gen *) p; switch (GetDescriptorTag(desc)) { case 0: break; case 0x48: //service_description parseServiceDescription(desc); break; case 0x4D: //short evt desc, [title] [sub-title] // there can be multiple language versions of these if (round == 0) { parseEventDescription(desc, TITLE); } else if (round == 1) parseEventDescription(desc, SUB_TITLE); break; case 0x4E: //long evt descriptor [desc] if (round == 2) parseLongEventDescription(desc); break; case 0x50: //component desc [language] [video] [audio] [subtitles] if (round == 4) parseComponentDescription(desc, LANGUAGE, &seen, ¬upscaled); else if (round == 5) parseComponentDescription(desc, VIDEO, &seen, ¬upscaled); else if (round == 6) parseComponentDescription(desc, AUDIO, &seen, &audiosubtitle); else if (round == 7) parseComponentDescription(desc, SUBTITLES, &seen, &audiosubtitle); break; case 0x53: // CA Identifier Descriptor break; case 0x54: // content desc [category] if (round == 3) parseContentDescription((u_char *) desc); break; case 0x55: // Parental Rating Descriptor [rating] if (round == 7) parseRatingDescription((u_char *) desc); break; case 0x5f: // Private Data Specifier pds = parsePrivateDataSpecifier(desc); break; case 0x64: // Data broadcast desc - Text Desc for Data components break; case 0x69: // Programm Identification Label break; case 0x81: // TODO ??? if (pds == 5) // ARD_ZDF_ORF break; case 0x82: // VPS (ARD, ZDF, ORF) if (pds == 5) // ARD_ZDF_ORF // TODO: <programme @vps-start="???"> break; case 0x4F: // Time Shifted Event case 0x52: // Stream Identifier Descriptor case 0x5E: // Multi Lingual Component Descriptor case 0x83: // Logical Channel Descriptor (some kind of news-ticker on ARD-MHP-Data?) case 0x84: // Preferred Name List Descriptor case 0x85: // Preferred Name Identifier Descriptor case 0x86: // Eacem Stream Identifier Descriptor default: if (round == 0) { parseUnknown((u_char *) desc); } } } } }