trunk 20080912
[gitenigma.git] / include / lib / dvb / epgcache.h
blobd632224d7435ba4d2c299c42e9d2087cc80c48ae
1 #ifndef __epgcache_h_
2 #define __epgcache_h_
4 #include <vector>
5 #include <list>
6 #include <ext/hash_map>
7 #include <ext/hash_set>
9 #include <errno.h>
11 #include "si.h"
12 #ifdef ENABLE_MHW_EPG
13 #include "lowlevel/mhw.h"
14 #endif
15 #include "dvb.h"
16 #include "edvb.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)
27 class eventData;
28 class eServiceReferenceDVB;
30 struct uniqueEPGKey
32 int sid, onid, tsid;
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 )
39 uniqueEPGKey()
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;
51 operator bool() const
53 return !(sid == -1 && onid == -1 && tsid == -1);
55 bool operator==(const uniqueEPGKey &a) const
57 return !memcmp( &sid, &a.sid, sizeof(int)*3);
59 struct equal
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 >
95 #endif
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>
104 #endif
105 #endif
107 class eventData
109 friend class eEPGCache;
110 private:
111 __u8* EITdata;
112 __u8 ByteSize;
113 static descriptorMap descriptors;
114 static __u8 data[4108];
115 public:
116 __u8 type;
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);
121 ~eventData();
122 const eit_event_struct* get() const;
123 operator const eit_event_struct*() const
125 return get();
127 int getEventID()
129 return (EITdata[0] << 8) | EITdata[1];
131 time_t getStartTime()
133 return parseDVBtime(EITdata[2], EITdata[3], EITdata[4], EITdata[5], EITdata[6]);
135 int getDuration()
137 return fromBCD(EITdata[7])*3600+fromBCD(EITdata[8])*60+fromBCD(EITdata[9]);
141 class eEPGCache;
143 class eSchedule: public eSection
145 friend class eEPGCache;
146 inline int sectionRead(__u8 *data);
147 inline void sectionFinish(int);
148 eSchedule()
150 inline void start()
151 { // 0x50 .. 0x5F
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);
161 eScheduleOther()
163 inline void start()
164 { // 0x60 .. 0x6F
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;
179 void cleanup();
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);
188 int start()
190 return setFilter( 0xD3, 0x91, -1, -1, SECREAD_NOTIMEOUT, 0xFF );
192 eScheduleMhw() {}
194 #endif
196 class eNowNext: public eSection
198 friend class eEPGCache;
199 inline int sectionRead(__u8 *data);
200 inline void sectionFinish(int);
201 eNowNext()
203 inline void start()
204 { // 0x4E, 0x4F
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;
215 ePrivateContent()
217 void stop()
219 if ( pid )
221 abort();
222 pid = 0;
225 void start( int pid )
227 if ( pid != this->pid )
228 start_filter(pid,-1);
230 void restart()
232 if ( pid )
233 start_filter(pid);
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);
242 #endif
244 class eEPGCache: public eMainloop, private eThread, public Object
246 public:
247 #ifdef ENABLE_MHW_EPG
248 friend class eScheduleMhw;
249 #endif
250 #ifdef ENABLE_PRIVATE_EPG
251 friend class ePrivateContent;
252 #endif
253 enum {
254 #ifdef ENABLE_PRIVATE_EPG
255 PRIVATE=0,
256 #endif
257 NOWNEXT=1,
258 SCHEDULE=2,
259 SCHEDULE_OTHER=4
260 #ifdef ENABLE_MHW_EPG
261 ,SCHEDULE_MHW=8
262 #endif
264 friend class eSchedule;
265 friend class eScheduleOther;
266 friend class eNowNext;
267 struct Message
269 enum
271 flush,
272 enterService,
273 leaveService,
274 pause,
275 restart,
276 updated,
277 isavail,
278 quit,
279 timeChanged,
280 content_pid,
281 save,
282 load
284 int type;
285 uniqueEPGKey service;
286 union {
287 int err;
288 int pid;
289 time_t time;
290 bool avail;
292 Message()
293 :type(0), time(0) {}
294 Message(int type)
295 :type(type) {}
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;
306 private:
307 // needed for caching current service until the thread has started
308 // (valid transponder time received)
309 eServiceReferenceDVB cached_service;
310 int cached_err;
312 static pthread_mutex_t cache_lock;
313 uniqueEPGKey current_service;
314 int paused;
315 int isLoading;
317 int state;
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;
323 eventCache eventDB;
324 updateMap serviceLastUpdated;
325 tmpMap temp;
326 nvodMap NVOD;
327 tidMap seenSections[3], calcedSections[3];
328 eSchedule scheduleReader;
329 eScheduleOther scheduleOtherReader;
330 #ifdef ENABLE_MHW_EPG
331 eScheduleMhw scheduleMhwReader;
332 #endif
333 eNowNext nownextReader;
334 #ifdef ENABLE_PRIVATE_EPG
335 contentMaps content_time_tables;
336 ePrivateContent contentReader;
337 void setContentPid(int pid);
338 #endif
339 eTimer CleanTimer;
340 eTimer zapTimer;
341 eTimer abortTimer;
342 bool finishEPG();
343 void abortNonAvail();
344 void flushEPG(const uniqueEPGKey & s=uniqueEPGKey());
345 void startEPG();
347 void changedService(const uniqueEPGKey &, int);
348 void abortEPG();
350 // called from other thread context !!
351 void enterService(const eServiceReferenceDVB &, int);
352 void leaveService(const eServiceReferenceDVB &);
354 void cleanLoop();
355 void pauseEPG();
356 void restartEPG();
357 void thread();
358 void gotMessage(const Message &message);
359 void timeUpdated();
360 void save();
361 void load();
362 public:
363 eEPGCache();
364 ~eEPGCache();
365 static eEPGCache *getInstance() { return instance; }
367 inline void Lock();
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);
387 else
388 return 0;
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);
396 else
397 return 0;
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);
405 else
406 return 0;
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;
431 if (e->haveData)
432 e->finishEPG();
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;
443 if (e->haveData)
444 e->finishEPG();
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;
455 if (e->haveData)
456 e->finishEPG();
460 inline void eEPGCache::Lock()
462 pthread_mutex_lock(&cache_lock);
465 inline void eEPGCache::Unlock()
467 pthread_mutex_unlock(&cache_lock);
470 #endif