Support turbo2.
[vuplus_dvbapp] / lib / dvb / epgcache.h
1 #ifndef __epgcache_h_
2 #define __epgcache_h_
3
4 #define ENABLE_PRIVATE_EPG 1
5 #define ENABLE_MHW_EPG 1
6 #define ENABLE_FREESAT 1
7 #define ENABLE_NETMED 1
8 #define ENABLE_VIRGIN 1
9
10 #ifndef SWIG
11
12 #include <vector>
13 #include <list>
14 #include <tr1/unordered_map>
15
16 #include <errno.h>
17
18 #include <lib/dvb/eit.h>
19 #ifdef ENABLE_MHW_EPG
20 #include <lib/dvb/lowlevel/mhw.h>
21 #endif
22 #include <lib/dvb/idvb.h>
23 #include <lib/dvb/demux.h>
24 #include <lib/dvb/dvbtime.h>
25 #include <lib/base/ebase.h>
26 #include <lib/base/thread.h>
27 #include <lib/base/message.h>
28 #include <lib/service/event.h>
29 #include <lib/python/python.h>
30
31 class eventData;
32 class eServiceReferenceDVB;
33 class eDVBServicePMTHandler;
34
35 struct uniqueEPGKey
36 {
37         int sid, onid, tsid;
38         uniqueEPGKey( const eServiceReference &ref )
39                 :sid( ref.type != eServiceReference::idInvalid ? ((eServiceReferenceDVB&)ref).getServiceID().get() : -1 )
40                 ,onid( ref.type != eServiceReference::idInvalid ? ((eServiceReferenceDVB&)ref).getOriginalNetworkID().get() : -1 )
41                 ,tsid( ref.type != eServiceReference::idInvalid ? ((eServiceReferenceDVB&)ref).getTransportStreamID().get() : -1 )
42         {
43         }
44         uniqueEPGKey()
45                 :sid(-1), onid(-1), tsid(-1)
46         {
47         }
48         uniqueEPGKey( int sid, int onid, int tsid )
49                 :sid(sid), onid(onid), tsid(tsid)
50         {
51         }
52         bool operator <(const uniqueEPGKey &a) const
53         {
54                 if (sid < a.sid)
55                         return true;
56                 if (sid != a.sid)
57                         return false;
58                 if (onid < a.onid)
59                         return true;
60                 if (onid != a.onid)
61                         return false;
62                 return (tsid < a.tsid);
63         }
64         operator bool() const
65         {
66                 return !(sid == -1 && onid == -1 && tsid == -1);
67         }
68         bool operator==(const uniqueEPGKey &a) const
69         {
70                 return (tsid == a.tsid) && (onid == a.onid) && (sid == a.sid);
71         }
72         struct equal
73         {
74                 bool operator()(const uniqueEPGKey &a, const uniqueEPGKey &b) const
75                 {
76                         return (a.tsid == b.tsid) && (a.onid == b.onid) && (a.sid == b.sid);
77                 }
78         };
79 };
80
81 //eventMap is sorted by event_id
82 typedef std::map<uint16_t, eventData*> eventMap;
83 //timeMap is sorted by beginTime
84 typedef std::map<time_t, eventData*> timeMap;
85
86 typedef std::map<eDVBChannelID, time_t> updateMap;
87
88 struct hash_uniqueEPGKey
89 {
90         inline size_t operator()( const uniqueEPGKey &x) const
91         {
92                 return (x.onid << 16) | x.tsid;
93         }
94 };
95
96 struct EventCacheItem {
97         eventMap byEvent;
98         timeMap byTime;
99 };
100
101 typedef std::set<uint32_t> tidMap;
102
103 typedef std::tr1::unordered_map<uniqueEPGKey, EventCacheItem, hash_uniqueEPGKey, uniqueEPGKey::equal> eventCache;
104 #ifdef ENABLE_PRIVATE_EPG
105         typedef std::tr1::unordered_map<time_t, std::pair<time_t, uint16_t> > contentTimeMap;
106         typedef std::tr1::unordered_map<int, contentTimeMap > contentMap;
107         typedef std::tr1::unordered_map<uniqueEPGKey, contentMap, hash_uniqueEPGKey, uniqueEPGKey::equal > contentMaps;
108 #endif
109
110 #endif
111
112 #ifdef ENABLE_FREESAT
113 #include <bitset>
114 class freesatEITSubtableStatus
115 {
116 private:
117         u_char version;
118         uint16_t sectionMap[32];
119         void initMap(uint8_t maxSection);
120
121 public:
122         freesatEITSubtableStatus(u_char version, uint8_t maxSection);
123         bool isSectionPresent(uint8_t sectionNo);
124         void seen(uint8_t sectionNo, uint8_t maxSegmentSection);
125         bool isVersionChanged(u_char testVersion);
126         void updateVersion(u_char newVersion, uint8_t maxSection);
127         bool isCompleted();
128 };
129 #endif
130
131 class eEPGCache: public eMainloop, private eThread, public Object
132 {
133 #ifndef SWIG
134         DECLARE_REF(eEPGCache)
135         struct channel_data: public Object
136         {
137                 pthread_mutex_t channel_active;
138                 channel_data(eEPGCache*);
139                 eEPGCache *cache;
140                 ePtr<eTimer> abortTimer, zapTimer;
141                 int prevChannelState;
142                 int state;
143                 unsigned int isRunning, haveData;
144                 ePtr<eDVBChannel> channel;
145                 ePtr<eConnection> m_stateChangedConn, m_NowNextConn, m_ScheduleConn, m_ScheduleOtherConn, m_ViasatConn;
146                 ePtr<iDVBSectionReader> m_NowNextReader, m_ScheduleReader, m_ScheduleOtherReader, m_ViasatReader;
147                 tidMap seenSections[4], calcedSections[4];
148 #ifdef ENABLE_VIRGIN
149                 ePtr<eConnection> m_VirginNowNextConn, m_VirginScheduleConn;
150                 ePtr<iDVBSectionReader> m_VirginNowNextReader, m_VirginScheduleReader;
151 #endif
152 #ifdef ENABLE_NETMED
153                 ePtr<eConnection> m_NetmedScheduleConn, m_NetmedScheduleOtherConn;
154                 ePtr<iDVBSectionReader> m_NetmedScheduleReader, m_NetmedScheduleOtherReader;
155 #endif
156 #ifdef ENABLE_FREESAT
157                 ePtr<eConnection> m_FreeSatScheduleOtherConn, m_FreeSatScheduleOtherConn2;
158                 ePtr<iDVBSectionReader> m_FreeSatScheduleOtherReader, m_FreeSatScheduleOtherReader2;
159                 std::map<uint32_t, freesatEITSubtableStatus> m_FreeSatSubTableStatus;
160                 uint32_t m_FreesatTablesToComplete;
161                 void readFreeSatScheduleOtherData(const uint8_t *data);
162                 void cleanupFreeSat();
163 #endif
164 #ifdef ENABLE_PRIVATE_EPG
165                 ePtr<eTimer> startPrivateTimer;
166                 int m_PrevVersion;
167                 int m_PrivatePid;
168                 uniqueEPGKey m_PrivateService;
169                 ePtr<eConnection> m_PrivateConn;
170                 ePtr<iDVBSectionReader> m_PrivateReader;
171                 std::set<uint8_t> seenPrivateSections;
172                 void readPrivateData(const uint8_t *data);
173                 void startPrivateReader();
174 #endif
175 #ifdef ENABLE_MHW_EPG
176                 std::vector<mhw_channel_name_t> m_channels;
177                 std::map<uint8_t, mhw_theme_name_t> m_themes;
178                 std::map<uint32_t, mhw_title_t> m_titles;
179                 std::multimap<uint32_t, uint32_t> m_program_ids;
180                 ePtr<eConnection> m_MHWConn, m_MHWConn2;
181                 ePtr<iDVBSectionReader> m_MHWReader, m_MHWReader2;
182                 eDVBSectionFilterMask m_MHWFilterMask, m_MHWFilterMask2;
183                 ePtr<eTimer> m_MHWTimeoutTimer;
184                 uint16_t m_mhw2_channel_pid, m_mhw2_title_pid, m_mhw2_summary_pid;
185                 bool m_MHWTimeoutet;
186                 void MHWTimeout() { m_MHWTimeoutet=true; }
187                 void readMHWData(const uint8_t *data);
188                 void readMHWData2(const uint8_t *data);
189                 void startMHWReader(uint16_t pid, uint8_t tid);
190                 void startMHWReader2(uint16_t pid, uint8_t tid, int ext=-1);
191                 void startMHWTimeout(int msek);
192                 bool checkMHWTimeout() { return m_MHWTimeoutet; }
193                 void cleanupMHW();
194                 uint8_t *delimitName( uint8_t *in, uint8_t *out, int len_in );
195                 void timeMHW2DVB( u_char hours, u_char minutes, u_char *return_time);
196                 void timeMHW2DVB( int minutes, u_char *return_time);
197                 void timeMHW2DVB( u_char day, u_char hours, u_char minutes, u_char *return_time);
198                 void storeMHWTitle(std::map<uint32_t, mhw_title_t>::iterator itTitle, std::string sumText, const uint8_t *data);
199 #endif
200                 void readData(const uint8_t *data, int source);
201                 void startChannel();
202                 void startEPG();
203                 void finishEPG();
204                 void abortEPG();
205                 void abortNonAvail();
206         };
207         bool FixOverlapping(EventCacheItem &servicemap, time_t TM, int duration, const timeMap::iterator &tm_it, const uniqueEPGKey &service);
208 public:
209         struct Message
210         {
211                 enum
212                 {
213                         flush,
214                         startChannel,
215                         leaveChannel,
216                         quit,
217                         got_private_pid,
218                         got_mhw2_channel_pid,
219                         got_mhw2_title_pid,
220                         got_mhw2_summary_pid,
221                         timeChanged
222                 };
223                 int type;
224                 iDVBChannel *channel;
225                 uniqueEPGKey service;
226                 union {
227                         int err;
228                         time_t time;
229                         bool avail;
230                         int pid;
231                 };
232                 Message()
233                         :type(0), time(0) {}
234                 Message(int type)
235                         :type(type) {}
236                 Message(int type, bool b)
237                         :type(type), avail(b) {}
238                 Message(int type, iDVBChannel *channel, int err=0)
239                         :type(type), channel(channel), err(err) {}
240                 Message(int type, const eServiceReference& service, int err=0)
241                         :type(type), service(service), err(err) {}
242                 Message(int type, time_t time)
243                         :type(type), time(time) {}
244         };
245         eFixedMessagePump<Message> messages;
246 private:
247         friend class channel_data;
248         friend class eventData;
249         static eEPGCache *instance;
250
251         typedef std::map<iDVBChannel*, channel_data*> ChannelMap;
252
253         ePtr<eTimer> cleanTimer;
254         ChannelMap m_knownChannels;
255         ePtr<eConnection> m_chanAddedConn;
256
257         unsigned int enabledSources;
258         unsigned int historySeconds;
259
260         eventCache eventDB;
261         updateMap channelLastUpdated;
262         std::string m_filename;
263         bool m_running;
264
265 #ifdef ENABLE_PRIVATE_EPG
266         contentMaps content_time_tables;
267 #endif
268
269         void thread();  // thread function
270
271 #ifdef ENABLE_PRIVATE_EPG
272         void privateSectionRead(const uniqueEPGKey &, const uint8_t *);
273 #endif
274         void sectionRead(const uint8_t *data, int source, channel_data *channel);
275         void gotMessage(const Message &message);
276         void cleanLoop();
277         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 source);
278
279 // called from main thread
280         void DVBChannelAdded(eDVBChannel*);
281         void DVBChannelStateChanged(iDVBChannel*);
282         void DVBChannelRunning(iDVBChannel *);
283
284         timeMap::iterator m_timemap_cursor, m_timemap_end;
285         int currentQueryTsidOnid; // needed for getNextTimeEntry.. only valid until next startTimeQuery call
286 #else
287         eEPGCache();
288         ~eEPGCache();
289 #endif // SWIG
290 public:
291         static eEPGCache *getInstance() { return instance; }
292
293         void save();
294         void load();
295         void timeUpdated();
296         void flushEPG(const uniqueEPGKey & s=uniqueEPGKey());
297 #ifndef SWIG
298         eEPGCache();
299         ~eEPGCache();
300
301 #ifdef ENABLE_PRIVATE_EPG
302         void PMTready(eDVBServicePMTHandler *pmthandler);
303 #else
304         void PMTready(eDVBServicePMTHandler *pmthandler) {}
305 #endif
306
307 #endif
308         // must be called once!
309         void setCacheFile(const char *filename);
310
311         // at moment just for one service..
312         RESULT startTimeQuery(const eServiceReference &service, time_t begin=-1, int minutes=-1);
313
314 #ifndef SWIG
315 private:
316         // For internal use only. Acquire the cache lock before calling.
317         RESULT lookupEventId(const eServiceReference &service, int event_id, const eventData *&);
318         RESULT lookupEventTime(const eServiceReference &service, time_t, const eventData *&, int direction=0);
319
320 public:
321         /* Only used by servicedvbrecord.cpp to write the EIT file */
322         RESULT saveEventToFile(const char* filename, const eServiceReference &service, int eit_event_id, time_t begTime, time_t endTime);
323
324         // Events are parsed epg events.. it's safe to use them after cache unlock
325         // after use the Event pointer must be released using "delete".
326         RESULT lookupEventId(const eServiceReference &service, int event_id, Event* &);
327         RESULT lookupEventTime(const eServiceReference &service, time_t, Event* &, int direction=0);
328         RESULT getNextTimeEntry(Event *&);
329 #endif
330         enum {
331                 SIMILAR_BROADCASTINGS_SEARCH,
332                 EXAKT_TITLE_SEARCH,
333                 PARTIAL_TITLE_SEARCH,
334                 START_TITLE_SEARCH
335         };
336         enum {
337                 CASE_CHECK,
338                 NO_CASE_CHECK
339         };
340         PyObject *lookupEvent(SWIG_PYOBJECT(ePyObject) list, SWIG_PYOBJECT(ePyObject) convertFunc=(PyObject*)0);
341         PyObject *search(SWIG_PYOBJECT(ePyObject));
342
343         // eServiceEvent are parsed epg events.. it's safe to use them after cache unlock
344         // for use from python ( members: m_start_time, m_duration, m_short_description, m_extended_description )
345         SWIG_VOID(RESULT) lookupEventId(const eServiceReference &service, int event_id, ePtr<eServiceEvent> &SWIG_OUTPUT);
346         SWIG_VOID(RESULT) lookupEventTime(const eServiceReference &service, time_t, ePtr<eServiceEvent> &SWIG_OUTPUT, int direction=0);
347         SWIG_VOID(RESULT) getNextTimeEntry(ePtr<eServiceEvent> &SWIG_OUTPUT);
348
349         enum {PRIVATE=0, NOWNEXT=1, SCHEDULE=2, SCHEDULE_OTHER=4
350 #ifdef ENABLE_MHW_EPG
351         ,MHW=8
352 #endif
353 #ifdef ENABLE_FREESAT
354         ,FREESAT_NOWNEXT=16
355         ,FREESAT_SCHEDULE=32
356         ,FREESAT_SCHEDULE_OTHER=64
357 #endif
358         ,VIASAT=256
359 #ifdef ENABLE_NETMED
360         ,NETMED_SCHEDULE=512
361         ,NETMED_SCHEDULE_OTHER=1024
362 #endif
363 #ifdef ENABLE_VIRGIN
364         ,VIRGIN_NOWNEXT=2048
365         ,VIRGIN_SCHEDULE=4096
366 #endif
367         ,EPG_IMPORT=0x80000000
368         };
369         void setEpgHistorySeconds(time_t seconds);
370         void setEpgSources(unsigned int mask);
371         unsigned int getEpgSources();
372
373         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);
374         void importEvents(SWIG_PYOBJECT(ePyObject) serviceReferences, SWIG_PYOBJECT(ePyObject) list);
375         void importEvent(SWIG_PYOBJECT(ePyObject) serviceReference, SWIG_PYOBJECT(ePyObject) list);
376 };
377 #endif