+ else if (!PyList_Check(sat_list))
+ {
+ PyErr_SetString(PyExc_StandardError,
+ "type error");
+ eDebug("arg 0 is not a python list");
+ return NULL;
+ }
+ XMLTree tree;
+ tree.setFilename("/etc/tuxbox/satellites.xml");
+ tree.read();
+ Element *root = tree.getRoot();
+ if (!root)
+ {
+ eDebug("couldn't open /etc/tuxbox/satellites.xml!!");
+ Py_INCREF(Py_False);
+ return Py_False;
+ }
+ int tmp, *dest = NULL,
+ modulation, system, freq, sr, pol, fec, inv, pilot, rolloff, tsid, onid;
+ char *end_ptr;
+ const Attribute *at;
+ std::string name;
+ const ElementList &root_elements = root->getElementList();
+ for (ElementConstIterator it(root_elements.begin()); it != root_elements.end(); ++it)
+ {
+// eDebug("element: %s", (*it)->name().c_str());
+ const Element *el = *it;
+ const ElementList &sat_elements = el->getElementList();
+ const AttributeList &sat_attributes = el->getAttributeList();
+ ePyObject sat_name;
+ ePyObject sat_pos;
+ ePyObject sat_flags;
+ for (AttributeConstIterator it(sat_attributes.begin()); it != sat_attributes.end(); ++it)
+ {
+// eDebug("\tattr: %s", at->name().c_str());
+ at = *it;
+ name = at->name();
+ if (name == "name")
+ sat_name = PyString_FromString(at->value().c_str());
+ else if (name == "flags")
+ {
+ tmp = strtol(at->value().c_str(), &end_ptr, 10);
+ if (!*end_ptr)
+ sat_flags = PyInt_FromLong(tmp);
+ }
+ else if (name == "position")
+ {
+ tmp = strtol(at->value().c_str(), &end_ptr, 10);
+ if (!*end_ptr)
+ {
+ if (tmp < 0)
+ tmp = 3600 + tmp;
+ sat_pos = PyInt_FromLong(tmp);
+ }
+ }
+ }
+ if (sat_pos && sat_name)
+ {
+ ePyObject tplist = PyList_New(0);
+ ePyObject tuple = PyTuple_New(3);
+ if (!sat_flags)
+ sat_flags = PyInt_FromLong(0);
+ PyTuple_SET_ITEM(tuple, 0, sat_pos);
+ PyTuple_SET_ITEM(tuple, 1, sat_name);
+ PyTuple_SET_ITEM(tuple, 2, sat_flags);
+ PyList_Append(sat_list, tuple);
+ Py_DECREF(tuple);
+ PyDict_SetItem(sat_dict, sat_pos, sat_name);
+ PyDict_SetItem(tp_dict, sat_pos, tplist);
+ for (ElementConstIterator it(sat_elements.begin()); it != sat_elements.end(); ++it)
+ {
+ //eDebug("\telement: %s", (*it)->name().c_str());
+ const AttributeList &tp_attributes = (*it)->getAttributeList();
+ AttributeConstIterator end = tp_attributes.end();
+ modulation = eDVBFrontendParametersSatellite::Modulation_QPSK;
+ system = eDVBFrontendParametersSatellite::System_DVB_S;
+ freq = 0;
+ sr = 0;
+ pol = -1;
+ fec = eDVBFrontendParametersSatellite::FEC_Auto;
+ inv = eDVBFrontendParametersSatellite::Inversion_Unknown;
+ pilot = eDVBFrontendParametersSatellite::Pilot_Unknown;
+ rolloff = eDVBFrontendParametersSatellite::RollOff_alpha_0_35;
+ tsid = -1;
+ onid = -1;
+
+ for (AttributeConstIterator it(tp_attributes.begin()); it != end; ++it)
+ {
+ at = *it;
+ //eDebug("\t\tattr: %s", at->name().c_str());
+ name = at->name();
+ if (name == "modulation") dest = &modulation;
+ else if (name == "system") dest = &system;
+ else if (name == "frequency") dest = &freq;
+ else if (name == "symbol_rate") dest = &sr;
+ else if (name == "polarization") dest = &pol;
+ else if (name == "fec_inner") dest = &fec;
+ else if (name == "inversion") dest = &inv;
+ else if (name == "rolloff") dest = &rolloff;
+ else if (name == "pilot") dest = &pilot;
+ else if (name == "tsid") dest = &tsid;
+ else if (name == "onid") dest = &onid;
+ else continue;
+ if (dest)
+ {
+ //eDebug("\t\t\tvalue: %s", at->value().c_str());
+ tmp = strtol(at->value().c_str(), &end_ptr, 10);
+ if (!*end_ptr)
+ *dest = tmp;
+ }
+ }
+ if (freq && sr && pol != -1)
+ {
+ tuple = PyTuple_New(12);
+ PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(0));
+ PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(freq));
+ PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(sr));
+ PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(pol));
+ PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong(fec));
+ PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong(system));
+ PyTuple_SET_ITEM(tuple, 6, PyInt_FromLong(modulation));
+ PyTuple_SET_ITEM(tuple, 7, PyInt_FromLong(inv));
+ PyTuple_SET_ITEM(tuple, 8, PyInt_FromLong(rolloff));
+ PyTuple_SET_ITEM(tuple, 9, PyInt_FromLong(pilot));
+ PyTuple_SET_ITEM(tuple, 10, PyInt_FromLong(tsid));
+ PyTuple_SET_ITEM(tuple, 11, PyInt_FromLong(onid));
+ PyList_Append(tplist, tuple);
+ Py_DECREF(tuple);
+ }
+ }
+ Py_DECREF(tplist);
+ }
+ else
+ {
+ if (sat_pos)
+ Py_DECREF(sat_pos);
+ if (sat_name)
+ Py_DECREF(sat_name);
+ if (sat_flags)
+ Py_DECREF(sat_flags);
+ }
+ }
+ Py_INCREF(Py_True);
+ return Py_True;
+}
+
+PyObject *eDVBDB::readCables(ePyObject cab_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(cab_list))
+ {
+ PyErr_SetString(PyExc_StandardError,
+ "type error");
+ eDebug("arg 0 is not a python list");
+ return NULL;
+ }
+ XMLTree tree;
+ tree.setFilename("/etc/tuxbox/cables.xml");
+ tree.read();
+ Element *root = tree.getRoot();
+ if (!root)
+ {
+ eDebug("couldn't open /etc/tuxbox/cables.xml!!");
+ Py_INCREF(Py_False);
+ return Py_False;
+ }
+ const Attribute *at;
+ int tmp, *dest,
+ modulation, fec, freq, sr;
+ std::string name;
+ 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 &cab_elements = el->getElementList();
+ const AttributeList &cab_attributes = el->getAttributeList();
+ ePyObject cab_name;
+ ePyObject cab_flags;
+ for (AttributeConstIterator it(cab_attributes.begin()); it != cab_attributes.end(); ++it)
+ {
+// eDebug("\tattr: %s", at->name().c_str());
+ at = *it;
+ name = at->name();
+ if (name == "name")
+ cab_name = PyString_FromString(at->value().c_str());
+ else if (name == "flags")
+ {
+ tmp = strtol(at->value().c_str(), &end_ptr, 10);
+ if (!*end_ptr)
+ cab_flags = PyInt_FromLong(tmp);
+ }
+ }
+ 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))
+ return 1;
+ }
+
+ switch (sortmode)
+ {
+ case eDVBChannelQuery::tName:
+ if (a_service)
+ {
+ if (b_service)
+ return a_service->m_service_name_sort < b_service->m_service_name_sort;
+ else
+ {
+ std::string str = b.name;
+ makeUpper(str);
+ return a_service->m_service_name_sort < str;
+ }
+ }
+ else if (b_service)
+ {
+ std::string str = a.name;
+ makeUpper(str);
+ return str < b_service->m_service_name_sort;
+ }
+ else
+ {
+ std::string aa = a.name, bb = b.name;
+ makeUpper(aa);
+ makeUpper(bb);
+ return aa < bb;
+ }
+ case eDVBChannelQuery::tProvider:
+ return a_service->m_provider_name < b_service->m_provider_name;
+ case eDVBChannelQuery::tType:
+ return a.getServiceType() < b.getServiceType();
+ case eDVBChannelQuery::tBouquet:
+ return 0;
+ case eDVBChannelQuery::tSatellitePosition:
+ return (a.getDVBNamespace().get() >> 16) < (b.getDVBNamespace().get() >> 16);
+ default:
+ return 1;
+ }
+ return 0;
+}
+
+eDVBDBQuery::eDVBDBQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
+ :eDVBDBQueryBase(db, source, query)
+{
+ m_cursor = m_db->m_services.begin();
+}
+
+RESULT eDVBDBQuery::getNextResult(eServiceReferenceDVB &ref)
+{
+ while (m_cursor != m_db->m_services.end())
+ {
+ ePtr<eDVBService> service = m_cursor->second;
+ if (service->isHidden())
+ ++m_cursor;
+ else
+ {
+ ref = m_cursor->first;
+
+ int res = (!m_query) || service->checkFilter(ref, *m_query);
+
+ ++m_cursor;
+
+ if (res)
+ return 0;
+ }
+ }
+
+ ref.type = eServiceReference::idInvalid;
+
+ return 1;
+}
+
+eDVBDBBouquetQuery::eDVBDBBouquetQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
+ :eDVBDBQueryBase(db, source, query), m_cursor(db->m_bouquets[query->m_bouquet_name].m_services.begin())
+{
+}
+
+RESULT eDVBDBBouquetQuery::getNextResult(eServiceReferenceDVB &ref)
+{
+ eBouquet &bouquet = m_db->m_bouquets[m_query->m_bouquet_name];
+ std::list<eServiceReference> &list = bouquet.m_services;
+ while (m_cursor != list.end())
+ {
+ ref = *((eServiceReferenceDVB*)&(*m_cursor));
+
+ std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it =
+ m_db->m_services.find(ref);
+
+ int res = (!m_query) || it == m_db->m_services.end() || !(it->second->isHidden() && it->second->checkFilter(ref, *m_query));
+
+ ++m_cursor;
+
+ if (res)
+ return 0;
+ }
+
+ ref.type = eServiceReference::idInvalid;
+
+ return 1;
+}
+
+eDVBDBListQuery::eDVBDBListQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
+ :eDVBDBQueryBase(db, source, query), m_cursor(m_list.end())
+{
+}
+
+RESULT eDVBDBListQuery::getNextResult(eServiceReferenceDVB &ref)
+{
+ if (m_cursor != m_list.end())
+ {
+ ref = *m_cursor++;
+ return 0;
+ }
+ ref.type = eServiceReference::idInvalid;
+ return 1;
+}
+
+int eDVBDBListQuery::compareLessEqual(const eServiceReferenceDVB &a, const eServiceReferenceDVB &b)
+{
+ if ( m_query->m_sort == eDVBChannelQuery::tSatellitePosition )
+ {
+ int x = (a.getDVBNamespace().get() >> 16);
+ int y = (b.getDVBNamespace().get() >> 16);
+ if ( x > 1800 )
+ x -= 3600;
+ if ( y > 1800 )
+ y -= 3600;
+ return x < y;
+ }
+ std::string aa = a.name, bb = b.name;
+ makeUpper(aa);
+ makeUpper(bb);
+ return aa < bb;
+}
+
+eDVBDBSatellitesQuery::eDVBDBSatellitesQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
+ :eDVBDBListQuery(db, source, query)
+{
+ std::set<unsigned int> found;
+ for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_db->m_services.begin());
+ it != m_db->m_services.end(); ++it)
+ {
+ int res = !it->second->isHidden() && it->second->checkFilter(it->first, *query);
+ if (res)
+ {
+ unsigned int dvbnamespace = it->first.getDVBNamespace().get()&0xFFFF0000;
+ if (found.find(dvbnamespace) == found.end())
+ {
+ found.insert(dvbnamespace);
+ eServiceReferenceDVB ref;
+ ref.setDVBNamespace(dvbnamespace);
+ ref.flags=eServiceReference::flagDirectory;
+ char buf[128];
+ snprintf(buf, 128, "(satellitePosition == %d) && ", dvbnamespace>>16);
+
+ ref.path=buf+source.path;
+ unsigned int pos=ref.path.find("FROM");
+ ref.path.erase(pos);
+ ref.path+="ORDER BY name";
+// eDebug("ref.path now %s", ref.path.c_str());
+ m_list.push_back(ref);
+
+ ref.path=buf+source.path;
+ pos=ref.path.find("FROM");
+ ref.path.erase(pos+5);
+ ref.path+="PROVIDERS ORDER BY name";
+// eDebug("ref.path now %s", ref.path.c_str());
+ m_list.push_back(ref);
+
+ snprintf(buf, 128, "(satellitePosition == %d) && (flags == %d) && ", dvbnamespace>>16, eDVBService::dxNewFound);
+ ref.path=buf+source.path;
+ pos=ref.path.find("FROM");
+ ref.path.erase(pos);
+ ref.path+="ORDER BY name";
+// eDebug("ref.path now %s", ref.path.c_str());
+ m_list.push_back(ref);
+ }
+ }
+ }
+ m_cursor=m_list.begin();
+}
+
+eDVBDBProvidersQuery::eDVBDBProvidersQuery(eDVBDB *db, const eServiceReference &source, eDVBChannelQuery *query)
+ :eDVBDBListQuery(db, source, query)
+{
+ std::set<std::string> found;
+ for (std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator it(m_db->m_services.begin());
+ it != m_db->m_services.end(); ++it)
+ {
+ int res = !it->second->isHidden() && it->second->checkFilter(it->first, *query);
+ if (res)
+ {
+ const char *provider_name = it->second->m_provider_name.length() ?
+ it->second->m_provider_name.c_str() :
+ "Unknown";
+ if (found.find(std::string(provider_name)) == found.end())
+ {
+ found.insert(std::string(provider_name));
+ eServiceReferenceDVB ref;
+ char buf[64];
+ ref.name=provider_name;
+ snprintf(buf, 64, "(provider == \"%s\") && ", provider_name);
+ ref.path=buf+source.path;
+ unsigned int pos = ref.path.find("FROM");
+ ref.flags=eServiceReference::flagDirectory;
+ ref.path.erase(pos);
+ ref.path+="ORDER BY name";
+// eDebug("ref.path now %s", ref.path.c_str());
+ m_list.push_back(ref);
+ }
+ }
+ }
+ m_cursor=m_list.begin();
+}
+
+/* (<name|provider|type|bouquet|satpos|chid> <==|...> <"string"|int>)[||,&& (..)] */
+
+static int decodeType(const std::string &type)
+{
+ if (type == "name")
+ return eDVBChannelQuery::tName;
+ else if (type == "provider")
+ return eDVBChannelQuery::tProvider;
+ else if (type == "type")
+ return eDVBChannelQuery::tType;
+ else if (type == "bouquet")
+ return eDVBChannelQuery::tBouquet;
+ else if (type == "satellitePosition")
+ return eDVBChannelQuery::tSatellitePosition;
+ else if (type == "channelID")
+ return eDVBChannelQuery::tChannelID;
+ else if (type == "flags")
+ return eDVBChannelQuery::tFlags;
+ else
+ return -1;
+}
+
+ /* never, NEVER write a parser in C++! */
+RESULT parseExpression(ePtr<eDVBChannelQuery> &res, std::list<std::string>::const_iterator begin, std::list<std::string>::const_iterator end)
+{
+ std::list<std::string>::const_iterator end_of_exp;
+
+ if (begin == end)
+ return 0;
+
+ if (*begin == "(")
+ {
+ end_of_exp = begin;
+ while (end_of_exp != end)
+ if (*end_of_exp == ")")
+ break;
+ else
+ ++end_of_exp;
+
+ if (end_of_exp == end)
+ {
+ eDebug("expression parse: end of expression while searching for closing brace");
+ return -1;
+ }
+
+ ++begin;
+ // begin..end_of_exp
+ int r = parseExpression(res, begin, end_of_exp);
+ if (r)
+ return r;
+ ++end_of_exp;
+
+ /* we had only one sub expression */
+ if (end_of_exp == end)
+ {
+// eDebug("only one sub expression");
+ return 0;
+ }
+
+ /* otherwise we have an operator here.. */
+
+ ePtr<eDVBChannelQuery> r2 = res;
+ res = new eDVBChannelQuery();
+ res->m_sort = 0;
+ res->m_p1 = r2;
+ res->m_inverse = 0;
+ r2 = 0;
+
+ if (*end_of_exp == "||")
+ res->m_type = eDVBChannelQuery::tOR;
+ else if (*end_of_exp == "&&")
+ res->m_type = eDVBChannelQuery::tAND;
+ else
+ {
+ eDebug("found operator %s, but only && and || are allowed!", end_of_exp->c_str());
+ res = 0;
+ return 1;
+ }
+
+ ++end_of_exp;
+
+ return parseExpression(res->m_p2, end_of_exp, end);
+ }
+
+ // "begin" <op> "end"
+ std::string type, op, val;
+
+ res = new eDVBChannelQuery();
+ res->m_sort = 0;
+
+ int cnt = 0;
+ while (begin != end)
+ {
+ switch (cnt)
+ {
+ case 0:
+ type = *begin;
+ break;
+ case 1:
+ op = *begin;
+ break;
+ case 2:
+ val = *begin;
+ break;
+ case 3:
+ eDebug("malformed query: got '%s', but expected only <type> <op> <val>", begin->c_str());
+ return 1;
+ }
+ ++begin;
+ ++cnt;
+ }
+
+ if (cnt != 3)
+ {
+ eDebug("malformed query: missing stuff");
+ res = 0;
+ return 1;
+ }
+
+ res->m_type = decodeType(type);
+
+ if (res->m_type == -1)
+ {
+ eDebug("malformed query: invalid type %s", type.c_str());
+ res = 0;
+ return 1;
+ }
+
+ if (op == "==")
+ res->m_inverse = 0;
+ else if (op == "!=")
+ res->m_inverse = 1;
+ else
+ {
+ eDebug("invalid operator %s", op.c_str());
+ res = 0;
+ return 1;
+ }
+
+ res->m_string = val;
+
+ if (res->m_type == eDVBChannelQuery::tChannelID)
+ {
+ int ns, tsid, onid;
+ if (sscanf(val.c_str(), "%08x%04x%04x", &ns, &tsid, &onid) == 3)
+ res->m_channelid = eDVBChannelID(eDVBNamespace(ns), eTransportStreamID(tsid), eOriginalNetworkID(onid));
+ else
+ eDebug("couldn't parse channelid !! format should be hex NNNNNNNNTTTTOOOO (namespace, tsid, onid)");
+ }
+ else
+ res->m_int = atoi(val.c_str());
+
+ return 0;
+}
+
+RESULT eDVBChannelQuery::compile(ePtr<eDVBChannelQuery> &res, std::string query)
+{
+ std::list<std::string> tokens;
+
+ std::string current_token;
+ std::string bouquet_name;
+
+// eDebug("splitting %s....", query.c_str());
+ unsigned int i = 0;
+ const char *splitchars="()";
+ int quotemode = 0, lastsplit = 0, lastalnum = 0;
+ while (i <= query.size())
+ {
+ int c = (i < query.size()) ? query[i] : ' ';
+ ++i;
+
+ int issplit = !!strchr(splitchars, c);
+ int isaln = isalnum(c);
+ int iswhite = c == ' ';
+ int isquot = c == '\"';
+
+ if (quotemode)
+ {
+ iswhite = issplit = 0;
+ isaln = lastalnum;
+ }
+
+ if (issplit || iswhite || isquot || lastsplit || (lastalnum != isaln))
+ {
+ if (current_token.size())
+ tokens.push_back(current_token);
+ current_token.clear();
+ }
+
+ if (!(iswhite || isquot))
+ current_token += c;
+
+ if (isquot)
+ quotemode = !quotemode;
+ lastsplit = issplit;
+ lastalnum = isaln;
+ }
+
+// for (std::list<std::string>::const_iterator a(tokens.begin()); a != tokens.end(); ++a)
+// {
+// printf("%s\n", a->c_str());
+// }
+
+ int sort = eDVBChannelQuery::tName;
+ /* check for "ORDER BY ..." */
+
+ std::list<std::string>::iterator it = tokens.begin();
+ while (it != tokens.end())
+ {
+ if (*it == "ORDER")
+ {
+ tokens.erase(it++);
+ if (it != tokens.end() && *it == "BY")
+ {
+ tokens.erase(it++);
+ sort = decodeType(*it);
+ tokens.erase(it++);
+ } else
+ sort = -1;
+ }
+ else if (*it == "FROM")
+ {
+ tokens.erase(it++);
+ if (it != tokens.end() && *it == "BOUQUET")
+ {
+ tokens.erase(it++);
+ bouquet_name = *it;
+ tokens.erase(it++);
+ }
+ else if (it != tokens.end() && *it == "SATELLITES")
+ tokens.erase(it++);
+ else if (it != tokens.end() && *it == "PROVIDERS")
+ tokens.erase(it++);
+ else
+ {
+ eDebug("FROM unknown %s", (*it).c_str());
+ tokens.erase(it++);
+ }
+ }
+ else
+ ++it;
+ }
+
+ if (sort == -1)
+ {
+ eWarning("ORDER BY .. string invalid.");
+ res = 0;
+ return -1;
+ }
+
+// eDebug("sort by %d", sort);
+
+ /* now we recursivly parse that. */
+ int r = parseExpression(res, tokens.begin(), tokens.end());
+
+ /* we have an empty (but valid!) expression */
+ if (!r && !res)
+ {
+ res = new eDVBChannelQuery();
+ res->m_inverse = 0;
+ res->m_type = eDVBChannelQuery::tAny;
+ }
+
+ if (res)
+ {
+ res->m_sort = sort;
+ res->m_bouquet_name = bouquet_name;
+ }
+
+// eDebug("return: %d", r);
+ return r;