move dvb-t 5V antenna switching to better place
[enigma2.git] / lib / dvb / epgcache.cpp
index eb031be3dda3d971ce23fcf63c29bd89a3f95e5a..7c64fb0cac05c497b5bd6fb5950b65f20a84f87e 100644 (file)
@@ -177,12 +177,11 @@ eEPGCache::eEPGCache()
 
 void eEPGCache::timeUpdated()
 {
-       if ( !thread_running() )
+       if (!sync())
        {
                eDebug("[EPGC] time updated.. start EPG Mainloop");
                run();
-       }
-       else
+       } else
                messages.send(Message(Message::timeChanged));
 }
 
@@ -672,9 +671,18 @@ void eEPGCache::gotMessage( const Message &msg )
                                        chid.original_network_id.get() == msg.service.onid &&
                                        data->m_PrivatePid == -1 )
                                {
+                                       data->m_PrevVersion = -1;
                                        data->m_PrivatePid = msg.pid;
                                        data->m_PrivateService = msg.service;
-                                       data->startPrivateReader(msg.pid, -1);
+                                       updateMap::iterator It = channelLastUpdated.find( channel->getChannelID() );
+                                       int update = ( It != channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (time(0)+eDVBLocalTimeHandler::getInstance()->difference()-It->second) * 1000 ) ) : ZAP_DELAY );
+                                       if (update < ZAP_DELAY)
+                                               update = ZAP_DELAY;
+                                       data->startPrivateTimer.start(update, 1);
+                                       if (update >= 60000)
+                                               eDebug("[EPGC] next private update in %i min", update/60000);
+                                       else if (update >= 1000)
+                                               eDebug("[EPGC] next private update in %i sec", update/1000);
                                        break;
                                }
                        }
@@ -692,6 +700,7 @@ void eEPGCache::gotMessage( const Message &msg )
 
 void eEPGCache::thread()
 {
+       hasStarted();
        nice(4);
        load();
        cleanLoop();
@@ -899,18 +908,19 @@ void eEPGCache::save()
 
 eEPGCache::channel_data::channel_data(eEPGCache *ml)
        :cache(ml)
-       ,abortTimer(ml), zapTimer(ml)
+       ,abortTimer(ml), zapTimer(ml), startPrivateTimer(ml)
        ,state(0), isRunning(0), haveData(0), can_delete(1)
 {
        CONNECT(zapTimer.timeout, eEPGCache::channel_data::startEPG);
        CONNECT(abortTimer.timeout, eEPGCache::channel_data::abortNonAvail);
+       CONNECT(startPrivateTimer.timeout, eEPGCache::channel_data::startPrivateReader);
 }
 
 bool eEPGCache::channel_data::finishEPG()
 {
        if (!isRunning)  // epg ready
        {
-               eDebug("[EPGC] stop caching events(%d)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
+               eDebug("[EPGC] stop caching events(%ld)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
                zapTimer.start(UPDATE_INTERVAL, 1);
                eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000);
                for (int i=0; i < 3; ++i)
@@ -931,7 +941,7 @@ bool eEPGCache::channel_data::finishEPG()
 
 void eEPGCache::channel_data::startEPG()
 {
-       eDebug("[EPGC] start caching events(%d)", eDVBLocalTimeHandler::getInstance()->difference()+time(0));
+       eDebug("[EPGC] start caching events(%ld)", eDVBLocalTimeHandler::getInstance()->difference()+time(0));
        state=0;
        haveData=0;
        can_delete=0;
@@ -1118,7 +1128,7 @@ void eEPGCache::channel_data::readData( const __u8 *data)
                                        break;
                                default: eDebugNoNewLine("unknown");break;
                        }
-                       eDebug(" finished(%d)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
+                       eDebug(" finished(%ld)", time(0)+eDVBLocalTimeHandler::getInstance()->difference());
                        if ( reader )
                                reader->stop();
                        isRunning &= ~source;
@@ -1532,6 +1542,7 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc)
                PyObject *item=PyList_GET_ITEM(list, listIt++); // borrowed reference!
                if (PyTuple_Check(item))
                {
+                       bool service_changed=false;
                        int type=0;
                        long event_id=-1;
                        time_t stime=-1;
@@ -1579,6 +1590,24 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc)
                                eDebug("service reference for epg query is not valid");
                                continue;
                        }
+
+                       // redirect subservice querys to parent service
+                       eServiceReferenceDVB &dvb_ref = (eServiceReferenceDVB&)ref;
+                       if (dvb_ref.getParentTransportStreamID().get()) // linkage subservice
+                       {
+                               eServiceCenterPtr service_center;
+                               if (!eServiceCenter::getPrivInstance(service_center))
+                               {
+                                       dvb_ref.setTransportStreamID( dvb_ref.getParentTransportStreamID() );
+                                       dvb_ref.setServiceID( dvb_ref.getParentServiceID() );
+                                       dvb_ref.setParentTransportStreamID(eTransportStreamID(0));
+                                       dvb_ref.setParentServiceID(eServiceID(0));
+                                       dvb_ref.name="";
+                                       service = PyString_FromString(dvb_ref.toString().c_str());
+                                       service_changed = true;
+                               }
+                       }
+
                        PyObject *service_name=NULL;
                        if (must_get_service_name)
                        {
@@ -1628,6 +1657,8 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc)
                                if (ret)
                                        return ret;
                        }
+                       if (service_changed)
+                               Py_DECREF(service);
                        if (service_name)
                                Py_DECREF(service_name);
                }
@@ -1946,16 +1977,16 @@ PyObject *eEPGCache::search(PyObject *arg)
                        }
                        PyObject *service_name=0;
                        PyObject *service_reference=0;
