epgache: move epg cache file name to main enigma2 settings file (config.misc.epgache_...
[enigma2.git] / lib / dvb / epgcache.cpp
index 47ebb355ace29307014238cdcc58ed7b7b06dfe3..15248a6bf4da72783bd03bce213a0dfdd48275ae 100644 (file)
 #include <sys/vfs.h> // for statfs
 // #include <libmd5sum.h>
 #include <lib/base/eerror.h>
 #include <sys/vfs.h> // for statfs
 // #include <libmd5sum.h>
 #include <lib/base/eerror.h>
+#include <lib/base/estring.h>
 #include <lib/dvb/pmt.h>
 #include <lib/dvb/db.h>
 #include <lib/python/python.h>
 #include <lib/dvb/pmt.h>
 #include <lib/dvb/db.h>
 #include <lib/python/python.h>
+#include <dvbsi++/descriptor_tag.h>
 
 int eventData::CacheSize=0;
 descriptorMap eventData::descriptors;
 
 int eventData::CacheSize=0;
 descriptorMap eventData::descriptors;
@@ -44,7 +46,6 @@ const eServiceReference &handleGroup(const eServiceReference &ref)
        return ref;
 }
 
        return ref;
 }
 
-
 eventData::eventData(const eit_event_struct* e, int size, int type)
        :ByteSize(size&0xFF), type(type&0xFF)
 {
 eventData::eventData(const eit_event_struct* e, int size, int type)
        :ByteSize(size&0xFF), type(type&0xFF)
 {
@@ -55,49 +56,67 @@ eventData::eventData(const eit_event_struct* e, int size, int type)
        __u32 *pdescr=descr;
 
        __u8 *data = (__u8*)e;
        __u32 *pdescr=descr;
 
        __u8 *data = (__u8*)e;
-       int ptr=10;
-       int descriptors_length = (data[ptr++]&0x0F) << 8;
-       descriptors_length |= data[ptr++];
-       while ( descriptors_length > 0 )
+       int ptr=12;
+       size -= 12;
+
+       while(size > 1)
        {
                __u8 *descr = data+ptr;
        {
                __u8 *descr = data+ptr;
-               int descr_len = descr[1]+2;
-
-               __u32 crc = 0;
-               int cnt=0;
-               while(cnt++ < descr_len)
-                       crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ data[ptr++]) & 0xFF];
-
-               descriptorMap::iterator it =
-                       descriptors.find(crc);
-               if ( it == descriptors.end() )
+               int descr_len = descr[1];
+               descr_len += 2;
+               if (size >= descr_len)
                {
                {
-                       CacheSize+=descr_len;
-                       __u8 *d = new __u8[descr_len];
-                       memcpy(d, descr, descr_len);
-                       descriptors[crc] = descriptorPair(1, d);
+                       switch (descr[0])
+                       {
+                               case EXTENDED_EVENT_DESCRIPTOR:
+                               case SHORT_EVENT_DESCRIPTOR:
+                               case LINKAGE_DESCRIPTOR:
+                               case COMPONENT_DESCRIPTOR:
+                               {
+                                       __u32 crc = 0;
+                                       int cnt=0;
+                                       while(cnt++ < descr_len)
+                                               crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ data[ptr++]) & 0xFF];
+       
+                                       descriptorMap::iterator it =
+                                               descriptors.find(crc);
+                                       if ( it == descriptors.end() )
+                                       {
+                                               CacheSize+=descr_len;
+                                               __u8 *d = new __u8[descr_len];
+                                               memcpy(d, descr, descr_len);
+                                               descriptors[crc] = descriptorPair(1, d);
+                                       }
+                                       else
+                                               ++it->second.first;
+                                       *pdescr++=crc;
+                                       break;
+                               }
+                               default: // do not cache all other descriptors
+                                       ptr += descr_len;
+                                       break;
+                       }
+                       size -= descr_len;
                }
                else
                }
                else
-                       ++it->second.first;
-
-               *pdescr++=crc;
-               descriptors_length -= descr_len;
+                       break;
        }
        ASSERT(pdescr <= &descr[65]);
        }
        ASSERT(pdescr <= &descr[65]);
-       ByteSize = 12+((pdescr-descr)*4);
+       ByteSize = 10+((pdescr-descr)*4);
        EITdata = new __u8[ByteSize];
        CacheSize+=ByteSize;
        EITdata = new __u8[ByteSize];
        CacheSize+=ByteSize;
-       memcpy(EITdata, (__u8*) e, 12);
-       memcpy(EITdata+12, descr, ByteSize-12);
+       memcpy(EITdata, (__u8*) e, 10);
+       memcpy(EITdata+10, descr, ByteSize-10);
 }
 
 const eit_event_struct* eventData::get() const
 {
        int pos = 12;
 }
 
 const eit_event_struct* eventData::get() const
 {
        int pos = 12;
-       int tmp = ByteSize-12;
-       memcpy(data, EITdata, 12);
-       __u32 *p = (__u32*)(EITdata+12);
-       while(tmp>0)
+       int tmp = ByteSize-10;
+       memcpy(data, EITdata, 10);
+       int descriptors_length=0;
+       __u32 *p = (__u32*)(EITdata+10);
+       while(tmp>3)
        {
                descriptorMap::iterator it =
                        descriptors.find(*p++);
        {
                descriptorMap::iterator it =
                        descriptors.find(*p++);
@@ -106,22 +125,26 @@ const eit_event_struct* eventData::get() const
                        int b = it->second.second[1]+2;
                        memcpy(data+pos, it->second.second, b );
                        pos += b;
                        int b = it->second.second[1]+2;
                        memcpy(data+pos, it->second.second, b );
                        pos += b;
+                       descriptors_length += b;
                }
                }
+               else
+                       eFatal("LINE %d descriptor not found in descriptor cache %08x!!!!!!", __LINE__, *(p-1));
                tmp-=4;
        }
        ASSERT(pos <= 4108);
                tmp-=4;
        }
        ASSERT(pos <= 4108);
-
-       return (const eit_event_struct*)data;
+       data[10] = (descriptors_length >> 8) & 0x0F;
+       data[11] = descriptors_length & 0xFF;
+       return (eit_event_struct*)data;
 }
 
 eventData::~eventData()
 {
        if ( ByteSize )
        {
 }
 
 eventData::~eventData()
 {
        if ( ByteSize )
        {
-               CacheSize-=ByteSize;
-               ByteSize-=12;
-               __u32 *d = (__u32*)(EITdata+12);
-               while(ByteSize)
+               CacheSize -= ByteSize;
+               __u32 *d = (__u32*)(EITdata+10);
+               ByteSize -= 10;
+               while(ByteSize>3)
                {
                        descriptorMap::iterator it =
                                descriptors.find(*d++);
                {
                        descriptorMap::iterator it =
                                descriptors.find(*d++);
@@ -136,8 +159,8 @@ eventData::~eventData()
                                }
                        }
                        else
                                }
                        }
                        else
-                               eFatal("[descriptor not found in descriptor cache!!!!!!");
-                       ByteSize-=4;
+                               eFatal("LINE %d descriptor not found in descriptor cache %08x!!!!!!", __LINE__, *(d-1));
+                       ByteSize -= 4;
                }
                delete [] EITdata;
        }
                }
                delete [] EITdata;
        }
@@ -190,13 +213,13 @@ pthread_mutex_t eEPGCache::channel_map_lock=
 DEFINE_REF(eEPGCache)
 
 eEPGCache::eEPGCache()
 DEFINE_REF(eEPGCache)
 
 eEPGCache::eEPGCache()
-       :messages(this,1), cleanTimer(this)//, paused(0)
+       :messages(this,1), cleanTimer(eTimer::create(this)), m_running(0)//, paused(0)
 {
 {
-       eDebug("[EPGC] Initialized EPGCache");
+       eDebug("[EPGC] Initialized EPGCache (wait for setCacheFile call now)");
 
        CONNECT(messages.recv_msg, eEPGCache::gotMessage);
        CONNECT(eDVBLocalTimeHandler::getInstance()->m_timeUpdated, eEPGCache::timeUpdated);
 
        CONNECT(messages.recv_msg, eEPGCache::gotMessage);
        CONNECT(eDVBLocalTimeHandler::getInstance()->m_timeUpdated, eEPGCache::timeUpdated);
-       CONNECT(cleanTimer.timeout, eEPGCache::cleanLoop);
+       CONNECT(cleanTimer->timeout, eEPGCache::cleanLoop);
 
        ePtr<eDVBResourceManager> res_mgr;
        eDVBResourceManager::getInstance(res_mgr);
 
        ePtr<eDVBResourceManager> res_mgr;
        eDVBResourceManager::getInstance(res_mgr);
@@ -204,17 +227,46 @@ eEPGCache::eEPGCache()
                eDebug("[eEPGCache] no resource manager !!!!!!!");
        else
                res_mgr->connectChannelAdded(slot(*this,&eEPGCache::DVBChannelAdded), m_chanAddedConn);
                eDebug("[eEPGCache] no resource manager !!!!!!!");
        else
                res_mgr->connectChannelAdded(slot(*this,&eEPGCache::DVBChannelAdded), m_chanAddedConn);
+
        instance=this;
        instance=this;
+       memset(m_filename, 0, sizeof(m_filename));
+}
+
+void eEPGCache::setCacheFile(const char *path)
+{
+       if (!strlen(m_filename))
+       {
+               strncpy(m_filename, path, 1024);
+               eDebug("[EPGC] setCacheFile read/write epg data from/to '%s'", m_filename);
+               if (eDVBLocalTimeHandler::getInstance()->ready())
+                       timeUpdated();
+       }
+       else
+               eDebug("[EPGC] setCacheFile already called... ignore '%s'", path);
 }
 
 void eEPGCache::timeUpdated()
 {
 }
 
 void eEPGCache::timeUpdated()
 {
-       if (!sync())
+       if (strlen(m_filename))
        {
        {
-               eDebug("[EPGC] time updated.. start EPG Mainloop");
-               run();
-       } else
-               messages.send(Message(Message::timeChanged));
+               if (!sync())
+               {
+                       eDebug("[EPGC] time updated.. start EPG Mainloop");
+                       run();
+                       singleLock s(channel_map_lock);
+                       channelMapIterator it = m_knownChannels.begin();
+                       for (; it != m_knownChannels.end(); ++it)
+                       {
+                               if (it->second->state == -1) {
+                                       it->second->state=0;
+                                       messages.send(Message(Message::startChannel, it->second));
+                               }
+                       }
+               } else
+                       messages.send(Message(Message::timeChanged));
+       }
+       else
+               eDebug("[EPGC] time updated.. but cache file not set yet.. dont start epg!!");
 }
 
 void eEPGCache::DVBChannelAdded(eDVBChannel *chan)
 }
 
 void eEPGCache::DVBChannelAdded(eDVBChannel *chan)
@@ -227,6 +279,11 @@ void eEPGCache::DVBChannelAdded(eDVBChannel *chan)
                data->prevChannelState = -1;
 #ifdef ENABLE_PRIVATE_EPG
                data->m_PrivatePid = -1;
                data->prevChannelState = -1;
 #ifdef ENABLE_PRIVATE_EPG
                data->m_PrivatePid = -1;
+#endif
+#ifdef ENABLE_MHW_EPG
+               data->m_mhw2_channel_pid = 0x231; // defaults for astra 19.2 D+
+               data->m_mhw2_title_pid = 0x234; // defaults for astra 19.2 D+
+               data->m_mhw2_summary_pid = 0x236; // defaults for astra 19.2 D+
 #endif
                singleLock s(channel_map_lock);
                m_knownChannels.insert( std::pair<iDVBChannel*, channel_data* >(chan, data) );
 #endif
                singleLock s(channel_map_lock);
                m_knownChannels.insert( std::pair<iDVBChannel*, channel_data* >(chan, data) );
@@ -276,6 +333,13 @@ void eEPGCache::DVBChannelRunning(iDVBChannel *chan)
                                        eDebug("[eEPGCache] couldnt initialize schedule other reader!!");
                                        return;
                                }
                                        eDebug("[eEPGCache] couldnt initialize schedule other reader!!");
                                        return;
                                }
+
+                               res = demux->createSectionReader( this, data.m_ViasatReader );
+                               if ( res )
+                               {
+                                       eDebug("[eEPGCache] couldnt initialize viasat reader!!");
+                                       return;
+                               }
 #ifdef ENABLE_PRIVATE_EPG
                                res = demux->createSectionReader( this, data.m_PrivateReader );
                                if ( res )
 #ifdef ENABLE_PRIVATE_EPG
                                res = demux->createSectionReader( this, data.m_PrivateReader );
                                if ( res )
@@ -298,8 +362,11 @@ void eEPGCache::DVBChannelRunning(iDVBChannel *chan)
                                        return;
                                }
 #endif
                                        return;
                                }
 #endif
-                               messages.send(Message(Message::startChannel, chan));
-                               // -> gotMessage -> changedService
+                               if (m_running) {
+                                       data.state=0;
+                                       messages.send(Message(Message::startChannel, chan));
+                                       // -> gotMessage -> changedService
+                               }
                        }
                }
        }
                        }
                }
        }
@@ -326,7 +393,8 @@ void eEPGCache::DVBChannelStateChanged(iDVBChannel *chan)
                                case iDVBChannel::state_release:
                                {
                                        eDebug("[eEPGCache] remove channel %p", chan);
                                case iDVBChannel::state_release:
                                {
                                        eDebug("[eEPGCache] remove channel %p", chan);
-                                       messages.send(Message(Message::leaveChannel, chan));
+                                       if (it->second->state >= 0)
+                                               messages.send(Message(Message::leaveChannel, chan));
                                        pthread_mutex_lock(&it->second->channel_active);
                                        singleLock s(channel_map_lock);
                                        m_knownChannels.erase(it);
                                        pthread_mutex_lock(&it->second->channel_active);
                                        singleLock s(channel_map_lock);
                                        m_knownChannels.erase(it);
@@ -345,8 +413,9 @@ void eEPGCache::DVBChannelStateChanged(iDVBChannel *chan)
        }
 }
 
        }
 }
 
-void eEPGCache::FixOverlapping(std::pair<eventMap,timeMap> &servicemap, time_t TM, int duration, const timeMap::iterator &tm_it, const uniqueEPGKey &service)
+bool eEPGCache::FixOverlapping(std::pair<eventMap,timeMap> &servicemap, time_t TM, int duration, const timeMap::iterator &tm_it, const uniqueEPGKey &service)
 {
 {
+       bool ret = false;
        timeMap::iterator tmp = tm_it;
        while ((tmp->first+tmp->second->getDuration()-300) > TM)
        {
        timeMap::iterator tmp = tm_it;
        while ((tmp->first+tmp->second->getDuration()-300) > TM)
        {
@@ -379,6 +448,7 @@ void eEPGCache::FixOverlapping(std::pair<eventMap,timeMap> &servicemap, time_t T
                        }
                        else
                                servicemap.second.erase(tmp--);
                        }
                        else
                                servicemap.second.erase(tmp--);
+                       ret = true;
                }
                else
                {
                }
                else
                {
@@ -407,12 +477,14 @@ void eEPGCache::FixOverlapping(std::pair<eventMap,timeMap> &servicemap, time_t T
 #endif
                        delete tmp->second;
                        servicemap.second.erase(tmp++);
 #endif
                        delete tmp->second;
                        servicemap.second.erase(tmp++);
+                       ret = true;
                }
                else
                        ++tmp;
                if (tmp == servicemap.second.end())
                        break;
        }
                }
                else
                        ++tmp;
                if (tmp == servicemap.second.end())
                        break;
        }
