diff --git a/lib/sectionsdclient/sectionsdMsg.h b/lib/sectionsdclient/sectionsdMsg.h index fb71f8322..2476d9106 100644 --- a/lib/sectionsdclient/sectionsdMsg.h +++ b/lib/sectionsdclient/sectionsdMsg.h @@ -67,6 +67,8 @@ struct sectionsd setConfig, // commandSetConfig + readSIfromIPTVXML, // commandReadSIfromIPTVXML + numberOfCommands // <- no actual command, end of command marker }; diff --git a/lib/sectionsdclient/sectionsdclient.cpp b/lib/sectionsdclient/sectionsdclient.cpp index cd5769996..261e5db12 100644 --- a/lib/sectionsdclient/sectionsdclient.cpp +++ b/lib/sectionsdclient/sectionsdclient.cpp @@ -194,6 +194,14 @@ void CSectionsdClient::readSIfromXML(const char * epgxmlname) close_connection(); } +void CSectionsdClient::readSIfromIPTVXML(const char * url) +{ + send(sectionsd::readSIfromIPTVXML, (char*) url, strlen(url)); + + readResponse(); + close_connection(); +} + void CSectionsdClient::writeSI2XML(const char * epgxmlname) { send(sectionsd::writeSI2XML, (char*) epgxmlname, strlen(epgxmlname)); diff --git a/lib/sectionsdclient/sectionsdclient.h b/lib/sectionsdclient/sectionsdclient.h index e9d8b16a3..ab7b91b02 100644 --- a/lib/sectionsdclient/sectionsdclient.h +++ b/lib/sectionsdclient/sectionsdclient.h @@ -200,6 +200,8 @@ class CSectionsdClient : private CBasicClient void readSIfromXML(const char * epgxmlname); + void readSIfromIPTVXML(const char * url); + void writeSI2XML(const char * epgxmlname); /* diff --git a/src/eitd/sectionsd.cpp b/src/eitd/sectionsd.cpp index b7aadd672..7f59b387c 100644 --- a/src/eitd/sectionsd.cpp +++ b/src/eitd/sectionsd.cpp @@ -1213,7 +1213,7 @@ static void commandFreeMemory(int connfd, char * /*data*/, const unsigned /*data static void commandReadSIfromXML(int connfd, char *data, const unsigned dataLength) { - pthread_t thrInsert; + pthread_t thrInsertXML; sendEmptyResponse(connfd, NULL, 0); @@ -1230,7 +1230,33 @@ static void commandReadSIfromXML(int connfd, char *data, const unsigned dataLeng pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); - if (pthread_create (&thrInsert, &attr, insertEventsfromFile, (void *)epg_dir_tmp.c_str() )) + if (pthread_create (&thrInsertXML, &attr, insertEventsfromFile, (void *)epg_dir_tmp.c_str() )) + { + perror("sectionsd: pthread_create()"); + } + + pthread_attr_destroy(&attr); +} + +static void commandReadSIfromIPTVXML(int connfd, char *data, const unsigned dataLength) +{ + pthread_t thrInsertIPTV; + + sendEmptyResponse(connfd, NULL, 0); + + if (dataLength > 100) + return ; + static std::string url_tmp = ""; + writeLockMessaging(); + data[dataLength] = '\0'; + url_tmp = (std::string)data; + unlockMessaging(); + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); + + if (pthread_create (&thrInsertIPTV, &attr, insertEventsfromHttp, (void *)url_tmp.c_str() )) { perror("sectionsd: pthread_create()"); } @@ -1272,6 +1298,7 @@ static s_cmd_table connectionCommands[sectionsd::numberOfCommands] = { { commandReadSIfromXML, "commandReadSIfromXML" }, { commandWriteSI2XML, "commandWriteSI2XML" }, { commandSetConfig, "commandSetConfig" }, + { commandReadSIfromIPTVXML, "commandReadSIfromIPTVXML" }, }; bool sectionsd_parse_command(CBasicMessage::Header &rmsg, int connfd) diff --git a/src/eitd/xmlutil.cpp b/src/eitd/xmlutil.cpp index 0eab74a32..cfdce2348 100644 --- a/src/eitd/xmlutil.cpp +++ b/src/eitd/xmlutil.cpp @@ -33,8 +33,11 @@ #include #include +#include + #include #include +#include #include @@ -48,6 +51,7 @@ extern MySIeventsOrderServiceUniqueKeyFirstStartTimeEventUniqueKey mySIeventsOrd extern bool reader_ready; extern pthread_rwlock_t eventsLock; extern bool dvb_time_update; +extern CBouquetManager *g_bouquetManager; std::string epg_filter_dir = CONFIGDIR "/zapit/epgfilter.xml"; std::string dvbtime_filter_dir = CONFIGDIR "/zapit/dvbtimefilter.xml"; @@ -445,6 +449,112 @@ bool readEventsFromFile(std::string &epgname, int &ev_count) return true; } +bool readEventsFromHttpFile(std::string &epgname, int &ev_count) +{ + xmlDocPtr event_parser = NULL; + xmlNodePtr tv; + xmlNodePtr programme; + t_original_network_id onid = 0; + t_transport_stream_id tsid = 0; + t_service_id sid = 0; + + if (!(event_parser = parseXmlFile(epgname.c_str()))) + { + printf("unable to open %s for reading\n", epgname.c_str()); + return false; + } + + tv = xmlDocGetRootElement(event_parser); + programme = xmlChildrenNode(tv); + + while ((programme = xmlGetNextOccurence(programme,"programme"))) + { + + const char *chan = xmlGetAttribute(programme, "channel"); + const char *start = xmlGetAttribute(programme, "start"); + const char *stop = xmlGetAttribute(programme, "stop"); + + struct tm starttime, stoptime; + strptime(start, "%Y%m%d%H%M%S %z", &starttime); + strptime(stop, "%Y%m%d%H%M%S %z", &stoptime); + time_t start_time = mktime(&starttime); + time_t duration = mktime(&stoptime)-start_time; + + t_channel_id epgid = getepgid(chan); + if (epgid != 0) + { + //printf("\e[1;34m%s - %d - %s 0x%012" PRIx64 "(%ld) (%ld)\e[0m\n",__func__, __LINE__,chan, epgid, start_time, duration); + onid = GET_ORIGINAL_NETWORK_ID_FROM_CHANNEL_ID(epgid); + tsid = GET_TRANSPORT_STREAM_ID_FROM_CHANNEL_ID(epgid); + sid = GET_SERVICE_ID_FROM_CHANNEL_ID(epgid); + + SIevent e(onid, tsid, sid, ev_count+0x8000); + e.table_id = 0x50; + e.times.insert(SItime(start_time, duration)); + xmlNodePtr node; + node = xmlChildrenNode(programme); + while ((node = xmlGetNextOccurence(node, "title"))) + { + const char *title = xmlGetData(node); + if(title != NULL) + e.setName(std::string(ZapitTools::UTF8_to_Latin1("deu")), std::string(title)); + node = xmlNextNode(node); + } + node = xmlChildrenNode(programme); + while ((node = xmlGetNextOccurence(node, "sub-title"))) + { + const char *subtitle = xmlGetData(node); + if(subtitle != NULL) + e.setText(std::string(ZapitTools::UTF8_to_Latin1("deu")), std::string(subtitle)); + node = xmlNextNode(node); + } + node = xmlChildrenNode(programme); + while ((node = xmlGetNextOccurence(node, "desc"))) + { + const char *description = xmlGetData(node); + if(description != NULL) + e.appendExtendedText(std::string(ZapitTools::UTF8_to_Latin1("deu")), std::string(description)); + node = xmlNextNode(node); + } + dprintf("XML DEBUG: %s channel 0x%012" PRIx64 "\n", chan, epgid); + + addEvent(e, 0); + + ev_count++; + } + programme = xmlNextNode(programme); + } + + xmlFreeDoc(event_parser); + return true; +} + +t_channel_id getepgid(std::string epg_name) +{ + t_channel_id epgid; + + CBouquetManager::ChannelIterator cit = g_bouquetManager->tvChannelsBegin(); + + for (; !(cit.EndOfChannels()); cit++) + { + std::string tvg_id = (*cit)->getScriptName(); + + if (tvg_id.empty()) + continue; + + std::size_t found = tvg_id.find("#"+epg_name); + if (found != std::string::npos) + { + tvg_id = tvg_id.substr(tvg_id.find_first_of("=")); + sscanf(tvg_id.c_str(), "=%" SCNx64, &epgid); + return epgid; + } + else + continue; + } + return 0; +} + static int my_filter(const struct dirent *entry) { int len = strlen(entry->d_name); @@ -523,6 +633,45 @@ void *insertEventsfromFile(void * data) pthread_exit(NULL); } +void *insertEventsfromHttp(void * data) +{ + set_threadname(__func__); + reader_ready=false; + int ev_count = 0; + if (!data) + { + reader_ready = true; + pthread_exit(NULL); + } + std::string url = (char *) data; + std::string tmp_name = tmpnam (NULL); + std::string url_ext = getFileExt(url); + tmp_name = tmp_name + "." + url_ext; + + int64_t now = time_monotonic_ms(); + + if (url.compare(0,1,"/") == 0) + readEventsFromHttpFile(url, ev_count); + else if (::downloadUrl(url,tmp_name)) + { + readEventsFromHttpFile(tmp_name, ev_count); + remove(tmp_name.c_str()); + } + else + { + reader_ready = true; + pthread_exit(NULL); + } + + printdate_ms(stdout); + printf("[sectionsd] Reading Information finished after %" PRId64 " milliseconds (%d events)\n", + time_monotonic_ms()-now, ev_count); + + reader_ready = true; + + pthread_exit(NULL); +} + 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, diff --git a/src/eitd/xmlutil.h b/src/eitd/xmlutil.h index 2fd3bb38a..ca8b47fc8 100644 --- a/src/eitd/xmlutil.h +++ b/src/eitd/xmlutil.h @@ -35,9 +35,12 @@ #include void *insertEventsfromFile(void * data); +void *insertEventsfromHttp(void * data); bool readEventsFromFile(std::string &epgname, int &ev_count); +bool readEventsFromHttpFile(std::string &epgname, int &ev_count); bool readEventsFromDir(std::string &epgdir, int &ev_count); void writeEventsToFile(const char *epgdir); +t_channel_id getepgid(std::string epg_name); bool readEPGFilter(void); void readDVBTimeFilter(void);