-
Notifications
You must be signed in to change notification settings - Fork 317
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Cherry pick -> OpenViX/enigma2@06c0765 OpenViX/enigma2@fd403aa
- Loading branch information
Showing
2 changed files
with
366 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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]> | ||
|
@@ -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... | ||
|
@@ -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; | ||
|
@@ -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) | ||
|
@@ -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; | ||
|
@@ -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; | ||
|
Oops, something went wrong.