Merge branch 'master' of /home/tmbinc/enigma2-git into tmbinc/FixTimingBugs
authorFelix Domke <tmbinc@elitedvb.net>
Wed, 11 Feb 2009 11:52:48 +0000 (12:52 +0100)
committerFelix Domke <tmbinc@elitedvb.net>
Wed, 11 Feb 2009 11:52:48 +0000 (12:52 +0100)
Conflicts:

lib/dvb/decoder.cpp

1  2 
lib/dvb/decoder.cpp
lib/dvb/decoder.h
lib/dvb/dvb.cpp
lib/dvb/idvb.h
lib/dvb/pvrparse.cpp
lib/dvb/pvrparse.h
lib/python/Screens/InfoBarGenerics.py
lib/service/servicedvb.cpp
lib/service/servicedvb.h

diff --combined lib/dvb/decoder.cpp
index 66b923a682f2356e1d95ce6a41de475f9f038fce,065a49c290ba7ceeb79d5368e1f882a0ee9f50f2..f73dbdd99b8878e24a83f090b1a6873628dfb830
@@@ -39,7 -39,7 +39,7 @@@
  DEFINE_REF(eDVBAudio);
  
  eDVBAudio::eDVBAudio(eDVBDemux *demux, int dev)
 -      :m_demux(demux), m_dev(dev), m_is_freezed(0)
 +      :m_demux(demux), m_dev(dev)
  {
        char filename[128];
  #if HAVE_DVB_API_VERSION < 3
@@@ -187,14 -187,18 +187,18 @@@ int eDVBAudio::startPid(int pid, int ty
        case aAC3:
                bypass = 0;
                break;
-               /*
        case aDTS:
                bypass = 2;
                break;
-               */
+       case aAAC:
+               bypass = 8;
+               break;
+       case aAACHE:
+               bypass = 9;
+               break;
        }
  
 -      eDebugNoNewLine("AUDIO_SET_BYPASS - ");
 +      eDebugNoNewLine("AUDIO_SET_BYPASS(%d) - ", bypass);
        if (::ioctl(m_fd, AUDIO_SET_BYPASS_MODE, bypass) < 0)
                eDebug("failed (%m)");
        else
@@@ -240,20 -244,28 +244,20 @@@ void eDVBAudio::flush(
  
  void eDVBAudio::freeze()
  {
 -      if (!m_is_freezed)
 -      {
 -              eDebugNoNewLine("AUDIO_PAUSE - ");
 -              if (::ioctl(m_fd, AUDIO_PAUSE) < 0)
 -                      eDebug("failed (%m)");
 -              else
 -                      eDebug("ok");
 -              m_is_freezed=1;
 -      }
 +      eDebugNoNewLine("AUDIO_PAUSE - ");
 +      if (::ioctl(m_fd, AUDIO_PAUSE) < 0)
 +              eDebug("failed (%m)");
 +      else
 +              eDebug("ok");
  }
  
  void eDVBAudio::unfreeze()
  {
 -      if (m_is_freezed)
 -      {
 -              eDebugNoNewLine("AUDIO_CONTINUE - ");
 -              if (::ioctl(m_fd, AUDIO_CONTINUE) < 0)
 -                      eDebug("failed (%m)");
 -              else
 -                      eDebug("ok");
 -              m_is_freezed=0;
 -      }
 +      eDebugNoNewLine("AUDIO_CONTINUE - ");
 +      if (::ioctl(m_fd, AUDIO_CONTINUE) < 0)
 +              eDebug("failed (%m)");
 +      else
 +              eDebug("ok");
  }
  
  void eDVBAudio::setChannel(int channel)
@@@ -291,7 -303,8 +295,9 @@@ eDVBAudio::~eDVBAudio(
  DEFINE_REF(eDVBVideo);
  
  eDVBVideo::eDVBVideo(eDVBDemux *demux, int dev)
-       :m_demux(demux), m_dev(dev)
 -      :m_demux(demux), m_dev(dev), m_is_slow_motion(0), m_is_fast_forward(0), m_is_freezed(0)
 -      ,m_width(-1), m_height(-1), m_framerate(-1), m_aspect(-1), m_progressive(-1)
++<<<<<<< HEAD:lib/dvb/decoder.cpp
++      : m_demux(demux), m_dev(dev),
++      m_width(-1), m_height(-1), m_framerate(-1), m_aspect(-1), m_progressive(-1)
  {
        char filename[128];
  #if HAVE_DVB_API_VERSION < 3
  // not finally values i think.. !!
  #define VIDEO_STREAMTYPE_MPEG2 0
  #define VIDEO_STREAMTYPE_MPEG4_H264 1
+ #define VIDEO_STREAMTYPE_VC1 3
+ #define VIDEO_STREAMTYPE_MPEG4_Part2 4
+ #define VIDEO_STREAMTYPE_VC1_SM 5
+ #define VIDEO_STREAMTYPE_MPEG1 6
  
  #if HAVE_DVB_API_VERSION < 3
  int eDVBVideo::setPid(int pid)
@@@ -386,13 -403,36 +396,36 @@@ int eDVBVideo::stopPid(
  #else
  int eDVBVideo::startPid(int pid, int type)
  {
+       int streamtype = VIDEO_STREAMTYPE_MPEG2;
        if ((m_fd < 0) || (m_fd_demux < 0))
                return -1;
        dmx_pes_filter_params pes;
  
-       eDebugNoNewLine("VIDEO_SET_STREAMTYPE %d - ",type == MPEG4_H264 ? VIDEO_STREAMTYPE_MPEG4_H264 : VIDEO_STREAMTYPE_MPEG2);
-       if (::ioctl(m_fd, VIDEO_SET_STREAMTYPE,
-               type == MPEG4_H264 ? VIDEO_STREAMTYPE_MPEG4_H264 : VIDEO_STREAMTYPE_MPEG2) < 0)
+       switch(type)
+       {
+       default:
+       case MPEG2:
+               break;
+       case MPEG4_H264:
+               streamtype = VIDEO_STREAMTYPE_MPEG4_H264;
+               break;
+       case MPEG1:
+               streamtype = VIDEO_STREAMTYPE_MPEG1;
+               break;
+       case MPEG4_Part2:
+               streamtype = VIDEO_STREAMTYPE_MPEG4_Part2;
+               break;
+       case VC1:
+               streamtype = VIDEO_STREAMTYPE_VC1;
+               break;
+       case VC1_SM:
+               streamtype = VIDEO_STREAMTYPE_VC1_SM;
+               break;
+       }
+       eDebugNoNewLine("VIDEO_SET_STREAMTYPE %d - ", streamtype);
+       if (::ioctl(m_fd, VIDEO_SET_STREAMTYPE, streamtype) < 0)
                eDebug("failed (%m)");
        else
                eDebug("ok");
@@@ -453,25 -493,34 +486,25 @@@ void eDVBVideo::flush(
  
  void eDVBVideo::freeze()
  {
 -      if (!m_is_freezed)
 -      {
 -              eDebugNoNewLine("VIDEO_FREEZE - ");
 -              if (::ioctl(m_fd, VIDEO_FREEZE) < 0)
 -                      eDebug("failed (%m)");
 -              else
 -                      eDebug("ok");
 -              m_is_freezed=1;
 -      }
 +      eDebugNoNewLine("VIDEO_FREEZE - ");
 +      if (::ioctl(m_fd, VIDEO_FREEZE) < 0)
 +              eDebug("failed (%m)");
 +      else
 +              eDebug("ok");
  }
  
  void eDVBVideo::unfreeze()
  {
 -      if (m_is_freezed)
 -      {
 -              eDebugNoNewLine("VIDEO_CONTINUE - ");
 -              if (::ioctl(m_fd, VIDEO_CONTINUE) < 0)
 -                      eDebug("failed (%m)");
 -              else
 -                      eDebug("ok");
 -              m_is_freezed=0;
 -      }
 +      eDebugNoNewLine("VIDEO_CONTINUE - ");
 +      if (::ioctl(m_fd, VIDEO_CONTINUE) < 0)
 +              eDebug("failed (%m)");
 +      else
 +              eDebug("ok");
  }
  
  int eDVBVideo::setSlowMotion(int repeat)
  {
 -      eDebugNoNewLine("VIDEO_SLOWMOTION - ");
 -      m_is_slow_motion = repeat;
 +      eDebugNoNewLine("VIDEO_SLOWMOTION(%d) - ", repeat);
        int ret = ::ioctl(m_fd, VIDEO_SLOWMOTION, repeat);
        if (ret < 0)
                eDebug("failed(%m)");
  
  int eDVBVideo::setFastForward(int skip)
  {
 -      eDebugNoNewLine("VIDEO_FAST_FORWARD - ");
 -      m_is_fast_forward = skip;
 +      eDebugNoNewLine("VIDEO_FAST_FORWARD(%d) - ", skip);
        int ret = ::ioctl(m_fd, VIDEO_FAST_FORWARD, skip);
        if (ret < 0)
                eDebug("failed(%m)");
@@@ -509,6 -559,11 +542,6 @@@ int eDVBVideo::getPTS(pts_t &now
  
  eDVBVideo::~eDVBVideo()
  {
 -      if (m_is_slow_motion)
 -              setSlowMotion(0);
 -      if (m_is_fast_forward)
 -              setFastForward(0);
 -      unfreeze();
        if (m_fd >= 0)
                ::close(m_fd);
        if (m_fd_demux >= 0)
@@@ -533,23 -588,23 +566,23 @@@ void eDVBVideo::video_event(int
                {
                        struct iTSMPEGDecoder::videoEvent event;
                        event.type = iTSMPEGDecoder::videoEvent::eventSizeChanged;
-                       event.aspect = evt.u.size.aspect_ratio;
-                       event.height = evt.u.size.h;
-                       event.width = evt.u.size.w;
+                       m_aspect = event.aspect = evt.u.size.aspect_ratio == 0 ? 2 : 3;  // convert dvb api to etsi
+                       m_height = event.height = evt.u.size.h;
+                       m_width = event.width = evt.u.size.w;
                        /* emit */ m_event(event);
                }
                else if (evt.type == VIDEO_EVENT_FRAME_RATE_CHANGED)
                {
                        struct iTSMPEGDecoder::videoEvent event;
                        event.type = iTSMPEGDecoder::videoEvent::eventFrameRateChanged;
-                       event.framerate = evt.u.frame_rate;
+                       m_framerate = event.framerate = evt.u.frame_rate;
                        /* emit */ m_event(event);
                }
                else if (evt.type == 16 /*VIDEO_EVENT_PROGRESSIVE_CHANGED*/)
                {
                        struct iTSMPEGDecoder::videoEvent event;
                        event.type = iTSMPEGDecoder::videoEvent::eventProgressiveChanged;
-                       event.progressive = evt.u.frame_rate;
+                       m_progressive = event.progressive = evt.u.frame_rate;
                        /* emit */ m_event(event);
                }
                else
@@@ -566,6 -621,93 +599,93 @@@ RESULT eDVBVideo::connectEvent(const Sl
        return 0;
  }
  
+ static int readMpegProc(char *str, int decoder)
+ {
+       int val = -1;
+       char tmp[64];
+       sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
+       FILE *f = fopen(tmp, "r");
+       if (f)
+       {
+               fscanf(f, "%x", &val);
+               fclose(f);
+       }
+       return val;
+ }
+ static int readApiSize(int fd, int &xres, int &yres, int &aspect)
+ {
+ #if HAVE_DVB_API_VERSION >= 3
+       video_size_t size;
+       if (!::ioctl(fd, VIDEO_GET_SIZE, &size))
+       {
+               xres = size.w;
+               yres = size.h;
+               aspect = size.aspect_ratio == 0 ? 2 : 3;  // convert dvb api to etsi
+               return 0;
+       }
+ //    eDebug("VIDEO_GET_SIZE failed (%m)");
+ #endif
+       return -1;
+ }
+ static int readApiFrameRate(int fd, int &framerate)
+ {
+ #if HAVE_DVB_API_VERSION >= 3
+       unsigned int frate;
+       if (!::ioctl(fd, VIDEO_GET_FRAME_RATE, &frate))
+       {
+               framerate = frate;      
+               return 0;
+       }
+ //    eDebug("VIDEO_GET_FRAME_RATE failed (%m)");
+ #endif
+       return -1;
+ }
+ int eDVBVideo::getWidth()
+ {
+       if (m_width == -1)
+               readApiSize(m_fd, m_width, m_height, m_aspect);
+       if (m_width == -1)
+               m_width = readMpegProc("xres", m_dev);
+       return m_width;
+ }
+ int eDVBVideo::getHeight()
+ {
+       if (m_height == -1)
+               readApiSize(m_fd, m_width, m_height, m_aspect);
+       if (m_height == -1)
+               m_height = readMpegProc("yres", m_dev);
+       return m_height;
+ }
+ int eDVBVideo::getAspect()
+ {
+       if (m_aspect == -1)
+               readApiSize(m_fd, m_width, m_height, m_aspect);
+       if (m_aspect == -1)
+               m_aspect = readMpegProc("aspect", m_dev);
+       return m_aspect;
+ }
+ int eDVBVideo::getProgressive()
+ {
+       if (m_progressive == -1)
+               m_progressive = readMpegProc("progressive", m_dev);
+       return m_progressive;
+ }
+ int eDVBVideo::getFrameRate()
+ {
+       if (m_framerate == -1)
+               readApiFrameRate(m_fd, m_framerate);
+       if (m_framerate == -1)
+               m_framerate = readMpegProc("framerate", m_dev);
+       return m_framerate;
+ }
  DEFINE_REF(eDVBPCR);
  
  eDVBPCR::eDVBPCR(eDVBDemux *demux): m_demux(demux)
@@@ -727,14 -869,14 +847,14 @@@ int eTSMPEGDecoder::setState(
  {
        int res = 0;
  
 -      int noaudio = m_is_sm || m_is_ff || m_is_trickmode;
 +      int noaudio = (m_state != statePlay) && (m_state != statePause);
        int nott = noaudio; /* actually same conditions */
  
        if ((noaudio && m_audio) || (!m_audio && !noaudio))
 -              m_changed |= changeAudio;
 +              m_changed |= changeAudio | changeState;
  
        if ((nott && m_text) || (!m_text && !nott))
 -              m_changed |= changeText;
 +              m_changed |= changeText | changeState;
  
        bool changed = !!m_changed;
  #if HAVE_DVB_API_VERSION < 3
                m_changed &= ~changeText;
        }
  #endif
 +
 +      if (m_changed & changeState)
 +      {
 +                                      /* play, slowmotion, fast-forward */
 +              int state_table[6][4] = 
 +                      {
 +                              /* [stateStop] =                 */ {0, 0, 0},
 +                              /* [statePause] =                */ {0, 0, 0},
 +                              /* [statePlay] =                 */ {1, 0, 0},
 +                              /* [stateDecoderFastForward] =   */ {1, 0, m_ff_sm_ratio},
 +                              /* [stateHighspeedFastForward] = */ {1, 0, 1},
 +                              /* [stateSlowMotion] =           */ {1, m_ff_sm_ratio, 0}
 +                      };
 +              int *s = state_table[m_state];
 +              if (m_video)
 +              {
 +                      m_video->setSlowMotion(s[1]);
 +                      m_video->setFastForward(s[2]);
 +                      if (s[0])
 +                              m_video->unfreeze();
 +                      else
 +                              m_video->freeze();
 +              }
 +              if (m_audio)
 +              {
 +                      if (s[0])
 +                              m_audio->unfreeze();
 +                      else
 +                              m_audio->freeze();
 +              }
 +              m_changed &= ~changeState;
 +      }
 +
        if (changed && !m_video && m_audio && m_radio_pic.length())
                showSinglePic(m_radio_pic.c_str());
  
@@@ -956,7 -1065,7 +1076,7 @@@ eTSMPEGDecoder::eTSMPEGDecoder(eDVBDemu
  {
        demux->connectEvent(slot(*this, &eTSMPEGDecoder::demux_event), m_demux_event_conn);
        CONNECT(m_showSinglePicTimer->timeout, eTSMPEGDecoder::finishShowSinglePic);
 -      m_is_ff = m_is_sm = m_is_trickmode = 0;
 +      m_state = stateStop;
  }
  
  eTSMPEGDecoder::~eTSMPEGDecoder()
@@@ -1038,61 -1147,82 +1158,61 @@@ RESULT eTSMPEGDecoder::setSyncMaster(in
        return -1;
  }
  
 -RESULT eTSMPEGDecoder::start()
 -{
 -      RESULT r;
 -      r = setState();
 -      if (r)
 -              return r;
 -      return unfreeze();
 -}
 -
 -      /* preroll is start in freezed mode. */
 -RESULT eTSMPEGDecoder::preroll()
 +RESULT eTSMPEGDecoder::set()
  {
        return setState();
  }
  
 -RESULT eTSMPEGDecoder::freeze(int cont)
 +RESULT eTSMPEGDecoder::play()
  {
 -      if (m_video)
 -              m_video->freeze();
 -
 -      if (m_audio)
 -              m_audio->freeze();
 -
 -      return 0;
 -}
 -
 -RESULT eTSMPEGDecoder::unfreeze()
 -{
 -      if (m_video)
 -              m_video->unfreeze();
 -
 -      if (m_audio)
 -              m_audio->unfreeze();
 -
 -      return 0;
 -}
 -
 -RESULT eTSMPEGDecoder::setSinglePictureMode(int when)
 -{
 -      return -1;
 +      if (m_state == statePlay)
 +              return 0;
 +      m_state = statePlay;
 +      m_changed |= changeState;
 +      return setState();
  }
  
 -RESULT eTSMPEGDecoder::setPictureSkipMode(int what)
 +RESULT eTSMPEGDecoder::pause()
  {
 -      return -1;
 +      if (m_state == statePause)
 +              return 0;
 +      m_state = statePause;
 +      m_changed |= changeState;
 +      return setState();
  }
  
  RESULT eTSMPEGDecoder::setFastForward(int frames_to_skip)
  {
 -      m_is_ff = frames_to_skip != 0;
 +      if ((m_state == stateDecoderFastForward) && (m_ff_sm_ratio == frames_to_skip))
 +              return 0;
  
 -      setState();
 -      unfreeze(); // audio might be restarted and still in preroll (freezed) state.
 +      m_state = stateDecoderFastForward;
 +      m_ff_sm_ratio = frames_to_skip;
 +      m_changed |= changeState;
 +      return setState();
  
 -      if (m_video)
 -              return m_video->setFastForward(frames_to_skip);
 -      else
 -              return -1;
 +//            return m_video->setFastForward(frames_to_skip);
  }
  
  RESULT eTSMPEGDecoder::setSlowMotion(int repeat)
  {
 -      m_is_sm = repeat != 0;
 -
 -      setState();
 -      unfreeze(); // audio might be restarted and still in preroll (freezed) state.
 +      if ((m_state == stateSlowMotion) && (m_ff_sm_ratio == repeat))
 +              return 0;
  
 -      if (m_video)
 -              return m_video->setSlowMotion(repeat);
 -      else
 -              return -1;
 +      m_state = stateSlowMotion;
 +      m_ff_sm_ratio = repeat;
 +      m_changed |= changeState;
 +      return setState();
  }
  
 -RESULT eTSMPEGDecoder::setZoom(int what)
 +RESULT eTSMPEGDecoder::setTrickmode()
  {
 -      return -1;
 +      if (m_state == stateTrickmode)
 +              return 0;
 +
 +      m_state = stateTrickmode;
 +      m_changed |= changeState;
 +      return setState();
  }
  
  RESULT eTSMPEGDecoder::flush()
@@@ -1116,6 -1246,13 +1236,6 @@@ void eTSMPEGDecoder::demux_event(int ev
        }
  }
  
 -RESULT eTSMPEGDecoder::setTrickmode(int what)
 -{
 -      m_is_trickmode = what;
 -      setState();
 -      return 0;
 -}
 -
  RESULT eTSMPEGDecoder::getPTS(int what, pts_t &pts)
  {
        if (what == 0) /* auto */
@@@ -1227,3 -1364,38 +1347,38 @@@ void eTSMPEGDecoder::video_event(struc
  {
        /* emit */ m_video_event(event);
  }
+ int eTSMPEGDecoder::getVideoWidth()
+ {
+       if (m_video)
+               return m_video->getWidth();
+       return -1;
+ }
+ int eTSMPEGDecoder::getVideoHeight()
+ {
+       if (m_video)
+               return m_video->getHeight();
+       return -1;
+ }
+ int eTSMPEGDecoder::getVideoProgressive()
+ {
+       if (m_video)
+               return m_video->getProgressive();
+       return -1;
+ }
+ int eTSMPEGDecoder::getVideoFrameRate()
+ {
+       if (m_video)
+               return m_video->getFrameRate();
+       return -1;
+ }
+ int eTSMPEGDecoder::getVideoAspect()
+ {
+       if (m_video)
+               return m_video->getAspect();
+       return -1;
+ }
diff --combined lib/dvb/decoder.h
index 04501fe6160d5da03ebd02f6215f7491ef0ff2b4,f2e10bb9eafd10e0d7e95e3e26bb832171616362..51be5141d1b27b624b6d0d00830e68a36ec22a24
@@@ -13,7 -13,7 +13,7 @@@ private
        ePtr<eDVBDemux> m_demux;
        int m_fd, m_fd_demux, m_dev, m_is_freezed;
  public:
-       enum { aMPEG, aAC3, aDTS, aAAC };
+       enum { aMPEG, aAC3, aDTS, aAAC, aAACHE };
        eDVBAudio(eDVBDemux *demux, int dev);
        enum { aMonoLeft, aStereo, aMonoRight };
        void setChannel(int channel);
@@@ -47,8 -47,9 +47,9 @@@ private
        ePtr<eSocketNotifier> m_sn;
        void video_event(int what);
        Signal1<void, struct iTSMPEGDecoder::videoEvent> m_event;
+       int m_width, m_height, m_framerate, m_aspect, m_progressive;
  public:
-       enum { MPEG2, MPEG4_H264 };
+       enum { MPEG2, MPEG4_H264, MPEG1, MPEG4_Part2, VC1, VC1_SM };
        eDVBVideo(eDVBDemux *demux, int dev);
        void stop();
  #if HAVE_DVB_API_VERSION < 3
        int getPTS(pts_t &now);
        virtual ~eDVBVideo();
        RESULT connectEvent(const Slot1<void, struct iTSMPEGDecoder::videoEvent> &event, ePtr<eConnection> &conn);
+       int getWidth();
+       int getHeight();
+       int getProgressive();
+       int getFrameRate();
+       int getAspect();
  };
  
  class eDVBPCR: public iObject
@@@ -119,12 -125,10 +125,12 @@@ private
                changeVideo = 1, 
                changeAudio = 2, 
                changePCR   = 4,
 -              changeText  = 8
 +              changeText  = 8,
 +              changeState = 16,
        };
        int m_changed, m_decoder;
 -      int m_is_ff, m_is_sm, m_is_trickmode;
 +      int m_state;
 +      int m_ff_sm_ratio;
        int setState();
        ePtr<eConnection> m_demux_event_conn;
        ePtr<eConnection> m_video_event_conn;
@@@ -150,38 -154,27 +156,43 @@@ public
        RESULT setSyncPCR(int pcrpid);
        RESULT setTextPID(int textpid);
        RESULT setSyncMaster(int who);
 -      RESULT start();
 -      RESULT preroll();
 -      RESULT freeze(int cont);
 -      RESULT unfreeze();
 -      RESULT setSinglePictureMode(int when);
 -      RESULT setPictureSkipMode(int what);
 -      RESULT setFastForward(int frames_to_skip);
 -      RESULT setSlowMotion(int repeat);
 -      RESULT setZoom(int what);
 +      
 +              /*
 +              The following states exist:
 +              
 +               - stop: data source closed, no playback
 +               - pause: data source active, decoder paused
 +               - play: data source active, decoder consuming
 +               - decoder fast forward: data source linear, decoder drops frames
 +               - trickmode, highspeed reverse: data source fast forwards / reverses, decoder just displays frames as fast as it can
 +               - slow motion: decoder displays frames multiple times
 +              */
 +      enum {
 +              stateStop,
 +              statePause,
 +              statePlay,
 +              stateDecoderFastForward,
 +              stateTrickmode,
 +              stateSlowMotion
 +      };
 +      RESULT set(); /* just apply settings, keep state */
 +      RESULT play(); /* -> play */
 +      RESULT pause(); /* -> pause */
 +      RESULT setFastForward(int frames_to_skip); /* -> decoder fast forward */
 +      RESULT setSlowMotion(int repeat); /* -> slow motion **/
 +      RESULT setTrickmode(); /* -> highspeed fast forward */
 +
        RESULT flush();
 -      RESULT setTrickmode(int what);
        RESULT showSinglePic(const char *filename);
        RESULT setRadioPic(const std::string &filename);
                /* what 0=auto, 1=video, 2=audio. */
        RESULT getPTS(int what, pts_t &pts);
        RESULT connectVideoEvent(const Slot1<void, struct videoEvent> &event, ePtr<eConnection> &connection);
+       int getVideoWidth();
+       int getVideoHeight();
+       int getVideoProgressive();
+       int getVideoFrameRate();
+       int getVideoAspect();
  };
  
  #endif
diff --combined lib/dvb/dvb.cpp
index 28012e7a47869cd02e6d0a54531f93244d8dc719,246094386ae834378a9b329fd0ab333c4a2303d6..c320fc7871199e6decf11733ee0409a2e54db1e1
@@@ -4,6 -4,7 +4,7 @@@
  #include <lib/dvb/dvb.h>
  #include <lib/dvb/pmt.h>
  #include <lib/dvb/sec.h>
+ #include <lib/dvb/specs.h>
  
  #include <errno.h>
  #include <sys/types.h>
@@@ -69,19 -70,19 +70,19 @@@ eDVBResourceManager::eDVBResourceManage
  
        if (!instance)
                instance = this;
-               
                /* search available adapters... */
  
                // add linux devices
-       
        int num_adapter = 0;
        while (eDVBAdapterLinux::exist(num_adapter))
        {
                addAdapter(new eDVBAdapterLinux(num_adapter));
                num_adapter++;
        }
-       
-       eDebug("found %d adapter, %d frontends(%d sim) and %d demux", 
+       eDebug("found %d adapter, %d frontends(%d sim) and %d demux",
                m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size());
  
        eDVBCAService::registerChannelCallback(this);
@@@ -103,7 -104,7 +104,7 @@@ eDVBAdapterLinux::eDVBAdapterLinux(int 
  {
                // scan frontends
        int num_fe = 0;
-       
        eDebug("scanning for frontends..");
        while (1)
        {
                }
                ++num_fe;
        }
-       
                // scan demux
        int num_demux = 0;
        while (1)
                if (stat(filename, &s))
                        break;
                ePtr<eDVBDemux> demux;
-               
                demux = new eDVBDemux(m_nr, num_demux);
                m_demux.push_back(demux);
-                       
                ++num_demux;
        }
  }
@@@ -168,12 -169,12 +169,12 @@@ RESULT eDVBAdapterLinux::getDemux(ePtr<
                --nr;
                ++i;
        }
-       
        if (i != m_demux.end())
                demux = *i;
        else
                return -1;
-               
        return 0;
  }
  
@@@ -190,12 -191,12 +191,12 @@@ RESULT eDVBAdapterLinux::getFrontend(eP
                --nr;
                ++i;
        }
-       
        if (i != m_frontend.end())
                fe = *i;
        else
                return -1;
-               
        return 0;
  }
  
@@@ -223,9 -224,9 +224,9 @@@ void eDVBResourceManager::addAdapter(iD
  {
        int num_fe = adapter->getNumFrontends();
        int num_demux = adapter->getNumDemux();
-       
        m_adapter.push_back(adapter);
-       
        int i;
        for (i=0; i<num_demux; ++i)
        {
@@@ -425,9 -426,9 +426,9 @@@ RESULT eDVBResourceManager::allocateDem
  
        if (i == m_demux.end())
                return -1;
-       
        ePtr<eDVBRegisteredDemux> unused;
-       
        if (m_demux.size() < 5)
        {
                /* FIXME: hardware demux policy */
                for (; i != m_demux.end(); ++i, ++n)
                {
                        int is_decode = n < 2;
-               
                        int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
-               
                        if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
                        {
                                if ((cap & iDVBChannel::capDecode) && !is_decode)
                                        continue;
-                               unused = i;     
+                               unused = i;
                                break;
                        }
                }
                                        if (!unused)
                                                unused = i;
                                }
-                               else if (i->m_adapter == fe->m_adapter && 
+                               else if (i->m_adapter == fe->m_adapter &&
                                    i->m_demux->getSource() == fe->m_frontend->getDVBID())
                                {
                                        demux = new eDVBAllocatedDemux(i);
@@@ -572,7 -573,7 +573,7 @@@ RESULT eDVBResourceManager::allocateCha
        }
  
        /* allocate a frontend. */
-       
        ePtr<eDVBAllocatedFrontend> fe;
  
        int err = allocateFrontend(fe, feparm, simulate);
@@@ -973,7 -974,7 +974,7 @@@ int eDVBChannelFilePush::filterRecordDa
        }
  #endif
  
 -#if 1 /* not yet */
 +#if 1 /* This codepath is required on Broadcom-based Dreamboxes (DM800, DM8000) and strips away non-I-frames. */
        if (!m_iframe_search)
                return len;
  
                unsigned char *ts = data + ts_offset;
                int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
  
 -              if ((d[3] == 0) && (m_pid == pid))  /* picture start */
 +              if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid))  /* picture start */
                {
 -                      int picture_type = (d[5] >> 3) & 7;
 +                      int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
                        d += 4;
  
  //                    eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
  
                        if (m_iframe_state == 1)
                        {
-                                       /* we are allowing data, and stop allowing data on the next frame. 
+                                       /* we are allowing data, and stop allowing data on the next frame.
                                           we now found a frame. so stop here. */
                                memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
                                current_span_remaining = 0;
                        }
                } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
                {
 -                      if (m_pid != pid)
 +                              /* verify that this is actually a PES header, not just some ES data */
 +                      if (ts[1] & 0x40) /* PUSI set */
                        {
 -                              eDebug("now locked to pid %04x", pid);
 -                              m_pid = pid;
 +                              int payload_start = 4;
 +                              if (ts[3] & 0x20) /* adaptation field present */
 +                                      payload_start += ts[4] + 1; /* skip AF */
 +                              if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
 +                              {
 +                                      if (m_pid != pid)
 +                                      {
 +                                              eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
 +                                              m_pid = pid;
 +                                      }
 +                              }
                        }
  //                    m_pid = 0x6e;
                        d += 4;
                } else
                        d += 4; /* ignore */
 -
        }
  
        if (m_iframe_state == 1)
@@@ -1072,9 -1064,9 +1073,9 @@@ eDVBChannel::eDVBChannel(eDVBResourceMa
        m_frontend = frontend;
  
        m_pvr_thread = 0;
-       
        m_skipmode_n = m_skipmode_m = 0;
-       
        if (m_frontend)
                m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
  }
@@@ -1090,14 -1082,14 +1091,14 @@@ eDVBChannel::~eDVBChannel(
  void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
  {
        int state, ourstate = 0;
-       
                /* if we are already in shutdown, don't change state. */
        if (m_state == state_release)
                return;
-       
        if (fe->getState(state))
                return;
-       
        if (state == iDVBFrontend::stateLock)
        {
                eDebug("OURSTATE: ok");
                ourstate = state_failed;
        } else
                eFatal("state unknown");
-       
        if (ourstate != m_state)
        {
                m_state = ourstate;
@@@ -1208,7 -1200,7 +1209,7 @@@ void eDVBChannel::cueSheetEvent(int eve
                {
                        off_t offset_in, offset_out;
                        pts_t pts_in = i->first, pts_out = i->second;
 -                      if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
 +                      if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
                        {
                                eDebug("span translation failed.\n");
                                continue;
@@@ -1243,7 -1235,7 +1244,7 @@@ void eDVBChannel::getNextSourceSpan(off
        const int blocksize = 188;
        unsigned int max = align(10*1024*1024, blocksize);
        current_offset = align(current_offset, blocksize);
-       
        if (!m_cue)
        {
                eDebug("no cue sheet. forcing normal play");
                                continue;
                        }
                }
-               
                if (relative == 1) /* pts relative */
                {
                        pts += now;
                if (relative != 2)
                        if (pts < 0)
                                pts = 0;
-               
                if (relative == 2) /* AP relative */
                {
                        eDebug("AP relative seeking: %lld, at %lld", pts, now);
                                eDebug("AP relative seeking failed!");
                        } else
                        {
 -                              eDebug("next ap is %llx\n", pts);
                                pts = nextap;
 +                              eDebug("next ap is %llx\n", pts);
                        }
                }
-               
                off_t offset = 0;
 -              if (m_tstools.getOffset(offset, pts))
 +              if (m_tstools.getOffset(offset, pts, -1))
                {
                        eDebug("get offset for pts=%lld failed!", pts);
                        continue;
        {
                long long aligned_start = align(i->first, blocksize);
                long long aligned_end = align(i->second, blocksize);
-       
                if ((current_offset >= aligned_start) && (current_offset < aligned_end))
                {
                        start = current_offset;
                }
        }
  
 -      if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
 -      {
 -              eDebug("reached SOF");
 -              m_skipmode_m = 0;
 -              m_pvr_thread->sendEvent(eFilePushThread::evtUser);
 +      if (m_source_span.empty()) {
 +              if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
 +              {
 +                      eDebug("reached SOF");
 +                      m_skipmode_m = 0;
 +                      m_pvr_thread->sendEvent(eFilePushThread::evtUser);
 +              }
 +              start = current_offset;
 +              size = max;
 +      } else {
 +              off_t tmp2, tmp = align(m_source_span.rbegin()->second, blocksize);
 +              pts_t len;
 +              getLength(len);
 +              m_tstools.getOffset(tmp2, len, 1);
 +              if (current_offset == tmp || current_offset == tmp2) {
 +                      start = tmp2;
 +                      size = max;
 +              } else {
 +                      start = tmp - align(512*1024, blocksize);
 +                      size = align(512*1024, blocksize);
 +              }
        }
  
 -      start = current_offset;
 -      size = max;
 -
        eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
        return;
  }
@@@ -1470,7 -1449,7 +1471,7 @@@ RESULT eDVBChannel::setChannel(const eD
  {
        if (m_channel_id)
                m_mgr->removeChannel(this);
-               
        if (!channelid)
                return 0;
  
                eDebug("no frontend to tune!");
                return -ENODEV;
        }
-       
        m_channel_id = channelid;
        m_mgr->addChannel(channelid, this);
        m_state = state_tuning;
        int res;
        res = m_frontend->get().tune(*feparm);
        m_current_frontend_parameters = feparm;
-       
        if (res)
        {
                m_state = state_release;
                m_stateChanged(this);
                return res;
        }
-       
        return 0;
  }
  
@@@ -1521,24 -1500,79 +1522,79 @@@ RESULT eDVBChannel::setCIRouting(const 
        return -1;
  }
  
+ void eDVBChannel::SDTready(int result)
+ {
+       ePyObject args = PyTuple_New(2), ret;
+       bool ok=false;
+       if (!result)
+       {
+               for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
+               {
+                       ok = true;
+                       PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
+                       PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
+                       break;
+               }
+       }
+       if (!ok)
+       {
+               PyTuple_SET_ITEM(args, 0, Py_None);
+               PyTuple_SET_ITEM(args, 1, Py_None);
+               Py_INCREF(Py_None);
+               Py_INCREF(Py_None);
+       }
+       ret = PyObject_CallObject(m_tsid_onid_callback, args);
+       if (ret)
+               Py_DECREF(ret);
+       Py_DECREF(args);
+       Py_DECREF(m_tsid_onid_callback);
+       m_tsid_onid_callback = ePyObject();
+       m_tsid_onid_demux = 0;
+       m_SDT = 0;
+ }
+ RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
+ {
+       if (PyCallable_Check(callback))
+       {
+               if (!getDemux(m_tsid_onid_demux, 0))
+               {
+                       m_SDT = new eTable<ServiceDescriptionSection>;
+                       CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
+                       if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
+                       {
+                               m_tsid_onid_demux = 0;
+                               m_SDT = 0;
+                       }
+                       else
+                       {
+                               Py_INCREF(callback);
+                               m_tsid_onid_callback = callback;
+                               return 0;
+                       }
+               }
+       }
+       return -1;
+ }
  RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
  {
        ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
-       
        if (!our_demux)
        {
                demux = 0;
-               
                if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
                        return -1;
        }
-       
        demux = *our_demux;
                /* don't hold a reference to the decoding demux, we don't need it. */
-               
                /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
-                  the refcount is lost. thus, decoding demuxes are never allocated. 
-                  
+                  the refcount is lost. thus, decoding demuxes are never allocated.
                   this poses a big problem for PiP. */
        if (cap & capDecode)
                our_demux = 0;
@@@ -1571,12 -1605,12 +1627,12 @@@ RESULT eDVBChannel::playFile(const cha
                delete m_pvr_thread;
                m_pvr_thread = 0;
        }
-       
        m_tstools.openFile(file);
-       
                /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
                   THEN DO A REAL FIX HERE! */
-       
                /* (this codepath needs to be improved anyway.) */
  #if HAVE_DVB_API_VERSION < 3
        m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
@@@ -1637,11 -1671,11 +1693,11 @@@ RESULT eDVBChannel::getCurrentPosition(
  {
        if (!decoding_demux)
                return -1;
-       
        pts_t now;
-       
        int r;
-       
        if (mode == 0) /* demux */
        {
                r = decoding_demux->getSTC(now, 0);
                }
        } else
                now = pos; /* fixup supplied */
-       
        off_t off = 0; /* TODO: fixme */
        r = m_tstools.fixupPTS(off, now);
        if (r)
                eDebug("fixup PTS failed");
                return -1;
        }
-       
        pos = now;
-       
        return 0;
  }
  
@@@ -1673,7 -1707,7 +1729,7 @@@ void eDVBChannel::flushPVR(iDVBDemux *d
                           a.) the filepush's internal buffer
                           b.) the PVR buffer (before demux)
                           c.) the ratebuffer (after demux)
-                          
                           it's important to clear them in the correct order, otherwise
                           the ratebuffer (for example) would immediately refill from
                           the not-yet-flushed PVR buffer.
        m_pvr_thread->flush();
                /* HACK: flush PVR buffer */
        ::ioctl(m_pvr_fd_dst, 0);
-       
                /* flush ratebuffers (video, audio) */
        if (decoding_demux)
                decoding_demux->flush();
@@@ -1708,7 -1742,7 +1764,7 @@@ void eCueSheet::seekTo(int relative, co
        m_lock.Unlock();
        m_event(evtSeek);
  }
-       
  void eCueSheet::clear()
  {
        m_lock.WrLock();
diff --combined lib/dvb/idvb.h
index bd1c7035af0d3a7eeec9ffc6dcfaa14e3411dbbf,ec016d6974925622d86b2b6e4195462874fd0c7f..cfa98ecf1d960aea4a84d2b117a20c3acae71d19
@@@ -404,15 -404,16 +404,16 @@@ class iDVBFrontendParameters: public iO
  #endif
  public:
        enum { flagOnlyFree = 1 };
-       virtual RESULT getSystem(int &SWIG_OUTPUT) const = 0;
-       virtual RESULT getDVBS(eDVBFrontendParametersSatellite &SWIG_OUTPUT) const = 0;
-       virtual RESULT getDVBC(eDVBFrontendParametersCable &SWIG_OUTPUT) const = 0;
-       virtual RESULT getDVBT(eDVBFrontendParametersTerrestrial &SWIG_OUTPUT) const = 0;
-       
-       virtual RESULT calculateDifference(const iDVBFrontendParameters *parm, int &SWIG_OUTPUT, bool exact) const = 0;
-       virtual RESULT getHash(unsigned long &SWIG_OUTPUT) const = 0;
-       virtual RESULT calcLockTimeout(unsigned int &) const = 0;
-       virtual RESULT getFlags(unsigned int &) const = 0;
+       virtual SWIG_VOID(RESULT) getSystem(int &SWIG_OUTPUT) const = 0;
+       virtual SWIG_VOID(RESULT) getDVBS(eDVBFrontendParametersSatellite &SWIG_OUTPUT) const = 0;
+       virtual SWIG_VOID(RESULT) getDVBC(eDVBFrontendParametersCable &SWIG_OUTPUT) const = 0;
+       virtual SWIG_VOID(RESULT) getDVBT(eDVBFrontendParametersTerrestrial &SWIG_OUTPUT) const = 0;
+       virtual SWIG_VOID(RESULT) getFlags(unsigned int &SWIG_OUTPUT) const = 0;
+ #ifndef SWIG
+       virtual SWIG_VOID(RESULT) calculateDifference(const iDVBFrontendParameters *parm, int &, bool exact) const = 0;
+       virtual SWIG_VOID(RESULT) getHash(unsigned long &) const = 0;
+       virtual SWIG_VOID(RESULT) calcLockTimeout(unsigned int &) const = 0;
+ #endif
  };
  SWIG_TEMPLATE_TYPEDEF(ePtr<iDVBFrontendParameters>, iDVBFrontendParametersPtr);
  
@@@ -504,6 -505,7 +505,7 @@@ class iDVBChannel: public iObjec
  public:
                /* direct frontend access for raw channels and/or status inquiries. */
        virtual SWIG_VOID(RESULT) getFrontend(ePtr<iDVBFrontend> &SWIG_OUTPUT)=0;
+       virtual RESULT requestTsidOnid(SWIG_PYOBJECT(ePyObject) callback) { return -1; }
  #ifndef SWIG
        enum
        {
@@@ -662,24 -664,37 +664,24 @@@ public
                /** Set Sync mode to either audio or video master */
        virtual RESULT setSyncMaster(int who)=0;
  
 -              /** Apply settings with starting video */
 -      virtual RESULT start()=0;
 -              /** Apply settings but don't start yet */
 -      virtual RESULT preroll()=0;
 +              /** Apply settings but don't change state */
 +      virtual RESULT set()=0;
 +              /* all those apply settings, then transition to the given state */
  
 -              /** Freeze frame. Either continue decoding (without display) or halt. */
 -      virtual RESULT freeze(int cont)=0;
 -              /** Continue after freeze. */
 -      virtual RESULT unfreeze()=0;
 +              /** play */
 +      virtual RESULT play()=0;
 +              /** Freeze frame. */
 +      virtual RESULT pause()=0;
  
                /** fast forward by skipping frames. 0 is disabled, 2 is twice-the-speed, ... */
        virtual RESULT setFastForward(int skip=0)=0;
  
 -              // stop on .. Picture
 -      enum { spm_I, spm_Ref, spm_Any };
 -              /** Stop on specific decoded picture. For I-Frame display. */
 -      virtual RESULT setSinglePictureMode(int when)=0;
 -
 -      enum { pkm_B, pkm_PB };
 -              /** Fast forward by skipping either B or P/B pictures */
 -      virtual RESULT setPictureSkipMode(int what)=0;
 -
                /** Slow Motion by repeating pictures */
        virtual RESULT setSlowMotion(int repeat)=0;
 -      
 -      enum { zoom_Normal, zoom_PanScan, zoom_Letterbox, zoom_Fullscreen };
 -              /** Set Zoom. mode *must* be fitting. */
 -      virtual RESULT setZoom(int what)=0;
 -
 -      virtual RESULT setTrickmode(int what) = 0;
  
 +              /** Display any complete data as fast as possible */
 +      virtual RESULT setTrickmode()=0;
 +      
        virtual RESULT getPTS(int what, pts_t &pts) = 0;
  
        virtual RESULT showSinglePic(const char *filename) = 0;
        };
  
        virtual RESULT connectVideoEvent(const Slot1<void, struct videoEvent> &event, ePtr<eConnection> &connection) = 0;
+       virtual int getVideoWidth() = 0;
+       virtual int getVideoHeight() = 0;
+       virtual int getVideoProgressive() = 0;
+       virtual int getVideoFrameRate() = 0;
+       virtual int getVideoAspect() = 0;
  };
  
  #endif //SWIG
diff --combined lib/dvb/pvrparse.cpp
index c7a37460a44619de77dc4ad9633ef15c2d4e7d1b,59313669e421749379ccf5e7ed9521a0159ebc86..71cbd602f06187bb7fced1640eb5f6c29ce8031a
@@@ -36,6 -36,8 +36,6 @@@ int eMPEGStreamInformation::load(const 
                return -1;
        m_access_points.clear();
        m_pts_to_offset.clear();
 -      pts_t last = -(1LL<<62);
 -      int loaded = 0, skipped = 0;
        while (1)
        {
                unsigned long long d[2];
                d[0] = bswap_64(d[0]);
                d[1] = bswap_64(d[1]);
  #endif
 -              if ((d[1] - last) > 90000/2)
 -              {
 -                      m_access_points[d[0]] = d[1];
 -                      m_pts_to_offset.insert(std::pair<pts_t,off_t>(d[1], d[0]));
 -                      last = d[1];
 -                      loaded++;
 -              } else
 -                      skipped++;
 +              m_access_points[d[0]] = d[1];
 +              m_pts_to_offset.insert(std::pair<pts_t,off_t>(d[1], d[0]));
        }
 -      eDebug("loaded %d, skipped %d", loaded, skipped);
        fclose(f);
        fixupDiscontinuties();
        return 0;
@@@ -207,45 -216,30 +207,45 @@@ pts_t eMPEGStreamInformation::getInterp
        return before_ts + diff;
  }
   
 -off_t eMPEGStreamInformation::getAccessPoint(pts_t ts)
 +off_t eMPEGStreamInformation::getAccessPoint(pts_t ts, int marg)
  {
                /* FIXME: more efficient implementation */
        off_t last = 0;
 +      off_t last2 = 0;
 +      pts_t lastc = 0;
        for (std::map<off_t, pts_t>::const_iterator i(m_access_points.begin()); i != m_access_points.end(); ++i)
        {
                pts_t delta = getDelta(i->first);
                pts_t c = i->second - delta;
 -              if (c > ts)
 -                      break;
 +              if (c > ts) {
 +                      if (marg > 0)
 +                              return (last + i->first)/376*188;
 +                      else if (marg < 0)
 +                              return (last + last2)/376*188;
 +                      else
 +                              return last;
 +              }
 +              lastc = c;
 +              last2 = last;
                last = i->first;
        }
 -      return last;
 +      if (marg < 0)
 +              return (last + last2)/376*188;
 +      else
 +              return last;
  }
  
  int eMPEGStreamInformation::getNextAccessPoint(pts_t &ts, const pts_t &start, int direction)
  {
        off_t offset = getAccessPoint(start);
 +      pts_t c1, c2;
        std::map<off_t, pts_t>::const_iterator i = m_access_points.find(offset);
        if (i == m_access_points.end())
        {
                eDebug("getNextAccessPoint: initial AP not found");
                return -1;
        }
 +      c1 = i->second - getDelta(i->first);
        while (direction)
        {
                if (direction > 0)
                        if (i == m_access_points.end())
                                return -1;
                        ++i;
 +                      c2 = i->second - getDelta(i->first);
 +                      if (c1 == c2) { // Discontinuity
 +                              ++i;
 +                              c2 = i->second - getDelta(i->first);
 +                      }
 +                      c1 = c2;
                        direction--;
                }
                if (direction < 0)
                                return -1;
                        }
                        --i;
 +                      c2 = i->second - getDelta(i->first);
 +                      if (c1 == c2) { // Discontinuity
 +                              --i;
 +                              c2 = i->second - getDelta(i->first);
 +                      }
 +                      c1 = c2;
                        direction++;
                }
        }
        return 0;
  }
  
- eMPEGStreamParserTS::eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo): m_streaminfo(streaminfo), m_pktptr(0), m_pid(-1), m_need_next_packet(0), m_skip(0)
+ eMPEGStreamParserTS::eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo): m_streaminfo(streaminfo), m_pktptr(0), m_pid(-1), m_need_next_packet(0), m_skip(0), m_last_pts_valid(0)
  {
  }
  
@@@ -331,6 -313,9 +331,9 @@@ int eMPEGStreamParserTS::processPacket(
                pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
                pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
                ptsvalid = 1;
+               
+               m_last_pts = pts;
+               m_last_pts_valid = 1;
  
  #if 0         
                int sec = pts / 90000;
                                /*eDebug("Sequence header but no valid PTS value.")*/;
                }
  
 -              if (pkt[3] == 0x09) /* MPEG4 AVC unit access delimiter */
 +              if (pkt[3] == 0x09 &&   /* MPEG4 AVC unit access delimiter */
 +                       (pkt[4] >> 5) == 0) /* and I-frame */
                {
                        if (ptsvalid)
                        {
@@@ -522,3 -506,15 +525,15 @@@ void eMPEGStreamParserTS::setPid(int _p
        m_pktptr = 0;
        m_pid = _pid;
  }
+ int eMPEGStreamParserTS::getLastPTS(pts_t &last_pts)
+ {
+       if (!m_last_pts_valid)
+       {
+               last_pts = 0;
+               return -1;
+       }
+       last_pts = m_last_pts;
+       return 0;
+ }
diff --combined lib/dvb/pvrparse.h
index b2ddd23d56139a630021d76a44ef863a4fd1790a,94f9f67fddc2590cc492cb31f9c38a746cbe2ea9..20d334709f0f5ff8257ce0631f0b59d529069014
@@@ -41,7 -41,7 +41,7 @@@ public
                /* inter/extrapolate timestamp from offset */
        pts_t getInterpolated(off_t offset);
        
 -      off_t getAccessPoint(pts_t ts);
 +      off_t getAccessPoint(pts_t ts, int marg=0);
        
        int getNextAccessPoint(pts_t &ts, const pts_t &start, int direction);
        
@@@ -55,6 -55,7 +55,7 @@@ public
        eMPEGStreamParserTS(eMPEGStreamInformation &streaminfo);
        void parseData(off_t offset, const void *data, unsigned int len);
        void setPid(int pid);
+       int getLastPTS(pts_t &last_pts);
  private:
        eMPEGStreamInformation &m_streaminfo;
        unsigned char m_pkt[188];
@@@ -64,6 -65,8 +65,8 @@@
        int m_pid;
        int m_need_next_packet;
        int m_skip;
+       int m_last_pts_valid;
+       pts_t m_last_pts;
  };
  
  #endif
index 409018de272ca6ec718577d7fbe9dcf497727145,9e0e50aff7d3ef51a6257deaf14e1086de86df99..89a6b8e3e82879980bce0fff05710a3ddca0a993
@@@ -29,7 -29,7 +29,7 @@@ from Screens.TimeDateInput import TimeD
  from ServiceReference import ServiceReference
  
  from Tools import Notifications
- from Tools.Directories import SCOPE_HDD, resolveFilename, pathExists
+ from Tools.Directories import SCOPE_HDD, resolveFilename, fileExists
  
  from enigma import eTimer, eServiceCenter, eDVBServicePMTHandler, iServiceInformation, \
        iPlayableService, eServiceReference, eEPGCache
@@@ -348,14 -348,14 +348,14 @@@ class InfoBarMenu
  
        def mainMenu(self):
                print "loading mainmenu XML..."
-               menu = mdom.childNodes[0]
-               assert menu.tagName == "menu", "root element in menu must be 'menu'!"
+               menu = mdom.getroot()
+               assert menu.tag == "menu", "root element in menu must be 'menu'!"
  
                self.session.infobar = self
                # so we can access the currently active infobar from screens opened from within the mainmenu
                # at the moment used from the SubserviceSelection
  
-               self.session.openWithCallback(self.mainMenuClosed, MainMenu, menu, menu.childNodes)
+               self.session.openWithCallback(self.mainMenuClosed, MainMenu, menu)
  
        def mainMenuClosed(self, *val):
                self.session.infobar = None
@@@ -403,7 -403,7 +403,7 @@@ class InfoBarEPG
                self.eventView = None
                self["EPGActions"] = HelpableActionMap(self, "InfobarEPGActions",
                        {
-                               "showEventView": (self.openEventView, _("show EPG...")),
+                               "showEventInfo": (self.openEventView, _("show EPG...")),
                                "showEventInfoPlugin": (self.showEventInfoPlugins, _("show single service EPG...")),
                                "showInfobarOrEpgWhenInfobarAlreadyVisible": self.showEventInfoWhenNotVisible,
                        })
@@@ -779,21 -779,12 +779,21 @@@ class InfoBarSeek
                        print "not pauseable."
                        state = self.SEEK_STATE_PLAY
  
 -              oldstate = self.seekstate
                self.seekstate = state
  
 -              for i in range(3):
 -                      if oldstate[i] != self.seekstate[i]:
 -                              (self.session.nav.pause, pauseable.setFastForward, pauseable.setSlowMotion)[i](self.seekstate[i])
 +              if pauseable is not None:
 +                      if self.seekstate[0]:
 +                              print "resolved to PAUSE"
 +                              pauseable.pause()
 +                      elif self.seekstate[1]:
 +                              print "resolved to FAST FORWARD"
 +                              pauseable.setFastForward(self.seekstate[1])
 +                      elif self.seekstate[2]:
 +                              print "resolved to SLOW MOTION"
 +                              pauseable.setSlowMotion(self.seekstate[2])
 +                      else:
 +                              print "resolved to PLAY"
 +                              pauseable.unpause()
  
                for c in self.onPlayStateChanged:
                        c(self.seekstate)
@@@ -1033,7 -1024,13 +1033,13 @@@ class InfoBarPVRState
        def __playStateChanged(self, state):
                playstateString = state[3]
                self.pvrStateDialog["state"].setText(playstateString)
-               self._mayShow()
+               
+               # if we return into "PLAY" state, ensure that the dialog gets hidden if there will be no infobar displayed
+               if not config.usage.show_infobar_on_skip.value and self.seekstate == self.SEEK_STATE_PLAY:
+                       self.pvrStateDialog.hide()
+               else:
+                       self._mayShow()
+                       
  
  class InfoBarTimeshiftState(InfoBarPVRState):
        def __init__(self):
@@@ -1321,7 -1318,6 +1327,6 @@@ class InfoBarJobman
                self.session.openWithCallback(self.JobViewCB, JobView, job)
        
        def JobViewCB(self, in_background):
-               from Screens.TaskView import JobView
                job_manager.in_background = in_background
  
  # depends on InfoBarExtensions
@@@ -1437,8 -1433,8 +1442,8 @@@ class InfoBarInstantRecord
                except:
                        pass
  
-               begin = time()
-               end = time() + 3600 * 24 * 365 * 1 # 1 year
+               begin = int(time())
+               end = begin + 3600      # dummy
                name = "instant record"
                description = ""
                eventid = None
  
                recording = RecordTimerEntry(serviceref, begin, end, name, description, eventid, dirname = config.movielist.last_videodir.value)
                recording.dontSave = True
-               recording.autoincrease = True
-               simulTimerList = self.session.nav.RecordTimer.record(recording)
-               if simulTimerList is not None:
-                       print "timer conflict detected!"
-                       if (len(simulTimerList) > 1):
-                               print "tsc_list > 1"
-                               recording.end = simulTimerList[1].begin - 30
+               
+               if event is None or limitEvent == False:
+                       recording.autoincrease = True
+                       if recording.setAutoincreaseEnd():
                                self.session.nav.RecordTimer.record(recording)
-                               print "new endtime applied"
-                       else:
-                               print "conflict with only one timer? ! ?"
-               self.recording.append(recording)
+                               self.recording.append(recording)
+               else:
+                               simulTimerList = self.session.nav.RecordTimer.record(recording)
+                               if simulTimerList is not None:  # conflict with other recording
+                                       name = simulTimerList[1].name
+                                       name_date = name + strftime(" %c", localtime(simulTimerList[1].begin))
+                                       print "[TIMER] conflicts with", name_date
+                                       recording.autoincrease = True   # start with max available length, then increment
+                                       if recording.setAutoincreaseEnd():
+                                               self.session.nav.RecordTimer.record(recording)
+                                               self.recording.append(recording)
+                                               self.session.open(MessageBox, _("Record time limited due to conflicting timer %s") % name_date, MessageBox.TYPE_INFO)
+                                       else:
+                                               self.session.open(MessageBox, _("Couldn't record due to conflicting timer %s") % name, MessageBox.TYPE_INFO)
+                                       recording.autoincrease = False
+                               else:
+                                       self.recording.append(recording)
  
        def isInstantRecordRunning(self):
                print "self.recording:", self.recording
                        print "stopping recording after", int(value), "minutes."
                        if int(value) != 0:
                                self.recording[self.selectedEntry].autoincrease = False
-                       self.recording[self.selectedEntry].end = time() + 60 * int(value)
+                       self.recording[self.selectedEntry].end = int(time()) + 60 * int(value)
                        self.session.nav.RecordTimer.timeChanged(self.recording[self.selectedEntry])
  
        def instantRecord(self):
                dir = config.movielist.last_videodir.value
-               if not pathExists(dir):
+               if not fileExists(dir, 'w'):
                        dir = resolveFilename(SCOPE_HDD)
                try:
                        stat = os_stat(dir)
                if self.isInstantRecordRunning():
                        self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \
                                title=_("A recording is currently running.\nWhat do you want to do?"), \
-                               list=[(_("stop recording"), "stop"), \
-                               (_("change recording (duration)"), "changeduration"), \
-                               (_("change recording (endtime)"), "changeendtime"), \
-                               (_("add recording (indefinitely)"), "indefinitely"), \
-                               (_("add recording (stop after current event)"), "event"), \
+                               list=[(_("add recording (stop after current event)"), "event"), \
                                (_("add recording (enter recording duration)"), "manualduration"), \
                                (_("add recording (enter recording endtime)"), "manualendtime"), \
+                               (_("add recording (indefinitely)"), "indefinitely"), \
+                               (_("change recording (duration)"), "changeduration"), \
+                               (_("change recording (endtime)"), "changeendtime"), \
+                               (_("stop recording"), "stop"), \
                                (_("do nothing"), "no")])
                else:
                        self.session.openWithCallback(self.recordQuestionCallback, ChoiceBox, \
                                title=_("Start recording?"), \
-                               list=[(_("add recording (indefinitely)"), "indefinitely"), \
-                               (_("add recording (stop after current event)"), "event"), \
+                               list=[(_("add recording (stop after current event)"), "event"), \
                                (_("add recording (enter recording duration)"), "manualduration"), \
                                (_("add recording (enter recording endtime)"), "manualendtime"), \
+                               (_("add recording (indefinitely)"), "indefinitely"), \
                                (_("don't record"), "no")])
  
  from Tools.ISO639 import LanguageCodes
index af3ab206805c6890e1e4b7879c857c45e1a2faa4,d4a3a562ab649aa7391be26a31580362ec33f40a..33cd865e9ea7c648893a6f37fa9a6e20a802b65a
@@@ -96,217 -96,50 +96,50 @@@ int eStaticServiceDVBInformation::isPla
        return false;
  }
  
- static void PutToDict(ePyObject &dict, const char*key, long value)
- {
-       ePyObject item = PyString_FromFormat("%d", value);
-       if (item)
-       {
-               if (PyDict_SetItemString(dict, key, item))
-                       eDebug("put %s to dict failed", key);
-               Py_DECREF(item);
-       }
-       else
-               eDebug("could not create PyObject for %s", key);
- }
- extern void PutToDict(ePyObject &dict, const char*key, const char *value);
+ extern void PutToDict(ePyObject &dict, const char*key, long value);  // defined in dvb/frontend.cpp
+ extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp
+ extern void PutToDict(ePyObject &dict, const char*key, const char *value); // defined in dvb/frontend.cpp
  
  void PutSatelliteDataToDict(ePyObject &dict, eDVBFrontendParametersSatellite &feparm)
  {
-       const char *tmp=0;
-       PutToDict(dict, "type", "Satellite");
+       PutToDict(dict, "tuner_type", "DVB-S");
        PutToDict(dict, "frequency", feparm.frequency);
-       PutToDict(dict, "symbolrate", feparm.symbol_rate);
-       PutToDict(dict, "orbital position", feparm.orbital_position);
-       switch (feparm.inversion)
-       {
-               case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
-               case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
-               default:
-               case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "inversion", tmp);
-       switch (feparm.fec)
-       {
-               case eDVBFrontendParametersSatellite::FEC::fNone: tmp="NONE"; break;
-               case eDVBFrontendParametersSatellite::FEC::f1_2: tmp="1/2"; break;
-               case eDVBFrontendParametersSatellite::FEC::f2_3: tmp="2/3"; break;
-               case eDVBFrontendParametersSatellite::FEC::f3_4: tmp="3/4"; break;
-               case eDVBFrontendParametersSatellite::FEC::f5_6: tmp="5/6"; break;
-               case eDVBFrontendParametersSatellite::FEC::f7_8: tmp="7/8"; break;
-               case eDVBFrontendParametersSatellite::FEC::f3_5: tmp="3/5"; break;
-               case eDVBFrontendParametersSatellite::FEC::f4_5: tmp="4/5"; break;
-               case eDVBFrontendParametersSatellite::FEC::f8_9: tmp="8/9"; break;
-               case eDVBFrontendParametersSatellite::FEC::f9_10: tmp="9/10"; break;
-               default:
-               case eDVBFrontendParametersSatellite::FEC::fAuto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "fec inner", tmp);
-       switch (feparm.modulation)
-       {
-               case eDVBFrontendParametersSatellite::Modulation::Auto: tmp="AUTO"; break;
-               case eDVBFrontendParametersSatellite::Modulation::QPSK: tmp="QPSK"; break;
-               case eDVBFrontendParametersSatellite::Modulation::M8PSK: tmp="8PSK"; break;
-               case eDVBFrontendParametersSatellite::Modulation::QAM_16: tmp="QAM16"; break;
-       }
-       PutToDict(dict, "modulation", tmp);
-       switch(feparm.polarisation)
+       PutToDict(dict, "symbol_rate", feparm.symbol_rate);
+       PutToDict(dict, "orbital_position", feparm.orbital_position);
+       PutToDict(dict, "inversion", feparm.inversion);
+       PutToDict(dict, "fec_inner", feparm.fec);
+       PutToDict(dict, "modulation", feparm.modulation);
+       PutToDict(dict, "polarization", feparm.polarisation);
+       if (feparm.system == eDVBFrontendParametersSatellite::System_DVB_S2)
        {
-               case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
-               case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
-               case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR LEFT"; break;
-               default:
-               case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR RIGHT"; break;
-       }
-       PutToDict(dict, "polarization", tmp);
-       switch(feparm.system)
-       {
-               default:
-               case eDVBFrontendParametersSatellite::System::DVB_S: tmp="DVB-S"; break;
-               case eDVBFrontendParametersSatellite::System::DVB_S2:
-                       switch(feparm.rolloff)
-                       {
-                               default:
-                               case eDVBFrontendParametersSatellite::RollOff::alpha_0_35: tmp="0.35"; break;
-                               case eDVBFrontendParametersSatellite::RollOff::alpha_0_25: tmp="0.25"; break;
-                               case eDVBFrontendParametersSatellite::RollOff::alpha_0_20: tmp="0.20"; break;
-                       }
-                       PutToDict(dict, "roll off", tmp);
-                       switch(feparm.pilot)
-                       {
-                               case eDVBFrontendParametersSatellite::Pilot::On: tmp="ON"; break;
-                               case eDVBFrontendParametersSatellite::Pilot::Off: tmp="OFF"; break;
-                               default:
-                               case eDVBFrontendParametersSatellite::Pilot::Unknown: tmp="AUTO"; break;
-                       }
-                       PutToDict(dict, "pilot", tmp);
-                       tmp="DVB-S2";
-                       break;
+               PutToDict(dict, "rolloff", feparm.rolloff);
+               PutToDict(dict, "pilot", feparm.pilot);
        }
-       PutToDict(dict, "system", tmp);
+       PutToDict(dict, "system", feparm.system);
  }
  
  void PutTerrestrialDataToDict(ePyObject &dict, eDVBFrontendParametersTerrestrial &feparm)
  {
-       PutToDict(dict, "type", "Terrestrial");
+       PutToDict(dict, "tuner_type", "DVB-T");
        PutToDict(dict, "frequency", feparm.frequency);
-       const char *tmp=0;
-       switch (feparm.bandwidth)
-       {
-       case eDVBFrontendParametersTerrestrial::Bandwidth::Bw8MHz: tmp="8 MHz"; break;
-       case eDVBFrontendParametersTerrestrial::Bandwidth::Bw7MHz: tmp="7 MHz"; break;
-       case eDVBFrontendParametersTerrestrial::Bandwidth::Bw6MHz: tmp="6 MHz"; break;
-       default:
-       case eDVBFrontendParametersTerrestrial::Bandwidth::BwAuto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "bandwidth", tmp);
-       switch (feparm.code_rate_LP)
-       {
-       case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
-       case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
-       case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
-       case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
-       case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
-       default:
-       case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "code rate lp", tmp);
-       switch (feparm.code_rate_HP)
-       {
-       case eDVBFrontendParametersTerrestrial::FEC::f1_2: tmp="1/2"; break;
-       case eDVBFrontendParametersTerrestrial::FEC::f2_3: tmp="2/3"; break;
-       case eDVBFrontendParametersTerrestrial::FEC::f3_4: tmp="3/4"; break;
-       case eDVBFrontendParametersTerrestrial::FEC::f5_6: tmp="5/6"; break;
-       case eDVBFrontendParametersTerrestrial::FEC::f7_8: tmp="7/8"; break;
-       default:
-       case eDVBFrontendParametersTerrestrial::FEC::fAuto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "code rate hp", tmp);
-       switch (feparm.modulation)
-       {
-       case eDVBFrontendParametersTerrestrial::Modulation::QPSK: tmp="QPSK"; break;
-       case eDVBFrontendParametersTerrestrial::Modulation::QAM16: tmp="QAM16"; break;
-       case eDVBFrontendParametersTerrestrial::Modulation::QAM64: tmp="QAM64"; break;
-       default:
-       case eDVBFrontendParametersTerrestrial::Modulation::Auto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "constellation", tmp);
-       switch (feparm.transmission_mode)
-       {
-       case eDVBFrontendParametersTerrestrial::TransmissionMode::TM2k: tmp="2k"; break;
-       case eDVBFrontendParametersTerrestrial::TransmissionMode::TM8k: tmp="8k"; break;
-       default:
-       case eDVBFrontendParametersTerrestrial::TransmissionMode::TMAuto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "transmission mode", tmp);
-       switch (feparm.guard_interval)
-       {
-               case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_32: tmp="1/32"; break;
-               case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_16: tmp="1/16"; break;
-               case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_8: tmp="1/8"; break;
-               case eDVBFrontendParametersTerrestrial::GuardInterval::GI_1_4: tmp="1/4"; break;
-               default:
-               case eDVBFrontendParametersTerrestrial::GuardInterval::GI_Auto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "guard interval", tmp);
-       switch (feparm.hierarchy)
-       {
-               case eDVBFrontendParametersTerrestrial::Hierarchy::HNone: tmp="NONE"; break;
-               case eDVBFrontendParametersTerrestrial::Hierarchy::H1: tmp="1"; break;
-               case eDVBFrontendParametersTerrestrial::Hierarchy::H2: tmp="2"; break;
-               case eDVBFrontendParametersTerrestrial::Hierarchy::H4: tmp="4"; break;
-               default:
-               case eDVBFrontendParametersTerrestrial::Hierarchy::HAuto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "hierarchy", tmp);
-       switch (feparm.inversion)
-       {
-               case eDVBFrontendParametersSatellite::Inversion::On: tmp="ON"; break;
-               case eDVBFrontendParametersSatellite::Inversion::Off: tmp="OFF"; break;
-               default:
-               case eDVBFrontendParametersSatellite::Inversion::Unknown: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "inversion", tmp);
+       PutToDict(dict, "bandwidth", feparm.bandwidth);
+       PutToDict(dict, "code_rate_lp", feparm.code_rate_LP);
+       PutToDict(dict, "code_rate_hp", feparm.code_rate_HP);
+       PutToDict(dict, "constellation", feparm.modulation);
+       PutToDict(dict, "transmission_mode", feparm.transmission_mode);
+       PutToDict(dict, "guard_interval", feparm.guard_interval);
+       PutToDict(dict, "hierarchy_information", feparm.hierarchy);
+       PutToDict(dict, "inversion", feparm.inversion);
  }
  
  void PutCableDataToDict(ePyObject &dict, eDVBFrontendParametersCable &feparm)
  {
-       const char *tmp=0;
-       PutToDict(dict, "type", "Cable");
+       PutToDict(dict, "tuner_type", "DVB-C");
        PutToDict(dict, "frequency", feparm.frequency);
-       PutToDict(dict, "symbolrate", feparm.symbol_rate);
-       switch (feparm.modulation)
-       {
-       case eDVBFrontendParametersCable::Modulation::QAM16: tmp="QAM16"; break;
-       case eDVBFrontendParametersCable::Modulation::QAM32: tmp="QAM32"; break;
-       case eDVBFrontendParametersCable::Modulation::QAM64: tmp="QAM64"; break;
-       case eDVBFrontendParametersCable::Modulation::QAM128: tmp="QAM128"; break;
-       case eDVBFrontendParametersCable::Modulation::QAM256: tmp="QAM256"; break;
-       default:
-       case eDVBFrontendParametersCable::Modulation::Auto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "modulation", tmp);
-       switch (feparm.inversion)
-       {
-       case eDVBFrontendParametersCable::Inversion::On: tmp="ON"; break;
-       case eDVBFrontendParametersCable::Inversion::Off: tmp="OFF"; break;
-       default:
-       case eDVBFrontendParametersCable::Inversion::Unknown: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "inversion", tmp);
-       switch (feparm.fec_inner)
-       {
-       case eDVBFrontendParametersCable::FEC::fNone: tmp="NONE"; break;
-       case eDVBFrontendParametersCable::FEC::f1_2: tmp="1/2"; break;
-       case eDVBFrontendParametersCable::FEC::f2_3: tmp="2/3"; break;
-       case eDVBFrontendParametersCable::FEC::f3_4: tmp="3/4"; break;
-       case eDVBFrontendParametersCable::FEC::f5_6: tmp="5/6"; break;
-       case eDVBFrontendParametersCable::FEC::f7_8: tmp="7/8"; break;
-       case eDVBFrontendParametersCable::FEC::f8_9: tmp="8/9"; break;
-       default:
-       case eDVBFrontendParametersCable::FEC::fAuto: tmp="AUTO"; break;
-       }
-       PutToDict(dict, "fec inner", tmp);
+       PutToDict(dict, "symbol_rate", feparm.symbol_rate);
+       PutToDict(dict, "modulation", feparm.modulation);
+       PutToDict(dict, "inversion", feparm.inversion);
+       PutToDict(dict, "fec_inner", feparm.fec_inner);
  }
  
  PyObject *eStaticServiceDVBInformation::getInfoObject(const eServiceReference &r, int what)
@@@ -534,14 -367,25 +367,25 @@@ int eStaticServiceDVBPVRInformation::ge
        
        eDVBTSTools tstools;
        
+       struct stat s;
+       stat(ref.path.c_str(), &s);
        if (tstools.openFile(ref.path.c_str()))
                return 0;
  
+                       /* check if cached data is still valid */
+       if (m_parser.m_data_ok && (s.st_size == m_parser.m_filesize) && (m_parser.m_length))
+               return m_parser.m_length / 90000;
+                       /* otherwise, re-calc length and update meta file */
        pts_t len;
        if (tstools.calcLen(len))
                return 0;
  
-       return len / 90000;
+       m_parser.m_length = len;
+       m_parser.m_filesize = s.st_size;
+       m_parser.updateMeta(ref.path);
+       return m_parser.m_length / 90000;
  }
  
  int eStaticServiceDVBPVRInformation::getInfo(const eServiceReference &ref, int w)
@@@ -1042,7 -886,6 +886,6 @@@ RESULT eServiceFactoryDVB::lookupServic
  eDVBServicePlay::eDVBServicePlay(const eServiceReference &ref, eDVBService *service): 
        m_reference(ref), m_dvb_service(service), m_have_video_pid(0), m_is_paused(0)
  {
-       memset(&m_videoEventData, 0, sizeof(struct iTSMPEGDecoder::videoEvent));
        m_is_primary = 1;
        m_is_pvr = !m_reference.path.empty();
        
@@@ -1281,9 -1124,6 +1124,9 @@@ RESULT eDVBServicePlay::pause(ePtr<iPau
  
  RESULT eDVBServicePlay::setSlowMotion(int ratio)
  {
 +      assert(ratio); /* The API changed: instead of calling setSlowMotion(0), call play! */
 +      eDebug("eDVBServicePlay::setSlowMotion(%d)", ratio);
 +      setFastForward_internal(0);
        if (m_decoder)
                return m_decoder->setSlowMotion(ratio);
        else
  }
  
  RESULT eDVBServicePlay::setFastForward(int ratio)
 +{
 +      eDebug("eDVBServicePlay::setFastForward(%d)", ratio);
 +      assert(ratio);
 +      return setFastForward_internal(ratio);
 +}
 +
 +RESULT eDVBServicePlay::setFastForward_internal(int ratio)
  {
        int skipmode, ffratio;
        
        if (!m_decoder)
                return -1;
  
 -      return m_decoder->setFastForward(ffratio);
 +      if (ffratio == 0)
 +              return 0;
 +      else if (ffratio != 1)
 +              return m_decoder->setFastForward(ffratio);
 +      else
 +              return m_decoder->setTrickmode();
  }
  
  RESULT eDVBServicePlay::seek(ePtr<iSeekableService> &ptr)
@@@ -1364,22 -1192,20 +1207,22 @@@ RESULT eDVBServicePlay::getLength(pts_
  
  RESULT eDVBServicePlay::pause()
  {
 -      if (!m_is_paused && m_decoder)
 +      eDebug("eDVBServicePlay::pause");
 +      setFastForward_internal(0);
 +      if (m_decoder)
        {
 -              m_is_paused = 1;
 -              return m_decoder->freeze(0);
 +              return m_decoder->pause();
        } else
                return -1;
  }
  
  RESULT eDVBServicePlay::unpause()
  {
 -      if (m_is_paused && m_decoder)
 +      eDebug("eDVBServicePlay::unpause");
 +      setFastForward_internal(0);
 +      if (m_decoder)
        {
 -              m_is_paused = 0;
 -              return m_decoder->unfreeze();
 +              return m_decoder->play();
        } else
                return -1;
  }
@@@ -1461,8 -1287,9 +1304,8 @@@ RESULT eDVBServicePlay::getPlayPosition
  
  RESULT eDVBServicePlay::setTrickmode(int trick)
  {
 -      if (m_decoder)
 -              m_decoder->setTrickmode(trick);
 -      return 0;
 +              /* currently unimplemented */
 +      return -1;
  }
  
  RESULT eDVBServicePlay::isCurrentlySeekable()
@@@ -1589,20 -1416,6 +1432,6 @@@ RESULT eDVBServicePlay::getEvent(ePtr<e
        return m_event_handler.getEvent(evt, nownext);
  }
  
- static int readMpegProc(char *str, int decoder)
- {
-       int val = -1;
-       char tmp[64];
-       sprintf(tmp, "/proc/stb/vmpeg/%d/%s", decoder, str);
-       FILE *f = fopen(tmp, "r");
-       if (f)
-       {
-               fscanf(f, "%x", &val);
-               fclose(f);
-       }
-       return val;
- }
  int eDVBServicePlay::getInfo(int w)
  {
        eDVBServicePMTHandler::program program;
  
        switch (w)
        {
- #if HAVE_DVB_API_VERSION >= 3
        case sVideoHeight:
-               if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
-                       return m_videoEventData.height;
-               else
-                       return readMpegProc("yres", !m_is_primary);
+               if (m_decoder)
+                       return m_decoder->getVideoHeight();
+               break;
        case sVideoWidth:
-               if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
-                       return m_videoEventData.width;
-               else
-                       return readMpegProc("xres", !m_is_primary);
+               if (m_decoder)
+                       return m_decoder->getVideoWidth();
+               break;
        case sFrameRate:
-               if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventFrameRateChanged)
-                       return m_videoEventData.framerate;
-               else
-                       return readMpegProc("framerate", !m_is_primary);
+               if (m_decoder)
+                       return m_decoder->getVideoFrameRate();
+               break;
        case sProgressive:
-               if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventProgressiveChanged)
-                       return m_videoEventData.progressive;
-               return readMpegProc("progressive", !m_is_primary);
- #else
- #warning "FIXMEE implement sFrameRate, sProgressive, sVideoHeight, sVideoWidth for old DVB API"
- #endif
+               if (m_decoder)
+                       return m_decoder->getVideoProgressive();
+               break;
        case sAspect:
        {
-               int val;
- #if HAVE_DVB_API_VERSION >= 3
-               if (m_videoEventData.type == iTSMPEGDecoder::videoEvent::eventSizeChanged)
-                       return m_videoEventData.aspect == VIDEO_FORMAT_4_3 ? 1 : 3;
-               else if ((val=readMpegProc("aspect", !m_is_primary)) != -1)
-                       return val;
-               else
- #else
- #warning "FIXMEE implement sAspect for old DVB API"
- #endif
+               int aspect = -1;
+               if (m_decoder)
+                       aspect = m_decoder->getVideoAspect();
                if (no_program_info)
-                       return -1; 
-               else if (!program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
+                       break;
+               else if (aspect == -1 && !program.videoStreams.empty() && program.videoStreams[0].component_tag != -1)
                {
                        ePtr<eServiceEvent> evt;
                        if (!m_event_handler.getEvent(evt, 0))
                                }
                        }
                }
-               return -1;
+               else
+                       return aspect;
+               break;
        }
        case sIsCrypted: if (no_program_info) return -1; return program.isCrypted();
        case sVideoPID: if (no_program_info) return -1; if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
        case sServiceref: return resIsString;
        case sDVBState: return m_tune_state;
        default:
-               return -1;
+               break;
        }
+       return -1;
  }
  
  std::string eDVBServicePlay::getInfoString(int w)
@@@ -1773,7 -1575,7 +1591,7 @@@ RESULT eDVBServicePlay::selectTrack(uns
  {
        int ret = selectAudioStream(i);
  
 -      if (m_decoder->start())
 +      if (m_decoder->play())
                return -5;
  
        return ret;
@@@ -1798,6 -1600,8 +1616,8 @@@ RESULT eDVBServicePlay::getTrackInfo(st
                info.m_description = "AC3";
        else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAAC)
                info.m_description = "AAC";
+       else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atAACHE)
+               info.m_description = "AAC-HE";
        else  if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS)
                info.m_description = "DTS";
        else
@@@ -2056,19 -1860,8 +1876,8 @@@ PyObject *eDVBServiceBase::getTranspond
                                        eDVBFrontendParametersSatellite osat;
                                        if (!feparm->getDVBS(osat))
                                        {
-                                               void PutToDict(ePyObject &, const char*, long);
-                                               void PutToDict(ePyObject &, const char*, const char*);
                                                PutToDict(ret, "orbital_position", osat.orbital_position);
-                                               const char *tmp = "UNKNOWN";
-                                               switch(osat.polarisation)
-                                               {
-                                                       case eDVBFrontendParametersSatellite::Polarisation::Horizontal: tmp="HORIZONTAL"; break;
-                                                       case eDVBFrontendParametersSatellite::Polarisation::Vertical: tmp="VERTICAL"; break;
-                                                       case eDVBFrontendParametersSatellite::Polarisation::CircularLeft: tmp="CIRCULAR_LEFT"; break;
-                                                       case eDVBFrontendParametersSatellite::Polarisation::CircularRight: tmp="CIRCULAR_RIGHT"; break;
-                                                       default:break;
-                                               }
-                                               PutToDict(ret, "polarization", tmp);
+                                               PutToDict(ret, "polarization", osat.polarisation);
                                        }
                                }
                        }
@@@ -2213,8 -2006,8 +2022,8 @@@ PyObject *eDVBServicePlay::getCutList(
        for (std::multiset<struct cueEntry>::iterator i(m_cue_entries.begin()); i != m_cue_entries.end(); ++i)
        {
                ePyObject tuple = PyTuple_New(2);
-               PyTuple_SetItem(tuple, 0, PyLong_FromLongLong(i->where));
-               PyTuple_SetItem(tuple, 1, PyInt_FromLong(i->what));
+               PyTuple_SET_ITEM(tuple, 0, PyLong_FromLongLong(i->where));
+               PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong(i->what));
                PyList_Append(list, tuple);
                Py_DECREF(tuple);
        }
@@@ -2498,12 -2291,12 +2307,12 @@@ void eDVBServicePlay::updateDecoder(
                m_teletext_parser->start(program.textPid);
  
                if (!m_is_primary)
 -                      m_decoder->setTrickmode(1);
 +                      m_decoder->setTrickmode();
  
                if (m_is_paused)
 -                      m_decoder->preroll();
 +                      m_decoder->pause();
                else
 -                      m_decoder->start();
 +                      m_decoder->play();
  
                if (vpid > 0 && vpid < 0x2000)
                        ;
@@@ -3014,7 -2807,6 +2823,6 @@@ void eDVBServicePlay::setPCMDelay(int d
  
  void eDVBServicePlay::video_event(struct iTSMPEGDecoder::videoEvent event)
  {
-       memcpy(&m_videoEventData, &event, sizeof(event));
        switch(event.type) {
                case iTSMPEGDecoder::videoEvent::eventSizeChanged:
                        m_event((iPlayableService*)this, evVideoSizeChanged);
@@@ -3041,18 -2833,16 +2849,16 @@@ PyObject *eDVBServicePlay::getStreaming
        eDVBServicePMTHandler::program program;
        if (m_service_handler.getProgramInfo(program))
        {
-               Py_INCREF(Py_None);
-               return Py_None;
+               Py_RETURN_NONE;
        }
  
-       PyObject *r = program.createPythonObject();
+       ePyObject r = program.createPythonObject();
        ePtr<iDVBDemux> demux;
        if (!m_service_handler.getDataDemux(demux))
        {
                uint8_t demux_id;
-               demux->getCADemuxID(demux_id);
-               
-               PyDict_SetItemString(r, "demux", PyInt_FromLong(demux_id));
+               if (!demux->getCADemuxID(demux_id))
+                       PutToDict(r, "demux", demux_id);
        }
  
        return r;
diff --combined lib/service/servicedvb.h
index c19e1ed520442a08562142a55922a48ca344a85b,56ec89eaa52a11498371479ffa57924533807e72..43e4690f8b3509395d21c58f607ed1f390741d67
@@@ -218,7 -218,6 +218,7 @@@ private
  
        int m_current_audio_stream;
        int selectAudioStream(int n = -1);
 +      RESULT setFastForward_internal(int ratio);
        
                /* timeshift */
        ePtr<iDVBTSRecorder> m_record;
  
        ePtr<eConnection> m_video_event_connection;
        void video_event(struct iTSMPEGDecoder::videoEvent);
-       struct iTSMPEGDecoder::videoEvent m_videoEventData;
  };
  
  class eStaticServiceDVBBouquetInformation: public iStaticServiceInformation