+ __u32 crc = *p++;
+ descriptorMap::iterator it =
+ eventData::descriptors.find(crc);
+ if (it != eventData::descriptors.end())
+ {
+ __u8 *descr_data = it->second.second;
+ switch(descr_data[0])
+ {
+ case 0x4D ... 0x4E:
+ descr[++descridx]=crc;
+ default:
+ break;
+ }
+ }
+ tmp-=4;
+ }
+ }
+ if (descridx<0)
+ eDebug("event not found");
+ }
+ else
+ {
+ 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");
+ eDebug("tuple arg 4 is not a string");
+ return NULL;
+ }
+ }
+ else if (tuplesize > 4 && (querytype == 1 || querytype == 2) )
+ {
+ ePyObject obj = PyTuple_GET_ITEM(arg, 3);
+ if (PyString_Check(obj))
+ {
+ int casetype = PyLong_AsLong(PyTuple_GET_ITEM(arg, 4));
+ const char *str = PyString_AS_STRING(obj);
+ int textlen = PyString_GET_SIZE(obj);
+ if (querytype == 1)
+ eDebug("lookup for events with '%s' as title(%s)", str, casetype?"ignore case":"case sensitive");
+ else
+ eDebug("lookup for events with '%s' in title(%s)", str, casetype?"ignore case":"case sensitive");
+ singleLock s(cache_lock);
+ for (descriptorMap::iterator it(eventData::descriptors.begin());
+ it != eventData::descriptors.end() && descridx < 511; ++it)
+ {
+ __u8 *data = it->second.second;
+ if ( data[0] == 0x4D ) // short event descriptor
+ {
+ int title_len = data[5];
+ if ( querytype == 1 )
+ {
+ if (title_len > textlen)
+ continue;
+ else if (title_len < textlen)
+ continue;
+ if ( casetype )
+ {
+ if ( !strncasecmp((const char*)data+6, str, title_len) )
+ {
+// std::string s((const char*)data+6, title_len);
+// eDebug("match1 %s %s", str, s.c_str() );
+ descr[++descridx] = it->first;
+ }
+ }
+ else if ( !strncmp((const char*)data+6, str, title_len) )
+ {
+// std::string s((const char*)data+6, title_len);
+// eDebug("match2 %s %s", str, s.c_str() );
+ descr[++descridx] = it->first;
+ }
+ }
+ else
+ {
+ int idx=0;
+ while((title_len-idx) >= textlen)
+ {
+ if (casetype)
+ {
+ if (!strncasecmp((const char*)data+6+idx, str, textlen) )
+ {
+ descr[++descridx] = it->first;
+// std::string s((const char*)data+6, title_len);
+// 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;
+ }
+ }
+ ++idx;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ PyErr_SetString(PyExc_StandardError,
+ "type error");
+ eDebug("tuple arg 4 is not a string");
+ return NULL;
+ }
+ }
+ else
+ {
+ PyErr_SetString(PyExc_StandardError,
+ "type error");
+ eDebug("tuple arg 3(%d) is not a known querytype(0, 1, 2)", querytype);
+ return NULL;
+ }
+ }
+ else
+ {
+ PyErr_SetString(PyExc_StandardError,
+ "type error");
+ eDebug("not enough args in tuple");
+ return NULL;
+ }
+ }
+ else
+ {
+ PyErr_SetString(PyExc_StandardError,
+ "type error");
+ eDebug("arg 0 is not a tuple");
+ return NULL;
+ }
+
+ if (descridx > -1)
+ {
+ int maxcount=maxmatches;
+ 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;
+ singleLock s(cache_lock);
+ eventCache::iterator cit(ref.valid() ? eventDB.find(ref) : eventDB.begin());
+ while(cit != eventDB.end() && maxcount)
+ {
+ if ( ref.valid() && !first && cit->first == ref )
+ {
+ // do not scan base service twice ( only in SIMILAR BROADCASTING SEARCH )
+ ++cit;
+ continue;
+ }
+ 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)
+ {
+ int evid = evit->second->getEventID();
+ if ( evid == eventid)
+ continue;
+ __u8 *data = evit->second->EITdata;
+ 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>3)
+ {
+ __u32 crc32 = *p++;
+ for ( int i=0; i <= descridx; ++i)
+ {
+ if (descr[i] == crc32) // found...
+ ++cnt;
+ }
+ tmp-=4;
+ }
+ if ( (querytype == 0 && cnt == descridx) ||
+ ((querytype == 1 || querytype == 2) && cnt != -1) )
+ {
+ const uniqueEPGKey &service = cit->first;
+ eServiceReference ref =
+ eDVBDB::getInstance()->searchReference(service.tsid, service.onid, service.sid);
+ if (ref.valid())
+ {
+ // create servive event
+ eServiceEvent ptr;
+ const eventData *ev_data=0;
+ if (needServiceEvent)
+ {
+ 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)
+ {
+ int must_get_service_name = strchr(argstring, 'N') ? 1 : strchr(argstring, 'n') ? 2 : 0;
+ if (must_get_service_name)
+ {
+ ePtr<iStaticServiceInformation> sptr;
+ eServiceCenterPtr service_center;
+ eServiceCenter::getPrivInstance(service_center);
+ if (service_center)
+ {
+ service_center->info(ref, sptr);
+ if (sptr)
+ {
+ 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 (!service_name)
+ service_name = PyString_FromString("<n/a>");
+ }
+ }
+ // create servicereference string
+ if (!service_reference && strchr(argstring,'R'))
+ service_reference = PyString_FromString(ref.toString().c_str());
+ // create list
+ if (!ret)
+ ret = PyList_New(0);
+ // create tuple
+ ePyObject tuple = PyTuple_New(argcount);
+ // fill tuple
+ fillTuple2(tuple, argstring, argcount, evit->second, ev_data ? &ptr : 0, service_name, service_reference);
+ PyList_Append(ret, tuple);
+ Py_DECREF(tuple);
+ --maxcount;
+ }
+ }
+ }
+ if (service_name)
+ Py_DECREF(service_name);
+ if (service_reference)
+ Py_DECREF(service_reference);
+ if (first)
+ {
+ // now start at first service in epgcache database ( only in SIMILAR BROADCASTING SEARCH )
+ first=false;
+ cit=eventDB.begin();
+ }
+ else
+ ++cit;
+ }
+ }
+
+ if (!ret)
+ Py_RETURN_NONE;
+
+ return ret;
+}
+
+#ifdef ENABLE_PRIVATE_EPG
+#include <dvbsi++/descriptor_tag.h>
+#include <dvbsi++/unknown_descriptor.h>
+#include <dvbsi++/private_data_specifier_descriptor.h>
+
+void eEPGCache::PMTready(eDVBServicePMTHandler *pmthandler)
+{
+ ePtr<eTable<ProgramMapSection> > ptr;
+ if (!pmthandler->getPMT(ptr) && ptr)
+ {
+ std::vector<ProgramMapSection*>::const_iterator i;
+ for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i)
+ {
+ const ProgramMapSection &pmt = **i;
+
+ ElementaryStreamInfoConstIterator es;
+ for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
+ {
+ int tmp=0;
+ switch ((*es)->getType())
+ {
+ case 0x05: // private
+ for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
+ desc != (*es)->getDescriptors()->end(); ++desc)
+ {
+ switch ((*desc)->getTag())
+ {
+ case PRIVATE_DATA_SPECIFIER_DESCRIPTOR:
+ if (((PrivateDataSpecifierDescriptor*)(*desc))->getPrivateDataSpecifier() == 190)
+ tmp |= 1;
+ break;
+ case 0x90:
+ {
+ UnknownDescriptor *descr = (UnknownDescriptor*)*desc;