X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/0d3b6f2c16aec76d38593a9e01d272817fb7fdd4..b14f1520fe0dabd185ab3555c9d2dd8ab5276dd0:/lib/dvb/epgcache.cpp diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index 46785de1..c76b0c06 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -12,15 +12,41 @@ #include // for statfs // #include #include +#include #include #include -#include +#include +#include int eventData::CacheSize=0; descriptorMap eventData::descriptors; __u8 eventData::data[4108]; extern const uint32_t crc32_table[256]; +const eServiceReference &handleGroup(const eServiceReference &ref) +{ + if (ref.flags & eServiceReference::isGroup) + { + ePtr res; + if (!eDVBResourceManager::getInstance(res)) + { + ePtr db; + if (!res->getChannelList(db)) + { + eBouquet *bouquet=0; + if (!db->getBouquet(ref, bouquet)) + { + std::list::iterator it(bouquet->m_services.begin()); + if (it != bouquet->m_services.end()) + return *it; + } + } + } + } + return ref; +} + + eventData::eventData(const eit_event_struct* e, int size, int type) :ByteSize(size&0xFF), type(type&0xFF) { @@ -31,48 +57,67 @@ eventData::eventData(const eit_event_struct* e, int size, int type) __u32 *pdescr=descr; __u8 *data = (__u8*)e; - int ptr=10; - int descriptors_length = (data[ptr++]&0x0F) << 8; - descriptors_length |= data[ptr++]; - while ( descriptors_length > 0 ) + int ptr=12; + size -= 12; + + while(size > 1) { __u8 *descr = data+ptr; - int descr_len = descr[1]+2; - - __u32 crc = 0; - int cnt=0; - while(cnt++ < descr_len) - crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ data[ptr++]) & 0xFF]; - - descriptorMap::iterator it = - descriptors.find(crc); - if ( it == descriptors.end() ) + int descr_len = descr[1]; + descr_len += 2; + if (size >= descr_len) { - CacheSize+=descr_len; - __u8 *d = new __u8[descr_len]; - memcpy(d, descr, descr_len); - descriptors[crc] = descriptorPair(1, d); + switch (descr[0]) + { + case EXTENDED_EVENT_DESCRIPTOR: + case SHORT_EVENT_DESCRIPTOR: + case LINKAGE_DESCRIPTOR: + case COMPONENT_DESCRIPTOR: + { + __u32 crc = 0; + int cnt=0; + while(cnt++ < descr_len) + crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ data[ptr++]) & 0xFF]; + + descriptorMap::iterator it = + descriptors.find(crc); + if ( it == descriptors.end() ) + { + CacheSize+=descr_len; + __u8 *d = new __u8[descr_len]; + memcpy(d, descr, descr_len); + descriptors[crc] = descriptorPair(1, d); + } + else + ++it->second.first; + *pdescr++=crc; + break; + } + default: // do not cache all other descriptors + ptr += descr_len; + break; + } + size -= descr_len; } else - ++it->second.first; - - *pdescr++=crc; - descriptors_length -= descr_len; + break; } - ByteSize = 12+((pdescr-descr)*4); + ASSERT(pdescr <= &descr[65]); + ByteSize = 10+((pdescr-descr)*4); EITdata = new __u8[ByteSize]; CacheSize+=ByteSize; - memcpy(EITdata, (__u8*) e, 12); - memcpy(EITdata+12, descr, ByteSize-12); + memcpy(EITdata, (__u8*) e, 10); + memcpy(EITdata+10, descr, ByteSize-10); } const eit_event_struct* eventData::get() const { int pos = 12; - int tmp = ByteSize-12; - memcpy(data, EITdata, 12); - __u32 *p = (__u32*)(EITdata+12); - while(tmp>0) + int tmp = ByteSize-10; + memcpy(data, EITdata, 10); + int descriptors_length=0; + __u32 *p = (__u32*)(EITdata+10); + while(tmp>3) { descriptorMap::iterator it = descriptors.find(*p++); @@ -81,21 +126,26 @@ const eit_event_struct* eventData::get() const int b = it->second.second[1]+2; memcpy(data+pos, it->second.second, b ); pos += b; + descriptors_length += b; } + else + eFatal("LINE %d descriptor not found in descriptor cache %08x!!!!!!", __LINE__, *(p-1)); tmp-=4; } - - return (const eit_event_struct*)data; + ASSERT(pos <= 4108); + data[10] = (descriptors_length >> 8) & 0x0F; + data[11] = descriptors_length & 0xFF; + return (eit_event_struct*)data; } eventData::~eventData() { if ( ByteSize ) { - CacheSize-=ByteSize; - ByteSize-=12; - __u32 *d = (__u32*)(EITdata+12); - while(ByteSize) + CacheSize -= ByteSize; + __u32 *d = (__u32*)(EITdata+10); + ByteSize -= 10; + while(ByteSize>3) { descriptorMap::iterator it = descriptors.find(*d++); @@ -109,7 +159,9 @@ eventData::~eventData() descriptors.erase(it); // remove entry from descriptor map } } - ByteSize-=4; + else + eFatal("LINE %d descriptor not found in descriptor cache %08x!!!!!!", __LINE__, *(d-1)); + ByteSize -= 4; } delete [] EITdata; } @@ -465,10 +517,11 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) if ( tm_it_tmp->first == TM ) // just update eventdata { // exempt memory - delete ev_it->second; + eventData *tmp = ev_it->second; ev_it->second = tm_it_tmp->second = new eventData(eit_event, eit_event_size, source); FixOverlapping(servicemap, TM, duration, tm_it_tmp, service); + delete tmp; goto next; } else // event has new event begin time @@ -505,32 +558,35 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) prevEventIt=servicemap.first.end(); } } - evt = new eventData(eit_event, eit_event_size, source); #ifdef EPG_DEBUG bool consistencyCheck=true; #endif if (ev_erase_count > 0 && tm_erase_count > 0) // 2 different pairs have been removed { - // exempt memory - delete ev_it->second; - delete tm_it->second; + eventData *tmp1 = ev_it->second, + *tmp2 = tm_it->second; ev_it->second=evt; tm_it->second=evt; + // exempt memory + delete tmp1; + delete tmp2; } else if (ev_erase_count == 0 && tm_erase_count > 0) { - // exempt memory - delete ev_it->second; + eventData *tmp = ev_it->second; tm_it=prevTimeIt=servicemap.second.insert( prevTimeIt, std::pair( TM, evt ) ); ev_it->second=evt; + // exempt memory + delete tmp; } else if (ev_erase_count > 0 && tm_erase_count == 0) { - // exempt memory - delete tm_it->second; + eventData *tmp = tm_it->second; ev_it=prevEventIt=servicemap.first.insert( prevEventIt, std::pair( event_id, evt) ); tm_it->second=evt; + // exempt memory + delete tmp; } else // added new eventData { @@ -687,7 +743,7 @@ void eEPGCache::cleanLoop() content_time_tables.find( DBIt->first ); if ( x != content_time_tables.end() ) { - timeMap &tmMap = eventDB[DBIt->first].second; + timeMap &tmMap = DBIt->second.second; for ( contentMap::iterator i = x->second.begin(); i != x->second.end(); ) { for ( contentTimeMap::iterator it(i->second.begin()); @@ -754,6 +810,7 @@ void eEPGCache::gotMessage( const Message &msg ) #ifdef ENABLE_PRIVATE_EPG case Message::got_private_pid: { + singleLock s(channel_map_lock); for (channelMapIterator it(m_knownChannels.begin()); it != m_knownChannels.end(); ++it) { eDVBChannel *channel = (eDVBChannel*) it->first; @@ -766,7 +823,10 @@ void eEPGCache::gotMessage( const Message &msg ) data->m_PrevVersion = -1; data->m_PrivatePid = msg.pid; data->m_PrivateService = msg.service; - updateMap::iterator It = channelLastUpdated.find( channel->getChannelID() ); + int onid = chid.original_network_id.get(); + onid |= 0x80000000; // we use highest bit as private epg indicator + chid.original_network_id = onid; + updateMap::iterator It = channelLastUpdated.find( chid ); int update = ( It != channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (eDVBLocalTimeHandler::getInstance()->nowTime()-It->second) * 1000 ) ) : ZAP_DELAY ); if (update < ZAP_DELAY) update = ZAP_DELAY; @@ -837,7 +897,7 @@ void eEPGCache::load() } char text1[13]; fread( text1, 13, 1, f); - if ( !strncmp( text1, "ENIGMA_EPG_V5", 13) ) + if ( !strncmp( text1, "ENIGMA_EPG_V7", 13) ) { fread( &size, sizeof(int), 1, f); while(size--) @@ -940,7 +1000,7 @@ void eEPGCache::save() { unsigned int magic = 0x98765432; fwrite( &magic, sizeof(int), 1, f); - const char *text = "ENIGMA_EPG_V5"; + const char *text = "ENIGMA_EPG_V7"; fwrite( text, 13, 1, f ); int size = eventDB.size(); fwrite( &size, sizeof(int), 1, f ); @@ -1314,7 +1374,7 @@ RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, co // if t == -1 we search the current event... { singleLock s(cache_lock); - uniqueEPGKey key(service); + uniqueEPGKey key(handleGroup(service)); // check if EPG for this service is ready... eventCache::iterator It = eventDB.find( key ); @@ -1390,7 +1450,7 @@ RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, eP RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id, const eventData *&result ) { singleLock s(cache_lock); - uniqueEPGKey key( service ); + uniqueEPGKey key(handleGroup(service)); eventCache::iterator It = eventDB.find( key ); if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached? @@ -1447,7 +1507,8 @@ RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id, RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin, int minutes) { - eventCache::iterator It = eventDB.find( service ); + Lock(); + eventCache::iterator It = eventDB.find(handleGroup(service)); if ( It != eventDB.end() && It->second.second.size() ) { m_timemap_end = minutes != -1 ? It->second.second.upper_bound(begin+minutes*60) : It->second.second.end(); @@ -1471,10 +1532,12 @@ RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin, } else m_timemap_cursor = It->second.second.begin(); - const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)service; + const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)handleGroup(service); currentQueryTsidOnid = (ref.getTransportStreamID().get()<<16) | ref.getOriginalNetworkID().get(); + Unlock(); return 0; } + Unlock(); return -1; } @@ -1519,9 +1582,9 @@ RESULT eEPGCache::getNextTimeEntry(ePtr &result) return -1; } -void fillTuple(PyObject *tuple, char *argstring, int argcount, PyObject *service, ePtr &ptr, PyObject *nowTime, PyObject *service_name ) +void fillTuple(ePyObject tuple, char *argstring, int argcount, ePyObject service, ePtr &ptr, ePyObject nowTime, ePyObject service_name ) { - PyObject *tmp=NULL; + ePyObject tmp; int pos=0; while(pos < argcount) { @@ -1532,22 +1595,22 @@ void fillTuple(PyObject *tuple, char *argstring, int argcount, PyObject *service tmp = PyLong_FromLong(0); break; case 'I': // Event Id - tmp = ptr ? PyLong_FromLong(ptr->getEventId()) : NULL; + tmp = ptr ? PyLong_FromLong(ptr->getEventId()) : ePyObject(); break; case 'B': // Event Begin Time - tmp = ptr ? PyLong_FromLong(ptr->getBeginTime()) : NULL; + tmp = ptr ? PyLong_FromLong(ptr->getBeginTime()) : ePyObject(); break; case 'D': // Event Duration - tmp = ptr ? PyLong_FromLong(ptr->getDuration()) : NULL; + tmp = ptr ? PyLong_FromLong(ptr->getDuration()) : ePyObject(); break; case 'T': // Event Title - tmp = ptr ? PyString_FromString(ptr->getEventName().c_str()) : NULL; + tmp = ptr ? PyString_FromString(ptr->getEventName().c_str()) : ePyObject(); break; case 'S': // Event Short Description - tmp = ptr ? PyString_FromString(ptr->getShortDescription().c_str()) : NULL; + tmp = ptr ? PyString_FromString(ptr->getShortDescription().c_str()) : ePyObject(); break; case 'E': // Event Extended Description - tmp = ptr ? PyString_FromString(ptr->getExtendedDescription().c_str()) : NULL; + tmp = ptr ? PyString_FromString(ptr->getExtendedDescription().c_str()) : ePyObject(); break; case 'C': // Current Time tmp = nowTime; @@ -1557,6 +1620,7 @@ void fillTuple(PyObject *tuple, char *argstring, int argcount, PyObject *service tmp = service; inc_refcount = true; break; + case 'n': // short service name case 'N': // service name tmp = service_name; inc_refcount = true; @@ -1572,13 +1636,13 @@ void fillTuple(PyObject *tuple, char *argstring, int argcount, PyObject *service } } -PyObject *handleEvent(ePtr &ptr, PyObject *dest_list, char* argstring, int argcount, PyObject *service, PyObject *nowTime, PyObject *service_name, PyObject *convertFunc, PyObject *convertFuncArgs) +int handleEvent(ePtr &ptr, ePyObject dest_list, char* argstring, int argcount, ePyObject service, ePyObject nowTime, ePyObject service_name, ePyObject convertFunc, ePyObject convertFuncArgs) { if (convertFunc) { fillTuple(convertFuncArgs, argstring, argcount, service, ptr, nowTime, service_name); - PyObject *result = PyObject_CallObject(convertFunc, convertFuncArgs); - if (result == NULL) + ePyObject result = PyObject_CallObject(convertFunc, convertFuncArgs); + if (result) { if (service_name) Py_DECREF(service_name); @@ -1586,14 +1650,17 @@ PyObject *handleEvent(ePtr &ptr, PyObject *dest_list, char* argst Py_DECREF(nowTime); Py_DECREF(convertFuncArgs); Py_DECREF(dest_list); - return result; + PyErr_SetString(PyExc_StandardError, + "error in convertFunc execute"); + eDebug("error in convertFunc execute"); + return -1; } PyList_Append(dest_list, result); Py_DECREF(result); } else { - PyObject *tuple = PyTuple_New(argcount); + ePyObject tuple = PyTuple_New(argcount); fillTuple(tuple, argstring, argcount, service, ptr, nowTime, service_name); PyList_Append(dest_list, tuple); Py_DECREF(tuple); @@ -1613,6 +1680,7 @@ PyObject *handleEvent(ePtr &ptr, PyObject *dest_list, char* argst // C = Current Time // R = Service Reference // N = Service Name +// n = Short Service Name // then for each service follows a tuple // first tuple entry is the servicereference (as string... use the ref.toString() function) // the second is the type of query @@ -1625,9 +1693,9 @@ PyObject *handleEvent(ePtr &ptr, PyObject *dest_list, char* argst // when type is time then it is the start_time ( 0 for now_time ) // the fourth is the end_time .. ( optional .. for query all events in time range) -PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc) +PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc) { - PyObject *convertFuncArgs=NULL; + ePyObject convertFuncArgs; int argcount=0; char *argstring=NULL; if (!PyList_Check(list)) @@ -1648,7 +1716,7 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc) } else { - PyObject *argv=PyList_GET_ITEM(list, 0); // borrowed reference! + ePyObject argv=PyList_GET_ITEM(list, 0); // borrowed reference! if (PyString_Check(argv)) { argstring = PyString_AS_STRING(argv); @@ -1671,17 +1739,17 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc) convertFuncArgs = PyTuple_New(argcount); } - PyObject *nowTime = strchr(argstring, 'C') ? + ePyObject nowTime = strchr(argstring, 'C') ? PyLong_FromLong(eDVBLocalTimeHandler::getInstance()->nowTime()) : - NULL; + ePyObject(); - bool must_get_service_name = strchr(argstring, 'N') ? true : false; + int must_get_service_name = strchr(argstring, 'N') ? 1 : strchr(argstring, 'n') ? 2 : 0; // create dest list - PyObject *dest_list=PyList_New(0); + ePyObject dest_list=PyList_New(0); while(listSize > listIt) { - PyObject *item=PyList_GET_ITEM(list, listIt++); // borrowed reference! + ePyObject item=PyList_GET_ITEM(list, listIt++); // borrowed reference! if (PyTuple_Check(item)) { bool service_changed=false; @@ -1691,10 +1759,10 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc) int minutes=0; int tupleSize=PyTuple_Size(item); int tupleIt=0; - PyObject *service=NULL; + ePyObject service; while(tupleSize > tupleIt) // parse query args { - PyObject *entry=PyTuple_GET_ITEM(item, tupleIt); // borrowed reference! + ePyObject entry=PyTuple_GET_ITEM(item, tupleIt); // borrowed reference! switch(tupleIt++) { case 0: @@ -1726,7 +1794,7 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc) break; } } - eServiceReference ref(PyString_AS_STRING(service)); + eServiceReference ref(handleGroup(eServiceReference(PyString_AS_STRING(service)))); if (ref.type != eServiceReference::idDVB) { eDebug("service reference for epg query is not valid"); @@ -1750,7 +1818,7 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc) } } - PyObject *service_name=NULL; + ePyObject service_name; if (must_get_service_name) { ePtr sptr; @@ -1763,6 +1831,19 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc) { std::string name; sptr->getName(ref, name); + + if (must_get_service_name == 1) + { + unsigned int pos; + // filter short name brakets + while((pos = name.find("\xc2\x86")) != std::string::npos) + name.erase(pos,2); + while((pos = name.find("\xc2\x87")) != std::string::npos) + name.erase(pos,2); + } + else + name = buildShortName(name); + if (name.length()) service_name = PyString_FromString(name.c_str()); } @@ -1778,9 +1859,11 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc) ePtr ptr; while (!getNextTimeEntry(ptr)) { - PyObject *ret = handleEvent(ptr, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs); - if (ret) - return ret; + if (handleEvent(ptr, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs)) + { + Unlock(); + return 0; // error + } } } Unlock(); @@ -1795,9 +1878,8 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc) else lookupEventTime(ref, stime, ptr, type); } - PyObject *ret = handleEvent(ptr, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs); - if (ret) - return ret; + if (handleEvent(ptr, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs)) + return 0; // error } if (service_changed) Py_DECREF(service); @@ -1814,9 +1896,9 @@ skip_entry: return dest_list; } -void fillTuple2(PyObject *tuple, const char *argstring, int argcount, eventData *evData, ePtr &ptr, PyObject *service_name, PyObject *service_reference) +void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData *evData, ePtr &ptr, ePyObject service_name, ePyObject service_reference) { - PyObject *tmp=NULL; + ePyObject tmp; int pos=0; while(pos < argcount) { @@ -1831,29 +1913,30 @@ void fillTuple2(PyObject *tuple, const char *argstring, int argcount, eventData break; case 'B': // Event Begin Time if (ptr) - tmp = ptr ? PyLong_FromLong(ptr->getBeginTime()) : NULL; + tmp = ptr ? PyLong_FromLong(ptr->getBeginTime()) : ePyObject(); else tmp = PyLong_FromLong(evData->getStartTime()); break; case 'D': // Event Duration if (ptr) - tmp = ptr ? PyLong_FromLong(ptr->getDuration()) : NULL; + tmp = ptr ? PyLong_FromLong(ptr->getDuration()) : ePyObject(); else tmp = PyLong_FromLong(evData->getDuration()); break; case 'T': // Event Title - tmp = ptr ? PyString_FromString(ptr->getEventName().c_str()) : NULL; + tmp = ptr ? PyString_FromString(ptr->getEventName().c_str()) : ePyObject(); break; case 'S': // Event Short Description - tmp = ptr ? PyString_FromString(ptr->getShortDescription().c_str()) : NULL; + tmp = ptr ? PyString_FromString(ptr->getShortDescription().c_str()) : ePyObject(); break; case 'E': // Event Extended Description - tmp = ptr ? PyString_FromString(ptr->getExtendedDescription().c_str()) : NULL; + tmp = ptr ? PyString_FromString(ptr->getExtendedDescription().c_str()) : ePyObject(); break; case 'R': // service reference string tmp = service_reference; inc_refcount = true; break; + case 'n': // short service name case 'N': // service name tmp = service_name; inc_refcount = true; @@ -1880,6 +1963,7 @@ void fillTuple2(PyObject *tuple, const char *argstring, int argcount, eventData // E = Event Extended Description // R = Service Reference // N = Service Name +// n = Short Service Name // the second tuple entry is the MAX matches value // the third tuple entry is the type of query // 0 = search for similar broadcastings (SIMILAR_BROADCASTINGS_SEARCH) @@ -1894,9 +1978,9 @@ void fillTuple2(PyObject *tuple, const char *argstring, int argcount, eventData // 0 = case sensitive (CASE_CHECK) // 1 = case insensitive (NO_CASECHECK) -PyObject *eEPGCache::search(PyObject *arg) +PyObject *eEPGCache::search(ePyObject arg) { - PyObject *ret = 0; + ePyObject ret; int descridx = -1; __u32 descr[512]; int eventid = -1; @@ -1912,7 +1996,7 @@ PyObject *eEPGCache::search(PyObject *arg) int tuplesize=PyTuple_Size(arg); if (tuplesize > 0) { - PyObject *obj = PyTuple_GET_ITEM(arg,0); + ePyObject obj = PyTuple_GET_ITEM(arg,0); if (PyString_Check(obj)) { argcount = PyString_GET_SIZE(obj); @@ -1943,7 +2027,7 @@ PyObject *eEPGCache::search(PyObject *arg) querytype = PyLong_AsLong(PyTuple_GET_ITEM(arg, 2)); if (tuplesize > 4 && querytype == 0) { - PyObject *obj = PyTuple_GET_ITEM(arg, 3); + ePyObject obj = PyTuple_GET_ITEM(arg, 3); if (PyString_Check(obj)) { refstr = PyString_AS_STRING(obj); @@ -1957,10 +2041,10 @@ PyObject *eEPGCache::search(PyObject *arg) if (evData) { __u8 *data = evData->EITdata; - int tmp = evData->ByteSize-12; - __u32 *p = (__u32*)(data+12); + int tmp = evData->ByteSize-10; + __u32 *p = (__u32*)(data+10); // search short and extended event descriptors - while(tmp>0) + while(tmp>3) { __u32 crc = *p++; descriptorMap::iterator it = @@ -2000,7 +2084,7 @@ PyObject *eEPGCache::search(PyObject *arg) } else if (tuplesize > 4 && (querytype == 1 || querytype == 2) ) { - PyObject *obj = PyTuple_GET_ITEM(arg, 3); + ePyObject obj = PyTuple_GET_ITEM(arg, 3); if (PyString_Check(obj)) { int casetype = PyLong_AsLong(PyTuple_GET_ITEM(arg, 4)); @@ -2103,7 +2187,7 @@ PyObject *eEPGCache::search(PyObject *arg) if (descridx > -1) { int maxcount=maxmatches; - eServiceReferenceDVB ref(refstr?refstr:""); + eServiceReferenceDVB ref(refstr?(const eServiceReferenceDVB&)handleGroup(eServiceReference(refstr)):eServiceReferenceDVB("")); // ref is only valid in SIMILAR_BROADCASTING_SEARCH // in this case we start searching with the base service bool first = ref.valid() ? true : false; @@ -2117,20 +2201,21 @@ PyObject *eEPGCache::search(PyObject *arg) ++cit; continue; } - PyObject *service_name=0; - PyObject *service_reference=0; + ePyObject service_name; + ePyObject service_reference; timeMap &evmap = cit->second.second; // check all events for (timeMap::iterator evit(evmap.begin()); evit != evmap.end() && maxcount; ++evit) { - if (evit->second->getEventID() == eventid) + int evid = evit->second->getEventID(); + if ( evid == eventid) continue; __u8 *data = evit->second->EITdata; - int tmp = evit->second->ByteSize-12; - __u32 *p = (__u32*)(data+12); + int tmp = evit->second->ByteSize-10; + __u32 *p = (__u32*)(data+10); // check if any of our descriptor used by this event int cnt=-1; - while(tmp>0) + while(tmp>3) { __u32 crc32 = *p++; for ( int i=0; i <= descridx; ++i) @@ -2152,29 +2237,46 @@ PyObject *eEPGCache::search(PyObject *arg) ePtr ptr; if (needServiceEvent) { - lookupEventId(ref, evit->first, ptr); + lookupEventId(ref, evid, ptr); if (!ptr) eDebug("event not found !!!!!!!!!!!"); } // create service name - if (!service_name && strchr(argstring,'N')) + if (!service_name) { - ePtr sptr; - eServiceCenterPtr service_center; - eServiceCenter::getPrivInstance(service_center); - if (service_center) + int must_get_service_name = strchr(argstring, 'N') ? 1 : strchr(argstring, 'n') ? 2 : 0; + if (must_get_service_name) { - service_center->info(ref, sptr); - if (sptr) + ePtr sptr; + eServiceCenterPtr service_center; + eServiceCenter::getPrivInstance(service_center); + if (service_center) { - std::string name; - sptr->getName(ref, name); - if (name.length()) - service_name = PyString_FromString(name.c_str()); + service_center->info(ref, sptr); + if (sptr) + { + std::string name; + sptr->getName(ref, name); + + if (must_get_service_name == 1) + { + unsigned int pos; + // filter short name brakets + while((pos = name.find("\xc2\x86")) != std::string::npos) + name.erase(pos,2); + while((pos = name.find("\xc2\x87")) != std::string::npos) + name.erase(pos,2); + } + else + name = buildShortName(name); + + if (name.length()) + service_name = PyString_FromString(name.c_str()); + } } + if (!service_name) + service_name = PyString_FromString(""); } - if (!service_name) - service_name = PyString_FromString(""); } // create servicereference string if (!service_reference && strchr(argstring,'R')) @@ -2183,7 +2285,7 @@ PyObject *eEPGCache::search(PyObject *arg) if (!ret) ret = PyList_New(0); // create tuple - PyObject *tuple = PyTuple_New(argcount); + ePyObject tuple = PyTuple_New(argcount); // fill tuple fillTuple2(tuple, argstring, argcount, evit->second, ptr, service_name, service_reference); PyList_Append(ret, tuple); @@ -2208,10 +2310,7 @@ PyObject *eEPGCache::search(PyObject *arg) } if (!ret) - { - Py_INCREF(Py_None); - ret=Py_None; - } + Py_RETURN_NONE; return ret; } @@ -2354,61 +2453,70 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey ¤t_service, const __ int descriptors_length = (data[ptr++]&0x0F) << 8; descriptors_length |= data[ptr++]; - while ( descriptors_length > 0 ) + while ( descriptors_length > 1 ) { int descr_type = data[ptr]; int descr_len = data[ptr+1]; - descriptors_length -= (descr_len+2); - if ( descr_type == 0xf2 ) + descriptors_length -= 2; + if (descriptors_length >= descr_len) { - ptr+=2; - int tsid = data[ptr++] << 8; - tsid |= data[ptr++]; - int onid = data[ptr++] << 8; - onid |= data[ptr++]; - int sid = data[ptr++] << 8; - sid |= data[ptr++]; + descriptors_length -= descr_len; + if ( descr_type == 0xf2 && descr_len > 5) + { + ptr+=2; + int tsid = data[ptr++] << 8; + tsid |= data[ptr++]; + int onid = data[ptr++] << 8; + onid |= data[ptr++]; + int sid = data[ptr++] << 8; + sid |= data[ptr++]; // WORKAROUND for wrong transmitted epg data (01.08.2006) - if ( onid == 0x85 ) - { - switch( (tsid << 16) | sid ) + if ( onid == 0x85 ) { - case 0x0300f0: sid = 0xe0; tsid = 2; break; - case 0x0300f1: sid = 0xe1; tsid = 2; break; - case 0x0300f5: sid = 0xdc; break; - case 0x0400d2: sid = 0xe2; tsid = 0x11; break; - case 0x1100d3: sid = 0xe3; break; + switch( (tsid << 16) | sid ) + { + case 0x01030b: sid = 0x1b; tsid = 4; break; // Premiere Win + case 0x0300f0: sid = 0xe0; tsid = 2; break; + case 0x0300f1: sid = 0xe1; tsid = 2; break; + case 0x0300f5: sid = 0xdc; break; + case 0x0400d2: sid = 0xe2; tsid = 0x11; break; + case 0x1100d3: sid = 0xe3; break; + } } - } //////////////////////////////////////////// - uniqueEPGKey service( sid, onid, tsid ); - descr_len -= 6; - while( descr_len > 0 ) - { - __u8 datetime[5]; - datetime[0] = data[ptr++]; - datetime[1] = data[ptr++]; - int tmp_len = data[ptr++]; - descr_len -= 3; - while( tmp_len > 0 ) + uniqueEPGKey service( sid, onid, tsid ); + descr_len -= 6; + while( descr_len > 2 ) { - memcpy(datetime+2, data+ptr, 3); - ptr+=3; + __u8 datetime[5]; + datetime[0] = data[ptr++]; + datetime[1] = data[ptr++]; + int tmp_len = data[ptr++]; descr_len -= 3; - tmp_len -= 3; - start_times[datetime].push_back(service); + if (descr_len >= tmp_len) + { + descr_len -= tmp_len; + while( tmp_len > 2 ) + { + memcpy(datetime+2, data+ptr, 3); + ptr += 3; + tmp_len -= 3; + start_times[datetime].push_back(service); + } + } } } - } - else - { - *pdescr++=data+ptr; - ptr += 2; - ptr += descr_len; + else + { + *pdescr++=data+ptr; + ptr += 2; + ptr += descr_len; + } } } + ASSERT(pdescr <= &descriptors[65]) __u8 event[4098]; eit_event_struct *ev_struct = (eit_event_struct*) event; ev_struct->running_status = 0; @@ -2422,6 +2530,7 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey ¤t_service, const __ ptr+=(*d++)[1]; ptr+=2; } + ASSERT(ptr <= 4098); for ( std::map< date_time, std::list >::iterator it(start_times.begin()); it != start_times.end(); ++it ) { time_t now = eDVBLocalTimeHandler::getInstance()->nowTime(); @@ -2461,6 +2570,7 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey ¤t_service, const __ eventData *d = new eventData( ev_struct, bptr, PRIVATE ); evMap[event_id] = d; tmMap[stime] = d; + ASSERT(bptr <= 4098); } } @@ -2487,7 +2597,7 @@ void eEPGCache::channel_data::startPrivateReader() void eEPGCache::channel_data::readPrivateData( const __u8 *data) { - if ( seenPrivateSections.find( data[6] ) == seenPrivateSections.end() ) + if ( seenPrivateSections.find(data[6]) == seenPrivateSections.end() ) { cache->privateSectionRead(m_PrivateService, data); seenPrivateSections.insert(data[6]); @@ -2495,6 +2605,11 @@ void eEPGCache::channel_data::readPrivateData( const __u8 *data) if ( seenPrivateSections.size() == (unsigned int)(data[7] + 1) ) { eDebug("[EPGC] private finished"); + eDVBChannelID chid = channel->getChannelID(); + int tmp = chid.original_network_id.get(); + tmp |= 0x80000000; // we use highest bit as private epg indicator + chid.original_network_id = tmp; + cache->channelLastUpdated[chid] = eDVBLocalTimeHandler::getInstance()->nowTime(); m_PrevVersion = (data[5] & 0x3E) >> 1; startPrivateReader(); } @@ -2559,19 +2674,21 @@ void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minu putenv("TZ=CET-1CEST,M3.5.0/2,M10.5.0/3"); tzset(); - tm *localnow = localtime( &dt ); + tm localnow; + localtime_r(&dt, &localnow); if (day == 7) day = 0; - if ( day + 1 < localnow->tm_wday ) // day + 1 to prevent old events to show for next week. + if ( day + 1 < localnow.tm_wday ) // day + 1 to prevent old events to show for next week. day += 7; if (local_hours <= 5) day++; - dt += 3600*24*(day - localnow->tm_wday); // Shift dt to the recording date (local time zone). - dt += 3600*(local_hours - localnow->tm_hour); // Shift dt to the recording hour. + dt += 3600*24*(day - localnow.tm_wday); // Shift dt to the recording date (local time zone). + dt += 3600*(local_hours - localnow.tm_hour); // Shift dt to the recording hour. - tm *recdate = gmtime( &dt ); // This will also take care of DST. + tm recdate; + gmtime_r( &dt, &recdate ); // This will also take care of DST. if ( old_tz == NULL ) unsetenv( "TZ" ); @@ -2581,15 +2698,15 @@ void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minu // Calculate MJD according to annex in ETSI EN 300 468 int l=0; - if ( recdate->tm_mon <= 1 ) // Jan or Feb + if ( recdate.tm_mon <= 1 ) // Jan or Feb l=1; - int mjd = 14956 + recdate->tm_mday + int( (recdate->tm_year - l) * 365.25) + - int( (recdate->tm_mon + 2 + l * 12) * 30.6001); + int mjd = 14956 + recdate.tm_mday + int( (recdate.tm_year - l) * 365.25) + + int( (recdate.tm_mon + 2 + l * 12) * 30.6001); return_time[0] = (mjd & 0xFF00)>>8; return_time[1] = mjd & 0xFF; - timeMHW2DVB( recdate->tm_hour, minutes, return_time+2 ); + timeMHW2DVB( recdate.tm_hour, minutes, return_time+2 ); } void eEPGCache::channel_data::storeTitle(std::map<__u32, mhw_title_t>::iterator itTitle, std::string sumText, const __u8 *data) @@ -3213,7 +3330,7 @@ start_summary: } } abort: - isRunning &= ~eEPGCache::MHW; + isRunning &= ~MHW; m_MHWConn2=0; if ( m_MHWReader2 ) m_MHWReader2->stop();