Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 119 additions & 18 deletions lib/dvb/epgcache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1871,32 +1871,41 @@ static inline uint8_t LO(int x) { return (uint8_t) (x & 0xFF); }
// convert from set of strings to DVB format (EIT)
void eEPGCache::submitEventData(const std::vector<eServiceReferenceDVB>& serviceRefs, long start,
long duration, const char* title, const char* short_summary,
const char* long_description, char event_type)
const char* long_description, std::vector<uint8_t> event_types, std::vector<eit_parental_rating> parental_ratings, uint16_t eventId)
{
std::vector<int> sids;
std::vector<eDVBChannelID> chids;
chids.reserve(serviceRefs.size());
for (std::vector<eServiceReferenceDVB>::const_iterator serviceRef = serviceRefs.begin();
serviceRef != serviceRefs.end();
++serviceRef)
{
eDVBChannelID chid;
serviceRef->getChannelID(chid);
chids.push_back(chid);
sids.push_back(serviceRef->getServiceID().get());

// disable EIT event parsing when using EPG_IMPORT
ePtr<eDVBService> service;
if (!eDVBDB::getInstance()->getService(*serviceRef, service) && service->useEIT())
{
service->m_flags |= eDVBService::dxNoEIT;
}
int sid = serviceRef->getServiceID().get();
sids.push_back(sid);
}
submitEventData(sids, chids, start, duration, title, short_summary, long_description, event_type, 0, EPG_IMPORT);
submitEventData(sids, chids, start, duration, title, short_summary, long_description, event_types, parental_ratings, eventId, EPG_IMPORT);
}

void eEPGCache::submitEventData(const std::vector<int>& sids, const std::vector<eDVBChannelID>& chids, long start,
long duration, const char* title, const char* short_summary,
const char* long_description, char event_type, int event_id, int source)
{
/* eDebug("[eEPGCache:import] submitEventData entered title=%d short=%d long=%d", title, short_summary, long_description); */
std::vector<uint8_t> event_types;
std::vector<eit_parental_rating> parental_ratings;
if(event_type != 0)
{
event_types.push_back(event_type);
}
submitEventData(sids, chids, start, duration, title, short_summary, long_description, event_types, parental_ratings, event_id, source);
}

