diff --git a/src/sectionsd/SIevents.cpp b/src/sectionsd/SIevents.cpp index 05153219f..bc18c0ada 100644 --- a/src/sectionsd/SIevents.cpp +++ b/src/sectionsd/SIevents.cpp @@ -73,7 +73,7 @@ SIevent::SIevent(const struct eit_event *e) } SIevent::SIevent(const t_original_network_id _original_network_id, const t_transport_stream_id _transport_stream_id, const t_service_id _service_id, - const unsigned short _event_id) + const unsigned short _event_id) { original_network_id = _original_network_id; transport_stream_id = _transport_stream_id; @@ -81,11 +81,11 @@ SIevent::SIevent(const t_original_network_id _original_network_id, const t_trans eventID = _event_id; table_id = 0xFF; /* not set */ version = 0xFF; -/* contentClassification = ""; - userClassification = ""; - itemDescription = ""; - item = ""; - extendedText = "";*/ + /* contentClassification = ""; + userClassification = ""; + itemDescription = ""; + item = ""; + extendedText = "";*/ } // Std-Copy @@ -134,10 +134,10 @@ char SIevent::getFSK() const { if (it->countryCode == "DEU") { - if ((it->rating >= 0x01) && (it->rating <= 0x0F)) - return (it->rating + 3); // 0x01 to 0x0F minimum age = rating + 3 years - else - return (it->rating == 0 ? 0 : 18); // return FSK 18 for : 0x10 to 0xFF defined by the broadcaster + if ((it->rating >= 0x01) && (it->rating <= 0x0F)) + return (it->rating + 3); // 0x01 to 0x0F minimum age = rating + 3 years + else + return (it->rating == 0 ? 0 : 18); // return FSK 18 for : 0x10 to 0xFF defined by the broadcaster } } if (!ratings.empty()) @@ -161,9 +161,9 @@ int SIevent::saveXML0(FILE *file) const int SIevent::saveXML2(FILE *file) const { for (std::map::const_iterator - i = langName.begin() ; - i != langName.end() ; - i++) { + i = langName.begin() ; + i != langName.end() ; + i++) { if (i->second.length()) { fprintf(file, "\t\t\tfirst.c_str()); saveStringToXMLfile(file, i->second.c_str()); @@ -171,9 +171,9 @@ int SIevent::saveXML2(FILE *file) const } } for (std::map::const_iterator - i = langText.begin() ; - i != langText.end() ; - i++) { + i = langText.begin() ; + i != langText.end() ; + i++) { if (i->second.length()) { fprintf(file, "\t\t\tfirst.c_str()); saveStringToXMLfile(file, i->second.c_str()); @@ -191,9 +191,9 @@ int SIevent::saveXML2(FILE *file) const fprintf(file, "\"/>\n"); } for (std::map::const_iterator - i = langExtendedText.begin() ; - i != langExtendedText.end() ; - i++) { + i = langExtendedText.begin() ; + i != langExtendedText.end() ; + i++) { if (i->second.length()) { fprintf(file, "\t\t\tfirst.c_str()); saveStringToXMLfile(file, i->second.c_str()); @@ -212,7 +212,7 @@ int SIevent::saveXML2(FILE *file) const std::string SIevent::getName() const { - if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()){ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { std::map::const_iterator it = langName.begin() ; if (it != langName.end()) return it->second; else return(""); @@ -228,7 +228,7 @@ void SIevent::setName(const std::string &lang, const std::string &name) std::string tmp = name; std::replace(tmp.begin(), tmp.end(), '\n', ' '); //printf("setName: lang %s text %s\n", lang.c_str(), name.c_str()); - if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()){ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { langName[languangeOFF] = tmp; //name; } else { langName[lang] = tmp; //name; @@ -237,7 +237,7 @@ void SIevent::setName(const std::string &lang, const std::string &name) std::string SIevent::getText() const { - if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()){ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { std::map::const_iterator it = langText.begin() ; if (it != langText.end()) return it->second; else return(""); @@ -251,7 +251,7 @@ std::string SIevent::getText() const void SIevent::setText(const std::string &lang, const std::string &text) { //printf("setText: lang %s text %s\n", lang.c_str(), text.c_str()); - if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()){ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { langText[languangeOFF] = text; } else { langText[lang] = text; @@ -260,7 +260,7 @@ void SIevent::setText(const std::string &lang, const std::string &text) std::string SIevent::getExtendedText() const { - if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()){ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { std::map::const_iterator it = langExtendedText.begin() ; if (it != langExtendedText.end()) return it->second; else return(""); @@ -273,7 +273,7 @@ std::string SIevent::getExtendedText() const void SIevent::appendExtendedText(const std::string &lang, const std::string &text) { - if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()){ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { langExtendedText[languangeOFF] += text; } else { langExtendedText[lang] += text; @@ -283,7 +283,7 @@ void SIevent::appendExtendedText(const std::string &lang, const std::string &tex void SIevent::setExtendedText(const std::string &lang, const std::string &text) { //printf("setExtendedText: lang %s text %s\n", lang.c_str(), text.c_str()); - if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()){ + if (CSectionsdClient::LANGUAGE_MODE_OFF == SIlanguage::getMode()) { langExtendedText[languangeOFF] = text; } else { langExtendedText[lang] = text; @@ -301,16 +301,16 @@ void SIevent::dump(void) const if(item.length()) printf("Item: %s\n", item.c_str()); if(itemDescription.length()) - printf("Item-Description: %s\n", itemDescription.c_str()); + printf("Item-Description: %s\n", itemDescription.c_str()); for (std::map::const_iterator it = langName.begin() ; - it != langName.end() ; ++it) - printf("Name (%s): %s\n", it->first.c_str(), it->second.c_str()); + it != langName.end() ; ++it) + printf("Name (%s): %s\n", it->first.c_str(), it->second.c_str()); for (std::map::const_iterator it = langText.begin() ; - it != langText.end() ; ++it) + it != langText.end() ; ++it) printf("Text (%s): %s\n", it->first.c_str(), it->second.c_str()); for (std::map::const_iterator it = langExtendedText.begin() ; - it != langExtendedText.end() ; ++it) + it != langExtendedText.end() ; ++it) printf("Extended-Text (%s): %s\n", it->first.c_str(), it->second.c_str()); if(contentClassification.length()) { @@ -325,12 +325,12 @@ void SIevent::dump(void) const printf(" 0x%02hhx", userClassification[i]); printf("\n"); } -/* - if(startzeit) - printf("Startzeit: %s", ctime(&startzeit)); - if(dauer) - printf("Dauer: %02u:%02u:%02u (%umin, %us)\n", dauer/3600, (dauer%3600)/60, dauer%60, dauer/60, dauer); -*/ + /* + if(startzeit) + printf("Startzeit: %s", ctime(&startzeit)); + if(dauer) + printf("Dauer: %02u:%02u:%02u (%umin, %us)\n", dauer/3600, (dauer%3600)/60, dauer%60, dauer/60, dauer); + */ for_each(times.begin(), times.end(), printSItime()); for_each(components.begin(), components.end(), printSIcomponent()); for_each(ratings.begin(), ratings.end(), printSIparentalRating()); @@ -340,20 +340,20 @@ void SIevent::dump(void) const void SIevent::dumpSmall(void) const { for (std::map::const_iterator it = langName.begin() ; - it != langName.end() ; ++it) - printf("Name (%s): %s\n", it->first.c_str(), it->second.c_str()); + it != langName.end() ; ++it) + printf("Name (%s): %s\n", it->first.c_str(), it->second.c_str()); for (std::map::const_iterator it = langText.begin() ; - it != langText.end() ; ++it) + it != langText.end() ; ++it) printf("Text (%s): %s\n", it->first.c_str(), it->second.c_str()); for (std::map::const_iterator it = langExtendedText.begin() ; - it != langExtendedText.end() ; ++it) + it != langExtendedText.end() ; ++it) printf("Extended-Text (%s): %s\n", it->first.c_str(), it->second.c_str()); -/* - if(startzeit) - printf("Startzeit: %s", ctime(&startzeit)); - if(dauer) - printf("Dauer: %02u:%02u:%02u (%umin, %us)\n", dauer/3600, (dauer%3600)/60, dauer%60, dauer/60, dauer); -*/ + /* + if(startzeit) + printf("Startzeit: %s", ctime(&startzeit)); + if(dauer) + printf("Dauer: %02u:%02u:%02u (%umin, %us)\n", dauer/3600, (dauer%3600)/60, dauer%60, dauer/60, dauer); + */ for_each(times.begin(), times.end(), printSItime()); for_each(ratings.begin(), ratings.end(), printSIparentalRating()); for_each(linkage_descs.begin(), linkage_descs.end(), printSIlinkage()); diff --git a/src/sectionsd/SIlanguage.cpp b/src/sectionsd/SIlanguage.cpp index 383539091..2d79877b7 100644 --- a/src/sectionsd/SIlanguage.cpp +++ b/src/sectionsd/SIlanguage.cpp @@ -72,7 +72,7 @@ void SIlanguage::filter(const std::map& s, int max, st if (mode != CSectionsdClient::ALL) { for (std::vector::const_iterator it = languages.begin() ; - it != languages.end() ; ++it) { + it != languages.end() ; ++it) { std::map::const_iterator text; if ((text = s.find(*it)) != s.end()) { if (count != max) { @@ -92,7 +92,7 @@ void SIlanguage::filter(const std::map& s, int max, st // return all available languages if (s.begin() != s.end()) { for (std::map::const_iterator it = s.begin() ; - it != s.end() ; ++it) { + it != s.end() ; ++it) { if (it != s.begin()) { retval.append(" \n"); } @@ -142,7 +142,7 @@ bool SIlanguage::loadLanguages() pthread_mutex_unlock(&languages_lock); return true; - error: +error: tmpLang.push_back("OFF"); languages = tmpLang; mode = tmpMode; @@ -176,7 +176,7 @@ bool SIlanguage::saveLanguages() } for (std::vector::iterator it = languages.begin() ; - it != languages.end() ; ++it) { + it != languages.end() ; ++it) { file << *it; file << "\n"; if (file.fail()) goto error; @@ -188,7 +188,7 @@ bool SIlanguage::saveLanguages() pthread_mutex_unlock(&languages_lock); return true; - error: +error: pthread_mutex_unlock(&languages_lock); return false; } diff --git a/src/sectionsd/SIsections.cpp b/src/sectionsd/SIsections.cpp index e36bc1938..b329cb485 100644 --- a/src/sectionsd/SIsections.cpp +++ b/src/sectionsd/SIsections.cpp @@ -129,28 +129,31 @@ inline unsigned min(unsigned a, unsigned b) static int get_table(unsigned char hi, unsigned char mid, unsigned char lo) { - char lang[4]; - lang[0] = hi; lang[1] = mid; lang[2] = lo; lang[3] = 0; - if(!strcmp(lang, "pol")) - return 2; - else if(!strcmp(lang, "tur")) - return 9; - else if(!strcmp(lang, "gre")) - return 7; - else if(!strcmp(lang, "rus")) - return 5; - else if(!strcmp(lang, "bul")) - return 5; - else if(!strcmp(lang, "ara")) - return 6; - return 0; + char lang[4]; + lang[0] = hi; + lang[1] = mid; + lang[2] = lo; + lang[3] = 0; + if(!strcmp(lang, "pol")) + return 2; + else if(!strcmp(lang, "tur")) + return 9; + else if(!strcmp(lang, "gre")) + return 7; + else if(!strcmp(lang, "rus")) + return 5; + else if(!strcmp(lang, "bul")) + return 5; + else if(!strcmp(lang, "ara")) + return 6; + return 0; } bool check_blacklisted(const t_original_network_id onid, const t_transport_stream_id tsid) { if ( (onid == 0x0001) && - ((tsid == 0x03F0) || (tsid == 0x0408) || (tsid == 0x040E) || (tsid == 0x0412) || (tsid == 0x0416) || (tsid == 0x041E) || - (tsid == 0x0420) || (tsid == 0x0422) || (tsid == 0x0424) || (tsid == 0x0444) )) + ((tsid == 0x03F0) || (tsid == 0x0408) || (tsid == 0x040E) || (tsid == 0x0412) || (tsid == 0x0416) || (tsid == 0x041E) || + (tsid == 0x0420) || (tsid == 0x0422) || (tsid == 0x0424) || (tsid == 0x0444) )) return true; else return false; @@ -186,9 +189,9 @@ void SIsectionEIT::parsePDCDescriptor(const char *buf, SIevent &e, unsigned maxl t.tm_min = s->pil2 & 0x3F; t.tm_sec = 0; if (month == 11 && t.tm_mon == 0) // current month is dec, but event is in jan - t.tm_year++; + t.tm_year++; else if (month == 0 && t.tm_mon == 11) // current month is jan, but event is in dec - t.tm_year--; + t.tm_year--; e.vps = mktime(&t); // fprintf(stderr, "SIsectionEIT::parsePDCDescriptor: vps: %ld %s", e.vps, ctime(&e.vps)); } @@ -293,108 +296,108 @@ void SIsectionEIT::parseExtendedEventDescriptor(const char *buf, SIevent &e, uns #ifdef ENABLE_FREESATEPG std::string SIsectionEIT::freesatHuffmanDecode(std::string input) { - const char *src = input.c_str(); - uint size = input.length(); + const char *src = input.c_str(); + uint size = input.length(); - if (src[1] == 1 || src[1] == 2) - { - std::string uncompressed(size * 3, ' '); - uint p = 0; - struct hufftab *table; - unsigned table_length; - if (src[1] == 1) - { - table = fsat_huffman1; - table_length = sizeof(fsat_huffman1) / sizeof(fsat_huffman1[0]); - } - else - { - table = fsat_huffman2; - table_length = sizeof(fsat_huffman2) / sizeof(fsat_huffman2[0]); - } - unsigned value = 0, byte = 2, bit = 0; - while (byte < 6 && byte < size) - { - value |= src[byte] << ((5-byte) * 8); - byte++; - } - char lastch = START; + if (src[1] == 1 || src[1] == 2) + { + std::string uncompressed(size * 3, ' '); + uint p = 0; + struct hufftab *table; + unsigned table_length; + if (src[1] == 1) + { + table = fsat_huffman1; + table_length = sizeof(fsat_huffman1) / sizeof(fsat_huffman1[0]); + } + else + { + table = fsat_huffman2; + table_length = sizeof(fsat_huffman2) / sizeof(fsat_huffman2[0]); + } + unsigned value = 0, byte = 2, bit = 0; + while (byte < 6 && byte < size) + { + value |= src[byte] << ((5-byte) * 8); + byte++; + } + char lastch = START; + + do + { + bool found = false; + unsigned bitShift = 0; + if (lastch == ESCAPE) + { + found = true; + // Encoded in the next 8 bits. + // Terminated by the first ASCII character. + char nextCh = (value >> 24) & 0xff; + bitShift = 8; + if ((nextCh & 0x80) == 0) + lastch = nextCh; + if (p >= uncompressed.length()) + uncompressed.resize(p+10); + uncompressed[p++] = nextCh; + } + else + { + for (unsigned j = 0; j < table_length; j++) + { + if (table[j].last == lastch) + { + unsigned mask = 0, maskbit = 0x80000000; + for (short kk = 0; kk < table[j].bits; kk++) + { + mask |= maskbit; + maskbit >>= 1; + } + if ((value & mask) == table[j].value) + { + char nextCh = table[j].next; + bitShift = table[j].bits; + if (nextCh != STOP && nextCh != ESCAPE) + { + if (p >= uncompressed.length()) + uncompressed.resize(p+10); + uncompressed[p++] = nextCh; + } + found = true; + lastch = nextCh; + break; + } + } + } + } + if (found) + { + // Shift up by the number of bits. + for (unsigned b = 0; b < bitShift; b++) + { + value = (value << 1) & 0xfffffffe; + if (byte < size) + value |= (src[byte] >> (7-bit)) & 1; + if (bit == 7) + { + bit = 0; + byte++; + } + else bit++; + } + } + else + { + // Entry missing in table. + uncompressed.resize(p); + uncompressed.append("..."); + return uncompressed; + } + } while (lastch != STOP && value != 0); - do - { - bool found = false; - unsigned bitShift = 0; - if (lastch == ESCAPE) - { - found = true; - // Encoded in the next 8 bits. - // Terminated by the first ASCII character. - char nextCh = (value >> 24) & 0xff; - bitShift = 8; - if ((nextCh & 0x80) == 0) - lastch = nextCh; - if (p >= uncompressed.length()) - uncompressed.resize(p+10); - uncompressed[p++] = nextCh; - } - else - { - for (unsigned j = 0; j < table_length; j++) - { - if (table[j].last == lastch) - { - unsigned mask = 0, maskbit = 0x80000000; - for (short kk = 0; kk < table[j].bits; kk++) - { - mask |= maskbit; - maskbit >>= 1; - } - if ((value & mask) == table[j].value) - { - char nextCh = table[j].next; - bitShift = table[j].bits; - if (nextCh != STOP && nextCh != ESCAPE) - { - if (p >= uncompressed.length()) - uncompressed.resize(p+10); - uncompressed[p++] = nextCh; - } - found = true; - lastch = nextCh; - break; - } - } - } - } - if (found) - { - // Shift up by the number of bits. - for (unsigned b = 0; b < bitShift; b++) - { - value = (value << 1) & 0xfffffffe; - if (byte < size) - value |= (src[byte] >> (7-bit)) & 1; - if (bit == 7) - { - bit = 0; - byte++; - } - else bit++; - } - } - else - { - // Entry missing in table. - uncompressed.resize(p); - uncompressed.append("..."); - return uncompressed; - } - } while (lastch != STOP && value != 0); - uncompressed.resize(p); - return uncompressed; - } - else return input; + return uncompressed; + } + else return input; } #endif @@ -420,7 +423,7 @@ void SIsectionEIT::parseShortEventDescriptor(const char *buf, SIevent &e, unsign #endif } else #endif // 0 -{ + { #ifdef ENABLE_FREESATEPG // e.setName(language, buf[0] == 0x1f ? freesatHuffmanDecode(std::string(buf, evt->event_name_length)) : std::string(buf, evt->event_name_length)); @@ -444,7 +447,7 @@ void SIsectionEIT::parseShortEventDescriptor(const char *buf, SIevent &e, unsign #endif } else #endif // 0 -{ + { #ifdef ENABLE_FREESATEPG // e.setText(language, buf[1] == 0x1f ? freesatHuffmanDecode(std::string(++buf, textlength)) : std::string(++buf, textlength)); std::string tmp_str = buf[1] == 0x1f ? freesatHuffmanDecode(std::string(++buf, textlength)) : std::string(++buf, textlength); @@ -539,106 +542,106 @@ void SIsectionEIT::parse(void) #ifdef ENABLE_PPT void SIsectionPPT::parseLinkageDescriptor(const char *buf, SIevent &e, unsigned maxlen) { - if(maxlen>=sizeof(struct descr_linkage_header)) - { - SIlinkage l((const struct descr_linkage_header *)buf); - e.linkage_descs.insert(e.linkage_descs.end(), l); + if(maxlen>=sizeof(struct descr_linkage_header)) + { + SIlinkage l((const struct descr_linkage_header *)buf); + e.linkage_descs.insert(e.linkage_descs.end(), l); // printf("LinkName: %s\n", l.name.c_str()); - } + } } void SIsectionPPT::parseComponentDescriptor(const char *buf, SIevent &e, unsigned maxlen) { - if(maxlen>=sizeof(struct descr_component_header)) - e.components.insert(SIcomponent((const struct descr_component_header *)buf)); + if(maxlen>=sizeof(struct descr_component_header)) + e.components.insert(SIcomponent((const struct descr_component_header *)buf)); } void SIsectionPPT::parseContentDescriptor(const char *buf, SIevent &e, unsigned maxlen) { - struct descr_generic_header *cont=(struct descr_generic_header *)buf; - if(cont->descriptor_length+sizeof(struct descr_generic_header)>maxlen) - return; // defekt - const char *classification=buf+sizeof(struct descr_generic_header); - while(classification<=buf+sizeof(struct descr_generic_header)+cont->descriptor_length-2) { - e.contentClassification+=std::string(classification, 1); + struct descr_generic_header *cont=(struct descr_generic_header *)buf; + if(cont->descriptor_length+sizeof(struct descr_generic_header)>maxlen) + return; // defekt + const char *classification=buf+sizeof(struct descr_generic_header); + while(classification<=buf+sizeof(struct descr_generic_header)+cont->descriptor_length-2) { + e.contentClassification+=std::string(classification, 1); // printf("Content: 0x%02hhx\n", *classification); - e.userClassification+=std::string(classification+1, 1); + e.userClassification+=std::string(classification+1, 1); // printf("User: 0x%02hhx\n", *(classification+1)); - classification+=2; - } + classification+=2; + } } void SIsectionPPT::parseParentalRatingDescriptor(const char *buf, SIevent &e, unsigned maxlen) { - struct descr_generic_header *cont=(struct descr_generic_header *)buf; - if(cont->descriptor_length+sizeof(struct descr_generic_header)>maxlen) - return; // defekt - const char *s=buf+sizeof(struct descr_generic_header); - while(sdescriptor_length-4) { - e.ratings.insert(SIparentalRating(std::string(s, 3), *(s+3))); - s+=4; - } + struct descr_generic_header *cont=(struct descr_generic_header *)buf; + if(cont->descriptor_length+sizeof(struct descr_generic_header)>maxlen) + return; // defekt + const char *s=buf+sizeof(struct descr_generic_header); + while(sdescriptor_length-4) { + e.ratings.insert(SIparentalRating(std::string(s, 3), *(s+3))); + s+=4; + } } void SIsectionPPT::parseExtendedEventDescriptor(const char *buf, SIevent &e, unsigned maxlen) { - struct descr_extended_event_header *evt=(struct descr_extended_event_header *)buf; - if((evt->descriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthdescriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthiso_639_2_language_code_hi + evt->iso_639_2_language_code_mid + evt->iso_639_2_language_code_lo; + std::string language; + language += evt->iso_639_2_language_code_hi + evt->iso_639_2_language_code_mid + evt->iso_639_2_language_code_lo; - unsigned char *items=(unsigned char *)(buf+sizeof(struct descr_extended_event_header)); - while(items<(unsigned char *)(buf+sizeof(struct descr_extended_event_header)+evt->length_of_items)) { - if(*items) { - if(*(items+1) < 0x06) // other code table - e.itemDescription=std::string((const char *)(items+2), min(maxlen-((const char *)items+2-buf), (*items)-1)); - else - e.itemDescription=std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items)); + unsigned char *items=(unsigned char *)(buf+sizeof(struct descr_extended_event_header)); + while(items<(unsigned char *)(buf+sizeof(struct descr_extended_event_header)+evt->length_of_items)) { + if(*items) { + if(*(items+1) < 0x06) // other code table + e.itemDescription=std::string((const char *)(items+2), min(maxlen-((const char *)items+2-buf), (*items)-1)); + else + e.itemDescription=std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items)); // printf("Item Description: %s\n", e.itemDescription.c_str()); - } - items+=1+*items; - if(*items) { - e.item=std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items)); + } + items+=1+*items; + if(*items) { + e.item=std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items)); // printf("Item: %s\n", e.item.c_str()); - } - items+=1+*items; - } - if(*items) { - if(*(items+1) < 0x06) // other code table - e.appendExtendedText(language, std::string((const char *)(items+2),min(maxlen-((const char *)items+2-buf), (*items)-1))); - else - e.appendExtendedText(language, std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items))); + } + items+=1+*items; + } + if(*items) { + if(*(items+1) < 0x06) // other code table + e.appendExtendedText(language, std::string((const char *)(items+2),min(maxlen-((const char *)items+2-buf), (*items)-1))); + else + e.appendExtendedText(language, std::string((const char *)(items+1), min(maxlen-((const char *)items+1-buf), *items))); // printf("Extended Text: %s\n", e.extendedText.c_str()); - } + } } void SIsectionPPT::parseShortEventDescriptor(const char *buf, SIevent &e, unsigned maxlen) { - struct descr_short_event_header *evt=(struct descr_short_event_header *)buf; - if((evt->descriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthdescriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthlanguage_code_hi + evt->language_code_mid + evt->language_code_lo; + std::string language; + language += evt->language_code_hi + evt->language_code_mid + evt->language_code_lo; - buf+=sizeof(struct descr_short_event_header); - if(evt->event_name_length) { - if(*buf < 0x06) // other code table - e.setName(language, std::string(buf+1, evt->event_name_length-1)); - else - e.setName(language, std::string(buf, evt->event_name_length)); - } + buf+=sizeof(struct descr_short_event_header); + if(evt->event_name_length) { + if(*buf < 0x06) // other code table + e.setName(language, std::string(buf+1, evt->event_name_length-1)); + else + e.setName(language, std::string(buf, evt->event_name_length)); + } - buf+=evt->event_name_length; - unsigned char textlength=*((unsigned char *)buf); - if(textlength > 2) { - if(*(buf+1) < 0x06) // other code table - e.setText(language, std::string((++buf)+1, textlength-1)); - else - e.setText(language, std::string(++buf, textlength)); - } + buf+=evt->event_name_length; + unsigned char textlength=*((unsigned char *)buf); + if(textlength > 2) { + if(*(buf+1) < 0x06) // other code table + e.setText(language, std::string((++buf)+1, textlength-1)); + else + e.setText(language, std::string(++buf, textlength)); + } // printf("Name: %s\n", e.name.c_str()); // printf("Text: %s\n", e.text.c_str()); @@ -647,42 +650,42 @@ void SIsectionPPT::parseShortEventDescriptor(const char *buf, SIevent &e, unsign void SIsectionPPT::parsePrivateContentOrderDescriptor(const char *buf, SIevent &e, unsigned maxlen) { - struct descr_short_event_header *evt=(struct descr_short_event_header *)buf; - if((evt->descriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthdescriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthdescriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthdescriptor_length+sizeof(descr_generic_header)>maxlen) || (evt->descriptor_lengthdescriptor_length) { - e.ratings.insert(SIparentalRating(std::string("", 0), *(buf))); - } + if (sizeof(struct descr_generic_header)+1 < evt->descriptor_length) { + e.ratings.insert(SIparentalRating(std::string("", 0), *(buf))); + } #if 0 - unsigned char rating; - unsigned char Controll_time_t1[3]; // BCD coded - unsigned char Controll_time_t2[3]; // BCD coded - unsigned char Parental_information_length; - unsigned char Parental_information[Parental_information_length]; + unsigned char rating; + unsigned char Controll_time_t1[3]; // BCD coded + unsigned char Controll_time_t2[3]; // BCD coded + unsigned char Parental_information_length; + unsigned char Parental_information[Parental_information_length]; #endif } @@ -707,7 +710,7 @@ void SIsectionPPT::parsePrivateContentTransmissionDescriptor(const char *buf, SI tm_buf[0] = *(p); tm_buf[1] = *(p+1); starttime_loop_length = (*(p+2))/3; - for (i=0;idescriptor_section_length_hi << 8) | ((SI_section_PPT_header*)buffer)->descriptor_section_length_lo; e.eventID = (unsigned short)(content_id()); // ?? @@ -804,42 +808,42 @@ void SIsectionPPT::parse(void) /********************/ void SIsectionSDT::parseNVODreferenceDescriptor(const char *buf, SIservice &s) { - struct descr_generic_header *hdr=(struct descr_generic_header *)buf; - unsigned short *spointer=(unsigned short *)(buf+sizeof(struct descr_generic_header)); - while((const char *)spointer<=buf+sizeof(struct descr_generic_header)+hdr->descriptor_length-2) { - unsigned short transportStreamID=*spointer++; - unsigned short originalNetworkID=*spointer++; - unsigned short sID=*spointer++; - s.nvods.insert(SInvodReference(transportStreamID, originalNetworkID, sID)); - } + struct descr_generic_header *hdr=(struct descr_generic_header *)buf; + unsigned short *spointer=(unsigned short *)(buf+sizeof(struct descr_generic_header)); + while((const char *)spointer<=buf+sizeof(struct descr_generic_header)+hdr->descriptor_length-2) { + unsigned short transportStreamID=*spointer++; + unsigned short originalNetworkID=*spointer++; + unsigned short sID=*spointer++; + s.nvods.insert(SInvodReference(transportStreamID, originalNetworkID, sID)); + } } void SIsectionSDT::parseServiceDescriptor(const char *buf, SIservice &s) { - bool is_blacklisted; + bool is_blacklisted; - struct descr_service_header *sv=(struct descr_service_header *)buf; - buf+=sizeof(struct descr_service_header); - s.serviceTyp=sv->service_typ; - is_blacklisted = check_blacklisted(s.original_network_id, s.transport_stream_id); - if(sv->service_provider_name_length) { - //if(*buf < 0x06) // other code table + struct descr_service_header *sv=(struct descr_service_header *)buf; + buf+=sizeof(struct descr_service_header); + s.serviceTyp=sv->service_typ; + is_blacklisted = check_blacklisted(s.original_network_id, s.transport_stream_id); + if(sv->service_provider_name_length) { + //if(*buf < 0x06) // other code table // s.providerName=std::string(buf+1, sv->service_provider_name_length-1); // else // s.providerName=std::string(buf, sv->service_provider_name_length); - if ((*buf > 0x05) && (is_blacklisted)) - s.providerName = CDVBString(("\x05" + std::string((const char *)(buf))).c_str(), sv->service_provider_name_length+1).getContent(); - else - s.providerName = CDVBString((const char *)(buf), sv->service_provider_name_length).getContent(); - } - buf+=sv->service_provider_name_length; - unsigned char servicenamelength=*((unsigned char *)buf); - if(servicenamelength) { - if ((*buf+1 > 0x05) && (is_blacklisted)) - s.serviceName = CDVBString(("\x05" + std::string((const char *)(++buf))).c_str(), servicenamelength+1).getContent(); - else - s.serviceName = CDVBString((const char *)(++buf), servicenamelength).getContent(); - } + if ((*buf > 0x05) && (is_blacklisted)) + s.providerName = CDVBString(("\x05" + std::string((const char *)(buf))).c_str(), sv->service_provider_name_length+1).getContent(); + else + s.providerName = CDVBString((const char *)(buf), sv->service_provider_name_length).getContent(); + } + buf+=sv->service_provider_name_length; + unsigned char servicenamelength=*((unsigned char *)buf); + if(servicenamelength) { + if ((*buf+1 > 0x05) && (is_blacklisted)) + s.serviceName = CDVBString(("\x05" + std::string((const char *)(++buf))).c_str(), servicenamelength+1).getContent(); + else + s.serviceName = CDVBString((const char *)(++buf), servicenamelength).getContent(); + } // printf("Provider-Name: %s\n", s.providerName.c_str()); // printf("Service-Name: %s\n", s.serviceName.c_str()); } @@ -854,30 +858,30 @@ void SIsectionSDT::parsePrivateDataDescriptor(const char *buf, SIservice &s) void SIsectionSDT::parseDescriptors(const char *des, unsigned len, SIservice &s) { - struct descr_generic_header *desc; - des += sizeof(struct sdt_service); - len -= sizeof(struct sdt_service); - while(len>=sizeof(struct descr_generic_header)) { - desc=(struct descr_generic_header *)des; + struct descr_generic_header *desc; + des += sizeof(struct sdt_service); + len -= sizeof(struct sdt_service); + while(len>=sizeof(struct descr_generic_header)) { + desc=(struct descr_generic_header *)des; // printf("Type: %s\n", decode_descr(desc->descriptor_tag)); // printf("Length: %hhu\n", desc->descriptor_length); - if(desc->descriptor_tag==0x48) { + if(desc->descriptor_tag==0x48) { // printf("Found service descriptor\n"); - parseServiceDescriptor((const char *)desc, s); - } - else if(desc->descriptor_tag==0x4b) { + parseServiceDescriptor((const char *)desc, s); + } + else if(desc->descriptor_tag==0x4b) { // printf("Found NVOD reference descriptor\n"); - parseNVODreferenceDescriptor((const char *)desc, s); - } - else if(desc->descriptor_tag==0x5f) { + parseNVODreferenceDescriptor((const char *)desc, s); + } + else if(desc->descriptor_tag==0x5f) { // printf("Found Private Data Specifier\n"); - parsePrivateDataDescriptor((const char *)desc, s); - } - // hotfix for ARD crash - if ((int) lendescriptor_length+2) break; - len-=desc->descriptor_length+2; - des+=desc->descriptor_length+2; - } + parsePrivateDataDescriptor((const char *)desc, s); + } + // hotfix for ARD crash + if ((int) lendescriptor_length+2) break; + len-=desc->descriptor_length+2; + des+=desc->descriptor_length+2; + } } // Die infos aus dem Puffer holen @@ -1004,7 +1008,7 @@ void SIsectionBAT::parse(void) // SIbouquet s((bh->bouquet_id_hi << 8) | bh->bouquet_id_lo); //Create a new Bouquet entry // printf("ident: %hu actpos: %p buf+bl: %p desclen: %hu\n", bi.bouquet_id, actPos, buffer+bufferLength, descriptors_loop_length); int count = 0; - //Fill out Bouquet Name + //Fill out Bouquet Name //count = parseDescriptors(((const char *)bh) + sizeof(SI_section_BAT_header), descriptors_loop_length, s, bh->section_number, count); const char *des = ((const char *)bh) + sizeof(SI_section_BAT_header); unsigned len = descriptors_loop_length; @@ -1021,12 +1025,12 @@ void SIsectionBAT::parse(void) //struct descr_generic_header *sv=(struct descr_generic_header *)buf; buf+=sizeof(struct descr_generic_header); if(desc->descriptor_length) { - /* - if(*buf < 0x06) // other code table - s.bouquetName=std::string(buf+1, sv->descriptor_length-1); - else - s.bouquetName=std::string(buf, sv->descriptor_length); - */ + /* + if(*buf < 0x06) // other code table + s.bouquetName=std::string(buf+1, sv->descriptor_length-1); + else + s.bouquetName=std::string(buf, sv->descriptor_length); + */ //Mega stupid providers do not reserve their own bouquet_id //So we do it for them... f*ck that's stupid too, but what else can we do... if (bouquet_id == 0x0001) { @@ -1046,7 +1050,7 @@ void SIsectionBAT::parse(void) struct private_data_specifier *pds=(struct private_data_specifier *)buf; buf+=sizeof(struct private_data_specifier); current_private_data_specifier=(((pds->byte1 << 24) | (pds->byte2 << 16)) | (pds->byte3 << 8)) | pds->byte4; - //printf("Private Data Specifier: %08x\n", current_private_data_specifier); + //printf("Private Data Specifier: %08x\n", current_private_data_specifier); } len-=desc->descriptor_length+2; des+=desc->descriptor_length+2; @@ -1063,35 +1067,35 @@ void SIsectionBAT::parse(void) if (bouquet_id != 0x0001) { while (actPos <= &buffer[bufferLength - sizeof(struct bat_service)]) { sv = (struct bat_service *)actPos; - //s.transport_stream_id = (sv->transport_stream_id_hi << 8) | sv->transport_stream_id_lo; - //s.original_network_id = (sv->original_network_id_hi << 8) | sv->original_network_id_lo; - // s.position = (uint16_t) (((bh->section_number & 0x1f) << 11) + (count & 0x7ff)); - // printf("Section Number: %d Count: %d position: %04x\n", bh->section_number, count, s.position); + //s.transport_stream_id = (sv->transport_stream_id_hi << 8) | sv->transport_stream_id_lo; + //s.original_network_id = (sv->original_network_id_hi << 8) | sv->original_network_id_lo; + // s.position = (uint16_t) (((bh->section_number & 0x1f) << 11) + (count & 0x7ff)); + // printf("Section Number: %d Count: %d position: %04x\n", bh->section_number, count, s.position); descriptors_length = (sv->descriptors_loop_length_hi << 8) | sv->descriptors_loop_length_lo; - // Transport Stream Loop - //count = parseDescriptors(((const char *)sv) + sizeof(struct bat_service), descriptors_length, s, bh->section_number, count, - //(const char *) bouquetName[0]); - bool found = false; + // Transport Stream Loop + //count = parseDescriptors(((const char *)sv) + sizeof(struct bat_service), descriptors_length, s, bh->section_number, count, + //(const char *) bouquetName[0]); + bool found = false; int loop_count = 1; - while (loop_count >= 0) { + while (loop_count >= 0) { const char *des_ = ((const char *)sv) + sizeof(struct bat_service); len = descriptors_length; while(len>=sizeof(struct descr_generic_header)) { - desc=(struct descr_generic_header *)des_; + desc=(struct descr_generic_header *)des_; // printf("Type: %s\n", decode_descr(desc->descriptor_tag)); // printf("Length: %hhu\n", desc->descriptor_length); const char *buf = (const char *) desc; buf+=sizeof(struct descr_generic_header); unsigned short dlen = desc->descriptor_length; - if ((desc->descriptor_tag==0x41) && (loop_count == 0) && (current_private_data_specifier != 0x00000002)) { + if ((desc->descriptor_tag==0x41) && (loop_count == 0) && (current_private_data_specifier != 0x00000002)) { // printf("Found service list descriptor\n"); - //count = parseServiceListDescriptor((const char *)desc, s, section_no, count); - //struct descr_generic_header *sv=(struct descr_generic_header *)buf; + //count = parseServiceListDescriptor((const char *)desc, s, section_no, count); + //struct descr_generic_header *sv=(struct descr_generic_header *)buf; - while(dlen >= sizeof(struct service_list_entry)) { - struct service_list_entry *sl=(struct service_list_entry *)buf; + while(dlen >= sizeof(struct service_list_entry)) { + struct service_list_entry *sl=(struct service_list_entry *)buf; buf+=sizeof(struct service_list_entry); SIbouquet bs(bouquet_id); bs.bouquetName = bouquetName; @@ -1117,7 +1121,7 @@ void SIsectionBAT::parse(void) (oe->channel_number_hi << 8) | oe->channel_number_lo); */ if ( ((sl->service_id_hi << 8) | sl->service_id_lo) == - ((oe->service_id_hi << 8) | oe->service_id_lo)) { + ((oe->service_id_hi << 8) | oe->service_id_lo)) { bs.position = (oe->channel_number_hi << 8) | oe->channel_number_lo; /* printf("Found Search: %04x Service_id: %04x Posi:%04x\n", @@ -1137,7 +1141,7 @@ void SIsectionBAT::parse(void) bsv.insert(bs); dlen -= sizeof(struct service_list_entry); count++; - } + } } if (desc->descriptor_tag == 0x5f) { struct private_data_specifier *pds=(struct private_data_specifier *)buf; @@ -1145,7 +1149,7 @@ void SIsectionBAT::parse(void) if ((pds->byte1 != 0) || (pds->byte2 != 0) || (pds->byte3 != 0) || (pds->byte4 != 0)) current_private_data_specifier=(((pds->byte1 << 24) | (pds->byte2 << 16)) | (pds->byte3 << 8)) | pds->byte4; - //printf("Private Data Specifier: %08x\n", current_private_data_specifier); + //printf("Private Data Specifier: %08x\n", current_private_data_specifier); } if (desc->descriptor_tag == 0x81) { if (current_private_data_specifier == 0x55504300) { @@ -1194,9 +1198,9 @@ void SIsectionBAT::parse(void) SIbouquet bs(bouquet_id); bs.bouquetName = bouquetName; bs.transport_stream_id = (sv->transport_stream_id_hi << 8) | - sv->transport_stream_id_lo; + sv->transport_stream_id_lo; bs.original_network_id = (sv->original_network_id_hi << 8) | - sv->original_network_id_lo; + sv->original_network_id_lo; bs.service_id = (oe->service_id_hi << 8) | oe->service_id_lo; bs.serviceTyp = oe->service_type; bs.position = (oe->channel_number_hi << 8) | oe->channel_number_lo; @@ -1207,14 +1211,14 @@ void SIsectionBAT::parse(void) } } - len-=desc->descriptor_length+2; - des_+=desc->descriptor_length+2; - } + len-=desc->descriptor_length+2; + des_+=desc->descriptor_length+2; + } loop_count--; } actPos += sizeof(struct bat_service) + descriptors_length; - // count++; + // count++; } } parsed = 1; @@ -1222,10 +1226,10 @@ void SIsectionBAT::parse(void) void SIsectionNIT::copyDeliveryDescriptor(const char *buf, SInetwork &s) { - //struct descr_generic_header *sv=(struct descr_generic_header *)buf; - buf+=sizeof(struct descr_generic_header); - memmove(s.delivery_descriptor, buf, sizeof(struct satellite_delivery_descriptor)); //same size as cable... - //printf("Bouquet-Name: %s\n", s.bouquetName.c_str()); + //struct descr_generic_header *sv=(struct descr_generic_header *)buf; + buf+=sizeof(struct descr_generic_header); + memmove(s.delivery_descriptor, buf, sizeof(struct satellite_delivery_descriptor)); //same size as cable... + //printf("Bouquet-Name: %s\n", s.bouquetName.c_str()); } void SIsectionNIT::parseDescriptors(const char *des, unsigned len, SInetwork &s) @@ -1236,28 +1240,28 @@ void SIsectionNIT::parseDescriptors(const char *des, unsigned len, SInetwork &s) // t_original_network_id onid; // unsigned short orbital_pos; - struct descr_generic_header *desc; - des += sizeof(struct nit_transponder); - len -= sizeof(struct nit_transponder); + struct descr_generic_header *desc; + des += sizeof(struct nit_transponder); + len -= sizeof(struct nit_transponder); - while(len>=sizeof(struct descr_generic_header)) { - desc=(struct descr_generic_header *)des; + while(len>=sizeof(struct descr_generic_header)) { + desc=(struct descr_generic_header *)des; // printf("Type: %s\n", decode_descr(desc->descriptor_tag)); // printf("Length: %hhu\n", desc->descriptor_length); - if ( (desc->descriptor_tag==0x43) || (desc->descriptor_tag==0x44) ) { - s.delivery_type = desc->descriptor_tag; + if ( (desc->descriptor_tag==0x43) || (desc->descriptor_tag==0x44) ) { + s.delivery_type = desc->descriptor_tag; // printf("Found satellite_delivery_system_descriptor\n"); - copyDeliveryDescriptor((const char *)desc, s); + copyDeliveryDescriptor((const char *)desc, s); // ddp = &s.delivery_descriptor[0]; // sdd = (struct satellite_delivery_descriptor *)ddp; // tsid = s.transport_stream_id; // onid = s.original_network_id; // orbital_pos = (sdd->orbital_pos_hi << 8) | sdd->orbital_pos_lo; // printf("ONID: %04x TSID: %04x Orbital Position: %d\n", onid, tsid, orbital_pos); - } - len-=desc->descriptor_length+2; - des+=desc->descriptor_length+2; - } + } + len-=desc->descriptor_length+2; + des+=desc->descriptor_length+2; + } } // Die infos aus dem Puffer holen @@ -1318,29 +1322,29 @@ void SIsectionNIT::parse(void) // ansonsten die Anzahl gelesener Bytes inline int readNbytes(int fd, char *buf, int n, unsigned timeoutInSeconds) { -int j; - for(j=0; j': - fprintf(out, ">"); - break; - case '&': - fprintf(out, "&"); - break; - case '\"': - fprintf(out, """); - break; - case '\'': - fprintf(out, "'"); - break; + if(!c) + return 1; + // Die Umlaute sind ISO-8859-9 [5] + /* + char buf[6000]; + int inlen=strlen(c); + int outlen=sizeof(buf); + // UTF8Toisolat1((unsigned char *)buf, &outlen, (const unsigned char *)c, &inlen); + isolat1ToUTF8((unsigned char *)buf, &outlen, (const unsigned char *)c, &inlen); + buf[outlen]=0; + c=buf; + */ + for(; *c; c++) { + switch ((unsigned char)*c) { + case '<': + fprintf(out, "<"); + break; + case '>': + fprintf(out, ">"); + break; + case '&': + fprintf(out, "&"); + break; + case '\"': + fprintf(out, """); + break; + case '\'': + fprintf(out, "'"); + break; #if 0 - case 0x81: - case 0x82: - break; - case 0x86: - if(withControlCodes) - fprintf(out, ""); - break; - case 0x87: - if(withControlCodes) - fprintf(out, ""); - break; - case 0x8a: - if(withControlCodes) - fprintf(out, "
"); - break; - default: - if (*c<32) - break; - if ((*c>=32) && (((unsigned char)*c)<128)) - fprintf(out, "%c", *c); - else - fprintf(out, "&#%d;", *c); + case 0x81: + case 0x82: + break; + case 0x86: + if(withControlCodes) + fprintf(out, ""); + break; + case 0x87: + if(withControlCodes) + fprintf(out, ""); + break; + case 0x8a: + if(withControlCodes) + fprintf(out, "
"); + break; + default: + if (*c<32) + break; + if ((*c>=32) && (((unsigned char)*c)<128)) + fprintf(out, "%c", *c); + else + fprintf(out, "&#%d;", *c); #else - default: - if ((unsigned char)*c<32) - break; - fprintf(out, "%c", *c); + default: + if ((unsigned char)*c<32) + break; + fprintf(out, "%c", *c); #endif - } // case + } // case - } // for - return 0; + } // for + return 0; } // Entfernt die ControlCodes aus dem String (-> String wird evtl. kuerzer) void removeControlCodes(char *string) { - if(!string) - return; - for(;*string; ) - if (!((*string>=32) && (((unsigned char)*string)<128))) - memmove(string, string+1, strlen(string+1)+1); - else - string++; - return ; + if(!string) + return; + for(; *string; ) + if (!((*string>=32) && (((unsigned char)*string)<128))) + memmove(string, string+1, strlen(string+1)+1); + else + string++; + return ; } diff --git a/src/sectionsd/bat.cpp b/src/sectionsd/bat.cpp index 3e693bb90..705a1b191 100644 --- a/src/sectionsd/bat.cpp +++ b/src/sectionsd/bat.cpp @@ -61,16 +61,16 @@ int main(int /*argc*/, char** /*argv*/) { - time_t starttime, endtime; - SIsectionsBAT batset; + time_t starttime, endtime; + SIsectionsBAT batset; - starttime=time(NULL); - batset.readSections(); - endtime=time(NULL); - printf("Sections read: %d\n", batset.size()); - printf("Time needed: %ds\n", (int)difftime(endtime, starttime)); + starttime=time(NULL); + batset.readSections(); + endtime=time(NULL); + printf("Sections read: %d\n", batset.size()); + printf("Time needed: %ds\n", (int)difftime(endtime, starttime)); // for_each(batset.begin(), batset.end(), printSmallSectionHeader()); // for_each(batset.begin(), batset.end(), printSIsection()); - for_each(batset.begin(), batset.end(), printSIsectionBAT()); - return 0; + for_each(batset.begin(), batset.end(), printSIsectionBAT()); + return 0; } diff --git a/src/sectionsd/dmx.cpp b/src/sectionsd/dmx.cpp index c35940dc9..45eb54661 100644 --- a/src/sectionsd/dmx.cpp +++ b/src/sectionsd/dmx.cpp @@ -100,9 +100,9 @@ ssize_t DMX::read(char * const /*buf*/, const size_t /*buflength*/, const unsign void DMX::close(void) { - if(dmx) - delete dmx; - dmx = NULL; + if(dmx) + delete dmx; + dmx = NULL; } void DMX::closefd(void) @@ -157,8 +157,10 @@ void DMX::lock(void) int rc = pthread_mutex_lock(&start_stop_mutex); if (rc != 0) { - fprintf(stderr, "[sectionsd] mutex_lock: %d %d %d\n", rc, EINVAL, EDEADLK); fflush(stderr); - fprintf(stderr, "[sectionsd] pid: %d\n", getpid()); fflush(stderr); + fprintf(stderr, "[sectionsd] mutex_lock: %d %d %d\n", rc, EINVAL, EDEADLK); + fflush(stderr); + fprintf(stderr, "[sectionsd] pid: %d\n", getpid()); + fflush(stderr); } #else pthread_mutex_lock(&start_stop_mutex); @@ -172,8 +174,10 @@ void DMX::unlock(void) int rc = pthread_mutex_unlock(&start_stop_mutex); if (rc != 0) { - fprintf(stderr, "[sectionsd] mutex_unlock: %d %d %d\n", rc, EINVAL, EPERM); fflush(stderr); - fprintf(stderr, "[sectionsd] pid: %d\n", getpid()); fflush(stderr); + fprintf(stderr, "[sectionsd] mutex_unlock: %d %d %d\n", rc, EINVAL, EPERM); + fflush(stderr); + fprintf(stderr, "[sectionsd] pid: %d\n", getpid()); + fflush(stderr); } #else pthread_mutex_unlock(&start_stop_mutex); @@ -198,20 +202,20 @@ bool DMX::check_complete(const unsigned char table_id, const unsigned short exte if (last == 0) return true; MyDMXOrderUniqueKey::iterator di = myDMXOrderUniqueKey.find(create_sections_id( - table_id, - extension_id, - current_section_number, - onid, - tsid)); + table_id, + extension_id, + current_section_number, + onid, + tsid)); if (di != myDMXOrderUniqueKey.end()) { di++; } while ((di != myDMXOrderUniqueKey.end()) && ((uint8_t) ((di->first >> 56) & 0xff) == table_id) && - ((uint16_t) ((di->first >> 40) & 0xffff) == extension_id) && - (((uint8_t) ((di->first >> 32) & 0xff) == current_section_number + 1) || - ((uint8_t) ((di->first >> 32) & 0xff) == current_section_number + 8)) && - ((uint16_t) ((di->first >> 16) & 0xffff) == onid) && - ((uint16_t) (di->first & 0xffff) == tsid)) + ((uint16_t) ((di->first >> 40) & 0xffff) == extension_id) && + (((uint8_t) ((di->first >> 32) & 0xff) == current_section_number + 1) || + ((uint8_t) ((di->first >> 32) & 0xff) == current_section_number + 8)) && + ((uint16_t) ((di->first >> 16) & 0xffff) == onid) && + ((uint16_t) (di->first & 0xffff) == tsid)) { if ((uint8_t) ((di->first >> 32) & 0xff) == last) { return true; @@ -343,7 +347,7 @@ int DMX::getSection(char *buf, const unsigned timeoutInMSeconds, int &timeouts) unlock(); // skip sections which are too short if ((section_length < 5) || - (initial_header->table_id >= 0x4e && initial_header->table_id <= 0x6f && section_length < 14)) + (initial_header->table_id >= 0x4e && initial_header->table_id <= 0x6f && section_length < 14)) { dprintf("section too short: table %x, length: %d\n", initial_header->table_id, section_length); return -1; @@ -376,8 +380,8 @@ int DMX::getSection(char *buf, const unsigned timeoutInMSeconds, int &timeouts) if (!cache) { if (initial_header->table_id == 0x4e && - eh_tbl_extension_id == current_service && - extended_header->version_number != eit_version) { + eh_tbl_extension_id == current_service && + extended_header->version_number != eit_version) { dprintf("EIT old: %d new version: %d\n",eit_version,extended_header->version_number); eit_version = extended_header->version_number; } @@ -398,9 +402,9 @@ int DMX::getSection(char *buf, const unsigned timeoutInMSeconds, int &timeouts) if (di->second == extended_header->version_number) { #ifdef DEBUG_CACHED_SECTIONS dprintf("[sectionsd] skipped duplicate section for table 0x%02x table_extension 0x%04x section 0x%02x\n", - initial_header->table_id, - eh_tbl_extension_id, - extended_header->section_number); + initial_header->table_id, + eh_tbl_extension_id, + extended_header->section_number); #endif //the version number is still up2date if (first_skipped == 0) { @@ -415,21 +419,21 @@ int DMX::getSection(char *buf, const unsigned timeoutInMSeconds, int &timeouts) } //since version is still up2date, check if table complete if (check_complete(initial_header->table_id, - eh_tbl_extension_id, - current_onid, - current_tsid, - extended_header->last_section_number)) + eh_tbl_extension_id, + current_onid, + current_tsid, + extended_header->last_section_number)) timeouts = -2; return -1; } else { #ifdef DEBUG_CACHED_SECTIONS dprintf("[sectionsd] version update from 0x%02x to 0x%02x for table 0x%02x table_extension 0x%04x section 0x%02x\n", - di->second, - extended_header->version_number, - initial_header->table_id, - eh_tbl_extension_id, - extended_header->section_number); + di->second, + extended_header->version_number, + initial_header->table_id, + eh_tbl_extension_id, + extended_header->section_number); #endif //update version number di->second = extended_header->version_number; @@ -438,19 +442,19 @@ int DMX::getSection(char *buf, const unsigned timeoutInMSeconds, int &timeouts) else { #ifdef DEBUG_CACHED_SECTIONS - dprintf("[sectionsd] new section for table 0x%02x table_extension 0x%04x section 0x%02x\n", - initial_header->table_id, - eh_tbl_extension_id, - extended_header->section_number); + dprintf("[sectionsd] new section for table 0x%02x table_extension 0x%04x section 0x%02x\n", + initial_header->table_id, + eh_tbl_extension_id, + extended_header->section_number); #endif //section was not read before - insert in list myDMXOrderUniqueKey.insert(std::make_pair(s_id, extended_header->version_number)); //check if table is now complete if (check_complete(initial_header->table_id, - eh_tbl_extension_id, - current_onid, - current_tsid, - extended_header->last_section_number)) + eh_tbl_extension_id, + current_onid, + current_tsid, + extended_header->last_section_number)) timeouts = -2; } //if control comes to here the sections skipped counter must be restarted @@ -465,7 +469,7 @@ int DMX::immediate_start(void) { if (isOpen()) { -xprintf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>DMX::imediate_start: isOpen()<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); + xprintf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>DMX::imediate_start: isOpen()<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"); closefd(); } @@ -487,12 +491,12 @@ xprintf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>DMX::imediate_start: isOpen()<<<<<<<<<<<< return 3; } #endif - if(dmx == NULL) { - dmx = new cDemux(dmx_num); + if(dmx == NULL) { + dmx = new cDemux(dmx_num); #if !HAVE_TRIPLEDRAGON - dmx->Open(DMX_PSI_CHANNEL, NULL, dmxBufferSizeInKB*1024UL); + dmx->Open(DMX_PSI_CHANNEL, NULL, dmxBufferSizeInKB*1024UL); #endif - } + } #if HAVE_TRIPLEDRAGON dmx->Open(DMX_PSI_CHANNEL, NULL, dmxBufferSizeInKB*1024UL); #endif @@ -501,20 +505,20 @@ xprintf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>DMX::imediate_start: isOpen()<<<<<<<<<<<< /* setfilter() only if this is no dummy filter... */ #if 0 if (filters[filter_index].filter && filters[filter_index].mask && - !setfilter(fd, pID, filters[filter_index].filter, filters[filter_index].mask, DMX_IMMEDIATE_START | DMX_CHECK_CRC)) + !setfilter(fd, pID, filters[filter_index].filter, filters[filter_index].mask, DMX_IMMEDIATE_START | DMX_CHECK_CRC)) #endif - if (filters[filter_index].filter && filters[filter_index].mask) - { - unsigned char filter[DMX_FILTER_SIZE]; - unsigned char mask[DMX_FILTER_SIZE]; + if (filters[filter_index].filter && filters[filter_index].mask) + { + unsigned char filter[DMX_FILTER_SIZE]; + unsigned char mask[DMX_FILTER_SIZE]; - filter[0] = filters[filter_index].filter; - mask[0] = filters[filter_index].mask; - dmx->sectionFilter(pID, filter, mask, 1); - //FIXME error check - //closefd(); - //return 4; - } + filter[0] = filters[filter_index].filter; + mask[0] = filters[filter_index].mask; + dmx->sectionFilter(pID, filter, mask, 1); + //FIXME error check + //closefd(); + //return 4; + } /* this is for dmxCN only... */ eit_version = 0xff; return 0; @@ -628,18 +632,18 @@ int DMX::unpause(void) #endif const char *dmx_filter_types [] = { - "dummy filter", - "actual transport stream, scheduled", - "other transport stream, now/next", - "other transport stream, scheduled 1", - "other transport stream, scheduled 2" + "dummy filter", + "actual transport stream, scheduled", + "other transport stream, now/next", + "other transport stream, scheduled 1", + "other transport stream, scheduled 2" }; int DMX::change(const int new_filter_index, const int new_current_service) { if (sections_debug) showProfiling("changeDMX: before pthread_mutex_lock(&start_stop_mutex)"); - lock(); + lock(); if (sections_debug) showProfiling("changeDMX: after pthread_mutex_lock(&start_stop_mutex)"); @@ -648,9 +652,9 @@ int DMX::change(const int new_filter_index, const int new_current_service) first_skipped = 0; #if 0 -/* i have to think about this. This #if 0 now makes .change() automatically unpause the - * demux. No idea if there are negative side effects - we will find out :) -- seife - */ + /* i have to think about this. This #if 0 now makes .change() automatically unpause the + * demux. No idea if there are negative side effects - we will find out :) -- seife + */ if (!isOpen()) { pthread_cond_signal(&change_cond); @@ -665,7 +669,7 @@ int DMX::change(const int new_filter_index, const int new_current_service) if (real_pauseCounter > 0) { printf("changeDMX: for 0x%x not ignored! even though real_pauseCounter> 0 (%d)\n", - filters[new_filter_index].filter, real_pauseCounter); + filters[new_filter_index].filter, real_pauseCounter); /* immediate_start() checks for real_pauseCounter again (and does nothing in that case), so we can just continue here. */ } @@ -698,7 +702,7 @@ int DMX::change(const int new_filter_index, const int new_current_service) if (sections_debug) showProfiling("after DMX_SET_FILTER"); - pthread_cond_signal(&change_cond); + pthread_cond_signal(&change_cond); lastChanged = time_monotonic(); @@ -734,8 +738,8 @@ ssize_t DMX::readNbytes(int _fd, char *buf, const size_t n, unsigned timeoutInMS { printdate_ms(stderr); fprintf(stderr, "[sectionsd] DMX::readNbytes received POLLERR, pid 0x%x, filter[%d] " - "filter 0x%02x mask 0x%02x\n", pID, filter_index, - filters[filter_index].filter, filters[filter_index].mask); + "filter 0x%02x mask 0x%02x\n", pID, filter_index, + filters[filter_index].filter, filters[filter_index].mask); return -1; } if (!(ufds.revents&POLLIN)) @@ -764,7 +768,7 @@ ssize_t DMX::readNbytes(int _fd, char *buf, const size_t n, unsigned timeoutInMS int DMX::setPid(const unsigned short new_pid) { - lock(); + lock(); if (!isOpen()) { @@ -790,7 +794,7 @@ int DMX::setPid(const unsigned short new_pid) return rc; } - pthread_cond_signal(&change_cond); + pthread_cond_signal(&change_cond); lastChanged = time_monotonic(); @@ -806,12 +810,12 @@ int DMX::setCurrentService(int new_current_service) int DMX::dropCachedSectionIDs() { - lock(); + lock(); -/* i think that those checks are wrong for dropCachedSectionIDs(), since - this is called from the housekeeping thread while sectionsd might be - idle waiting for the EIT update filter to trigger -- seife - */ + /* i think that those checks are wrong for dropCachedSectionIDs(), since + this is called from the housekeeping thread while sectionsd might be + idle waiting for the EIT update filter to trigger -- seife + */ #if 0 if (!isOpen()) { @@ -840,7 +844,7 @@ int DMX::dropCachedSectionIDs() } #endif - pthread_cond_signal(&change_cond); + pthread_cond_signal(&change_cond); unlock(); diff --git a/src/sectionsd/dmx.h b/src/sectionsd/dmx.h index 91121ca82..a0209bad8 100644 --- a/src/sectionsd/dmx.h +++ b/src/sectionsd/dmx.h @@ -41,7 +41,7 @@ typedef unsigned char version_number_t; class DMX { - private: +private: int fd; cDemux * dmx; @@ -54,15 +54,17 @@ class DMX unsigned char eit_version; bool cache; /* should read sections be cached? true for all but dmxCN */ - inline bool isOpen(void) { return (fd != -1); } - + inline bool isOpen(void) { + return (fd != -1); + } + int immediate_start(void); /* mutex must be locked before and unlocked after this method */ int immediate_stop(void); /* mutex must be locked before and unlocked after this method */ bool check_complete(const unsigned char table_id, const unsigned short extension_id, const unsigned short onid, const unsigned short tsid, const unsigned char); sections_id_t create_sections_id(const unsigned char table_id, const unsigned short extension_id, const unsigned char section_number, const unsigned short onid, const unsigned short tsid); ssize_t readNbytes(int fd, char * buf, const size_t n, unsigned timeoutInMSeconds); - public: +public: struct s_filters { unsigned char filter; diff --git a/src/sectionsd/dmxapi.cpp b/src/sectionsd/dmxapi.cpp index b82fd6fb5..953200509 100644 --- a/src/sectionsd/dmxapi.cpp +++ b/src/sectionsd/dmxapi.cpp @@ -89,7 +89,7 @@ struct SI_section_TDT_header unsigned char reserved_future_use : 1; unsigned char reserved1 : 2; unsigned short section_length : 12; -/* uint64_t UTC_time : 40;*/ + /* uint64_t UTC_time : 40;*/ UTC_t UTC_time; } __attribute__ ((packed)); /* 8 bytes */ @@ -156,7 +156,7 @@ bool getUTC(UTC_t * const UTC, const bool TDT) if ((cUTC[2] > 0x23) || (cUTC[3] > 0x59) || (cUTC[4] > 0x59)) // no valid time { printf("[sectionsd] getUTC: invalid %s section received: %02x %02x %02x %02x %02x\n", - TDT ? "TDT" : "TOT", cUTC[0], cUTC[1], cUTC[2], cUTC[3], cUTC[4]); + TDT ? "TDT" : "TOT", cUTC[0], cUTC[1], cUTC[2], cUTC[3], cUTC[4]); ret = false; } diff --git a/src/sectionsd/edvbstring.cpp b/src/sectionsd/edvbstring.cpp index e15e4d113..d7a63d3d3 100644 --- a/src/sectionsd/edvbstring.cpp +++ b/src/sectionsd/edvbstring.cpp @@ -38,119 +38,133 @@ int readEncodingFile() return -1; } - // 8859-x to ucs-16 coding tables. taken from www.unicode.org/Public/MAPPINGS/ISO8859/ +// 8859-x to ucs-16 coding tables. taken from www.unicode.org/Public/MAPPINGS/ISO8859/ -static unsigned long c88592[96]={ -0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, -0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, -0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, -0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, -0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, -0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0142, /*0x0159,*/ 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9}; - -static unsigned long c88593[96]={ -0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7, 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B, -0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C, -0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, -0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF, -0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, -0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9}; +static unsigned long c88592[96]= { + 0x00A0, 0x0104, 0x02D8, 0x0141, 0x00A4, 0x013D, 0x015A, 0x00A7, 0x00A8, 0x0160, 0x015E, 0x0164, 0x0179, 0x00AD, 0x017D, 0x017B, + 0x00B0, 0x0105, 0x02DB, 0x0142, 0x00B4, 0x013E, 0x015B, 0x02C7, 0x00B8, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, 0x017C, + 0x0154, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0139, 0x0106, 0x00C7, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x011A, 0x00CD, 0x00CE, 0x010E, + 0x0110, 0x0143, 0x0147, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x00D7, 0x0158, 0x016E, 0x00DA, 0x0170, 0x00DC, 0x00DD, 0x0162, 0x00DF, + 0x0155, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x013A, 0x0107, 0x00E7, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x011B, 0x00ED, 0x00EE, 0x010F, + 0x0111, 0x0144, 0x0148, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x00F7, 0x0142, /*0x0159,*/ 0x016F, 0x00FA, 0x0171, 0x00FC, 0x00FD, 0x0163, 0x02D9 +}; -static unsigned long c88594[96]={ -0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF, -0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B, -0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A, -0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF, -0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B, -0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9}; +static unsigned long c88593[96]= { + 0x00A0, 0x0126, 0x02D8, 0x00A3, 0x00A4, 0x0000, 0x0124, 0x00A7, 0x00A8, 0x0130, 0x015E, 0x011E, 0x0134, 0x00AD, 0x0000, 0x017B, + 0x00B0, 0x0127, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x0125, 0x00B7, 0x00B8, 0x0131, 0x015F, 0x011F, 0x0135, 0x00BD, 0x0000, 0x017C, + 0x00C0, 0x00C1, 0x00C2, 0x0000, 0x00C4, 0x010A, 0x0108, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x0000, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x0120, 0x00D6, 0x00D7, 0x011C, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x016C, 0x015C, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x0000, 0x00E4, 0x010B, 0x0109, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x0000, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x0121, 0x00F6, 0x00F7, 0x011D, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x016D, 0x015D, 0x02D9 +}; -static unsigned long c88595[96]={ -0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F, -0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, -0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, -0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, -0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, -0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F}; - -static unsigned long c88596[96]={ -0x00A0, 0x0000, 0x0000, 0x0000, 0x00A4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x060C, 0x00AD, 0x0000, 0x0000, -0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x061B, 0x0000, 0x0000, 0x0000, 0x061F, -0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, -0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, -0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000}; - -static unsigned long c88597[96]={ -0x00A0, 0x2018, 0x2019, 0x00A3, 0x20AC, 0x20AF, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x037A, 0x00AB, 0x00AC, 0x00AD, 0x0000, 0x2015, -0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7, 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, -0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, -0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, -0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, -0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000}; +static unsigned long c88594[96]= { + 0x00A0, 0x0104, 0x0138, 0x0156, 0x00A4, 0x0128, 0x013B, 0x00A7, 0x00A8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00AD, 0x017D, 0x00AF, + 0x00B0, 0x0105, 0x02DB, 0x0157, 0x00B4, 0x0129, 0x013C, 0x02C7, 0x00B8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014A, 0x017E, 0x014B, + 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x012A, + 0x0110, 0x0145, 0x014C, 0x0136, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x0168, 0x016A, 0x00DF, + 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x012B, + 0x0111, 0x0146, 0x014D, 0x0137, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x0169, 0x016B, 0x02D9 +}; -static unsigned long c88598[96]={ -0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, -0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x0000, -0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017, -0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, -0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000}; +static unsigned long c88595[96]= { + 0x00A0, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x00AD, 0x040E, 0x040F, + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x2116, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x00A7, 0x045E, 0x045F +}; -static unsigned long c88599[96]={ -0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, -0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, -0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, -0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, -0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, -0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF}; +static unsigned long c88596[96]= { + 0x00A0, 0x0000, 0x0000, 0x0000, 0x00A4, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x060C, 0x00AD, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x061B, 0x0000, 0x0000, 0x0000, 0x061F, + 0x0000, 0x0621, 0x0622, 0x0623, 0x0624, 0x0625, 0x0626, 0x0627, 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, + 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0640, 0x0641, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, + 0x0650, 0x0651, 0x0652, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; -static unsigned long c885910[96]={ -0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A, -0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B, -0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF, -0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, -0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF, -0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138}; - -static unsigned long c885911[96]={ -0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, -0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, -0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, -0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, -0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, -0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000}; +static unsigned long c88597[96]= { + 0x00A0, 0x2018, 0x2019, 0x00A3, 0x20AC, 0x20AF, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x037A, 0x00AB, 0x00AC, 0x00AD, 0x0000, 0x2015, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x0384, 0x0385, 0x0386, 0x00B7, 0x0388, 0x0389, 0x038A, 0x00BB, 0x038C, 0x00BD, 0x038E, 0x038F, + 0x0390, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, + 0x03A0, 0x03A1, 0x0000, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03AA, 0x03AB, 0x03AC, 0x03AD, 0x03AE, 0x03AF, + 0x03B0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, + 0x03C0, 0x03C1, 0x03C2, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, 0x03C9, 0x03CA, 0x03CB, 0x03CC, 0x03CD, 0x03CE, 0x0000 +}; -static unsigned long c885913[96]={ -0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7, 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, -0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7, 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, -0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, -0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, -0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, -0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019}; +static unsigned long c88598[96]= { + 0x00A0, 0x0000, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00D7, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00F7, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2017, + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x0000, 0x0000, 0x200E, 0x200F, 0x0000 +}; -static unsigned long c885914[96]={ -0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7, 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178, -0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56, 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61, -0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, -0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF, -0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, -0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF}; +static unsigned long c88599[96]= { + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x00B4, 0x00B5, 0x00B6, 0x00B7, 0x00B8, 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x011E, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0130, 0x015E, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x011F, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0131, 0x015F, 0x00FF +}; -static unsigned long c885915[96]={ -0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, -0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7, 0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF, -0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, -0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, -0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, -0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF}; +static unsigned long c885910[96]= { + 0x00A0, 0x0104, 0x0112, 0x0122, 0x012A, 0x0128, 0x0136, 0x00A7, 0x013B, 0x0110, 0x0160, 0x0166, 0x017D, 0x00AD, 0x016A, 0x014A, + 0x00B0, 0x0105, 0x0113, 0x0123, 0x012B, 0x0129, 0x0137, 0x00B7, 0x013C, 0x0111, 0x0161, 0x0167, 0x017E, 0x2015, 0x016B, 0x014B, + 0x0100, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x012E, 0x010C, 0x00C9, 0x0118, 0x00CB, 0x0116, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x0145, 0x014C, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x0168, 0x00D8, 0x0172, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x0101, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x012F, 0x010D, 0x00E9, 0x0119, 0x00EB, 0x0117, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x0146, 0x014D, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x0169, 0x00F8, 0x0173, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x0138 +}; -static unsigned long c885916[96]={ -0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B, -0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7, 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C, -0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, -0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A, 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF, -0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, -0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B, 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF}; +static unsigned long c885911[96]= { + 0x00A0, 0x0E01, 0x0E02, 0x0E03, 0x0E04, 0x0E05, 0x0E06, 0x0E07, 0x0E08, 0x0E09, 0x0E0A, 0x0E0B, 0x0E0C, 0x0E0D, 0x0E0E, 0x0E0F, + 0x0E10, 0x0E11, 0x0E12, 0x0E13, 0x0E14, 0x0E15, 0x0E16, 0x0E17, 0x0E18, 0x0E19, 0x0E1A, 0x0E1B, 0x0E1C, 0x0E1D, 0x0E1E, 0x0E1F, + 0x0E20, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, + 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, 0x0E38, 0x0E39, 0x0E3A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0E3F, + 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, + 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static unsigned long c885913[96]= { + 0x00A0, 0x201D, 0x00A2, 0x00A3, 0x00A4, 0x201E, 0x00A6, 0x00A7, 0x00D8, 0x00A9, 0x0156, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00C6, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x201C, 0x00B5, 0x00B6, 0x00B7, 0x00F8, 0x00B9, 0x0157, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00E6, + 0x0104, 0x012E, 0x0100, 0x0106, 0x00C4, 0x00C5, 0x0118, 0x0112, 0x010C, 0x00C9, 0x0179, 0x0116, 0x0122, 0x0136, 0x012A, 0x013B, + 0x0160, 0x0143, 0x0145, 0x00D3, 0x014C, 0x00D5, 0x00D6, 0x00D7, 0x0172, 0x0141, 0x015A, 0x016A, 0x00DC, 0x017B, 0x017D, 0x00DF, + 0x0105, 0x012F, 0x0101, 0x0107, 0x00E4, 0x00E5, 0x0119, 0x0113, 0x010D, 0x00E9, 0x017A, 0x0117, 0x0123, 0x0137, 0x012B, 0x013C, + 0x0161, 0x0144, 0x0146, 0x00F3, 0x014D, 0x00F5, 0x00F6, 0x00F7, 0x0173, 0x0142, 0x015B, 0x016B, 0x00FC, 0x017C, 0x017E, 0x2019 +}; + +static unsigned long c885914[96]= { + 0x00A0, 0x1E02, 0x1E03, 0x00A3, 0x010A, 0x010B, 0x1E0A, 0x00A7, 0x1E80, 0x00A9, 0x1E82, 0x1E0B, 0x1EF2, 0x00AD, 0x00AE, 0x0178, + 0x1E1E, 0x1E1F, 0x0120, 0x0121, 0x1E40, 0x1E41, 0x00B6, 0x1E56, 0x1E81, 0x1E57, 0x1E83, 0x1E60, 0x1EF3, 0x1E84, 0x1E85, 0x1E61, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x0174, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x1E6A, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x0176, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x0175, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x1E6B, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x0177, 0x00FF +}; + +static unsigned long c885915[96]= { + 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x20AC, 0x00A5, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x00AF, + 0x00B0, 0x00B1, 0x00B2, 0x00B3, 0x017D, 0x00B5, 0x00B6, 0x00B7, 0x017E, 0x00B9, 0x00BA, 0x00BB, 0x0152, 0x0153, 0x0178, 0x00BF, + 0x00C0, 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x00D0, 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D7, 0x00D8, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x00F0, 0x00F1, 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF +}; + +static unsigned long c885916[96]= { + 0x00A0, 0x0104, 0x0105, 0x0141, 0x20AC, 0x201E, 0x0160, 0x00A7, 0x0161, 0x00A9, 0x0218, 0x00AB, 0x0179, 0x00AD, 0x017A, 0x017B, + 0x00B0, 0x00B1, 0x010C, 0x0142, 0x017D, 0x201D, 0x00B6, 0x00B7, 0x017E, 0x010D, 0x0219, 0x00BB, 0x0152, 0x0153, 0x0178, 0x017C, + 0x00C0, 0x00C1, 0x00C2, 0x0102, 0x00C4, 0x0106, 0x00C6, 0x00C7, 0x00C8, 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, + 0x0110, 0x0143, 0x00D2, 0x00D3, 0x00D4, 0x0150, 0x00D6, 0x015A, 0x0170, 0x00D9, 0x00DA, 0x00DB, 0x00DC, 0x0118, 0x021A, 0x00DF, + 0x00E0, 0x00E1, 0x00E2, 0x0103, 0x00E4, 0x0107, 0x00E6, 0x00E7, 0x00E8, 0x00E9, 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, + 0x0111, 0x0144, 0x00F2, 0x00F3, 0x00F4, 0x0151, 0x00F6, 0x015B, 0x0171, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x0119, 0x021B, 0x00FF +}; // Two Char Mapping ( many polish services and UPC Direct/HBO services) // get from http://mitglied.lycos.de/buran/charsets/videotex-suppl.html @@ -159,140 +173,369 @@ static inline unsigned int doVideoTexSuppl(char c1, char c2) { switch (c1) { - case 0xC1: // grave - switch (c2) - { - case 0x61: return 224; case 0x41: return 192; - case 0x65: return 232; case 0x45: return 200; - case 0x69: return 236; case 0x49: return 204; - case 0x6f: return 242; case 0x4f: return 210; - case 0x75: return 249; case 0x55: return 217; - default: return 0; - } - case 0xC2: // acute - switch (c2) - { - case 0x61: return 225; case 0x41: return 193; - case 0x65: return 233; case 0x45: return 201; - case 0x69: return 237; case 0x49: return 205; - case 0x6f: return 243; case 0x4f: return 211; - case 0x75: return 250; case 0x55: return 218; - case 0x79: return 253; case 0x59: return 221; - case 0x63: return 263; case 0x43: return 262; - case 0x6c: return 314; case 0x4c: return 313; - case 0x6e: return 324; case 0x4e: return 323; - case 0x72: return 341; case 0x52: return 340; - case 0x73: return 347; case 0x53: return 346; - case 0x7a: return 378; case 0x5a: return 377; - default: return 0; - } - case 0xC3: // cedilla - switch (c2) - { - case 0x61: return 226; case 0x41: return 194; - case 0x65: return 234; case 0x45: return 202; - case 0x69: return 238; case 0x49: return 206; - case 0x6f: return 244; case 0x4f: return 212; - case 0x75: return 251; case 0x55: return 219; - case 0x79: return 375; case 0x59: return 374; - case 0x63: return 265; case 0x43: return 264; - case 0x67: return 285; case 0x47: return 284; - case 0x68: return 293; case 0x48: return 292; - case 0x6a: return 309; case 0x4a: return 308; - case 0x73: return 349; case 0x53: return 348; - case 0x77: return 373; case 0x57: return 372; - default: return 0; - } - case 0xC4: // tilde - switch (c2) - { - case 0x61: return 227; case 0x41: return 195; - case 0x6e: return 241; case 0x4e: return 209; - case 0x69: return 297; case 0x49: return 296; - case 0x6f: return 245; case 0x4f: return 213; - case 0x75: return 361; case 0x55: return 360; - default: return 0; - } - case 0xC6: // breve - switch (c2) - { - case 0x61: return 259; case 0x41: return 258; - case 0x67: return 287; case 0x47: return 286; - case 0x75: return 365; case 0x55: return 364; - default: return 0; - } - case 0xC7: // dot above - switch (c2) - { - case 0x63: return 267; case 0x43: return 266; - case 0x65: return 279; case 0x45: return 278; - case 0x67: return 289; case 0x47: return 288; - case 0x49: return 304; case 0x7a: return 380; - case 0x5a: return 379; - default: return 0; - } - case 0xC8: // diaeresis - switch (c2) - { - case 0x61: return 228; case 0x41: return 196; - case 0x65: return 235; case 0x45: return 203; - case 0x69: return 239; case 0x49: return 207; - case 0x6f: return 246; case 0x4f: return 214; - case 0x75: return 252; case 0x55: return 220; - case 0x79: return 255; case 0x59: return 376; - default: return 0; - } - case 0xCA: // ring above - switch (c2) - { - case 0x61: return 229; case 0x41: return 197; - case 0x75: return 367; case 0x55: return 366; - default: return 0; - } - case 0xCB: // cedilla - switch (c2) - { - case 0x63: return 231; case 0x43: return 199; - case 0x67: return 291; case 0x47: return 290; - case 0x6b: return 311; case 0x4b: return 310; - case 0x6c: return 316; case 0x4c: return 315; - case 0x6e: return 326; case 0x4e: return 325; - case 0x72: return 343; case 0x52: return 342; - case 0x73: return 351; case 0x53: return 350; - case 0x74: return 355; case 0x54: return 354; - default: return 0; - } - case 0xCD: // double acute accent - switch (c2) - { - case 0x6f: return 337; case 0x4f: return 336; - case 0x75: return 369; case 0x55: return 368; - default: return 0; - } - case 0xCE: // ogonek - switch (c2) - { - case 0x61: return 261; case 0x41: return 260; - case 0x65: return 281; case 0x45: return 280; - case 0x69: return 303; case 0x49: return 302; - case 0x75: return 371; case 0x55: return 370; - default: return 0; - } - case 0xCF: // caron - switch (c2) - { - case 0x63: return 269; case 0x43: return 268; - case 0x64: return 271; case 0x44: return 270; - case 0x65: return 283; case 0x45: return 282; - case 0x6c: return 318; case 0x4c: return 317; - case 0x6e: return 328; case 0x4e: return 327; - case 0x72: return 345; case 0x52: return 344; - case 0x73: return 353; case 0x53: return 352; - case 0x74: return 357; case 0x54: return 356; - case 0x7a: return 382; case 0x5a: return 381; - default: return 0; - } - } + case 0xC1: // grave + switch (c2) + { + case 0x61: + return 224; + case 0x41: + return 192; + case 0x65: + return 232; + case 0x45: + return 200; + case 0x69: + return 236; + case 0x49: + return 204; + case 0x6f: + return 242; + case 0x4f: + return 210; + case 0x75: + return 249; + case 0x55: + return 217; + default: + return 0; + } + case 0xC2: // acute + switch (c2) + { + case 0x61: + return 225; + case 0x41: + return 193; + case 0x65: + return 233; + case 0x45: + return 201; + case 0x69: + return 237; + case 0x49: + return 205; + case 0x6f: + return 243; + case 0x4f: + return 211; + case 0x75: + return 250; + case 0x55: + return 218; + case 0x79: + return 253; + case 0x59: + return 221; + case 0x63: + return 263; + case 0x43: + return 262; + case 0x6c: + return 314; + case 0x4c: + return 313; + case 0x6e: + return 324; + case 0x4e: + return 323; + case 0x72: + return 341; + case 0x52: + return 340; + case 0x73: + return 347; + case 0x53: + return 346; + case 0x7a: + return 378; + case 0x5a: + return 377; + default: + return 0; + } + case 0xC3: // cedilla + switch (c2) + { + case 0x61: + return 226; + case 0x41: + return 194; + case 0x65: + return 234; + case 0x45: + return 202; + case 0x69: + return 238; + case 0x49: + return 206; + case 0x6f: + return 244; + case 0x4f: + return 212; + case 0x75: + return 251; + case 0x55: + return 219; + case 0x79: + return 375; + case 0x59: + return 374; + case 0x63: + return 265; + case 0x43: + return 264; + case 0x67: + return 285; + case 0x47: + return 284; + case 0x68: + return 293; + case 0x48: + return 292; + case 0x6a: + return 309; + case 0x4a: + return 308; + case 0x73: + return 349; + case 0x53: + return 348; + case 0x77: + return 373; + case 0x57: + return 372; + default: + return 0; + } + case 0xC4: // tilde + switch (c2) + { + case 0x61: + return 227; + case 0x41: + return 195; + case 0x6e: + return 241; + case 0x4e: + return 209; + case 0x69: + return 297; + case 0x49: + return 296; + case 0x6f: + return 245; + case 0x4f: + return 213; + case 0x75: + return 361; + case 0x55: + return 360; + default: + return 0; + } + case 0xC6: // breve + switch (c2) + { + case 0x61: + return 259; + case 0x41: + return 258; + case 0x67: + return 287; + case 0x47: + return 286; + case 0x75: + return 365; + case 0x55: + return 364; + default: + return 0; + } + case 0xC7: // dot above + switch (c2) + { + case 0x63: + return 267; + case 0x43: + return 266; + case 0x65: + return 279; + case 0x45: + return 278; + case 0x67: + return 289; + case 0x47: + return 288; + case 0x49: + return 304; + case 0x7a: + return 380; + case 0x5a: + return 379; + default: + return 0; + } + case 0xC8: // diaeresis + switch (c2) + { + case 0x61: + return 228; + case 0x41: + return 196; + case 0x65: + return 235; + case 0x45: + return 203; + case 0x69: + return 239; + case 0x49: + return 207; + case 0x6f: + return 246; + case 0x4f: + return 214; + case 0x75: + return 252; + case 0x55: + return 220; + case 0x79: + return 255; + case 0x59: + return 376; + default: + return 0; + } + case 0xCA: // ring above + switch (c2) + { + case 0x61: + return 229; + case 0x41: + return 197; + case 0x75: + return 367; + case 0x55: + return 366; + default: + return 0; + } + case 0xCB: // cedilla + switch (c2) + { + case 0x63: + return 231; + case 0x43: + return 199; + case 0x67: + return 291; + case 0x47: + return 290; + case 0x6b: + return 311; + case 0x4b: + return 310; + case 0x6c: + return 316; + case 0x4c: + return 315; + case 0x6e: + return 326; + case 0x4e: + return 325; + case 0x72: + return 343; + case 0x52: + return 342; + case 0x73: + return 351; + case 0x53: + return 350; + case 0x74: + return 355; + case 0x54: + return 354; + default: + return 0; + } + case 0xCD: // double acute accent + switch (c2) + { + case 0x6f: + return 337; + case 0x4f: + return 336; + case 0x75: + return 369; + case 0x55: + return 368; + default: + return 0; + } + case 0xCE: // ogonek + switch (c2) + { + case 0x61: + return 261; + case 0x41: + return 260; + case 0x65: + return 281; + case 0x45: + return 280; + case 0x69: + return 303; + case 0x49: + return 302; + case 0x75: + return 371; + case 0x55: + return 370; + default: + return 0; + } + case 0xCF: // caron + switch (c2) + { + case 0x63: + return 269; + case 0x43: + return 268; + case 0x64: + return 271; + case 0x44: + return 270; + case 0x65: + return 283; + case 0x45: + return 282; + case 0x6c: + return 318; + case 0x4c: + return 317; + case 0x6e: + return 328; + case 0x4e: + return 327; + case 0x72: + return 345; + case 0x52: + return 344; + case 0x73: + return 353; + case 0x53: + return 352; + case 0x74: + return 357; + case 0x54: + return 356; + case 0x7a: + return 382; + case 0x5a: + return 381; + default: + return 0; + } + } return 0; } @@ -325,8 +568,8 @@ static inline unsigned int recode(unsigned char d, int cp) return c885910[d-0xA0]; case 11:// 8859-11 -> unicode mapping return c885911[d-0xA0]; -/* case 12:// 8859-12 -> unicode mapping // reserved for indian use.. - return c885912[d-0xA0];*/ + /* case 12:// 8859-12 -> unicode mapping // reserved for indian use.. + return c885912[d-0xA0];*/ case 13:// 8859-13 -> unicode mapping return c885913[d-0xA0]; case 14:// 8859-14 -> unicode mapping @@ -360,48 +603,48 @@ std::string convertDVBUTF8(const char *data, int len, int table, int tsidonid) //printf("table %d tsidonid %04x twochar %d : %20s\n", table, tsidonid, twochar, data); switch(data[0]) { - case 1 ... 12: - newtable=data[i++]+4; + case 1 ... 12: + newtable=data[i++]+4; // eDebug("(1..12)text encoded in ISO-8859-%d",table); - break; - case 0x10: - { + break; + case 0x10: + { // eDebug("(0x10)text encoded in ISO-8859-%d",n); - int n=(data[i+1]<<8)|(data[i+2]); - i += 3; - switch(n) - { - case 12: - {} //eDebug("unsup. ISO8859-12 enc.", n); - default: - newtable=n; - break; - } + int n=(data[i+1]<<8)|(data[i+2]); + i += 3; + switch(n) + { + case 12: + {} //eDebug("unsup. ISO8859-12 enc.", n); + default: + newtable=n; break; } - case 0x11:// Basic Multilingual Plane of ISO/IEC 10646-1 enc (UTF-16... Unicode) - table = 65; - tsidonid = 0; - ++i; - break; - case 0x12: - ++i; - {} //eDebug("unsup. KSC 5601 enc."); - break; - case 0x13: - ++i; - {} //eDebug("unsup. GB-2312-1980 enc."); - break; - case 0x14: - ++i; - {} //eDebug("unsup. Big5 subset of ISO/IEC 10646-1 enc."); - break; - case 0x0: - case 0xD ... 0xF: - case 0x15 ... 0x1F: - {} //eDebug("reserved %d", data[0]); - ++i; - break; + break; + } + case 0x11:// Basic Multilingual Plane of ISO/IEC 10646-1 enc (UTF-16... Unicode) + table = 65; + tsidonid = 0; + ++i; + break; + case 0x12: + ++i; + {} //eDebug("unsup. KSC 5601 enc."); + break; + case 0x13: + ++i; + {} //eDebug("unsup. GB-2312-1980 enc."); + break; + case 0x14: + ++i; + {} //eDebug("unsup. Big5 subset of ISO/IEC 10646-1 enc."); + break; + case 0x0: + case 0xD ... 0xF: + case 0x15 ... 0x1F: + {} //eDebug("reserved %d", data[0]); + ++i; + break; } if(!table) table = newtable; @@ -428,11 +671,11 @@ std::string convertDVBUTF8(const char *data, int len, int table, int tsidonid) } if (!code) continue; - // Unicode->UTF8 encoding + // Unicode->UTF8 encoding if (code < 0x80) // identity ascii <-> utf8 mapping res[t++]=char(code); else if((table == 5) && (code == 0x8A)) - res[t++]= 0x20; + res[t++]= 0x20; else if ((code == 0x8A)) res[t++]= '\n'; // 0x8a is vertical tab. Just use newline for now. else if (code < 0x800) // two byte mapping @@ -468,7 +711,7 @@ eString convertUTF8DVB(const eString &string, int table) unsigned char buf[len]; - for(int i=0;iUTF8 encoding + // Unicode->UTF8 encoding if (code < 0x80) // identity latin <-> utf8 mapping res[t++]=char(code); else if (code < 0x800) // two byte mapping @@ -592,14 +835,14 @@ const std::string convertLatin1UTF8(const std::string &string) int isUTF8(const std::string &string) { unsigned int len=string.size(); - + for (unsigned int i=0; i < len; ++i) { if (!(string[i]&0x80)) // normal ASCII continue; if ((string[i] & 0xE0) == 0xC0) // one char following. { - // first, length check: + // first, length check: if (i+1 >= len) return 0; // certainly NOT utf-8 i++; diff --git a/src/sectionsd/epg.cpp b/src/sectionsd/epg.cpp index c7fdc5bcb..a3424a2e3 100644 --- a/src/sectionsd/epg.cpp +++ b/src/sectionsd/epg.cpp @@ -93,38 +93,38 @@ int main(int /*argc*/, char** /*argv*/) { - time_t starttime, endtime; - SIsectionsSDT sdtset; + time_t starttime, endtime; + SIsectionsSDT sdtset; #ifdef READ_PRESENT_INFOS - SIsectionsEIT epgset; + SIsectionsEIT epgset; #else - SIsectionsEITschedule epgset; + SIsectionsEITschedule epgset; #endif - tzset(); // TZ auswerten + tzset(); // TZ auswerten - starttime=time(NULL); - epgset.readSections(); - sdtset.readSections(); - endtime=time(NULL); - printf("EIT Sections read: %d\n", epgset.size()); - printf("SDT Sections read: %d\n", sdtset.size()); - printf("Time needed: %ds\n", (int)difftime(endtime, starttime)); + starttime=time(NULL); + epgset.readSections(); + sdtset.readSections(); + endtime=time(NULL); + printf("EIT Sections read: %d\n", epgset.size()); + printf("SDT Sections read: %d\n", sdtset.size()); + printf("Time needed: %ds\n", (int)difftime(endtime, starttime)); // for_each(epgset.begin(), epgset.end(), printSmallSectionHeader()); // for_each(epgset.begin(), epgset.end(), printSIsection()); - SIevents events; - for(SIsectionsEIT::iterator k=epgset.begin(); k!=epgset.end(); k++) - events.insert((k->events()).begin(), (k->events()).end()); + SIevents events; + for(SIsectionsEIT::iterator k=epgset.begin(); k!=epgset.end(); k++) + events.insert((k->events()).begin(), (k->events()).end()); - SIservices services; - for(SIsectionsSDT::iterator k=sdtset.begin(); k!=sdtset.end(); k++) - services.insert((k->services()).begin(), (k->services()).end()); + SIservices services; + for(SIsectionsSDT::iterator k=sdtset.begin(); k!=sdtset.end(); k++) + services.insert((k->services()).begin(), (k->services()).end()); - // Damit wir die Zeiten der nvods richtig einsortiert bekommen - // Ist bei epgLarge eigentlich nicht noetig, da die NVODs anscheinend nur im present/actual (epgSmall) vorkommen - events.mergeAndRemoveTimeShiftedEvents(services); + // Damit wir die Zeiten der nvods richtig einsortiert bekommen + // Ist bei epgLarge eigentlich nicht noetig, da die NVODs anscheinend nur im present/actual (epgSmall) vorkommen + events.mergeAndRemoveTimeShiftedEvents(services); - for_each(events.begin(), events.end(), printSIeventWithService(services)); + for_each(events.begin(), events.end(), printSIeventWithService(services)); // for_each(events.begin(), events.end(), printSIevent()); // for_each(epgset.begin(), epgset.end(), printSIsectionEIT()); @@ -134,5 +134,5 @@ int main(int /*argc*/, char** /*argv*/) // sprintf(fname, "seit%d", i+1); // s->saveBufferToFile(fname); // } - return 0; + return 0; } diff --git a/src/sectionsd/epgMini.cpp b/src/sectionsd/epgMini.cpp index 179c5dcb5..c48c3f7a8 100644 --- a/src/sectionsd/epgMini.cpp +++ b/src/sectionsd/epgMini.cpp @@ -47,40 +47,40 @@ int main(int argc, char **argv) { - SIsectionsSDT sdtset; + SIsectionsSDT sdtset; - if(argc!=2) { - fprintf(stderr, "Aufruf: %s Sendername\n", argv[0]); - return 1; - } + if(argc!=2) { + fprintf(stderr, "Aufruf: %s Sendername\n", argv[0]); + return 1; + } - tzset(); // TZ auswerten + tzset(); // TZ auswerten - sdtset.readSections(); + sdtset.readSections(); - // Die for-Schleifen sind laestig, - // Evtl. sollte man aus den sets maps machen, damit man den key einfacher aendern - // kann und somit find() funktioniert - for(SIsectionsSDT::iterator k=sdtset.begin(); k!=sdtset.end(); k++) - for(SIservices::iterator ks=k->services().begin(); ks!=k->services().end(); ks++) { - // Erst mal die Controlcodes entfernen + // Die for-Schleifen sind laestig, + // Evtl. sollte man aus den sets maps machen, damit man den key einfacher aendern + // kann und somit find() funktioniert + for(SIsectionsSDT::iterator k=sdtset.begin(); k!=sdtset.end(); k++) + for(SIservices::iterator ks=k->services().begin(); ks!=k->services().end(); ks++) { + // Erst mal die Controlcodes entfernen // printf("Servicename: '%s'\n", ks->serviceName.c_str()); - char servicename[50]; - strncpy(servicename, ks->serviceName.c_str(), sizeof(servicename)-1); - servicename[sizeof(servicename)-1]=0; - removeControlCodes(servicename); - // Jetz pruefen ob der Servicename der gewuenschte ist + char servicename[50]; + strncpy(servicename, ks->serviceName.c_str(), sizeof(servicename)-1); + servicename[sizeof(servicename)-1]=0; + removeControlCodes(servicename); + // Jetz pruefen ob der Servicename der gewuenschte ist // printf("Servicename: '%s'\n", servicename); - if(!strcmp(servicename, argv[1])) { - // Event (serviceid) suchen - SIevent evt=SIevent::readActualEvent(ks->service_id); - if(evt.service_id != 0) - evt.saveXML(stdout); // gefunden + if(!strcmp(servicename, argv[1])) { + // Event (serviceid) suchen + SIevent evt=SIevent::readActualEvent(ks->service_id); + if(evt.service_id != 0) + evt.saveXML(stdout); // gefunden // evt.dump(); // gefunden - else - printf("Kein aktuelles EPG fuer %s gefunden!\n", argv[1]); - return 0; - } - } - return 1; + else + printf("Kein aktuelles EPG fuer %s gefunden!\n", argv[1]); + return 0; + } + } + return 1; } diff --git a/src/sectionsd/nit.cpp b/src/sectionsd/nit.cpp index d26e3cd70..05b0cd74a 100644 --- a/src/sectionsd/nit.cpp +++ b/src/sectionsd/nit.cpp @@ -61,16 +61,16 @@ int main(int /*argc*/, char** /*argv*/) { - time_t starttime, endtime; - SIsectionsNIT nitset; + time_t starttime, endtime; + SIsectionsNIT nitset; - starttime=time(NULL); - nitset.readSections(); - endtime=time(NULL); - printf("Sections read: %d\n", nitset.size()); - printf("Time needed: %ds\n", (int)difftime(endtime, starttime)); + starttime=time(NULL); + nitset.readSections(); + endtime=time(NULL); + printf("Sections read: %d\n", nitset.size()); + printf("Time needed: %ds\n", (int)difftime(endtime, starttime)); // for_each(nitset.begin(), nitset.end(), printSmallSectionHeader()); // for_each(nitset.begin(), nitset.end(), printSIsection()); - for_each(nitset.begin(), nitset.end(), printSIsectionNIT()); - return 0; + for_each(nitset.begin(), nitset.end(), printSIsectionNIT()); + return 0; } diff --git a/src/sectionsd/sdt.cpp b/src/sectionsd/sdt.cpp index 88beccff7..a09deb059 100644 --- a/src/sectionsd/sdt.cpp +++ b/src/sectionsd/sdt.cpp @@ -70,16 +70,16 @@ int main(int /*argc*/, char** /*argv*/) { - time_t starttime, endtime; - SIsectionsSDT sdtset; + time_t starttime, endtime; + SIsectionsSDT sdtset; - starttime=time(NULL); - sdtset.readSections(); - endtime=time(NULL); - printf("Sections read: %d\n", sdtset.size()); - printf("Time needed: %ds\n", (int)difftime(endtime, starttime)); + starttime=time(NULL); + sdtset.readSections(); + endtime=time(NULL); + printf("Sections read: %d\n", sdtset.size()); + printf("Time needed: %ds\n", (int)difftime(endtime, starttime)); // for_each(sdtset.begin(), sdtset.end(), printSmallSectionHeader()); // for_each(sdtset.begin(), sdtset.end(), printSIsection()); - for_each(sdtset.begin(), sdtset.end(), printSIsectionSDT()); - return 0; + for_each(sdtset.begin(), sdtset.end(), printSIsectionSDT()); + return 0; } diff --git a/src/sectionsd/sectionsd.cpp b/src/sectionsd/sectionsd.cpp index 78ffa9015..8571e68f7 100644 --- a/src/sectionsd/sectionsd.cpp +++ b/src/sectionsd/sectionsd.cpp @@ -1,9626 +1,9627 @@ -// -// $Id: sectionsd.cpp,v 1.305 2009/07/30 12:41:39 seife Exp $ -// -// sectionsd.cpp (network daemon for SI-sections) -// (dbox-II-project) -// -// Copyright (C) 2001 by fnbrd -// -// Homepage: http://dbox2.elxsi.de -// -// Copyright (C) 2008, 2009 Stefan Seyfried -// -// This program 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 of the License, or -// (at your option) any later version. -// -// This program 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 this program; if not, write to the Free Software -// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -// -// -// - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -//#include // getrusage -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include -//#include -#include - -// Daher nehmen wir SmartPointers aus der Boost-Lib (www.boost.org) -#include - -#include -#include -#include -#include - -#include "SIutils.hpp" -#include "SIservices.hpp" -#include "SIevents.hpp" -#ifdef UPDATE_NETWORKS -#include "SIbouquets.hpp" -#include "SInetworks.hpp" -#endif -#include "SIsections.hpp" -#include "SIlanguage.hpp" - -#include "edvbstring.h" -//#include "timerdclient.h" -//#include "../timermanager.h" - -// 60 Minuten Zyklus... -#define TIME_EIT_SCHEDULED_PAUSE 60 * 60 -// -- 5 Minutes max. pause should improve behavior (rasc, 2005-05-02) -// #define TIME_EIT_SCHEDULED_PAUSE 5* 60 -// Zeit die fuer die gewartet wird, bevor der Filter weitergeschaltet wird, falls es automatisch nicht klappt -#define TIME_EIT_SKIPPING 90 - -#ifdef ENABLE_FREESATEPG -// a little more time for freesat epg -#define TIME_FSEIT_SKIPPING 240 -#endif - -static bool reader_ready = true; -//#define MAX_EVENTS 6000 -static unsigned int max_events; -// sleep 5 minutes -//#define HOUSEKEEPING_SLEEP (30 * 60) -#define HOUSEKEEPING_SLEEP (5 * 60) -// meta housekeeping after XX housekeepings - every 24h - -#define META_HOUSEKEEPING (24 * 60 * 60) / HOUSEKEEPING_SLEEP - -// 12h Pause fr SDT -//#define TIME_SDT_SCHEDULED_PAUSE 12* 60* 60 -// -- shorter time for pause should result in better behavior (rasc, 2005-05-02) -#define TIME_SDT_SCHEDULED_PAUSE 2* 60* 60 -//#define TIME_SDT_SKIPPING 30 -//We are very nice here. Start scanning for channels, if the user stays for XX secs on that channel -//#define TIME_SDT_BACKOFF 120 -//Sleeping when TIME_SDT_NODATA seconds no NEW section was received -#define TIME_SDT_NONEWDATA 5 -//How many BATs shall we read per transponder -#define MAX_BAT 10 -//How many other SDTs shall we puzzle per transponder at the same time -//#define MAX_CONCURRENT_OTHER_SDT 5 -//How many other SDTs shall we assume per tranponder -//#define MAX_OTHER_SDT 70 -#define MAX_SDTs 70 -//How many sections can a table consist off? -#define MAX_SECTIONS 0x1f -//Okay, since zapit has got nothing do to with scanning - we read it on our own -#define NEUTRINO_SCAN_SETTINGS_FILE CONFIGDIR "/scan.conf" - -//Set pause for NIT -#define TIME_NIT_SCHEDULED_PAUSE 2* 60* 60 -//We are very nice here. Start scanning for channels, if the user stays for XX secs on that channel -//#define TIME_NIT_BACKOFF 20 -//Sleeping when TIME_NIT_NODATA seconds no NEW section was received -#define TIME_NIT_NONEWDATA 5 -//How many other NITs shall we puzzle per transponder at the same time -//#define MAX_CONCURRENT_OTHER_NIT 5 -//How many other SDTs shall we assume per tranponder -//#define MAX_OTHER_NIT 10 -#define MAX_NIDs 10 - -// Timeout bei tcp/ip connections in ms -#define READ_TIMEOUT_IN_SECONDS 2 -#define WRITE_TIMEOUT_IN_SECONDS 2 - -// Gibt die Anzahl Timeouts an, nach der die Verbindung zum DMX neu gestartet wird (wegen evtl. buffer overflow) -// for NIT and SDT threads... -#define RESTART_DMX_AFTER_TIMEOUTS 5 - -// Timeout in ms for reading from dmx in EIT threads. Dont make this too long -// since we are holding the start_stop lock during this read! -#define EIT_READ_TIMEOUT 100 -// Number of DMX read timeouts, after which we check if there is an EIT at all -// for EIT and PPT threads... -#define CHECK_RESTART_DMX_AFTER_TIMEOUTS (2000 / EIT_READ_TIMEOUT) // 2 seconds - -// Time in seconds we are waiting for an EIT version number -#define TIME_EIT_VERSION_WAIT 3 -// number of timeouts after which we stop waiting for an EIT version number -#define TIMEOUTS_EIT_VERSION_WAIT (2 * CHECK_RESTART_DMX_AFTER_TIMEOUTS) - -// the maximum length of a section (0x0fff) + header (3) -#define MAX_SECTION_LENGTH (0x0fff + 3) - -// Wieviele Sekunden EPG gecached werden sollen -//static long secondsToCache=4*24*60L*60L; // 4 Tage - weniger Prozessorlast?! -//static long secondsToCache = 14*24*60L*60L; // 14 Tage - Prozessorlast <3% (rasc) -static long secondsToCache; -static long secondsExtendedTextCache; -// Ab wann ein Event als alt gilt (in Sekunden) -//static long oldEventsAre = 60*60L; // 2h (sometimes want to know something about current/last movie) -static long oldEventsAre; -static int scanning = 1; - -std::string epg_filter_dir = "/var/tuxbox/config/zapit/epgfilter.xml"; -static bool epg_filter_is_whitelist = false; -static bool epg_filter_except_current_next = false; -// static bool bouquet_filter_is_whitelist = false; -static bool messaging_zap_detected = false; - -std::string dvbtime_filter_dir = "/var/tuxbox/config/zapit/dvbtimefilter.xml"; -static bool dvb_time_update = false; - -//NTP- Config -#define CONF_FILE "/var/tuxbox/config/neutrino.conf" -//const std::string ntp_system_cmd_prefix = "/sbin/rdate -s "; -const std::string ntp_system_cmd_prefix = "/sbin/ntpdate "; -std::string ntp_system_cmd; -CConfigFile ntp_config(','); -std::string ntpserver; -int ntprefresh; -int ntpenable; - -static int eit_update_fd = -1; -static bool update_eit = true; - -/* messaging_current_servicekey does probably not need locking, since it is - changed from one place */ -static t_channel_id messaging_current_servicekey = 0; -static bool channel_is_blacklisted = false; -// EVENTS... - -static CEventServer *eventServer; -//CTimerdClient *timerdClient; -//bool timerd = false; - -static pthread_rwlock_t eventsLock = PTHREAD_RWLOCK_INITIALIZER; // Unsere (fast-)mutex, damit nicht gleichzeitig in die Menge events geschrieben und gelesen wird -static pthread_rwlock_t servicesLock = PTHREAD_RWLOCK_INITIALIZER; // Unsere (fast-)mutex, damit nicht gleichzeitig in die Menge services geschrieben und gelesen wird -static pthread_rwlock_t transpondersLock = PTHREAD_RWLOCK_INITIALIZER; // Unsere (fast-)mutex, damit nicht gleichzeitig in die Menge transponders geschrieben und gelesen wird -static pthread_rwlock_t bouquetsLock = PTHREAD_RWLOCK_INITIALIZER; // Unsere (fast-)mutex, damit nicht gleichzeitig in die Menge bouquets geschrieben und gelesen wird -static pthread_rwlock_t messagingLock = PTHREAD_RWLOCK_INITIALIZER; - -static pthread_cond_t timeThreadSleepCond = PTHREAD_COND_INITIALIZER; -static pthread_mutex_t timeThreadSleepMutex = PTHREAD_MUTEX_INITIALIZER; - -// k.A. ob volatile im Kampf gegen Bugs trotz mutex's was bringt, -// falsch ist es zumindest nicht -/* -static DMX dmxEIT(0x12, 0x4f, (0xff- 0x01), 0x50, (0xff- 0x0f), 256); -static DMX dmxSDT(0x11, 0x42, 0xff, 0x42, 0xff, 256); -*/ -// Houdini: changed sizes, EIT thread no more receives POLLER, saves some mem in sdt -//static DMX dmxEIT(0x12, 256); -//static DMX dmxSDT(0x11, 256); -/* no matter how big the buffer, we will receive spurious POLLERR's in table 0x60, - but those are not a big deal, so let's save some memory */ -static DMX dmxEIT(0x12, 3000 /*320*/); -#ifdef ENABLE_FREESATEPG -static DMX dmxFSEIT(3842, 320); -#endif -static DMX dmxCN(0x12, 512, false, 1); -#ifdef UPDATE_NETWORKS -static DMX dmxSDT(0x11, 512, true, 1); -static DMX dmxNIT(0x10, 128); -#endif -#ifdef ENABLE_PPT -// Houdini: added for Premiere Private EPG section for Sport/Direkt Portal -static DMX dmxPPT(0x00, 256); -unsigned int privatePid=0; -#endif -int sectionsd_stop = 0; - -static bool slow_addevent = true; - -inline void readLockServices(void) -{ - pthread_rwlock_rdlock(&servicesLock); -} - -inline void writeLockServices(void) -{ - pthread_rwlock_wrlock(&servicesLock); -} - -inline void unlockServices(void) -{ - pthread_rwlock_unlock(&servicesLock); -} - -inline void readLockMessaging(void) -{ - pthread_rwlock_rdlock(&messagingLock); -} - -inline void writeLockMessaging(void) -{ - pthread_rwlock_wrlock(&messagingLock); -} - -inline void unlockMessaging(void) -{ - pthread_rwlock_unlock(&messagingLock); -} - -inline void readLockEvents(void) -{ - pthread_rwlock_rdlock(&eventsLock); -} - -inline void writeLockEvents(void) -{ - pthread_rwlock_wrlock(&eventsLock); -} - -inline void unlockEvents(void) -{ - pthread_rwlock_unlock(&eventsLock); -} - -inline void readLockTransponders(void) -{ - pthread_rwlock_rdlock(&transpondersLock); -} - -inline void writeLockTransponders(void) -{ - pthread_rwlock_wrlock(&transpondersLock); -} - -inline void unlockTransponders(void) -{ - pthread_rwlock_unlock(&transpondersLock); -} - -inline void readLockBouquets(void) -{ - pthread_rwlock_rdlock(&bouquetsLock); -} - -inline void writeLockBouquets(void) -{ - pthread_rwlock_wrlock(&bouquetsLock); -} - -inline void unlockBouquets(void) -{ - pthread_rwlock_unlock(&bouquetsLock); -} - -#if 0 -/* access to the data structures is protected by locks anyway, so there is no - reason to pause the EITThreads anymore for the sake of locking. It was not - used otherwise at all anyway and it did not work correctly since quite some - time. - To be removed, just kept for reference. 10.2008-seife */ -inline int EITThreadsPause(void) -{ - return( dmxEIT.pause() || - dmxCN.pause() || -#ifdef ENABLE_FREESATEPG - dmxFSEIT.pause() || -#endif - dmxPPT.pause()); -} - -inline int EITThreadsUnPause(void) -{ - return( dmxCN.unpause() || - dmxEIT.unpause() || -#ifdef ENABLE_FREESATEPG - dmxFSEIT.unpause() || -#endif - dmxPPT.unpause()); -} -#endif - -bool timeset = false; -bool bTimeCorrect = false; -pthread_cond_t timeIsSetCond = PTHREAD_COND_INITIALIZER; -pthread_mutex_t timeIsSetMutex = PTHREAD_MUTEX_INITIALIZER; - -//static bool messaging_wants_current_next_Event = false; -//static bool messaging_got_current = false; -//static bool messaging_got_next = false; -static int messaging_have_CN = 0x00; // 0x01 = CURRENT, 0x02 = NEXT -static int messaging_got_CN = 0x00; // 0x01 = CURRENT, 0x02 = NEXT -static time_t messaging_last_requested = time_monotonic(); -static bool messaging_neutrino_sets_time = false; -//static bool messaging_WaitForServiceDesc = false; - -inline bool waitForTimeset(void) -{ - pthread_mutex_lock(&timeIsSetMutex); - while(!timeset) - pthread_cond_wait(&timeIsSetCond, &timeIsSetMutex); - pthread_mutex_unlock(&timeIsSetMutex); - /* we have time synchronization issues, at least on kernel 2.4, so - sometimes the time in the threads is still 1.1.1970, even after - waitForTimeset() returns. Let's hope that we work around this issue - with this sleep */ - sleep(1); - writeLockMessaging(); - messaging_last_requested = time_monotonic(); - unlockMessaging(); - return true; -} - -static int64_t last_profile_call; - -void showProfiling( std::string text ) -{ - struct timeval tv; - - gettimeofday( &tv, NULL ); - int64_t now = (int64_t) tv.tv_usec + (int64_t)((int64_t) tv.tv_sec * (int64_t) 1000000); - - int64_t tmp = now - last_profile_call; - dprintf("--> '%s' %lld.%03lld\n", text.c_str(), tmp / 1000LL, tmp % 1000LL); - last_profile_call = now; -} - -static const SIevent nullEvt; // Null-Event - -//------------------------------------------------------------ -// Wir verwalten die events in SmartPointers -// und nutzen verschieden sortierte Menge zum Zugriff -//------------------------------------------------------------ - -// SmartPointer auf SIevent -//typedef Loki::SmartPtr -// SIeventPtr; -typedef boost::shared_ptr -SIeventPtr; - -typedef std::map > MySIeventsOrderUniqueKey; -static MySIeventsOrderUniqueKey mySIeventsOrderUniqueKey; -static SIevent * myCurrentEvent = NULL; -static SIevent * myNextEvent = NULL; - -// Mengen mit SIeventPtr sortiert nach Event-ID fuer NVOD-Events (mehrere Zeiten) -static MySIeventsOrderUniqueKey mySIeventsNVODorderUniqueKey; - -struct OrderServiceUniqueKeyFirstStartTimeEventUniqueKey -{ - bool operator()(const SIeventPtr &p1, const SIeventPtr &p2) - { - return - (p1->get_channel_id() == p2->get_channel_id()) ? - (p1->times.begin()->startzeit == p2->times.begin()->startzeit ? p1->eventID < p2->eventID : p1->times.begin()->startzeit < p2->times.begin()->startzeit ) - : - (p1->get_channel_id() < p2->get_channel_id()); - } -}; - -typedef std::set MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey; -static MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey; - -struct OrderFirstEndTimeServiceIDEventUniqueKey -{ - bool operator()(const SIeventPtr &p1, const SIeventPtr &p2) - { - return - p1->times.begin()->startzeit + (long)p1->times.begin()->dauer == p2->times.begin()->startzeit + (long)p2->times.begin()->dauer ? - // ( p1->serviceID == p2->serviceID ? p1->uniqueKey() < p2->uniqueKey() : p1->serviceID < p2->serviceID ) - (p1->service_id == p2->service_id ? p1->uniqueKey() > p2->uniqueKey() : p1->service_id < p2->service_id) - : - ( p1->times.begin()->startzeit + (long)p1->times.begin()->dauer < p2->times.begin()->startzeit + (long)p2->times.begin()->dauer ) ; - } -}; - -typedef std::set MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey; -static MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey; - -// Hier landen alle Service-Ids von Meta-Events inkl. der zugehoerigen Event-ID (nvod) -// d.h. key ist der Unique Service-Key des Meta-Events und Data ist der unique Event-Key -typedef std::map > MySIeventUniqueKeysMetaOrderServiceUniqueKey; -static MySIeventUniqueKeysMetaOrderServiceUniqueKey mySIeventUniqueKeysMetaOrderServiceUniqueKey; - -/* -class NvodSubEvent { - public: - NvodSubEvent() { - uniqueServiceID=0; - uniqueEventID=0; - } - NvodSubEvent(const NvodSubEvent &n) { - uniqueServiceID=n.uniqueServiceID; - uniqueEventID=n.uniqueEventID; - } - t_channel_id uniqueServiceID; - event_id_t uniqueMetaEventID; // ID des Meta-Events - event_id_t uniqueMetaEventID; // ID des eigentlichen Events -}; - -// Menge sortiert nach Meta-ServiceIDs (NVODs) -typedef std::multimap > nvodSubEvents; -*/ - -struct EPGFilter -{ - t_original_network_id onid; - t_transport_stream_id tsid; - t_service_id sid; - EPGFilter *next; -}; - -struct ChannelBlacklist -{ - t_channel_id chan; - t_channel_id mask; - ChannelBlacklist *next; -}; - -struct ChannelNoDVBTimelist -{ - t_channel_id chan; - t_channel_id mask; - ChannelNoDVBTimelist *next; -}; - -EPGFilter *CurrentEPGFilter = NULL; -ChannelBlacklist *CurrentBlacklist = NULL; -ChannelNoDVBTimelist *CurrentNoDVBTime = NULL; - -static bool checkEPGFilter(t_original_network_id onid, t_transport_stream_id tsid, t_service_id sid) -{ - EPGFilter *filterptr = CurrentEPGFilter; - while (filterptr) - { - if (((filterptr->onid == onid) || (filterptr->onid == 0)) && - ((filterptr->tsid == tsid) || (filterptr->tsid == 0)) && - ((filterptr->sid == sid) || (filterptr->sid == 0))) - return true; - filterptr = filterptr->next; - } - return false; -} - -static bool checkBlacklist(t_channel_id channel_id) -{ - ChannelBlacklist *blptr = CurrentBlacklist; - while (blptr) - { - if (blptr->chan == (channel_id & blptr->mask)) - return true; - blptr = blptr->next; - } - return false; -} - -static bool checkNoDVBTimelist(t_channel_id channel_id) -{ - ChannelNoDVBTimelist *blptr = CurrentNoDVBTime; - while (blptr) - { - if (blptr->chan == (channel_id & blptr->mask)) - return true; - blptr = blptr->next; - } - return false; -} - -static void addEPGFilter(t_original_network_id onid, t_transport_stream_id tsid, t_service_id sid) -{ - if (!checkEPGFilter(onid, tsid, sid)) - { - dprintf("Add EPGFilter for onid=\"%04x\" tsid=\"%04x\" service_id=\"%04x\"\n", onid, tsid, sid); - EPGFilter *node = new EPGFilter; - node->onid = onid; - node->tsid = tsid; - node->sid = sid; - node->next = CurrentEPGFilter; - CurrentEPGFilter = node; - } -} - -static void addBlacklist(t_original_network_id onid, t_transport_stream_id tsid, t_service_id sid) -{ - t_channel_id channel_id = - CREATE_CHANNEL_ID_FROM_SERVICE_ORIGINALNETWORK_TRANSPORTSTREAM_ID(sid, onid, tsid); - t_channel_id mask = - CREATE_CHANNEL_ID_FROM_SERVICE_ORIGINALNETWORK_TRANSPORTSTREAM_ID( - (sid ? 0xFFFF : 0), (onid ? 0xFFFF : 0), (tsid ? 0xFFFF : 0) - ); - if (!checkBlacklist(channel_id)) - { - xprintf("Add Channel Blacklist for channel 0x%012llx, mask 0x%012llx\n", channel_id, mask); - ChannelBlacklist *node = new ChannelBlacklist; - node->chan = channel_id; - node->mask = mask; - node->next = CurrentBlacklist; - CurrentBlacklist = node; - } -} - -static void addNoDVBTimelist(t_original_network_id onid, t_transport_stream_id tsid, t_service_id sid) -{ - t_channel_id channel_id = - CREATE_CHANNEL_ID_FROM_SERVICE_ORIGINALNETWORK_TRANSPORTSTREAM_ID(sid, onid, tsid); - t_channel_id mask = - CREATE_CHANNEL_ID_FROM_SERVICE_ORIGINALNETWORK_TRANSPORTSTREAM_ID( - (sid ? 0xFFFF : 0), (onid ? 0xFFFF : 0), (tsid ? 0xFFFF : 0) - ); - if (!checkNoDVBTimelist(channel_id)) - { - xprintf("Add channel 0x%012llx, mask 0x%012llx to NoDVBTimelist\n", channel_id, mask); - ChannelNoDVBTimelist *node = new ChannelNoDVBTimelist; - node->chan = channel_id; - node->mask = mask; - node->next = CurrentNoDVBTime; - CurrentNoDVBTime = node; - } -} - -#if 0 -static void removeEPGFilter(t_original_network_id onid, t_transport_stream_id tsid, t_service_id sid) -{ - -} - -struct ExceptService -{ - t_service_id sid; - ExceptService *next; -}; - -struct BouquetAdderEntry -{ -#define MAX_SIZE_MYBOUQUETS_STR 50 - char ProviderName[MAX_SIZE_MYBOUQUETS_STR]; - t_original_network_id onid; - t_transport_stream_id tsid; - ExceptService *es; - BouquetAdderEntry *next; -}; - -struct BouquetAdder -{ - char BouquetName[MAX_SIZE_MYBOUQUETS_STR]; - t_bouquet_id bid; - BouquetAdderEntry *bae; - BouquetAdder *next; -}; - -struct BouquetFilter -{ - t_bouquet_id bid; - BouquetFilter *next; -}; - -BouquetFilter *CurrentBouquetFilter = NULL; -BouquetAdder *CurrentBouquetAdder = NULL; - -static bool checkBouquetFilter(t_bouquet_id bid) -{ - BouquetFilter *filterptr = CurrentBouquetFilter; - while (filterptr) - { - if ((filterptr->bid == bid) || (filterptr->bid == 0)) - return true; - filterptr = filterptr->next; - } - return false; -} - -static void addBouquetFilter(t_bouquet_id bid) -{ - if (!checkBouquetFilter(bid)) - { - dprintf("Add Bouquet Filter for bouquet_id=\"%04x\"\n", bid); - BouquetFilter *node = new BouquetFilter; - node->bid = bid; - node->next = CurrentBouquetFilter; - CurrentBouquetFilter = node; - } -} -#endif - -// Loescht ein Event aus allen Mengen -static bool deleteEvent(const event_id_t uniqueKey) -{ - writeLockEvents(); - MySIeventsOrderUniqueKey::iterator e = mySIeventsOrderUniqueKey.find(uniqueKey); - - if (e != mySIeventsOrderUniqueKey.end()) - { - if (e->second->times.size()) - { - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.erase(e->second); - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.erase(e->second); - } - - mySIeventsOrderUniqueKey.erase(uniqueKey); - mySIeventsNVODorderUniqueKey.erase(uniqueKey); - -// printf("Deleting: %04x\n", (int) uniqueKey); - unlockEvents(); - return true; - } - else - { - unlockEvents(); - return false; - } - - /* - for(MySIeventIDsMetaOrderServiceID::iterator i=mySIeventIDsMetaOrderServiceID.begin(); i!=mySIeventIDsMetaOrderServiceID.end(); i++) - if(i->second==eventID) - mySIeventIDsMetaOrderServiceID.erase(i); - */ -} - -// Fuegt ein Event in alle Mengen ein -/* if cn == true (if called by cnThread), then myCurrentEvent and myNextEvent is updated, too */ -static void addEvent(const SIevent &evt, const unsigned table_id, const time_t zeit, bool cn = false) -{ - bool EPG_filtered = checkEPGFilter(evt.original_network_id, evt.transport_stream_id, evt.service_id); - - /* more readable in "plain english": - if current/next are not to be filtered and table_id is current/next -> continue - else { - if epg filter is blacklist and filter matched -> stop. (return) - if epg filter is whitelist and filter did not match -> stop also. - } - */ - if (!(epg_filter_except_current_next && (table_id == 0x4e || table_id == 0x4f)) && - (table_id != 0)) { - if (!epg_filter_is_whitelist && EPG_filtered) { - //dprintf("addEvent: blacklist and filter did match\n"); - return; - } - if (epg_filter_is_whitelist && !EPG_filtered) { - //dprintf("addEvent: whitelist and filter did not match\n"); - return; - } - } - - if (cn) { // current-next => fill current or next event... - readLockMessaging(); - if (evt.get_channel_id() == messaging_current_servicekey && // but only if it is the current channel... - (messaging_got_CN != 0x03)) { // ...and if we don't have them already. - unlockMessaging(); - SIevent *eptr = new SIevent(evt); - if (!eptr) - { - printf("[sectionsd::addEvent] new SIevent1 failed.\n"); - return; - //throw std::bad_alloc(); - } - - SIeventPtr e(eptr); - - writeLockEvents(); - if (e->runningStatus() > 2) { // paused or currently running - if (!myCurrentEvent || (myCurrentEvent && (*myCurrentEvent).uniqueKey() != e->uniqueKey())) { - if (myCurrentEvent) - delete myCurrentEvent; - myCurrentEvent = new SIevent(evt); - writeLockMessaging(); - messaging_got_CN |= 0x01; - if (myNextEvent && (*myNextEvent).uniqueKey() == e->uniqueKey()) { - dprintf("addevent-cn: removing next-event\n"); - /* next got "promoted" to current => trigger re-read */ - delete myNextEvent; - myNextEvent = NULL; - messaging_got_CN &= 0x01; - } - unlockMessaging(); - dprintf("addevent-cn: added running (%d) event 0x%04x '%s'\n", - e->runningStatus(), e->eventID, e->getName().c_str()); - } else { - writeLockMessaging(); - messaging_got_CN |= 0x01; - unlockMessaging(); - dprintf("addevent-cn: not add runn. (%d) event 0x%04x '%s'\n", - e->runningStatus(), e->eventID, e->getName().c_str()); - } - } else { - if ((!myNextEvent || (myNextEvent && (*myNextEvent).uniqueKey() != e->uniqueKey() && (*myNextEvent).times.begin()->startzeit < e->times.begin()->startzeit)) && - (!myCurrentEvent || (myCurrentEvent && (*myCurrentEvent).uniqueKey() != e->uniqueKey()))) { - if (myNextEvent) - delete myNextEvent; - myNextEvent = new SIevent(evt); - writeLockMessaging(); - messaging_got_CN |= 0x02; - unlockMessaging(); - dprintf("addevent-cn: added next (%d) event 0x%04x '%s'\n", - e->runningStatus(), e->eventID, e->getName().c_str()); - } else { - dprintf("addevent-cn: not added next(%d) event 0x%04x '%s'\n", - e->runningStatus(), e->eventID, e->getName().c_str()); - writeLockMessaging(); - messaging_got_CN |= 0x02; - unlockMessaging(); - } - } - unlockEvents(); - } else - unlockMessaging(); - } - - readLockEvents(); - MySIeventsOrderUniqueKey::iterator si = mySIeventsOrderUniqueKey.find(evt.uniqueKey()); - bool already_exists = (si != mySIeventsOrderUniqueKey.end()); - if (already_exists && (evt.table_id < si->second->table_id)) - { - /* if the new event has a lower (== more recent) table ID, replace the old one */ - already_exists = false; - dprintf("replacing event %016llx:%02x with %04x:%02x '%.40s'\n", si->second->uniqueKey(), - si->second->table_id, evt.eventID, evt.table_id, evt.getName().c_str()); - } - else if (already_exists && ( (evt.table_id == 0x51 || evt.table_id == 0x50 || evt.table_id == 0x4e) && evt.table_id == si->second->table_id && evt.version != si->second->version )) - { - //replace event if new version - dprintf("replacing event version old 0x%02x new 0x%02x'\n", si->second->version, evt.version ); - already_exists = false; - } - - /* Check size of some descriptors of the new event before comparing - them with the old ones, because the same event can be complete - on one German Sky channel and incomplete on another one. So we - make sure to keep the complete event, if applicable. */ - - if ((already_exists) && (evt.components.size() > 0)) { - if (si->second->components.size() != evt.components.size()) - already_exists = false; - else { - SIcomponents::iterator c1 = si->second->components.begin(); - SIcomponents::iterator c2 = evt.components.begin(); - while ((c1 != si->second->components.end()) && (c2 != evt.components.end())) { - if ((c1->componentType != c2->componentType) || - (c1->componentTag != c2->componentTag) || - (c1->streamContent != c2->streamContent) || - (strcmp(c1->component.c_str(),c2->component.c_str()) != 0)){ - already_exists = false; - break; - } - c1++; - c2++; - } - } - } - - if ((already_exists) && (evt.linkage_descs.size() > 0)) { - if (si->second->linkage_descs.size() != evt.linkage_descs.size()) - already_exists = false; - else { - for (unsigned int i = 0; i < si->second->linkage_descs.size(); i++) { - if ((si->second->linkage_descs[i].linkageType != - evt.linkage_descs[i].linkageType) || - (si->second->linkage_descs[i].originalNetworkId != - evt.linkage_descs[i].originalNetworkId) || - (si->second->linkage_descs[i].transportStreamId != - evt.linkage_descs[i].transportStreamId) || - (strcmp(si->second->linkage_descs[i].name.c_str(), - evt.linkage_descs[i].name.c_str()) != 0)) { - already_exists = false; - break; - } - } - } - } - - if ((already_exists) && (evt.ratings.size() > 0)) { - if (si->second->ratings.size() != evt.ratings.size()) - already_exists = false; - else { - SIparentalRatings::iterator p1 = si->second->ratings.begin(); - SIparentalRatings::iterator p2 = evt.ratings.begin(); - while ((p1 != si->second->ratings.end()) && (p2 != evt.ratings.end())) { - if ((p1->rating != p2->rating) || - (strcmp(p1->countryCode.c_str(),p2->countryCode.c_str()) != 0)) { - already_exists = false; - break; - } - p1++; - p2++; - } - } - } - - if (already_exists) { - if (si->second->times.size() != evt.times.size()) - already_exists = false; - else { - SItimes::iterator t1 = si->second->times.begin(); - SItimes::iterator t2 = evt.times.begin(); - while ((t1 != si->second->times.end()) && (t2 != evt.times.end())) { - if ((t1->startzeit != t2->startzeit) || - (t1->dauer != t2->dauer)) { - already_exists = false; - break; - } - t1++; - t2++; - } - } - } - - if ((already_exists) && (SIlanguage::getMode() == CSectionsdClient::LANGUAGE_MODE_OFF)) { - si->second->contentClassification = evt.contentClassification; - si->second->userClassification = evt.userClassification; - si->second->vps = evt.vps; - if ((evt.getExtendedText().length() > 0) && - (evt.times.begin()->startzeit < zeit + secondsExtendedTextCache)) - si->second->setExtendedText("OFF",evt.getExtendedText().c_str()); - if (evt.getText().length() > 0) - si->second->setText("OFF",evt.getText().c_str()); - if (evt.getName().length() > 0) - si->second->setName("OFF",evt.getName().c_str()); - } - else { - - SIevent *eptr = new SIevent(evt); - - if (!eptr) - { - printf("[sectionsd::addEvent] new SIevent failed.\n"); - unlockEvents(); - return; - // throw std::bad_alloc(); - } - - SIeventPtr e(eptr); - - //Strip ExtendedDescription if too far in the future - if ((e->times.begin()->startzeit > zeit + secondsExtendedTextCache) && - (SIlanguage::getMode() == CSectionsdClient::LANGUAGE_MODE_OFF) && (zeit != 0)) - e->setExtendedText("OFF",""); - -/* - * this is test code, so indentation is deliberately wrong :-) - * we'll hopefully remove this if clause after testing is done - */ -if (slow_addevent) -{ - std::vector to_delete; - unsigned short eventID = e->eventID; - event_id_t e_key = e->uniqueKey(); - t_channel_id e_chid = e->get_channel_id(); - time_t start_time = e->times.begin()->startzeit; - /* create an event that's surely behind the one to check in the sort order */ - e->eventID = 0xFFFF; /* lowest order sort criteria is eventID */ - /* returns an iterator that's behind 'e' */ - MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator x = - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.upper_bound(e); - e->eventID = eventID; - - /* the first decrement of the iterator gives us an event that's a potential - * match *or* from a different channel, then no event for this channel is stored */ - while (x != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin()) - { - x--; - if ((*x)->get_channel_id() != e_chid) - break; - else - { - event_id_t x_key = (*x)->uniqueKey(); - /* do we need this check? */ - if (x_key == e_key) - continue; - if ((*x)->times.begin()->startzeit > start_time) - continue; - /* iterating backwards: if the starttime of the stored events - * is earlier than the new one, we'll never find an identical one - * => bail out */ - if ((*x)->times.begin()->startzeit < start_time) - break; - /* here we have (*x)->times.begin()->startzeit == start_time */ - if ((*x)->table_id < e->table_id) - { - /* if we already have an event with the same start time but a lower - * table ID, there is no need to add this one - it would be removed - * by removeDupEvents() anyway => just return here. */ - //dprintf("%s: not added: time==,id!=, table_id %02x<%02x, 0x%016llx 0x%016llx %s\n", __func__, (*x)->table_id, e->table_id, x_key, e_key, (*x)->getName().c_str()); - unlockEvents(); - return; - } - dprintf("%s: delete 0x%016llx.%02x time = 0x%016llx.%02x\n", __func__, - x_key, (*x)->table_id, e_key, e->table_id); - to_delete.push_back(x_key); - } - } - unlockEvents(); - - while (! to_delete.empty()) - { - deleteEvent(to_delete.back()); - to_delete.pop_back(); - } -} else { - // Damit in den nicht nach Event-ID sortierten Mengen - // Mehrere Events mit gleicher ID sind, diese vorher loeschen - unlockEvents(); -} - deleteEvent(e->uniqueKey()); - readLockEvents(); - if (mySIeventsOrderUniqueKey.size() >= max_events) { - //FIXME: Set Old Events to 0 if limit is reached... - MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent = - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end(); - lastEvent--; - - //preserve events of current channel - readLockMessaging(); - while ((lastEvent != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin()) && - ((*lastEvent)->get_channel_id() == messaging_current_servicekey)) { - lastEvent--; - } - unlockMessaging(); - unlockEvents(); - deleteEvent((*lastEvent)->uniqueKey()); - } - else - unlockEvents(); - readLockEvents(); - // Pruefen ob es ein Meta-Event ist - MySIeventUniqueKeysMetaOrderServiceUniqueKey::iterator i = mySIeventUniqueKeysMetaOrderServiceUniqueKey.find(e->get_channel_id()); - - if (i != mySIeventUniqueKeysMetaOrderServiceUniqueKey.end()) - { - // ist ein MetaEvent, d.h. mit Zeiten fuer NVOD-Event - - if (e->times.size()) - { - // D.h. wir fuegen die Zeiten in das richtige Event ein - MySIeventsOrderUniqueKey::iterator ie = mySIeventsOrderUniqueKey.find(i->second); - - if (ie != mySIeventsOrderUniqueKey.end()) - { - - // Event vorhanden - // Falls das Event in den beiden Mengen mit Zeiten nicht vorhanden - // ist, dieses dort einfuegen - MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator i2 = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.find(ie->second); - unlockEvents(); - writeLockEvents(); - - if (i2 == mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) - { - // nicht vorhanden -> einfuegen - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.insert(ie->second); - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.insert(ie->second); - - } - - // Und die Zeiten im Event updaten - ie->second->times.insert(e->times.begin(), e->times.end()); - } - } - } - unlockEvents(); - writeLockEvents(); -// printf("Adding: %04x\n", (int) e->uniqueKey()); - - // normales Event - mySIeventsOrderUniqueKey.insert(std::make_pair(e->uniqueKey(), e)); - - if (e->times.size()) - { - // diese beiden Mengen enthalten nur Events mit Zeiten - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.insert(e); - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.insert(e); - } - } - unlockEvents(); -} -#if 0 -// Fuegt zusaetzliche Zeiten in ein Event ein -static void addEventTimes(const SIevent &evt, const unsigned table_id) -{ - if (evt.times.size()) - { - readLockEvents(); - // D.h. wir fuegen die Zeiten in das richtige Event ein - MySIeventsOrderUniqueKey::iterator e = mySIeventsOrderUniqueKey.find(evt.uniqueKey()); - - if (e != mySIeventsOrderUniqueKey.end()) - { - // Event vorhanden - // Falls das Event in den beiden Mengen mit Zeiten vorhanden ist, dieses dort loeschen - unlockEvents(); - writeLockEvents(); - if (e->second->times.size()) - { - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.erase(e->second); - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.erase(e->second); - //unlockEvents(); - } - - // Und die Zeiten im Event updaten - e->second->times.insert(evt.times.begin(), evt.times.end()); - - // Und das Event in die beiden Mengen mit Zeiten (wieder) einfuegen - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.insert(e->second); - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.insert(e->second); - unlockEvents(); -// printf("Updating: %04x times.size() = %d\n", (int) evt.uniqueKey(), e->second->times.size()); - } - else - { - unlockEvents(); - // Event nicht vorhanden -> einfuegen - addEvent(evt, table_id, 0); - } - } -} -#endif -static void addNVODevent(const SIevent &evt) -{ - SIevent *eptr = new SIevent(evt); - - if (!eptr) - { - printf("[sectionsd::addNVODevent] new SIevent failed.\n"); - return; - //throw std::bad_alloc(); - } - - SIeventPtr e(eptr); - - readLockEvents(); - MySIeventsOrderUniqueKey::iterator e2 = mySIeventsOrderUniqueKey.find(e->uniqueKey()); - - if (e2 != mySIeventsOrderUniqueKey.end()) - { - // bisher gespeicherte Zeiten retten - unlockEvents(); - writeLockEvents(); - e->times.insert(e2->second->times.begin(), e2->second->times.end()); - } - unlockEvents(); - - // Damit in den nicht nach Event-ID sortierten Mengen - // mehrere Events mit gleicher ID sind, diese vorher loeschen - deleteEvent(e->uniqueKey()); - readLockEvents(); - if (mySIeventsOrderUniqueKey.size() >= max_events) { - //FIXME: Set Old Events to 0 if limit is reached... - MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator lastEvent = - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end(); - lastEvent--; - - //preserve events of current channel - readLockMessaging(); - while ((lastEvent != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin()) && - ((*lastEvent)->get_channel_id() == messaging_current_servicekey)) { - lastEvent--; - } - unlockMessaging(); - unlockEvents(); - deleteEvent((*lastEvent)->uniqueKey()); - } - else - unlockEvents(); - writeLockEvents(); - mySIeventsOrderUniqueKey.insert(std::make_pair(e->uniqueKey(), e)); - - mySIeventsNVODorderUniqueKey.insert(std::make_pair(e->uniqueKey(), e)); - unlockEvents(); - if (e->times.size()) - { - // diese beiden Mengen enthalten nur Events mit Zeiten - writeLockEvents(); - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.insert(e); - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.insert(e); - unlockEvents(); - } -} - -#if 0 -static void removeNewEvents(void) -{ - // Alte events loeschen - time_t zeit = time(NULL); - - // Mal umgekehrt wandern - - for (MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); e != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end(); e++) - if ((*e)->times.begin()->startzeit > zeit + secondsToCache) - deleteEvent((*e)->uniqueKey()); - - return ; -} -#endif -/* -static void removeOldEvents(const long seconds) -{ - bool goodtimefound; - MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator etmp; - - // Alte events loeschen - time_t zeit = time(NULL); - - MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); - while (e != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end()) { - goodtimefound = false; - for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); t++) { - if (t->startzeit + (long)t->dauer >= zeit - seconds) { - goodtimefound=true; - // one time found -> exit times loop - break; - } - } - if (false == goodtimefound) { - // keep track of our iterator - etmp = e; - if (etmp == mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin()) { - etmp++; // get next element - deleteEvent((*e)->uniqueKey()); - } else { - etmp--; // get last element and iterate later - deleteEvent((*e)->uniqueKey()); - etmp++; - } - e = etmp; - } - else - e++; // solange das nicht richtig funktioniert einfach bis zum ende suchen - // break; // sortiert nach Endzeit, daher weiteres Suchen unnoetig - } - return ; -} -*/ -#ifdef UPDATE_NETWORKS -xmlNodePtr getProvbyPosition(xmlNodePtr node, const int position) { - while (node) { - if (xmlGetSignedNumericAttribute(node, "position", 16) == position) - return node; - node = node->xmlNextNode; - } - return NULL; -} - -//Parses services.xml and delivers the node with the concerning transponder -xmlNodePtr FindTransponder(xmlNodePtr provider, const t_original_network_id onid, const t_transport_stream_id tsid) -{ - //EUTELSAT & SIRIUS: This is for you: Obey DVB rules please!!! Neither of you is allowed to use onid 0001! FIX IT! - if ( (tsid == 1) && (onid == 1) ) { - if ((getProvbyPosition(provider, 0x50) != NULL) && (getProvbyPosition(provider, 0x130) != NULL)) { - //If 5E and 13E are used together we can't determine whose SDT this is. - printf("Sirius and Eutelsat suck big time!\n"); - return NULL; - } - } - - while (provider) - { - dprintf("going to search dvb-%c provider %s\n", xmlGetName(provider)[0], xmlGetAttribute(provider, "name")); - xmlNodePtr transponder = provider->xmlChildrenNode; - - while (transponder) - { - if ((xmlGetNumericAttribute(transponder, "id", 16) == tsid) && (xmlGetNumericAttribute(transponder, "onid", 16) == onid)) - return transponder; - else - transponder = transponder->xmlNextNode; - } - provider = provider->xmlNextNode; - } - return NULL; -} -#endif -static void removeOldEvents(const long seconds) -{ - bool goodtimefound; - - // Alte events loeschen - time_t zeit = time(NULL); - - readLockEvents(); - - MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); - - while ((e != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end()) && (!messaging_zap_detected)) { - unlockEvents(); - goodtimefound = false; - for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); t++) { - if (t->startzeit + (long)t->dauer >= zeit - seconds) { - goodtimefound=true; - // one time found -> exit times loop - break; - } - } - - if (false == goodtimefound) - deleteEvent((*(e++))->uniqueKey()); - else - ++e; - readLockEvents(); - } - unlockEvents(); - - return; -} - -/* Remove duplicate events (same Service, same start and endtime) - * with different eventID. Use the one from the lower table_id. - * This routine could be extended to remove overlapping events also, - * but let's keep that for later - */ -static void removeDupEvents(void) -{ - MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator e1, e2, del; - /* list of event IDs to delete */ - std::vectorto_delete; - unsigned int dauer_diff= 0; - unsigned int startzeit_diff = 0; - - readLockEvents(); - e1 = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin(); - - while ((e1 != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) && !messaging_zap_detected) - { - e2 = e1; - e1++; - if (e1 == mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) - break; - - /* check for the same service */ - if ((*e1)->get_channel_id() != (*e2)->get_channel_id()) - continue; - /* check for same time */ - if( (*e1)->table_id != 0xFF && (*e2)->table_id != 0xFF ){ - if (((*e1)->times.begin()->startzeit != (*e2)->times.begin()->startzeit) || - ((*e1)->times.begin()->dauer != (*e2)->times.begin()->dauer)) - continue; - } - // remove servustv && sixx hd crap & co channels (only from save epg) - else { - startzeit_diff = abs((*e1)->times.begin()->startzeit - (*e2)->times.begin()->startzeit); - dauer_diff = abs((*e1)->times.begin()->dauer - (*e2)->times.begin()->dauer); - if (( startzeit_diff > ((*e1)->times.begin()->dauer/2) && (*e1)->times.begin()->dauer > 360 ) || - ( dauer_diff > ((*e1)->times.begin()->dauer/2))) - continue; - } - if ((*e1)->table_id == (*e2)->table_id && ((*e1)->table_id != 0xFF )) - { - dprintf("%s: not removing events %llx %llx, t:%02x '%s'\n", __func__, - (*e1)->uniqueKey(), (*e2)->uniqueKey(), (*e1)->table_id, (*e1)->getName().c_str()); - continue; - } - - if ((*e1)->table_id > (*e2)->table_id) - del = e1; - else if ((*e1)->table_id < (*e2)->table_id) - del = e2; - else if((*e1)->table_id == 0xFF ) - del = e1; - else - del = e2; - - dprintf("%s: removing event %llx.%02x '%s'\n", __func__, - (*del)->uniqueKey(), (*del)->table_id, (*del)->getName().c_str()); - /* remember the unique ID for later deletion */ - to_delete.push_back((*del)->uniqueKey()); - } - unlockEvents(); - - /* clean up outside of the iterator loop */ - for (std::vector::iterator i = to_delete.begin(); i != to_delete.end(); i++) - deleteEvent(*i); - to_delete.clear(); /* needed? can't hurt... */ - - return; -} - -#ifdef UPDATE_NETWORKS -static void removeWasteEvents() -{ - bool haslinkage; - bool validevent; - xmlDocPtr service_parser = parseXmlFile(SERVICES_XML); - - xmlNodePtr services_tp; - xmlNodePtr node; - - t_service_id last_service_id = 0; - t_original_network_id last_original_network_id = 0; - t_transport_stream_id last_transport_stream_id = 0; - bool lastidfound = true; - - readLockEvents(); - - MySIeventsOrderUniqueKey::iterator e = mySIeventsOrderUniqueKey.begin(); - - while ((e != mySIeventsOrderUniqueKey.end()) && (!messaging_zap_detected)) { - unlockEvents(); - validevent = true; - haslinkage = false; - if ((last_original_network_id == e->second->original_network_id) && - (last_transport_stream_id == e->second->transport_stream_id) && - (last_service_id == e->second->service_id)) { - if (!lastidfound) { - validevent = false; - dprintf("Same ONID:%04x TSID:%04x SID:%04x\n",last_original_network_id, - last_transport_stream_id, - last_service_id); - } - } - else { - for (unsigned int i = 0; i < e->second->linkage_descs.size(); i++) - if ((e->second->linkage_descs[i].linkageType == 0xB0) || - (e->second->linkage_descs[i].linkageType == 0x00)) - { - haslinkage = true; - break; - } -// printf("here1\n"); - if (validevent && !haslinkage) { -// printf("here2\n"); - if (service_parser != NULL) { -// printf("here3\n"); - services_tp = FindTransponder(xmlDocGetRootElement(service_parser) - ->xmlChildrenNode,e->second->original_network_id, - e->second->transport_stream_id); - if ( services_tp ) { -// printf("here4\n"); - node = services_tp->xmlChildrenNode; - while (xmlGetNextOccurence(node, "channel") != NULL) { -// printf("here5\n"); - if (e->second->service_id != xmlGetNumericAttribute(node, - (char*)"service_id", 16)) - node = node->xmlNextNode; - else break; - } -// printf("here6\n"); - if (xmlGetNextOccurence(node, "channel") == NULL) - validevent = false; - } else validevent = false; - } else validevent = false; - lastidfound = validevent; - if (!lastidfound) - dprintf("Wasted ONID:%04x TSID:%04x SID:%04x\n", - e->second->original_network_id, - e->second->transport_stream_id, - e->second->service_id); - } else lastidfound = true; - last_service_id = e->second->service_id; - last_original_network_id = e->second->original_network_id; - last_transport_stream_id = e->second->transport_stream_id; - } - - if (!validevent) - deleteEvent((e++)->first); - else - ++e; - readLockEvents(); - } - unlockEvents(); - - xmlFreeDoc(service_parser); - return; -} -#endif -// SIservicePtr; -typedef boost::shared_ptr -SIservicePtr; - -typedef std::map > MySIservicesOrderUniqueKey; -static MySIservicesOrderUniqueKey mySIservicesOrderUniqueKey; - -typedef std::map > MySIservicesNVODorderUniqueKey; -static MySIservicesNVODorderUniqueKey mySIservicesNVODorderUniqueKey; - -// Hier sollte man die hash-funktion fuer strings der stl benutzen -// Muss mal schauen ob es die auch fuer 'ignore_case' gibt -/* -struct OrderServiceName -{ - bool operator()(const SIservicePtr &p1, const SIservicePtr &p2) - { - return strcasecmp(p1->serviceName.c_str(), p2->serviceName.c_str()) < 0; - } -}; - -typedef std::set MySIservicesOrderServiceName; -static MySIservicesOrderServiceName mySIservicesOrderServiceName; -*/ -#ifdef UPDATE_NETWORKS -xmlNodePtr findBouquetByName(xmlDocPtr parser,char *name) -{ - xmlNodePtr bouquet = NULL; - if (parser) - bouquet = xmlDocGetRootElement(parser)->xmlChildrenNode; - else { - dprintf("Bouquet parsing failed!\n"); - return NULL; - } - while (xmlGetNextOccurence(bouquet, "Bouquet") != NULL) { - if ((xmlGetNumericAttribute(bouquet, "type", 8) == 2) && - (strcmp(xmlGetAttribute(bouquet, "name"), name) == 0)) - return bouquet; - bouquet = bouquet->xmlNextNode; - } - return NULL; -} - -static BouquetAdder* getNextAutoBouquet(BouquetAdder *currentAdder, const char *provname, - const t_original_network_id onid, const t_transport_stream_id tsid, - const t_service_id sid) -{ - bool found = false; - BouquetAdderEntry *currentEntry = NULL; - ExceptService *excepts = NULL; - - while ((currentAdder) && (!found)) { - currentEntry = currentAdder->bae; - while ((currentEntry) && (!found)) { - if ( ((strcmp(currentEntry->ProviderName, provname) == 0) || - ((strcmp(currentEntry->ProviderName, "") == 0))) && - ((currentEntry->onid == onid) || (currentEntry->onid == 0)) && - ((currentEntry->tsid == tsid) || (currentEntry->tsid == 0)) ) - found = true; - excepts = currentEntry->es; - while ((excepts) && (found)) { - if (excepts->sid == sid) - found = false; - excepts = excepts->next; - } - currentEntry = currentEntry->next; - } - if (!found) - currentAdder = currentAdder->next; - } - return currentAdder; -} - -static bool bouquetContainsService(const xmlNodePtr bouquet, const t_original_network_id onid, - const t_transport_stream_id tsid, const t_service_id sid) -{ - if (!bouquet) - return false; - - xmlNodePtr channel = NULL; - - channel = bouquet->xmlChildrenNode; - while (channel) { - if ((xmlGetNumericAttribute(channel, "onid", 16) == onid) && - (xmlGetNumericAttribute(channel, "tsid", 16) == tsid) && - (xmlGetNumericAttribute(channel, "serviceID", 16) == sid)) - return true; - channel = channel->xmlNextNode; - } - return false; -} - -static void write_bouquet_xml_header(FILE * fd) -{ - fprintf(fd, - "\n" - "\n" - "\n"); -} - -static void write_bouquet_xml_footer(FILE *fd) -{ - fprintf(fd, "\n"); -} - -//stolen from zapitools.cpp -std::string UTF8_to_UTF8XML(const char * s) -{ - std::string r; - - while ((*s) != 0) - { - /* cf. - * http://www.w3.org/TR/2004/REC-xml-20040204/#syntax - * and - * http://www.w3.org/TR/2004/REC-xml-20040204/#sec-predefined-ent - */ - switch (*s) - { - case '<': - r += "<"; - break; - case '>': - r += ">"; - break; - case '&': - r += "&"; - break; - case '\"': - r += """; - break; - case '\'': - r += "'"; - break; - default: - r += *s; - } - s++; - } - return r; -} - -static void writebouquetwithoutend(FILE *fd, xmlNodePtr bouquet) -{ - std::string name; - - name = xmlGetAttribute(bouquet, "name"); - - fprintf(fd, "\t\n"); - bouquet2 = bouquet2->xmlNextNode; - } - if (!bouquet_found) { - fprintf(dst, "\t\n"); - } - } - else { - if (bouquet) - writebouquetwithoutend(dst, bouquet); - else - fprintf(dst, "\t\n"); - } - write_bouquet_xml_footer(dst); - returnvalue = true; - fclose(dst); - rename(CURRENTBOUQUETS_TMP, CURRENTBOUQUETS_XML); - } - } - } - currentBouquet = currentBouquet->next; - currentBouquet = getNextAutoBouquet(currentBouquet, provname, onid, tsid, sid); - } - - return returnvalue; -} - -// Fuegt ein Service in alle Mengen ein -static bool addService(const SIservice &s, const int is_actual) -{ - bool already_exists; - bool is_new = false; - - //if (mySIservicesNVODorderUniqueKey.find(s.uniqueKey())) - readLockServices(); - MySIservicesOrderUniqueKey::iterator si = mySIservicesOrderUniqueKey.find(s.uniqueKey()); - already_exists = (si != mySIservicesOrderUniqueKey.end()); - unlockServices(); - - if ( (!already_exists) || ((is_actual & 7) && (!si->second->is_actual)) ) { - - if (already_exists) - { - writeLockServices(); - mySIservicesOrderUniqueKey.erase(s.uniqueKey()); - unlockServices(); - } - - SIservice *sp = new SIservice(s); - - if (!sp) - { - printf("[sectionsd::addService] new SIservice failed.\n"); - return false; - //throw std::bad_alloc(); - } - - SIservicePtr sptr(sp); - - // Leere Servicenamen in ServiceID in hex umbenennen -#define MAX_SIZE_SERVICENAME 50 - char servicename[MAX_SIZE_SERVICENAME]; - - if (sptr->serviceName.empty()) { - sprintf(servicename, "%04x", sptr->service_id); - servicename[sizeof(servicename) - 1] = 0; - sptr->serviceName = servicename; - } - - sptr->is_actual = is_actual; - - writeLockServices(); - mySIservicesOrderUniqueKey.insert(std::make_pair(sptr->uniqueKey(), sptr)); - unlockServices(); - - if (sptr->nvods.size()) - { - writeLockServices(); - mySIservicesNVODorderUniqueKey.insert(std::make_pair(sptr->uniqueKey(), sptr)); - unlockServices(); - } - // if(sptr->serviceID==0x01 || sptr->serviceID==0x02 || sptr->serviceID==0x04) -// mySIservicesOrderServiceName.insert(sptr); - is_new = true; - } - - return is_new; -} - - // SIsPtr; -typedef boost::shared_ptr -SIbouquetPtr; - -typedef std::map > MySIbouquetsOrderUniqueKey; -static MySIbouquetsOrderUniqueKey mySIbouquetsOrderUniqueKey; - -// Fuegt einen BouquetEntry in alle Mengen ein -static int addBouquetEntry(const SIbouquet &s/*, int section_nr, int count*/) -{ - bool already_exists; - uint16_t bouquet_id = 0; - - //s.position = (uint16_t) (((section_nr & 0x1f) << 11) + (count & 0x7ff)); - - //if (mySIservicesNVODorderUniqueKey.find(s.uniqueKey())) - readLockBouquets(); - MySIbouquetsOrderUniqueKey::iterator si = mySIbouquetsOrderUniqueKey.find(s.uniqueKey()); - already_exists = (si != mySIbouquetsOrderUniqueKey.end()); - - if (!already_exists) { - - SIbouquet *bp = new SIbouquet(s); - - if (!bp) - { - printf("[sectionsd::addBouquetEntry] new SIbouquet failed.\n"); - unlockBouquets(); - throw std::bad_alloc(); - } - - SIbouquetPtr bpptr(bp); - /* - bpptr->position = (uint16_t) (((section_nr & 0x1f) << 11) + (number & 0x7ff)); - - printf("Section Number: %d Count: %d position: %04x\n", section_nr, number, bpptr->position); - */ - unlockBouquets(); - writeLockBouquets(); - mySIbouquetsOrderUniqueKey.insert(std::make_pair(bpptr->uniqueKey(), bpptr)); - - //Because of Bouquet_Id misuse. see SIsections.cpp. IDs are introduced there - if ((bpptr->bouquet_id == 0x3ffe) || (bpptr->bouquet_id == 0x3fff)) - bouquet_id = bpptr->bouquet_id; - else - bouquet_id = 0; - - } - unlockBouquets(); - return bouquet_id << 1 | (int) !already_exists; -} - -/* - * - * communication with sectionsdclient: - * - */ - - // SIsPtr; -typedef boost::shared_ptr -SInetworkPtr; - -typedef std::map > MySItranspondersOrderUniqueKey; -static MySItranspondersOrderUniqueKey mySItranspondersOrderUniqueKey; - -// Fuegt einen Tranponder in alle Mengen ein -static bool addTransponder(const SInetwork &s, const bool is_actual) -{ - readLockTransponders(); - MySItranspondersOrderUniqueKey::iterator si = mySItranspondersOrderUniqueKey.find(s.uniqueKey()); - bool already_exists = (si != mySItranspondersOrderUniqueKey.end()); - - if (!already_exists) { - - SInetwork *nw = new SInetwork(s); - - if (!nw) - { - printf("[sectionsd::updateNetwork] new SInetwork failed.\n"); - unlockTransponders(); - throw std::bad_alloc(); - } - - SInetworkPtr tpptr(nw); - - tpptr->is_actual = is_actual; - - unlockTransponders(); - writeLockTransponders(); - mySItranspondersOrderUniqueKey.insert(std::make_pair(tpptr->uniqueKey(), tpptr)); - } - unlockTransponders(); - return !already_exists; -} -#endif -inline bool readNbytes(int fd, char *buf, const size_t numberOfBytes, const time_t timeoutInSeconds) -{ - timeval timeout; - timeout.tv_sec = timeoutInSeconds; - timeout.tv_usec = 0; - return receive_data(fd, buf, numberOfBytes, timeout); -} - -inline bool writeNbytes(int fd, const char *buf, const size_t numberOfBytes, const time_t timeoutInSeconds) -{ - timeval timeout; - timeout.tv_sec = timeoutInSeconds; - timeout.tv_usec = 0; - return send_data(fd, buf, numberOfBytes, timeout); -} - - -//------------------------------------------------------------ -// misc. functions -//------------------------------------------------------------ -/* -static t_channel_id findServiceUniqueKeyforServiceName(const char * const serviceName) -{ - SIservice *sp = new SIservice(0, 0, 0); - - if (!sp) - { - printf("[sectionsd::findServiceUniqueKeyforServiceName] new SIservice failed.\n"); - throw std::bad_alloc(); - } - - SIservicePtr s(sp); - - s->serviceName = serviceName; - - dprintf("Search for Service '%s'\n", serviceName); - - MySIservicesOrderServiceName::iterator si = mySIservicesOrderServiceName.find(s); - - if (si != mySIservicesOrderServiceName.end()) - return (*si)->uniqueKey(); - - dputs("Service not found"); - - return 0; -} -*/ -static const SIevent& findSIeventForEventUniqueKey(const event_id_t eventUniqueKey) -{ - // Event (eventid) suchen - MySIeventsOrderUniqueKey::iterator e = mySIeventsOrderUniqueKey.find(eventUniqueKey); - - if (e != mySIeventsOrderUniqueKey.end()) - return *(e->second); - - return nullEvt; -} - -static const SIevent& findActualSIeventForServiceUniqueKey(const t_channel_id serviceUniqueKey, SItime& zeit, long plusminus = 0, unsigned *flag = 0) -{ - time_t azeit = time(NULL); - - if (flag != 0) - *flag = 0; - - for (MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); e != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end(); ++e) - if ((*e)->get_channel_id() == serviceUniqueKey) - { - if (flag != 0) - *flag |= CSectionsdClient::epgflags::has_anything; // berhaupt was da... - -// for (SItimes::reverse_iterator t = (*e)->times.rend(); t != (*e)->times.rbegin(); t--) { - for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) { - if ((long)(azeit + plusminus) < (long)(t->startzeit + t->dauer)) - { - if (flag != 0) - *flag |= CSectionsdClient::epgflags::has_later; // later events are present... - - if (t->startzeit <= (long)(azeit + plusminus)) - { - //printf("azeit %d, startzeit+t->dauer %d \n", azeit, (long)(t->startzeit+t->dauer) ); - - if (flag != 0) - *flag |= CSectionsdClient::epgflags::has_current; // aktuelles event da... - - zeit = *t; - - return *(*e); - } - } - } - } - - return nullEvt; -} - -static const SIevent& findNextSIeventForServiceUniqueKey(const t_channel_id serviceUniqueKey, SItime& zeit) -{ - time_t azeit = time(NULL); - - for (MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); e != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end(); e++) - if ((*e)->get_channel_id() == serviceUniqueKey) - { - for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) - if ((long)(azeit) < (long)(t->startzeit + t->dauer)) - { - zeit = *t; - return *(*e); - } - } - - return nullEvt; -} -#if 0 -static bool ServiceUniqueKeyHasCurrentNext(const t_channel_id serviceUniqueKey) -{ - time_t azeit = time(NULL); - time_t nextstart = time(NULL); - bool found = false; - SItimes::iterator t; - - MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); - - while ((e != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end()) && (!found)) { - if ((*e)->get_channel_id() == serviceUniqueKey) - { - t = (*e)->times.begin(); - while ((t != (*e)->times.end()) && (!found)) { - if (((long)(azeit) < (long)(t->startzeit + t->dauer)) && (t->startzeit <= (long)(azeit))) { - nextstart = t->startzeit + t->dauer; - found = true; - } - else - t++; - } - } - if (!found) - e++; - } - if (found) { - dprintf("Current Event: %s\n",(*e)->getName().c_str()); - //current is there; check if next is too - if (++t != (*e)->times.end()) - return true; - while (e != mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end()) { - if ((*e)->get_channel_id() == serviceUniqueKey) { - t = (*e)->times.begin(); - while (t != (*e)->times.end()) { - if (t->startzeit >= nextstart) { - dprintf("Next Event: %s\n",(*e)->getName().c_str()); - return true; - } - t++; - } - } - e++; - } - } - - return false; -} -#endif -/* -static const SIevent &findActualSIeventForServiceName(const char * const serviceName, SItime& zeit) -{ - t_channel_id serviceUniqueKey = findServiceUniqueKeyforServiceName(serviceName); - - if (serviceUniqueKey) - return findActualSIeventForServiceUniqueKey(serviceUniqueKey, zeit); - - return nullEvt; -} -*/ -// Sucht das naechste Event anhand unique key und Startzeit -static const SIevent &findNextSIevent(const event_id_t uniqueKey, SItime &zeit) -{ - MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(uniqueKey); - - if (eFirst != mySIeventsOrderUniqueKey.end()) - { - SItimes::iterator nextnvodtimes = eFirst->second->times.end(); - SItimes::iterator nexttimes = eFirst->second->times.end(); - - if (eFirst->second->times.size() > 1) - { - //find next nvod - nextnvodtimes = eFirst->second->times.begin(); - while ( nextnvodtimes != eFirst->second->times.end() ) { - if ( nextnvodtimes->startzeit == zeit.startzeit ) - break; - else - ++nextnvodtimes; - } - } - - MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator eNext; - - //if ((nextnvodtimes != eFirst->second->times.begin()) && (nextnvodtimes != eFirst->second->times.end())) { - //Startzeit not first - we can't use the ordered list... - for (MySIeventsOrderFirstEndTimeServiceIDEventUniqueKey::iterator e = mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.begin(); e != - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.end(); ++e ) { - if ((*e)->get_channel_id() == eFirst->second->get_channel_id()) { - for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) { - if (t->startzeit > zeit.startzeit) { - if (nexttimes != eFirst->second->times.end()) { - if (t->startzeit < nexttimes->startzeit) { - eNext = e; - nexttimes = t; - } - } - else { - eNext = e; - nexttimes = t; - } - } - } - } - } -/* } else { - //find next normal - eNext = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.find(eFirst->second); - eNext++; - - if (eNext != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) - { - if ((*eNext)->get_channel_id() == eFirst->second->get_channel_id()) - nexttimes = (*eNext)->times.begin(); - } - } -*/ - if (nextnvodtimes != eFirst->second->times.end()) - ++nextnvodtimes; - //Compare - if (nexttimes != eFirst->second->times.end()) { - if (nextnvodtimes != eFirst->second->times.end()) { - //both times are set - take the first - if (nexttimes->startzeit < nextnvodtimes->startzeit) { - zeit = *nexttimes; - return *(*eNext); - - } else { - zeit = *nextnvodtimes; - return *(eFirst->second); - } - } else { - //only nexttimes set - zeit = *nexttimes; - return *(*eNext); - } - } else if (nextnvodtimes != eFirst->second->times.end()) { - //only nextnvodtimes set - zeit = *nextnvodtimes; - return *(eFirst->second); - } - } - - return nullEvt; -} - - -/* - -// Sucht das naechste Event anhand unique key und Startzeit -static const SIevent &findNextSIevent(const event_id_t uniqueKey, SItime &zeit) -{ - MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(uniqueKey); - - if (eFirst != mySIeventsOrderUniqueKey.end()) - { - - SItimes::iterator t = eFirst->second->times.end(); - - if (eFirst->second->times.size() > 1) - { - // Wir haben ein NVOD-Event - // d.h. wir suchen die aktuelle Zeit und nehmen die naechste davon, falls existent - - for ( t = eFirst->second->times.begin(); t != eFirst->second->times.end(); t++) - if (t->startzeit == zeit.startzeit) - { - t++; - - if (t != eFirst->second->times.end()) - { - // zeit = *t; - // return *(eFirst->second); - break; - } - - t = eFirst->second->times.end(); - break; // ganz normal naechstes Event suchen - } - } - - MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator eNext = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.find(eFirst->second); - eNext++; - - if (eNext != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) - { - if ((*eNext)->get_channel_id() == eFirst->second->get_channel_id()) - { - if (t != eFirst->second->times.end()) { - if (t->startzeit < (*eNext)->times.begin()->startzeit) { - zeit = *t; - return *(eFirst->second); - } - } - MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator ePrev = - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin(); - while ( ((*ePrev)->times.begin()->startzeit < zeit.startzeit) && - (ePrev != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) ) { - if ((*ePrev)->times.size() > 1) { - t = (*ePrev)->times.begin(); - while ( (t != (*ePrev)->times.end()) && (t->startzeit < - (*eNext)->times.begin()->startzeit) ) { - if (t->startzeit > zeit.startzeit) { - zeit = *t; - return *(*ePrev); - } - t++; - } - } - ePrev++; - } - zeit = *((*eNext)->times.begin()); - return *(*eNext); - } - else if (t != eFirst->second->times.end()) { - zeit = *t; - return *(eFirst->second); - } - else - return nullEvt; - } - else if (t != eFirst->second->times.end()) { - zeit = *t; - return *(eFirst->second); - } - } - - return nullEvt; -} -*/ -// Sucht das naechste UND vorhergehende Event anhand unique key und Startzeit -static void findPrevNextSIevent(const event_id_t uniqueKey, SItime &zeit, SIevent &prev, SItime &prev_zeit, SIevent &next, SItime &next_zeit) -{ - prev = nullEvt; - next = nullEvt; - bool prev_ok = false; - bool next_ok = false; - - MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(uniqueKey); - - if (eFirst != mySIeventsOrderUniqueKey.end()) - { - if (eFirst->second->times.size() > 1) - { - // Wir haben ein NVOD-Event - // d.h. wir suchen die aktuelle Zeit und nehmen die naechste davon, falls existent - - for (SItimes::iterator t = eFirst->second->times.begin(); t != eFirst->second->times.end(); ++t) - if (t->startzeit == zeit.startzeit) - { - if (t != eFirst->second->times.begin()) - { - --t; - prev_zeit = *t; - prev = *(eFirst->second); - prev_ok = true; - ++t; - } - - ++t; - - if (t != eFirst->second->times.end()) - { - next_zeit = *t; - next = *(eFirst->second); - next_ok = true; - } - - if ( prev_ok && next_ok ) - return ; // beide gefunden... - else - break; - } - } - - MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator eNext = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.find(eFirst->second); - - if ( (!prev_ok) && (eNext != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin() ) ) - { - --eNext; - - if ((*eNext)->get_channel_id() == eFirst->second->get_channel_id()) - { - prev_zeit = *((*eNext)->times.begin()); - prev = *(*eNext); - } - - ++eNext; - } - - ++eNext; - - if ( (!next_ok) && (eNext != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) ) - { - if ((*eNext)->get_channel_id() == eFirst->second->get_channel_id()) - { - next_zeit = *((*eNext)->times.begin()); - next = *(*eNext); - } - } - - // printf("evt_id >%llx<, time %x - evt_id >%llx<, time %x\n", prev.uniqueKey(), prev_zeit.startzeit, next.uniqueKey(), next_zeit.startzeit); - } -} - -//--------------------------------------------------------------------- -// connection-thread -// handles incoming requests -//--------------------------------------------------------------------- - -struct connectionData -{ - int connectionSocket; - - struct sockaddr_in clientAddr; -}; - -static void commandPauseScanning(int connfd, char *data, const unsigned dataLength) -{ - if (dataLength != 4) - return ; - - int pause = *(int *)data; - - if (pause && pause != 1) - return ; - - dprintf("Request of %s scanning.\n", pause ? "stop" : "continue" ); - - if (scanning && pause) - { - dmxCN.request_pause(); - dmxEIT.request_pause(); -#ifdef ENABLE_FREESATEPG - dmxFSEIT.request_pause(); -#endif -#ifdef UPDATE_NETWORKS - dmxNIT.request_pause(); - dmxSDT.request_pause(); -#endif -#ifdef ENABLE_PPT - dmxPPT.request_pause(); -#endif - scanning = 0; - } - else if (!pause && !scanning) - { - dmxCN.request_unpause(); -#ifdef UPDATE_NETWORKS - dmxNIT.request_unpause(); - dmxSDT.request_unpause(); -#endif - dmxEIT.request_unpause(); -#ifdef ENABLE_FREESATEPG - dmxFSEIT.request_unpause(); -#endif -#ifdef ENABLE_PPT - dmxPPT.request_unpause(); -#endif - writeLockEvents(); - if (myCurrentEvent) { - delete myCurrentEvent; - myCurrentEvent = NULL; - } - if (myNextEvent) { - delete myNextEvent; - myNextEvent = NULL; - } - unlockEvents(); - writeLockMessaging(); - messaging_have_CN = 0x00; - messaging_got_CN = 0x00; - unlockMessaging(); - scanning = 1; - if (!bTimeCorrect && !ntpenable) - { - pthread_mutex_lock(&timeThreadSleepMutex); - pthread_cond_broadcast(&timeThreadSleepCond); - pthread_mutex_unlock(&timeThreadSleepMutex); - } - - scanning = 1; - dmxCN.change(0); - dmxEIT.change(0); -#ifdef ENABLE_FREESATEPG - dmxFSEIT.change(0); -#endif - } - - struct sectionsd::msgResponseHeader msgResponse; - - msgResponse.dataLength = 0; - - writeNbytes(connfd, (const char *)&msgResponse, sizeof(msgResponse), WRITE_TIMEOUT_IN_SECONDS); - - return ; -} - -static void commandGetIsScanningActive(int connfd, char* /*data*/, const unsigned /*dataLength*/) -{ - struct sectionsd::msgResponseHeader responseHeader; - - responseHeader.dataLength = sizeof(scanning); - - if (writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) - { - writeNbytes(connfd, (const char *)&scanning, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); -} - -static void commandDumpAllServices(int connfd, char* /*data*/, const unsigned /*dataLength*/) -{ - dputs("Request of service list.\n"); - long count=0; -#define MAX_SIZE_SERVICELIST 64*1024 - char *serviceList = new char[MAX_SIZE_SERVICELIST]; // 65kb should be enough and dataLength is unsigned short - - if (!serviceList) - { - fprintf(stderr, "low on memory!\n"); - return ; - } - - *serviceList = 0; - readLockServices(); -#define MAX_SIZE_DATEN 200 - char daten[MAX_SIZE_DATEN]; - - for (MySIservicesOrderUniqueKey::iterator s = mySIservicesOrderUniqueKey.begin(); s != mySIservicesOrderUniqueKey.end(); ++s) - { - count += 1 + snprintf(daten, MAX_SIZE_DATEN, - PRINTF_CHANNEL_ID_TYPE_NO_LEADING_ZEROS - " %hu %hhu %d %d %d %d %u ", - s->first, - s->second->service_id, s->second->serviceTyp, - s->second->eitScheduleFlag(), s->second->eitPresentFollowingFlag(), - s->second->runningStatus(), s->second->freeCAmode(), - s->second->nvods.size()); -/** soll es in count ? - + strlen(s->second->serviceName.c_str()) + 1 - + strlen(s->second->providerName.c_str()) + 1 - + 3; **/ - if (count < MAX_SIZE_SERVICELIST) - { - strcat(serviceList, daten); - strcat(serviceList, "\n"); - strcat(serviceList, s->second->serviceName.c_str()); - strcat(serviceList, "\n"); - strcat(serviceList, s->second->providerName.c_str()); - strcat(serviceList, "\n"); - } else { - dprintf("warning: commandDumpAllServices: serviceList cut\n"); - break; - } - } - - unlockServices(); - struct sectionsd::msgResponseHeader msgResponse; - msgResponse.dataLength = strlen(serviceList) + 1; - - if (msgResponse.dataLength > MAX_SIZE_SERVICELIST) - printf("warning: commandDumpAllServices: length=%d\n", msgResponse.dataLength); - - if (msgResponse.dataLength == 1) - msgResponse.dataLength = 0; - - if (writeNbytes(connfd, (const char *)&msgResponse, sizeof(msgResponse), WRITE_TIMEOUT_IN_SECONDS) == true) - { - if (msgResponse.dataLength) - writeNbytes(connfd, serviceList, msgResponse.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - delete[] serviceList; - - return ; -} - -#if 0 -static void commandSetEventsAreOldInMinutes(int connfd, char *data, const unsigned dataLength) -{ - if (dataLength != 2) - return ; - - dprintf("Set events are old after minutes: %hd\n", *((unsigned short*)data)); - - oldEventsAre = *((unsigned short*)data)*60L; - - struct sectionsd::msgResponseHeader responseHeader; - - responseHeader.dataLength = 0; - - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - - return ; -} - -static void commandSetHoursToCache(int connfd, char *data, const unsigned dataLength) -{ - if (dataLength != 2) - return ; - - dprintf("Set hours to cache: %hd\n", *((unsigned short*)data)); - - secondsToCache = *((unsigned short*)data)*60L*60L; - - struct sectionsd::msgResponseHeader responseHeader; - - responseHeader.dataLength = 0; - - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - - return ; -} - -static void commandSetHoursExtendedCache(int connfd, char *data, const unsigned dataLength) -{ - if (dataLength != 2) - return ; - - dprintf("Set hours to cache extended text: %hd\n", *((unsigned short*)data)); - - secondsExtendedTextCache = *((unsigned short*)data)*60L*60L; - - struct sectionsd::msgResponseHeader responseHeader; - - responseHeader.dataLength = 0; - - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - - return ; -} - -#endif - -static void sendAllEvents(int connfd, t_channel_id serviceUniqueKey, bool oldFormat = true, char search = 0, std::string search_text = "") -{ -#define MAX_SIZE_EVENTLIST 64*1024 - char *evtList = new char[MAX_SIZE_EVENTLIST]; // 64kb should be enough and dataLength is unsigned short - char *liste; - long count=0; - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; -// int laststart = 0; - - if (!evtList) - { - fprintf(stderr, "low on memory!\n"); - goto out; - } - - dprintf("sendAllEvents for " PRINTF_CHANNEL_ID_TYPE "\n", serviceUniqueKey); - *evtList = 0; - liste = evtList; - - if (serviceUniqueKey != 0) - { - // service Found - readLockEvents(); - int serviceIDfound = 0; - - if (search_text.length()) std::transform(search_text.begin(), search_text.end(), search_text.begin(), tolower); - for (MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator e = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin(); e != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end(); ++e) - { - if ((*e)->get_channel_id() == serviceUniqueKey) - { - serviceIDfound = 1; - - bool copy = true; - if(search == 0); // nothing to do here - else if(search == 1) - { - std::string eName = (*e)->getName(); - std::transform(eName.begin(), eName.end(), eName.begin(), tolower); - if(eName.find(search_text) == std::string::npos) - copy = false; - } - else if(search == 2) - { - std::string eText = (*e)->getText(); - std::transform(eText.begin(), eText.end(), eText.begin(), tolower); - if(eText.find(search_text) == std::string::npos) - copy = false; - } - else if(search == 3) - { - std::string eExtendedText = (*e)->getExtendedText(); - std::transform(eExtendedText.begin(), eExtendedText.end(), eExtendedText.begin(), tolower); - if(eExtendedText.find(search_text) == std::string::npos) - copy = false; - } - - if(copy) - { - for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) - { -// if (t->startzeit > laststart) { -// laststart = t->startzeit; - if ( oldFormat ) - { -#define MAX_SIZE_STRTIME 50 - char strZeit[MAX_SIZE_STRTIME]; - char strZeit2[MAX_SIZE_STRTIME]; - struct tm *tmZeit; - - tmZeit = localtime(&(t->startzeit)); - count += snprintf(strZeit, MAX_SIZE_STRTIME, "%012llx ", (*e)->uniqueKey()); - count += snprintf(strZeit2, MAX_SIZE_STRTIME, "%02d.%02d %02d:%02d %u ", - tmZeit->tm_mday, tmZeit->tm_mon + 1, tmZeit->tm_hour, tmZeit->tm_min, (*e)->times.begin()->dauer / 60); - count += (*e)->getName().length() + 1; - - if (count < MAX_SIZE_EVENTLIST) { - strcat(liste, strZeit); - strcat(liste, strZeit2); - strcat(liste, (*e)->getName().c_str()); - strcat(liste, "\n"); - } else { - dprintf("warning: sendAllEvents eventlist cut\n"); - break; - } - } - else - { - count += sizeof(event_id_t) + 4 + 4 + (*e)->getName().length() + 1; - if (((*e)->getText()).empty()) - { - count += (*e)->getExtendedText().substr(0, 50).length(); - } - else - { - count += (*e)->getText().length(); - } - count++; - - if (count < MAX_SIZE_EVENTLIST) { - *((event_id_t *)liste) = (*e)->uniqueKey(); - liste += sizeof(event_id_t); - *((unsigned *)liste) = t->startzeit; - liste += 4; - *((unsigned *)liste) = t->dauer; - liste += 4; - strcpy(liste, (*e)->getName().c_str()); - liste += (*e)->getName().length(); - liste++; - - if (((*e)->getText()).empty()) - { - strcpy(liste, (*e)->getExtendedText().substr(0, 50).c_str()); - liste += strlen(liste); - } - else - { - strcpy(liste, (*e)->getText().c_str()); - liste += (*e)->getText().length(); - } - liste++; - } else { - dprintf("warning: sendAllEvents eventlist cut\n"); - break; - } - } - // } - } - } // if = serviceID - } - else if ( serviceIDfound ) - break; // sind nach serviceID und startzeit sortiert -> nicht weiter suchen - } - - unlockEvents(); - } - - //printf("warning: [sectionsd] all events - response-size: 0x%x, count = %lx\n", liste - evtList, count); - if (liste - evtList > MAX_SIZE_EVENTLIST) - printf("warning: [sectionsd] all events - response-size: 0x%x\n", liste - evtList); - responseHeader.dataLength = liste - evtList; - - dprintf("[sectionsd] all events - response-size: 0x%x\n", responseHeader.dataLength); - - if ( responseHeader.dataLength == 1 ) - responseHeader.dataLength = 0; - - out: - if (writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) - { - if (responseHeader.dataLength) - writeNbytes(connfd, evtList, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - if (evtList) - delete[] evtList; - - return ; -} -/* -static void commandAllEventsChannelName(int connfd, char *data, const unsigned dataLength) -{ - data[dataLength - 1] = 0; // to be sure it has an trailing 0 - dprintf("Request of all events for '%s'\n", data); - lockServices(); - t_channel_id uniqueServiceKey = findServiceUniqueKeyforServiceName(data); - unlockServices(); - sendAllEvents(connfd, uniqueServiceKey); - return ; -} -*/ -static void commandAllEventsChannelID(int connfd, char *data, const unsigned dataLength) -{ - if (dataLength != sizeof(t_channel_id)) - return ; - - t_channel_id serviceUniqueKey = *(t_channel_id *)data; - - dprintf("Request of all events for " PRINTF_CHANNEL_ID_TYPE "\n", serviceUniqueKey); - - sendAllEvents(connfd, serviceUniqueKey, false); - - return ; -} - -static void commandDumpStatusInformation(int /*connfd*/, char* /*data*/, const unsigned /*dataLength*/) -{ - dputs("Request of status information"); - - readLockEvents(); - - unsigned anzEvents = mySIeventsOrderUniqueKey.size(); - - unsigned anzNVODevents = mySIeventsNVODorderUniqueKey.size(); - - unsigned anzMetaServices = mySIeventUniqueKeysMetaOrderServiceUniqueKey.size(); - - unlockEvents(); - - readLockServices(); - - unsigned anzServices = mySIservicesOrderUniqueKey.size(); - - unsigned anzNVODservices = mySIservicesNVODorderUniqueKey.size(); - - // unsigned anzServices=services.size(); - unlockServices(); - - struct mallinfo speicherinfo = mallinfo(); - - // struct rusage resourceUsage; - // getrusage(RUSAGE_CHILDREN, &resourceUsage); - // getrusage(RUSAGE_SELF, &resourceUsage); - time_t zeit = time(NULL); - -#define MAX_SIZE_STATI 2024 - char stati[MAX_SIZE_STATI]; - - snprintf(stati, MAX_SIZE_STATI, - "$Id: sectionsd.cpp,v 1.305 2009/07/30 12:41:39 seife Exp $\n" - "Current time: %s" - "Hours to cache: %ld\n" - "Hours to cache extended text: %ld\n" - "Events are old %ldmin after their end time\n" - "Number of cached services: %u\n" - "Number of cached nvod-services: %u\n" - "Number of cached events: %u\n" - "Number of cached nvod-events: %u\n" - "Number of cached meta-services: %u\n" - // "Resource-usage: maxrss: %ld ixrss: %ld idrss: %ld isrss: %ld\n" - "Total size of memory occupied by chunks\n" - "handed out by malloc: %d (%dkb)\n" - "Total bytes memory allocated with `sbrk' by malloc,\n" - "in bytes: %d (%dkb)\n" -#ifdef ENABLE_FREESATEPG - "FreeSat enabled\n" -#else - "" -#endif - ,ctime(&zeit), - secondsToCache / (60*60L), secondsExtendedTextCache / (60*60L), oldEventsAre / 60, anzServices, anzNVODservices, anzEvents, anzNVODevents, anzMetaServices, - // resourceUsage.ru_maxrss, resourceUsage.ru_ixrss, resourceUsage.ru_idrss, resourceUsage.ru_isrss, - speicherinfo.uordblks, speicherinfo.uordblks / 1024, - speicherinfo.arena, speicherinfo.arena / 1024 - ); - printf("%s\n", stati); -#if 0 - struct sectionsd::msgResponseHeader responseHeader; - - responseHeader.dataLength = strlen(stati) + 1; - - if (writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) - { - if (responseHeader.dataLength) - writeNbytes(connfd, stati, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); -#endif - return ; -} -/* -static void commandCurrentNextInfoChannelName(int connfd, char *data, const unsigned dataLength) -{ - int nResultDataSize = 0; - char* pResultData = 0; - - data[dataLength - 1] = 0; // to be sure it has an trailing 0 - dprintf("Request of current/next information for '%s'\n", data); - - if (EITThreadsPause()) // -> lock - return ; - - lockServices(); - - lockEvents(); - - SItime zeitEvt1(0, 0); - - const SIevent &evt = findActualSIeventForServiceName(data, zeitEvt1); - - unlockServices(); - - if (evt.service_id != 0) - { //Found - dprintf("current EPG found.\n"); - SItime zeitEvt2(zeitEvt1); - const SIevent &nextEvt = findNextSIevent(evt.uniqueKey(), zeitEvt2); - - if (nextEvt.service_id != 0) - { - dprintf("next EPG found.\n"); - // Folgendes ist grauenvoll, habs aber einfach kopiert aus epgd - // und keine Lust das grossartig zu verschoenern - nResultDataSize = - 12 + 1 + // Unique-Key + del - strlen(evt.getName().c_str()) + 1 + //Name + del - 3 + 2 + 1 + //std:min + del - 4 + 1 + //dauer (mmmm) + del - 3 + 1 + //100 + del - 12 + 1 + // Unique-Key + del - strlen(nextEvt.getName().c_str()) + 1 + //Name + del - 3 + 2 + 1 + //std:min + del - 4 + 1 + 1; //dauer (mmmm) + del + 0 - pResultData = new char[nResultDataSize]; - - if (!pResultData) - { - fprintf(stderr, "low on memory!\n"); - unlockEvents(); - EITThreadsUnPause(); - return ; - } - - struct tm *pStartZeit = localtime(&zeitEvt1.startzeit); - - int nSH(pStartZeit->tm_hour), nSM(pStartZeit->tm_min); - - unsigned dauer = zeitEvt1.dauer / 60; - - unsigned nProcentagePassed = (unsigned)((float)(time(NULL) - zeitEvt1.startzeit) / (float)zeitEvt1.dauer * 100.); - - pStartZeit = localtime(&zeitEvt2.startzeit); - - int nSH2(pStartZeit->tm_hour), nSM2(pStartZeit->tm_min); - - unsigned dauer2 = zeitEvt2.dauer / 60; - - sprintf(pResultData, - "%012llx\n%s\n%02d:%02d\n%04u\n%03u\n%012llx\n%s\n%02d:%02d\n%04u\n", - evt.uniqueKey(), - evt.getName().c_str(), - nSH, nSM, dauer, nProcentagePassed, - nextEvt.uniqueKey(), - nextEvt.getName().c_str(), - nSH2, nSM2, dauer2); - } - } - - unlockEvents(); - EITThreadsUnPause(); // -> unlock - - // response - - struct sectionsd::msgResponseHeader pmResponse; - pmResponse.dataLength = nResultDataSize; - bool rc = writeNbytes(connfd, (const char *)&pmResponse, sizeof(pmResponse), WRITE_TIMEOUT_IN_SECONDS); - - if ( nResultDataSize > 0 ) - { - if (rc == true) - writeNbytes(connfd, pResultData, nResultDataSize, WRITE_TIMEOUT_IN_SECONDS); - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - delete[] pResultData; - } - else - { - dprintf("current/next EPG not found!\n"); - } - - return ; -} -*/ -static void commandComponentTagsUniqueKey(int connfd, char *data, const unsigned dataLength) -{ - int nResultDataSize = 0; - char *pResultData = 0; - char *p; - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - MySIeventsOrderUniqueKey::iterator eFirst; - - if (dataLength != 8) - return ; - - event_id_t uniqueKey = *(event_id_t *)data; - - dprintf("Request of ComponentTags for 0x%llx\n", uniqueKey); - - readLockEvents(); - - nResultDataSize = sizeof(int); // num. Component-Tags - - eFirst = mySIeventsOrderUniqueKey.find(uniqueKey); - - if (eFirst != mySIeventsOrderUniqueKey.end()) - { - //Found - dprintf("ComponentTags found.\n"); - dprintf("components.size %d \n", eFirst->second->components.size()); - - for (SIcomponents::iterator cmp = eFirst->second->components.begin(); cmp != eFirst->second->components.end(); ++cmp) - { - dprintf(" %s \n", cmp->component.c_str()); - nResultDataSize += cmp->component.length() + 1 + // name - sizeof(unsigned char) + // componentType - sizeof(unsigned char) + // componentTag - sizeof(unsigned char); // streamContent - } - } - - pResultData = new char[nResultDataSize]; - - if (!pResultData) - { - fprintf(stderr, "low on memory!\n"); - unlockEvents(); - goto out; - } - - p = pResultData; - - if (eFirst != mySIeventsOrderUniqueKey.end()) - { - *((int *)p) = eFirst->second->components.size(); - p += sizeof(int); - - for (SIcomponents::iterator cmp = eFirst->second->components.begin(); cmp != eFirst->second->components.end(); ++cmp) - { - - strcpy(p, cmp->component.c_str()); - p += cmp->component.length() + 1; - *((unsigned char *)p) = cmp->componentType; - p += sizeof(unsigned char); - *((unsigned char *)p) = cmp->componentTag; - p += sizeof(unsigned char); - *((unsigned char *)p) = cmp->streamContent; - p += sizeof(unsigned char); - } - } - else - { - *((int *)p) = 0; - p += sizeof(int); - } - - unlockEvents(); - - responseHeader.dataLength = nResultDataSize; - - out: - if (writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) - { - if (responseHeader.dataLength) - writeNbytes(connfd, pResultData, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - if (pResultData) - delete[] pResultData; - - return ; -} - -static void commandLinkageDescriptorsUniqueKey(int connfd, char *data, const unsigned dataLength) -{ - int nResultDataSize = 0; - char *pResultData = 0; - char *p; - MySIeventsOrderUniqueKey::iterator eFirst; - int countDescs = 0; - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - event_id_t uniqueKey; - - if (dataLength != 8) - goto out; - - uniqueKey = *(event_id_t *)data; - - dprintf("Request of LinkageDescriptors for 0x%llx\n", uniqueKey); - - readLockEvents(); - - nResultDataSize = sizeof(int); // num. Component-Tags - - eFirst = mySIeventsOrderUniqueKey.find(uniqueKey); - - if (eFirst != mySIeventsOrderUniqueKey.end()) - { - //Found - dprintf("LinkageDescriptors found.\n"); - dprintf("linkage_descs.size %d \n", eFirst->second->linkage_descs.size()); - - - for (SIlinkage_descs::iterator linkage_desc = eFirst->second->linkage_descs.begin(); linkage_desc != eFirst->second->linkage_descs.end(); ++linkage_desc) - { - if (linkage_desc->linkageType == 0xB0) - { - countDescs++; - dprintf(" %s \n", linkage_desc->name.c_str()); - nResultDataSize += linkage_desc->name.length() + 1 + // name - sizeof(t_transport_stream_id) + //transportStreamId - sizeof(t_original_network_id) + //originalNetworkId - sizeof(t_service_id); //serviceId - } - } - } - - pResultData = new char[nResultDataSize]; - - if (!pResultData) - { - fprintf(stderr, "low on memory!\n"); - unlockEvents(); - goto out; - } - - p = pResultData; - - *((int *)p) = countDescs; - p += sizeof(int); - - if (eFirst != mySIeventsOrderUniqueKey.end()) - { - for (SIlinkage_descs::iterator linkage_desc = eFirst->second->linkage_descs.begin(); linkage_desc != eFirst->second->linkage_descs.end(); ++linkage_desc) - { - if (linkage_desc->linkageType == 0xB0) - { - strcpy(p, linkage_desc->name.c_str()); - p += linkage_desc->name.length() + 1; - *((t_transport_stream_id *)p) = linkage_desc->transportStreamId; - p += sizeof(t_transport_stream_id); - *((t_original_network_id *)p) = linkage_desc->originalNetworkId; - p += sizeof(t_original_network_id); - *((t_service_id *)p) = linkage_desc->serviceId; - p += sizeof(t_service_id); - } - } - } - - unlockEvents(); - - responseHeader.dataLength = nResultDataSize; - - out: - if (writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) - { - if (responseHeader.dataLength) - writeNbytes(connfd, pResultData, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - if (pResultData) - delete[] pResultData; - - return ; -} -/* -std::vector messaging_skipped_sections_ID [0x22]; // 0x4e .. 0x6f -static int64_t messaging_sections_max_ID [0x22]; // 0x4e .. 0x6f -static int messaging_sections_got_all [0x22]; // 0x4e .. 0x6f -*/ -//static unsigned char messaging_current_version_number = 0xff; -//static unsigned char messaging_current_section_number = 0; -/* messaging_eit_is_busy does not need locking, it is only written to from CN-Thread */ -static bool messaging_eit_is_busy = false; -static bool messaging_need_eit_version = false; - -//std::vector messaging_sdt_skipped_sections_ID [2]; // 0x42, 0x46 -//static int64_t messaging_sdt_sections_max_ID [2]; // 0x42, 0x46 -//static int messaging_sdt_sections_got_all [2]; // 0x42, 0x46 -/* -static bool messaging_sdt_actual_sections_got_all; // 0x42 -static bool messaging_sdt_actual_sections_so_far [MAX_SECTIONS]; // 0x42 -static t_transponder_id messaging_sdt_other_sections_got_all [MAX_OTHER_SDT]; // 0x46 -static bool messaging_sdt_other_sections_so_far [MAX_CONCURRENT_OTHER_SDT] [MAX_SECTIONS]; // 0x46 -static t_transponder_id messaging_sdt_other_tid [MAX_CONCURRENT_OTHER_SDT]; // 0x46 -*/ -#ifdef UPDATE_NETWORKS -static int messaging_bat_last_section [MAX_BAT]; // 0x4A -static int messaging_bat_sections_so_far [MAX_BAT] [MAX_SECTIONS]; // 0x4A -static t_bouquet_id messaging_bat_bouquet_id [MAX_BAT]; // 0x4A - -//static bool sdt_backoff = true; -//static bool new_services = false; -/* -static bool nit_backoff = true; -static bool messaging_nit_actual_sections_got_all; // 0x40 -static bool messaging_nit_actual_sections_so_far [MAX_SECTIONS]; // 0x40 -static t_network_id messaging_nit_other_sections_got_all [MAX_OTHER_NIT]; // 0x41 -static bool messaging_nit_other_sections_so_far [MAX_CONCURRENT_OTHER_NIT] [MAX_SECTIONS]; // 0x41 -static t_network_id messaging_nit_other_nid [MAX_CONCURRENT_OTHER_NIT]; // 0x41 -*/ -/* nessaging_nit_nid does not need locking, because it is only used in one thread (nit thread). */ -static t_network_id messaging_nit_nid[MAX_NIDs]; // 0x40,0x41 -/* nessaging_sdt_tid does not need locking, because it is only used in one thread (sdt thread). */ -static t_transponder_id messaging_sdt_tid[MAX_SDTs]; // 0x42,0x46 -static int auto_scanning = 0; -#endif -std::string epg_dir(""); - -static void commandserviceChanged(int connfd, char *data, const unsigned dataLength) -{ - t_channel_id *uniqueServiceKey; - if (dataLength != sizeof(sectionsd::commandSetServiceChanged)) - goto out; - - uniqueServiceKey = &(((sectionsd::commandSetServiceChanged *)data)->channel_id); - - dprintf("[sectionsd] commandserviceChanged: Service changed to " PRINTF_CHANNEL_ID_TYPE "\n", *uniqueServiceKey); - - messaging_last_requested = time_monotonic(); - - if(checkBlacklist(*uniqueServiceKey)) - { - if (!channel_is_blacklisted) { - channel_is_blacklisted = true; - dmxCN.request_pause(); - dmxEIT.request_pause(); -#ifdef UPDATE_NETWORKS - dmxNIT.request_pause(); - dmxSDT.request_pause(); -#endif -#ifdef ENABLE_PPT - dmxPPT.request_pause(); -#endif - } - xprintf("[sectionsd] commandserviceChanged: service is filtered!\n"); - } - else - { - if (channel_is_blacklisted) { - channel_is_blacklisted = false; - dmxCN.request_unpause(); - dmxEIT.request_unpause(); -#ifdef UPDATE_NETWORKS - dmxNIT.request_unpause(); - dmxSDT.request_unpause(); -#endif -#ifdef ENABLE_PPT - dmxPPT.request_unpause(); -#endif - xprintf("[sectionsd] commandserviceChanged: service is no longer filtered!\n"); - } - } - - if(checkNoDVBTimelist(*uniqueServiceKey)) - { - if (dvb_time_update) { - dvb_time_update = false; - } - xprintf("[sectionsd] commandserviceChanged: DVB time update is blocked!\n"); - } - else - { - if (!dvb_time_update) { - dvb_time_update = true; - xprintf("[sectionsd] commandserviceChanged: DVB time update is allowed!\n"); - } - } - - if (messaging_current_servicekey != *uniqueServiceKey) - { - //if (debug) showProfiling("[sectionsd] commandserviceChanged: before events lock"); - writeLockEvents(); - //if (debug) showProfiling("[sectionsd] commandserviceChanged: after events lock"); - if (myCurrentEvent) { - delete myCurrentEvent; - myCurrentEvent = NULL; - } - if (myNextEvent) { - delete myNextEvent; - myNextEvent = NULL; - } - unlockEvents(); - writeLockMessaging(); - messaging_current_servicekey = *uniqueServiceKey; - messaging_have_CN = 0x00; - messaging_got_CN = 0x00; - messaging_zap_detected = true; -#ifdef UPDATE_NETWORKS - for ( int i = 0; i < MAX_BAT; i++) { - messaging_bat_bouquet_id[i] = 0; - messaging_bat_last_section[i] = 0; - for ( int j= 0; j < MAX_SECTIONS; j++) - messaging_bat_sections_so_far[i][j] = 0; - } -#endif - messaging_need_eit_version = false; - unlockMessaging(); - dmxCN.setCurrentService(messaging_current_servicekey & 0xffff); - dmxEIT.setCurrentService(messaging_current_servicekey & 0xffff); -#ifdef ENABLE_FREESATEPG - dmxFSEIT.setCurrentService(messaging_current_servicekey & 0xffff); -#endif - } - else - dprintf("[sectionsd] commandserviceChanged: no change...\n"); - - out: - struct sectionsd::msgResponseHeader msgResponse; - msgResponse.dataLength = 0; - writeNbytes(connfd, (const char *)&msgResponse, sizeof(msgResponse), WRITE_TIMEOUT_IN_SECONDS); - - dprintf("[sectionsd] commandserviceChanged: END!!\n"); - return ; -} - -/* send back the current and next event for the channel id passed to it - * Works like that: - * - if the currently running program is requested, return myCurrentEvent and myNextEvent, - * if they are present (filled in by cnThread) - * - if one or both of those are not present, or if a different program than the currently - * running is requested, search the missing events in the list of events gathered by the - * EIT and PPT threads, based on the current time. - * - * TODO: the handling of "flag" should be vastly simplified. - */ -static void commandCurrentNextInfoChannelID(int connfd, char *data, const unsigned dataLength) -{ - int nResultDataSize = 0; - char* pResultData = 0; - char* p; - SIevent currentEvt; - SIevent nextEvt; - unsigned flag = 0, flag2=0; - /* ugly hack: retry fetching current/next by restarting dmxCN if this is true */ - bool change = false; - struct sectionsd::msgResponseHeader pmResponse; - - t_channel_id * uniqueServiceKey = (t_channel_id *)data; - - if (dataLength != sizeof(t_channel_id)) - goto out; - - dprintf("[sectionsd] Request of current/next information for " PRINTF_CHANNEL_ID_TYPE "\n", *uniqueServiceKey); - - readLockEvents(); - /* if the currently running program is requested... */ - if (*uniqueServiceKey == messaging_current_servicekey) { - /* ...check for myCurrentEvent and myNextEvent */ - if (!myCurrentEvent) { - dprintf("!myCurrentEvent "); - change = true; - flag |= CSectionsdClient::epgflags::not_broadcast; - } else { - currentEvt = *myCurrentEvent; - flag |= CSectionsdClient::epgflags::has_current; // aktuelles event da... - flag |= CSectionsdClient::epgflags::has_anything; - } - if (!myNextEvent) { - dprintf("!myNextEvent "); - change = true; - } else { - nextEvt = *myNextEvent; - if (flag & CSectionsdClient::epgflags::not_broadcast) { - dprintf("CSectionsdClient::epgflags::has_no_current\n"); - flag = CSectionsdClient::epgflags::has_no_current; - } - flag |= CSectionsdClient::epgflags::has_next; // aktuelles event da... - flag |= CSectionsdClient::epgflags::has_anything; - } - } - - //dprintf("flag: 0x%x, has_current: 0x%x has_next: 0x%x\n", flag, CSectionsdClient::epgflags::has_current, CSectionsdClient::epgflags::has_next); - /* if another than the currently running program is requested, then flag will still be 0 - if either the current or the next event is not found, this condition will be true, too. - */ - if ((flag & (CSectionsdClient::epgflags::has_current|CSectionsdClient::epgflags::has_next)) != - (CSectionsdClient::epgflags::has_current|CSectionsdClient::epgflags::has_next)) { - //dprintf("commandCurrentNextInfoChannelID: current or next missing!\n"); - SItime zeitEvt1(0, 0); - if (!(flag & CSectionsdClient::epgflags::has_current)) { - currentEvt = findActualSIeventForServiceUniqueKey(*uniqueServiceKey, zeitEvt1, 0, &flag2); - } else { - zeitEvt1.startzeit = currentEvt.times.begin()->startzeit; - zeitEvt1.dauer = currentEvt.times.begin()->dauer; - } - SItime zeitEvt2(zeitEvt1); - - if (currentEvt.getName().empty() && flag2 != 0) - { - dprintf("commandCurrentNextInfoChannelID change1\n"); - change = true; - } - - if (currentEvt.service_id != 0) - { //Found - flag &= (CSectionsdClient::epgflags::has_no_current|CSectionsdClient::epgflags::not_broadcast)^(unsigned)-1; - flag |= CSectionsdClient::epgflags::has_current; - flag |= CSectionsdClient::epgflags::has_anything; - dprintf("[sectionsd] current EPG found. service_id: %x, flag: 0x%x\n",currentEvt.service_id, flag); - - if (!(flag & CSectionsdClient::epgflags::has_next)) { - dprintf("*nextEvt not from cur/next V1!\n"); - nextEvt = findNextSIevent(currentEvt.uniqueKey(), zeitEvt2); - } - } - else - { // no current event... - readLockServices(); - - MySIservicesOrderUniqueKey::iterator si = mySIservicesOrderUniqueKey.end(); - si = mySIservicesOrderUniqueKey.find(*uniqueServiceKey); - - if (si != mySIservicesOrderUniqueKey.end()) - { - dprintf("[sectionsd] current service has%s scheduled events, and has%s present/following events\n", si->second->eitScheduleFlag() ? "" : " no", si->second->eitPresentFollowingFlag() ? "" : " no" ); - - if ( /*( !si->second->eitScheduleFlag() ) || */ - ( !si->second->eitPresentFollowingFlag() ) ) - { - flag |= CSectionsdClient::epgflags::not_broadcast; - } - } - unlockServices(); - - if ( flag2 & CSectionsdClient::epgflags::has_anything ) - { - flag |= CSectionsdClient::epgflags::has_anything; - if (!(flag & CSectionsdClient::epgflags::has_next)) { - dprintf("*nextEvt not from cur/next V2!\n"); - nextEvt = findNextSIeventForServiceUniqueKey(*uniqueServiceKey, zeitEvt2); - } - - if (nextEvt.service_id != 0) - { - MySIeventsOrderUniqueKey::iterator eFirst = mySIeventsOrderUniqueKey.find(*uniqueServiceKey); - - if (eFirst != mySIeventsOrderUniqueKey.end()) - { - // this is a race condition if first entry found is == mySIeventsOrderUniqueKey.begin() - // so perform a check - if (eFirst != mySIeventsOrderUniqueKey.begin()) - --eFirst; - - if (eFirst != mySIeventsOrderUniqueKey.begin()) - { - time_t azeit = time(NULL); - - if (eFirst->second->times.begin()->startzeit < azeit && - eFirst->second->uniqueKey() == nextEvt.uniqueKey() - 1) - flag |= CSectionsdClient::epgflags::has_no_current; - } - } - } - } - } - if (nextEvt.service_id != 0) - { - flag &= CSectionsdClient::epgflags::not_broadcast^(unsigned)-1; - dprintf("[sectionsd] next EPG found. service_id: %x, flag: 0x%x\n",nextEvt.service_id, flag); - flag |= CSectionsdClient::epgflags::has_next; - } - else if (flag != 0) - { - dprintf("commandCurrentNextInfoChannelID change2 flag: 0x%02x\n", flag); - change = true; - } - } - - if (currentEvt.service_id != 0) - { - /* check for nvod linkage */ - for (unsigned int i = 0; i < currentEvt.linkage_descs.size(); i++) - if (currentEvt.linkage_descs[i].linkageType == 0xB0) - { - fprintf(stderr,"[sectionsd] linkage in current EPG found.\n"); - flag |= CSectionsdClient::epgflags::current_has_linkagedescriptors; - break; - } - } else - flag |= CSectionsdClient::epgflags::has_no_current; - - nResultDataSize = - sizeof(event_id_t) + // Unique-Key - sizeof(CSectionsdClient::sectionsdTime) + // zeit - currentEvt.getName().length() + 1 + // name + '\0' - sizeof(event_id_t) + // Unique-Key - sizeof(CSectionsdClient::sectionsdTime) + // zeit - nextEvt.getName().length() + 1 + // name + '\0' - sizeof(unsigned) + // flags - 1 // CurrentFSK - ; - - pResultData = new char[nResultDataSize]; - time_t now; - - if (!pResultData) - { - fprintf(stderr, "low on memory!\n"); - unlockEvents(); - nResultDataSize = 0; // send empty response - goto out; - } - - dprintf("currentEvt: '%s' (%04x) nextEvt: '%s' (%04x) flag: 0x%02x\n", - currentEvt.getName().c_str(), currentEvt.eventID, - nextEvt.getName().c_str(), nextEvt.eventID, flag); - - CSectionsdClient::sectionsdTime time_cur; - CSectionsdClient::sectionsdTime time_nxt; - now = time(NULL); - time_cur.startzeit = currentEvt.times.begin()->startzeit; - time_cur.dauer = currentEvt.times.begin()->dauer; - time_nxt.startzeit = nextEvt.times.begin()->startzeit; - time_nxt.dauer = nextEvt.times.begin()->dauer; - /* for nvod events that have multiple times, find the one that matches the current time... */ - if (currentEvt.times.size() > 1) { - for (SItimes::iterator t = currentEvt.times.begin(); t != currentEvt.times.end(); ++t) { - if ((long)now < (long)(t->startzeit + t->dauer) && (long)now > (long)t->startzeit) { - time_cur.startzeit = t->startzeit; - time_cur.dauer =t->dauer; - break; - } - } - } - /* ...and the one after that. */ - if (nextEvt.times.size() > 1) { - for (SItimes::iterator t = nextEvt.times.begin(); t != nextEvt.times.end(); ++t) { - if ((long)(time_cur.startzeit + time_cur.dauer) <= (long)(t->startzeit)) { // TODO: it's not "long", it's "time_t" - time_nxt.startzeit = t->startzeit; - time_nxt.dauer =t->dauer; - break; - } - } - } - - p = pResultData; - *((event_id_t *)p) = currentEvt.uniqueKey(); - p += sizeof(event_id_t); - *((CSectionsdClient::sectionsdTime *)p) = time_cur; - p += sizeof(CSectionsdClient::sectionsdTime); - strcpy(p, currentEvt.getName().c_str()); - p += currentEvt.getName().length() + 1; - *((event_id_t *)p) = nextEvt.uniqueKey(); - p += sizeof(event_id_t); - *((CSectionsdClient::sectionsdTime *)p) = time_nxt; - p += sizeof(CSectionsdClient::sectionsdTime); - strcpy(p, nextEvt.getName().c_str()); - p += nextEvt.getName().length() + 1; - *((unsigned*)p) = flag; - p += sizeof(unsigned); - *p = currentEvt.getFSK(); - p++; - - unlockEvents(); - - //dprintf("change: %s, messaging_eit_busy: %s, last_request: %d\n", change?"true":"false", messaging_eit_is_busy?"true":"false",(time_monotonic() - messaging_last_requested)); - if (change && !messaging_eit_is_busy && (time_monotonic() - messaging_last_requested) < 11) { - /* restart dmxCN, but only if it is not already running, and only for 10 seconds */ - dprintf("change && !messaging_eit_is_busy => dmxCN.change(0)\n"); - dmxCN.change(0); - } - - // response - - out: - pmResponse.dataLength = nResultDataSize; - bool rc = writeNbytes(connfd, (const char *)&pmResponse, sizeof(pmResponse), WRITE_TIMEOUT_IN_SECONDS); - - if ( nResultDataSize > 0 ) - { - if (rc == true) - writeNbytes(connfd, pResultData, nResultDataSize, WRITE_TIMEOUT_IN_SECONDS); - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - delete[] pResultData; - } - else - { - dprintf("[sectionsd] current/next EPG not found!\n"); - } - - return ; -} - -// Sendet ein EPG, unlocked die events, unpaused dmxEIT - -static void sendEPG(int connfd, const SIevent& e, const SItime& t, int shortepg = 0) -{ - - struct sectionsd::msgResponseHeader responseHeader; - - if (!shortepg) - { - // new format - 0 delimiters - responseHeader.dataLength = - sizeof(event_id_t) + // Unique-Key - e.getName().length() + 1 + // Name + del - e.getText().length() + 1 + // Text + del - e.getExtendedText().length() + 1 + // ext + del - // 21.07.2005 - rainerk - // Send extended events - e.itemDescription.length() + 1 + // Item Description + del - e.item.length() + 1 + // Item + del - e.contentClassification.length() + 1 + // Text + del - e.userClassification.length() + 1 + // ext + del - 1 + // fsk - sizeof(CSectionsdClient::sectionsdTime); // zeit - } - else - responseHeader.dataLength = - e.getName().length() + 1 + // Name + del - e.getText().length() + 1 + // Text + del - e.getExtendedText().length() + 1 + 1; // ext + del + 0 - - char* msgData = new char[responseHeader.dataLength]; - - if (!msgData) - { - fprintf(stderr, "sendEPG: low on memory!\n"); - unlockEvents(); - responseHeader.dataLength = 0; - goto out; - } - - if (!shortepg) - { - char *p = msgData; - *((event_id_t *)p) = e.uniqueKey(); - p += sizeof(event_id_t); - - strcpy(p, e.getName().c_str()); - p += e.getName().length() + 1; - strcpy(p, e.getText().c_str()); - p += e.getText().length() + 1; - strcpy(p, e.getExtendedText().c_str()); - p += e.getExtendedText().length() + 1; - // 21.07.2005 - rainerk - // Send extended events - strcpy(p, e.itemDescription.c_str()); - p += e.itemDescription.length() + 1; - strcpy(p, e.item.c_str()); - p += e.item.length() + 1; - -// strlen(userClassification.c_str()) is not equal to e.userClassification.length() -// because of binary data same is with contentClassification - // add length - *p = (unsigned char)e.contentClassification.length(); - p++; - memmove(p, e.contentClassification.data(), e.contentClassification.length()); - p += e.contentClassification.length(); - - *p = (unsigned char)e.userClassification.length(); - p++; - memmove(p, e.userClassification.data(), e.userClassification.length()); - p += e.userClassification.length(); - - *p = e.getFSK(); - p++; - - CSectionsdClient::sectionsdTime zeit; - zeit.startzeit = t.startzeit; - zeit.dauer = t.dauer; - *((CSectionsdClient::sectionsdTime *)p) = zeit; - p += sizeof(CSectionsdClient::sectionsdTime); - - } - else - sprintf(msgData, - "%s\xFF%s\xFF%s\xFF", - e.getName().c_str(), - e.getText().c_str(), - e.getExtendedText().c_str() - ); - - unlockEvents(); - - out: - if (writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS)) { - if (responseHeader.dataLength) - writeNbytes(connfd, msgData, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - if (msgData) - delete[] msgData; -} - -static void commandGetNextEPG(int connfd, char *data, const unsigned dataLength) -{ - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - - if (dataLength != 8 + 4) { - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - return ; - } - - event_id_t * uniqueEventKey = (event_id_t *)data; - - time_t *starttime = (time_t *)(data + 8); - - dprintf("Request of next epg for 0x%llx %s", *uniqueEventKey, ctime(starttime)); - - readLockEvents(); - - SItime zeit(*starttime, 0); - - const SIevent &nextEvt = findNextSIevent(*uniqueEventKey, zeit); - - if (nextEvt.service_id != 0) - { - dprintf("next epg found.\n"); - sendEPG(connfd, nextEvt, zeit); -// this call is made in sendEPG() -// unlockEvents(); - return; - } - - unlockEvents(); - dprintf("next epg not found!\n"); - - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - return ; -} - -static void commandActualEPGchannelID(int connfd, char *data, const unsigned dataLength) -{ - if (dataLength != sizeof(t_channel_id)) - return ; - - t_channel_id * uniqueServiceKey = (t_channel_id *)data; - SIevent evt; - SItime zeit(0, 0); - - dprintf("[commandActualEPGchannelID] Request of current EPG for " PRINTF_CHANNEL_ID_TYPE "\n", * uniqueServiceKey); - - readLockEvents(); - if (*uniqueServiceKey == messaging_current_servicekey) { - if (myCurrentEvent) { - evt = *myCurrentEvent; - zeit.startzeit = evt.times.begin()->startzeit; - zeit.dauer = evt.times.begin()->dauer; - if (evt.times.size() > 1) { - time_t now = time(NULL); - for (SItimes::iterator t = evt.times.begin(); t != evt.times.end(); ++t) { - if ((long)now < (long)(t->startzeit + t->dauer) && (long)now > (long)t->startzeit) { - zeit.startzeit = t->startzeit; - zeit.dauer = t->dauer; - break; - } - } - } - } - } - - if (evt.service_id == 0) - { - dprintf("[commandActualEPGchannelID] evt.service_id == 0 ==> no myCurrentEvent!\n"); - evt = findActualSIeventForServiceUniqueKey(*uniqueServiceKey, zeit); - } - - if (evt.service_id != 0) - { - dprintf("EPG found.\n"); - sendEPG(connfd, evt, zeit); - return; - } - - unlockEvents(); - dprintf("EPG not found!\n"); - -// out: - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - - return ; -} - -static void commandGetEPGPrevNext(int connfd, char *data, const unsigned dataLength) -{ - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - char* msgData = NULL; - - if (dataLength != 8 + 4) { - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - return; - } - - event_id_t * uniqueEventKey = (event_id_t *)data; - - time_t *starttime = (time_t *)(data + 8); - SItime zeit(*starttime, 0); - SItime prev_zeit(0, 0); - SItime next_zeit(0, 0); - SIevent prev_evt; - SIevent next_evt; - - dprintf("Request of Prev/Next EPG for 0x%llx %s", *uniqueEventKey, ctime(starttime)); - - readLockEvents(); - - findPrevNextSIevent(*uniqueEventKey, zeit, prev_evt, prev_zeit, next_evt, next_zeit); - - responseHeader.dataLength = - 12 + 1 + // Unique-Key + del - 8 + 1 + // start time + del - 12 + 1 + // Unique-Key + del - 8 + 1 + 1; // start time + del - - msgData = new char[responseHeader.dataLength]; - - if (!msgData) - { - fprintf(stderr, "low on memory!\n"); - unlockEvents(); - responseHeader.dataLength = 0; // empty response - goto out; - } - - sprintf(msgData, "%012llx\xFF%08lx\xFF%012llx\xFF%08lx\xFF", - prev_evt.uniqueKey(), - prev_zeit.startzeit, - next_evt.uniqueKey(), - next_zeit.startzeit - ); - unlockEvents(); - - out: - if (writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS)) { - if (responseHeader.dataLength) - writeNbytes(connfd, msgData, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } else - dputs("[sectionsd] Fehler/Timeout bei write"); - - if (msgData) - delete[] msgData; - - return ; -} - -// Mostly copied from epgd (something bugfixed ;) ) -/* -static void commandActualEPGchannelName(int connfd, char *data, const unsigned dataLength) -{ - int nResultDataSize = 0; - char* pResultData = 0; - - data[dataLength - 1] = 0; // to be sure it has an trailing 0 - dprintf("Request of actual EPG for '%s'\n", data); - - if (EITThreadsPause()) // -> lock - return ; - - lockServices(); - - lockEvents(); - - SItime zeitEvt(0, 0); - - const SIevent &evt = findActualSIeventForServiceName(data, zeitEvt); - - unlockServices(); - - if (evt.service_id != 0) - { //Found - dprintf("EPG found.\n"); - nResultDataSize = - 12 + 1 + // Unique-Key + del - strlen(evt.getName().c_str()) + 1 + //Name + del - strlen(evt.getText().c_str()) + 1 + //Text + del - strlen(evt.getExtendedText().c_str()) + 1 + //ext + del - 3 + 3 + 4 + 1 + //dd.mm.yyyy + del - 3 + 2 + 1 + //std:min + del - 3 + 2 + 1 + //std:min+ del - 3 + 1 + 1; //100 + del + 0 - pResultData = new char[nResultDataSize]; - - if (!pResultData) - { - fprintf(stderr, "low on memory!\n"); - unlockEvents(); - EITThreadsUnPause(); - return ; - } - - struct tm *pStartZeit = localtime(&zeitEvt.startzeit); - - int nSDay(pStartZeit->tm_mday), nSMon(pStartZeit->tm_mon + 1), nSYear(pStartZeit->tm_year + 1900), - nSH(pStartZeit->tm_hour), nSM(pStartZeit->tm_min); - - long int uiEndTime(zeitEvt.startzeit + zeitEvt.dauer); - - struct tm *pEndeZeit = localtime((time_t*) & uiEndTime); - - int nFH(pEndeZeit->tm_hour), nFM(pEndeZeit->tm_min); - - unsigned nProcentagePassed = (unsigned)((float)(time(NULL) - zeitEvt.startzeit) / (float)zeitEvt.dauer * 100.); - - sprintf(pResultData, "%012llx\xFF%s\xFF%s\xFF%s\xFF%02d.%02d.%04d\xFF%02d:%02d\xFF%02d:%02d\xFF%03u\xFF", - evt.uniqueKey(), - evt.getName().c_str(), - evt.getText().c_str(), - evt.getExtendedText().c_str(), nSDay, nSMon, nSYear, nSH, nSM, nFH, nFM, nProcentagePassed ); - } - else - dprintf("actual EPG not found!\n"); - - unlockEvents(); - - EITThreadsUnPause(); // -> unlock - - // response - - struct sectionsd::msgResponseHeader pmResponse; - - pmResponse.dataLength = nResultDataSize; - - bool rc = writeNbytes(connfd, (const char *)&pmResponse, sizeof(pmResponse), WRITE_TIMEOUT_IN_SECONDS); - - if ( nResultDataSize > 0 ) - { - if (rc == true) - writeNbytes(connfd, pResultData, nResultDataSize, WRITE_TIMEOUT_IN_SECONDS); - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - delete[] pResultData; - } -} -*/ - -bool channel_in_requested_list(t_channel_id * clist, t_channel_id chid, int len) -{ - if(len == 0) return true; - for(int i = 0; i < len; i++) { - if(clist[i] == chid) - return true; - } - return false; -} -#if 0 -bool channel_in_requested_list(std::vector *chidlist, t_channel_id chid) -{ - if (chidlist->empty()) return true; - for (std::vector ::iterator i=chidlist->begin(); i!=chidlist->end(); i++) { - if (*i == chid) return true; - } - return false; -} -#endif -static void sendEventList(int connfd, const unsigned char serviceTyp1, const unsigned char serviceTyp2 = 0, int sendServiceName = 1, t_channel_id * chidlist = NULL, int clen = 0) -{ -#define MAX_SIZE_BIGEVENTLIST 128*1024 - - char *evtList = new char[MAX_SIZE_BIGEVENTLIST]; // 128k mssen reichen... schaut euch mal das Ergebnis fr loop an, jedesmal wenn die Senderliste aufgerufen wird - char *liste; - long count=0; - t_channel_id uniqueNow = 0; - t_channel_id uniqueOld = 0; - bool found_already = false; - time_t azeit = time(NULL); - std::string sname; - struct sectionsd::msgResponseHeader msgResponse; - msgResponse.dataLength = 0; - - if (!evtList) - { - fprintf(stderr, "low on memory!\n"); - goto out; - } - - *evtList = 0; - liste = evtList; - - readLockEvents(); - - /* !!! FIX ME: if the box starts on a channel where there is no EPG sent, it hangs!!! */ - for (MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator e = mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin(); e != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end(); ++e) - { - uniqueNow = (*e)->get_channel_id(); - if (!channel_in_requested_list(chidlist, uniqueNow, clen)) continue; - if ( uniqueNow != uniqueOld ) - { - found_already = true; - readLockServices(); - // new service, check service- type - MySIservicesOrderUniqueKey::iterator s = mySIservicesOrderUniqueKey.find(uniqueNow); - - if (s != mySIservicesOrderUniqueKey.end()) - { - if (s->second->serviceTyp == serviceTyp1 || (serviceTyp2 && s->second->serviceTyp == serviceTyp2)) - { - sname = s->second->serviceName; - found_already = false; - } - } - else - { - // wenn noch nie hingetuned wurde, dann gibts keine Info ber den ServiceTyp... - // im Zweifel mitnehmen - found_already = false; - } - unlockServices(); - - uniqueOld = uniqueNow; - } - - if ( !found_already ) - { - std::string eName = (*e)->getName(); - std::string eText = (*e)->getText(); - std::string eExtendedText = (*e)->getExtendedText(); - - for (SItimes::iterator t = (*e)->times.begin(); t != (*e)->times.end(); ++t) - { - if (t->startzeit <= azeit && azeit <= (long)(t->startzeit + t->dauer)) - { - if (sendServiceName) - { - count += 13 + sname.length() + 1 + eName.length() + 1; - if (count < MAX_SIZE_BIGEVENTLIST) { - sprintf(liste, "%012llx\n", (*e)->uniqueKey()); - liste += 13; - strcpy(liste, sname.c_str()); - liste += sname.length(); - *liste = '\n'; - liste++; - strcpy(liste, eName.c_str()); - liste += eName.length(); - *liste = '\n'; - liste++; - } else { - dprintf("warning: sendEventList - eventlist cut\n"); - break; - } - - } // if sendServiceName - else - { - count += sizeof(event_id_t) + 4 + 4 + eName.length() + 1; - if (eText.empty()) - { - count += eExtendedText.substr(0, 50).length(); - } - else - { - count += eText.length(); - } - count++; - - if (count < MAX_SIZE_BIGEVENTLIST) { - *((event_id_t *)liste) = (*e)->uniqueKey(); - liste += sizeof(event_id_t); - *((unsigned *)liste) = t->startzeit; - liste += 4; - *((unsigned *)liste) = t->dauer; - liste += 4; - strcpy(liste, eName.c_str()); - liste += eName.length(); - liste++; - - if (eText.empty()) - { - strcpy(liste, eExtendedText.substr(0, 50).c_str()); - liste += strlen(liste); - } - else - { - strcpy(liste, eText.c_str()); - liste += eText.length(); - } - liste++; - } else { - dprintf("warning: sendEventList - eventlist cut\n"); - break; - } - } // else !sendServiceName - - found_already = true; - - break; - } - } - } - } - - if (sendServiceName && (count+1 < MAX_SIZE_BIGEVENTLIST)) - { - *liste = 0; - liste++; - count++; - } - - unlockEvents(); - - //printf("warning: [sectionsd] sendEventList - response-size: 0x%x, count = %lx\n", liste - evtList, count); - if (liste - evtList > MAX_SIZE_BIGEVENTLIST) - printf("warning: [sectionsd] sendEventList- response-size: 0x%x\n", liste - evtList); - msgResponse.dataLength = liste - evtList; - dprintf("[sectionsd] sendEventList - response-size: 0x%x\n", msgResponse.dataLength); - - if ( msgResponse.dataLength == 1 ) - msgResponse.dataLength = 0; - - out: - if (writeNbytes(connfd, (const char *)&msgResponse, sizeof(msgResponse), WRITE_TIMEOUT_IN_SECONDS) == true) - { - if (msgResponse.dataLength) - writeNbytes(connfd, evtList, msgResponse.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - if (evtList) - delete[] evtList; -} - -// Sendet ein short EPG, unlocked die events, unpaused dmxEIT - -static void sendShort(int connfd, const SIevent& e, const SItime& t) -{ - - struct sectionsd::msgResponseHeader responseHeader; - - responseHeader.dataLength = - 12 + 1 + // Unique-Key + del - e.getName().length() + 1 + // name + del - 8 + 1 + // start time + del - 8 + 1 + 1; // duration + del + 0 - char* msgData = new char[responseHeader.dataLength]; - - if (!msgData) - { - fprintf(stderr, "low on memory!\n"); - unlockEvents(); - responseHeader.dataLength = 0; - goto out; - } - - sprintf(msgData, - "%012llx\n%s\n%08lx\n%08x\n", - e.uniqueKey(), - e.getName().c_str(), - t.startzeit, - t.dauer - ); - unlockEvents(); - - out: - if(writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS)) { - if (responseHeader.dataLength) - writeNbytes(connfd, msgData, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } else - dputs("[sectionsd] Fehler/Timeout bei write"); - - if (msgData) - delete[] msgData; -} - -static void commandGetNextShort(int connfd, char *data, const unsigned dataLength) -{ - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - if (dataLength != 8 + 4) { - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - return; - } - - event_id_t * uniqueEventKey = (event_id_t *)data; - - time_t *starttime = (time_t *)(data + 8); - SItime zeit(*starttime, 0); - - dprintf("Request of next short for 0x%llx %s", *uniqueEventKey, ctime(starttime)); - - readLockEvents(); - - const SIevent &nextEvt = findNextSIevent(*uniqueEventKey, zeit); - - if (nextEvt.service_id != 0) - { - dprintf("next short found.\n"); - sendShort(connfd, nextEvt, zeit); -// this call is made in sendShort() -// unlockEvents(); - return; - } - unlockEvents(); - dprintf("next short not found!\n"); - - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); -} - -static void commandEventListTV(int connfd, char* /*data*/, const unsigned /*dataLength*/) -{ - dputs("Request of TV event list.\n"); - sendEventList(connfd, 0x01, 0x04); -} - -static void commandEventListTVids(int connfd, char* data, const unsigned dataLength) -{ - dputs("Request of TV event list (IDs).\n"); -#if 0 - std::vector chidlist; - if (dataLength>0) { - t_channel_id *tmp = (t_channel_id*)data; - for (uint32_t i=0; i chidlist; - dputs("Request of radio event list (IDs).\n"); - if (dataLength>0) { - t_channel_id *tmp = (t_channel_id*)data; - for (uint i=0; istartzeit == *startzeit) - break; - - if (t != evt.times.end()) - { - dputs("EPG found."); - // Sendet ein EPG, unlocked die events, unpaused dmxEIT - sendEPG(connfd, evt, *t); -// this call is made in sendEPG() -// unlockEvents(); - return; - } - } - - dputs("EPG not found!"); - unlockEvents(); - // response - - writeNbytes(connfd, (const char *)&pmResponse, sizeof(pmResponse), WRITE_TIMEOUT_IN_SECONDS); -} - -static void commandEPGepgIDshort(int connfd, char *data, const unsigned dataLength) -{ - struct sectionsd::msgResponseHeader pmResponse; - pmResponse.dataLength = 0; - - if (dataLength != 8) { - writeNbytes(connfd, (const char *)&pmResponse, sizeof(pmResponse), WRITE_TIMEOUT_IN_SECONDS); - return; - } - - event_id_t * epgID = (event_id_t *)data; - - dprintf("Request of current EPG for 0x%llx\n", *epgID); - - readLockEvents(); - - const SIevent& evt = findSIeventForEventUniqueKey(*epgID); - - if (evt.service_id != 0) - { // Event found - dputs("EPG found."); - sendEPG(connfd, evt, SItime(0, 0), 1); -// this call is made in sendEPG() -// unlockEvents(); - return; - } - - dputs("EPG not found!"); - unlockEvents(); - // response - - writeNbytes(connfd, (const char *)&pmResponse, sizeof(pmResponse), WRITE_TIMEOUT_IN_SECONDS); -} - -static void commandTimesNVODservice(int connfd, char *data, const unsigned dataLength) -{ - MySIservicesNVODorderUniqueKey::iterator si; - char *msgData = 0; - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - t_channel_id uniqueServiceKey; - - if (dataLength != sizeof(t_channel_id)) - goto out; - - uniqueServiceKey = *(t_channel_id *)data; - - dprintf("Request of NVOD times for " PRINTF_CHANNEL_ID_TYPE "\n", uniqueServiceKey); - - readLockServices(); - readLockEvents(); - - si = mySIservicesNVODorderUniqueKey.find(uniqueServiceKey); - - if (si != mySIservicesNVODorderUniqueKey.end()) - { - dprintf("NVODServices: %u\n", si->second->nvods.size()); - - if (si->second->nvods.size()) - { - responseHeader.dataLength = (sizeof(t_service_id) + sizeof(t_original_network_id) + sizeof(t_transport_stream_id) + 4 + 4) * si->second->nvods.size(); - msgData = new char[responseHeader.dataLength]; - - if (!msgData) - { - fprintf(stderr, "low on memory!\n"); - unlockEvents(); - unlockServices(); - responseHeader.dataLength = 0; // empty response - goto out; - } - - char *p = msgData; - // time_t azeit=time(NULL); - - for (SInvodReferences::iterator ni = si->second->nvods.begin(); ni != si->second->nvods.end(); ++ni) - { - // Zeiten sind erstmal dummy, d.h. pro Service eine Zeit - ni->toStream(p); // => p += sizeof(t_service_id) + sizeof(t_original_network_id) + sizeof(t_transport_stream_id); - - SItime zeitEvt1(0, 0); - // const SIevent &evt= - findActualSIeventForServiceUniqueKey(ni->uniqueKey(), zeitEvt1, 15*60); - *(time_t *)p = zeitEvt1.startzeit; - p += 4; - *(unsigned *)p = zeitEvt1.dauer; - p += 4; - - /* MySIeventUniqueKeysMetaOrderServiceUniqueKey::iterator ei=mySIeventUniqueKeysMetaOrderServiceUniqueKey.find(ni->uniqueKey()); - if(ei!=mySIeventUniqueKeysMetaOrderServiceUniqueKey.end()) - { - dprintf("found NVod - Service: %0llx\n", ei->second); - MySIeventsOrderUniqueKey::iterator e=mySIeventsOrderUniqueKey.find(ei->second); - if(e!=mySIeventsOrderUniqueKey.end()) - { - // ist ein MetaEvent, d.h. mit Zeiten fuer NVOD-Event - for(SItimes::iterator t=e->second->times.begin(); t!=e->second->times.end(); t++) - if(t->startzeit<=azeit && azeit<=(long)(t->startzeit+t->dauer)) - { - *(time_t *)p=t->startzeit; - break; - } - } - } - */ - - } - } - } - unlockEvents(); - unlockServices(); - - dprintf("data bytes: %u\n", responseHeader.dataLength); - - out: - if (writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS)) - { - if (responseHeader.dataLength) - writeNbytes(connfd, msgData, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); - - if (msgData) - delete[] msgData; -} - - -static void commandGetIsTimeSet(int connfd, char* /*data*/, const unsigned /*dataLength*/) -{ - sectionsd::responseIsTimeSet rmsg; - - rmsg.IsTimeSet = timeset; - - dprintf("Request of Time-Is-Set %d\n", rmsg.IsTimeSet); - - struct sectionsd::msgResponseHeader responseHeader; - - responseHeader.dataLength = sizeof(rmsg); - - if (writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) - { - writeNbytes(connfd, (const char *)&rmsg, responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); -} - - -static void commandRegisterEventClient(int /*connfd*/, char *data, const unsigned dataLength) -{ - if (dataLength == sizeof(CEventServer::commandRegisterEvent)) - { - eventServer->registerEvent2(((CEventServer::commandRegisterEvent*)data)->eventID, ((CEventServer::commandRegisterEvent*)data)->clientID, ((CEventServer::commandRegisterEvent*)data)->udsName); - - if (((CEventServer::commandRegisterEvent*)data)->eventID == CSectionsdClient::EVT_TIMESET) - messaging_neutrino_sets_time = true; - } -} - - - -static void commandUnRegisterEventClient(int /*connfd*/, char *data, const unsigned dataLength) -{ - if (dataLength == sizeof(CEventServer::commandUnRegisterEvent)) - eventServer->unRegisterEvent2(((CEventServer::commandUnRegisterEvent*)data)->eventID, ((CEventServer::commandUnRegisterEvent*)data)->clientID); -} - - -#ifdef ENABLE_PPT -static void commandSetPrivatePid(int connfd, char *data, const unsigned dataLength) -{ - unsigned short pid; - - if (dataLength != 2) - goto out; - - pid = *((unsigned short*)data); -// if (privatePid != pid) - { - privatePid = pid; - if (pid != 0) { - dprintf("[sectionsd] wakeup PPT Thread, pid=%x\n", pid); - dmxPPT.change( 0 ); - } - } - - out: - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - return ; -} -#endif - -#ifdef UPDATE_NETWORKS -static void commandSetSectionsdScanMode(int connfd, char *data, const unsigned dataLength) -{ - if (dataLength != 4) - goto out; - - writeLockMessaging(); - auto_scanning = *((int*)data); - unlockMessaging(); - - out: - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - return ; - -} -#endif - -static void commandSetConfig(int connfd, char *data, const unsigned /*dataLength*/) -{ - struct sectionsd::msgResponseHeader responseHeader; - struct sectionsd::commandSetConfig *pmsg; - - pmsg = (struct sectionsd::commandSetConfig *)data; -#ifdef UPDATE_NETWORKS - if (pmsg->scanMode != auto_scanning) { - dprintf("new scanMode = %d\n", pmsg->scanMode); - writeLockMessaging(); - auto_scanning = pmsg->scanMode; - unlockMessaging(); - } -#endif - - if (secondsToCache != (long)(pmsg->epg_cache)*24*60L*60L) { - dprintf("new epg_cache = %d\n", pmsg->epg_cache); - writeLockEvents(); - secondsToCache = (long)(pmsg->epg_cache)*24*60L*60L; - unlockEvents(); - } - - if (oldEventsAre != (long)(pmsg->epg_old_events)*60L*60L) { - dprintf("new epg_old_events = %d\n", pmsg->epg_old_events); - writeLockEvents(); - oldEventsAre = (long)(pmsg->epg_old_events)*60L*60L; - unlockEvents(); - } - if (secondsExtendedTextCache != (long)(pmsg->epg_extendedcache)*60L*60L) { - dprintf("new epg_extendedcache = %d\n", pmsg->epg_extendedcache); -// lockEvents(); - writeLockEvents(); - secondsExtendedTextCache = (long)(pmsg->epg_extendedcache)*60L*60L; - unlockEvents(); - } - if (max_events != pmsg->epg_max_events) { - dprintf("new epg_max_events = %d\n", pmsg->epg_max_events); - writeLockEvents(); - max_events = pmsg->epg_max_events; - unlockEvents(); - } - - if (ntprefresh != pmsg->network_ntprefresh) { - dprintf("new network_ntprefresh = %d\n", pmsg->network_ntprefresh); - pthread_mutex_lock(&timeThreadSleepMutex); - ntprefresh = pmsg->network_ntprefresh; - if (timeset) { - // wake up time thread - pthread_cond_broadcast(&timeThreadSleepCond); - } - pthread_mutex_unlock(&timeThreadSleepMutex); - } - - if (ntpenable ^ (pmsg->network_ntpenable == 1)) { - dprintf("new network_ntpenable = %d\n", pmsg->network_ntpenable); - pthread_mutex_lock(&timeThreadSleepMutex); - ntpenable = (pmsg->network_ntpenable == 1); - if (timeset) { - // wake up time thread - pthread_cond_broadcast(&timeThreadSleepCond); - } - pthread_mutex_unlock(&timeThreadSleepMutex); - } - - if (ntpserver.compare((std::string)&data[sizeof(struct sectionsd::commandSetConfig)])) { - ntpserver = (std::string)&data[sizeof(struct sectionsd::commandSetConfig)]; - dprintf("new network_ntpserver = %s\n", ntpserver.c_str()); - ntp_system_cmd = ntp_system_cmd_prefix + ntpserver; - } - - if (epg_dir.compare((std::string)&data[sizeof(struct sectionsd::commandSetConfig) + strlen(&data[sizeof(struct sectionsd::commandSetConfig)]) + 1])) { - epg_dir= (std::string)&data[sizeof(struct sectionsd::commandSetConfig) + strlen(&data[sizeof(struct sectionsd::commandSetConfig)]) + 1]; - dprintf("new epg_dir = %s\n", epg_dir.c_str()); - } - - responseHeader.dataLength = 0; - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - return ; -} - -static void deleteSIexceptEPG() -{ - writeLockServices(); - mySIservicesOrderUniqueKey.clear(); - unlockServices(); -#ifdef UPDATE_NETWORKS - writeLockTransponders(); - mySItranspondersOrderUniqueKey.clear(); - unlockTransponders(); - writeLockBouquets(); - mySIbouquetsOrderUniqueKey.clear(); - unlockBouquets(); - dmxNIT.dropCachedSectionIDs(); - dmxSDT.dropCachedSectionIDs(); -#endif - dmxEIT.dropCachedSectionIDs(); -} - -static void commandFreeMemory(int connfd, char * /*data*/, const unsigned /*dataLength*/) -{ - deleteSIexceptEPG(); - - writeLockEvents(); - mySIeventsOrderFirstEndTimeServiceIDEventUniqueKey.clear(); - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.clear(); - mySIeventsOrderUniqueKey.clear(); - mySIeventsNVODorderUniqueKey.clear(); - unlockEvents(); - - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - return ; -} - -std::string UTF8_to_Latin1(const char * s) -{ - std::string r; - - while ((*s) != 0) - { - if (((*s) & 0xf0) == 0xf0) /* skip (can't be encoded in Latin1) */ - { - s++; - if ((*s) == 0) - return r; - s++; - if ((*s) == 0) - return r; - s++; - if ((*s) == 0) - return r; - } - else if (((*s) & 0xe0) == 0xe0) /* skip (can't be encoded in Latin1) */ - { - s++; - if ((*s) == 0) - return r; - s++; - if ((*s) == 0) - return r; - } - else if (((*s) & 0xc0) == 0xc0) - { - char c = (((*s) & 3) << 6); - s++; - if ((*s) == 0) - return r; - r += (c | ((*s) & 0x3f)); - } - else r += *s; - s++; - } - return r; -} - -static void *insertEventsfromFile(void *) -{ - xmlDocPtr event_parser = NULL; - xmlNodePtr eventfile = NULL; - xmlNodePtr service = NULL; - xmlNodePtr event = NULL; - xmlNodePtr node = NULL; - t_original_network_id onid = 0; - t_transport_stream_id tsid = 0; - t_service_id sid = 0; - char cclass[20]; - char cuser[20]; - std::string indexname; - std::string filename; - std::string epgname; - int ev_count = 0; - - indexname = epg_dir + "index.xml"; - - xmlDocPtr index_parser = parseXmlFile(indexname.c_str()); - - if (index_parser != NULL) { - time_t now = time_monotonic_ms(); - printdate_ms(stdout); - printf("[sectionsd] Reading Information from file %s:\n", indexname.c_str()); - - eventfile = xmlDocGetRootElement(index_parser)->xmlChildrenNode; - - while (eventfile) { - filename = xmlGetAttribute(eventfile, "name"); - epgname = epg_dir + filename; - if (!(event_parser = parseXmlFile(epgname.c_str()))) { - dprintf("unable to open %s for reading\n", epgname.c_str()); - } - else { - service = xmlDocGetRootElement(event_parser)->xmlChildrenNode; - - while (service) { - onid = xmlGetNumericAttribute(service, "original_network_id", 16); - tsid = xmlGetNumericAttribute(service, "transport_stream_id", 16); - sid = xmlGetNumericAttribute(service, "service_id", 16); - - event = service->xmlChildrenNode; - - while (event) { - - SIevent e(onid,tsid,sid,xmlGetNumericAttribute(event, "id", 16)); - - node = event->xmlChildrenNode; - - while (xmlGetNextOccurence(node, "name") != NULL) { - e.setName( std::string(UTF8_to_Latin1(xmlGetAttribute(node, "lang"))), - std::string(xmlGetAttribute(node, "string"))); - node = node->xmlNextNode; - } - while (xmlGetNextOccurence(node, "text") != NULL) { - e.setText( std::string(UTF8_to_Latin1(xmlGetAttribute(node, "lang"))), - std::string(xmlGetAttribute(node, "string"))); - node = node->xmlNextNode; - } - while (xmlGetNextOccurence(node, "item") != NULL) { - e.item = std::string(xmlGetAttribute(node, "string")); - node = node->xmlNextNode; - } - while (xmlGetNextOccurence(node, "item_description") != NULL) { - e.itemDescription = std::string(xmlGetAttribute(node, "string")); - node = node->xmlNextNode; - } - while (xmlGetNextOccurence(node, "extended_text") != NULL) { - e.appendExtendedText( std::string(UTF8_to_Latin1(xmlGetAttribute(node, "lang"))), - std::string(xmlGetAttribute(node, "string"))); - node = node->xmlNextNode; - } - /* - if (xmlGetNextOccurence(node, "description") != NULL) { - if (xmlGetAttribute(node, "name") != NULL) { - e.langName = std::string(UTF8_to_Latin1(xmlGetAttribute(node, "name"))); - } - //printf("Name: %s\n", e->name); - if (xmlGetAttribute(node, "text") != NULL) { - e.langText = std::string(UTF8_to_Latin1(xmlGetAttribute(node, "text"))); - } - if (xmlGetAttribute(node, "item") != NULL) { - e.item = std::string(UTF8_to_Latin1(xmlGetAttribute(node, "item"))); - } - if (xmlGetAttribute(node, "item_description") != NULL) { - e.itemDescription = std::string(UTF8_to_Latin1(xmlGetAttribute(node,"item_description"))); - } - if (xmlGetAttribute(node, "extended_text") != NULL) { - e.langExtendedText = std::string(UTF8_to_Latin1(xmlGetAttribute(node, "extended_text"))); - } - node = node->xmlNextNode; - } -*/ - while (xmlGetNextOccurence(node, "time") != NULL) { - e.times.insert(SItime(xmlGetNumericAttribute(node, "start_time", 10), - xmlGetNumericAttribute(node, "duration", 10))); - node = node->xmlNextNode; - } - - int count = 0; - while (xmlGetNextOccurence(node, "content") != NULL) { - cclass[count] = xmlGetNumericAttribute(node, "class", 16); - cuser[count] = xmlGetNumericAttribute(node, "user", 16); - node = node->xmlNextNode; - count++; - } - e.contentClassification = std::string(cclass, count); - e.userClassification = std::string(cuser, count); - - while (xmlGetNextOccurence(node, "component") != NULL) { - SIcomponent c; - c.streamContent = xmlGetNumericAttribute(node, "stream_content", 16); - c.componentType = xmlGetNumericAttribute(node, "type", 16); - c.componentTag = xmlGetNumericAttribute(node, "tag", 16); - c.component = std::string(xmlGetAttribute(node, "text")); - e.components.insert(c); - node = node->xmlNextNode; - } - while (xmlGetNextOccurence(node, "parental_rating") != NULL) { - e.ratings.insert(SIparentalRating(std::string(UTF8_to_Latin1(xmlGetAttribute(node, "country"))), (unsigned char) xmlGetNumericAttribute(node, "rating", 10))); - node = node->xmlNextNode; - } - while (xmlGetNextOccurence(node, "linkage") != NULL) { - SIlinkage l; - l.linkageType = xmlGetNumericAttribute(node, "type", 16); - l.transportStreamId = xmlGetNumericAttribute(node, "transport_stream_id", 16); - l.originalNetworkId = xmlGetNumericAttribute(node, "original_network_id", 16); - l.serviceId = xmlGetNumericAttribute(node, "service_id", 16); - l.name = std::string(xmlGetAttribute(node, "linkage_descriptor")); - e.linkage_descs.insert(e.linkage_descs.end(), l); - - node = node->xmlNextNode; - } - //lockEvents(); - //writeLockEvents(); - addEvent(e, 0, 0); - ev_count++; - //unlockEvents(); - - event = event->xmlNextNode; - } - - service = service->xmlNextNode; - } - xmlFreeDoc(event_parser); - } - - eventfile = eventfile->xmlNextNode; - } - - xmlFreeDoc(index_parser); - printdate_ms(stdout); - printf("[sectionsd] Reading Information finished after %ld miliseconds (%d events)\n", - time_monotonic_ms()-now, ev_count); - } - reader_ready = true; - - pthread_exit(NULL); -} - -static void commandReadSIfromXML(int connfd, char *data, const unsigned dataLength) -{ - pthread_t thrInsert; - - if (dataLength > 100) - return ; - - writeLockMessaging(); - data[dataLength] = '\0'; - epg_dir = (std::string)data + "/"; - unlockMessaging(); - - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - - pthread_attr_t attr; - pthread_attr_init(&attr); - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - - if (pthread_create (&thrInsert, &attr, insertEventsfromFile, 0 )) - { - perror("sectionsd: pthread_create()"); - } - - pthread_attr_destroy(&attr); - - return ; -} - -static void write_epg_xml_header(FILE * fd, const t_original_network_id onid, const t_transport_stream_id tsid, const t_service_id sid) -{ - fprintf(fd, - "\n" - "\n" - "\n"); - fprintf(fd,"\t\n",onid,tsid,sid); -} - -static void write_index_xml_header(FILE * fd) -{ - fprintf(fd, - "\n" - "\n" - "\n"); -} - -static void write_epgxml_footer(FILE *fd) -{ - fprintf(fd, "\t\n"); - fprintf(fd, "\n"); -} - -static void write_indexxml_footer(FILE *fd) -{ - fprintf(fd, "\n"); -} - -void cp(char * from, char * to) -{ - char cmd[256]; - snprintf(cmd, 256, "cp -f %s %s", from, to); - system(cmd); -} - -static void commandWriteSI2XML(int connfd, char *data, const unsigned dataLength) -{ - FILE * indexfile = NULL; - FILE * eventfile =NULL; - char filename[100] = ""; - char tmpname[100] = ""; - char epgdir[100] = ""; - char eventname[17] = ""; - t_original_network_id onid = 0; - t_transport_stream_id tsid = 0; - t_service_id sid = 0; - - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - - if (dataLength > 100) - goto _ret ; - - strncpy(epgdir, data, dataLength); - epgdir[dataLength] = '\0'; - sprintf(tmpname, "%s/index.tmp", epgdir); - - if (!(indexfile = fopen(tmpname, "w"))) { - printf("[sectionsd] unable to open %s for writing\n", tmpname); - goto _ret; - } - else { - - printf("[sectionsd] Writing Information to file: %s\n", tmpname); - - write_index_xml_header(indexfile); - - readLockEvents(); - - MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey::iterator e = - mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.begin(); - if (e != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) { - onid = (*e)->original_network_id; - tsid = (*e)->transport_stream_id; - sid = (*e)->service_id; - snprintf(eventname,17,"%04x%04x%04x.xml",onid,tsid,sid); - sprintf(filename, "%s/%s", epgdir, eventname); - if (!(eventfile = fopen(filename, "w"))) { - write_indexxml_footer(indexfile); - fclose(indexfile); - goto _done; - } - fprintf(indexfile, "\t\n",eventname); - write_epg_xml_header(eventfile,onid,tsid,sid); - - while (e != mySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey.end()) { - if ( (onid != (*e)->original_network_id) || (tsid != (*e)->transport_stream_id) || (sid != (*e)->service_id) ) { - onid = (*e)->original_network_id; - tsid = (*e)->transport_stream_id; - sid = (*e)->service_id; - write_epgxml_footer(eventfile); - fclose(eventfile); - snprintf(eventname,17,"%04x%04x%04x.xml",onid,tsid,sid); - sprintf(filename, "%s/%s", epgdir, eventname); - if (!(eventfile = fopen(filename, "w"))) { - goto _done; - } - fprintf(indexfile, "\t\n", eventname); - write_epg_xml_header(eventfile,onid,tsid,sid); - } - (*e)->saveXML(eventfile); - e ++; - } - write_epgxml_footer(eventfile); - fclose(eventfile); - - } -_done: - unlockEvents(); - write_indexxml_footer(indexfile); - fclose(indexfile); - - printf("[sectionsd] Writing Information finished\n"); - } - strncpy(filename, data, dataLength); - filename[dataLength] = '\0'; - strncat(filename, "/index.xml", 10); - - cp(tmpname, filename); - unlink(tmpname); -_ret: - eventServer->sendEvent(CSectionsdClient::EVT_WRITE_SI_FINISHED, CEventServer::INITID_SECTIONSD); - return ; -} - -/* dummy1: do not send back anything */ -static void commandDummy1(int, char *, const unsigned) -{ - return; -} - -/* dummy2: send back an empty response */ -static void commandDummy2(int connfd, char *, const unsigned) -{ - struct sectionsd::msgResponseHeader msgResponse; - msgResponse.dataLength = 0; - writeNbytes(connfd, (const char *)&msgResponse, sizeof(msgResponse), WRITE_TIMEOUT_IN_SECONDS); - return; -} - -static void commandAllEventsChannelIDSearch(int connfd, char *data, const unsigned dataLength) -{ - //dprintf("Request of commandAllEventsChannelIDSearch, %d\n",dataLength); - if (dataLength > 5) - { - char *data_ptr = data; - char search = 0; - std::string search_text; - - t_channel_id channel_id = *(t_channel_id*)data_ptr; - data_ptr += sizeof(t_channel_id); - search = *data_ptr; - data_ptr += sizeof(char); - if(search != 0) - search_text = data_ptr; - sendAllEvents(connfd, channel_id, false, search, search_text); - } - return; -} - -static void commandLoadLanguages(int connfd, char* /*data*/, const unsigned /*dataLength*/) -{ - struct sectionsd::msgResponseHeader responseHeader; - bool retval = SIlanguage::loadLanguages(); - responseHeader.dataLength = sizeof(retval); - - if (writeNbytes(connfd, (const char *)&responseHeader, - sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) { - writeNbytes(connfd, (const char *)&retval, - responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); -} - - -static void commandSaveLanguages(int connfd, char* /*data*/, const unsigned /*dataLength*/) -{ - struct sectionsd::msgResponseHeader responseHeader; - bool retval = SIlanguage::saveLanguages(); - responseHeader.dataLength = sizeof(retval); - - if (writeNbytes(connfd, (const char *)&responseHeader, - sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) { - writeNbytes(connfd, (const char *)&retval, - responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } - else - dputs("[sectionsd] Fehler/Timeout bei write"); -} - - -static void commandSetLanguages(int connfd, char* data, const unsigned dataLength) -{ - bool retval = true; - - if (dataLength % 3) { - retval = false; - } else { - std::vector languages; - for (unsigned int i = 0 ; i < dataLength ; ) { - char tmp[4]; - tmp[0] = data[i++]; - tmp[1] = data[i++]; - tmp[2] = data[i++]; - tmp[3] = '\0'; - languages.push_back(tmp); - } - SIlanguage::setLanguages(languages); - } - - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = sizeof(retval); - - if (writeNbytes(connfd, (const char *)&responseHeader, - sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) { - writeNbytes(connfd, (const char *)&retval, responseHeader.dataLength, - WRITE_TIMEOUT_IN_SECONDS); - } else { - dputs("[sectionsd] Fehler/Timeout bei write"); - } -} - - -static void commandGetLanguages(int connfd, char* /* data */, const unsigned /* dataLength */) -{ - std::string retval; - std::vector languages = SIlanguage::getLanguages(); - - for (std::vector::iterator it = languages.begin() ; - it != languages.end() ; it++) { - retval.append(*it); - } - - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = retval.length(); - - if (writeNbytes(connfd, (const char *)&responseHeader, - sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) { - writeNbytes(connfd, (const char *)retval.c_str(), - responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } else { - dputs("[sectionsd] Fehler/Timeout bei write"); - } -} - - -static void commandSetLanguageMode(int connfd, char* data , const unsigned dataLength) -{ - bool retval = true; - CSectionsdClient::SIlanguageMode_t tmp(CSectionsdClient::ALL); - - if (dataLength != sizeof(tmp)) { - retval = false; - } else { - tmp = *(CSectionsdClient::SIlanguageMode_t *)data; - SIlanguage::setMode(tmp); - } - - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = sizeof(retval); - - if (writeNbytes(connfd, (const char *)&responseHeader, - sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) { - writeNbytes(connfd, (const char *)&retval, - responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } else { - dputs("[sectionsd] Fehler/Timeout bei write"); - } -} - - -static void commandGetLanguageMode(int connfd, char* /* data */, const unsigned /* dataLength */) -{ - CSectionsdClient::SIlanguageMode_t retval(CSectionsdClient::ALL); - - retval = SIlanguage::getMode(); - - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = sizeof(retval); - - if (writeNbytes(connfd, (const char *)&responseHeader, - sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS) == true) { - writeNbytes(connfd, (const char *)&retval, - responseHeader.dataLength, WRITE_TIMEOUT_IN_SECONDS); - } else { - dputs("[sectionsd] Fehler/Timeout bei write"); - } -} - -#if 0 -#define SETENVI(var) { \ - sprintf(val,"%d",var); \ - if (setenv("SD_"#var, val, 1)<0) \ - perror("SETENVI("#var") "); } -#define SETENVB(var) { \ - sprintf(val,"%s",var?"1":"0"); \ - if (setenv("SD_"#var, val, 1)<0) \ - perror("SETENVB("#var") "); } -#define SETENVL(var) { \ - sprintf(val,"%ld",var); \ - if (setenv("SD_"#var, val, 1)<0) \ - perror("SETENVL("#var") "); } -#define SETENVS(var) { \ - if (setenv("SD_"#var, ((std::string)var).c_str(), 1)< 0) \ - perror("SETENVS("#var") "); } -// restart sectionsd.... -static void commandRestart(int connfd, char * /*data*/, const unsigned /*dataLength*/) -{ - struct sectionsd::msgResponseHeader responseHeader; - responseHeader.dataLength = 0; - char * buf = (char*)malloc(64); - char *val = (char*)malloc(32); // needed for SETENV?-macros - int count; - if (val && buf && (count = readlink("/proc/self/exe", buf, 63)) >= 0) { - buf[count] = '\0'; - printf("re-starting %s\n", buf); - } else { - fprintf(stderr, "[sectionsd] commandRestart: cannot determine who i am\n"); - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - return; - } - /* if we close filedescriptors here, the 2.4 kernel hangs hard when we - close the two pipe fds probably created by the old threading - implementation. We close them instead at startup. - for (int i = 3; i < 256; i++) - close(i); - */ -#ifdef UPDATE_NETWORKS - SETENVI(auto_scanning); -#endif - SETENVL(secondsToCache); - SETENVL(oldEventsAre); - SETENVL(secondsExtendedTextCache); - SETENVI(max_events); - SETENVI(ntprefresh); - SETENVI(ntpenable); - SETENVS(ntp_system_cmd); - SETENVS(epg_dir); - SETENVB(update_eit); - SETENVB(bTimeCorrect); - SETENVB(sections_debug); - writeNbytes(connfd, (const char *)&responseHeader, sizeof(responseHeader), WRITE_TIMEOUT_IN_SECONDS); - unlink(SECTIONSD_UDS_NAME); - char* const p[3] = { buf, (char *) "-p", NULL }; - fprintf(stderr,"[sectionsd] starting '%s'\n",buf); - execv(buf, p); - perror("[sectionsd] commandRestart execv"); - fprintf(stderr, "[sectionsd] ERROR! This is impossible!\n\n"); - free(buf); -} -#endif - -struct s_cmd_table -{ - void (*cmd)(int connfd, char *, const unsigned); - std::string sCmd; -}; - -static s_cmd_table connectionCommands[sectionsd::numberOfCommands] = { - //commandActualEPGchannelName, -{ commandDummy2, "commandDummy1" }, -{ commandEventListTV, "commandEventListTV" }, - //commandCurrentNextInfoChannelName, -{ commandDummy2, "commandDummy2" }, -{ commandDumpStatusInformation, "commandDumpStatusInformation" }, - //commandAllEventsChannelName, -{ commandAllEventsChannelIDSearch, "commandAllEventsChannelIDSearch" }, -{ commandDummy2, "commandSetHoursToCache" }, -{ commandDummy2, "commandSetHoursExtendedCache" }, -{ commandDummy2, "commandSetEventsAreOldInMinutes" }, -{ commandDumpAllServices, "commandDumpAllServices" }, -{ commandEventListRadio, "commandEventListRadio" }, -{ commandGetNextEPG, "commandGetNextEPG" }, -{ commandGetNextShort, "commandGetNextShort" }, -{ commandPauseScanning, "commandPauseScanning" }, -{ commandGetIsScanningActive, "commandGetIsScanningActive" }, -{ commandActualEPGchannelID, "commandActualEPGchannelID" }, -{ commandEventListTVids, "commandEventListTVids" }, -{ commandEventListRadioIDs, "commandEventListRadioIDs" }, -{ commandCurrentNextInfoChannelID, "commandCurrentNextInfoChannelID" }, -{ commandEPGepgID, "commandEPGepgID" }, -{ commandEPGepgIDshort, "commandEPGepgIDshort" }, -{ commandComponentTagsUniqueKey, "commandComponentTagsUniqueKey" }, -{ commandAllEventsChannelID, "commandAllEventsChannelID" }, -{ commandTimesNVODservice, "commandTimesNVODservice" }, -{ commandGetEPGPrevNext, "commandGetEPGPrevNext" }, -{ commandGetIsTimeSet, "commandGetIsTimeSet" }, -{ commandserviceChanged, "commandserviceChanged" }, -{ commandLinkageDescriptorsUniqueKey, "commandLinkageDescriptorsUniqueKey" }, -{ commandDummy2, "commandPauseSorting" }, -{ commandRegisterEventClient, "commandRegisterEventClient" }, -{ commandUnRegisterEventClient, "commandUnRegisterEventClient" }, -#ifdef ENABLE_PPT -{ commandSetPrivatePid, "commandSetPrivatePid" }, -#else -{ commandDummy2, "commandSetPrivatePid" }, -#endif -#ifdef UPDATE_NETWORKS -{ commandSetSectionsdScanMode, "commandSetSectionsdScanMode" }, -#else -{ commandDummy2, "commandSetSectionsdScanMode" }, -#endif -{ commandFreeMemory, "commandFreeMemory" }, -{ commandReadSIfromXML, "commandReadSIfromXML" }, -{ commandWriteSI2XML, "commandWriteSI2XML" }, -{ commandLoadLanguages, "commandLoadLanguages" }, -{ commandSaveLanguages, "commandSaveLanguages" }, -{ commandSetLanguages, "commandSetLanguages" }, -{ commandGetLanguages, "commandGetLanguages" }, -{ commandSetLanguageMode, "commandSetLanguageMode" }, -{ commandGetLanguageMode, "commandGetLanguageMode" }, -{ commandSetConfig, "commandSetConfig" }, -#if 0 -{ commandRestart, "commandRestart" }, -#else -{ commandDummy1, "commandRestart" }, -#endif -{ commandDummy1, "commandPing" } -}; - -//static void *connectionThread(void *conn) -bool sectionsd_parse_command(CBasicMessage::Header &rmsg, int connfd) -{ - /* - pthread_t threadConnection; - rc = pthread_create(&threadConnection, &conn_attrs, connectionThread, client); - if(rc) - { - fprintf(stderr, "[sectionsd] failed to create connection-thread (rc=%d)\n", rc); - return 4; - } - */ - // VERSUCH OHNE CONNECTION-THREAD! - // spart die thread-creation-zeit, und die Locks lassen ohnehin nur ein cmd gleichzeitig zu - try - { - dprintf("Connection from UDS\n"); - - struct sectionsd::msgRequestHeader header; - - memmove(&header, &rmsg, sizeof(CBasicMessage::Header)); - memset(((char *)&header) + sizeof(CBasicMessage::Header), 0, sizeof(header) - sizeof(CBasicMessage::Header)); - - bool readbytes = readNbytes(connfd, ((char *)&header) + sizeof(CBasicMessage::Header), sizeof(header) - sizeof(CBasicMessage::Header), READ_TIMEOUT_IN_SECONDS); - - if (readbytes == true) - { - dprintf("version: %hhd, cmd: %hhd, numbytes: %d\n", header.version, header.command, readbytes); - - if (header.command < sectionsd::numberOfCommands) - { - dprintf("data length: %hd\n", header.dataLength); - char *data = new char[header.dataLength + 1]; - - if (!data) - fprintf(stderr, "low on memory!\n"); - else - { - bool rc = true; - - if (header.dataLength) - rc = readNbytes(connfd, data, header.dataLength, READ_TIMEOUT_IN_SECONDS); - - if (rc == true) - { - dprintf("%s\n", connectionCommands[header.command].sCmd.c_str()); - connectionCommands[header.command].cmd(connfd, data, header.dataLength); - } - - delete[] data; - } - } - else - dputs("Unknown format or version of request!"); - } - } // try -#ifdef WITH_EXCEPTIONS - catch (std::exception& e) - { - fprintf(stderr, "Caught std-exception in connection-thread %s!\n", e.what()); - } -#endif - catch (...) - { - fprintf(stderr, "Caught exception in connection-thread!\n"); - } - - return true; -} -#ifdef UPDATE_NETWORKS -xmlNodePtr GetProvider(xmlNodePtr provider, xmlNodePtr tp_node) -{ - xmlNodePtr found = NULL; - - while (provider && !found) - { - xmlNodePtr transponder = provider->xmlChildrenNode; - - while (transponder && !found) - { - if ( (xmlGetNumericAttribute(transponder, "id", 16) == xmlGetNumericAttribute(tp_node, "id", 16)) && - (xmlGetNumericAttribute(transponder, "onid", 16) == xmlGetNumericAttribute(tp_node, "onid", 16)) ) - found = provider; - else - transponder = transponder->xmlNextNode; - } - if (!found) - provider = provider->xmlNextNode; - } - return found; -} - -static void write_xml_header(FILE * fd) -{ - fprintf(fd, - "\n" - "\n" - "\n"); -} - -static void write_xml_footer(FILE *fd) -{ - fprintf(fd, "\n"); -} - -static void write_xml_provend(FILE *dst, const bool is_sat) -{ - if (is_sat) - fprintf(dst,"\t\n"); - else - fprintf(dst,"\t\n"); -} - -//Writes transponder entry or copies all existing tps of a provider. -static bool write_xml_transponder(FILE *src, FILE *dst, const xmlNodePtr tp_node, const bool is_sat, const bool copy) -{ -#define MAX_SIZE_TP_STR 256 - char tp_str[MAX_SIZE_TP_STR] = ""; - char buffer[256] = ""; - bool tp_existed = false; - if (is_sat) { - snprintf(tp_str, MAX_SIZE_TP_STR, "\t\t\n", - (t_transport_stream_id) xmlGetNumericAttribute(tp_node, "id", 16), - (t_original_network_id) xmlGetNumericAttribute(tp_node, "onid", 16), - (uint32_t) xmlGetNumericAttribute(tp_node, "frequency", 0), - (fe_spectral_inversion_t) xmlGetNumericAttribute(tp_node, "inversion", 0), - (uint32_t) xmlGetNumericAttribute(tp_node, "symbol_rate", 0), - (fe_code_rate_t) xmlGetNumericAttribute(tp_node, "fec_inner", 0), - (uint8_t) xmlGetNumericAttribute(tp_node, "polarization", 0)); - } - else { - snprintf(tp_str, MAX_SIZE_TP_STR, "\t\t\n", - (t_transport_stream_id) xmlGetNumericAttribute(tp_node, "id", 16), - (t_original_network_id) xmlGetNumericAttribute(tp_node, "onid", 16), - (uint32_t) xmlGetNumericAttribute(tp_node, "frequency", 0), - (fe_spectral_inversion_t) xmlGetNumericAttribute(tp_node, "inversion", 0), - (uint32_t) xmlGetNumericAttribute(tp_node, "symbol_rate", 0), - (fe_code_rate_t) xmlGetNumericAttribute(tp_node, "fec_inner", 0), - (fe_modulation_t) xmlGetNumericAttribute(tp_node, "modulation", 0)); - } - - if (!copy) - fprintf(dst, tp_str); - else { - if (!feof(src)) { - fgets(buffer, 255, src); - - if (is_sat) { - //find tp in currentservices.xml - while( (!feof(src)) && (strcmp(buffer, "\t\n") != 0) && (strcmp(buffer, tp_str) != 0) ) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - } - else { - while( (!feof(src)) && (strcmp(buffer, "\t\n") != 0) && (strcmp(buffer, tp_str) != 0) ) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - } - //If the Transponder alredy existed. This isn't reached at the moment because if the transponder - //didn't exist we don't call the update function. But maybe this is to be changed: - //We should save if the update came from SDT other and update it once again, if - //we find SDT ACTUAL. So we leave it here. Save could be done through another node SDT in - //currentservices.xml. Should be easy to realize... - if ( (!feof(src)) && (!strcmp(buffer, tp_str)) ) { - while( (!feof(src)) && (strcmp(buffer, "\t\t\n") != 0) ) { - tp_existed = true; - fgets(buffer, 255, src); - } - } - } - } - return tp_existed; -} - -//return true for sat, false for cable -//The function fulfills two purposes. It writes the correct provider entry (if copy = false) or it copies -//all data including the provider entry if it existed -//Otherwise it reads to the end signalling that it didn't find the provider -static bool write_xml_provider(FILE *src, FILE *dst, const xmlNodePtr provider, const bool copy) -{ -#define MAX_SIZE_PROV_STR 256 - char prov_str[MAX_SIZE_PROV_STR] = ""; - char buffer[256] = ""; - std::string frontendType; - std::string provider_name; - std::string diseqc; - bool is_sat = false; - int position = 0; - - frontendType = xmlGetName(provider); - provider_name = xmlGetAttribute(provider, "name"); - - if (!strcmp(frontendType.c_str(), "sat")) { - diseqc = xmlGetAttribute(provider, "diseqc"); - position = xmlGetSignedNumericAttribute(provider, "position", 16); - if (position == 0) - snprintf(prov_str, MAX_SIZE_PROV_STR, "\t<%s name=\"%s\" diseqc=\"%s\">\n", frontendType.c_str(), - provider_name.c_str(), diseqc.c_str()); - else { - //east_west = xmlGetNumericAttribute(provider, "east_west", 16); - snprintf(prov_str, MAX_SIZE_PROV_STR, "\t<%s name=\"%s\" position=\"%04x\" diseqc=\"%s\">\n", - frontendType.c_str(), - provider_name.c_str(), - position, - //east_west, - diseqc.c_str()); - } - is_sat = true; - } - else { - snprintf(prov_str, MAX_SIZE_PROV_STR, "\t<%s name=\"%s\">\n", frontendType.c_str(), provider_name.c_str()); - is_sat = false; - } - - if (!copy) - fprintf(dst, prov_str); - else { - if (!feof(src)) { - fgets(buffer, 255, src); - //find prov in currentservices.xml - while( (!feof(src)) && (strcmp(buffer, "\n") != 0) && (strcmp(buffer, prov_str) != 0) ) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - if (strcmp(buffer, prov_str) != 0) { - while (!feof(src)) - fgets(buffer, 255, src); -// printf("reading to the end!\n"); - } else - fprintf(dst, buffer); - } - } - - return is_sat; -} - -//Determines which action (none, add, replace) should be taken for current service -//This funtion considers the entry scanType in scan.conf. -static int get_action(const xmlNodePtr tp_node, const MySIservicesOrderUniqueKey::iterator s, const int scanType) -{ - //And now node points to transponders channels first entry - xmlNodePtr node = tp_node->xmlChildrenNode; - std::string name; - - if ( ((s->second->serviceTyp == 1) && (scanType == 1)) || - ((s->second->serviceTyp == 2) && (scanType == 2)) || - (((s->second->serviceTyp == 1) || (s->second->serviceTyp == 2)) && (scanType == 0)) || - (scanType == 3) ) { - - while (xmlGetNextOccurence(node, "channel") != NULL) { - if (s->second->service_id == xmlGetNumericAttribute(node, "service_id", 16)) { - name = xmlGetAttribute(node, "name"); - if ( (s->second->serviceTyp == xmlGetNumericAttribute(node, "service_type", 16)) && - (!strcmp(s->second->serviceName.c_str(), name.c_str())) ) { - dprintf("[sectionsd] Service %s okay\n", name.c_str()); - return 0; //service okay - } - else { - if (s->second->is_actual & 7) { - dprintf("[sectionsd] Replacing Service %s\n", name.c_str()); - return 2; //replace - } - else { - dprintf("[sectionsd] Service %s changed but signalled from SDT_Other\n", name.c_str()); - return 0; //service not okay, but came from SDT_OTHER - we can't truly trust - } - } - } - node = node->xmlNextNode; - } - dprintf("[sectionsd] Adding Service %s\n", s->second->serviceName.c_str()); - return 1; //add - } - return 0; //scanType didn't match do not handle in any case -} - -//This updates the /tmp/currentservices.xml with the differences between services.xml and SDT content -//It contains two loops. Each is nested. First loop adds and replaces the services which are new in the SDT -//The second loop removes Services which are in services.xml and not in the SDT anymore. -//Returns true if the transponder needs to be updated -bool updateCurrentXML(xmlNodePtr provider, xmlNodePtr tp_node, const int scanType, const bool /*is_current*/) -{ - bool is_needed = false; - bool newprov = false; - bool is_sat = false; - bool tp_existed = false; - - std::string name; - - FILE * src = NULL; - FILE * dst = NULL; - char buffer[256] = ""; - - readLockServices(); - for (MySIservicesOrderUniqueKey::iterator s = mySIservicesOrderUniqueKey.begin(); s != mySIservicesOrderUniqueKey.end(); s++) - { - unlockServices(); - readLockMessaging(); - if (messaging_zap_detected) { - unlockMessaging(); - return false; - } - unlockMessaging(); - if ( (s->second->transport_stream_id == xmlGetNumericAttribute(tp_node, "id", 16)) && - (s->second->original_network_id == xmlGetNumericAttribute(tp_node, "onid", 16)) ) - { - int action = get_action(tp_node, s, scanType); - - if (action > 0) { - if (!is_needed) { - is_needed = true; - //create new currentservices - if (!(dst = fopen(CURRENTSERVICES_TMP, "w"))) { - dprintf("unable to open %s for writing\n", CURRENTSERVICES_TMP); - return false; - } - if (!(src = fopen(CURRENTSERVICES_XML, "r"))) { - //if currentservices doesn't yet exist - newprov = true; - write_xml_header(dst); - is_sat = write_xml_provider(src, dst, provider, false); - } else { - //if it exists. copy till provider - is_sat = write_xml_provider(src, dst, provider, true); - //if eof provider didn't exist - if (feof(src)) { - newprov = true; - write_xml_provider(src, dst, provider, false); - } - else - //copy all transponders belonging to current prov - tp_existed = write_xml_transponder(src, dst, tp_node, is_sat, true); - } - // write new transponder node - write_xml_transponder(src, dst, tp_node, is_sat, false); - } - //check which action is necessary for current service - //0 = nothing / 1 = add / 2 = replace - switch (action) - { - case 1: - fprintf(dst, - "\t\t\t\n", - "add", - s->second->service_id, - UTF8_to_UTF8XML(s->second->serviceName.c_str()).c_str(), - s->second->serviceTyp); - break; - case 2: - fprintf(dst, - "\t\t\t\n", - "replace", - s->second->service_id, - UTF8_to_UTF8XML(s->second->serviceName.c_str()).c_str(), - s->second->serviceTyp); - break; - default: - break; - } - - } - } - readLockServices(); - } - unlockServices(); - //Second loop to detect services which are not longer in SDT - //Only remove if Actual SDT. This could be changed, if all providers would send correct data - //It is pretty much the same as the first loop. Check there. Later: merge them together? - readLockServices(); - MySIservicesOrderUniqueKey::iterator s = mySIservicesOrderUniqueKey.begin(); - if (s->second->is_actual == 2) { - xmlNodePtr node = tp_node->xmlChildrenNode; - - while (xmlGetNextOccurence(node, "channel") != NULL) { - - readLockMessaging(); - if (messaging_zap_detected) { - unlockMessaging(); - return false; - } - unlockMessaging(); - - s = mySIservicesOrderUniqueKey.begin(); - while ( (s != mySIservicesOrderUniqueKey.end()) && - (s->second->service_id != xmlGetNumericAttribute(node, "service_id", 16)) ) - s++; - if (s == mySIservicesOrderUniqueKey.end()) { - if (!is_needed) { - - is_needed = true; - //create new currentservices - if (!(dst = fopen(CURRENTSERVICES_TMP, "w"))) { - dprintf("unable to open %s for writing\n", CURRENTSERVICES_TMP); - unlockServices(); - return false; - } - if (!(src = fopen(CURRENTSERVICES_XML, "r"))) { - newprov = true; - write_xml_header(dst); - is_sat = write_xml_provider(src, dst, provider, false); - } else { - - is_sat = write_xml_provider(src, dst, provider, true); - if (feof(src)) { - newprov = true; - write_xml_provider(src, dst, provider, false); - } - tp_existed = write_xml_transponder(src, dst, tp_node, is_sat, true); - } - write_xml_transponder(src, dst, tp_node, is_sat, false); - } - name = xmlGetAttribute(node, "name"); - - dprintf("[sectionsd] Removing Service %s\n", name.c_str()); - fprintf(dst, - "\t\t\t\n", - "remove", - xmlGetNumericAttribute(node, "service_id", 16), - UTF8_to_UTF8XML(name.c_str()).c_str(), - xmlGetNumericAttribute(node, "service_type", 16)); - } - node = node->xmlNextNode; - } - } - - unlockServices(); - - //If we chnged some services write the closing tags. - if (is_needed) { - - fprintf(dst,"\t\t\n"); - - if (!tp_existed) - write_xml_provend(dst, is_sat); - - if (newprov) { - write_xml_footer(dst); - } - else { - fgets(buffer, 255, src); - while(!feof(src)) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - fclose(src); - } - - fclose(dst); - } - - return is_needed; -} - -xmlNodePtr getProviderFromSatellitesXML(xmlNodePtr node, const int position) -{ - struct stat buf; - const char *filename = ZAPITCONFIGDIR "/" SATELLITES_XML; - if ((stat(filename, &buf) == -1) && (errno == ENOENT)) - filename = DATADIR "/" SATELLITES_XML; - - xmlDocPtr satellites_parser = parseXmlFile(filename); - if (satellites_parser == NULL) - return NULL; - xmlNodePtr satellite = xmlDocGetRootElement(satellites_parser)->xmlChildrenNode; - while (satellite) { - if (xmlGetSignedNumericAttribute(satellite, "position", 16) == position) { - while (node) { - if (!strcmp(xmlGetAttribute(satellite, "name"), xmlGetAttribute(node, "name"))) - { - xmlFreeDoc(satellites_parser); - return node; - } - node = node->xmlNextNode; - } - } - satellite = satellite->xmlNextNode; - } - xmlFreeDoc(satellites_parser); - return NULL; -} - -xmlNodePtr getProviderbyName(xmlNodePtr current_provider, xmlNodePtr provider) { - while (current_provider) { - if (!strcmp(xmlGetAttribute(current_provider, "name"), xmlGetAttribute(provider, "name"))) - return current_provider; - current_provider = current_provider->xmlNextNode; - } - return NULL; -} - -xmlNodePtr findTransponderFromProv(xmlNodePtr transponder, const t_original_network_id onid, const t_transport_stream_id tsid) { - while (transponder) { - if ((xmlGetNumericAttribute(transponder, "onid", 16) == onid) && (xmlGetNumericAttribute(transponder, "id", 16) == tsid)) - return transponder; - transponder = transponder->xmlNextNode; - } - return NULL; -} - -//SDT-Thread calls this function if it found a complete Service Description Table (SDT). Overwrite for actual = true - for other = false -//static bool updateTP(const t_original_network_id onid, const t_transport_stream_id tsid, const int scanType, const bool overwrite) -static bool updateTP(const int scanType) -{ - xmlDocPtr service_parser = parseXmlFile(SERVICES_XML); - xmlDocPtr current_parser = NULL; - bool need_update = false; - FILE * tmp = NULL; - xmlNodePtr provider = NULL; - xmlNodePtr current_provider = NULL; - t_transport_stream_id tsid = 0; - t_original_network_id onid = 0; - - if (service_parser == NULL) - return false; - - int i = 0; - while ((i < MAX_SDTs) && (messaging_sdt_tid[i] != 0)) { - readLockMessaging(); - if (messaging_zap_detected) { - unlockMessaging(); - need_update = false; - if (current_parser != NULL) - xmlFreeDoc(current_parser); - unlink(CURRENTSERVICES_TMP); - break; - } - unlockMessaging(); - onid = (t_original_network_id) (messaging_sdt_tid[i] >> 16) & 0xffff; - tsid = (t_transport_stream_id) messaging_sdt_tid[i] & 0xffff; - -//GET_ORIGINAL_NETWORK_ID_FROM_CHANNEL_ID(channel_id) ((t_original_network_id)((channel_id) >> 16)) -//GET_SERVICE_ID_FROM_CHANNEL_ID(channel_id) ((t_service_id)(channel_id)) - - xmlNodePtr services_tp = FindTransponder(xmlDocGetRootElement(service_parser)->xmlChildrenNode, onid, tsid); - - if (services_tp) - provider = GetProvider(xmlDocGetRootElement(service_parser)->xmlChildrenNode, services_tp); - else - provider = NULL; - - tmp = fopen(CURRENTSERVICES_XML, "r"); - if (tmp) { - fclose(tmp); - current_parser= parseXmlFile(CURRENTSERVICES_XML); - } - - xmlNodePtr current_tp = NULL; - - if (current_parser != NULL) { - current_tp = FindTransponder(xmlDocGetRootElement(current_parser)->xmlChildrenNode, onid, tsid); - if (provider) { - //printf("getProvbyname\n"); - current_provider = getProviderbyName(xmlDocGetRootElement(current_parser)->xmlChildrenNode, provider); - - } - else { - if (current_tp) - current_provider = GetProvider(xmlDocGetRootElement(current_parser)->xmlChildrenNode, current_tp); - } - } - - if (!current_tp) { - if (provider) { - if (current_provider) { - //printf("update with current\n"); - if (!strcmp(xmlGetAttribute(current_provider, "name"), xmlGetAttribute(provider, "name"))) - if (updateCurrentXML(current_provider, services_tp, scanType, false)) - need_update = true; - - } - else { - //printf("update with prov\n"); - if (updateCurrentXML(provider, services_tp, scanType, false)) - need_update = true; - - } - } - else - dprintf("[sectionsd] No Transponder with ONID: %04x TSID: %04x found in services.xml!\n", onid, tsid); - } - else { - if (!provider) { - //printf("update with current / current\n"); - - if (updateCurrentXML(current_provider, current_tp, scanType, false)) - need_update = true; - - } - else - dprintf("[sectionsd] No Update needed for Transponder with ONID: %04x TSID: %04x!\n", onid, tsid); - } - if (current_parser != NULL) - xmlFreeDoc(current_parser); - current_parser = NULL; - - i++; - } - - xmlFreeDoc(service_parser); - - if (need_update) - { - rename(CURRENTSERVICES_TMP, CURRENTSERVICES_XML); - - dprintf("[sectionsd] We updated at least one Transponder in currentservices.xml!\n"); - - } else - dprintf("[sectionsd] No new services found!\n"); -//printf("Finishing updateTP\n"); - return need_update; -} -//stolen from frontend.cpp please fix. -fe_code_rate_t getCodeRate(const uint8_t fec_inner) -{ - switch (fec_inner & 0x0F) { - case 0x01: - return FEC_1_2; - case 0x02: - return FEC_2_3; - case 0x03: - return FEC_3_4; - case 0x04: - return FEC_5_6; - case 0x05: - return FEC_7_8; - case 0x0F: - return FEC_NONE; - default: - return FEC_AUTO; - } -} -//also stolen from frontend.cpp. please fix. -fe_modulation_t getModulation(const uint8_t modulation) -{ - switch (modulation) { - case 0x00: - return QPSK; - case 0x01: - return QAM_16; - case 0x02: - return QAM_32; - case 0x03: - return QAM_64; - case 0x04: - return QAM_128; - case 0x05: - return QAM_256; - default: -#if 1 - return QAM_AUTO; -#else - // i do not know how to do it correctly for old API -- seife - return QAM_256; -#endif - } -} - -static void writeTransponderFromDescriptor(FILE *dst, const t_original_network_id onid, const t_transport_stream_id tsid, const char *ddp, const bool is_sat) -{ - struct satellite_delivery_descriptor *sdd; - struct cable_delivery_descriptor *cdd; - - if (is_sat) { - sdd = (struct satellite_delivery_descriptor *)ddp; - fprintf(dst,"\t\t\n", - tsid, - onid, - ((sdd->frequency_1 >> 4) * 100000000) + - ((sdd->frequency_1 & 0x0F) * 10000000) + - ((sdd->frequency_2 >> 4) * 1000000) + - ((sdd->frequency_2 & 0x0F) * 100000) + - ((sdd->frequency_3 >> 4) * 10000) + - ((sdd->frequency_3 & 0x0F) * 1000) + - ((sdd->frequency_4 >> 4) * 100) + - ((sdd->frequency_4 & 0x0F) * 10), -// sdd->modulation, - INVERSION_AUTO, - ((sdd->symbol_rate_1 >> 4) * 100000000) + - ((sdd->symbol_rate_1 & 0x0F) * 10000000) + - ((sdd->symbol_rate_2 >> 4) * 1000000) + - ((sdd->symbol_rate_2 & 0x0F) * 100000) + - ((sdd->symbol_rate_3 >> 4) * 10000) + - ((sdd->symbol_rate_3 & 0x0F) * 1000) + - ((sdd->symbol_rate_4 >> 4) * 100), - (fe_code_rate_t) getCodeRate(sdd->fec_inner & 0x0F), - sdd->polarization); - } - else { - cdd = (struct cable_delivery_descriptor *)ddp; - fprintf(dst,"\t\t\n", - tsid, - onid, - ((cdd->frequency_1 >> 4) * 1000000000) + - ((cdd->frequency_1 & 0x0F) * 100000000) + - ((cdd->frequency_2 >> 4) * 10000000) + - ((cdd->frequency_2 & 0x0F) * 1000000) + - ((cdd->frequency_3 >> 4) * 100000) + - ((cdd->frequency_3 & 0x0F) * 10000) + - ((cdd->frequency_4 >> 4) * 1000) + - ((cdd->frequency_4 & 0x0F) * 100), -// cdd->fec_outer, - INVERSION_AUTO, - ((cdd->symbol_rate_1 >> 4) * 100000000) + - ((cdd->symbol_rate_1 & 0x0F) * 10000000) + - ((cdd->symbol_rate_2 >> 4) * 1000000) + - ((cdd->symbol_rate_2 & 0x0F) * 100000) + - ((cdd->symbol_rate_3 >> 4) * 10000) + - ((cdd->symbol_rate_3 & 0x0F) * 1000) + - ((cdd->symbol_rate_4 >> 4) * 100), - (fe_code_rate_t) getCodeRate(cdd->fec_inner & 0x0F), - (fe_modulation_t) getModulation(cdd->modulation)); - } - fprintf(dst,"\t\t\n"); -} - -static void updateXMLnet(xmlNodePtr provider, const t_original_network_id onid, const t_transport_stream_id tsid, - const char *ddp, const int position) -{ - FILE * src = NULL; - FILE * dst = NULL; - bool is_new = false; - bool is_sat = false; - -#define MAX_SIZE_PROV_STR 256 - char prov_str_neu[MAX_SIZE_PROV_STR] = ""; - char buffer[256] = ""; - - std::string frontendType; - std::string provider_name; - std::string diseqc; - - if (!(dst = fopen(CURRENTSERVICES_TMP, "w"))) { - dprintf("unable to open %s for writing\n", CURRENTSERVICES_TMP); - return; - } - - frontendType = xmlGetName(provider); - provider_name = xmlGetAttribute(provider, "name"); - - if (!strcmp(frontendType.c_str(), "sat")) { - diseqc = xmlGetAttribute(provider, "diseqc"); - snprintf(prov_str_neu, MAX_SIZE_PROV_STR, "\t<%s name=\"%s\" position=\"%04x\" diseqc=\"%s\">\n", frontendType.c_str(), provider_name.c_str(), - position, diseqc.c_str()); - is_sat = true; - } - else { - snprintf(prov_str_neu, MAX_SIZE_PROV_STR, "\t<%s name=\"%s\">\n", frontendType.c_str(), provider_name.c_str()); - is_sat = false; - } - - if (!(src = fopen(CURRENTSERVICES_XML, "r"))) { - is_new = true; - write_xml_header(dst); - fprintf(dst, prov_str_neu); - if (ddp != NULL) - writeTransponderFromDescriptor(dst, onid, tsid, ddp, is_sat); - write_xml_provend(dst, is_sat); - write_xml_footer(dst); - } - else { - if (!feof(src)) { - fgets(buffer, 255, src); - //find prov in currentservices.xml - while( (!feof(src)) && (strcmp(buffer, "\n") != 0) && (strcmp(buffer, prov_str_neu) != 0) ) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - if (strcmp(buffer, prov_str_neu) != 0) - fprintf(dst, prov_str_neu); - if (ddp != NULL) { - while( (!feof(src)) && (strcmp(buffer, "\n") != 0) && - (strcmp(buffer, "\t\n") != 0) && (strcmp(buffer, "\t\n")) ) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - //if (strcmp(buffer, "\n") == 0) - writeTransponderFromDescriptor(dst, onid, tsid, ddp, is_sat); - } - if (strcmp(buffer, "\n") == 0) - write_xml_provend(dst, is_sat); - - while (!feof(src)) - { - fprintf(dst, buffer); - fgets(buffer, 255, src); - } - } - - fclose(src); - } - fclose(dst); - - rename(CURRENTSERVICES_TMP, CURRENTSERVICES_XML); - - return; -} - -static bool updateNetwork() -{ - t_transport_stream_id tsid; - t_original_network_id onid; - t_network_id network_id; - - int position = 0; - struct satellite_delivery_descriptor *sdd; - const char *ddp; - std::string frontendType; - - bool need_update = false; - bool needs_fix = false; - - xmlNodePtr provider; - xmlNodePtr tp; - - FILE * tmp; - - xmlDocPtr service_parser = parseXmlFile(SERVICES_XML); - - if (service_parser == NULL) - return false; - - xmlDocPtr current_parser = NULL; - xmlNodePtr current_tp = NULL; - xmlNodePtr current_provider = NULL; - - tmp = fopen(CURRENTSERVICES_XML, "r"); - if (tmp) { - fclose(tmp); - current_parser= parseXmlFile(CURRENTSERVICES_XML); - } - - int i = 0; - readLockMessaging(); - while ((i < MAX_NIDs) && (messaging_nit_nid[i] != 0) && (!messaging_zap_detected)) { - unlockMessaging(); - - network_id = messaging_nit_nid[i]; - - // go through all transpopnders currently cached by neutrino - I won't need them after this loop. They COULD be cleared. - for (MySItranspondersOrderUniqueKey::iterator s = mySItranspondersOrderUniqueKey.begin(); s != - mySItranspondersOrderUniqueKey.end(); s++) - { - readLockMessaging(); - if (messaging_zap_detected) { - unlockMessaging(); - break; - } - unlockMessaging(); - if (s->second->network_id == network_id) { - needs_fix = false; - tsid = s->second->transport_stream_id; - onid = s->second->original_network_id; - ddp = &s->second->delivery_descriptor[0]; - - //printf("Descriptor_type: %02x\n", s->second->delivery_type); - frontendType = xmlGetName(xmlDocGetRootElement(service_parser)->xmlChildrenNode); - switch (s->second->delivery_type) { - case 0x43: - if (!strcmp(frontendType.c_str(), "sat")) { - sdd = (struct satellite_delivery_descriptor *)ddp; - position = (sdd->orbital_pos_hi << 8) | sdd->orbital_pos_lo; - if (!sdd->west_east_flag) - position = -position; - provider = getProvbyPosition(xmlDocGetRootElement(service_parser)->xmlChildrenNode, position); - } - else { - provider = NULL; - position = 1000; - } - break; - case 0x44: - if (!strcmp(frontendType.c_str(), "cable")) { - provider = xmlDocGetRootElement(service_parser)->xmlChildrenNode; - position = 0; - } - else { - position = 1000; - provider = NULL; - } - break; - default: - position = 1000; - provider = NULL; - break; - } - - //provider with satellite position does not exist in services.xml - if ((!provider) && (position != 1000)) { - provider = getProviderFromSatellitesXML(xmlDocGetRootElement(service_parser)->xmlChildrenNode, position); - if (provider) - needs_fix = true; //backward compatibility - add position node - } - //provider also not found in satellites.xml... - if ((!provider) && (position != 1000)) { - if (current_parser != NULL) { - provider = getProvbyPosition(xmlDocGetRootElement(current_parser)->xmlChildrenNode, position); - } - } - //and finally provider not found in currentservices.xml - we give up - if (!provider) { - dprintf("[sectionsd::updateNetwork] Provider not found for Transponder ONID: %04x TSID: %04x.\n", onid, - tsid); - } - else { - //we found a valid provider node - tp = findTransponderFromProv(provider->xmlChildrenNode, onid, tsid); - if (!tp) { - dprintf("[sectionsd::updateNetwork] Transponder ONID: %04x TSID: %04x not found.\n", onid, tsid); - if (current_parser != NULL) { - - switch (s->second->delivery_type) { - case 0x43: //satellite descriptor - current_provider = - getProvbyPosition(xmlDocGetRootElement(current_parser)->xmlChildrenNode, - position); - break; - case 0x44: //cable - current_provider = xmlDocGetRootElement(current_parser)->xmlChildrenNode; - break; - default: - break; - } - if (current_provider) - current_tp = findTransponderFromProv(current_provider->xmlChildrenNode, onid, - tsid); - } - //write the new transponder to currentservices.xml - if (!current_tp) { - updateXMLnet(provider, onid, tsid, ddp, position); - xmlFreeDoc(current_parser); - current_parser= parseXmlFile(CURRENTSERVICES_XML); - } - - } else { - dprintf("[sectionsd::updateNetwork] Transponder ONID: %04x TSID: %04x found.\n", onid, tsid); - if ( (s->second->is_actual & 7) && (needs_fix) ) { - //if(!(tmp = fopen(CURRENTSERVICES_XML, "r"))) - if (current_parser == NULL) { - dprintf("[sectionsd::updateNetwork] services.xml provider needs update\n"); - updateXMLnet(provider, onid, tsid, NULL, position); - current_parser= parseXmlFile(CURRENTSERVICES_XML); - } - else { - current_provider = - getProvbyPosition(xmlDocGetRootElement(current_parser)->xmlChildrenNode, - position); - if (!current_provider) { - updateXMLnet(provider, onid, tsid, NULL, position); - xmlFreeDoc(current_parser); - current_parser= parseXmlFile(CURRENTSERVICES_XML); - } - } - } - } - } - } - //sleep(10); - } - i++; - readLockMessaging(); - } - unlockMessaging(); - if (current_parser != NULL) - xmlFreeDoc(current_parser); - xmlFreeDoc(service_parser); - - return need_update; -} - -xmlNodePtr findBouquet(xmlDocPtr parser,t_bouquet_id bouquet_id) -{ - xmlNodePtr bouquet = xmlDocGetRootElement(parser)->xmlChildrenNode; - while (xmlGetNextOccurence(bouquet, "Bouquet") != NULL) { - //printf("Checking: %04x\n", xmlGetNumericAttribute(bouquet, "bouquet_id", 16)); - if (xmlGetNumericAttribute(bouquet, "bouquet_id", 16) == bouquet_id) - return bouquet; - bouquet = bouquet->xmlNextNode; - } - return NULL; -} - -static bool compareBouquet(xmlNodePtr channel, t_bouquet_id bouquet_id) -{ - MySIbouquetsOrderUniqueKey::iterator s = mySIbouquetsOrderUniqueKey.begin(); - while (s != mySIbouquetsOrderUniqueKey.end()) { - if (s->second->bouquet_id == bouquet_id) { - if (channel) { - if ( (xmlGetNumericAttribute(channel, "serviceID", 16) != s->second->service_id) || - (xmlGetNumericAttribute(channel, "tsid", 16) != s->second->transport_stream_id) || - (xmlGetNumericAttribute(channel, "onid", 16) != s->second->original_network_id) ) { - //printf("Service: %04x\n",s->second->service_id); - return true; - } - channel = channel->xmlNextNode; - } else - return true; - } - s++; - } - if ((!channel) && (s == mySIbouquetsOrderUniqueKey.end())) - return false; - else - return true; -} - -static void write_bouquet_xml_node(FILE *fd, t_bouquet_id bouquet_id) -{ - bool found = false; - - MySIbouquetsOrderUniqueKey::iterator s = mySIbouquetsOrderUniqueKey.begin(); - while ((!found) && (s != mySIbouquetsOrderUniqueKey.end())) { - if ((s->second->bouquet_id == bouquet_id) && (s->second->bouquetName.length() != 0)) - found = true; - else - s++; - } - if (found) - fprintf(fd, "\t