1 #include <lib/service/event.h>
2 #include <lib/base/estring.h>
3 #include <lib/base/encoding.h>
4 #include <lib/dvb/dvbtime.h>
5 #include <lib/dvb/idvb.h>
6 #include <dvbsi++/event_information_section.h>
7 #include <dvbsi++/short_event_descriptor.h>
8 #include <dvbsi++/extended_event_descriptor.h>
9 #include <dvbsi++/linkage_descriptor.h>
10 #include <dvbsi++/component_descriptor.h>
11 #include <dvbsi++/content_descriptor.h>
12 #include <dvbsi++/parental_rating_descriptor.h>
13 #include <dvbsi++/descriptor_tag.h>
14 #include <dvbsi++/pdc_descriptor.h>
16 #include <sys/types.h>
19 // static members / methods
20 std::string eServiceEvent::m_language = "---";
21 std::string eServiceEvent::m_language_alternative = "---";
23 ///////////////////////////
25 DEFINE_REF(eServiceEvent);
26 DEFINE_REF(eComponentData);
27 DEFINE_REF(eGenreData);
28 DEFINE_REF(eParentalData);
30 /* search for the presence of language from given EIT event descriptors*/
31 bool eServiceEvent::loadLanguage(Event *evt, const std::string &lang, int tsidonid)
34 std::string language = lang;
35 for (DescriptorConstIterator desc = evt->getDescriptors()->begin(); desc != evt->getDescriptors()->end(); ++desc)
37 switch ((*desc)->getTag())
39 case LINKAGE_DESCRIPTOR:
40 m_linkage_services.clear();
42 case SHORT_EVENT_DESCRIPTOR:
44 const ShortEventDescriptor *sed = (ShortEventDescriptor*)*desc;
45 std::string cc = sed->getIso639LanguageCode();
46 std::transform(cc.begin(), cc.end(), cc.begin(), tolower);
47 int table=encodingHandler.getCountryCodeDefaultMapping(cc);
48 if (language == "---" || language.find(cc) != std::string::npos)
50 /* stick to this language, avoid merging or mixing descriptors of different languages */
52 m_event_name += replace_all(replace_all(convertDVBUTF8(sed->getEventName(), table, tsidonid), "\n", " ",table), "\t", " ",table);
53 m_short_description += convertDVBUTF8(sed->getText(), table, tsidonid);
58 case EXTENDED_EVENT_DESCRIPTOR:
60 const ExtendedEventDescriptor *eed = (ExtendedEventDescriptor*)*desc;
61 std::string cc = eed->getIso639LanguageCode();
62 std::transform(cc.begin(), cc.end(), cc.begin(), tolower);
63 int table=encodingHandler.getCountryCodeDefaultMapping(cc);
64 if (language == "---" || language.find(cc) != std::string::npos)
66 /* stick to this language, avoid merging or mixing descriptors of different languages */
69 * Bit of a hack, some providers put the event description partly in the short descriptor,
70 * and the remainder in extended event descriptors.
71 * In that case, we cannot really treat short/extended description as separate descriptions.
72 * Unfortunately we cannot recognise this, but we'll use the length of the short description
73 * to guess whether we should concatenate both descriptions (without any spaces)
75 if (eed->getText().empty() && m_short_description.size() >= 180)
77 m_extended_description = m_short_description;
78 m_short_description = "";
80 if (table == 0) // Two Char Mapping EED must be processed in one pass
82 m_tmp_extended_description += eed->getText();
83 if (eed->getDescriptorNumber() == eed->getLastDescriptorNumber())
85 m_extended_description += convertDVBUTF8(m_tmp_extended_description, table, tsidonid);
90 m_extended_description += convertDVBUTF8(eed->getText(), table, tsidonid);
95 const ExtendedEventList *itemlist = eed->getItems();
96 for (ExtendedEventConstIterator it = itemlist->begin(); it != itemlist->end(); ++it)
98 m_extended_description += '\n';
99 m_extended_description += convertDVBUTF8((*it)->getItemDescription());
100 m_extended_description += ' ';
101 m_extended_description += convertDVBUTF8((*it)->getItem());
112 for (DescriptorConstIterator desc = evt->getDescriptors()->begin(); desc != evt->getDescriptors()->end(); ++desc)
114 switch ((*desc)->getTag())
116 case COMPONENT_DESCRIPTOR:
118 const ComponentDescriptor *cp = (ComponentDescriptor*)*desc;
120 data.m_streamContent = cp->getStreamContent();
121 data.m_componentType = cp->getComponentType();
122 data.m_componentTag = cp->getComponentTag();
123 data.m_iso639LanguageCode = cp->getIso639LanguageCode();
124 std::transform(data.m_iso639LanguageCode.begin(), data.m_iso639LanguageCode.end(), data.m_iso639LanguageCode.begin(), tolower);
125 int table=encodingHandler.getCountryCodeDefaultMapping(data.m_iso639LanguageCode);
126 data.m_text = convertDVBUTF8(cp->getText(),table,tsidonid);
127 m_component_data.push_back(data);
130 case LINKAGE_DESCRIPTOR:
132 const LinkageDescriptor *ld = (LinkageDescriptor*)*desc;
133 if ( ld->getLinkageType() == 0xB0 )
135 eServiceReferenceDVB dvb_ref;
136 dvb_ref.type = eServiceReference::idDVB;
137 dvb_ref.setServiceType(1);
138 dvb_ref.setTransportStreamID(ld->getTransportStreamId());
139 dvb_ref.setOriginalNetworkID(ld->getOriginalNetworkId());
140 dvb_ref.setServiceID(ld->getServiceId());
141 const PrivateDataByteVector *privateData = ld->getPrivateDataBytes();
142 dvb_ref.name = convertDVBUTF8((const unsigned char*)&((*privateData)[0]), privateData->size(), 1, tsidonid);
143 m_linkage_services.push_back(dvb_ref);
147 case CONTENT_DESCRIPTOR:
149 const ContentDescriptor *cd = (ContentDescriptor *)*desc;
150 const ContentClassificationList *con = cd->getClassifications();
151 for (ContentClassificationConstIterator it = con->begin(); it != con->end(); ++it)
154 data.m_level1 = (*it)->getContentNibbleLevel1();
155 data.m_level2 = (*it)->getContentNibbleLevel2();
156 data.m_user1 = (*it)->getUserNibble1();
157 data.m_user2 = (*it)->getUserNibble2();
158 m_genres.push_back(data);
162 case PARENTAL_RATING_DESCRIPTOR:
164 const ParentalRatingDescriptor *prd = (ParentalRatingDescriptor *)*desc;
165 const ParentalRatingList *par = prd->getParentalRatings();
166 for (ParentalRatingConstIterator it = par->begin(); it != par->end(); ++it)
170 data.m_country_code = (*it)->getCountryCode();
171 data.m_rating = (*it)->getRating();
172 m_ratings.push_back(data);
178 const PdcDescriptor *pdcd = (PdcDescriptor *)*desc;
179 m_pdc_pil = pdcd->getProgrammeIdentificationLabel();
185 if ( m_extended_description.find(m_short_description) == 0 )
186 m_short_description="";
190 RESULT eServiceEvent::parseFrom(Event *evt, int tsidonid)
192 m_begin = parseDVBtime(evt->getStartTimeMjd(), evt->getStartTimeBcd());
193 m_event_id = evt->getEventId();
194 uint32_t duration = evt->getDuration();
195 m_duration = fromBCD(duration>>16)*3600+fromBCD(duration>>8)*60+fromBCD(duration);
196 uint8_t running_status = evt->getRunningStatus();
197 m_running_status = running_status;
198 if (m_language != "---" && loadLanguage(evt, m_language, tsidonid))
200 if (m_language_alternative != "---" && loadLanguage(evt, m_language_alternative, tsidonid))
202 if (loadLanguage(evt, "---", tsidonid))
207 RESULT eServiceEvent::parseFrom(const std::string &filename, int tsidonid)
209 if (!filename.empty())
211 int fd = ::open( filename.c_str(), O_RDONLY );
215 int rd = ::read(fd, buf, 4096);
217 if ( rd > 12 /*EIT_LOOP_SIZE*/ )
220 parseFrom(&ev, tsidonid);
228 std::string eServiceEvent::getBeginTimeString() const
231 localtime_r(&m_begin, &t);
233 snprintf(tmp, 13, "%02d.%02d, %02d:%02d",
234 t.tm_mday, t.tm_mon+1,
235 t.tm_hour, t.tm_min);
236 return std::string(tmp, 12);
239 RESULT eServiceEvent::getGenreData(ePtr<eGenreData> &dest) const
241 std::list<eGenreData>::const_iterator it = m_genres.begin();
242 for(;it != m_genres.end(); ++it) {
243 dest = new eGenreData(*it);
244 // for now just return the first item on the list
251 PyObject *eServiceEvent::getGenreData() const
253 ePyObject ret = PyList_New(m_genres.size());
255 for (std::list<eGenreData>::const_iterator it(m_genres.begin()); it != m_genres.end(); ++it)
257 ePyObject tuple = PyTuple_New(4);
258 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(it->getLevel1()));
259 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->getLevel2()));
260 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->getUser1()));
261 PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(it->getUser2()));
262 PyList_SET_ITEM(ret, cnt++, tuple);
267 RESULT eServiceEvent::getParentalData(ePtr<eParentalData> &dest) const
269 std::list<eParentalData>::const_iterator it = m_ratings.begin();
270 for(;it != m_ratings.end(); ++it) {
271 dest = new eParentalData(*it);
272 // for now just return the first item on the list
279 PyObject *eServiceEvent::getParentalData() const
281 ePyObject ret = PyList_New(m_ratings.size());
283 for (std::list<eParentalData>::const_iterator it(m_ratings.begin()); it != m_ratings.end(); ++it)
285 ePyObject tuple = PyTuple_New(2);
286 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(it->getCountryCode().c_str()));
287 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->getRating()));
288 PyList_SET_ITEM(ret, cnt++, tuple);
293 RESULT eServiceEvent::getComponentData(ePtr<eComponentData> &dest, int tagnum) const
295 std::list<eComponentData>::const_iterator it =
296 m_component_data.begin();
297 for(;it != m_component_data.end(); ++it)
299 if ( it->m_componentTag == tagnum )
301 dest=new eComponentData(*it);
309 PyObject *eServiceEvent::getComponentData() const
311 ePyObject ret = PyList_New(m_component_data.size());
313 for (std::list<eComponentData>::const_iterator it(m_component_data.begin()); it != m_component_data.end(); ++it)
315 ePyObject tuple = PyTuple_New(5);
316 PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(it->m_componentTag));
317 PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(it->m_componentType));
318 PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(it->m_streamContent));
319 PyTuple_SET_ITEM(tuple, 3, PyString_FromString(it->m_iso639LanguageCode.c_str()));
320 PyTuple_SET_ITEM(tuple, 4, PyString_FromString(it->m_text.c_str()));
321 PyList_SET_ITEM(ret, cnt++, tuple);
326 RESULT eServiceEvent::getLinkageService(eServiceReference &service, eServiceReference &parent, int num) const
328 std::list<eServiceReference>::const_iterator it =
329 m_linkage_services.begin();
330 while( it != m_linkage_services.end() && num-- )
332 if ( it != m_linkage_services.end() )
335 eServiceReferenceDVB &subservice = (eServiceReferenceDVB&) service;
336 eServiceReferenceDVB ¤t = (eServiceReferenceDVB&) parent;
337 subservice.setDVBNamespace(current.getDVBNamespace());
338 if ( current.getParentTransportStreamID().get() )
340 subservice.setParentTransportStreamID( current.getParentTransportStreamID() );
341 subservice.setParentServiceID( current.getParentServiceID() );
345 subservice.setParentTransportStreamID( current.getTransportStreamID() );
346 subservice.setParentServiceID( current.getServiceID() );
348 if ( subservice.getParentTransportStreamID() == subservice.getTransportStreamID() &&
349 subservice.getParentServiceID() == subservice.getServiceID() )
351 subservice.setParentTransportStreamID( eTransportStreamID(0) );
352 subservice.setParentServiceID( eServiceID(0) );
356 service.type = eServiceReference::idInvalid;
360 DEFINE_REF(eDebugClass);