Skip to content

Commit

Permalink
[db/scan] create database for logical channel number (descriptor 0x83…
Browse files Browse the repository at this point in the history
…) DVB-C/T/T2 (#4051)

Data is fully handled in C++ and is accessible from both C++ and python modules

Author: @DimitarCC

Includes openatv/enigma2@b13920f
Includes some elements from openatv/enigma2@be62b2d
  • Loading branch information
Huevos authored and WanWizard committed Oct 24, 2024
1 parent d3188c8 commit fa2d56a
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 0 deletions.
92 changes: 92 additions & 0 deletions lib/dvb/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -787,6 +787,65 @@ void eDVBDB::loadServiceListV5(FILE * f)
eDebug("loaded %d channels/transponders and %d services", tcount, scount);
}

void eDVBDB::resetLcnDB()
{
m_lcnmap.clear();
FILE *m_lcn_file = fopen(eEnv::resolve("${sysconfdir}/enigma2/lcndb").c_str(), "w");
if (m_lcn_file)
fclose(m_lcn_file);
}

void eDVBDB::saveLcnDB()
{
std::string lfname = eEnv::resolve("${sysconfdir}/enigma2/lcndb");
CFile lf(lfname, "w");
if (lf)
{
for (auto &[key, value] : m_lcnmap)
{
value.write(lf, key);
}
}
}

void eDVBDB::addLcnToDB(int ns, int onid, int tsid, int sid, uint16_t lcn, uint32_t signal)
{
eServiceReferenceDVB s = eServiceReferenceDVB(eDVBNamespace(ns), eTransportStreamID(tsid), eOriginalNetworkID(onid), eServiceID(sid), 0);
std::map<eServiceReferenceDVB, LCNData>::iterator it = m_lcnmap.find(s);
if (it != m_lcnmap.end())
{
it->second.Update(lcn, signal);
}
else
{
LCNData lcndata;
lcndata.Update(lcn, signal);
m_lcnmap.insert(std::pair<eServiceReferenceDVB, LCNData>(s, lcndata));
}
}

void eDVBDB::readLcnDBFile()
{
char line[256];
m_lcnmap.clear();
std::string lfname = eEnv::resolve("${sysconfdir}/enigma2/lcndb");
CFile lf(lfname, "rt");
if(lf)
{
while (!feof(lf))
{
if (!fgets(line, sizeof(line), lf))
break;

LCNData lcndata;
eServiceReferenceDVB s = lcndata.parse(line);
if (s)
m_lcnmap.insert(std::pair<eServiceReferenceDVB, LCNData>(s, lcndata));

}
}
}

void eDVBDB::loadServicelist(const char *file)
{
eDebug("[eDVBDB] ---- opening lame channel db");
Expand Down Expand Up @@ -815,6 +874,8 @@ void eDVBDB::loadServicelist(const char *file)
eDebug("[eDVBDB] services invalid, no transponders");
return;
}

readLcnDBFile();
// clear all transponders
int tcount = 0;
while (!feof(f))
Expand Down Expand Up @@ -1100,6 +1161,7 @@ void eDVBDB::saveServicelist(const char *file)
void eDVBDB::saveServicelist()
{
saveServicelist(eEnv::resolve("${sysconfdir}/enigma2/lamedb").c_str());
saveLcnDB();
}

void eDVBDB::saveIptvServicelist()
Expand Down Expand Up @@ -2115,6 +2177,30 @@ PyObject *eDVBDB::readATSC(ePyObject atsc_list, ePyObject tp_dict)
return Py_True;
}

PyObject *eDVBDB::getLcnDBData()
{
ePyObject dest = PyList_New(0);
if (dest)
{
std::map<eServiceReferenceDVB, LCNData>::iterator it = m_lcnmap.begin();
for (;it != m_lcnmap.end();++it)
{
ePyObject tuple = PyTuple_New(6);
PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong((unsigned long)it->second.NS));
PyTuple_SET_ITEM(tuple, 1, PyLong_FromLongLong((unsigned long)it->second.ONID));
PyTuple_SET_ITEM(tuple, 2, PyLong_FromLongLong((unsigned long)it->second.TSID));
PyTuple_SET_ITEM(tuple, 3, PyLong_FromLongLong((unsigned long)it->second.SID));
PyTuple_SET_ITEM(tuple, 4, PyLong_FromLongLong((unsigned long)it->second.LCN));
PyTuple_SET_ITEM(tuple, 5, PyLong_FromLongLong((unsigned long)it->second.SIGNAL));
PyList_Append(dest, tuple);
Py_DECREF(tuple);
}
}
else
Py_RETURN_NONE;
return dest;
}

eDVBDB::~eDVBDB()
{
instance=NULL;
Expand Down Expand Up @@ -2464,6 +2550,12 @@ RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr<eDVBServic
return 0;
}

