more changes for service groups (replacement for zapping alternatives
[enigma2.git] / lib / dvb / epgcache.cpp
index 9c2849b..47da410 100644 (file)
@@ -21,6 +21,30 @@ 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<eDVBResourceManager> res;
+               if (!eDVBResourceManager::getInstance(res))
+               {
+                       ePtr<iDVBChannelList> db;
+                       if (!res->getChannelList(db))
+                       {
+                               eBouquet *bouquet=0;
+                               if (!db->getBouquet(ref, bouquet))
+                               {
+                                       std::list<eServiceReference>::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)
 {
@@ -1317,7 +1341,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 );
@@ -1393,7 +1417,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?
@@ -1450,7 +1474,7 @@ 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 );
+       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();
@@ -1474,7 +1498,7 @@ 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();
                return 0;
        }
@@ -1522,9 +1546,9 @@ RESULT eEPGCache::getNextTimeEntry(ePtr<eServiceEvent> &result)
        return -1;
 }
 
-void fillTuple(PyObject *tuple, char *argstring, int argcount, PyObject *service, ePtr<eServiceEvent> &ptr, PyObject *nowTime, PyObject *service_name )
+void fillTuple(ePyObject tuple, char *argstring, int argcount, ePyObject service, ePtr<eServiceEvent> &ptr, ePyObject nowTime, ePyObject service_name )
 {
-       PyObject *tmp=NULL;
+       ePyObject tmp;
        int pos=0;
        while(pos < argcount)
        {
@@ -1535,22 +1559,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;
@@ -1575,13 +1599,13 @@ void fillTuple(PyObject *tuple, char *argstring, int argcount, PyObject *service
        }
 }
 
-int handleEvent(ePtr<eServiceEvent> &ptr, PyObject *dest_list, char* argstring, int argcount, PyObject *service, PyObject *nowTime, PyObject *service_name, PyObject *convertFunc, PyObject *convertFuncArgs)
+int handleEvent(ePtr<eServiceEvent> &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);
@@ -1599,7 +1623,7 @@ int handleEvent(ePtr<eServiceEvent> &ptr, PyObject *dest_list, char* argstring,
        }
        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);
@@ -1631,9 +1655,9 @@ int handleEvent(ePtr<eServiceEvent> &ptr, PyObject *dest_list, char* argstring,
 //      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))
@@ -1654,7 +1678,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);
@@ -1677,17 +1701,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;
 
        // 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;
@@ -1697,10 +1721,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:
@@ -1732,7 +1756,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");
@@ -1756,7 +1780,7 @@ PyObject *eEPGCache::lookupEvent(PyObject *list, PyObject *convertFunc)
                                }
                        }
 
-                       PyObject *service_name=NULL;
+                       ePyObject service_name;
                        if (must_get_service_name)
                        {
                                ePtr<iStaticServiceInformation> sptr;
@@ -1821,9 +1845,9 @@ skip_entry:
        return dest_list;
 }
 
-void fillTuple2(PyObject *tuple, const char *argstring, int argcount, eventData *evData, ePtr<eServiceEvent> &ptr, PyObject *service_name, PyObject *service_reference)
+void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData *evData, ePtr<eServiceEvent> &ptr, ePyObject service_name, ePyObject service_reference)
 {
-       PyObject *tmp=NULL;
+       ePyObject tmp;
        int pos=0;
        while(pos < argcount)
        {
@@ -1838,24 +1862,24 @@ 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;
@@ -1901,9 +1925,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;
@@ -1919,7 +1943,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);
@@ -1950,7 +1974,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);
@@ -2007,7 +2031,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));
@@ -2110,7 +2134,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;
@@ -2124,8 +2148,8 @@ 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)
@@ -2191,7 +2215,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);