void eEPGCache::submitEventData(const std::vector<int>& sids, const std::vector<eDVBChannelID>& chids, long start,
long duration, const char* title, const char* short_summary,
const char* long_description, std::vector<uint8_t> event_types, std::vector<eit_parental_rating> parental_ratings, int event_id, int source)
{
if (!title)
return;
Expand Down Expand Up @@ -1968,13 +1977,49 @@ void eEPGCache::submitEventData(const std::vector<int>& sids, const std::vector<
}

//Content type
if (event_type != 0)
if (!event_types.empty())
{
const int max_etypes = (256 - 2) / 2;
int count = event_types.size();
if (count > max_etypes)
count = max_etypes;

x[0] = CONTENT_DESCRIPTOR;
x[1] = 2 * event_types.size();
x += 2;
for (std::vector<uint8_t>::const_iterator event_type = event_types.begin();
event_type != event_types.end();
++event_type)
{
if(--count < 0)
break;
x[0] = *event_type;
x[1] = 0;
x += 2;
}
}

//Parental rating
if (!parental_ratings.empty())
{
x[0] = 0x54;
x[1] = 2;
x[2] = event_type;
x[3] = 0;
x += 4;
const int max_ratings = (256 - 2) / 4;
int count = parental_ratings.size();
if (count > max_ratings)
count = max_ratings;

x[0] = PARENTAL_RATING_DESCRIPTOR;
x[1] = 4 * count;
x += 2;
for (std::vector<eit_parental_rating>::const_iterator parental_rating = parental_ratings.begin();
parental_rating != parental_ratings.end();
++parental_rating)
{
if(--count < 0)
break;
memcpy(x, parental_rating->country_code, 3);
x[3] = parental_rating->rating;
x += 4;
}
}

//Long description
Expand Down Expand Up @@ -2138,10 +2183,66 @@ void eEPGCache::importEvents(ePyObject serviceReferences, ePyObject list)
const char *title = getStringFromPython(PyTuple_GET_ITEM(singleEvent, 2));
const char *short_summary = getStringFromPython(PyTuple_GET_ITEM(singleEvent, 3));
const char *long_description = getStringFromPython(PyTuple_GET_ITEM(singleEvent, 4));
char event_type = (char) PyLong_AsLong(PyTuple_GET_ITEM(singleEvent, 5));
std::vector<uint8_t> event_types;
ePyObject eventTypeList = PyTuple_GET_ITEM(singleEvent, 5);
bool eventTypeIsTuple = PyTuple_Check(eventTypeList);
if(eventTypeIsTuple || PyList_Check(eventTypeList)) {
int numberOfEventTypes = eventTypeIsTuple ? PyTuple_Size(eventTypeList) : PyList_Size(eventTypeList);
event_types.reserve(numberOfEventTypes);
for (int j = 0; j < numberOfEventTypes; ++j)
{
uint8_t event_type = (uint8_t) PyLong_AsUnsignedLongMask(eventTypeIsTuple ? PyTuple_GET_ITEM(eventTypeList, j) : PyList_GET_ITEM(eventTypeList, j));
event_types.push_back(event_type);
}
} else if (PyLong_Check(eventTypeList)) {
uint8_t event_type = (uint8_t) PyLong_AsUnsignedLongMask(eventTypeList);
event_types.push_back(event_type);
} else {
eDebug("[eEPGCache:import] event type must be a single integer or a list or tuple of integers, aborting");
return;
}

uint16_t eventId = 0;
if (tupleSize >= 7)
{
eventId = (uint16_t) PyLong_AsUnsignedLongMask(PyTuple_GET_ITEM(singleEvent, 6));
}

std::vector<eit_parental_rating> parental_ratings;
if (tupleSize >= 8)
{
ePyObject parentalInfoList = PyTuple_GET_ITEM(singleEvent, 7);
bool parentalInfoIsTuple = PyTuple_Check(parentalInfoList);
if(parentalInfoIsTuple || PyList_Check(parentalInfoList)) {
int numberOfpInfoTypes = parentalInfoIsTuple ? PyTuple_Size(parentalInfoList) : PyList_Size(parentalInfoList);
parental_ratings.reserve(numberOfpInfoTypes);
for (int j = 0; j < numberOfpInfoTypes; ++j)
{
ePyObject parentalInfo = parentalInfoIsTuple ? PyTuple_GET_ITEM(parentalInfoList, j) : PyList_GET_ITEM(parentalInfoList, j);
if (!PyTuple_Check(parentalInfo) || PyTuple_Size(parentalInfo) != 2)
{
eDebug("[eEPGCache:import] parental rating must be a tuple of length 2, aborting");
return;
}
const char* country = getStringFromPython(PyTuple_GET_ITEM(parentalInfo, 0));
if (strlen(country) != 3)
{
eDebug("[eEPGCache:import] parental rating country code must be of length 3, aborting");
return;
}
eit_parental_rating p_rating;
memcpy(p_rating.country_code, country, 3);
u_char rating = (u_char) PyLong_AsUnsignedLongMask(PyTuple_GET_ITEM(parentalInfo, 1));
p_rating.rating = rating;
parental_ratings.push_back(p_rating);
}
} else {
eDebug("[eEPGCache:import] parental ratings must be a list or tuple of parental rating tuples, aborting");
}
}

Py_BEGIN_ALLOW_THREADS;
submitEventData(refs, start, duration, title, short_summary, long_description, event_type);
submitEventData(refs, start, duration, title, short_summary, long_description, event_types, parental_ratings, eventId);
Py_END_ALLOW_THREADS;
}
}
Expand Down
8 changes: 7 additions & 1 deletion lib/dvb/epgcache.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,11 @@ typedef std::tr1::unordered_map<uniqueEPGKey, EventCacheItem, hash_uniqueEPGKey,
typedef std::tr1::unordered_map<uniqueEPGKey, contentMap, hash_uniqueEPGKey, uniqueEPGKey::equal > contentMaps;
#endif

struct eit_parental_rating {
u_char country_code[3];
u_char rating;
};

#endif

