Update EPG Cache(thanks to open source community)
[vuplus_dvbapp] / lib / dvb / epgcache.h
index 90aff6c..2b47977 100644 (file)
@@ -2,32 +2,20 @@
 #define __epgcache_h_
 
 #define ENABLE_PRIVATE_EPG 1
-//#define ENABLE_MHW_EPG 1
+#define ENABLE_MHW_EPG 1
+#define ENABLE_FREESAT 1
+#define ENABLE_NETMED 1
+#define ENABLE_VIRGIN 1
 
 #ifndef SWIG
 
-/* Test for gcc >= maj.min, as per __GNUC_PREREQ in glibc */
-#if defined (__GNUC__) && defined (__GNUC_MINOR__)
-#define __GNUC_PREREQ(maj, min) \
-         ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-#else
-#define __GNUC_PREREQ(maj, min)  0
-#endif
-
 #include <vector>
 #include <list>
-#if 0 && __GNUC_PREREQ(4,3)
-#include <unordered_map>
-#include <unordered_set>
-#else
-#include <ext/hash_map>
-#include <ext/hash_set>
-#endif
+#include <tr1/unordered_map>
 
 #include <errno.h>
 
 #include <lib/dvb/eit.h>
-#include <lib/dvb/lowlevel/eit.h>
 #ifdef ENABLE_MHW_EPG
 #include <lib/dvb/lowlevel/mhw.h>
 #endif
 #include <lib/service/event.h>
 #include <lib/python/python.h>
 
-#define CLEAN_INTERVAL 60000    //  1 min
-#define UPDATE_INTERVAL 3600000  // 60 min
-#define ZAP_DELAY 2000          // 2 sek
-
-#define HILO(x) (x##_hi << 8 | x##_lo)
-
 class eventData;
 class eServiceReferenceDVB;
 class eDVBServicePMTHandler;
@@ -69,32 +51,39 @@ struct uniqueEPGKey
        }
        bool operator <(const uniqueEPGKey &a) const
        {
-               return memcmp( &sid, &a.sid, sizeof(int)*3)<0;
+               if (sid < a.sid)
+                       return true;
+               if (sid != a.sid)
+                       return false;
+               if (onid < a.onid)
+                       return true;
+               if (onid != a.onid)
+                       return false;
+               return (tsid < a.tsid);
        }
        operator bool() const
-       { 
-               return !(sid == -1 && onid == -1 && tsid == -1); 
+       {
+               return !(sid == -1 && onid == -1 && tsid == -1);
        }
        bool operator==(const uniqueEPGKey &a) const
        {
-               return !memcmp( &sid, &a.sid, sizeof(int)*3);
+               return (tsid == a.tsid) && (onid == a.onid) && (sid == a.sid);
        }
        struct equal
        {
                bool operator()(const uniqueEPGKey &a, const uniqueEPGKey &b) const
                {
-                       return !memcmp( &a.sid, &b.sid, sizeof(int)*3);
+                       return (a.tsid == b.tsid) && (a.onid == b.onid) && (a.sid == b.sid);
                }
        };
 };
 
 //eventMap is sorted by event_id
-#define eventMap std::map<__u16, eventData*>
+typedef std::map<uint16_t, eventData*> eventMap;
 //timeMap is sorted by beginTime
-#define timeMap std::map<time_t, eventData*>
+typedef std::map<time_t, eventData*> timeMap;
 
-#define channelMapIterator std::map<iDVBChannel*, channel_data*>::iterator
-#define updateMap std::map<eDVBChannelID, time_t>
+typedef std::map<eDVBChannelID, time_t> updateMap;
 
 struct hash_uniqueEPGKey
 {
@@ -104,65 +93,38 @@ struct hash_uniqueEPGKey
        }
 };
 
