6 #include <ext/hash_map>
7 #include <ext/hash_set>
13 #include "lowlevel/mhw.h"
17 #include <lib/base/ebase.h>
18 #include <lib/base/thread.h>
19 #include <lib/base/message.h>
21 #define CLEAN_INTERVAL 60000 // 1 min
22 #define UPDATE_INTERVAL 3600000 // 60 min
23 #define ZAP_DELAY 2000 // 2 sek
25 #define HILO(x) (x##_hi << 8 | x##_lo)
28 class eServiceReferenceDVB
;
33 uniqueEPGKey( const eServiceReferenceDVB
&ref
)
34 :sid( ref
.type
!= eServiceReference::idInvalid
? ref
.getServiceID().get() : -1 )
35 ,onid( ref
.type
!= eServiceReference::idInvalid
? ref
.getOriginalNetworkID().get() : -1 )
36 ,tsid( ref
.type
!= eServiceReference::idInvalid
? ref
.getTransportStreamID().get() : -1 )
40 :sid(-1), onid(-1), tsid(-1)
43 uniqueEPGKey( int sid
, int onid
, int tsid
)
44 :sid(sid
), onid(onid
), tsid(tsid
)
47 bool operator <(const uniqueEPGKey
&a
) const
49 return memcmp( &sid
, &a
.sid
, sizeof(int)*3)<0;
53 return !(sid
== -1 && onid
== -1 && tsid
== -1);
55 bool operator==(const uniqueEPGKey
&a
) const
57 return !memcmp( &sid
, &a
.sid
, sizeof(int)*3);
61 bool operator()(const uniqueEPGKey
&a
, const uniqueEPGKey
&b
) const
63 return !memcmp( &a
.sid
, &b
.sid
, sizeof(int)*3);
68 //eventMap is sorted by event_id
69 #define eventMap std::map<__u16, eventData*>
70 //timeMap is sorted by beginTime
71 #define timeMap std::map<time_t, eventData*>
73 #define tmpMap std::map<uniqueEPGKey, std::pair<time_t, int> >
74 #define nvodMap std::map<uniqueEPGKey, std::list<NVODReferenceEntry> >
76 struct hash_uniqueEPGKey
78 inline size_t operator()( const uniqueEPGKey
&x
) const
80 return (x
.tsid
<< 16) | x
.sid
;
84 #define tidMap std::set<__u32>
85 #define descriptorPair std::pair<__u16,__u8*>
87 #if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || __GNUC__ == 4 ) // check if gcc version >= 3.1
88 #define eventCache __gnu_cxx::hash_map<uniqueEPGKey, std::pair<eventMap, timeMap>, hash_uniqueEPGKey, uniqueEPGKey::equal>
89 #define updateMap __gnu_cxx::hash_map<uniqueEPGKey, time_t, hash_uniqueEPGKey, uniqueEPGKey::equal >
90 #define descriptorMap __gnu_cxx::hash_map<__u32, descriptorPair >
91 #ifdef ENABLE_PRIVATE_EPG
92 #define contentTimeMap __gnu_cxx::hash_map<time_t, std::pair<time_t, __u16> >
93 #define contentMap __gnu_cxx::hash_map<int, contentTimeMap >
94 #define contentMaps __gnu_cxx::hash_map<uniqueEPGKey, contentMap, hash_uniqueEPGKey, uniqueEPGKey::equal >
96 #else // for older gcc use following
97 #define eventCache std::hash_map<uniqueEPGKey, std::pair<eventMap, timeMap>, hash_uniqueEPGKey, uniqueEPGKey::equal >
98 #define updateMap std::hash_map<uniqueEPGKey, time_t, hash_uniqueEPGKey, uniqueEPGKey::equal >
99 #define descriptorMap std::hash_map<__u32, descriptorPair, hash_descriptor >
100 #ifdef ENABLE_PRIVATE_EPG
101 #define contentTimeMap std::hash_map<time_t, std::pair<time_t, __u16> >
102 #define contentMap std::hash_map<int, contentTimeMap >
103 #define contentMaps std::hash_map<uniqueEPGKey, contentMap, hash_uniqueEPGKey, uniqueEPGKey::equal>
109 friend class eEPGCache
;
113 static descriptorMap descriptors
;
114 static __u8 data
[4108];
117 static int CacheSize
;
118 static void load(FILE *);
119 static void save(FILE *);
120 eventData(const eit_event_struct
* e
, int size
, int type
);
122 const eit_event_struct
* get() const;
123 operator const eit_event_struct
*() const
129 return (EITdata
[0] << 8) | EITdata
[1];
131 time_t getStartTime()
133 return parseDVBtime(EITdata
[2], EITdata
[3], EITdata
[4], EITdata
[5], EITdata
[6]);
137 return fromBCD(EITdata
[7])*3600+fromBCD(EITdata
[8])*60+fromBCD(EITdata
[9]);
143 class eSchedule
: public eSection
145 friend class eEPGCache
;
146 inline int sectionRead(__u8
*data
);
147 inline void sectionFinish(int);
152 setFilter(0x12, 0x50, -1, -1, SECREAD_CRC
|SECREAD_NOTIMEOUT
, 0xF0);
156 class eScheduleOther
: public eSection
158 friend class eEPGCache
;
159 inline int sectionRead(__u8
*data
);
160 inline void sectionFinish(int);
165 setFilter(0x12, 0x60, -1, -1, SECREAD_CRC
|SECREAD_NOTIMEOUT
, 0xF0);
169 #ifdef ENABLE_MHW_EPG
170 class eScheduleMhw
: public eSection
172 friend class eEPGCache
;
173 std::vector
<mhw_channel_name_t
> channels
;
174 std::map
<__u8
, mhw_theme_name_t
> themes
;
175 std::map
<__u32
, mhw_title_t
> titles
;
176 std::map
<__u32
, __u32
> program_ids
;
177 time_t tnew_summary_read
;
180 __u8
*delimitName( __u8
*in
, __u8
*out
, int len_in
);
181 void eScheduleMhw::timeMHW2DVB( u_char hours
, u_char minutes
, u_char
*return_time
);
182 void eScheduleMhw::timeMHW2DVB( int minutes
, u_char
*return_time
);
183 void eScheduleMhw::timeMHW2DVB( u_char day
, u_char hours
, u_char minutes
, u_char
*return_time
);
184 void eScheduleMhw::storeTitle(std::map
<__u32
, mhw_title_t
>::iterator itTitle
,
185 eString sumText
, __u8
*data
);
186 int sectionRead(__u8
*data
);
187 void sectionFinish(int);
190 return setFilter( 0xD3, 0x91, -1, -1, SECREAD_NOTIMEOUT
, 0xFF );
196 class eNowNext
: public eSection
198 friend class eEPGCache
;
199 inline int sectionRead(__u8
*data
);
200 inline void sectionFinish(int);
205 setFilter(0x12, 0x4E, -1, -1, SECREAD_CRC
|SECREAD_NOTIMEOUT
, 0xFE);
209 #ifdef ENABLE_PRIVATE_EPG
210 class ePrivateContent
: public eSection
212 friend class eEPGCache
;
213 int sectionRead(__u8
*data
);
214 std::set
<__u8
> seenSections
;
225 void start( int pid
)
227 if ( pid
!= this->pid
)
228 start_filter(pid
,-1);
235 void start_filter(int pid
, int version
=-1)
237 eDebug("[EPGC] start private content filter pid %04x, version %d", pid
, version
);
238 seenSections
.clear();
239 setFilter(pid
, 0xA0, -1, version
, SECREAD_CRC
|SECREAD_NOTIMEOUT
, 0xFF);
244 class eEPGCache
: public eMainloop
, private eThread
, public Object
247 #ifdef ENABLE_MHW_EPG
248 friend class eScheduleMhw
;
250 #ifdef ENABLE_PRIVATE_EPG
251 friend class ePrivateContent
;
254 #ifdef ENABLE_PRIVATE_EPG
260 #ifdef ENABLE_MHW_EPG
264 friend class eSchedule
;
265 friend class eScheduleOther
;
266 friend class eNowNext
;
285 uniqueEPGKey service
;
296 Message(int type
, int pid
)
297 :type(type
), pid(pid
) {}
298 Message(int type
, bool b
)
299 :type(type
), avail(b
) {}
300 Message(int type
, const eServiceReferenceDVB
& service
, int err
=0)
301 :type(type
), service(service
), err(err
) {}
302 Message(int type
, time_t time
)
303 :type(type
), time(time
) {}
305 eFixedMessagePump
<Message
> messages
;
307 // needed for caching current service until the thread has started
308 // (valid transponder time received)
309 eServiceReferenceDVB cached_service
;
312 static pthread_mutex_t cache_lock
;
313 uniqueEPGKey current_service
;
318 __u8 isRunning
, firstStart
, haveData
;
319 bool FixOverlapping(std::pair
<eventMap
,timeMap
> &, time_t, int, const timeMap::iterator
&, const uniqueEPGKey
&);
320 int sectionRead(__u8
*data
, int source
);
321 static eEPGCache
*instance
;
324 updateMap serviceLastUpdated
;
327 tidMap seenSections
[3], calcedSections
[3];
328 eSchedule scheduleReader
;
329 eScheduleOther scheduleOtherReader
;
330 #ifdef ENABLE_MHW_EPG
331 eScheduleMhw scheduleMhwReader
;
333 eNowNext nownextReader
;
334 #ifdef ENABLE_PRIVATE_EPG
335 contentMaps content_time_tables
;
336 ePrivateContent contentReader
;
337 void setContentPid(int pid
);
343 void abortNonAvail();
344 void flushEPG(const uniqueEPGKey
& s
=uniqueEPGKey());
347 void changedService(const uniqueEPGKey
&, int);
350 // called from other thread context !!
351 void enterService(const eServiceReferenceDVB
&, int);
352 void leaveService(const eServiceReferenceDVB
&);
358 void gotMessage(const Message
&message
);
365 static eEPGCache
*getInstance() { return instance
; }
368 inline void Unlock();
370 const eventMap
* getEventMap(const eServiceReferenceDVB
&service
);
371 const timeMap
* getTimeMap(const eServiceReferenceDVB
&service
);
372 tmpMap
* getUpdatedMap() { return &temp
; }
373 const std::list
<NVODReferenceEntry
>* getNVODRefList(const eServiceReferenceDVB
&service
);
375 EITEvent
*lookupEvent(const eServiceReferenceDVB
&service
, int event_id
, bool plain
=false );
376 EITEvent
*lookupEvent(const eServiceReferenceDVB
&service
, time_t=0, bool plain
=false );
378 Signal1
<void, bool> EPGAvail
;
379 Signal0
<void> EPGUpdated
;
382 inline const std::list
<NVODReferenceEntry
>* eEPGCache::getNVODRefList(const eServiceReferenceDVB
&service
)
384 nvodMap::iterator It
= NVOD
.find( service
);
385 if ( It
!= NVOD
.end() && It
->second
.size() )
386 return &(It
->second
);
391 inline const eventMap
* eEPGCache::getEventMap(const eServiceReferenceDVB
&service
)
393 eventCache::iterator It
= eventDB
.find( service
);
394 if ( It
!= eventDB
.end() && It
->second
.first
.size() )
395 return &(It
->second
.first
);
400 inline const timeMap
* eEPGCache::getTimeMap(const eServiceReferenceDVB
&service
)
402 eventCache::iterator It
= eventDB
.find( service
);
403 if ( It
!= eventDB
.end() && It
->second
.second
.size() )
404 return &(It
->second
.second
);
409 inline int eNowNext::sectionRead(__u8
*data
)
411 return eEPGCache::getInstance()->sectionRead(data
, eEPGCache::NOWNEXT
);
414 inline int eSchedule::sectionRead(__u8
*data
)
416 return eEPGCache::getInstance()->sectionRead(data
, eEPGCache::SCHEDULE
);
419 inline int eScheduleOther::sectionRead(__u8
*data
)
421 return eEPGCache::getInstance()->sectionRead(data
, eEPGCache::SCHEDULE_OTHER
);
424 inline void eSchedule::sectionFinish(int err
)
426 eEPGCache
*e
= eEPGCache::getInstance();
427 if ( (e
->isRunning
& eEPGCache::SCHEDULE
) && (err
== -ETIMEDOUT
|| err
== -ECANCELED
) )
429 eDebug("[EPGC] stop schedule");
430 e
->isRunning
&= ~eEPGCache::SCHEDULE
;
436 inline void eScheduleOther::sectionFinish(int err
)
438 eEPGCache
*e
= eEPGCache::getInstance();
439 if ( (e
->isRunning
& eEPGCache::SCHEDULE_OTHER
) && (err
== -ETIMEDOUT
|| err
== -ECANCELED
) )
441 eDebug("[EPGC] stop schedule other");
442 e
->isRunning
&= ~eEPGCache::SCHEDULE_OTHER
;
448 inline void eNowNext::sectionFinish(int err
)
450 eEPGCache
*e
= eEPGCache::getInstance();
451 if ( (e
->isRunning
& eEPGCache::NOWNEXT
) && (err
== -ETIMEDOUT
|| err
== -ECANCELED
) )
453 eDebug("[EPGC] stop nownext");
454 e
->isRunning
&= ~eEPGCache::NOWNEXT
;
460 inline void eEPGCache::Lock()
462 pthread_mutex_lock(&cache_lock
);
465 inline void eEPGCache::Unlock()
467 pthread_mutex_unlock(&cache_lock
);