8 #include <ext/hash_map>
10 // check if gcc version >= 3.4
11 #if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ == 4 )
13 #include <ext/stl_hash_fun.h>
17 #include <lib/dvb/eit.h>
18 #include <lib/dvb/lowlevel/eit.h>
19 #include <lib/dvb/idvb.h>
20 #include <lib/dvb/demux.h>
21 #include <lib/dvb/dvbtime.h>
22 #include <lib/base/ebase.h>
23 #include <lib/base/thread.h>
24 #include <lib/base/message.h>
26 #define CLEAN_INTERVAL 60000 // 1 min
27 #define UPDATE_INTERVAL 3600000 // 60 min
28 #define ZAP_DELAY 2000 // 2 sek
30 #define HILO(x) (x##_hi << 8 | x##_lo)
33 class eServiceReferenceDVB;
38 uniqueEPGKey( const eServiceReferenceDVB &ref )
39 :sid( ref.type != eServiceReference::idInvalid ? ref.getServiceID().get() : -1 )
40 ,onid( ref.type != eServiceReference::idInvalid ? ref.getOriginalNetworkID().get() : -1 )
41 ,tsid( ref.type != eServiceReference::idInvalid ? ref.getTransportStreamID().get() : -1 )
45 :sid(-1), onid(-1), tsid(-1)
48 uniqueEPGKey( int sid, int onid, int tsid )
49 :sid(sid), onid(onid), tsid(tsid)
52 bool operator <(const uniqueEPGKey &a) const
54 return memcmp( &sid, &a.sid, sizeof(int)*3)<0;
58 return !(sid == -1 && onid == -1 && tsid == -1);
60 bool operator==(const uniqueEPGKey &a) const
62 return !memcmp( &sid, &a.sid, sizeof(int)*3);
66 bool operator()(const uniqueEPGKey &a, const uniqueEPGKey &b) const
68 return !memcmp( &a.sid, &b.sid, sizeof(int)*3);
73 //eventMap is sorted by event_id
74 #define eventMap std::map<__u16, eventData*>
75 //timeMap is sorted by beginTime
76 #define timeMap std::map<time_t, eventData*>
78 #define tmpMap std::map<uniqueEPGKey, std::pair<time_t, int> >
80 #if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || __GNUC__ == 4 ) // check if gcc version >= 3.1
81 #define eventCache __gnu_cxx::hash_map<uniqueEPGKey, std::pair<eventMap, timeMap>, __gnu_cxx::hash<uniqueEPGKey>, uniqueEPGKey::equal>
82 #define updateMap __gnu_cxx::hash_map<uniqueEPGKey, time_t, __gnu_cxx::hash<uniqueEPGKey>, uniqueEPGKey::equal >
84 #else // for older gcc use following
85 #define eventCache std::hash_map<uniqueEPGKey, std::pair<eventMap, timeMap>, std::hash<uniqueEPGKey>, uniqueEPGKey::equal >
86 #define updateMap std::hash_map<uniqueEPGKey, time_t, std::hash<uniqueEPGKey>, uniqueEPGKey::equal >
90 template<> struct hash<uniqueEPGKey>
92 inline size_t operator()( const uniqueEPGKey &x) const
103 friend class eEPGCache;
109 static int CacheSize;
110 eventData(const eit_event_struct* e, int size, int type)
111 :ByteSize(size), type(type)
114 EITdata = new __u8[size];
116 memcpy(EITdata, (__u8*) e, size);
123 operator const eit_event_struct*() const
125 return (const eit_event_struct*) EITdata;
127 const eit_event_struct* get() const
129 return (const eit_event_struct*) EITdata;
133 return HILO( ((const eit_event_struct*) EITdata)->event_id );
135 time_t getStartTime()
138 EITdata[2], EITdata[3],
139 EITdata[4], EITdata[5], EITdata[6]);
143 #include <lib/base/smartptr.h>
146 class eEPGCache: public eMainloop, private eThread, public Object
148 DECLARE_REF(eEPGCache)
151 enum {NOWNEXT, SCHEDULE, SCHEDULE_OTHER};
168 uniqueEPGKey service;
178 Message(int type, bool b)
179 :type(type), avail(b) {}
180 Message(int type, const eServiceReferenceDVB& service, int err=0)
181 :type(type), service(service), err(err) {}
182 Message(int type, time_t time)
183 :type(type), time(time) {}
185 eFixedMessagePump<Message> messages;
186 eFixedMessagePump<Message> back_messages;
188 static pthread_mutex_t cache_lock;
189 eServiceReferenceDVB next_service;
190 uniqueEPGKey current_service;
194 __u8 isRunning, haveData;
196 ePtr<iDVBChannel> m_currentChannel;
197 ePtr<eConnection> m_NowNextConn, m_ScheduleConn, m_ScheduleOtherConn;
198 ePtr<iDVBSectionReader> m_NowNextReader, m_ScheduleReader, m_ScheduleOtherReader;
200 int sectionRead(const __u8 *data, int source);
201 void readNowNextData(const __u8 *data);
202 void readScheduleData(const __u8 *data);
203 void readScheduleOtherData(const __u8 *data);
205 static eEPGCache *instance;
208 updateMap serviceLastUpdated;
214 void abortNonAvail();
215 void flushEPG(const uniqueEPGKey & s=uniqueEPGKey());
218 void changedService(const uniqueEPGKey &);
225 void gotMessage(const Message &message);
226 void gotBackMessage(const Message &message);
230 void leaveChannel(iDVBChannel *);
233 static RESULT getInstance(ePtr<eEPGCache> &ptr);
234 // called from other thread context !!
235 void startCache(const eServiceReferenceDVB &);
236 Event *lookupEvent(const eServiceReferenceDVB &service, int event_id, bool plain=false );
237 Event *lookupEvent(const eServiceReferenceDVB &service, time_t=0, bool plain=false );
243 inline void Unlock();
245 const eventMap* getEventMap(const eServiceReferenceDVB &service);
246 const timeMap* getTimeMap(const eServiceReferenceDVB &service);
247 tmpMap* getUpdatedMap() { return &temp; }
249 Signal1<void, bool> EPGAvail;
250 Signal0<void> EPGUpdated;
254 TEMPLATE_TYPEDEF(ePtr<eEPGCache>,eEPGCachePtr);
256 inline const eventMap* eEPGCache::getEventMap(const eServiceReferenceDVB &service)
258 eventCache::iterator It = eventDB.find( service );
259 if ( It != eventDB.end() && It->second.first.size() )
260 return &(It->second.first);
265 inline const timeMap* eEPGCache::getTimeMap(const eServiceReferenceDVB &service)
267 eventCache::iterator It = eventDB.find( service );
268 if ( It != eventDB.end() && It->second.second.size() )
269 return &(It->second.second);
274 inline void eEPGCache::readNowNextData( const __u8 *data)
276 if ( !data || state == 2 )
277 m_NowNextReader->stop();
279 sectionRead(data, eEPGCache::NOWNEXT);
282 inline void eEPGCache::readScheduleData(const __u8 *data)
284 if ( !data || state == 2 )
285 m_ScheduleReader->stop();
287 sectionRead(data, eEPGCache::SCHEDULE);
290 inline void eEPGCache::readScheduleOtherData(const __u8 *data)
292 if ( !data || state == 2 )
293 m_ScheduleOtherReader->stop();
295 sectionRead(data, eEPGCache::SCHEDULE_OTHER);
298 inline void eEPGCache::Lock()
300 pthread_mutex_lock(&cache_lock);
303 inline void eEPGCache::Unlock()
305 pthread_mutex_unlock(&cache_lock);