RESULT eDVBDB::getLcnDBData(std::map<eServiceReferenceDVB, LCNData> &data)
{
data = m_lcnmap;
return 0;
}

RESULT eDVBDB::flush()
{
saveServicelist();
Expand Down
74 changes: 74 additions & 0 deletions lib/dvb/db.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,75 @@
#include <lib/base/eptrlist.h>
#include <set>
#include <vector>
#include <sstream>
class ServiceDescriptionSection;

struct LCNData
{
private:
bool FOUND;

std::vector<std::string> split_str(std::string s)
{
std::vector<std::string> tokens;
std::string token;
std::stringstream str(s);
while (getline(str, token, ':')) {
tokens.push_back(token);
}
return tokens;
}

public:
int NS;
int ONID;
int TSID;
int SID;
int SIGNAL;
int LCN;
LCNData()
{
LCN = 0;
SIGNAL = -1;
FOUND = true;
}

eServiceReferenceDVB parse(const char *line)
{

if (sscanf(line, "%x:%x:%x:%x:%d:%d", &NS, &ONID, &TSID, &SID, &LCN, &SIGNAL) == 6)
return eServiceReferenceDVB(eDVBNamespace(NS), eTransportStreamID(TSID), eOriginalNetworkID(ONID), eServiceID(SID), 0);
else
return eServiceReferenceDVB();

}

void Update(uint16_t lcn, uint32_t signal)
{
LCN = lcn;
SIGNAL = signal;
FOUND = true;
}

void write(FILE *lf, const eServiceReferenceDVB &key)
{
if (FOUND)
{
int sid = key.getServiceID().get();
int tsid = key.getTransportStreamID().get();
int onid = key.getOriginalNetworkID().get();
int ns = key.getDVBNamespace().get();
fprintf(lf, "%x:%x:%x:%x:%d:%d\n", ns, onid, tsid, sid, LCN, SIGNAL);
}
}

void resetFound()
{
FOUND = false;
}

};

class eIPTVDBItem
{
public:
Expand Down Expand Up @@ -65,6 +132,7 @@ class eDVBDB: public iDVBChannelList
#endif
private:
void loadServiceListV5(FILE * f);
std::map<eServiceReferenceDVB, LCNData> m_lcnmap;
public:
std::vector<eIPTVDBItem> iptv_services;
// iDVBChannelList
Expand All @@ -83,6 +151,7 @@ class eDVBDB: public iDVBChannelList
PyObject *readTerrestrials(SWIG_PYOBJECT(ePyObject) ter_list, SWIG_PYOBJECT(ePyObject) tp_dict);
PyObject *readCables(SWIG_PYOBJECT(ePyObject) cab_list, SWIG_PYOBJECT(ePyObject) tp_dict);
PyObject *readATSC(SWIG_PYOBJECT(ePyObject) atsc_list, SWIG_PYOBJECT(ePyObject) tp_dict);
PyObject *getLcnDBData();
#ifndef SWIG
RESULT removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned int orb_pos);
RESULT removeServices(eDVBChannelID chid, unsigned int orb_pos);
Expand All @@ -95,6 +164,7 @@ class eDVBDB: public iDVBChannelList

RESULT addService(const eServiceReferenceDVB &referenc, eDVBService *service);
RESULT getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service);
RESULT getLcnDBData(std::map<eServiceReferenceDVB, LCNData> &data);
RESULT flush();

RESULT startQuery(ePtr<iDVBChannelListQuery> &query, eDVBChannelQuery *q, const eServiceReference &source);
Expand All @@ -107,6 +177,9 @@ class eDVBDB: public iDVBChannelList
eDVBDB();
virtual ~eDVBDB();
int renumberBouquet(eBouquet &bouquet, int startChannelNum = 1);
void addLcnToDB(int ns, int onid, int tsid, int sid, uint16_t lcn, uint32_t signal);
void resetLcnDB();
void readLcnDBFile();
#endif
void setNumberingMode(bool numberingMode);
void setLoadUnlinkedUserbouquets(bool value) { m_load_unlinked_userbouquets=value; }
Expand All @@ -117,6 +190,7 @@ class eDVBDB: public iDVBChannelList
void saveServicelist();
void saveIptvServicelist();
void saveServicelist(const char *file);
void saveLcnDB();
void reloadBouquets();
void parseServiceData(ePtr<eDVBService> s, std::string str);
};
Expand Down
72 changes: 72 additions & 0 deletions lib/dvb/scan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <dvbsi++/terrestrial_delivery_system_descriptor.h>
#include <dvbsi++/t2_delivery_system_descriptor.h>
#include <dvbsi++/cable_delivery_system_descriptor.h>
#include <dvbsi++/logical_channel_descriptor.h>
#include <dvbsi++/ca_identifier_descriptor.h>
#include <dvbsi++/registration_descriptor.h>
#include <dvbsi++/extension_descriptor.h>
Expand All @@ -23,6 +24,7 @@
#include <lib/base/estring.h>
#include <lib/dvb/dvb.h>
#include <lib/dvb/db.h>
#include <lib/python/python.h>
#include <errno.h>
#include "absdiff.h"

