Skip to content

Commit

Permalink
[eDVBDB]
Browse files Browse the repository at this point in the history
  • Loading branch information
jbleyel committed Oct 27, 2024
1 parent 5e568e1 commit 6436603
Show file tree
Hide file tree
Showing 2 changed files with 366 additions and 0 deletions.
355 changes: 355 additions & 0 deletions lib/dvb/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@
#include <dvbsi++/satellite_delivery_system_descriptor.h>
#include <dvbsi++/s2_satellite_delivery_system_descriptor.h>
#include <dirent.h>
#include <lib/nav/core.h>
#include <fstream>
//#include <stdexcept>
//#include <exception>
#include <regex>

/*
* Copyright (C) 2017 Marcus Metzler <[email protected]>
Expand Down Expand Up @@ -439,6 +444,65 @@ void eDVBDB::reloadServicelist()
loadServicelist(eEnv::resolve("${sysconfdir}/enigma2/lamedb").c_str());
}

void eDVBDB::loadIPTVCachefile(const char *file)
{
CFile f(file, "rt");
if (!f)
{
eDebug("[eDVBDB] can't open %s: %m", file);
return;
}
iptv_services.clear();
int scount=0;
char line[1024];
while (fgets(line, 1024, f))
{
int len = strlen(line);
if (!len) continue;
if (line[len - 1] == '\n')
line[len - 1] = '\0';
if (!strncmp(line, "s:", 2)) // Service data
{
char * sdata = strchr(line, ',');
ePtr<eDVBService> s = new eDVBService;
if (sdata)
{
*sdata++ = '\0';
parseIPTVServiceData(s, sdata);
}
s->m_reference_str = line + 2;
iptv_services.push_back(s);
scount ++;
}
}
eDebug("[eDVBDB] loaded %d iptv channels from cache file.", scount);
}

void eDVBDB::parseIPTVServiceData(ePtr<eDVBService> s, std::string str)
{
while ((!str.empty()) && str[1]==':')
{
size_t c=str.find(',');
char p=str[0];
std::string v;
if (c == std::string::npos)
{
v=str.substr(2);
str="";
} else
{
v=str.substr(2, c-2);
str=str.substr(c+1);
}
if (p == 'c')
{
int cid, val;
sscanf(v.c_str(), "%02d%x", &cid, &val);
s->setCacheEntry((eDVBService::cacheID)cid,val);
}
}
}

void eDVBDB::parseServiceData(ePtr<eDVBService> s, std::string str)
{
while ((!str.empty()) && str[1]==':') // new: p:, f:, c:%02d...
Expand Down Expand Up @@ -1167,6 +1231,41 @@ void eDVBDB::saveServicelist()
saveServicelist(eEnv::resolve("${sysconfdir}/enigma2/lamedb").c_str());
}

void eDVBDB::saveIptvServicelist()
{
saveIptvServicelist(eEnv::resolve("${sysconfdir}/enigma2/iptvcache").c_str());
}

void eDVBDB::saveIptvServicelist(const char *file)
{
std::string filename = file;

CFile f((filename + ".writing").c_str(), "w");
if (!f)
eFatal("[eDVBDB] couldn't save iptv cache file!");
else
{
eDebug("[eDVBDB] saveIptvServicelist");
for(std::vector<ePtr<eDVBService>>::iterator it = iptv_services.begin(); it != iptv_services.end(); ++it)
{
eDebug("[eDVBDB] saveIptvServicelist %s",(*it)->m_reference_str.c_str());
fprintf(f, "s:%s", (*it)->m_reference_str.c_str());
for (int x=0; x < eDVBService::cacheMax; ++x)
{
// write cached pids
int entry = (*it)->getCacheEntry((eDVBService::cacheID)x);
if (entry != -1) {
fprintf(f, ",c:%02d%x", x, entry);
}
}
fprintf(f, "\n");
}
f.sync();
rename((filename + ".writing").c_str(), filename.c_str());
}

}

void eDVBDB::loadBouquet(const char *path)
{
std::vector<std::string> userbouquetsfiles;
Expand Down Expand Up @@ -1506,6 +1605,7 @@ eDVBDB::eDVBDB()
instance = this;
m_numbering_mode = eSimpleConfig::getInt("config.usage.numberMode", 0);
reloadServicelist();
loadIPTVCachefile(eEnv::resolve("${sysconfdir}/enigma2/iptvcache").c_str());
}

PyObject *eDVBDB::readSatellites(ePyObject sat_list, ePyObject sat_dict, ePyObject tp_dict)
Expand Down Expand Up @@ -2449,6 +2549,251 @@ RESULT eDVBDB::removeFlags(unsigned int flagmask, eDVBChannelID chid, unsigned i
return 0;
}

RESULT eDVBDB::addOrUpdateBouquet(const std::string &name, ePyObject services, const int type, bool isAddedFirst)
{
std::string ext = ".tv";
if (type == 2) {
ext = ".radio";
}
std::string filename = "userbouquet." + name + ext;
return addOrUpdateBouquet(name, filename, services, isAddedFirst);
}

RESULT eDVBDB::addOrUpdateBouquet(const std::string &name, const std::string &filename, ePyObject services, bool isAddedFirst)
{
std::string ext = ".tv";
int type = 1;
if (filename.find(".radio") != std::string::npos) {
ext = ".radio";
type = 2;
}
ePtr<iDVBChannelList> db;
ePtr<eDVBResourceManager> res;
eDVBResourceManager::getInstance(res);
res->getChannelList(db);
std::string bouquetquery = "FROM BOUQUET \"" + filename + "\" ORDER BY bouquet";
eServiceReference bouquetref(eServiceReference::idDVB, eServiceReference::flagDirectory, bouquetquery);
bouquetref.setData(0, type);
eBouquet *bouquet = NULL;
eServiceReference rootref(eServiceReference::idDVB, eServiceReference::flagDirectory, "FROM BOUQUET \"bouquets" + ext + "\" ORDER BY bouquet");
if (!db->getBouquet(bouquetref, bouquet) && bouquet)
{
bouquet->m_services.clear();
}
else
{
/* bouquet doesn't yet exist, create a new one */
if (!db->getBouquet(rootref, bouquet) && bouquet)
{
if (isAddedFirst)
bouquet->m_services.push_front(bouquetref);
else
bouquet->m_services.push_back(bouquetref);
bouquet->flushChanges();
}
/* loading the bouquet seems to be the only way to add it to the bouquet list */
loadBouquet(filename.c_str());
/* and now that it has been added to the list, we can find it */
db->getBouquet(bouquetref, bouquet);
bouquet->setListName(name);
}
if (!PyList_Check(services)) {
const char *errstr = "eDVBDB::appendServicesToBouquet second parameter is not a python list!";
PyErr_SetString(PyExc_TypeError, errstr);
return -1;
}
int size = PyList_Size(services);
while(size)
{
--size;
ePyObject refstr = PyList_GET_ITEM(services, size);
if (!PyUnicode_Check(refstr))
{
const char *errstr = "eDVBDB::appendServicesToBouquet entry in service list is not a string.";
PyErr_SetString(PyExc_TypeError, errstr);
return -1;
}
const char *tmpstr = PyUnicode_AsUTF8(refstr);
eDebug("[eDVBDB] ParsedReference: %s", tmpstr);
eServiceReference ref(tmpstr);
if (ref.valid())
{
eDebug("eDVBDB::appendServicesToBouquet push ref %s", tmpstr);
bouquet->m_services.push_front(ref);
}
else
eDebug("eDVBDB::appendServicesToBouquet '%s' is not a valid service reference.", tmpstr);
}

