X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/17f0a48b8816b223f684b8deb227ab333e9e8725..b80e9a16a2a0400fec0dd270d0eb75b0c456055a:/lib/dvb/epgcache.cpp diff --git a/lib/dvb/epgcache.cpp b/lib/dvb/epgcache.cpp index 2a070473..2dc36412 100644 --- a/lib/dvb/epgcache.cpp +++ b/lib/dvb/epgcache.cpp @@ -213,13 +213,13 @@ pthread_mutex_t eEPGCache::channel_map_lock= DEFINE_REF(eEPGCache) eEPGCache::eEPGCache() - :messages(this,1), cleanTimer(this)//, paused(0) + :messages(this,1), cleanTimer(eTimer::create(this))//, paused(0) { eDebug("[EPGC] Initialized EPGCache"); CONNECT(messages.recv_msg, eEPGCache::gotMessage); CONNECT(eDVBLocalTimeHandler::getInstance()->m_timeUpdated, eEPGCache::timeUpdated); - CONNECT(cleanTimer.timeout, eEPGCache::cleanLoop); + CONNECT(cleanTimer->timeout, eEPGCache::cleanLoop); ePtr res_mgr; eDVBResourceManager::getInstance(res_mgr); @@ -303,6 +303,13 @@ void eEPGCache::DVBChannelRunning(iDVBChannel *chan) eDebug("[eEPGCache] couldnt initialize schedule other reader!!"); return; } + + res = demux->createSectionReader( this, data.m_ViasatReader ); + if ( res ) + { + eDebug("[eEPGCache] couldnt initialize viasat reader!!"); + return; + } #ifdef ENABLE_PRIVATE_EPG res = demux->createSectionReader( this, data.m_PrivateReader ); if ( res ) @@ -472,7 +479,12 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) 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 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 = ::time(0); if ( TM != 3599 && TM > -1) @@ -487,6 +499,7 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) while (ptrdescriptors_loop_length)+EIT_LOOP_SIZE; duration = fromBCD(eit_event->duration_1)*3600+fromBCD(eit_event->duration_2)*60+fromBCD(eit_event->duration_3); @@ -495,7 +508,8 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) eit_event->start_time_2, eit_event->start_time_3, eit_event->start_time_4, - eit_event->start_time_5); + eit_event->start_time_5, + &event_hash); if ( TM == 3599 ) goto next; @@ -506,16 +520,24 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel) if ( now <= (TM+duration) || TM == 3599 /*NVOD Service*/ ) // old events should not be cached { __u16 event_id = HILO(eit_event->event_id); -// eDebug("event_id is %d sid is %04x", event_id, service.sid); - eventData *evt = 0; int ev_erase_count = 0; int tm_erase_count = 0; + if (event_id == 0) { + // hack for some polsat services on 13.0E..... but this also replaces other valid event_ids with value 0.. + // but we dont care about it... + event_id = event_hash; + eit_event->event_id_hi = event_hash >> 8; + eit_event->event_id_lo = event_hash & 0xFF; + } + // search in eventmap eventMap::iterator ev_it = servicemap.first.find(event_id); +// eDebug("event_id is %d sid is %04x", event_id, service.sid); + // entry with this event_id is already exist ? if ( ev_it != servicemap.first.end() ) { @@ -783,7 +805,7 @@ void eEPGCache::cleanLoop() eDebug("[EPGC] stop cleanloop"); eDebug("[EPGC] %i bytes for cache used", eventData::CacheSize); } - cleanTimer.start(CLEAN_INTERVAL,true); + cleanTimer->start(CLEAN_INTERVAL,true); } eEPGCache::~eEPGCache() @@ -847,7 +869,7 @@ void eEPGCache::gotMessage( const Message &msg ) 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); + data->startPrivateTimer->start(update, 1); if (update >= 60000) eDebug("[EPGC] next private update in %i min", update/60000); else if (update >= 1000) @@ -1018,7 +1040,7 @@ void eEPGCache::save() { unsigned int magic = 0x98765432; fwrite( &magic, sizeof(int), 1, f); - const char *text = "ENIGMA_EPG_V7"; + const char *text = "UNFINISHED_V7"; fwrite( text, 13, 1, f ); int size = eventDB.size(); fwrite( &size, sizeof(int), 1, f ); @@ -1065,6 +1087,11 @@ void eEPGCache::save() } } #endif + // write version string after binary data + // has been written to disk. + fsync(fileno(f)); + fseek(f, sizeof(int), SEEK_SET); + fwrite("ENIGMA_EPG_V7", 13, 1, f); fclose(f); #if 0 unsigned char md5[16]; @@ -1083,22 +1110,22 @@ void eEPGCache::save() eEPGCache::channel_data::channel_data(eEPGCache *ml) :cache(ml) - ,abortTimer(ml), zapTimer(ml), state(0) + ,abortTimer(eTimer::create(ml)), zapTimer(eTimer::create(ml)), state(0) ,isRunning(0), haveData(0) #ifdef ENABLE_PRIVATE_EPG - ,startPrivateTimer(ml) + ,startPrivateTimer(eTimer::create(ml)) #endif #ifdef ENABLE_MHW_EPG - ,m_MHWTimeoutTimer(ml) + ,m_MHWTimeoutTimer(eTimer::create(ml)) #endif { #ifdef ENABLE_MHW_EPG - CONNECT(m_MHWTimeoutTimer.timeout, eEPGCache::channel_data::MHWTimeout); + CONNECT(m_MHWTimeoutTimer->timeout, eEPGCache::channel_data::MHWTimeout); #endif - CONNECT(zapTimer.timeout, eEPGCache::channel_data::startEPG); - CONNECT(abortTimer.timeout, eEPGCache::channel_data::abortNonAvail); + CONNECT(zapTimer->timeout, eEPGCache::channel_data::startEPG); + CONNECT(abortTimer->timeout, eEPGCache::channel_data::abortNonAvail); #ifdef ENABLE_PRIVATE_EPG - CONNECT(startPrivateTimer.timeout, eEPGCache::channel_data::startPrivateReader); + CONNECT(startPrivateTimer->timeout, eEPGCache::channel_data::startPrivateReader); #endif pthread_mutex_init(&channel_active, 0); } @@ -1108,9 +1135,9 @@ bool eEPGCache::channel_data::finishEPG() if (!isRunning) // epg ready { eDebug("[EPGC] stop caching events(%ld)", ::time(0)); - zapTimer.start(UPDATE_INTERVAL, 1); + zapTimer->start(UPDATE_INTERVAL, 1); eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000); - for (int i=0; i < 3; ++i) + for (unsigned int i=0; i < sizeof(seenSections)/sizeof(tidMap); ++i) { seenSections[i].clear(); calcedSections[i].clear(); @@ -1130,7 +1157,7 @@ void eEPGCache::channel_data::startEPG() eDebug("[EPGC] start caching events(%ld)", ::time(0)); state=0; haveData=0; - for (int i=0; i < 3; ++i) + for (unsigned int i=0; i < sizeof(seenSections)/sizeof(tidMap); ++i) { seenSections[i].clear(); calcedSections[i].clear(); @@ -1181,7 +1208,15 @@ void eEPGCache::channel_data::startEPG() m_ScheduleOtherReader->start(mask); isRunning |= SCHEDULE_OTHER; - abortTimer.start(7000,true); + mask.pid = 0x39; + + mask.data[0] = 0x40; + mask.mask[0] = 0x40; + m_ViasatReader->connectRead(slot(*this, &eEPGCache::channel_data::readDataViasat), m_ViasatConn); + m_ViasatReader->start(mask); + isRunning |= VIASAT; + + abortTimer->start(7000,true); } void eEPGCache::channel_data::abortNonAvail() @@ -1204,11 +1239,18 @@ void eEPGCache::channel_data::abortNonAvail() } if ( !(haveData&SCHEDULE_OTHER) && (isRunning&SCHEDULE_OTHER) ) { - eDebug("[EPGC] abort non avail schedule_other reading"); + eDebug("[EPGC] abort non avail schedule other reading"); isRunning &= ~SCHEDULE_OTHER; m_ScheduleOtherReader->stop(); m_ScheduleOtherConn=0; } + if ( !(haveData&VIASAT) && (isRunning&VIASAT) ) + { + eDebug("[EPGC] abort non avail viasat reading"); + isRunning &= ~VIASAT; + m_ViasatReader->stop(); + m_ViasatConn=0; + } #ifdef ENABLE_MHW_EPG if ( !(haveData&MHW) && (isRunning&MHW) ) { @@ -1220,12 +1262,14 @@ void eEPGCache::channel_data::abortNonAvail() m_MHWConn2=0; } #endif - if ( isRunning ) - abortTimer.start(90000, true); + if ( isRunning & VIASAT ) + abortTimer->start(300000, true); + else if ( isRunning ) + abortTimer->start(90000, true); else { ++state; - for (int i=0; i < 3; ++i) + for (unsigned int i=0; i < sizeof(seenSections)/sizeof(tidMap); ++i) { seenSections[i].clear(); calcedSections[i].clear(); @@ -1245,7 +1289,7 @@ void eEPGCache::channel_data::startChannel() if (update < ZAP_DELAY) update = ZAP_DELAY; - zapTimer.start(update, 1); + zapTimer->start(update, 1); if (update >= 60000) eDebug("[EPGC] next update in %i min", update/60000); else if (update >= 1000) @@ -1254,13 +1298,13 @@ void eEPGCache::channel_data::startChannel() void eEPGCache::channel_data::abortEPG() { - for (int i=0; i < 3; ++i) + for (unsigned int i=0; i < sizeof(seenSections)/sizeof(tidMap); ++i) { seenSections[i].clear(); calcedSections[i].clear(); } - abortTimer.stop(); - zapTimer.stop(); + abortTimer->stop(); + zapTimer->stop(); if (isRunning) { eDebug("[EPGC] abort caching events !!"); @@ -1282,6 +1326,12 @@ void eEPGCache::channel_data::abortEPG() m_ScheduleOtherReader->stop(); m_ScheduleOtherConn=0; } + if (isRunning & VIASAT) + { + isRunning &= ~VIASAT; + m_ViasatReader->stop(); + m_ViasatConn=0; + } #ifdef ENABLE_MHW_EPG if (isRunning & MHW) { @@ -1302,6 +1352,15 @@ void eEPGCache::channel_data::abortEPG() pthread_mutex_unlock(&channel_active); } + +void eEPGCache::channel_data::readDataViasat( const __u8 *data) +{ + __u8 *d=0; + memcpy(&d, &data, sizeof(__u8*)); + d[0] |= 0x80; + readData(data); +} + void eEPGCache::channel_data::readData( const __u8 *data) { int source; @@ -1324,6 +1383,12 @@ void eEPGCache::channel_data::readData( const __u8 *data) source=SCHEDULE_OTHER; map=2; break; + case 0xD0 ... 0xDF: + case 0xE0 ... 0xEF: + reader=m_ViasatReader; + source=VIASAT; + map=3; + break; default: eDebug("[EPGC] unknown table_id !!!"); return; @@ -1347,6 +1412,10 @@ void eEPGCache::channel_data::readData( const __u8 *data) m_ScheduleOtherConn=0; eDebugNoNewLine("schedule other"); break; + case VIASAT: + m_ViasatConn=0; + eDebugNoNewLine("viasat"); + break; default: eDebugNoNewLine("unknown");break; } eDebug(" finished(%ld)", ::time(0)); @@ -1648,6 +1717,7 @@ void fillTuple(ePyObject tuple, const char *argstring, int argcount, ePyObject s ++argcount; continue; default: // ignore unknown + tmp = ePyObject(); eDebug("fillTuple unknown '%c'... insert 'None' in result", c); } if (!tmp) @@ -1667,7 +1737,7 @@ int handleEvent(eServiceEvent *ptr, ePyObject dest_list, const char* argstring, { fillTuple(convertFuncArgs, argstring, argcount, service, ptr, nowTime, service_name); ePyObject result = PyObject_CallObject(convertFunc, convertFuncArgs); - if (result) + if (!result) { if (service_name) Py_DECREF(service_name); @@ -1992,6 +2062,7 @@ void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData inc_refcount = true; break; default: // ignore unknown + tmp = ePyObject(); eDebug("fillTuple2 unknown '%c'... insert None in Result", argstring[pos]); } if (!tmp) @@ -2042,6 +2113,8 @@ PyObject *eEPGCache::search(ePyObject arg) int querytype=-1; bool needServiceEvent=false; int maxmatches=0; + int must_get_service_name = 0; + bool must_get_service_reference = false; if (PyTuple_Check(arg)) { @@ -2051,7 +2124,11 @@ PyObject *eEPGCache::search(ePyObject arg) ePyObject obj = PyTuple_GET_ITEM(arg,0); if (PyString_Check(obj)) { +#if PY_VERSION_HEX < 0x02060000 argcount = PyString_GET_SIZE(obj); +#else + argcount = PyString_Size(obj); +#endif argstring = PyString_AS_STRING(obj); for (int i=0; i < argcount; ++i) switch(argstring[i]) @@ -2060,6 +2137,16 @@ PyObject *eEPGCache::search(ePyObject arg) case 'E': case 'T': needServiceEvent=true; + break; + case 'N': + must_get_service_name = 1; + break; + case 'n': + must_get_service_name = 2; + break; + case 'R': + must_get_service_reference = true; + break; default: break; } @@ -2139,7 +2226,11 @@ PyObject *eEPGCache::search(ePyObject arg) { int casetype = PyLong_AsLong(PyTuple_GET_ITEM(arg, 4)); const char *str = PyString_AS_STRING(obj); +#if PY_VERSION_HEX < 0x02060000 int textlen = PyString_GET_SIZE(obj); +#else + int textlen = PyString_Size(obj); +#endif if (querytype == 1) eDebug("lookup for events with '%s' as title(%s)", str, casetype?"ignore case":"case sensitive"); else @@ -2154,22 +2245,32 @@ PyObject *eEPGCache::search(ePyObject arg) int title_len = data[5]; if ( querytype == 1 ) { - if (title_len > textlen) - continue; - else if (title_len < textlen) + int offs = 6; + // skip DVB-Text Encoding! + if (data[6] == 0x10) + { + offs+=3; + title_len-=3; + } + else if(data[6] > 0 && data[6] < 0x20) + { + offs+=1; + title_len-=1; + } + if (title_len != textlen) continue; if ( casetype ) { - if ( !strncasecmp((const char*)data+6, str, title_len) ) + if ( !strncasecmp((const char*)data+offs, str, title_len) ) { -// std::string s((const char*)data+6, title_len); +// std::string s((const char*)data+offs, title_len); // eDebug("match1 %s %s", str, s.c_str() ); descr[++descridx] = it->first; } } - else if ( !strncmp((const char*)data+6, str, title_len) ) + else if ( !strncmp((const char*)data+offs, str, title_len) ) { -// std::string s((const char*)data+6, title_len); +// std::string s((const char*)data+offs, title_len); // eDebug("match2 %s %s", str, s.c_str() ); descr[++descridx] = it->first; } @@ -2188,13 +2289,13 @@ PyObject *eEPGCache::search(ePyObject arg) // eDebug("match 3 %s %s", str, s.c_str() ); break; } - else if (!strncmp((const char*)data+6+idx, str, textlen) ) - { - descr[++descridx] = it->first; -// std::string s((const char*)data+6, title_len); -// eDebug("match 4 %s %s", str, s.c_str() ); - break; - } + } + else if (!strncmp((const char*)data+6+idx, str, textlen) ) + { + descr[++descridx] = it->first; +// std::string s((const char*)data+6, title_len); +// eDebug("match 4 %s %s", str, s.c_str() ); + break; } ++idx; } @@ -2298,44 +2399,40 @@ PyObject *eEPGCache::search(ePyObject arg) } } // create service name - if (!service_name) + if (must_get_service_name && !service_name) { - int must_get_service_name = strchr(argstring, 'N') ? 1 : strchr(argstring, 'n') ? 2 : 0; - if (must_get_service_name) + ePtr sptr; + eServiceCenterPtr service_center; + eServiceCenter::getPrivInstance(service_center); + if (service_center) { - ePtr sptr; - eServiceCenterPtr service_center; - eServiceCenter::getPrivInstance(service_center); - if (service_center) + service_center->info(ref, sptr); + if (sptr) { - service_center->info(ref, sptr); - if (sptr) - { - std::string name; - sptr->getName(ref, name); + std::string name; + sptr->getName(ref, name); - if (must_get_service_name == 1) - { - size_t 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 (must_get_service_name == 1) + { + size_t 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')) + if (must_get_service_reference && !service_reference) service_reference = PyString_FromString(ref.toString().c_str()); // create list if (!ret) @@ -2573,7 +2670,7 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey ¤t_service, const __ } } } - ASSERT(pdescr <= &descriptors[65]) + ASSERT(pdescr <= &descriptors[65]); __u8 event[4098]; eit_event_struct *ev_struct = (eit_event_struct*) event; ev_struct->running_status = 0; @@ -2716,6 +2813,7 @@ void eEPGCache::channel_data::timeMHW2DVB( int minutes, u_char *return_time) void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minutes, u_char *return_time) // For date plus time of day { + char tz_saved[1024]; // Remove offset in mhw time. __u8 local_hours = hours; if ( hours >= 16 ) @@ -2728,6 +2826,8 @@ void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minu time_t dt = ::time(0); char *old_tz = getenv( "TZ" ); + if (old_tz) + strcpy(tz_saved, old_tz); putenv("TZ=CET-1CEST,M3.5.0/2,M10.5.0/3"); tzset(); @@ -2750,7 +2850,7 @@ void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minu if ( old_tz == NULL ) unsetenv( "TZ" ); else - putenv( old_tz ); + setenv("TZ", tz_saved, 1); tzset(); // Calculate MJD according to annex in ETSI EN 300 468 @@ -2914,7 +3014,7 @@ void eEPGCache::channel_data::storeTitle(std::map<__u32, mhw_title_t>::iterator void eEPGCache::channel_data::startTimeout(int msec) { - m_MHWTimeoutTimer.start(msec,true); + m_MHWTimeoutTimer->start(msec,true); m_MHWTimeoutet=false; } @@ -2952,7 +3052,7 @@ void eEPGCache::channel_data::readMHWData(const __u8 *data) if ( state > 1 || // aborted // have si data.. so we dont read mhw data - (haveData & (SCHEDULE|SCHEDULE_OTHER)) ) + (haveData & (SCHEDULE|SCHEDULE_OTHER|VIASAT)) ) { eDebug("[EPGC] mhw aborted %d", state); } @@ -3118,7 +3218,7 @@ void eEPGCache::channel_data::readMHWData2(const __u8 *data) if ( state > 1 || // aborted // have si data.. so we dont read mhw data - (haveData & (eEPGCache::SCHEDULE|eEPGCache::SCHEDULE_OTHER)) ) + (haveData & (SCHEDULE|SCHEDULE_OTHER|VIASAT)) ) { eDebug("[EPGC] mhw2 aborted %d", state); }