+       return ret;
 }
 
 void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
 }
 
 void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
@@ -429,13 +501,25 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
        if ( data[ptr-1] < 0x40 )
                --ptr;
 
        if ( data[ptr-1] < 0x40 )
                --ptr;
 
-       uniqueEPGKey service( HILO(eit->service_id), HILO(eit->original_network_id), HILO(eit->transport_stream_id) );
+       // Cablecom HACK .. tsid / onid in eit data are incorrect.. so we use
+       // it from running channel (just for current transport stream eit data)
+       bool use_transponder_chid = source == SCHEDULE || (source == NOWNEXT && data[0] == 0x4E);
+       eDVBChannelID chid = channel->channel->getChannelID();
+       uniqueEPGKey service( HILO(eit->service_id),
+               use_transponder_chid ? chid.original_network_id.get() : HILO(eit->original_network_id),
+               use_transponder_chid ? chid.transport_stream_id.get() : HILO(eit->transport_stream_id));
+
        eit_event_struct* eit_event = (eit_event_struct*) (data+ptr);
        int eit_event_size;
        int duration;
 
        eit_event_struct* eit_event = (eit_event_struct*) (data+ptr);
        int eit_event_size;
        int duration;
 
-       time_t TM = parseDVBtime( eit_event->start_time_1, eit_event->start_time_2,     eit_event->start_time_3, eit_event->start_time_4, eit_event->start_time_5);
-       time_t now = eDVBLocalTimeHandler::getInstance()->nowTime();
+       time_t TM = parseDVBtime(
+                       eit_event->start_time_1,
+                       eit_event->start_time_2,
+                       eit_event->start_time_3,
+                       eit_event->start_time_4,
+                       eit_event->start_time_5);
+       time_t now = ::time(0);
 
        if ( TM != 3599 && TM > -1)
                channel->haveData |= source;
 
        if ( TM != 3599 && TM > -1)
                channel->haveData |= source;
@@ -449,6 +533,7 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
 
        while (ptr<len)
        {
 
        while (ptr<len)
        {
+               __u16 event_hash;
                eit_event_size = HILO(eit_event->descriptors_loop_length)+EIT_LOOP_SIZE;
 
                duration = fromBCD(eit_event->duration_1)*3600+fromBCD(eit_event->duration_2)*60+fromBCD(eit_event->duration_3);
                eit_event_size = HILO(eit_event->descriptors_loop_length)+EIT_LOOP_SIZE;
 
                duration = fromBCD(eit_event->duration_1)*3600+fromBCD(eit_event->duration_2)*60+fromBCD(eit_event->duration_3);
@@ -457,7 +542,8 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
                        eit_event->start_time_2,
                        eit_event->start_time_3,
                        eit_event->start_time_4,
                        eit_event->start_time_2,
                        eit_event->start_time_3,
                        eit_event->start_time_4,
-                       eit_event->start_time_5);
+                       eit_event->start_time_5,
+                       &event_hash);
 
                if ( TM == 3599 )
                        goto next;
 
                if ( TM == 3599 )
                        goto next;
@@ -468,16 +554,24 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
                if ( now <= (TM+duration) || TM == 3599 /*NVOD Service*/ )  // old events should not be cached
                {
                        __u16 event_id = HILO(eit_event->event_id);
                if ( now <= (TM+duration) || TM == 3599 /*NVOD Service*/ )  // old events should not be cached
                {
                        __u16 event_id = HILO(eit_event->event_id);
-//                     eDebug("event_id is %d sid is %04x", event_id, service.sid);
-
                        eventData *evt = 0;
                        int ev_erase_count = 0;
                        int tm_erase_count = 0;
 
                        eventData *evt = 0;
                        int ev_erase_count = 0;
                        int tm_erase_count = 0;
 
+                       if (event_id == 0) {
+                               // hack for some polsat services on 13.0E..... but this also replaces other valid event_ids with value 0..
+                               // but we dont care about it...
+                               event_id = event_hash;
+                               eit_event->event_id_hi = event_hash >> 8;
+                               eit_event->event_id_lo = event_hash & 0xFF;
+                       }
+
                        // search in eventmap
                        eventMap::iterator ev_it =
                                servicemap.first.find(event_id);
 
                        // search in eventmap
                        eventMap::iterator ev_it =
                                servicemap.first.find(event_id);
 
+//                     eDebug("event_id is %d sid is %04x", event_id, service.sid);
+
                        // entry with this event_id is already exist ?
                        if ( ev_it != servicemap.first.end() )
                        {
                        // entry with this event_id is already exist ?
                        if ( ev_it != servicemap.first.end() )
                        {
@@ -493,10 +587,15 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
                                        if ( tm_it_tmp->first == TM ) // just update eventdata
                                        {
                                                // exempt memory
                                        if ( tm_it_tmp->first == TM ) // just update eventdata
                                        {
                                                // exempt memory
-                                               delete ev_it->second;
+                                               eventData *tmp = ev_it->second;
                                                ev_it->second = tm_it_tmp->second =
                                                        new eventData(eit_event, eit_event_size, source);
                                                ev_it->second = tm_it_tmp->second =
                                                        new eventData(eit_event, eit_event_size, source);
-                                               FixOverlapping(servicemap, TM, duration, tm_it_tmp, service);
+                                               if (FixOverlapping(servicemap, TM, duration, tm_it_tmp, service))
+                                               {
+                                                       prevEventIt = servicemap.first.end();
+                                                       prevTimeIt = servicemap.second.end();
+                                               }
+                                               delete tmp;
                                                goto next;
                                        }
                                        else  // event has new event begin time
                                                goto next;
                                        }
                                        else  // event has new event begin time
@@ -533,7 +632,6 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
                                        prevEventIt=servicemap.first.end();
                                }
                        }
                                        prevEventIt=servicemap.first.end();
                                }
                        }
-
                        evt = new eventData(eit_event, eit_event_size, source);
 #ifdef EPG_DEBUG
                        bool consistencyCheck=true;
                        evt = new eventData(eit_event, eit_event_size, source);
 #ifdef EPG_DEBUG
                        bool consistencyCheck=true;
@@ -569,8 +667,6 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
                                tm_it=prevTimeIt=servicemap.second.insert( prevTimeIt, std::pair<const time_t, eventData*>( TM, evt ) );
                        }
 
                                tm_it=prevTimeIt=servicemap.second.insert( prevTimeIt, std::pair<const time_t, eventData*>( TM, evt ) );
                        }
 
-                       FixOverlapping(servicemap, TM, duration, tm_it, service);
-
 #ifdef EPG_DEBUG
                        if ( consistencyCheck )
                        {
 #ifdef EPG_DEBUG
                        if ( consistencyCheck )
                        {
@@ -590,6 +686,11 @@ void eEPGCache::sectionRead(const __u8 *data, int source, channel_data *channel)
                                                ev_it->first, event_id );
                        }
 #endif
                                                ev_it->first, event_id );
                        }
 #endif
+                       if (FixOverlapping(servicemap, TM, duration, tm_it, service))
+                       {
+                               prevEventIt = servicemap.first.end();
+                               prevTimeIt = servicemap.second.end();
+                       }
                }
 next:
 #ifdef EPG_DEBUG
                }
 next:
 #ifdef EPG_DEBUG
@@ -680,7 +781,7 @@ void eEPGCache::cleanLoop()
        {
                eDebug("[EPGC] start cleanloop");
 
        {
                eDebug("[EPGC] start cleanloop");
 
-               time_t now = eDVBLocalTimeHandler::getInstance()->nowTime();
+               time_t now = ::time(0);
 
                for (eventCache::iterator DBIt = eventDB.begin(); DBIt != eventDB.end(); DBIt++)
                {
 
                for (eventCache::iterator DBIt = eventDB.begin(); DBIt != eventDB.end(); DBIt++)
                {
@@ -738,7 +839,7 @@ void eEPGCache::cleanLoop()
                eDebug("[EPGC] stop cleanloop");
                eDebug("[EPGC] %i bytes for cache used", eventData::CacheSize);
        }
                eDebug("[EPGC] stop cleanloop");
                eDebug("[EPGC] %i bytes for cache used", eventData::CacheSize);
        }
-       cleanTimer.start(CLEAN_INTERVAL,true);
+       cleanTimer->start(CLEAN_INTERVAL,true);
 }
 
 eEPGCache::~eEPGCache()
 }
 
 eEPGCache::~eEPGCache()
@@ -799,10 +900,10 @@ void eEPGCache::gotMessage( const Message &msg )
                                        onid |= 0x80000000;  // we use highest bit as private epg indicator
                                        chid.original_network_id = onid;
                                        updateMap::iterator It = channelLastUpdated.find( chid );
                                        onid |= 0x80000000;  // we use highest bit as private epg indicator
                                        chid.original_network_id = onid;
                                        updateMap::iterator It = channelLastUpdated.find( chid );
-                                       int update = ( It != channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (eDVBLocalTimeHandler::getInstance()->nowTime()-It->second) * 1000 ) ) : ZAP_DELAY );
+                                       int update = ( It != channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (::time(0)-It->second) * 1000 ) ) : ZAP_DELAY );
                                        if (update < ZAP_DELAY)
                                                update = ZAP_DELAY;
                                        if (update < ZAP_DELAY)
                                                update = ZAP_DELAY;
-                                       data->startPrivateTimer.start(update, 1);
+                                       data->startPrivateTimer->start(update, 1);
                                        if (update >= 60000)
                                                eDebug("[EPGC] next private update in %i min", update/60000);
                                        else if (update >= 1000)
                                        if (update >= 60000)
                                                eDebug("[EPGC] next private update in %i min", update/60000);
                                        else if (update >= 1000)
@@ -812,6 +913,62 @@ void eEPGCache::gotMessage( const Message &msg )
                        }
                        break;
                }
                        }
                        break;
                }
+#endif
+#ifdef ENABLE_MHW_EPG
+               case Message::got_mhw2_channel_pid:
+               {
+                       singleLock s(channel_map_lock);
+                       for (channelMapIterator it(m_knownChannels.begin()); it != m_knownChannels.end(); ++it)
+                       {
+                               eDVBChannel *channel = (eDVBChannel*) it->first;
+                               channel_data *data = it->second;
+                               eDVBChannelID chid = channel->getChannelID();
+                               if ( chid.transport_stream_id.get() == msg.service.tsid &&
+                                       chid.original_network_id.get() == msg.service.onid )
+                               {
+                                       data->m_mhw2_channel_pid = msg.pid;
+                                       eDebug("[EPGC] got mhw2 channel pid %04x", msg.pid);
+                                       break;
+                               }
+                       }
+                       break;
+               }
+               case Message::got_mhw2_title_pid:
+               {
+                       singleLock s(channel_map_lock);
+                       for (channelMapIterator it(m_knownChannels.begin()); it != m_knownChannels.end(); ++it)
+                       {
+                               eDVBChannel *channel = (eDVBChannel*) it->first;
+                               channel_data *data = it->second;
+                               eDVBChannelID chid = channel->getChannelID();
+                               if ( chid.transport_stream_id.get() == msg.service.tsid &&
+                                       chid.original_network_id.get() == msg.service.onid )
+                               {
+                                       data->m_mhw2_title_pid = msg.pid;
+                                       eDebug("[EPGC] got mhw2 title pid %04x", msg.pid);
+                                       break;
+                               }
+                       }
+                       break;
+               }
+               case Message::got_mhw2_summary_pid:
+               {
+                       singleLock s(channel_map_lock);
+                       for (channelMapIterator it(m_knownChannels.begin()); it != m_knownChannels.end(); ++it)
+                       {
+                               eDVBChannel *channel = (eDVBChannel*) it->first;
+                               channel_data *data = it->second;
+                               eDVBChannelID chid = channel->getChannelID();
+                               if ( chid.transport_stream_id.get() == msg.service.tsid &&
+                                       chid.original_network_id.get() == msg.service.onid )
+                               {
+                                       data->m_mhw2_summary_pid = msg.pid;
+                                       eDebug("[EPGC] got mhw2 summary pid %04x", msg.pid);
+                                       break;
+                               }
+                       }
+                       break;
+               }
 #endif
                case Message::timeChanged:
                        cleanLoop();
 #endif
                case Message::timeChanged:
                        cleanLoop();