-#define tidMap std::set<__u32>
-#if 0 && __GNUC_PREREQ(4,3)
-       #define eventCache std::unordered_map<uniqueEPGKey, std::pair<eventMap, timeMap>, hash_uniqueEPGKey, uniqueEPGKey::equal>
-       #ifdef ENABLE_PRIVATE_EPG
-               #define contentTimeMap std::unordered_map<time_t, std::pair<time_t, __u16> >
-               #define contentMap std::unordered_map<int, contentTimeMap >
-               #define contentMaps std::unordered_map<uniqueEPGKey, contentMap, hash_uniqueEPGKey, uniqueEPGKey::equal >
-       #endif
-#elif __GNUC_PREREQ(3,1)
-       #define eventCache __gnu_cxx::hash_map<uniqueEPGKey, std::pair<eventMap, timeMap>, hash_uniqueEPGKey, uniqueEPGKey::equal>
-       #ifdef ENABLE_PRIVATE_EPG
-               #define contentTimeMap __gnu_cxx::hash_map<time_t, std::pair<time_t, __u16> >
-               #define contentMap __gnu_cxx::hash_map<int, contentTimeMap >
-               #define contentMaps __gnu_cxx::hash_map<uniqueEPGKey, contentMap, hash_uniqueEPGKey, uniqueEPGKey::equal >
-       #endif
-#else // for older gcc use following
-       #define eventCache std::hash_map<uniqueEPGKey, std::pair<eventMap, timeMap>, hash_uniqueEPGKey, uniqueEPGKey::equal >
-       #ifdef ENABLE_PRIVATE_EPG
-               #define contentTimeMap std::hash_map<time_t, std::pair<time_t, __u16> >
-               #define contentMap std::hash_map<int, contentTimeMap >
-               #define contentMaps std::hash_map<uniqueEPGKey, contentMap, hash_uniqueEPGKey, uniqueEPGKey::equal>
-       #endif
+struct EventCacheItem {
+       eventMap byEvent;
+       timeMap byTime;
+};
+
+typedef std::set<uint32_t> tidMap;
+
+typedef std::tr1::unordered_map<uniqueEPGKey, EventCacheItem, hash_uniqueEPGKey, uniqueEPGKey::equal> eventCache;
+#ifdef ENABLE_PRIVATE_EPG
+       typedef std::tr1::unordered_map<time_t, std::pair<time_t, uint16_t> > contentTimeMap;
+       typedef std::tr1::unordered_map<int, contentTimeMap > contentMap;
+       typedef std::tr1::unordered_map<uniqueEPGKey, contentMap, hash_uniqueEPGKey, uniqueEPGKey::equal > contentMaps;
 #endif
 
-#define descriptorPair std::pair<int,__u8*>
-#define descriptorMap std::map<__u32, descriptorPair >
+#endif
 
-class eventData
+#ifdef ENABLE_FREESAT
+#include <bitset>
+class freesatEITSubtableStatus
 {
-       friend class eEPGCache;
 private:
-       __u8* EITdata;
-       __u8 ByteSize;
-       __u8 type;
-       static descriptorMap descriptors;
-       static __u8 data[4108];
-       static int CacheSize;
-       static void load(FILE *);
-       static void save(FILE *);
+       u_char version;
+       uint16_t sectionMap[32];
+       void initMap(uint8_t maxSection);
+
 public:
-       eventData(const eit_event_struct* e=NULL, int size=0, int type=0);
-       ~eventData();
-       const eit_event_struct* get() const;
-       operator const eit_event_struct*() const
-       {
-               return get();
-       }
-       int getEventID()
-       {
-               return (EITdata[0] << 8) | EITdata[1];
-       }
-       time_t getStartTime()
-       {
-               return parseDVBtime(EITdata[2], EITdata[3], EITdata[4], EITdata[5], EITdata[6]);
-       }
-       int getDuration()
-       {
-               return fromBCD(EITdata[7])*3600+fromBCD(EITdata[8])*60+fromBCD(EITdata[9]);
-       }
+       freesatEITSubtableStatus(u_char version, uint8_t maxSection);
+       bool isSectionPresent(uint8_t sectionNo);
+       void seen(uint8_t sectionNo, uint8_t maxSegmentSection);
+       bool isVersionChanged(u_char testVersion);
+       void updateVersion(u_char newVersion, uint8_t maxSection);
+       bool isCompleted();
 };
 #endif
 
@@ -178,11 +140,27 @@ class eEPGCache: public eMainloop, private eThread, public Object
                ePtr<eTimer> abortTimer, zapTimer;
                int prevChannelState;
                int state;
