+ if (cab_name)
+ {
+ ePyObject tplist = PyList_New(0);
+ ePyObject tuple = PyTuple_New(2);
+ if (!cab_flags)
+ cab_flags = PyInt_FromLong(0);
+ PyTuple_SET_ITEM(tuple, 0, cab_name);
+ PyTuple_SET_ITEM(tuple, 1, cab_flags);
+ PyList_Append(cab_list, tuple);
+ Py_DECREF(tuple);
+ PyDict_SetItem(tp_dict, cab_name, tplist);
+ for (ElementConstIterator it(cab_elements.begin()); it != cab_elements.end(); ++it)
+ {
+// eDebug("\telement: %s", (*it)->name().c_str());
+ const AttributeList &tp_attributes = (*it)->getAttributeList();
+ AttributeConstIterator end = tp_attributes.end();
+ modulation = eDVBFrontendParametersCable::Modulation_QAM64;
+ fec = eDVBFrontendParametersCable::FEC_Auto;
+ freq = 0;
+ sr = 0;
+ for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it)
+ {
+// eDebug("\t\tattr: %s", at->name().c_str());
+ at = *it;
+ dest = 0;
+ name = at->name();
+ if (name == "modulation") dest = &modulation;
+ else if (name == "frequency") dest = &freq;
+ else if (name == "symbol_rate") dest = &sr;
+ else if (name == "fec_inner") dest = &fec;
+ else continue;
+ if (dest)
+ {
+ tmp = strtol(at->value().c_str(), &end_ptr, 10);
+ if (!*end_ptr)
+ *dest = tmp;
+ }
+ }
+ if (freq && sr)
+ {
+ while (freq > 999999)
+ freq /= 10;
+ tuple = PyTuple_New(5);
+ PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(1));
+ PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq));
+ PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(sr));
+ PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(modulation));
+ PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(fec));
+ PyList_Append(tplist, tuple);
+ Py_DECREF(tuple);
+ }
+ }
+ Py_DECREF(tplist);
+ }
+ else if (cab_flags)
+ Py_DECREF(cab_flags);
+ }
+ Py_INCREF(Py_True);
+ return Py_True;
+}
+
+PyObject *eDVBDB::readTerrestrials(ePyObject ter_list, ePyObject tp_dict)
+{
+ if (!PyDict_Check(tp_dict)) {
+ PyErr_SetString(PyExc_StandardError,
+ "type error");
+ eDebug("arg 1 is not a python dict");
+ return NULL;
+ }
+ else if (!PyList_Check(ter_list))
+ {
+ PyErr_SetString(PyExc_StandardError,
+ "type error");
+ eDebug("arg 0 is not a python list");
+ return NULL;
+ }
+ XMLTree tree;
+ tree.setFilename("/etc/tuxbox/terrestrial.xml");
+ tree.read();
+ Element *root = tree.getRoot();
+ if (!root)
+ {
+ eDebug("couldn't open /etc/tuxbox/terrestrial.xml!!");
+ Py_INCREF(Py_False);
+ return Py_False;
+ }
+ const Attribute *at;
+ std::string name;
+ int tmp, *dest,
+ freq, bw, constellation, crh = 5, crl = 5, guard = 4, transm, hierarchy, inv = 2;
+ char *end_ptr;
+ const ElementList &root_elements = root->getElementList();
+ for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it)
+ {
+// eDebug("element: %s", el->name().c_str());
+ const Element *el = *it;
+ const ElementList &ter_elements = el->getElementList();
+ const AttributeList &ter_attributes = el->getAttributeList();
+ ePyObject ter_name;
+ ePyObject ter_flags;
+ for (AttributeConstIterator it(ter_attributes.begin()); it != ter_attributes.end(); ++it)
+ {
+// eDebug("\tattr: %s", at->name().c_str());
+ at = *it;
+ name = at->name();
+ if (name == "name")
+ ter_name = PyString_FromString(at->value().c_str());
+ else if (name == "flags")
+ {
+ tmp = strtol(at->value().c_str(), &end_ptr, 10);
+ if (!*end_ptr)
+ ter_flags = PyInt_FromLong(tmp);
+ }
+ }
+ if (ter_name)
+ {
+ ePyObject tplist = PyList_New(0);
+ ePyObject tuple = PyTuple_New(2);
+ if (!ter_flags)
+ ter_flags = PyInt_FromLong(0);
+ PyTuple_SET_ITEM(tuple, 0, ter_name);
+ PyTuple_SET_ITEM(tuple, 1, ter_flags);
+ PyList_Append(ter_list, tuple);
+ Py_DECREF(tuple);
+ PyDict_SetItem(tp_dict, ter_name, tplist);
+ for (ElementConstIterator it(ter_elements.begin()); it != ter_elements.end(); ++it)
+ {
+// eDebug("\telement: %s", (*it)->name().c_str());
+ const AttributeList &tp_attributes = (*it)->getAttributeList();
+ AttributeConstIterator end = tp_attributes.end();
+ freq = 0;
+ bw = eDVBFrontendParametersTerrestrial::Bandwidth_Auto;
+ constellation = eDVBFrontendParametersTerrestrial::Modulation_Auto;
+ crh = eDVBFrontendParametersTerrestrial::FEC_Auto;
+ crl = eDVBFrontendParametersTerrestrial::FEC_Auto;
+ guard = eDVBFrontendParametersTerrestrial::GuardInterval_Auto;
+ transm = eDVBFrontendParametersTerrestrial::TransmissionMode_Auto;
+ hierarchy = eDVBFrontendParametersTerrestrial::Hierarchy_Auto;
+ inv = eDVBFrontendParametersTerrestrial::Inversion_Unknown;
+ for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it)
+ {
+// eDebug("\t\tattr: %s", at->name().c_str());
+ at = *it;
+ dest = 0;
+ name = at->name();
+ if (name == "centre_frequency") dest = &freq;
+ else if (name == "bandwidth") dest = &bw;
+ else if (name == "constellation") dest = &constellation;
+ else if (name == "code_rate_hp") dest = &crh;
+ else if (name == "code_rate_lp") dest = &crl;
+ else if (name == "guard_interval") dest = &guard;
+ else if (name == "transmission_mode") dest = &transm;
+ else if (name == "hierarchy_information") dest = &hierarchy;
+ else if (name == "inversion") dest = &inv;
+ else continue;
+ if (dest)
+ {
+ tmp = strtol(at->value().c_str(), &end_ptr, 10);
+ if (!*end_ptr)
+ *dest = tmp;
+ }
+ }
+ if (freq)
+ {
+ if (crh > 5) // our terrestrial.xml is buggy... 6 for AUTO
+ crh = 5;
+ if (crl > 5) // our terrestrial.xml is buggy... 6 for AUTO
+ crl = 5;
+ tuple = PyTuple_New(10);
+ PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(2));
+ PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq));
+ PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(bw));
+ PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(constellation));
+ PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(crh));
+ PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong(crl));
+ PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(guard));
+ PyTuple_SET_ITEM(tuple, 7, PyInt_FromLong(transm));
+ PyTuple_SET_ITEM(tuple, 8, PyInt_FromLong(hierarchy));
+ PyTuple_SET_ITEM(tuple, 9, PyInt_FromLong(inv));
+ PyList_Append(tplist, tuple);
+ Py_DECREF(tuple);
+ }
+ }
+ Py_DECREF(tplist);
+ }
+ else if (ter_flags)
+ Py_DECREF(ter_flags);
+ }
+ Py_INCREF(Py_True);
+ return Py_True;
+}
+
+eDVBDB::~eDVBDB()
+{
+ instance=NULL;
+}
+
+RESULT eDVBDB::removeService(const eServiceReference &ref)
+{
+ if (ref.type == eServiceReference::idDVB)
+ {
+ eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
+ std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
+ if (it != m_services.end())
+ {
+ m_services.erase(it);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+RESULT eDVBDB::removeServices(int dvb_namespace, int tsid, int onid, unsigned int orb_pos)
+{
+ return removeServices(eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos);
+}
+
+RESULT eDVBDB::removeServices(eDVBChannelID chid, unsigned int orbpos)
+{
+ RESULT ret=-1;
+ eDVBNamespace eNs;
+ eTransportStreamID eTsid;
+ eOriginalNetworkID eOnid;
+ std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
+ std::set<eDVBChannelID> removed_chids;
+ while (it != m_channels.end())
+ {
+ const eDVBChannelID &ch = it->first;
+ bool remove=true;
+ int system;
+ it->second.m_frontendParameters->getSystem(system);
+ if ( system == iDVBFrontend::feSatellite )
+ {
+ eDVBFrontendParametersSatellite sat;
+ it->second.m_frontendParameters->getDVBS(sat);
+ if ((unsigned int)sat.orbital_position != orbpos)
+ remove=false;
+ }
+ if ( remove && chid.dvbnamespace != eNs ) // namespace given?
+ {
+ if ( system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000 )
+ ;
+ else if ( system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000 )
+ ;
+ else if ( chid.dvbnamespace != ch.dvbnamespace )
+ remove=false;
+ }
+ else if ( system == iDVBFrontend::feCable || system == iDVBFrontend::feTerrestrial )
+ remove=false;
+ if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id )
+ remove=false;
+ if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id )
+ remove=false;
+ if ( remove )
+ {
+ eDebug("remove %08x %04x %04x",
+ ch.dvbnamespace.get(),
+ ch.original_network_id.get(),
+ ch.transport_stream_id.get());
+ removed_chids.insert(it->first);
+ m_channels.erase(it++);
+ }
+ else
+ ++it;
+ }
+ if (!removed_chids.empty())
+ {
+ std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
+ while(service != m_services.end())
+ {
+ eDVBChannelID chid;
+ service->first.getChannelID(chid);
+ std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
+ if (it != removed_chids.end())
+ m_services.erase(service++);
+ else
+ ++service;
+ ret=0;
+ }
+ }
+ return ret;
+}
+
+RESULT eDVBDB::removeServices(iDVBFrontendParameters *feparm)
+{
+ int ret = -1;
+ std::set<eDVBChannelID> removed_chids;
+ std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
+ while (it != m_channels.end())
+ {
+ int diff;
+ if (!feparm->calculateDifference(&(*it->second.m_frontendParameters), diff, false))
+ {
+ if (diff < 4000)
+ {
+ removed_chids.insert(it->first);
+ m_channels.erase(it++);
+ }
+ else
+ ++it;
+ }
+ else
+ ++it;
+ }
+ if (!removed_chids.empty())
+ {
+ std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
+ while(service != m_services.end())
+ {
+ eDVBChannelID chid;
+ service->first.getChannelID(chid);
+ std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
+ if (it != removed_chids.end())
+ m_services.erase(service++);
+ else
+ ++service;
+ }
+ ret = 0;
+ }
+ return ret;
+}
+
+RESULT eDVBDB::addFlag(const eServiceReference &ref, unsigned int flagmask)
+{
+ if (ref.type == eServiceReference::idDVB)
+ {
+ eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
+ std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
+ if (it != m_services.end())
+ it->second->m_flags |= ~flagmask;
+ return 0;
+ }
+ return -1;
+}
+
+RESULT eDVBDB::removeFlag(const eServiceReference &ref, unsigned int flagmask)
+{
+ if (ref.type == eServiceReference::idDVB)
+ {
+ eServiceReferenceDVB &service = (eServiceReferenceDVB&)ref;
+ std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(service));
+ if (it != m_services.end())
+ it->second->m_flags &= ~flagmask;
+ return 0;
+ }
+ return -1;
+}
+
+RESULT eDVBDB::removeFlags(unsigned int flagmask, int dvb_namespace, int tsid, int onid, unsigned int orb_pos)
+{
+ return removeFlags(flagmask, eDVBChannelID(eDVBNamespace(dvb_namespace), eTransportStreamID(tsid), eOriginalNetworkID(onid)), orb_pos);
+}
+
+RESULT eDVBDB::removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned int orbpos)
+{
+ eDVBNamespace eNs;
+ eTransportStreamID eTsid;
+ eOriginalNetworkID eOnid;
+ std::map<eDVBChannelID, channel>::iterator it(m_channels.begin());
+ std::set<eDVBChannelID> removed_chids;
+ while (it != m_channels.end())
+ {
+ const eDVBChannelID &ch = it->first;
+ bool remove=true;
+ int system;
+ it->second.m_frontendParameters->getSystem(system);
+ if ( orbpos != 0xFFFFFFFF && system == iDVBFrontend::feSatellite )
+ {
+ eDVBFrontendParametersSatellite sat;
+ it->second.m_frontendParameters->getDVBS(sat);
+ if ((unsigned int)sat.orbital_position != orbpos)
+ remove=false;
+ }
+ if ( remove && chid.dvbnamespace != eNs )
+ {
+ if (system == iDVBFrontend::feCable && chid.dvbnamespace.get() == (int)0xFFFF0000)
+ ;
+ else if (system == iDVBFrontend::feTerrestrial && chid.dvbnamespace.get() == (int)0xEEEE0000)
+ ;
+ else if ( chid.dvbnamespace != ch.dvbnamespace )
+ remove=false;
+ }
+ if ( remove && chid.original_network_id != eOnid && chid.original_network_id != ch.original_network_id )
+ remove=false;
+ if ( remove && chid.transport_stream_id != eTsid && chid.transport_stream_id != ch.transport_stream_id )
+ remove=false;
+ if ( remove )
+ removed_chids.insert(it->first);
+ ++it;
+ }
+ if (!removed_chids.empty())
+ {
+ std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator service(m_services.begin());
+ while(service != m_services.end())
+ {
+ eDVBChannelID chid;
+ service->first.getChannelID(chid);
+ std::set<eDVBChannelID>::iterator it(removed_chids.find(chid));
+ if (it != removed_chids.end())
+ service->second->m_flags &= ~flagmask;
+ ++service;
+ }
+ }
+ return 0;
+}
+
+RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm)
+{
+ channel ch;
+ std::map<eDVBChannelID, channel>::iterator it = m_channels.find(id);
+ ASSERT(feparm);
+ ch.m_frontendParameters = feparm;
+ if (it != m_channels.end())
+ it->second = ch;
+ else
+ m_channels.insert(std::pair<eDVBChannelID, channel>(id, ch));
+ return 0;
+}
+
+RESULT eDVBDB::removeChannel(const eDVBChannelID &id)
+{
+ m_channels.erase(id);
+ return 0;
+}
+
+RESULT eDVBDB::getChannelFrontendData(const eDVBChannelID &id, ePtr<iDVBFrontendParameters> &parm)
+{
+ std::map<eDVBChannelID, channel>::iterator i = m_channels.find(id);
+ if (i == m_channels.end())
+ {
+ parm = 0;
+ return -ENOENT;
+ }
+ parm = i->second.m_frontendParameters;
+ return 0;
+}
+
+RESULT eDVBDB::addService(const eServiceReferenceDVB &serviceref, eDVBService *service)
+{
+ std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_services.find(serviceref));
+ if (it == m_services.end())
+ m_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(serviceref, service));
+ return 0;
+}
+
+RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service)
+{
+ std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator i;
+ i = m_services.find(reference);
+ if (i == m_services.end())
+ {
+ service = 0;
+ return -ENOENT;
+ }
+ service = i->second;
+ return 0;
+}
+
+RESULT eDVBDB::flush()
+{
+ saveServicelist();
+ return 0;
+}
+
+RESULT eDVBDB::getBouquet(const eServiceReference &ref, eBouquet* &bouquet)
+{
+ std::string str = ref.path;
+ if (str.empty())
+ {
+ eDebug("getBouquet failed.. no path given!");
+ return -1;
+ }
+ size_t pos = str.find("FROM BOUQUET \"");
+ if ( pos != std::string::npos )
+ {
+ str.erase(0, pos+14);
+ pos = str.find('"');
+ if ( pos != std::string::npos )
+ str.erase(pos);
+ else
+ str.clear();
+ }
+ if (str.empty())
+ {
+ eDebug("getBouquet failed.. couldn't parse bouquet name");
+ return -1;
+ }
+ std::map<std::string, eBouquet>::iterator i =
+ m_bouquets.find(str);
+ if (i == m_bouquets.end())
+ {
+ bouquet = 0;
+ return -ENOENT;
+ }
+ bouquet = &i->second;
+ return 0;
+}
+
+RESULT eDVBDB::startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *q, const eServiceReference &source)
+{
+ if ( source.path.find("FROM") != std::string::npos )
+ {
+ if ( source.path.find("BOUQUET") != std::string::npos )
+ query = new eDVBDBBouquetQuery(this, source, q);
+ else if ( source.path.find("SATELLITES") != std::string::npos )
+ query = new eDVBDBSatellitesQuery(this, source, q);
+ else if ( source.path.find("PROVIDERS") != std::string::npos )
+ query = new eDVBDBProvidersQuery(this, source, q);
+ else
+ eFatal("invalid query %s", source.toString().c_str());
+ }
+ else
+ query = new eDVBDBQuery(this, source, q);
+ return 0;
+}
+
+eServiceReference eDVBDB::searchReference(int tsid, int onid, int sid)
+{
+ eServiceID Sid(sid);
+ eTransportStreamID Tsid(tsid);
+ eOriginalNetworkID Onid(onid);
+ for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator sit(m_services.begin());
+ sit != m_services.end(); ++sit)
+ {
+ if (sit->first.getTransportStreamID() == Tsid &&
+ sit->first.getOriginalNetworkID() == Onid &&
+ sit->first.getServiceID() == Sid)
+ return sit->first;
+ }
+ return eServiceReference();
+}
+
+DEFINE_REF(eDVBDBQueryBase);
+
+eDVBDBQueryBase::eDVBDBQueryBase(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
+ :m_db(db), m_query(query), m_source(source)
+{
+}
+
+int eDVBDBQueryBase::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)
+{
+ ePtr<eDVBService> a_service, b_service;
+ int sortmode = m_query ? m_query->m_sort : eDVBChannelQuery::tName;
+
+ if ((sortmode == eDVBChannelQuery::tName) || (sortmode == eDVBChannelQuery::tProvider))
+ {
+ if (a.name.empty() && m_db->getService(a, a_service))
+ return 1;
+ if (b.name.empty() && m_db->getService(b, b_service))