Expand Down Expand Up @@ -758,6 +760,9 @@ void eDVBScan::channelDone()
(*tsinfo)->getOriginalNetworkId());
bool T2 = false;
eDVBFrontendParametersTerrestrial t2transponder;
eOriginalNetworkID onid = (*tsinfo)->getOriginalNetworkId();
eTransportStreamID tsid = (*tsinfo)->getTransportStreamId();
eDVBNamespace ns(0);

for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
desc != (*tsinfo)->getDescriptors()->end(); ++desc)
Expand All @@ -774,6 +779,10 @@ void eDVBScan::channelDone()
cable.set(d);
feparm->setDVBC(cable);

unsigned long hash=0;
feparm->getHash(hash);
ns = buildNamespace(onid, tsid, hash);

addChannelToScan(feparm);
break;
}
Expand All @@ -786,10 +795,19 @@ void eDVBScan::channelDone()
eDVBFrontendParametersTerrestrial terr;
terr.set(d);
feparm->setDVBT(terr);

unsigned long hash=0;
feparm->getHash(hash);
ns = buildNamespace(onid, tsid, hash);

addChannelToScan(feparm);
break;
}
case LOGICAL_CHANNEL_DESCRIPTOR:
{
// we handle it later
break;
}
case S2_SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR:
{
eDebug("[eDVBScan] S2_SATELLITE_DELIVERY_SYSTEM_DESCRIPTOR found");
Expand Down Expand Up @@ -859,6 +877,18 @@ void eDVBScan::channelDone()
T2DeliverySystemDescriptor &d = (T2DeliverySystemDescriptor&)**desc;
t2transponder.set(d);

// fetch T2 namespace for LCN output, where frequency data may not be in SI table
ePtr<iDVBFrontend> fe;
ePtr<iDVBTransponderData> trdata;
if (!m_channel->getFrontend(fe))
{
fe->getTransponderData(trdata, true);
int freq = trdata->getFrequency();
long hash = 0xEEEE0000;
hash |= (freq/1000000)&0xFFFF;
ns = buildNamespace(onid, tsid, hash); // used in case LOGICAL_CHANNEL_DESCRIPTOR
} // end fetch T2 namespace

for (T2CellConstIterator cell = d.getCells()->begin();
cell != d.getCells()->end(); ++cell)
{
Expand Down Expand Up @@ -900,6 +930,42 @@ void eDVBScan::channelDone()
break;
}
}
// we do this after the main loop because we absolutely need the namespace
for (DescriptorConstIterator desc = (*tsinfo)->getDescriptors()->begin();
desc != (*tsinfo)->getDescriptors()->end(); ++desc)
{
switch ((*desc)->getTag())
{
case LOGICAL_CHANNEL_DESCRIPTOR:
{
if (!(system == iDVBFrontend::feTerrestrial || system == iDVBFrontend::feCable))
break; // when current locked transponder is not terrestrial or cable ignore this descriptor

if (ns.get() == 0)
break; // invalid namespace

int signal = 0;
ePtr<iDVBFrontend> fe;

if (!m_channel->getFrontend(fe))
signal = fe->readFrontendData(iFrontendInformation_ENUMS::signalQuality);

LogicalChannelDescriptor &d = (LogicalChannelDescriptor&)**desc;
for (LogicalChannelListConstIterator it = d.getChannelList()->begin(); it != d.getChannelList()->end(); it++)
{
LogicalChannel *ch = *it;
if (ch->getVisibleServiceFlag())
{
eDVBDB::getInstance()->addLcnToDB(ns.get(), onid.get(), tsid.get(), eServiceID(ch->getServiceId()).get(), ch->getLogicalChannelNumber(), signal);
SCAN_eDebug("NAMESPACE: %08x ONID: %04x TSID: %04x SID: %04x LCN: %05d SIGNAL: %08d", ns.get(), onid.get(), tsid.get(), ch->getServiceId(), ch->getLogicalChannelNumber(), signal);
}
}
break;
}
default:
break;
}
}
}

}
Expand Down Expand Up @@ -1164,6 +1230,12 @@ void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transpon
transponderlist = &m_ch_blindscan;
}

if (m_flags & scanRemoveServices)
{
eDVBDB::getInstance()->resetLcnDB();
}


for (eSmartPtrList<iDVBFrontendParameters>::const_iterator i(known_transponders.begin()); i != known_transponders.end(); ++i)
{
bool exist=false;
Expand Down

0 comments on commit fa2d56a

Please sign in to comment.