-               __u8 isRunning, haveData;
+               unsigned int isRunning, haveData;
                ePtr<eDVBChannel> channel;
                ePtr<eConnection> m_stateChangedConn, m_NowNextConn, m_ScheduleConn, m_ScheduleOtherConn, m_ViasatConn;
                ePtr<iDVBSectionReader> m_NowNextReader, m_ScheduleReader, m_ScheduleOtherReader, m_ViasatReader;
                tidMap seenSections[4], calcedSections[4];
+#ifdef ENABLE_VIRGIN
+               ePtr<eConnection> m_VirginNowNextConn, m_VirginScheduleConn;
+               ePtr<iDVBSectionReader> m_VirginNowNextReader, m_VirginScheduleReader;
+#endif
+#ifdef ENABLE_NETMED
+               ePtr<eConnection> m_NetmedScheduleConn, m_NetmedScheduleOtherConn;
+               ePtr<iDVBSectionReader> m_NetmedScheduleReader, m_NetmedScheduleOtherReader;
+#endif
+#ifdef ENABLE_FREESAT
+               ePtr<eConnection> m_FreeSatScheduleOtherConn, m_FreeSatScheduleOtherConn2;
+               ePtr<iDVBSectionReader> m_FreeSatScheduleOtherReader, m_FreeSatScheduleOtherReader2;
+               std::map<uint32_t, freesatEITSubtableStatus> m_FreeSatSubTableStatus;
+               uint32_t m_FreesatTablesToComplete;
+               void readFreeSatScheduleOtherData(const uint8_t *data);
+               void cleanupFreeSat();
+#endif
 #ifdef ENABLE_PRIVATE_EPG
                ePtr<eTimer> startPrivateTimer;
                int m_PrevVersion;
@@ -190,51 +168,44 @@ class eEPGCache: public eMainloop, private eThread, public Object
                uniqueEPGKey m_PrivateService;
                ePtr<eConnection> m_PrivateConn;
                ePtr<iDVBSectionReader> m_PrivateReader;
-               std::set<__u8> seenPrivateSections;
-               void readPrivateData(const __u8 *data);
+               std::set<uint8_t> seenPrivateSections;
+               void readPrivateData(const uint8_t *data);
                void startPrivateReader();
 #endif
 #ifdef ENABLE_MHW_EPG
                std::vector<mhw_channel_name_t> m_channels;
-               std::map<__u8, mhw_theme_name_t> m_themes;
-               std::map<__u32, mhw_title_t> m_titles;
-               std::multimap<__u32, __u32> m_program_ids;
+               std::map<uint8_t, mhw_theme_name_t> m_themes;
+               std::map<uint32_t, mhw_title_t> m_titles;
+               std::multimap<uint32_t, uint32_t> m_program_ids;
                ePtr<eConnection> m_MHWConn, m_MHWConn2;
                ePtr<iDVBSectionReader> m_MHWReader, m_MHWReader2;
                eDVBSectionFilterMask m_MHWFilterMask, m_MHWFilterMask2;
                ePtr<eTimer> m_MHWTimeoutTimer;
-               __u16 m_mhw2_channel_pid, m_mhw2_title_pid, m_mhw2_summary_pid;
+               uint16_t m_mhw2_channel_pid, m_mhw2_title_pid, m_mhw2_summary_pid;
                bool m_MHWTimeoutet;
                void MHWTimeout() { m_MHWTimeoutet=true; }
-               void readMHWData(const __u8 *data);
-               void readMHWData2(const __u8 *data);
-               void startMHWReader(__u16 pid, __u8 tid);
-               void startMHWReader2(__u16 pid, __u8 tid, int ext=-1);
-               void startTimeout(int msek);
-               bool checkTimeout() { return m_MHWTimeoutet; }
-               void cleanup();
-               __u8 *delimitName( __u8 *in, __u8 *out, int len_in );
+               void readMHWData(const uint8_t *data);
+               void readMHWData2(const uint8_t *data);
+               void startMHWReader(uint16_t pid, uint8_t tid);
+               void startMHWReader2(uint16_t pid, uint8_t tid, int ext=-1);
+               void startMHWTimeout(int msek);
+               bool checkMHWTimeout() { return m_MHWTimeoutet; }
+               void cleanupMHW();
+               uint8_t *delimitName( uint8_t *in, uint8_t *out, int len_in );
                void timeMHW2DVB( u_char hours, u_char minutes, u_char *return_time);
                void timeMHW2DVB( int minutes, u_char *return_time);
                void timeMHW2DVB( u_char day, u_char hours, u_char minutes, u_char *return_time);