bouquet->flushChanges();
renumberBouquet();
return 0;
}

RESULT eDVBDB::appendServicesToBouquet(const std::string &filename, ePyObject services)
{
std::string ext = ".tv";
int type = 1;
if (filename.find(".radio") != std::string::npos) {
ext = ".radio";
type = 2;
}
ePtr<iDVBChannelList> db;
ePtr<eDVBResourceManager> res;
eDVBResourceManager::getInstance(res);
res->getChannelList(db);
std::string bouquetquery = "FROM BOUQUET \"" + filename + "\" ORDER BY bouquet";
eServiceReference bouquetref(eServiceReference::idDVB, eServiceReference::flagDirectory, bouquetquery);
bouquetref.setData(0, type);
eBouquet *bouquet = NULL;
if (!db->getBouquet(bouquetref, bouquet) && bouquet)
{

if (!PyList_Check(services)) {
const char *errstr = "eDVBDB::appendServicesToBouquet second parameter is not a python list!";
PyErr_SetString(PyExc_TypeError, errstr);
return -1;
}
int size = PyList_Size(services);
while(size)
{
--size;
ePyObject refstr = PyList_GET_ITEM(services, size);
if (!PyUnicode_Check(refstr))
{
const char *errstr = "eDVBDB::appendServicesToBouquet entry in service list is not a string.";
PyErr_SetString(PyExc_TypeError, errstr);
return -1;
}
const char *tmpstr = PyUnicode_AsUTF8(refstr);
//eDebug("[eDVBDB] ParsedReference: %s", tmpstr);
eServiceReference ref(tmpstr);
if (ref.valid())
{
eDebug("eDVBDB::appendServicesToBouquet push ref %s", tmpstr);
bouquet->m_services.push_front(ref);
}
else
eDebug("eDVBDB::appendServicesToBouquet '%s' is not a valid service reference!", tmpstr);
}
bouquet->flushChanges();
renumberBouquet();
}
else
return -1;

return 0;
}

