X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/24ac423a92cf63ed6a8a09fa1ef48bef2c9382a6..a29bbc0a4ee2eb5f0d86407088380de9887359a0:/lib/dvb/epgcache.cpp diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index 550561e2..2a070473 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -372,8 +372,9 @@ void eEPGCache::DVBChannelStateChanged(iDVBChannel *chan) } } -void eEPGCache::FixOverlapping(std::pair &servicemap, time_t TM, int duration, const timeMap::iterator &tm_it, const uniqueEPGKey &service) +bool eEPGCache::FixOverlapping(std::pair &servicemap, time_t TM, int duration, const timeMap::iterator &tm_it, const uniqueEPGKey &service) { + bool ret = false; timeMap::iterator tmp = tm_it; while ((tmp->first+tmp->second->getDuration()-300) > TM) { @@ -406,6 +407,7 @@ void eEPGCache::FixOverlapping(std::pair &servicemap, time_t T } else servicemap.second.erase(tmp--); + ret = true; } else { @@ -434,12 +436,14 @@ void eEPGCache::FixOverlapping(std::pair &servicemap, time_t T #endif delete tmp->second; servicemap.second.erase(tmp++); + ret = true; } else ++tmp; if (tmp == servicemap.second.end()) break; } + return ret; } void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) @@ -456,13 +460,20 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) if ( data[ptr-1] < 0x40 ) --ptr; - uniqueEPGKey service( HILO(eit->service_id), HILO(eit->original_network_id), HILO(eit->transport_stream_id) ); + // Cablecom HACK .. tsid / onid in eit data are incorrect.. so we use + // it from running channel (just for current transport stream eit data) + bool use_transponder_chid = source == SCHEDULE || (source == NOWNEXT && data[0] == 0x4E); + eDVBChannelID chid = channel->channel->getChannelID(); + uniqueEPGKey service( HILO(eit->service_id), + use_transponder_chid ? chid.original_network_id.get() : HILO(eit->original_network_id), + use_transponder_chid ? chid.transport_stream_id.get() : HILO(eit->transport_stream_id)); + eit_event_struct* eit_event = (eit_event_struct*) (data+ptr); int eit_event_size; int duration; time_t TM = parseDVBtime( eit_event->start_time_1, eit_event->start_time_2, eit_event->start_time_3, eit_event->start_time_4, eit_event->start_time_5); - time_t now = eDVBLocalTimeHandler::getInstance()->nowTime(); + time_t now = ::time(0); if ( TM != 3599 && TM > -1) channel->haveData |= source; @@ -523,7 +534,11 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) 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); + if (FixOverlapping(servicemap, TM, duration, tm_it_tmp, service)) + { + prevEventIt = servicemap.first.end(); + prevTimeIt = servicemap.second.end(); + } delete tmp; goto next; } @@ -596,8 +611,6 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) tm_it=prevTimeIt=servicemap.second.insert( prevTimeIt, std::pair( TM, evt ) ); } - FixOverlapping(servicemap, TM, duration, tm_it, service); - #ifdef EPG_DEBUG if ( consistencyCheck ) { @@ -617,6 +630,11 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) ev_it->first, event_id ); } #endif + if (FixOverlapping(servicemap, TM, duration, tm_it, service)) + { + prevEventIt = servicemap.first.end(); + prevTimeIt = servicemap.second.end(); + } } next: #ifdef EPG_DEBUG @@ -707,7 +725,7 @@ void eEPGCache::cleanLoop() { eDebug("[EPGC] start cleanloop"); - time_t now = eDVBLocalTimeHandler::getInstance()->nowTime(); + time_t now = ::time(0); for (eventCache::iterator DBIt = eventDB.begin(); DBIt != eventDB.end(); DBIt++) { @@ -826,7 +844,7 @@ void eEPGCache::gotMessage( const Message &msg ) 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 ); + int update = ( It != channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (::time(0)-It->second) * 1000 ) ) : ZAP_DELAY ); if (update < ZAP_DELAY) update = ZAP_DELAY; data->startPrivateTimer.start(update, 1); @@ -1089,7 +1107,7 @@ bool eEPGCache::channel_data::finishEPG() { if (!isRunning) // epg ready { - eDebug("[EPGC] stop caching events(%ld)", eDVBLocalTimeHandler::getInstance()->nowTime()); + eDebug("[EPGC] stop caching events(%ld)", ::time(0)); zapTimer.start(UPDATE_INTERVAL, 1); eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000); for (int i=0; i < 3; ++i) @@ -1098,7 +1116,7 @@ bool eEPGCache::channel_data::finishEPG() calcedSections[i].clear(); } singleLock l(cache->cache_lock); - cache->channelLastUpdated[channel->getChannelID()] = eDVBLocalTimeHandler::getInstance()->nowTime(); + cache->channelLastUpdated[channel->getChannelID()] = ::time(0); #ifdef ENABLE_MHW_EPG cleanup(); #endif @@ -1109,7 +1127,7 @@ bool eEPGCache::channel_data::finishEPG() void eEPGCache::channel_data::startEPG() { - eDebug("[EPGC] start caching events(%ld)", eDVBLocalTimeHandler::getInstance()->nowTime()); + eDebug("[EPGC] start caching events(%ld)", ::time(0)); state=0; haveData=0; for (int i=0; i < 3; ++i) @@ -1222,7 +1240,7 @@ void eEPGCache::channel_data::startChannel() pthread_mutex_lock(&channel_active); updateMap::iterator It = cache->channelLastUpdated.find( channel->getChannelID() ); - int update = ( It != cache->channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (eDVBLocalTimeHandler::getInstance()->nowTime()-It->second) * 1000 ) ) : ZAP_DELAY ); + int update = ( It != cache->channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (::time(0)-It->second) * 1000 ) ) : ZAP_DELAY ); if (update < ZAP_DELAY) update = ZAP_DELAY; @@ -1331,7 +1349,7 @@ void eEPGCache::channel_data::readData( const __u8 *data) break; default: eDebugNoNewLine("unknown");break; } - eDebug(" finished(%ld)", eDVBLocalTimeHandler::getInstance()->nowTime()); + eDebug(" finished(%ld)", ::time(0)); if ( reader ) reader->stop(); isRunning &= ~source; @@ -1381,7 +1399,7 @@ RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, co if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached ? { if (t==-1) - t = eDVBLocalTimeHandler::getInstance()->nowTime(); + t = ::time(0); timeMap::iterator i = direction <= 0 ? It->second.second.lower_bound(t) : // find > or equal It->second.second.upper_bound(t); // just > if ( i != It->second.second.end() ) @@ -1507,42 +1525,37 @@ RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id, RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin, int minutes) { + singleLock s(cache_lock); const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)handleGroup(service); - Lock(); + if (begin == -1) + begin = ::time(0); eventCache::iterator It = eventDB.find(ref); if ( It != eventDB.end() && It->second.second.size() ) { - if ( begin != -1 ) + m_timemap_cursor = It->second.second.lower_bound(begin); + if ( m_timemap_cursor != It->second.second.end() ) { - m_timemap_cursor = It->second.second.lower_bound(begin); - if ( m_timemap_cursor != It->second.second.end() ) + if ( m_timemap_cursor->first != begin ) { - if ( m_timemap_cursor->first != begin ) + timeMap::iterator x = m_timemap_cursor; + --x; + if ( x != It->second.second.end() ) { - timeMap::iterator x = m_timemap_cursor; - --x; - if ( x != It->second.second.end() ) - { - time_t start_time = x->first; - if ( begin > start_time && begin < (start_time+x->second->getDuration())) - m_timemap_cursor = x; - } + time_t start_time = x->first; + if ( begin > start_time && begin < (start_time+x->second->getDuration())) + m_timemap_cursor = x; } } } - else - m_timemap_cursor = It->second.second.begin(); - if (minutes != -1 && m_timemap_cursor != It->second.second.end()) - m_timemap_end = It->second.second.upper_bound(m_timemap_cursor->first+minutes*60); + if (minutes != -1) + m_timemap_end = It->second.second.lower_bound(begin+minutes*60); else m_timemap_end = It->second.second.end(); currentQueryTsidOnid = (ref.getTransportStreamID().get()<<16) | ref.getOriginalNetworkID().get(); - Unlock(); - return 0; + return m_timemap_cursor == m_timemap_end ? -1 : 0; } - Unlock(); return -1; } @@ -1587,14 +1600,15 @@ RESULT eEPGCache::getNextTimeEntry(ePtr &result) return -1; } -void fillTuple(ePyObject tuple, char *argstring, int argcount, ePyObject service, ePtr &ptr, ePyObject nowTime, ePyObject service_name ) +void fillTuple(ePyObject tuple, const char *argstring, int argcount, ePyObject service, eServiceEvent *ptr, ePyObject nowTime, ePyObject service_name ) { ePyObject tmp; - int pos=0; - while(pos < argcount) + int spos=0, tpos=0; + char c; + while(spos < argcount) { bool inc_refcount=false; - switch(argstring[pos]) + switch((c=argstring[spos++])) { case '0': // PyLong 0 tmp = PyLong_FromLong(0); @@ -1629,6 +1643,12 @@ void fillTuple(ePyObject tuple, char *argstring, int argcount, ePyObject service case 'N': // service name tmp = service_name; inc_refcount = true; + break; + case 'X': + ++argcount; + continue; + default: // ignore unknown + eDebug("fillTuple unknown '%c'... insert 'None' in result", c); } if (!tmp) { @@ -1637,11 +1657,11 @@ void fillTuple(ePyObject tuple, char *argstring, int argcount, ePyObject service } if (inc_refcount) Py_INCREF(tmp); - PyTuple_SET_ITEM(tuple, pos++, tmp); + PyTuple_SET_ITEM(tuple, tpos++, tmp); } } -int handleEvent(ePtr &ptr, ePyObject dest_list, char* argstring, int argcount, ePyObject service, ePyObject nowTime, ePyObject service_name, ePyObject convertFunc, ePyObject convertFuncArgs) +int handleEvent(eServiceEvent *ptr, ePyObject dest_list, const char* argstring, int argcount, ePyObject service, ePyObject nowTime, ePyObject service_name, ePyObject convertFunc, ePyObject convertFuncArgs) { if (convertFunc) { @@ -1686,6 +1706,9 @@ int handleEvent(ePtr &ptr, ePyObject dest_list, char* argstring, // R = Service Reference // N = Service Name // n = Short Service Name +// X = Return a minimum of one tuple per service in the result list... even when no event was found. +// The returned tuple is filled with all available infos... non avail is filled as None +// The position and existence of 'X' in the format string has no influence on the result tuple... its completely ignored.. // 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 @@ -1702,7 +1725,7 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc) { ePyObject convertFuncArgs; int argcount=0; - char *argstring=NULL; + const char *argstring=NULL; if (!PyList_Check(list)) { PyErr_SetString(PyExc_StandardError, @@ -1732,6 +1755,11 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc) argcount = strlen(argstring); // eDebug("have %d args('%s')", argcount, argstring); } + + bool forceReturnOne = strchr(argstring, 'X') ? true : false; + if (forceReturnOne) + --argcount; + if (convertFunc) { if (!PyCallable_Check(convertFunc)) @@ -1745,7 +1773,7 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc) } ePyObject nowTime = strchr(argstring, 'C') ? - PyLong_FromLong(eDVBLocalTimeHandler::getInstance()->nowTime()) : + PyLong_FromLong(::time(0)) : ePyObject(); int must_get_service_name = strchr(argstring, 'N') ? 1 : strchr(argstring, 'n') ? 2 : 0; @@ -1799,6 +1827,10 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc) break; } } + + if (minutes && stime == -1) + stime = ::time(0); + eServiceReference ref(handleGroup(eServiceReference(PyString_AS_STRING(service)))); if (ref.type != eServiceReference::idDVB) { @@ -1839,7 +1871,7 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc) if (must_get_service_name == 1) { - unsigned int pos; + size_t pos; // filter short name brakets while((pos = name.find("\xc2\x86")) != std::string::npos) name.erase(pos,2); @@ -1858,32 +1890,45 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc) } if (minutes) { - Lock(); + singleLock s(cache_lock); if (!startTimeQuery(ref, stime, minutes)) { - ePtr ptr; - while (!getNextTimeEntry(ptr)) + while ( m_timemap_cursor != m_timemap_end ) { - if (handleEvent(ptr, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs)) - { - Unlock(); + Event ev((uint8_t*)m_timemap_cursor++->second->get()); + eServiceEvent evt; + evt.parseFrom(&ev, currentQueryTsidOnid); + if (handleEvent(&evt, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs)) return 0; // error - } } } - Unlock(); + else if (forceReturnOne && handleEvent(0, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs)) + return 0; // error } else { - ePtr ptr; + eServiceEvent evt; + const eventData *ev_data=0; if (stime) { + singleLock s(cache_lock); if (type == 2) - lookupEventId(ref, event_id, ptr); + lookupEventId(ref, event_id, ev_data); else - lookupEventTime(ref, stime, ptr, type); + lookupEventTime(ref, stime, ev_data, type); + if (ev_data) + { + const eServiceReferenceDVB &dref = (const eServiceReferenceDVB&)ref; + Event ev((uint8_t*)ev_data->get()); + evt.parseFrom(&ev, (dref.getTransportStreamID().get()<<16)|dref.getOriginalNetworkID().get()); + } } - if (handleEvent(ptr, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs)) + if (ev_data) + { + if (handleEvent(&evt, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs)) + return 0; // error + } + else if (forceReturnOne && handleEvent(0, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs)) return 0; // error } if (service_changed) @@ -1901,7 +1946,7 @@ skip_entry: return dest_list; } -void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData *evData, ePtr &ptr, ePyObject service_name, ePyObject service_reference) +void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData *evData, eServiceEvent *ptr, ePyObject service_name, ePyObject service_reference) { ePyObject tmp; int pos=0; @@ -1946,6 +1991,8 @@ void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData tmp = service_name; inc_refcount = true; break; + default: // ignore unknown + eDebug("fillTuple2 unknown '%c'... insert None in Result", argstring[pos]); } if (!tmp) { @@ -2073,16 +2120,14 @@ PyObject *eEPGCache::search(ePyObject arg) } else { - PyErr_SetString(PyExc_StandardError, - "type error"); + PyErr_SetString(PyExc_StandardError, "type error"); eDebug("tuple arg 4 is not a valid service reference string"); return NULL; } } else { - PyErr_SetString(PyExc_StandardError, - "type error"); + PyErr_SetString(PyExc_StandardError, "type error"); eDebug("tuple arg 4 is not a string"); return NULL; } @@ -2239,12 +2284,18 @@ PyObject *eEPGCache::search(ePyObject arg) if (ref.valid()) { // create servive event - ePtr ptr; + eServiceEvent ptr; + const eventData *ev_data=0; if (needServiceEvent) { - lookupEventId(ref, evid, ptr); - if (!ptr) + if (lookupEventId(ref, evid, ev_data)) eDebug("event not found !!!!!!!!!!!"); + else + { + const eServiceReferenceDVB &dref = (const eServiceReferenceDVB&)ref; + Event ev((uint8_t*)ev_data->get()); + ptr.parseFrom(&ev, (dref.getTransportStreamID().get()<<16)|dref.getOriginalNetworkID().get()); + } } // create service name if (!service_name) @@ -2265,7 +2316,7 @@ PyObject *eEPGCache::search(ePyObject arg) if (must_get_service_name == 1) { - unsigned int pos; + size_t pos; // filter short name brakets while((pos = name.find("\xc2\x86")) != std::string::npos) name.erase(pos,2); @@ -2292,7 +2343,7 @@ PyObject *eEPGCache::search(ePyObject arg) // create tuple ePyObject tuple = PyTuple_New(argcount); // fill tuple - fillTuple2(tuple, argstring, argcount, evit->second, ptr, service_name, service_reference); + fillTuple2(tuple, argstring, argcount, evit->second, ev_data ? &ptr : 0, service_name, service_reference); PyList_Append(ret, tuple); Py_DECREF(tuple); --maxcount; @@ -2476,7 +2527,7 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey ¤t_service, const __ int sid = data[ptr++] << 8; sid |= data[ptr++]; -// WORKAROUND for wrong transmitted epg data (01.08.2006) +// WORKAROUND for wrong transmitted epg data (01.10.2007) if ( onid == 0x85 ) { switch( (tsid << 16) | sid ) @@ -2487,6 +2538,7 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey ¤t_service, const __ case 0x0300f5: sid = 0xdc; break; case 0x0400d2: sid = 0xe2; tsid = 0x11; break; case 0x1100d3: sid = 0xe3; break; + case 0x0100d4: sid = 0xe4; tsid = 4; break; } } //////////////////////////////////////////// @@ -2538,7 +2590,7 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey ¤t_service, const __ 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(); + time_t now = ::time(0); if ( (it->first.tm + duration_sec) < now ) continue; memcpy(event+2, it->first.data, 5); @@ -2614,7 +2666,7 @@ void eEPGCache::channel_data::readPrivateData( const __u8 *data) 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(); + cache->channelLastUpdated[chid] = ::time(0); m_PrevVersion = (data[5] & 0x3E) >> 1; startPrivateReader(); } @@ -2673,7 +2725,7 @@ void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minu // As far as we know all mhw time data is sent in central Europe time zone. // So, temporarily set timezone to western europe - time_t dt = eDVBLocalTimeHandler::getInstance()->nowTime(); + time_t dt = ::time(0); char *old_tz = getenv( "TZ" ); putenv("TZ=CET-1CEST,M3.5.0/2,M10.5.0/3"); @@ -3043,7 +3095,7 @@ void eEPGCache::channel_data::readMHWData(const __u8 *data) } } eDebug("[EPGC] mhw finished(%ld) %d summaries not found", - eDVBLocalTimeHandler::getInstance()->nowTime(), + ::time(0), m_program_ids.size()); // Summaries have been read, titles that have summaries have been stored. // Now store titles that do not have summaries. @@ -3348,7 +3400,7 @@ start_summary: for (std::map<__u32, mhw_title_t>::iterator itTitle(m_titles.begin()); itTitle != m_titles.end(); itTitle++) storeTitle( itTitle, "", data ); eDebug("[EPGC] mhw2 finished(%ld) %d summaries not found", - eDVBLocalTimeHandler::getInstance()->nowTime(), + ::time(0), m_program_ids.size()); } }