-               void storeTitle(std::map<__u32, mhw_title_t>::iterator itTitle, std::string sumText, const __u8 *data);
+               void storeMHWTitle(std::map<uint32_t, mhw_title_t>::iterator itTitle, std::string sumText, const uint8_t *data);
 #endif
-               void readData(const __u8 *data);
-               void readDataViasat(const __u8 *data);
+               void readData(const uint8_t *data, int source);
                void startChannel();
                void startEPG();
-               bool finishEPG();
+               void finishEPG();
                void abortEPG();
                void abortNonAvail();
        };
-       bool FixOverlapping(std::pair<eventMap,timeMap> &servicemap, time_t TM, int duration, const timeMap::iterator &tm_it, const uniqueEPGKey &service);
+       bool FixOverlapping(EventCacheItem &servicemap, time_t TM, int duration, const timeMap::iterator &tm_it, const uniqueEPGKey &service);
 public:
-       enum {PRIVATE=0, NOWNEXT=1, SCHEDULE=2, SCHEDULE_OTHER=4
-#ifdef ENABLE_MHW_EPG
-       ,MHW=8
-#endif
-       ,VIASAT=16
-       };
        struct Message
        {
                enum
@@ -274,15 +245,22 @@ public:
        eFixedMessagePump<Message> messages;
 private:
        friend class channel_data;
+       friend class eventData;
        static eEPGCache *instance;
 
+       typedef std::map<iDVBChannel*, channel_data*> ChannelMap;
+
        ePtr<eTimer> cleanTimer;
-       std::map<iDVBChannel*, channel_data*> m_knownChannels;
+       ChannelMap m_knownChannels;
        ePtr<eConnection> m_chanAddedConn;
 
+       unsigned int enabledSources;
+       unsigned int historySeconds;
+
        eventCache eventDB;
        updateMap channelLastUpdated;
-       static pthread_mutex_t cache_lock, channel_map_lock;
+       std::string m_filename;
+       bool m_running;
 
 #ifdef ENABLE_PRIVATE_EPG
        contentMaps content_time_tables;
@@ -290,21 +268,15 @@ private:
 
        void thread();  // thread function
 
-// called from epgcache thread
-       int m_running;
-       char m_filename[1024];
-       void save();
-       void load();
 #ifdef ENABLE_PRIVATE_EPG
-       void privateSectionRead(const uniqueEPGKey &, const __u8 *);
+       void privateSectionRead(const uniqueEPGKey &, const uint8_t *);
 #endif
-       void sectionRead(const __u8 *data, int source, channel_data *channel);
+       void sectionRead(const uint8_t *data, int source, channel_data *channel);
        void gotMessage(const Message &message);
-       void flushEPG(const uniqueEPGKey & s=uniqueEPGKey());
        void cleanLoop();
+       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);
 
 // called from main thread
-       void timeUpdated();
        void DVBChannelAdded(eDVBChannel*);
        void DVBChannelStateChanged(iDVBChannel*);
        void DVBChannelRunning(iDVBChannel *);
@@ -317,6 +289,11 @@ private:
 #endif // SWIG
 public:
        static eEPGCache *getInstance() { return instance; }
+
+       void save();
+       void load();
+       void timeUpdated();
+       void flushEPG(const uniqueEPGKey & s=uniqueEPGKey());
 #ifndef SWIG
        eEPGCache();
        ~eEPGCache();
@@ -331,28 +308,21 @@ public:
        // must be called once!
        void setCacheFile(const char *filename);
 
-       // called from main thread
-       inline void Lock();
-       inline void Unlock();
-
        // at moment just for one service..
        RESULT startTimeQuery(const eServiceReference &service, time_t begin=-1, int minutes=-1);
 
 #ifndef SWIG