@@ -825,39 +982,24 @@ void eEPGCache::gotMessage( const Message &msg )
 void eEPGCache::thread()
 {
        hasStarted();
 void eEPGCache::thread()
 {
        hasStarted();
+       m_running=1;
        nice(4);
        load();
        cleanLoop();
        runLoop();
        save();
        nice(4);
        load();
        cleanLoop();
        runLoop();
        save();
+       m_running=0;
 }
 
 void eEPGCache::load()
 {
 }
 
 void eEPGCache::load()
 {
-       singleLock s(cache_lock);
-       FILE *f = fopen("/hdd/epg.dat", "r");
+       FILE *f = fopen(m_filename, "r");
        if (f)
        {
        if (f)
        {
+               unlink(m_filename);
                int size=0;
                int cnt=0;
                int size=0;
                int cnt=0;
-#if 0
-               unsigned char md5_saved[16];
-               unsigned char md5[16];
-               bool md5ok=false;
 
 
-               if (!md5_file("/hdd/epg.dat", 1, md5))
-               {
-                       FILE *f = fopen("/hdd/epg.dat.md5", "r");
-                       if (f)
-                       {
-                               fread( md5_saved, 16, 1, f);
-                               fclose(f);
-                               if ( !memcmp(md5_saved, md5, 16) )
-                                       md5ok=true;
-                       }
-               }
-               if ( md5ok )
-#endif
                {
                        unsigned int magic=0;
                        fread( &magic, sizeof(int), 1, f);
                {
                        unsigned int magic=0;
                        fread( &magic, sizeof(int), 1, f);
@@ -869,8 +1011,9 @@ void eEPGCache::load()
                        }
                        char text1[13];
                        fread( text1, 13, 1, f);
                        }
                        char text1[13];
                        fread( text1, 13, 1, f);
-                       if ( !strncmp( text1, "ENIGMA_EPG_V5", 13) )
+                       if ( !strncmp( text1, "ENIGMA_EPG_V7", 13) )
                        {
                        {
+                               singleLock s(cache_lock);
                                fread( &size, sizeof(int), 1, f);
                                while(size--)
                                {
                                fread( &size, sizeof(int), 1, f);
                                while(size--)
                                {
@@ -898,7 +1041,7 @@ void eEPGCache::load()
                                        eventDB[key]=std::pair<eventMap,timeMap>(evMap,tmMap);
                                }
                                eventData::load(f);
                                        eventDB[key]=std::pair<eventMap,timeMap>(evMap,tmMap);
                                }
                                eventData::load(f);
-                               eDebug("[EPGC] %d events read from /hdd/epg.dat", cnt);
+                               eDebug("[EPGC] %d events read from %s", cnt, m_filename);
 #ifdef ENABLE_PRIVATE_EPG
                                char text2[11];
                                fread( text2, 11, 1, f);
 #ifdef ENABLE_PRIVATE_EPG
                                char text2[11];
                                fread( text2, 11, 1, f);
@@ -946,113 +1089,121 @@ void eEPGCache::load()
 
 void eEPGCache::save()
 {
 
 void eEPGCache::save()
 {
-       struct statfs s;
-       off64_t tmp;
-       if (statfs("/hdd", &s)<0)
-               tmp=0;
-       else
+       /* create empty file */
+       FILE *f = fopen(m_filename, "w");
+
+       if (!f)
        {
        {
-               tmp=s.f_blocks;
-               tmp*=s.f_bsize;
+               eDebug("[EPGC] couldn't save epg data to '%s'(%m)", m_filename);
+               return;
        }
 
        }
 
-       // prevent writes to builtin flash
-       if ( tmp < 1024*1024*50 ) // storage size < 50MB
+       char *buf = realpath(m_filename, NULL);
+       if (!buf)
+       {
+               eDebug("[EPGC] realpath to '%s' failed in save (%m)", m_filename);
+               fclose(f);
                return;
                return;
+       }
+
+       eDebug("[EPGC] store epg to realpath '%s'", buf);
+
+       struct statfs s;
+       off64_t tmp;
+       if (statfs(buf, &s) < 0) {
+               eDebug("[EPGC] statfs '%s' failed in save (%m)", buf);
+               fclose(f);
+               return;
+       }
+
+       free(buf);
 
        // check for enough free space on storage
        tmp=s.f_bfree;
        tmp*=s.f_bsize;
        if ( tmp < (eventData::CacheSize*12)/10 ) // 20% overhead
 
        // check for enough free space on storage
        tmp=s.f_bfree;
        tmp*=s.f_bsize;
        if ( tmp < (eventData::CacheSize*12)/10 ) // 20% overhead
+       {
+               eDebug("[EPGC] not enough free space at path '%s' %lld bytes availd but %d needed", buf, tmp, (eventData::CacheSize*12)/10);
+               fclose(f);
                return;
                return;
+       }
 
 
-       FILE *f = fopen("/hdd/epg.dat", "w");
        int cnt=0;
        int cnt=0;
-       if ( f )
-       {
-               unsigned int magic = 0x98765432;
-               fwrite( &magic, sizeof(int), 1, f);
-               const char *text = "ENIGMA_EPG_V5";
-               fwrite( text, 13, 1, f );
-               int size = eventDB.size();
-               fwrite( &size, sizeof(int), 1, f );
-               for (eventCache::iterator service_it(eventDB.begin()); service_it != eventDB.end(); ++service_it)
-               {
-                       timeMap &timemap = service_it->second.second;
-                       fwrite( &service_it->first, sizeof(uniqueEPGKey), 1, f);
-                       size = timemap.size();
-                       fwrite( &size, sizeof(int), 1, f);
-                       for (timeMap::iterator time_it(timemap.begin()); time_it != timemap.end(); ++time_it)
-                       {
-                               __u8 len = time_it->second->ByteSize;
-                               fwrite( &time_it->second->type, sizeof(__u8), 1, f );
-                               fwrite( &len, sizeof(__u8), 1, f);
-                               fwrite( time_it->second->EITdata, len, 1, f);
-                               ++cnt;
-                       }
+       unsigned int magic = 0x98765432;
+       fwrite( &magic, sizeof(int), 1, f);
+       const char *text = "UNFINISHED_V7";
+       fwrite( text, 13, 1, f );
+       int size = eventDB.size();
+       fwrite( &size, sizeof(int), 1, f );
+       for (eventCache::iterator service_it(eventDB.begin()); service_it != eventDB.end(); ++service_it)
+       {
+               timeMap &timemap = service_it->second.second;
+               fwrite( &service_it->first, sizeof(uniqueEPGKey), 1, f);
+               size = timemap.size();
+               fwrite( &size, sizeof(int), 1, f);
+               for (timeMap::iterator time_it(timemap.begin()); time_it != timemap.end(); ++time_it)
+               {
+                       __u8 len = time_it->second->ByteSize;
+                       fwrite( &time_it->second->type, sizeof(__u8), 1, f );
+                       fwrite( &len, sizeof(__u8), 1, f);
+                       fwrite( time_it->second->EITdata, len, 1, f);
+                       ++cnt;
                }
                }
-               eDebug("[EPGC] %d events written to /hdd/epg.dat", cnt);
-               eventData::save(f);
+       }
+       eDebug("[EPGC] %d events written to %s", cnt, m_filename);
+       eventData::save(f);
 #ifdef ENABLE_PRIVATE_EPG
 #ifdef ENABLE_PRIVATE_EPG
-               const char* text3 = "PRIVATE_EPG";
-               fwrite( text3, 11, 1, f );
-               size = content_time_tables.size();
+       const char* text3 = "PRIVATE_EPG";
+       fwrite( text3, 11, 1, f );
+       size = content_time_tables.size();
+       fwrite( &size, sizeof(int), 1, f);
+       for (contentMaps::iterator a = content_time_tables.begin(); a != content_time_tables.end(); ++a)
+       {
+               contentMap &content_time_table = a->second;
+               fwrite( &a->first, sizeof(uniqueEPGKey), 1, f);
+               int size = content_time_table.size();
                fwrite( &size, sizeof(int), 1, f);
                fwrite( &size, sizeof(int), 1, f);
-               for (contentMaps::iterator a = content_time_tables.begin(); a != content_time_tables.end(); ++a)
+               for (contentMap::iterator i = content_time_table.begin(); i != content_time_table.end(); ++i )
                {
                {
-                       contentMap &content_time_table = a->second;
-                       fwrite( &a->first, sizeof(uniqueEPGKey), 1, f);
-                       int size = content_time_table.size();
+                       int size = i->second.size();
+                       fwrite( &i->first, sizeof(int), 1, f);
                        fwrite( &size, sizeof(int), 1, f);
                        fwrite( &size, sizeof(int), 1, f);
-                       for (contentMap::iterator i = content_time_table.begin(); i != content_time_table.end(); ++i )
+                       for ( contentTimeMap::iterator it(i->second.begin());
+                               it != i->second.end(); ++it )
                        {
                        {
-                               int size = i->second.size();
-                               fwrite( &i->first, sizeof(int), 1, f);
-                               fwrite( &size, sizeof(int), 1, f);
-                               for ( contentTimeMap::iterator it(i->second.begin());
-                                       it != i->second.end(); ++it )
-                               {
-                                       fwrite( &it->first, sizeof(time_t), 1, f);
-                                       fwrite( &it->second.first, sizeof(time_t), 1, f);
-                                       fwrite( &it->second.second, sizeof(__u16), 1, f);
-                               }
+                               fwrite( &it->first, sizeof(time_t), 1, f);
+                               fwrite( &it->second.first, sizeof(time_t), 1, f);
+                               fwrite( &it->second.second, sizeof(__u16), 1, f);
                        }
                }
                        }
                }
-#endif
-               fclose(f);
-#if 0
-               unsigned char md5[16];
-               if (!md5_file("/hdd/epg.dat", 1, md5))
-               {
-                       FILE *f = fopen("/hdd/epg.dat.md5", "w");
-                       if (f)
-                       {
-                               fwrite( md5, 16, 1, f);
-                               fclose(f);
-                       }
-               }
-#endif
        }
        }
+#endif
+       // write version string after binary data
+       // has been written to disk.
+       fsync(fileno(f));
+       fseek(f, sizeof(int), SEEK_SET);
+       fwrite("ENIGMA_EPG_V7", 13, 1, f);
+       fclose(f);
 }
 
 eEPGCache::channel_data::channel_data(eEPGCache *ml)
        :cache(ml)
 }
 
 eEPGCache::channel_data::channel_data(eEPGCache *ml)
        :cache(ml)
-       ,abortTimer(ml), zapTimer(ml), state(0)
+       ,abortTimer(eTimer::create(ml)), zapTimer(eTimer::create(ml)), state(-1)
        ,isRunning(0), haveData(0)
 #ifdef ENABLE_PRIVATE_EPG
        ,isRunning(0), haveData(0)
 #ifdef ENABLE_PRIVATE_EPG
-       ,startPrivateTimer(ml)
+       ,startPrivateTimer(eTimer::create(ml))
 #endif
 #ifdef ENABLE_MHW_EPG
 #endif
 #ifdef ENABLE_MHW_EPG
-       ,m_MHWTimeoutTimer(ml)
+       ,m_MHWTimeoutTimer(eTimer::create(ml))
 #endif
 {
 #ifdef ENABLE_MHW_EPG
 #endif
 {
 #ifdef ENABLE_MHW_EPG
-       CONNECT(m_MHWTimeoutTimer.timeout, eEPGCache::channel_data::MHWTimeout);
+       CONNECT(m_MHWTimeoutTimer->timeout, eEPGCache::channel_data::MHWTimeout);
 #endif
 #endif
-       CONNECT(zapTimer.timeout, eEPGCache::channel_data::startEPG);
-       CONNECT(abortTimer.timeout, eEPGCache::channel_data::abortNonAvail);
+       CONNECT(zapTimer->timeout, eEPGCache::channel_data::startEPG);
+       CONNECT(abortTimer->timeout, eEPGCache::channel_data::abortNonAvail);
 #ifdef ENABLE_PRIVATE_EPG
 #ifdef ENABLE_PRIVATE_EPG
-       CONNECT(startPrivateTimer.timeout, eEPGCache::channel_data::startPrivateReader);
+       CONNECT(startPrivateTimer->timeout, eEPGCache::channel_data::startPrivateReader);
 #endif
        pthread_mutex_init(&channel_active, 0);
 }
 #endif
        pthread_mutex_init(&channel_active, 0);
 }
@@ -1061,16 +1212,16 @@ bool eEPGCache::channel_data::finishEPG()
 {
        if (!isRunning)  // epg ready
        {
 {
        if (!isRunning)  // epg ready
        {
-               eDebug("[EPGC] stop caching events(%ld)", eDVBLocalTimeHandler::getInstance()->nowTime());
-               zapTimer.start(UPDATE_INTERVAL, 1);
+               eDebug("[EPGC] stop caching events(%ld)", ::time(0));
+               zapTimer->start(UPDATE_INTERVAL, 1);
                eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000);
                eDebug("[EPGC] next update in %i min", UPDATE_INTERVAL / 60000);
-               for (int i=0; i < 3; ++i)
+               for (unsigned int i=0; i < sizeof(seenSections)/sizeof(tidMap); ++i)
                {
                        seenSections[i].clear();
                        calcedSections[i].clear();
                }
                singleLock l(cache->cache_lock);
                {
                        seenSections[i].clear();
                        calcedSections[i].clear();
                }
                singleLock l(cache->cache_lock);
-               cache->channelLastUpdated[channel->getChannelID()] = eDVBLocalTimeHandler::getInstance()->nowTime();
+               cache->channelLastUpdated[channel->getChannelID()] = ::time(0);
 #ifdef ENABLE_MHW_EPG
                cleanup();
 #endif
 #ifdef ENABLE_MHW_EPG
                cleanup();
 #endif
@@ -1081,10 +1232,10 @@ bool eEPGCache::channel_data::finishEPG()
 
 void eEPGCache::channel_data::startEPG()
 {
 
 void eEPGCache::channel_data::startEPG()
 {
-       eDebug("[EPGC] start caching events(%ld)", eDVBLocalTimeHandler::getInstance()->nowTime());
+       eDebug("[EPGC] start caching events(%ld)", ::time(0));
        state=0;
        haveData=0;
        state=0;
        haveData=0;
-       for (int i=0; i < 3; ++i)
+       for (unsigned int i=0; i < sizeof(seenSections)/sizeof(tidMap); ++i)
        {
                seenSections[i].clear();
                calcedSections[i].clear();
        {
                seenSections[i].clear();
                calcedSections[i].clear();
@@ -1102,7 +1253,7 @@ void eEPGCache::channel_data::startEPG()
        isRunning |= MHW;
        memcpy(&m_MHWFilterMask, &mask, sizeof(eDVBSectionFilterMask));
 
        isRunning |= MHW;
        memcpy(&m_MHWFilterMask, &mask, sizeof(eDVBSectionFilterMask));
 
-       mask.pid = 0x231;
+       mask.pid = m_mhw2_channel_pid;
        mask.data[0] = 0xC8;
        mask.mask[0] = 0xFF;
        mask.data[1] = 0;
        mask.data[0] = 0xC8;
        mask.mask[0] = 0xFF;
        mask.data[1] = 0;
@@ -1113,6 +1264,7 @@ void eEPGCache::channel_data::startEPG()
        memcpy(&m_MHWFilterMask2, &mask, sizeof(eDVBSectionFilterMask));
        mask.data[1] = 0;
        mask.mask[1] = 0;
        memcpy(&m_MHWFilterMask2, &mask, sizeof(eDVBSectionFilterMask));
        mask.data[1] = 0;
        mask.mask[1] = 0;
+       m_MHWTimeoutet=false;
 #endif
 
        mask.pid = 0x12;
 #endif
 
        mask.pid = 0x12;
@@ -1135,7 +1287,15 @@ void eEPGCache::channel_data::startEPG()
        m_ScheduleOtherReader->start(mask);
        isRunning |= SCHEDULE_OTHER;
 
        m_ScheduleOtherReader->start(mask);
        isRunning |= SCHEDULE_OTHER;
 
-       abortTimer.start(7000,true);
+       mask.pid = 0x39;
+
+       mask.data[0] = 0x40;
+       mask.mask[0] = 0x40;
+       m_ViasatReader->connectRead(slot(*this, &eEPGCache::channel_data::readDataViasat), m_ViasatConn);
+       m_ViasatReader->start(mask);
+       isRunning |= VIASAT;
+
+       abortTimer->start(7000,true);
 }
 
 void eEPGCache::channel_data::abortNonAvail()
 }
 
 void eEPGCache::channel_data::abortNonAvail()
@@ -1158,11 +1318,18 @@ void eEPGCache::channel_data::abortNonAvail()
                }
                if ( !(haveData&SCHEDULE_OTHER) && (isRunning&SCHEDULE_OTHER) )
                {
                }
                if ( !(haveData&SCHEDULE_OTHER) && (isRunning&SCHEDULE_OTHER) )
                {
-                       eDebug("[EPGC] abort non avail schedule_other reading");
+                       eDebug("[EPGC] abort non avail schedule other reading");
                        isRunning &= ~SCHEDULE_OTHER;
                        m_ScheduleOtherReader->stop();
                        m_ScheduleOtherConn=0;
                }
                        isRunning &= ~SCHEDULE_OTHER;
                        m_ScheduleOtherReader->stop();
                        m_ScheduleOtherConn=0;
                }
+               if ( !(haveData&VIASAT) && (isRunning&VIASAT) )
+               {
+                       eDebug("[EPGC] abort non avail viasat reading");
+                       isRunning &= ~VIASAT;
+                       m_ViasatReader->stop();
+                       m_ViasatConn=0;
+               }
 #ifdef ENABLE_MHW_EPG
                if ( !(haveData&MHW) && (isRunning&MHW) )
                {
 #ifdef ENABLE_MHW_EPG
                if ( !(haveData&MHW) && (isRunning&MHW) )
                {
@@ -1174,12 +1341,14 @@ void eEPGCache::channel_data::abortNonAvail()
                        m_MHWConn2=0;
                }
 #endif
                        m_MHWConn2=0;
                }
 #endif
-               if ( isRunning )
-                       abortTimer.start(90000, true);
+               if ( isRunning & VIASAT )
+                       abortTimer->start(300000, true);
+               else if ( isRunning )
+                       abortTimer->start(90000, true);
                else
                {
                        ++state;
                else
                {
                        ++state;
-                       for (int i=0; i < 3; ++i)
+                       for (unsigned int i=0; i < sizeof(seenSections)/sizeof(tidMap); ++i)
                        {
                                seenSections[i].clear();
                                calcedSections[i].clear();
                        {
                                seenSections[i].clear();
                                calcedSections[i].clear();
@@ -1194,12 +1363,12 @@ void eEPGCache::channel_data::startChannel()
        pthread_mutex_lock(&channel_active);
        updateMap::iterator It = cache->channelLastUpdated.find( channel->getChannelID() );
 
        pthread_mutex_lock(&channel_active);
        updateMap::iterator It = cache->channelLastUpdated.find( channel->getChannelID() );
 
-       int update = ( It != cache->channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (eDVBLocalTimeHandler::getInstance()->nowTime()-It->second) * 1000 ) ) : ZAP_DELAY );
+       int update = ( It != cache->channelLastUpdated.end() ? ( UPDATE_INTERVAL - ( (::time(0)-It->second) * 1000 ) ) : ZAP_DELAY );
 
        if (update < ZAP_DELAY)
                update = ZAP_DELAY;
 
 
        if (update < ZAP_DELAY)
                update = ZAP_DELAY;
 
-       zapTimer.start(update, 1);
+       zapTimer->start(update, 1);
        if (update >= 60000)
                eDebug("[EPGC] next update in %i min", update/60000);
        else if (update >= 1000)
        if (update >= 60000)
                eDebug("[EPGC] next update in %i min", update/60000);
        else if (update >= 1000)
@@ -1208,13 +1377,13 @@ void eEPGCache::channel_data::startChannel()
 
 void eEPGCache::channel_data::abortEPG()
 {
 
 void eEPGCache::channel_data::abortEPG()
 {
-       for (int i=0; i < 3; ++i)
+       for (unsigned int i=0; i < sizeof(seenSections)/sizeof(tidMap); ++i)
        {
                seenSections[i].clear();
                calcedSections[i].clear();
        }
        {
                seenSections[i].clear();
                calcedSections[i].clear();
        }
-       abortTimer.stop();
-       zapTimer.stop();
+       abortTimer->stop();
+       zapTimer->stop();
        if (isRunning)
        {
                eDebug("[EPGC] abort caching events !!");
        if (isRunning)
        {
                eDebug("[EPGC] abort caching events !!");
@@ -1236,6 +1405,12 @@ void eEPGCache::channel_data::abortEPG()
                        m_ScheduleOtherReader->stop();
                        m_ScheduleOtherConn=0;
                }
                        m_ScheduleOtherReader->stop();
                        m_ScheduleOtherConn=0;
                }
+               if (isRunning & VIASAT)
+               {
+                       isRunning &= ~VIASAT;
+                       m_ViasatReader->stop();
+                       m_ViasatConn=0;
+               }
 #ifdef ENABLE_MHW_EPG
                if (isRunning & MHW)
                {
 #ifdef ENABLE_MHW_EPG
                if (isRunning & MHW)
                {
@@ -1256,6 +1431,15 @@ void eEPGCache::channel_data::abortEPG()
        pthread_mutex_unlock(&channel_active);
 }
 
        pthread_mutex_unlock(&channel_active);
 }
 
+
+void eEPGCache::channel_data::readDataViasat( const __u8 *data)
+{
+       __u8 *d=0;
+       memcpy(&d, &data, sizeof(__u8*));
+       d[0] |= 0x80;
+       readData(data);
+}
+
 void eEPGCache::channel_data::readData( const __u8 *data)
 {
        int source;
 void eEPGCache::channel_data::readData( const __u8 *data)
 {
        int source;
@@ -1278,13 +1462,19 @@ void eEPGCache::channel_data::readData( const __u8 *data)
                        source=SCHEDULE_OTHER;
                        map=2;
                        break;
                        source=SCHEDULE_OTHER;
                        map=2;
                        break;
+               case 0xD0 ... 0xDF:
+               case 0xE0 ... 0xEF:
+                       reader=m_ViasatReader;
+                       source=VIASAT;
+                       map=3;
+                       break;
                default:
                        eDebug("[EPGC] unknown table_id !!!");
                        return;
        }
        tidMap &seenSections = this->seenSections[map];
        tidMap &calcedSections = this->calcedSections[map];
                default:
                        eDebug("[EPGC] unknown table_id !!!");
                        return;
        }
        tidMap &seenSections = this->seenSections[map];
        tidMap &calcedSections = this->calcedSections[map];
-       if ( state == 1 && calcedSections == seenSections || state > 1 )
+       if ( (state == 1 && calcedSections == seenSections) || state > 1 )
        {
                eDebugNoNewLine("[EPGC] ");
                switch (source)
        {
                eDebugNoNewLine("[EPGC] ");
                switch (source)
@@ -1301,9 +1491,13 @@ void eEPGCache::channel_data::readData( const __u8 *data)
                                m_ScheduleOtherConn=0;
                                eDebugNoNewLine("schedule other");
                                break;
                                m_ScheduleOtherConn=0;
                                eDebugNoNewLine("schedule other");
                                break;
+                       case VIASAT:
+                               m_ViasatConn=0;
+                               eDebugNoNewLine("viasat");
+                               break;
                        default: eDebugNoNewLine("unknown");break;
                }
                        default: eDebugNoNewLine("unknown");break;
                }
-               eDebug(" finished(%ld)", eDVBLocalTimeHandler::getInstance()->nowTime());
+               eDebug(" finished(%ld)", ::time(0));
                if ( reader )
                        reader->stop();
                isRunning &= ~source;
                if ( reader )
                        reader->stop();
                isRunning &= ~source;
@@ -1353,18 +1547,18 @@ RESULT eEPGCache::lookupEventTime(const eServiceReference &service, time_t t, co
        if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached ?
        {
                if (t==-1)
        if ( It != eventDB.end() && !It->second.first.empty() ) // entrys cached ?
        {
                if (t==-1)
-                       t = eDVBLocalTimeHandler::getInstance()->nowTime();
+                       t = ::time(0);
                timeMap::iterator i = direction <= 0 ? It->second.second.lower_bound(t) :  // find > or equal
                        It->second.second.upper_bound(t); // just >
                if ( i != It->second.second.end() )
                {
                timeMap::iterator i = direction <= 0 ? It->second.second.lower_bound(t) :  // find > or equal
                        It->second.second.upper_bound(t); // just >
                if ( i != It->second.second.end() )
                {
-                       if ( direction < 0 || (direction == 0 && i->second->getStartTime() > t) )
+                       if ( direction < 0 || (direction == 0 && i->first > t) )
                        {
                                timeMap::iterator x = i;
                                --x;
                                if ( x != It->second.second.end() )
                                {
                        {
                                timeMap::iterator x = i;
                                --x;
                                if ( x != It->second.second.end() )
                                {
-                                       time_t start_time = x->second->getStartTime();
+                                       time_t start_time = x->first;
                                        if (direction >= 0)
                                        {
                                                if (t < start_time)
                                        if (direction >= 0)
                                        {
                                                if (t < start_time)
@@ -1479,37 +1673,37 @@ RESULT eEPGCache::lookupEventId(const eServiceReference &service, int event_id,
 
 RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin, int minutes)
 {
 
 RESULT eEPGCache::startTimeQuery(const eServiceReference &service, time_t begin, int minutes)
 {
-       Lock();
-       eventCache::iterator It = eventDB.find(handleGroup(service));
+       singleLock s(cache_lock);
+       const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)handleGroup(service);
+       if (begin == -1)
+               begin = ::time(0);
+       eventCache::iterator It = eventDB.find(ref);
        if ( It != eventDB.end() && It->second.second.size() )
        {
        if ( It != eventDB.end() && It->second.second.size() )
        {
-               m_timemap_end = minutes != -1 ? It->second.second.upper_bound(begin+minutes*60) : It->second.second.end();
-               if ( begin != -1 )
+               m_timemap_cursor = It->second.second.lower_bound(begin);
+               if ( m_timemap_cursor != It->second.second.end() )
                {
                {
-                       m_timemap_cursor = It->second.second.lower_bound(begin);
-                       if ( m_timemap_cursor != It->second.second.end() )
+                       if ( m_timemap_cursor->first != begin )
                        {
                        {
-                               if ( m_timemap_cursor->second->getStartTime() != begin )
+                               timeMap::iterator x = m_timemap_cursor;
+                               --x;
+                               if ( x != It->second.second.end() )
                                {
                                {
-                                       timeMap::iterator x = m_timemap_cursor;
-                                       --x;
-                                       if ( x != It->second.second.end() )
-                                       {
-                                               time_t start_time = x->second->getStartTime();
-                                               if ( begin > start_time && begin < (start_time+x->second->getDuration()))
-                                                       m_timemap_cursor = x;
-                                       }
+                                       time_t start_time = x->first;
+                                       if ( begin > start_time && begin < (start_time+x->second->getDuration()))
+                                               m_timemap_cursor = x;
                                }
                        }
                }
                                }
                        }
                }
+
+               if (minutes != -1)
+                       m_timemap_end = It->second.second.lower_bound(begin+minutes*60);
                else
                else
-                       m_timemap_cursor = It->second.second.begin();
-               const eServiceReferenceDVB &ref = (const eServiceReferenceDVB&)handleGroup(service);
+                       m_timemap_end = It->second.second.end();
+
                currentQueryTsidOnid = (ref.getTransportStreamID().get()<<16) | ref.getOriginalNetworkID().get();
                currentQueryTsidOnid = (ref.getTransportStreamID().get()<<16) | ref.getOriginalNetworkID().get();
-               Unlock();
-               return 0;
+               return m_timemap_cursor == m_timemap_end ? -1 : 0;
        }
        }
-       Unlock();
        return -1;
 }
 
        return -1;
 }
 
@@ -1554,14 +1748,15 @@ RESULT eEPGCache::getNextTimeEntry(ePtr<eServiceEvent> &result)
        return -1;
 }
 
        return -1;
 }
 
-void fillTuple(ePyObject tuple, char *argstring, int argcount, ePyObject service, ePtr<eServiceEvent> &ptr, ePyObject nowTime, ePyObject service_name )
+void fillTuple(ePyObject tuple, const char *argstring, int argcount, ePyObject service, eServiceEvent *ptr, ePyObject nowTime, ePyObject service_name )
 {
        ePyObject tmp;
 {
        ePyObject tmp;
-       int pos=0;
-       while(pos < argcount)
+       int spos=0, tpos=0;
+       char c;
+       while(spos < argcount)
        {
                bool inc_refcount=false;
        {
                bool inc_refcount=false;
-               switch(argstring[pos])
+               switch((c=argstring[spos++]))
                {
                        case '0': // PyLong 0
                                tmp = PyLong_FromLong(0);
                {
                        case '0': // PyLong 0
                                tmp = PyLong_FromLong(0);
@@ -1592,9 +1787,17 @@ void fillTuple(ePyObject tuple, char *argstring, int argcount, ePyObject service
                                tmp = service;
                                inc_refcount = true;
                                break;
                                tmp = service;
                                inc_refcount = true;
                                break;
+                       case 'n': // short service name
                        case 'N': // service name
                                tmp = service_name;
                                inc_refcount = true;
                        case 'N': // service name
                                tmp = service_name;
                                inc_refcount = true;
+                               break;
+                       case 'X':
+                               ++argcount;
+                               continue;
+                       default:  // ignore unknown
+                               tmp = ePyObject();
+                               eDebug("fillTuple unknown '%c'... insert 'None' in result", c);
                }
                if (!tmp)
                {
                }
                if (!tmp)
                {
@@ -1603,17 +1806,17 @@ void fillTuple(ePyObject tuple, char *argstring, int argcount, ePyObject service
                }
                if (inc_refcount)
                        Py_INCREF(tmp);
                }
                if (inc_refcount)
                        Py_INCREF(tmp);
-               PyTuple_SET_ITEM(tuple, pos++, tmp);
+               PyTuple_SET_ITEM(tuple, tpos++, tmp);
        }
 }
 
        }
 }
 
-int handleEvent(ePtr<eServiceEvent> &ptr, ePyObject dest_list, char* argstring, int argcount, ePyObject service, ePyObject nowTime, ePyObject service_name, ePyObject convertFunc, ePyObject convertFuncArgs)
+int handleEvent(eServiceEvent *ptr, ePyObject dest_list, const char* argstring, int argcount, ePyObject service, ePyObject nowTime, ePyObject service_name, ePyObject convertFunc, ePyObject convertFuncArgs)
 {
        if (convertFunc)
        {
                fillTuple(convertFuncArgs, argstring, argcount, service, ptr, nowTime, service_name);
                ePyObject result = PyObject_CallObject(convertFunc, convertFuncArgs);
 {
        if (convertFunc)
        {
                fillTuple(convertFuncArgs, argstring, argcount, service, ptr, nowTime, service_name);
                ePyObject result = PyObject_CallObject(convertFunc, convertFuncArgs);
-               if (result)
+               if (!result)
                {
                        if (service_name)
                                Py_DECREF(service_name);
                {
                        if (service_name)
                                Py_DECREF(service_name);
@@ -1651,6 +1854,10 @@ int handleEvent(ePtr<eServiceEvent> &ptr, ePyObject dest_list, char* argstring,
 //   C = Current Time
 //   R = Service Reference
 //   N = Service Name
 //   C = Current Time
 //   R = Service Reference
 //   N = Service Name
+//   n = Short Service Name
+//   X = Return a minimum of one tuple per service in the result list... even when no event was found.
+//       The returned tuple is filled with all available infos... non avail is filled as None
+//       The position and existence of 'X' in the format string has no influence on the result tuple... its completely ignored..
 // then for each service follows a tuple
 //   first tuple entry is the servicereference (as string... use the ref.toString() function)
 //   the second is the type of query
 // then for each service follows a tuple
 //   first tuple entry is the servicereference (as string... use the ref.toString() function)
 //   the second is the type of query
@@ -1660,14 +1867,14 @@ int handleEvent(ePtr<eServiceEvent> &ptr, ePyObject dest_list, char* argstring,
 //    +1 = event after given start_time
 //   the third
 //      when type is eventid it is the event_id
 //    +1 = event after given start_time
 //   the third
 //      when type is eventid it is the event_id
-//      when type is time then it is the start_time ( 0 for now_time )
+//      when type is time then it is the start_time ( -1 for now_time )
 //   the fourth is the end_time .. ( optional .. for query all events in time range)
 
 PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc)
 {
        ePyObject convertFuncArgs;
        int argcount=0;
 //   the fourth is the end_time .. ( optional .. for query all events in time range)
 
 PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc)
 {
        ePyObject convertFuncArgs;
        int argcount=0;
-       char *argstring=NULL;
+       const char *argstring=NULL;
        if (!PyList_Check(list))
        {
                PyErr_SetString(PyExc_StandardError,
        if (!PyList_Check(list))
        {
                PyErr_SetString(PyExc_StandardError,
@@ -1697,6 +1904,11 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc)
                argcount = strlen(argstring);
 //             eDebug("have %d args('%s')", argcount, argstring);
        }
                argcount = strlen(argstring);
 //             eDebug("have %d args('%s')", argcount, argstring);
        }
+
+       bool forceReturnOne = strchr(argstring, 'X') ? true : false;
+       if (forceReturnOne)
+               --argcount;
+
        if (convertFunc)
        {
                if (!PyCallable_Check(convertFunc))
        if (convertFunc)
        {
                if (!PyCallable_Check(convertFunc))
@@ -1710,10 +1922,10 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc)
        }
 
        ePyObject nowTime = strchr(argstring, 'C') ?
        }
 
        ePyObject nowTime = strchr(argstring, 'C') ?
-               PyLong_FromLong(eDVBLocalTimeHandler::getInstance()->nowTime()) :
+               PyLong_FromLong(::time(0)) :
                ePyObject();
 
                ePyObject();
 
-       bool must_get_service_name = strchr(argstring, 'N') ? true : false;
+       int must_get_service_name = strchr(argstring, 'N') ? 1 : strchr(argstring, 'n') ? 2 : 0;
 
        // create dest list
        ePyObject dest_list=PyList_New(0);
 
        // create dest list
        ePyObject dest_list=PyList_New(0);
@@ -1764,6 +1976,10 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc)
                                                break;
                                }
                        }
                                                break;
                                }
                        }
+
+                       if (minutes && stime == -1)
+                               stime = ::time(0);
+
                        eServiceReference ref(handleGroup(eServiceReference(PyString_AS_STRING(service))));
                        if (ref.type != eServiceReference::idDVB)
                        {
                        eServiceReference ref(handleGroup(eServiceReference(PyString_AS_STRING(service))));
                        if (ref.type != eServiceReference::idDVB)
                        {
@@ -1801,6 +2017,19 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc)
                                        {
                                                std::string name;
                                                sptr->getName(ref, name);
                                        {
                                                std::string name;
                                                sptr->getName(ref, name);
+
+                                               if (must_get_service_name == 1)
+                                               {
+                                                       size_t pos;
+                                                       // filter short name brakets
+                                                       while((pos = name.find("\xc2\x86")) != std::string::npos)
+                                                               name.erase(pos,2);
+                                                       while((pos = name.find("\xc2\x87")) != std::string::npos)
+                                                               name.erase(pos,2);
+                                               }
+                                               else
+                                                       name = buildShortName(name);
+
                                                if (name.length())
                                                        service_name = PyString_FromString(name.c_str());
                                        }
                                                if (name.length())
                                                        service_name = PyString_FromString(name.c_str());
                                        }
@@ -1810,32 +2039,45 @@ PyObject *eEPGCache::lookupEvent(ePyObject list, ePyObject convertFunc)
                        }
                        if (minutes)
                        {
                        }
                        if (minutes)
                        {
-                               Lock();
+                               singleLock s(cache_lock);
                                if (!startTimeQuery(ref, stime, minutes))
                                {
                                if (!startTimeQuery(ref, stime, minutes))
                                {
-                                       ePtr<eServiceEvent> ptr;
-                                       while (!getNextTimeEntry(ptr))
+                                       while ( m_timemap_cursor != m_timemap_end )
                                        {
                                        {
-                                               if (handleEvent(ptr, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs))
-                                               {
-                                                       Unlock();
+                                               Event ev((uint8_t*)m_timemap_cursor++->second->get());
+                                               eServiceEvent evt;
+                                               evt.parseFrom(&ev, currentQueryTsidOnid);
+                                               if (handleEvent(&evt, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs))
                                                        return 0;  // error
                                                        return 0;  // error
-                                               }
                                        }
                                }
                                        }
                                }
-                               Unlock();
+                               else if (forceReturnOne && handleEvent(0, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs))
+                                       return 0;  // error
                        }
                        else
                        {
                        }
                        else
                        {
-                               ePtr<eServiceEvent> ptr;
+                               eServiceEvent evt;
+                               const eventData *ev_data=0;
                                if (stime)
                                {
                                if (stime)
                                {
+                                       singleLock s(cache_lock);
                                        if (type == 2)
                                        if (type == 2)
-                                               lookupEventId(ref, event_id, ptr);
+                                               lookupEventId(ref, event_id, ev_data);
                                        else
                                        else
-                                               lookupEventTime(ref, stime, ptr, type);
+                                               lookupEventTime(ref, stime, ev_data, type);
+                                       if (ev_data)
+                                       {
+                                               const eServiceReferenceDVB &dref = (const eServiceReferenceDVB&)ref;
+                                               Event ev((uint8_t*)ev_data->get());
+                                               evt.parseFrom(&ev, (dref.getTransportStreamID().get()<<16)|dref.getOriginalNetworkID().get());
+                                       }
                                }
                                }
-                               if (handleEvent(ptr, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs))
+                               if (ev_data)
+                               {
+                                       if (handleEvent(&evt, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs))
+                                               return 0; // error
+                               }
+                               else if (forceReturnOne && handleEvent(0, dest_list, argstring, argcount, service, nowTime, service_name, convertFunc, convertFuncArgs))
                                        return 0; // error
                        }
                        if (service_changed)
                                        return 0; // error
                        }
                        if (service_changed)
@@ -1853,7 +2095,7 @@ skip_entry:
        return dest_list;
 }
 
        return dest_list;
 }
 
-void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData *evData, ePtr<eServiceEvent> &ptr, ePyObject service_name, ePyObject service_reference)
+void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData *evData, eServiceEvent *ptr, ePyObject service_name, ePyObject service_reference)
 {
        ePyObject tmp;
        int pos=0;
 {
        ePyObject tmp;
        int pos=0;
@@ -1893,10 +2135,14 @@ void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData
                                tmp = service_reference;
                                inc_refcount = true;
                                break;
                                tmp = service_reference;
                                inc_refcount = true;
                                break;
+                       case 'n': // short service name
                        case 'N': // service name
                                tmp = service_name;
                                inc_refcount = true;
                                break;
                        case 'N': // service name
                                tmp = service_name;
                                inc_refcount = true;
                                break;
+                       default:  // ignore unknown
+                               tmp = ePyObject();
+                               eDebug("fillTuple2 unknown '%c'... insert None in Result", argstring[pos]);
                }
                if (!tmp)
                {
                }
                if (!tmp)
                {
@@ -1919,6 +2165,7 @@ void fillTuple2(ePyObject tuple, const char *argstring, int argcount, eventData
 //   E = Event Extended Description
 //   R = Service Reference
 //   N = Service Name
 //   E = Event Extended Description
 //   R = Service Reference
 //   N = Service Name
+//   n = Short Service Name
 //  the second tuple entry is the MAX matches value
 //  the third tuple entry is the type of query
 //     0 = search for similar broadcastings (SIMILAR_BROADCASTINGS_SEARCH)
 //  the second tuple entry is the MAX matches value
 //  the third tuple entry is the type of query
 //     0 = search for similar broadcastings (SIMILAR_BROADCASTINGS_SEARCH)
@@ -1945,6 +2192,8 @@ PyObject *eEPGCache::search(ePyObject arg)
        int querytype=-1;
        bool needServiceEvent=false;
        int maxmatches=0;
        int querytype=-1;
        bool needServiceEvent=false;
        int maxmatches=0;
+       int must_get_service_name = 0;
+       bool must_get_service_reference = false;
 
        if (PyTuple_Check(arg))
        {
 
        if (PyTuple_Check(arg))
        {
@@ -1954,7 +2203,11 @@ PyObject *eEPGCache::search(ePyObject arg)
                        ePyObject obj = PyTuple_GET_ITEM(arg,0);
                        if (PyString_Check(obj))
                        {
                        ePyObject obj = PyTuple_GET_ITEM(arg,0);
                        if (PyString_Check(obj))
                        {
+#if PY_VERSION_HEX < 0x02060000
                                argcount = PyString_GET_SIZE(obj);
                                argcount = PyString_GET_SIZE(obj);
+#else
+                               argcount = PyString_Size(obj);
+#endif
                                argstring = PyString_AS_STRING(obj);
                                for (int i=0; i < argcount; ++i)
                                        switch(argstring[i])
                                argstring = PyString_AS_STRING(obj);
                                for (int i=0; i < argcount; ++i)
                                        switch(argstring[i])
@@ -1963,6 +2216,16 @@ PyObject *eEPGCache::search(ePyObject arg)
                                        case 'E':
                                        case 'T':
                                                needServiceEvent=true;
                                        case 'E':
                                        case 'T':
                                                needServiceEvent=true;
+                                               break;
+                                       case 'N':
+                                               must_get_service_name = 1;
+                                               break;
+                                       case 'n':
+                                               must_get_service_name = 2;
+                                               break;
+                                       case 'R':
+                                               must_get_service_reference = true;
+                                               break;
                                        default:
                                                break;
                                        }
                                        default:
                                                break;
                                        }
@@ -1996,10 +2259,10 @@ PyObject *eEPGCache::search(ePyObject arg)
                                                if (evData)
                                                {
                                                        __u8 *data = evData->EITdata;
                                                if (evData)
                                                {
                                                        __u8 *data = evData->EITdata;
-                                                       int tmp = evData->ByteSize-12;
-                                                       __u32 *p = (__u32*)(data+12);
+                                                       int tmp = evData->ByteSize-10;
+                                                       __u32 *p = (__u32*)(data+10);
                                                                // search short and extended event descriptors
                                                                // search short and extended event descriptors
-                                                       while(tmp>0)
+                                                       while(tmp>3)
                                                        {
                                                                __u32 crc = *p++;
                                                                descriptorMap::iterator it =
                                                        {
                                                                __u32 crc = *p++;
                                                                descriptorMap::iterator it =
@@ -2023,16 +2286,14 @@ PyObject *eEPGCache::search(ePyObject arg)
                                        }
                                        else
                                        {
                                        }
                                        else
                                        {
-                                               PyErr_SetString(PyExc_StandardError,
-                                                       "type error");
+                                               PyErr_SetString(PyExc_StandardError, "type error");
                                                eDebug("tuple arg 4 is not a valid service reference string");
                                                return NULL;
                                        }
                                }
                                else
                                {
                                                eDebug("tuple arg 4 is not a valid service reference string");
                                                return NULL;
                                        }
                                }
                                else
                                {
-                                       PyErr_SetString(PyExc_StandardError,
-                                       "type error");
+                                       PyErr_SetString(PyExc_StandardError, "type error");
                                        eDebug("tuple arg 4 is not a string");
                                        return NULL;
                                }
                                        eDebug("tuple arg 4 is not a string");
                                        return NULL;
                                }
@@ -2044,7 +2305,11 @@ PyObject *eEPGCache::search(ePyObject arg)
                                {
                                        int casetype = PyLong_AsLong(PyTuple_GET_ITEM(arg, 4));
                                        const char *str = PyString_AS_STRING(obj);
                                {
                                        int casetype = PyLong_AsLong(PyTuple_GET_ITEM(arg, 4));
                                        const char *str = PyString_AS_STRING(obj);
+#if PY_VERSION_HEX < 0x02060000
                                        int textlen = PyString_GET_SIZE(obj);
                                        int textlen = PyString_GET_SIZE(obj);
+#else
+                                       int textlen = PyString_Size(obj);
+#endif
                                        if (querytype == 1)
                                                eDebug("lookup for events with '%s' as title(%s)", str, casetype?"ignore case":"case sensitive");
                                        else
                                        if (querytype == 1)
                                                eDebug("lookup for events with '%s' as title(%s)", str, casetype?"ignore case":"case sensitive");
                                        else
@@ -2059,22 +2324,32 @@ PyObject *eEPGCache::search(ePyObject arg)
                                                        int title_len = data[5];
                                                        if ( querytype == 1 )
                                                        {
                                                        int title_len = data[5];
                                                        if ( querytype == 1 )
                                                        {
-                                                               if (title_len > textlen)
-                                                                       continue;
-                                                               else if (title_len < textlen)
+                                                               int offs = 6;
+                                                               // skip DVB-Text Encoding!
+                                                               if (data[6] == 0x10)
+                                                               {
+                                                                       offs+=3;
+                                                                       title_len-=3;
+                                                               }
+                                                               else if(data[6] > 0 && data[6] < 0x20)
+                                                               {
+                                                                       offs+=1;
+                                                                       title_len-=1;
+                                                               }
+                                                               if (title_len != textlen)
                                                                        continue;
                                                                if ( casetype )
                                                                {
                                                                        continue;
                                                                if ( casetype )
                                                                {
-                                                                       if ( !strncasecmp((const char*)data+6, str, title_len) )
+                                                                       if ( !strncasecmp((const char*)data+offs, str, title_len) )
                                                                        {
                                                                        {
-//                                                                             std::string s((const char*)data+6, title_len);
+//                                                                             std::string s((const char*)data+offs, title_len);
 //                                                                             eDebug("match1 %s %s", str, s.c_str() );
                                                                                descr[++descridx] = it->first;
                                                                        }
                                                                }
 //                                                                             eDebug("match1 %s %s", str, s.c_str() );
                                                                                descr[++descridx] = it->first;
                                                                        }
                                                                }
-                                                               else if ( !strncmp((const char*)data+6, str, title_len) )
+                                                               else if ( !strncmp((const char*)data+offs, str, title_len) )
                                                                {
                                                                {
-//                                                                     std::string s((const char*)data+6, title_len);
+//                                                                     std::string s((const char*)data+offs, title_len);
 //                                                                     eDebug("match2 %s %s", str, s.c_str() );
                                                                        descr[++descridx] = it->first;
                                                                }
 //                                                                     eDebug("match2 %s %s", str, s.c_str() );
                                                                        descr[++descridx] = it->first;
                                                                }
@@ -2093,13 +2368,13 @@ PyObject *eEPGCache::search(ePyObject arg)
 //                                                                                     eDebug("match 3 %s %s", str, s.c_str() );
                                                                                        break;
                                                                                }
 //                                                                                     eDebug("match 3 %s %s", str, s.c_str() );
                                                                                        break;
                                                                                }
-                                                                               else if (!strncmp((const char*)data+6+idx, str, textlen) )
-                                                                               {
-                                                                                       descr[++descridx] = it->first;
-//                                                                                     std::string s((const char*)data+6, title_len);
-//                                                                                     eDebug("match 4 %s %s", str, s.c_str() );
-                                                                                       break;
-                                                                               }
+                                                                       }
+                                                                       else if (!strncmp((const char*)data+6+idx, str, textlen) )
+                                                                       {
+                                                                               descr[++descridx] = it->first;
+//                                                                             std::string s((const char*)data+6, title_len);
+//                                                                             eDebug("match 4 %s %s", str, s.c_str() );
+                                                                               break;
                                                                        }
                                                                        ++idx;
                                                                }
                                                                        }
                                                                        ++idx;
                                                                }
@@ -2139,8 +2414,6 @@ PyObject *eEPGCache::search(ePyObject arg)
                return NULL;
        }
 
                return NULL;
        }
 
-       ASSERT(descridx <= 512);
-
        if (descridx > -1)
        {
                int maxcount=maxmatches;
        if (descridx > -1)
        {
                int maxcount=maxmatches;
@@ -2168,11 +2441,11 @@ PyObject *eEPGCache::search(ePyObject arg)
                                if ( evid == eventid)
                                        continue;
                                __u8 *data = evit->second->EITdata;
                                if ( evid == eventid)
                                        continue;
                                __u8 *data = evit->second->EITdata;
-                               int tmp = evit->second->ByteSize-12;
-                               __u32 *p = (__u32*)(data+12);
+                               int tmp = evit->second->ByteSize-10;
+                               __u32 *p = (__u32*)(data+10);
                                // check if any of our descriptor used by this event
                                int cnt=-1;
                                // check if any of our descriptor used by this event
                                int cnt=-1;
-                               while(tmp>0)
+                               while(tmp>3)
                                {
                                        __u32 crc32 = *p++;
                                        for ( int i=0; i <= descridx; ++i)
                                {
                                        __u32 crc32 = *p++;
                                        for ( int i=0; i <= descridx; ++i)
@@ -2191,15 +2464,21 @@ PyObject *eEPGCache::search(ePyObject arg)
                                        if (ref.valid())
                                        {
                                        // create servive event
                                        if (ref.valid())
                                        {
                                        // create servive event
-                                               ePtr<eServiceEvent> ptr;
+                                               eServiceEvent ptr;
+                                               const eventData *ev_data=0;
                                                if (needServiceEvent)
                                                {
                                                if (needServiceEvent)
                                                {
-                                                       lookupEventId(ref, evid, ptr);
-                                                       if (!ptr)
+                                                       if (lookupEventId(ref, evid, ev_data))
                                                                eDebug("event not found !!!!!!!!!!!");
                                                                eDebug("event not found !!!!!!!!!!!");
+                                                       else
+                                                       {
+                                                               const eServiceReferenceDVB &dref = (const eServiceReferenceDVB&)ref;
+                                                               Event ev((uint8_t*)ev_data->get());
+                                                               ptr.parseFrom(&ev, (dref.getTransportStreamID().get()<<16)|dref.getOriginalNetworkID().get());
+                                                       }
                                                }
                                        // create service name
                                                }
                                        // create service name
-                                               if (!service_name && strchr(argstring,'N'))
+                                               if (must_get_service_name && !service_name)
                                                {
                                                        ePtr<iStaticServiceInformation> sptr;
                                                        eServiceCenterPtr service_center;
                                                {
                                                        ePtr<iStaticServiceInformation> sptr;
                                                        eServiceCenterPtr service_center;
@@ -2211,6 +2490,19 @@ PyObject *eEPGCache::search(ePyObject arg)
                                                                {
                                                                        std::string name;
                                                                        sptr->getName(ref, name);
                                                                {
                                                                        std::string name;
                                                                        sptr->getName(ref, name);
+
+                                                                       if (must_get_service_name == 1)
+                                                                       {
+                                                                               size_t pos;
+                                                                               // filter short name brakets
+                                                                               while((pos = name.find("\xc2\x86")) != std::string::npos)
+                                                                                       name.erase(pos,2);
+                                                                               while((pos = name.find("\xc2\x87")) != std::string::npos)
+                                                                                       name.erase(pos,2);
+                                                                       }
+                                                                       else
+                                                                               name = buildShortName(name);
+
                                                                        if (name.length())
                                                                                service_name = PyString_FromString(name.c_str());
                                                                }
                                                                        if (name.length())
                                                                                service_name = PyString_FromString(name.c_str());
                                                                }
@@ -2219,7 +2511,7 @@ PyObject *eEPGCache::search(ePyObject arg)
                                                                service_name = PyString_FromString("<n/a>");
                                                }
                                        // create servicereference string
                                                                service_name = PyString_FromString("<n/a>");
                                                }
                                        // create servicereference string
-                                               if (!service_reference && strchr(argstring,'R'))
+                                               if (must_get_service_reference && !service_reference)
                                                        service_reference = PyString_FromString(ref.toString().c_str());
                                        // create list
                                                if (!ret)
                                                        service_reference = PyString_FromString(ref.toString().c_str());
                                        // create list
                                                if (!ret)
@@ -2227,7 +2519,7 @@ PyObject *eEPGCache::search(ePyObject arg)
                                        // create tuple
                                                ePyObject tuple = PyTuple_New(argcount);
                                        // fill tuple
                                        // create tuple
                                                ePyObject tuple = PyTuple_New(argcount);
                                        // fill tuple
-                                               fillTuple2(tuple, argstring, argcount, evit->second, ptr, service_name, service_reference);
+                                               fillTuple2(tuple, argstring, argcount, evit->second, ev_data ? &ptr : 0, service_name, service_reference);
                                                PyList_Append(ret, tuple);
                                                Py_DECREF(tuple);
                                                --maxcount;
                                                PyList_Append(ret, tuple);
                                                Py_DECREF(tuple);
                                                --maxcount;
@@ -2276,6 +2568,50 @@ void eEPGCache::PMTready(eDVBServicePMTHandler *pmthandler)
                                int tmp=0;
                                switch ((*es)->getType())
                                {
                                int tmp=0;
                                switch ((*es)->getType())
                                {
+                               case 0xC1: // user private
+                                       for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
+                                               desc != (*es)->getDescriptors()->end(); ++desc)
+                                       {
+                                               switch ((*desc)->getTag())
+                                               {
+                                                       case 0xC2: // user defined
+                                                               if ((*desc)->getLength() == 8) 
+                                                               {
+                                                                       __u8 buffer[10];
+                                                                       (*desc)->writeToBuffer(buffer);
+                                                                       if (!strncmp((const char *)buffer+2, "EPGDATA", 7))
+                                                                       {
+                                                                               eServiceReferenceDVB ref;
+                                                                               if (!pmthandler->getServiceReference(ref))
+                                                                               {
+                                                                                       int pid = (*es)->getPid();
+                                                                                       messages.send(Message(Message::got_mhw2_channel_pid, ref, pid));
+                                                                               }
+                                                                       }
+                                                                       else if(!strncmp((const char *)buffer+2, "FICHAS", 6))
+                                                                       {
+                                                                               eServiceReferenceDVB ref;
+                                                                               if (!pmthandler->getServiceReference(ref))
+                                                                               {
+                                                                                       int pid = (*es)->getPid();
+                                                                                       messages.send(Message(Message::got_mhw2_summary_pid, ref, pid));
+                                                                               }
+                                                                       }
+                                                                       else if(!strncmp((const char *)buffer+2, "GENEROS", 7))
+                                                                       {
+                                                                               eServiceReferenceDVB ref;
+                                                                               if (!pmthandler->getServiceReference(ref))
+                                                                               {
+                                                                                       int pid = (*es)->getPid();
+                                                                                       messages.send(Message(Message::got_mhw2_title_pid, ref, pid));
+                                                                               }
+                                                                       }
+                                                               }
+                                                               break;
+                                                       default:
+                                                               break;
+                                               }
+                                       }
                                case 0x05: // private
                                        for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
                                                desc != (*es)->getDescriptors()->end(); ++desc)
                                case 0x05: // private
                                        for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
                                                desc != (*es)->getDescriptors()->end(); ++desc)
@@ -2393,63 +2729,71 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey &current_service, const __
 
        int descriptors_length = (data[ptr++]&0x0F) << 8;
        descriptors_length |= data[ptr++];
 
        int descriptors_length = (data[ptr++]&0x0F) << 8;
        descriptors_length |= data[ptr++];
-       while ( descriptors_length > 0 )
+       while ( descriptors_length > 1 )
        {
                int descr_type = data[ptr];
                int descr_len = data[ptr+1];
        {
                int descr_type = data[ptr];
                int descr_len = data[ptr+1];
-               descriptors_length -= (descr_len+2);
-               if ( descr_type == 0xf2 )
-               {
-                       ptr+=2;
-                       int tsid = data[ptr++] << 8;
-                       tsid |= data[ptr++];
-                       int onid = data[ptr++] << 8;
-                       onid |= data[ptr++];
-                       int sid = data[ptr++] << 8;
-                       sid |= data[ptr++];
-
-// WORKAROUND for wrong transmitted epg data (01.08.2006)
-                       if ( onid == 0x85 )
+               descriptors_length -= 2;
+               if (descriptors_length >= descr_len)
+               {
+                       descriptors_length -= descr_len;
+                       if ( descr_type == 0xf2 && descr_len > 5)
                        {
                        {
-                               switch( (tsid << 16) | sid )
+                               ptr+=2;
+                               int tsid = data[ptr++] << 8;
+                               tsid |= data[ptr++];
+                               int onid = data[ptr++] << 8;
+                               onid |= data[ptr++];
+                               int sid = data[ptr++] << 8;
+                               sid |= data[ptr++];
+
+// WORKAROUND for wrong transmitted epg data (01.10.2007)
+                               if ( onid == 0x85 )
                                {
                                {
-                                       case 0x01030b: sid = 0x1b; tsid = 4; break;  // Premiere Win
-                                       case 0x0300f0: sid = 0xe0; tsid = 2; break;
-                                       case 0x0300f1: sid = 0xe1; tsid = 2; break;
-                                       case 0x0300f5: sid = 0xdc; break;
-                                       case 0x0400d2: sid = 0xe2; tsid = 0x11; break;
-                                       case 0x1100d3: sid = 0xe3; break;
+                                       switch( (tsid << 16) | sid )
+                                       {
+                                               case 0x01030b: sid = 0x1b; tsid = 4; break;  // Premiere Win
+                                               case 0x0300f0: sid = 0xe0; tsid = 2; break;
+                                               case 0x0300f1: sid = 0xe1; tsid = 2; break;
+                                               case 0x0300f5: sid = 0xdc; break;
+                                               case 0x0400d2: sid = 0xe2; tsid = 0x11; break;
+                                               case 0x1100d3: sid = 0xe3; break;
+                                               case 0x0100d4: sid = 0xe4; tsid = 4; break;
+                                       }
                                }
                                }
-                       }
 ////////////////////////////////////////////
 
 ////////////////////////////////////////////
 
-                       uniqueEPGKey service( sid, onid, tsid );
-                       descr_len -= 6;
-                       while( descr_len > 0 )
-                       {
-                               __u8 datetime[5];
-                               datetime[0] = data[ptr++];
-                               datetime[1] = data[ptr++];
-                               int tmp_len = data[ptr++];
-                               descr_len -= 3;
-                               while( tmp_len > 0 )
+                               uniqueEPGKey service( sid, onid, tsid );
+                               descr_len -= 6;
+                               while( descr_len > 2 )
                                {
                                {
-                                       memcpy(datetime+2, data+ptr, 3);
-                                       ptr+=3;
+                                       __u8 datetime[5];
+                                       datetime[0] = data[ptr++];
+                                       datetime[1] = data[ptr++];
+                                       int tmp_len = data[ptr++];
                                        descr_len -= 3;
                                        descr_len -= 3;
-                                       tmp_len -= 3;
-                                       start_times[datetime].push_back(service);
+                                       if (descr_len >= tmp_len)
+                                       {
+                                               descr_len -= tmp_len;
+                                               while( tmp_len > 2 )
+                                               {
+                                                       memcpy(datetime+2, data+ptr, 3);
+                                                       ptr += 3;
+                                                       tmp_len -= 3;
+                                                       start_times[datetime].push_back(service);
+                                               }
+                                       }
                                }
                        }
                                }
                        }
-               }
-               else
-               {
-                       *pdescr++=data+ptr;
-                       ptr += 2;
-                       ptr += descr_len;
+                       else
+                       {
+                               *pdescr++=data+ptr;
+                               ptr += 2;
+                               ptr += descr_len;
+                       }
                }
        }
                }
        }
-       ASSERT(pdescr <= &descriptors[65])
+       ASSERT(pdescr <= &descriptors[65]);
        __u8 event[4098];
        eit_event_struct *ev_struct = (eit_event_struct*) event;
        ev_struct->running_status = 0;
        __u8 event[4098];
        eit_event_struct *ev_struct = (eit_event_struct*) event;
        ev_struct->running_status = 0;
@@ -2466,7 +2810,7 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey &current_service, const __
        ASSERT(ptr <= 4098);
        for ( std::map< date_time, std::list<uniqueEPGKey> >::iterator it(start_times.begin()); it != start_times.end(); ++it )
        {
        ASSERT(ptr <= 4098);
        for ( std::map< date_time, std::list<uniqueEPGKey> >::iterator it(start_times.begin()); it != start_times.end(); ++it )
        {
-               time_t now = eDVBLocalTimeHandler::getInstance()->nowTime();
+               time_t now = ::time(0);
                if ( (it->first.tm + duration_sec) < now )
                        continue;
                memcpy(event+2, it->first.data, 5);
                if ( (it->first.tm + duration_sec) < now )
                        continue;
                memcpy(event+2, it->first.data, 5);
@@ -2503,6 +2847,7 @@ void eEPGCache::privateSectionRead(const uniqueEPGKey &current_service, const __
                eventData *d = new eventData( ev_struct, bptr, PRIVATE );
                evMap[event_id] = d;
                tmMap[stime] = d;
                eventData *d = new eventData( ev_struct, bptr, PRIVATE );
                evMap[event_id] = d;
                tmMap[stime] = d;
+               ASSERT(bptr <= 4098);
        }
 }
 
        }
 }
 
@@ -2541,7 +2886,7 @@ void eEPGCache::channel_data::readPrivateData( const __u8 *data)
                int tmp = chid.original_network_id.get();
                tmp |= 0x80000000; // we use highest bit as private epg indicator
                chid.original_network_id = tmp;
                int tmp = chid.original_network_id.get();
                tmp |= 0x80000000; // we use highest bit as private epg indicator
                chid.original_network_id = tmp;
-               cache->channelLastUpdated[chid] = eDVBLocalTimeHandler::getInstance()->nowTime();
+               cache->channelLastUpdated[chid] = ::time(0);
                m_PrevVersion = (data[5] & 0x3E) >> 1;
                startPrivateReader();
        }
                m_PrevVersion = (data[5] & 0x3E) >> 1;
                startPrivateReader();
        }
@@ -2591,6 +2936,7 @@ void eEPGCache::channel_data::timeMHW2DVB( int minutes, u_char *return_time)
 void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minutes, u_char *return_time)
 // For date plus time of day
 {
 void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minutes, u_char *return_time)
 // For date plus time of day
 {
+       char tz_saved[1024];
        // Remove offset in mhw time.
        __u8 local_hours = hours;
        if ( hours >= 16 )
        // Remove offset in mhw time.
        __u8 local_hours = hours;
        if ( hours >= 16 )
@@ -2600,9 +2946,11 @@ void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minu
 
        // As far as we know all mhw time data is sent in central Europe time zone.
        // So, temporarily set timezone to western europe
 
        // As far as we know all mhw time data is sent in central Europe time zone.
        // So, temporarily set timezone to western europe
-       time_t dt = eDVBLocalTimeHandler::getInstance()->nowTime();
+       time_t dt = ::time(0);
 
        char *old_tz = getenv( "TZ" );
 
        char *old_tz = getenv( "TZ" );
+       if (old_tz)
+               strcpy(tz_saved, old_tz);
        putenv("TZ=CET-1CEST,M3.5.0/2,M10.5.0/3");
        tzset();
 
        putenv("TZ=CET-1CEST,M3.5.0/2,M10.5.0/3");
        tzset();
 
@@ -2625,7 +2973,7 @@ void eEPGCache::channel_data::timeMHW2DVB( u_char day, u_char hours, u_char minu
        if ( old_tz == NULL )
                unsetenv( "TZ" );
        else
        if ( old_tz == NULL )
                unsetenv( "TZ" );
        else
-               putenv( old_tz );
+               setenv("TZ", tz_saved, 1);
        tzset();
 
        // Calculate MJD according to annex in ETSI EN 300 468
        tzset();
 
        // Calculate MJD according to annex in ETSI EN 300 468
@@ -2645,6 +2993,7 @@ void eEPGCache::channel_data::storeTitle(std::map<__u32, mhw_title_t>::iterator
 // data is borrowed from calling proc to save memory space.
 {
        __u8 name[34];
 // data is borrowed from calling proc to save memory space.
 {
        __u8 name[34];
+
        // For each title a separate EIT packet will be sent to eEPGCache::sectionRead()
        bool isMHW2 = itTitle->second.mhw2_mjd_hi || itTitle->second.mhw2_mjd_lo ||
                itTitle->second.mhw2_duration_hi || itTitle->second.mhw2_duration_lo;
        // For each title a separate EIT packet will be sent to eEPGCache::sectionRead()
        bool isMHW2 = itTitle->second.mhw2_mjd_hi || itTitle->second.mhw2_mjd_lo ||
                itTitle->second.mhw2_duration_hi || itTitle->second.mhw2_duration_lo;
@@ -2652,6 +3001,7 @@ void eEPGCache::channel_data::storeTitle(std::map<__u32, mhw_title_t>::iterator
        eit_t *packet = (eit_t *) data;
        packet->table_id = 0x50;
        packet->section_syntax_indicator = 1;
        eit_t *packet = (eit_t *) data;
        packet->table_id = 0x50;
        packet->section_syntax_indicator = 1;
+
        packet->service_id_hi = m_channels[ itTitle->second.channel_id - 1 ].channel_id_hi;
        packet->service_id_lo = m_channels[ itTitle->second.channel_id - 1 ].channel_id_lo;
        packet->version_number = 0;     // eEPGCache::sectionRead() will dig this for the moment
        packet->service_id_hi = m_channels[ itTitle->second.channel_id - 1 ].channel_id_hi;
        packet->service_id_lo = m_channels[ itTitle->second.channel_id - 1 ].channel_id_lo;
        packet->version_number = 0;     // eEPGCache::sectionRead() will dig this for the moment
@@ -2666,7 +3016,7 @@ void eEPGCache::channel_data::storeTitle(std::map<__u32, mhw_title_t>::iterator
        packet->segment_last_table_id = 0x50;
 
        __u8 *title = isMHW2 ? ((__u8*)(itTitle->second.title))-4 : (__u8*)itTitle->second.title;
        packet->segment_last_table_id = 0x50;
 
        __u8 *title = isMHW2 ? ((__u8*)(itTitle->second.title))-4 : (__u8*)itTitle->second.title;
-       std::string prog_title = (char *) delimitName( title, name, isMHW2 ? 33 : 23 );
+       std::string prog_title = (char *) delimitName( title, name, isMHW2 ? 35 : 23 );
        int prog_title_length = prog_title.length();
 
        int packet_length = EIT_SIZE + EIT_LOOP_SIZE + EIT_SHORT_EVENT_DESCRIPTOR_SIZE +
        int prog_title_length = prog_title.length();
 
        int packet_length = EIT_SIZE + EIT_LOOP_SIZE + EIT_SHORT_EVENT_DESCRIPTOR_SIZE +
@@ -2787,7 +3137,7 @@ void eEPGCache::channel_data::storeTitle(std::map<__u32, mhw_title_t>::iterator
 
 void eEPGCache::channel_data::startTimeout(int msec)
 {
 
 void eEPGCache::channel_data::startTimeout(int msec)
 {
-       m_MHWTimeoutTimer.start(msec,true);
+       m_MHWTimeoutTimer->start(msec,true);
        m_MHWTimeoutet=false;
 }
 
        m_MHWTimeoutet=false;
 }
 
@@ -2825,7 +3175,7 @@ void eEPGCache::channel_data::readMHWData(const __u8 *data)
 
        if ( state > 1 || // aborted
                // have si data.. so we dont read mhw data
 
        if ( state > 1 || // aborted
                // have si data.. so we dont read mhw data
-               (haveData & (SCHEDULE|SCHEDULE_OTHER)) )
+               (haveData & (SCHEDULE|SCHEDULE_OTHER|VIASAT)) )
        {
                eDebug("[EPGC] mhw aborted %d", state);
        }
        {
                eDebug("[EPGC] mhw aborted %d", state);
        }
@@ -2836,10 +3186,11 @@ void eEPGCache::channel_data::readMHWData(const __u8 *data)
                int record_size = sizeof( mhw_channel_name_t );
                int nbr_records = int (len/record_size);
 
                int record_size = sizeof( mhw_channel_name_t );
                int nbr_records = int (len/record_size);
 
+               m_channels.resize(nbr_records);
                for ( int i = 0; i < nbr_records; i++ )
                {
                        mhw_channel_name_t *channel = (mhw_channel_name_t*) &data[4 + i*record_size];
                for ( int i = 0; i < nbr_records; i++ )
                {
                        mhw_channel_name_t *channel = (mhw_channel_name_t*) &data[4 + i*record_size];
-                       m_channels.push_back( *channel );
+                       m_channels[i]=*channel;
                }
                haveData |= MHW;
 
                }
                haveData |= MHW;
 
@@ -2905,7 +3256,7 @@ void eEPGCache::channel_data::readMHWData(const __u8 *data)
                                m_titles[ title_id ] = *title;
                                if ( (title->ms.summary_available) && (m_program_ids.find(program_id) == m_program_ids.end()) )
                                        // program_ids will be used to gather summaries.
                                m_titles[ title_id ] = *title;
                                if ( (title->ms.summary_available) && (m_program_ids.find(program_id) == m_program_ids.end()) )
                                        // program_ids will be used to gather summaries.
-                                       m_program_ids[ program_id ] = title_id;
+                                       m_program_ids.insert(std::pair<__u32,__u32>(program_id,title_id));
                                return; // Continue reading of the current table.
                        }
                        else if (!checkTimeout())
                                return; // Continue reading of the current table.
                        }
                        else if (!checkTimeout())
@@ -2938,7 +3289,7 @@ void eEPGCache::channel_data::readMHWData(const __u8 *data)
                memcpy(&tmp, &data, sizeof(void*));
                tmp[len+3] = 0; // Terminate as a string.
 
                memcpy(&tmp, &data, sizeof(void*));
                tmp[len+3] = 0; // Terminate as a string.
 
-               std::map<__u32, __u32>::iterator itProgid( m_program_ids.find( program_id ) );
+               std::multimap<__u32, __u32>::iterator itProgid( m_program_ids.find( program_id ) );
                if ( itProgid == m_program_ids.end() )
                { /*    This part is to prevent to looping forever if some summaries are not received yet.
                        There is a timeout of 4 sec. after the last successfully read summary. */
                if ( itProgid == m_program_ids.end() )
                { /*    This part is to prevent to looping forever if some summaries are not received yet.
                        There is a timeout of 4 sec. after the last successfully read summary. */
@@ -2967,7 +3318,7 @@ void eEPGCache::channel_data::readMHWData(const __u8 *data)
                }
        }
        eDebug("[EPGC] mhw finished(%ld) %d summaries not found",
                }
        }
        eDebug("[EPGC] mhw finished(%ld) %d summaries not found",
-               eDVBLocalTimeHandler::getInstance()->nowTime(),
+               ::time(0),
                m_program_ids.size());
        // Summaries have been read, titles that have summaries have been stored.
        // Now store titles that do not have summaries.
                m_program_ids.size());
        // Summaries have been read, titles that have summaries have been stored.
        // Now store titles that do not have summaries.
@@ -2990,17 +3341,18 @@ void eEPGCache::channel_data::readMHWData2(const __u8 *data)
 
        if ( state > 1 || // aborted
                // have si data.. so we dont read mhw data
 
        if ( state > 1 || // aborted
                // have si data.. so we dont read mhw data
-               (haveData & (eEPGCache::SCHEDULE|eEPGCache::SCHEDULE_OTHER)) )
+               (haveData & (SCHEDULE|SCHEDULE_OTHER|VIASAT)) )
        {
                eDebug("[EPGC] mhw2 aborted %d", state);
        }
        {
                eDebug("[EPGC] mhw2 aborted %d", state);
        }
-       else if (m_MHWFilterMask2.pid == 0x231 && m_MHWFilterMask2.data[0] == 0xC8 && m_MHWFilterMask2.data[1] == 0)
+       else if (m_MHWFilterMask2.pid == m_mhw2_channel_pid && m_MHWFilterMask2.data[0] == 0xC8 && m_MHWFilterMask2.data[1] == 0)
        // Channels table
        {
                int num_channels = data[120];
        // Channels table
        {
                int num_channels = data[120];
+               m_channels.resize(num_channels);
                if(dataLen > 120)
                {
                if(dataLen > 120)
                {
-                       int ptr = 121 + 6 * num_channels;
+                       int ptr = 121 + 8 * num_channels;
                        if( dataLen > ptr )
                        {
                                for( int chid = 0; chid < num_channels; ++chid )
                        if( dataLen > ptr )
                        {
                                for( int chid = 0; chid < num_channels; ++chid )
@@ -3020,14 +3372,14 @@ void eEPGCache::channel_data::readMHWData2(const __u8 *data)
                for (int i=0; i < num_channels; ++i)
                {
                        mhw_channel_name_t channel;
                for (int i=0; i < num_channels; ++i)
                {
                        mhw_channel_name_t channel;
+                       channel.network_id_hi = *(tmp++);
+                       channel.network_id_lo = *(tmp++);
                        channel.transport_stream_id_hi = *(tmp++);
                        channel.transport_stream_id_lo = *(tmp++);
                        channel.channel_id_hi = *(tmp++);
                        channel.channel_id_lo = *(tmp++);
                        channel.transport_stream_id_hi = *(tmp++);
                        channel.transport_stream_id_lo = *(tmp++);
                        channel.channel_id_hi = *(tmp++);
                        channel.channel_id_lo = *(tmp++);
-#warning FIXME hardcoded network_id in mhw2 epg
-                       channel.network_id_hi = 0; // hardcoded astra 19.2
-                       channel.network_id_lo = 1;
-                       m_channels.push_back(channel);
+                       m_channels[i]=channel;
+//                     eDebug("%d(%02x) %04x: %02x %02x", i, i, (channel.channel_id_hi << 8) | channel.channel_id_lo, *tmp, *(tmp+1));
                        tmp+=2;
                }
                for (int i=0; i < num_channels; ++i)
                        tmp+=2;
                }
                for (int i=0; i < num_channels; ++i)
@@ -3038,95 +3390,106 @@ void eEPGCache::channel_data::readMHWData2(const __u8 *data)
                        for (; x < channel_name_len; ++x)
                                channel.name[x]=*(tmp++);
                        channel.name[x+1]=0;
                        for (; x < channel_name_len; ++x)
                                channel.name[x]=*(tmp++);
                        channel.name[x+1]=0;
+//                     eDebug("%d(%02x) %s", i, i, channel.name);
                }
                haveData |= MHW;
                eDebug("[EPGC] mhw2 %d channels found", m_channels.size());
        }
                }
                haveData |= MHW;
                eDebug("[EPGC] mhw2 %d channels found", m_channels.size());
        }
-       else if (m_MHWFilterMask2.pid == 0x231 && m_MHWFilterMask2.data[0] == 0xC8 && m_MHWFilterMask2.data[1] == 1)
+       else if (m_MHWFilterMask2.pid == m_mhw2_channel_pid && m_MHWFilterMask2.data[0] == 0xC8 && m_MHWFilterMask2.data[1] == 1)
        {
                // Themes table
                eDebug("[EPGC] mhw2 themes nyi");
        }
        {
                // Themes table
                eDebug("[EPGC] mhw2 themes nyi");
        }
-       else if (m_MHWFilterMask2.pid == 0x234 && m_MHWFilterMask2.data[0] == 0xe6)
+       else if (m_MHWFilterMask2.pid == m_mhw2_title_pid && m_MHWFilterMask2.data[0] == 0xe6)
        // Titles table
        {
                int pos=18;
        // Titles table
        {
                int pos=18;
-               bool valid=true;
-               int len = ((data[1]&0xf)<<8) + data[2] - 16;
+               bool valid=false;
                bool finish=false;
                bool finish=false;
-               if(data[dataLen-1] != 0xff)
-                       return;
-               while( pos < dataLen )
+
+//             eDebug("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+//                     data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10],
+//                     data[11], data[12], data[13], data[14], data[15], data[16], data[17] );
+
+               while( pos < dataLen && !valid)
                {
                {
-                       valid = false;
-                       pos += 7;
-                       if( pos < dataLen )
-                       {
-                               pos += 3;
-                               if( pos < dataLen )
-                               {
-                                       if( data[pos] > 0xc0 )
-                                       {
-                                               pos += ( data[pos] - 0xc0 );
-                                               pos += 4;
-                                               if( pos < dataLen )
-                                               {
-                                                       if( data[pos] == 0xff )
-                                                       {
-                                                               ++pos;
-                                                               valid = true;
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-                       if( !valid )
-                       {
-                               if (checkTimeout())
-                                       goto start_summary;
-                               return;
-                       }
+                       pos += 18;
+                       pos += (data[pos] & 0x3F) + 4;
+                       if( pos == dataLen )
+                               valid = true;
                }
                }
+
+               if (!valid)
+               {
+                       if (dataLen > 18)
+                               eDebug("mhw2 title table invalid!!");
+                       if (checkTimeout())
+                               goto abort;
+                       if (!m_MHWTimeoutTimer->isActive())
+                               startTimeout(5000);
+                       return; // continue reading
+               }
+
                // data seems consistent...
                mhw_title_t title;
                pos = 18;
                // data seems consistent...
                mhw_title_t title;
                pos = 18;
-               while (pos < len)
+               while (pos < dataLen)
                {
                {
+//                     eDebugNoNewLine("    [%02x] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x [%02x %02x %02x %02x %02x %02x %02x] LL - DESCR - ",
+//                             data[pos], data[pos+1], data[pos+2], data[pos+3], data[pos+4], data[pos+5], data[pos+6], data[pos+7], 
+//                             data[pos+8], data[pos+9], data[pos+10], data[pos+11], data[pos+12], data[pos+13], data[pos+14], data[pos+15], data[pos+16], data[pos+17]);
                        title.channel_id = data[pos]+1;
                        title.channel_id = data[pos]+1;
-                       title.program_id_ml = data[pos+1];
-                       title.program_id_lo = data[pos+2];
-                       title.mhw2_mjd_hi = data[pos+3];
-                       title.mhw2_mjd_lo = data[pos+4];
-                       title.mhw2_hours = data[pos+5];
-                       title.mhw2_minutes = data[pos+6];
-                       title.mhw2_seconds = data[pos+7];
-                       int duration = ((data[pos+8] << 8)|data[pos+9]) >> 4;
+                       title.mhw2_mjd_hi = data[pos+11];
+                       title.mhw2_mjd_lo = data[pos+12];
+                       title.mhw2_hours = data[pos+13];
+                       title.mhw2_minutes = data[pos+14];
+                       title.mhw2_seconds = data[pos+15];
+                       int duration = ((data[pos+16] << 8)|data[pos+17]) >> 4;
                        title.mhw2_duration_hi = (duration&0xFF00) >> 8;
                        title.mhw2_duration_lo = duration&0xFF;
                        title.mhw2_duration_hi = (duration&0xFF00) >> 8;
                        title.mhw2_duration_lo = duration&0xFF;
-                       __u8 slen = data[pos+10] & 0x3f;
+
+                       // Create unique key per title
+                       __u32 title_id = (data[pos+7] << 24) | (data[pos+8] << 16) | (data[pos+9] << 8) | data[pos+10];
+
+                       __u8 slen = data[pos+18] & 0x3f;
                        __u8 *dest = ((__u8*)title.title)-4;
                        __u8 *dest = ((__u8*)title.title)-4;
-                       memcpy(dest, &data[pos+11], slen>33 ? 33 : slen);
-                       memset(dest+slen, 0x20, 33-slen);
-                       pos += 11 + slen;
+                       memcpy(dest, &data[pos+19], slen>35 ? 35 : slen);
+                       memset(dest+slen, 0, 35-slen);
+                       pos += 19 + slen;
+//                     eDebug("%02x [%02x %02x]: %s", data[pos], data[pos+1], data[pos+2], dest);
+
 //                     not used theme id (data[7] & 0x3f) + (data[pos] & 0x3f);
                        __u32 summary_id = (data[pos+1] << 8) | data[pos+2];
 
 //                     not used theme id (data[7] & 0x3f) + (data[pos] & 0x3f);
                        __u32 summary_id = (data[pos+1] << 8) | data[pos+2];
 
-                       // Create unique key per title
-                       __u32 title_id = (title.channel_id<<16) | (title.program_id_ml<<8) | title.program_id_lo;
+//                     if (title.channel_id > m_channels.size())
+//                             eDebug("channel_id(%d %02x) to big!!", title.channel_id);
 
 
-//                     eDebug("program_id: %08x, %s", program_id,
-//                             std::string((const char *)title.title, (int)(slen > 23 ? 23 : slen)).c_str());
+//                     eDebug("pos %d prog_id %02x %02x chid %02x summary_id %04x dest %p len %d\n",
+//                             pos, title.program_id_ml, title.program_id_lo, title.channel_id, summary_id, dest, slen);
 
 
-                       pos += 4;
+//                     eDebug("title_id %08x -> summary_id %04x\n", title_id, summary_id);
 
 
-                       if ( m_titles.find( title_id ) == m_titles.end() )
+                       pos += 3;
+
+                       std::map<__u32, mhw_title_t>::iterator it = m_titles.find( title_id );
+                       if ( it == m_titles.end() )
                        {
                        {
-                               startTimeout(4000);
+                               startTimeout(5000);
                                m_titles[ title_id ] = title;
                                m_titles[ title_id ] = title;
-                               if (summary_id != 0xFFFF &&  // no summary avail
-                                       m_program_ids.find(summary_id) == m_program_ids.end())
+                               if (summary_id != 0xFFFF)
                                {
                                {
-                                       m_program_ids[ summary_id ] = title_id;
+                                       bool add=true;
+                                       std::multimap<__u32, __u32>::iterator it(m_program_ids.lower_bound(summary_id));
+                                       while (it != m_program_ids.end() && it->first == summary_id)
+                                       {
+                                               if (it->second == title_id) {
+                                                       add=false;
+                                                       break;
+                                               }
+                                               ++it;
+                                       }
+                                       if (add)
+                                               m_program_ids.insert(std::pair<__u32,__u32>(summary_id,title_id));
                                }
                        }
                        else
                                }
                        }
                        else
@@ -3145,109 +3508,122 @@ start_summary:
                        {
                                // Titles table has been read, there are summaries to read.
                                // Start reading summaries, store corresponding titles on the fly.
                        {
                                // Titles table has been read, there are summaries to read.
                                // Start reading summaries, store corresponding titles on the fly.
-                               startMHWReader2(0x236, 0x96);
-                               startTimeout(4000);
+                               startMHWReader2(m_mhw2_summary_pid, 0x96);
+                               startTimeout(15000);
                                return;
                        }
                }
                else
                        return;
        }
                                return;
                        }
                }
                else
                        return;
        }
-       else if (m_MHWFilterMask2.pid == 0x236 && m_MHWFilterMask2.data[0] == 0x96)
+       else if (m_MHWFilterMask2.pid == m_mhw2_summary_pid && m_MHWFilterMask2.data[0] == 0x96)
        // Summaries table
        {
        // Summaries table
        {
-               int len, loop, pos, lenline;
-               bool valid;
-               valid = true;
-               if( dataLen > 18 )
+               if (!checkTimeout())
                {
                {
-                       loop = data[12];
-                       pos = 13 + loop;
-                       if( dataLen > pos )
+                       int len, loop, pos, lenline;
+                       bool valid;
+                       valid = true;
+                       if( dataLen > 15 )
                        {
                        {
-                               loop = data[pos] & 0x0f;
-                               pos += 1;
+                               loop = data[14];
+                               pos = 15 + loop;
                                if( dataLen > pos )
                                {
                                if( dataLen > pos )
                                {
-                                       len = 0;
-                                       for( ; loop > 0; --loop )
+                                       loop = data[pos] & 0x0f;
+                                       pos += 1;
+                                       if( dataLen > pos )
                                        {
                                        {
-                                               if( dataLen > (pos+len) )
+                                               len = 0;
+                                               for( ; loop > 0; --loop )
                                                {
                                                {
-                                                       lenline = data[pos+len];
-                                                       len += lenline + 1;
+                                                       if( dataLen > (pos+len) )
+                                                       {
+                                                               lenline = data[pos+len];
+                                                               len += lenline + 1;
+                                                       }
+                                                       else
+                                                               valid=false;
                                                }
                                                }
-                                               else
-                                                       valid=false;
                                        }
                                }
                        }
                                        }
                                }
                        }
-               }
-               else if (!checkTimeout())
-                       return;  // continue reading
-               if (valid && !checkTimeout())
-               {
-                       // data seems consistent...
-                       __u32 summary_id = (data[3]<<8)|data[4];
-
-                       // ugly workaround to convert const __u8* to char*
-                       char *tmp=0;
-                       memcpy(&tmp, &data, sizeof(void*));
-
-                       len = 0;
-                       loop = data[12];
-                       pos = 13 + loop;
-                       loop = tmp[pos] & 0x0f;
-                       pos += 1;
-                       for( ; loop > 0; loop -- )
-                       {
-                               lenline = tmp[pos+len];
-                               tmp[pos+len] = ' ';
-                               len += lenline + 1;
-                       }
-                       if( len > 0 )
-                           tmp[pos+len] = 0;
                        else
                        else
-                               tmp[pos+1] = 0;
+                               return;  // continue reading
 
 
-                       std::map<__u32, __u32>::iterator itProgid( m_program_ids.find( summary_id ) );
-                       if ( itProgid == m_program_ids.end() )
-                       { /*    This part is to prevent to looping forever if some summaries are not received yet.
-                               There is a timeout of 4 sec. after the last successfully read summary. */
-       
-                               if ( !m_program_ids.empty() && !checkTimeout() )
-                                       return; // Continue reading of the current table.
-                       }
-                       else
+                       if (valid)
                        {
                        {
-                               startTimeout(4000);
-                               std::string the_text = (char *) (data + pos + 1);
-
-                               // Find corresponding title, store title and summary in epgcache.
-                               std::map<__u32, mhw_title_t>::iterator itTitle( m_titles.find( itProgid->second ) );
-                               if ( itTitle != m_titles.end() )
+                               // data seems consistent...
+                               __u32 summary_id = (data[3]<<8)|data[4];
+//                             eDebug ("summary id %04x\n", summary_id);
+//                             eDebug("[%02x %02x] %02x %02x %02x %02x %02x %02x %02x %02x XX\n", data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[12], data[13] );
+
+                               // ugly workaround to convert const __u8* to char*
+                               char *tmp=0;
+                               memcpy(&tmp, &data, sizeof(void*));
+
+                               len = 0;
+                               loop = data[14];
+                               pos = 15 + loop;
+                               loop = tmp[pos] & 0x0f;
+                               pos += 1;
+                               for( ; loop > 0; loop -- )
+                               {
+                                       lenline = tmp[pos+len];
+                                       tmp[pos+len] = ' ';
+                                       len += lenline + 1;
+                               }
+                               if( len > 0 )
+                                       tmp[pos+len] = 0;
+                               else
+                                       tmp[pos+1] = 0;
+
+                               std::multimap<__u32, __u32>::iterator itProgId( m_program_ids.lower_bound(summary_id) );
+                               if ( itProgId == m_program_ids.end() || itProgId->first != summary_id)
+                               { /*    This part is to prevent to looping forever if some summaries are not received yet.
+                                       There is a timeout of 4 sec. after the last successfully read summary. */
+                                       if ( !m_program_ids.empty() )
+                                               return; // Continue reading of the current table.
+                               }
+                               else
                                {
                                {
-                                       storeTitle( itTitle, the_text, data );
-                                       m_titles.erase( itTitle );
+                                       startTimeout(15000);
+                                       std::string the_text = (char *) (data + pos + 1);
+
+//                                     eDebug ("summary id %04x : %s\n", summary_id, data+pos+1);
+
+                                       while( itProgId != m_program_ids.end() && itProgId->first == summary_id )
+                                       {
+//                                             eDebug(".");
+                                               // Find corresponding title, store title and summary in epgcache.
+                                               std::map<__u32, mhw_title_t>::iterator itTitle( m_titles.find( itProgId->second ) );
+                                               if ( itTitle != m_titles.end() )
+                                               {
+                                                       storeTitle( itTitle, the_text, data );
+                                                       m_titles.erase( itTitle );
+                                               }
+                                               m_program_ids.erase( itProgId++ );
+                                       }
+                                       if ( !m_program_ids.empty() )
+                                               return; // Continue reading of the current table.
                                }
                                }
-                               m_program_ids.erase( itProgid );
-                               if ( !m_program_ids.empty() )
-                                       return; // Continue reading of the current table.
                        }
                        }
+                       else
+                               return;  // continue reading
                }
        }
        if (isRunning & eEPGCache::MHW)
        {
                }
        }
        if (isRunning & eEPGCache::MHW)
        {
-               if ( m_MHWFilterMask2.pid == 0x231 && m_MHWFilterMask2.data[0] == 0xC8 && m_MHWFilterMask2.data[1] == 0)
+               if ( m_MHWFilterMask2.pid == m_mhw2_channel_pid && m_MHWFilterMask2.data[0] == 0xC8 && m_MHWFilterMask2.data[1] == 0)
                {
                        // Channels table has been read, start reading the themes table.
                {
                        // Channels table has been read, start reading the themes table.
-                       startMHWReader2(0x231, 0xC8, 1);
+                       startMHWReader2(m_mhw2_channel_pid, 0xC8, 1);
                        return;
                }
                        return;
                }
-               else if ( m_MHWFilterMask2.pid == 0x231 && m_MHWFilterMask2.data[0] == 0xC8 && m_MHWFilterMask2.data[1] == 1)
+               else if ( m_MHWFilterMask2.pid == m_mhw2_channel_pid && m_MHWFilterMask2.data[0] == 0xC8 && m_MHWFilterMask2.data[1] == 1)
                {
                        // Themes table has been read, start reading the titles table.
                {
                        // Themes table has been read, start reading the titles table.
-                       startMHWReader2(0x234, 0xe6);
+                       startMHWReader2(m_mhw2_title_pid, 0xe6);
                        return;
                }
                else
                        return;
                }
                else
@@ -3257,7 +3633,7 @@ start_summary:
                        for (std::map<__u32, mhw_title_t>::iterator itTitle(m_titles.begin()); itTitle != m_titles.end(); itTitle++)
                                storeTitle( itTitle, "", data );
                        eDebug("[EPGC] mhw2 finished(%ld) %d summaries not found",
                        for (std::map<__u32, mhw_title_t>::iterator itTitle(m_titles.begin()); itTitle != m_titles.end(); itTitle++)
                                storeTitle( itTitle, "", data );
                        eDebug("[EPGC] mhw2 finished(%ld) %d summaries not found",
-                               eDVBLocalTimeHandler::getInstance()->nowTime(),
+                               ::time(0),
                                m_program_ids.size());
                }
        }
                                m_program_ids.size());
                }
        }