-                       eventMap &evmap = cit->second.first;
+                       timeMap &evmap = cit->second.second;
                        // check all events
-                       for (eventMap::iterator evit(evmap.begin()); evit != evmap.end() && maxcount; ++evit)
+                       for (timeMap::iterator evit(evmap.begin()); evit != evmap.end() && maxcount; ++evit)
                        {
+                               if (evit->second->getEventID() == eventid)
+                                       continue;
                                __u8 *data = evit->second->EITdata;
                                int tmp = evit->second->ByteSize-12;
                                __u32 *p = (__u32*)(data+12);
                                // check if any of our descriptor used by this event
-                               if (evit->first == eventid )
-                                       continue;
                                int cnt=-1;
                                while(tmp>0)
                                {
@@ -2097,7 +2128,7 @@ void eEPGCache::PMTready(eDVBServicePMTHandler *pmthandler)
                                if (tmp==3)
                                {
                                        eServiceReferenceDVB ref;
-                                       if (!pmthandler->getService(ref))
+                                       if (!pmthandler->getServiceReference(ref))
                                        {
                                                int pid = (*es)->getPid();
                                                messages.send(Message(Message::got_private_pid, ref, pid));
@@ -2195,6 +2226,14 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey &current_service, const __
                        onid |= data[ptr++];
                        int sid = data[ptr++] << 8;
                        sid |= data[ptr++];
+
+// WORKAROUND for wrong transmitted epg data
+                       if ( onid == 0x85 && tsid == 0x11 && sid == 0xd3 )  // premiere sends wrong tsid here
+                               tsid = 0x1;
+                       else if ( onid == 0x85 && tsid == 0x3 && sid == 0xf5 ) // premiere sends wrong sid here
+                               sid = 0xdc;
+////////////////////////////////////////////
+                               
                        uniqueEPGKey service( sid, onid, tsid );
                        descr_len -= 6;
                        while( descr_len > 0 )
@@ -2276,27 +2315,24 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey &current_service, const __
        }
 }
 
-void eEPGCache::channel_data::startPrivateReader(int pid, int version)
+void eEPGCache::channel_data::startPrivateReader()
 {
        eDVBSectionFilterMask mask;
        memset(&mask, 0, sizeof(mask));
-       mask.pid = pid;
+       mask.pid = m_PrivatePid;
        mask.flags = eDVBSectionFilterMask::rfCRC;
        mask.data[0] = 0xA0;
        mask.mask[0] = 0xFF;
-       eDebug("start privatefilter for pid %04x and version %d", pid, version);
-       if (version != -1)
+       eDebug("start privatefilter for pid %04x and version %d", m_PrivatePid, m_PrevVersion);
+       if (m_PrevVersion != -1)
        {
-               mask.data[3] = version << 1;
+               mask.data[3] = m_PrevVersion << 1;
                mask.mask[3] = 0x3E;
                mask.mode[3] = 0x3E;
        }
        seenPrivateSections.clear();
        m_PrivateReader->connectRead(slot(*this, &eEPGCache::channel_data::readPrivateData), m_PrivateConn);
        m_PrivateReader->start(mask);
-#ifdef NEED_DEMUX_WORKAROUND
-       m_PrevVersion=version;
-#endif
 }
 
 void eEPGCache::channel_data::readPrivateData( const __u8 *data)
@@ -2329,9 +2365,8 @@ void eEPGCache::channel_data::readPrivateData( const __u8 *data)
                        eDebug("[EPGC] private finished");
                        if (!isRunning)
                                can_delete = 1;
-                       int version = data[5];
-                       version = ((version & 0x3E) >> 1);
-                       startPrivateReader(m_PrivatePid, version);
+                       m_PrevVersion = (data[5] & 0x3E) >> 1;
+                       startPrivateReader();
                }
        }
 }