class eEPGCache: public eMainloop, private eThread, public sigc::trackable
Expand Down Expand Up @@ -159,6 +164,7 @@ class eEPGCache: public eMainloop, private eThread, public sigc::trackable
void gotMessage(const Message &message);
void cleanLoop();
void submitEventData(const std::vector<int>& sids, const std::vector<eDVBChannelID>& chids, long start, long duration, const char* title, const char* short_summary, const char* long_description, char event_type, int event_id, int source);
void submitEventData(const std::vector<int>& sids, const std::vector<eDVBChannelID>& chids, long start, long duration, const char* title, const char* short_summary, const char* long_description, std::vector<uint8_t> event_types, std::vector<eit_parental_rating> parental_ratings, int event_id, int source);
void clearCompleteEPGCache();

eServiceReferenceDVB *m_timeQueryRef;
Expand Down Expand Up @@ -255,7 +261,7 @@ class eEPGCache: public eMainloop, private eThread, public sigc::trackable
void setEpgSources(unsigned int mask);
unsigned int getEpgSources();

void submitEventData(const std::vector<eServiceReferenceDVB>& serviceRefs, long start, long duration, const char* title, const char* short_summary, const char* long_description, char event_type);
void submitEventData(const std::vector<eServiceReferenceDVB>& serviceRefs, long start, long duration, const char* title, const char* short_summary, const char* long_description, std::vector<uint8_t> event_types, std::vector<eit_parental_rating> parental_ratings, uint16_t eventId=0);

void importEvents(SWIG_PYOBJECT(ePyObject) serviceReferences, SWIG_PYOBJECT(ePyObject) list);
void importEvent(SWIG_PYOBJECT(ePyObject) serviceReference, SWIG_PYOBJECT(ePyObject) list);
Expand Down
11 changes: 7 additions & 4 deletions lib/python/Components/ConfigList.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from skin import parameters, applySkinFactor, parseColor

from Components.ActionMap import HelpableActionMap, HelpableNumberActionMap
from Components.config import ConfigBoolean, ConfigElement, ConfigInteger, ConfigMacText, ConfigNothing, ConfigNumber, ConfigPassword, ConfigSelection, ConfigSequence, ConfigText, ACTIONKEY_0, ACTIONKEY_ASCII, ACTIONKEY_BACKSPACE, ACTIONKEY_DELETE, ACTIONKEY_ERASE, ACTIONKEY_FIRST, ACTIONKEY_LAST, ACTIONKEY_LEFT, ACTIONKEY_NUMBERS, ACTIONKEY_RIGHT, ACTIONKEY_SELECT, ACTIONKEY_TIMEOUT, ACTIONKEY_TOGGLE, configfile
from Components.config import ConfigBoolean, ConfigElement, ConfigInteger, ConfigMacText, ConfigNothing, ConfigNumber, ConfigSelection, ConfigSequence, ConfigText, ACTIONKEY_0, ACTIONKEY_ASCII, ACTIONKEY_BACKSPACE, ACTIONKEY_DELETE, ACTIONKEY_ERASE, ACTIONKEY_FIRST, ACTIONKEY_LAST, ACTIONKEY_LEFT, ACTIONKEY_NUMBERS, ACTIONKEY_RIGHT, ACTIONKEY_SELECT, ACTIONKEY_TIMEOUT, ACTIONKEY_TOGGLE, configfile
from Components.GUIComponent import GUIComponent
from Components.Pixmap import Pixmap
from Components.Sources.Boolean import Boolean
Expand Down Expand Up @@ -291,6 +291,9 @@ def handleInputHelpers(self):
self["editConfigActions"].setEnabled(True)
else:
self["editConfigActions"].setEnabled(False)
if isinstance(currConfig[1], (ConfigText, ConfigMacText)) and "HelpWindow" in self and currConfig[1].help_window and currConfig[1].help_window.instance is not None:
helpwindowpos = self["HelpWindow"].getPosition()
currConfig[1].help_window.instance.move(ePoint(helpwindowpos[0], helpwindowpos[1]))
if isinstance(currConfig[1], ConfigText):
self.showVirtualKeyBoard(True)
else:
Expand All @@ -312,11 +315,11 @@ def hideHelpWindow(self):
def displayHelp(self, state):
if "config" in self and "HelpWindow" in self and self["config"].getCurrent() is not None and len(self["config"].getCurrent()) > 1:
currConf = self["config"].getCurrent()[1]
if isinstance(currConf, (ConfigText, ConfigMacText, ConfigPassword)) and currConf.helpWindow is not None and currConf.helpWindow.instance is not None:
if isinstance(currConf, (ConfigText, ConfigMacText)) and currConf.help_window is not None and currConf.help_window.instance is not None:
if state:
currConf.helpWindow.show()
currConf.help_window.show()
else:
currConf.helpWindow.hide()
currConf.help_window.hide()