RESULT eDVBDB::removeBouquet(const std::string &filename_regex)
{
std::string ext = ".tv";
int type = 1;
if (filename_regex.find(".radio") != std::string::npos) {
ext = ".radio";
type = 2;
}
ePtr<iDVBChannelList> db;
ePtr<eDVBResourceManager> res;
eDVBResourceManager::getInstance(res);
res->getChannelList(db);
std::string p = eEnv::resolve("${sysconfdir}/enigma2/");
DIR *dir = opendir(p.c_str());
if (!dir)
{
eDebug("[eDVBDB] Cannot open directory where the userbouquets should be expected.");
return -1;
}
dirent *entry;
while((entry = readdir(dir)) != NULL)
if (entry->d_type == DT_REG)
{
std::string path = entry->d_name;
if (std::regex_search(path, std::regex(filename_regex)))
{
std::string bouquetquery = "FROM BOUQUET \"" + path + "\" ORDER BY bouquet";
eServiceReference bouquetref(eServiceReference::idDVB, eServiceReference::flagDirectory, bouquetquery);
bouquetref.setData(0, type);
eBouquet *bouquet = NULL;
eServiceReference rootref(eServiceReference::idDVB, eServiceReference::flagDirectory, "FROM BOUQUET \"bouquets" + ext + "\" ORDER BY bouquet");
if (!db->getBouquet(bouquetref, bouquet) && bouquet)
{
if (!db->getBouquet(rootref, bouquet) && bouquet)
{
int status = std::remove((p+path).c_str());
if (status != 0) {
eDebug("[eDVBDB] ERROR DELETING FILE %s", path.c_str());
}
m_bouquets.erase(path);
bouquet->m_services.remove(bouquetref);
bouquet->flushChanges();
}
else
{
return -1;
}
}
else
{
return -1;
}
}
}
closedir(dir);

return 0;
}

RESULT eDVBDB::addChannelToDB(const eServiceReference &service, const eDVBFrontendParameters &feparam, SWIG_PYOBJECT(ePyObject) cachedPids, SWIG_PYOBJECT(ePyObject) caPids, const int serviceFlags)
{
const eServiceReferenceDVB &sref = (const eServiceReferenceDVB&)service;
eDVBFrontendParameters *feparam_ptr = const_cast<eDVBFrontendParameters*>(&feparam);
eDVBChannelID chid;
sref.getChannelID(chid);
addChannelToList(chid, feparam_ptr);
ePtr<eDVBService> s = new eDVBService;
s->m_service_name = service.getName();
s->m_provider_name = service.getProvider();
s->genSortName();
s->m_flags = serviceFlags;
if (PyList_Check(cachedPids)) {
int size = PyList_Size(cachedPids);
while(size)
{
--size;
ePyObject cachedPidTupleObj = PyList_GET_ITEM(cachedPids, size);
if (PyTuple_Check(cachedPidTupleObj) && PyTuple_Size(cachedPidTupleObj) == 2)
{
ePyObject cIDObj = PyTuple_GET_ITEM(cachedPidTupleObj, 0);
ePyObject cachedPidValObj = PyTuple_GET_ITEM(cachedPidTupleObj, 1);
if (PyLong_Check(cIDObj) && PyLong_Check(cachedPidValObj))
{
int cID = PyLong_AsLong(cIDObj);
int cPid = PyLong_AsLong(cachedPidValObj);
s->setCacheEntry((eDVBService::cacheID)cID, cPid);
}
}
}
}
CAID_LIST m_ca;
if (PyList_Check(caPids)) {
int size = PyList_Size(caPids);
while(size)
{
--size;
ePyObject caPidObj = PyList_GET_ITEM(caPids, size);
if (PyLong_Check(caPidObj))
{
int caPid = PyLong_AsLong(caPidObj);
m_ca.push_back((uint16_t)caPid);
}
}
}
s->m_ca = m_ca;
addOrUpdateService(sref, s);
return 0;
}

RESULT eDVBDB::addChannelToList(const eDVBChannelID &id, iDVBFrontendParameters *feparm)
{
channel ch;
Expand Down Expand Up @@ -2488,6 +2833,16 @@ RESULT eDVBDB::addService(const eServiceReferenceDVB &serviceref, eDVBService *s
return 0;
}

RESULT eDVBDB::addOrUpdateService(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));
else
it->second = service;
return 0;
}

RESULT eDVBDB::getService(const eServiceReferenceDVB &reference, ePtr<eDVBService> &service)
{
std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator i;
Expand Down
Loading

0 comments on commit 6436603

Please sign in to comment.