-       // eventData's are plain entrys out of the cache.. it's not safe to use them after cache unlock
-       // but its faster in use... its not allowed to delete this pointers via delete or free..
+private:
+       // For internal use only. Acquire the cache lock before calling.
        RESULT lookupEventId(const eServiceReference &service, int event_id, const eventData *&);
        RESULT lookupEventTime(const eServiceReference &service, time_t, const eventData *&, int direction=0);
-       RESULT getNextTimeEntry(const eventData *&);
 
-       // eit_event_struct's are plain dvb eit_events .. it's not safe to use them after cache unlock
-       // its not allowed to delete this pointers via delete or free..
-       RESULT lookupEventId(const eServiceReference &service, int event_id, const eit_event_struct *&);
-       RESULT lookupEventTime(const eServiceReference &service, time_t , const eit_event_struct *&, int direction=0);
-       RESULT getNextTimeEntry(const eit_event_struct *&);
+public:
+       /* Only used by servicedvbrecord.cpp to write the EIT file */
+       RESULT saveEventToFile(const char* filename, const eServiceReference &service, int eit_event_id, time_t begTime, time_t endTime);
 
-       // Event's are parsed epg events.. it's safe to use them after cache unlock
-       // after use this Events must be deleted (memleaks)
+       // Events are parsed epg events.. it's safe to use them after cache unlock
+       // after use the Event pointer must be released using "delete".
        RESULT lookupEventId(const eServiceReference &service, int event_id, Event* &);
        RESULT lookupEventTime(const eServiceReference &service, time_t, Event* &, int direction=0);
        RESULT getNextTimeEntry(Event *&);
@@ -360,7 +330,8 @@ public:
        enum {
                SIMILAR_BROADCASTINGS_SEARCH,
                EXAKT_TITLE_SEARCH,
-               PARTIAL_TITLE_SEARCH
+               PARTIAL_TITLE_SEARCH,
+               START_TITLE_SEARCH
        };
        enum {
                CASE_CHECK,
@@ -374,18 +345,33 @@ public:
        SWIG_VOID(RESULT) lookupEventId(const eServiceReference &service, int event_id, ePtr<eServiceEvent> &SWIG_OUTPUT);
        SWIG_VOID(RESULT) lookupEventTime(const eServiceReference &service, time_t, ePtr<eServiceEvent> &SWIG_OUTPUT, int direction=0);
        SWIG_VOID(RESULT) getNextTimeEntry(ePtr<eServiceEvent> &SWIG_OUTPUT);
-};
 
-#ifndef SWIG
-inline void eEPGCache::Lock()
-{
-       pthread_mutex_lock(&cache_lock);
-}
-
-inline void eEPGCache::Unlock()
-{
-       pthread_mutex_unlock(&cache_lock);
-}
+       enum {PRIVATE=0, NOWNEXT=1, SCHEDULE=2, SCHEDULE_OTHER=4
+#ifdef ENABLE_MHW_EPG
+       ,MHW=8
+#endif
+#ifdef ENABLE_FREESAT
+       ,FREESAT_NOWNEXT=16
+       ,FREESAT_SCHEDULE=32
+       ,FREESAT_SCHEDULE_OTHER=64
+#endif
+       ,VIASAT=256
+#ifdef ENABLE_NETMED
+       ,NETMED_SCHEDULE=512
+       ,NETMED_SCHEDULE_OTHER=1024
 #endif
+#ifdef ENABLE_VIRGIN
+       ,VIRGIN_NOWNEXT=2048
+       ,VIRGIN_SCHEDULE=4096
+#endif
+       ,EPG_IMPORT=0x80000000
+       };
+       void setEpgHistorySeconds(time_t seconds);
+       void setEpgSources(unsigned int mask);
+       unsigned int getEpgSources();
 
+       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);
+       void importEvents(SWIG_PYOBJECT(ePyObject) serviceReferences, SWIG_PYOBJECT(ePyObject) list);
+       void importEvent(SWIG_PYOBJECT(ePyObject) serviceReference, SWIG_PYOBJECT(ePyObject) list);
+};
 #endif