def keySelect(self):
if isinstance(self.getCurrentItem(), ConfigBoolean):
Expand Down
8 changes: 4 additions & 4 deletions lib/python/Components/Converter/EventName.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,10 @@ def __init__(self):
# If there is no matching country then the default ETSI should be selected.

countries = {
"ETSI": (ETSIClassifications(), lambda age: (_("bc%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/ETSI-na.png")),
"AUS": (AusClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/AUS-na.png")),
"GBR": (GBrClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/GBR-na.png")),
"ITA": (ItaClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/ITA-na.png"))
"ETSI": (ETSIClassifications(), lambda age: (_("bc%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/ETSI-na.png", 0x222222)),
"AUS": (AusClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/AUS-na.png", 0x222222)),
"GBR": (GBrClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/GBR-na.png", 0x222222)),
"ITA": (ItaClassifications(), lambda age: (_("BC%d") % age, _("Rating defined by broadcaster - %d") % age, "ratings/ITA-na.png", 0x222222))
}


Expand Down
31 changes: 18 additions & 13 deletions lib/python/Components/Renderer/Picon.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,38 @@
from ServiceReference import ServiceReference
from Components.config import config

class paths:
searchPaths = []
lastPiconPath = None
searchPaths = []
lastPiconPath = None


def initPiconPaths():
paths.searchPaths = []
global searchPaths
searchPaths = []
for mp in ('/usr/share/enigma2/', '/'):
onMountpointAdded(mp)
for part in harddiskmanager.getMountedPartitions():
onMountpointAdded(part.mountpoint)


def onMountpointAdded(mountpoint):
global searchPaths
try:
path = os.path.join(mountpoint, 'picon') + '/'
if os.path.isdir(path) and path not in paths.searchPaths:
if os.path.isdir(path) and path not in searchPaths:
for fn in os.listdir(path):
if fn.endswith('.png') or fn.endswith('.svg'):
print("[Picon] adding path:", path)
paths.searchPaths.append(path)
searchPaths.append(path)
break
except Exception as ex:
print("[Picon] Failed to investigate %s:" % mountpoint, ex)


def onMountpointRemoved(mountpoint):
global searchPaths
path = os.path.join(mountpoint, 'picon') + '/'
try:
paths.searchPaths.remove(path)
searchPaths.remove(path)
print("[Picon] removed path:", path)
except:
pass
Expand All @@ -51,17 +53,19 @@ def onPartitionChange(why, part):


def findPicon(serviceName):
if paths.lastPiconPath is not None:
global lastPiconPath
if lastPiconPath is not None:
for ext in ('.png', '.svg'):
pngname = paths.lastPiconPath + serviceName + ext
pngname = lastPiconPath + serviceName + ext
if pathExists(pngname):
return pngname
for path in paths.searchPaths:
global searchPaths
for path in searchPaths:
if pathExists(path):
for ext in ('.png', '.svg'):
pngname = path + serviceName + ext
if pathExists(pngname):
paths.lastPiconPath = path
lastPiconPath = path
return pngname
return ""

Expand Down Expand Up @@ -123,10 +127,11 @@ def __init__(self):

def addPath(self, value):
if pathExists(value):
global searchPaths
if not value.endswith('/'):
value += '/'
if value not in paths.searchPaths:
paths.searchPaths.append(value)
if value not in searchPaths:
searchPaths.append(value)

def applySkin(self, desktop, parent):
attribs = self.skinAttributes[:]
Expand Down
Loading