Index: NuppelVideoPlayer.cpp
===================================================================
--- NuppelVideoPlayer.cpp	(revision 8040)
+++ NuppelVideoPlayer.cpp	(working copy)
@@ -4762,3 +4767,13 @@
     }
 }
 
+void NuppelVideoPlayer::ChangeDVDTrack(bool ffw)
+{
+    if ( !ringBuffer->isDVD())
+       return;
+
+    GetDecoder()->ChangeDVDTrack(ffw);
+    usleep(100000);
+    ClearAfterSeek();
+}
+
Index: NuppelVideoPlayer.h
===================================================================
--- NuppelVideoPlayer.h	(revision 8040)
+++ NuppelVideoPlayer.h	(working copy)
@@ -249,6 +249,9 @@
     void CheckTVChain();
     void FileChangedCallback();
 
+    // DVD public stuff
+    void ChangeDVDTrack(bool ffw);
+
   protected:
     void DisplayPauseFrame(void);
     void DisplayNormalFrame(void);
Index: decoderbase.cpp
===================================================================
--- decoderbase.cpp	(revision 8040)
+++ decoderbase.cpp	(working copy)
@@ -88,8 +88,15 @@
     // Overwrites current positionmap with entire contents of database
     QMap<long long, long long> posMap;
 
-
-    if ((positionMapType == MARK_UNSET) ||
+    if (ringBuffer->isDVD())
+    {
+        keyframedist = 15;
+        if (fps < 26 && fps > 24)
+           keyframedist = 12;
+        long long totframes =(long long) (ringBuffer->GetTotalTimeOfTitle() * fps);
+        posMap[totframes] = ringBuffer->GetTotalReadPosition();
+    }
+    else if ((positionMapType == MARK_UNSET) ||
         (keyframedist == -1))
     {
         m_playbackinfo->GetPositionMap(posMap, MARK_GOP_BYFRAME);
@@ -296,9 +303,19 @@
     bool ret_val = m_positionMap.size() > old_posmap_size;
     if (ret_val && keyframedist > 0)
     {
-        long long totframes = 
-            m_positionMap[m_positionMap.size()-1].index * keyframedist;
-        int length = (int)((totframes * 1.0) / fps);
+        long long totframes;
+        int length;
+        if (ringBuffer->isDVD())
+        {
+            totframes = m_positionMap[m_positionMap.size()-1].index;
+            length = ringBuffer->GetTotalTimeOfTitle();
+        }
+        else
+        {
+            totframes = 
+                m_positionMap[m_positionMap.size()-1].index * keyframedist;
+            length = (int)((totframes * 1.0) / fps);
+        }
         GetNVP()->SetFileLength(length, totframes);
         GetNVP()->SetKeyframeDistance(keyframedist);
         posmapStarted = true;
@@ -392,42 +409,51 @@
     if (m_positionMap.empty())
         return false;
 
-    // Find keyframe <= desiredFrame, store in lastKey (frames)
-    int pos_idx1, pos_idx2;
+    if (ringBuffer->isDVD())
+    {
+        long long pos = DVDFindPosition(desiredFrame);
+        ringBuffer->Seek(pos,SEEK_SET);
+        lastKey = desiredFrame+1;
+    }
+    else
+    {
+        // Find keyframe <= desiredFrame, store in lastKey (frames)
+        int pos_idx1, pos_idx2;
 
-    FindPosition(desiredFrame, hasKeyFrameAdjustTable, pos_idx1, pos_idx2);
+        FindPosition(desiredFrame, hasKeyFrameAdjustTable, pos_idx1, pos_idx2);
 
-    int pos_idx = pos_idx1 < pos_idx2 ? pos_idx1 : pos_idx2;
+        int pos_idx = pos_idx1 < pos_idx2 ? pos_idx1 : pos_idx2;
 
-    if (hasKeyFrameAdjustTable)
-        lastKey = m_positionMap[pos_idx].adjFrame;
-    else
-        lastKey = m_positionMap[pos_idx].index * keyframedist;
-
-    long long keyPos = m_positionMap[pos_idx].pos;
-    long long curPosition = ringBuffer->GetReadPosition();
-    long long diff = keyPos - curPosition;
-
-    // Don't rewind further than we have space to store video
-    while (keyPos <= 0)
-    {
-        pos_idx++;
-        if (pos_idx >= (int)m_positionMap.size())
-        {
-            diff = 0;
-            return false;
-        }
         if (hasKeyFrameAdjustTable)
             lastKey = m_positionMap[pos_idx].adjFrame;
         else
             lastKey = m_positionMap[pos_idx].index * keyframedist;
-        keyPos = m_positionMap[pos_idx].pos;
 
-        diff = keyPos - curPosition;
+        long long keyPos = m_positionMap[pos_idx].pos;
+        long long curPosition = ringBuffer->GetReadPosition();
+        long long diff = keyPos - curPosition;
+
+        // Don't rewind further than we have space to store video
+        while (keyPos <= 0)
+        {
+            pos_idx++;
+            if (pos_idx >= (int)m_positionMap.size())
+           {
+                diff = 0;
+                return false;
+            }
+            if (hasKeyFrameAdjustTable)
+                lastKey = m_positionMap[pos_idx].adjFrame;
+            else
+                lastKey = m_positionMap[pos_idx].index * keyframedist;
+                keyPos = m_positionMap[pos_idx].pos;
+
+             diff = keyPos - curPosition;
+         }
+
+         ringBuffer->Seek(diff, SEEK_CUR);
     }
 
-    ringBuffer->Seek(diff, SEEK_CUR);
-    
     framesPlayed = lastKey;
     framesRead = lastKey;
 
@@ -455,11 +481,14 @@
     if (desiredFrame < framesPlayed)
         return DoRewind(desiredFrame, doflush);
 
+
     bool oldrawstate = getrawframes;
     getrawframes = false;
 
     long long last_frame = 0;
-    if (!m_positionMap.empty())
+    if (ringBuffer->isDVD())
+        last_frame = m_positionMap[m_positionMap.size()-1].index;
+    else if (!m_positionMap.empty())
         last_frame = m_positionMap[m_positionMap.size()-1].index * keyframedist;
 
     if (desiredFrame > last_frame)
@@ -474,6 +503,8 @@
 
     bool needflush = false;
 
+    if (ringBuffer->isDVD())
+        last_frame = m_positionMap[m_positionMap.size()-1].index;
     if (!m_positionMap.empty())
         last_frame = m_positionMap[m_positionMap.size()-1].index * keyframedist;
 
@@ -506,29 +537,40 @@
     if (m_positionMap.empty())
         return false;
 
-    // Find keyframe >= desiredFrame, store in lastKey
-    // if exactseeks, use keyframe <= desiredFrame
-    int pos_idx1, pos_idx2;
-    FindPosition(desiredFrame, hasKeyFrameAdjustTable, pos_idx1, pos_idx2);
+    if (ringBuffer->isDVD())
+    {
+        long long pos = DVDFindPosition(desiredFrame);
+        ringBuffer->Seek(pos,SEEK_SET);
+        lastKey = desiredFrame+1;
+        framesPlayed = lastKey;
+        framesRead = lastKey;
+    }
+    else
+    {
+        // Find keyframe >= desiredFrame, store in lastKey
+        // if exactseeks, use keyframe <= desiredFrame
+        int pos_idx1, pos_idx2;
+        FindPosition(desiredFrame, hasKeyFrameAdjustTable, pos_idx1, pos_idx2);
 
-    int pos_idx = pos_idx1 < pos_idx2 ? pos_idx1 : pos_idx2;
+        int pos_idx = pos_idx1 < pos_idx2 ? pos_idx1 : pos_idx2;
 
-    if (hasKeyFrameAdjustTable)
-        lastKey = m_positionMap[pos_idx].adjFrame;
-    else
-        lastKey = m_positionMap[pos_idx].index * keyframedist;
+        if (hasKeyFrameAdjustTable)
+            lastKey = m_positionMap[pos_idx].adjFrame;
+        else
+            lastKey = m_positionMap[pos_idx].index * keyframedist;
 
-    long long keyPos = m_positionMap[pos_idx].pos;
+        long long keyPos = m_positionMap[pos_idx].pos;
 
-    if (framesPlayed < lastKey)
-    {
-        long long diff = keyPos - ringBuffer->GetReadPosition();
+        if (framesPlayed < lastKey)
+        {
+            long long diff = keyPos - ringBuffer->GetReadPosition();
 
-        ringBuffer->Seek(diff, SEEK_CUR);
-        needflush = true;
-    
-        framesPlayed = lastKey;
-        framesRead = lastKey;
+            ringBuffer->Seek(diff, SEEK_CUR);
+            needflush = true;
+      
+            framesPlayed = lastKey;
+            framesRead = lastKey;
+        }
     }
 
     int normalframes = desiredFrame - framesPlayed;
@@ -577,3 +619,50 @@
     waitingForChange = true;
 }
  
+void DecoderBase::ChangeDVDTrack(bool ffw)
+{
+    bool result = true;
+    if (!ringBuffer->isDVD())
+        return;
+
+    uint prevcellstart = ringBuffer->GetCellStart();
+
+    if (ffw)
+        result = ringBuffer->nextTrack();
+    else
+        ringBuffer->prevTrack();
+
+    if (result)
+   {
+
+        if ((prevcellstart == 0 && ffw) || (prevcellstart != 0 ))
+        {
+           while (prevcellstart == ringBuffer->GetCellStart())
+           {
+               usleep(10000);
+           }
+        } 
+
+        uint elapsed = ringBuffer->GetCellStart();
+
+        if (elapsed == 0)
+           SeekReset(framesPlayed,0,true);
+
+        // update frames played
+        long long played = (int) (elapsed * fps);
+
+        framesPlayed = played;
+        GetNVP()->getVideoOutput()->SetFramesPlayed(played+1);
+        GetNVP()->SetFramesPlayed(played+1);
+   }
+}
+
+long long DecoderBase::DVDFindPosition(long long desiredFrame)
+{
+    if ( !ringBuffer->isDVD())
+       return 0;
+    
+   int size = m_positionMap.size() - 1;
+   int multiplier = m_positionMap[size].pos / m_positionMap[size].index ;
+   return (long long) (desiredFrame * multiplier);
+}
Index: decoderbase.h
===================================================================
--- decoderbase.h	(revision 8040)
+++ decoderbase.h	(working copy)
@@ -85,6 +85,10 @@
     void SetWaitForChange(void);
     void SetReadAdjust(long long adjust);
 
+    // DVD public stuff
+    void ChangeDVDTrack(bool ffw);
+    long long DVDFindPosition(long long desiredFrame);
+
   protected:
     void FileChanged(void);
 
Index: RingBuffer.h
===================================================================
--- RingBuffer.h	(revision 8040)
+++ RingBuffer.h	(working copy)
@@ -77,8 +77,11 @@
     bool isDVD(void) const { return dvdPriv; }
     void getPartAndTitle(int &title, int &part);
     void getDescForPos(QString &desc);
-    void nextTrack(void);
+    bool nextTrack(void);
     void prevTrack(void);
+    uint GetTotalTimeOfTitle(void);
+    uint GetCellStart(void);
+    long long GetTotalReadPosition(void);
 
     long long SetAdjustFilesize(void);
     
Index: RingBuffer.cpp
===================================================================
--- RingBuffer.cpp	(revision 8040)
+++ RingBuffer.cpp	(working copy)
@@ -1112,10 +1112,11 @@
 /** \fn RingBuffer::nextTrack(void)
  *  \brief Calls DVDRingBufferPriv::nextTrack(void)
  */
-void RingBuffer::nextTrack(void)
+bool RingBuffer::nextTrack(void)
 {
    if (dvdPriv)
-       dvdPriv->nextTrack();
+       return dvdPriv->nextTrack();
+   return false;
 }
 
 /** \fn RingBuffer::prevTrack(void)
@@ -1127,3 +1128,34 @@
        dvdPriv->prevTrack();
 }
 
+/** \fn RingBuffer::GetTotalTimeOfTitle(void)
+ *  \brief Calls DVDRingBufferPriv::GetTotalTimeOfTitle(void)
+ */
+uint RingBuffer::GetTotalTimeOfTitle(void)
+{
+   if (dvdPriv)
+       return dvdPriv->GetTotalTimeOfTitle();
+   return 0;
+}
+
+/** \fn RingBuffer::GetCellStart(void)
+ *  \brief Calls DVDRingBufferPriv::GetCellStart(void)
+ */
+uint RingBuffer::GetCellStart(void)
+{
+   if (dvdPriv)
+       return dvdPriv->GetCellStart();
+   return 0;
+}
+
+/** \fn RingBuffer::GetTotalReadPosition(void)
+ *  \brief Calls DVDRingBufferPriv::GetTotalReadPosition(void)
+ */
+long long RingBuffer::GetTotalReadPosition(void)
+{
+   if (dvdPriv)
+       return dvdPriv->GetTotalReadPosition();
+   return 0;
+}
+
+
Index: DVDRingBuffer.cpp
===================================================================
--- DVDRingBuffer.cpp	(revision 8040)
+++ DVDRingBuffer.cpp	(working copy)
@@ -326,20 +327,34 @@
     return tot;
 }
 
-void DVDRingBufferPriv::nextTrack(void)
+bool DVDRingBufferPriv::nextTrack(void)
 {
     int newPart = part + 1;
-    if (newPart < maxPart)
+    if (newPart < maxPart) 
+   {
         dvdnav_part_play(dvdnav, title, newPart);
+        return true;
+   }
+   return false;
 }
 
 void DVDRingBufferPriv::prevTrack(void)
 {
     int newPart = part - 1;
-    if (newPart < 0)
-        newPart = 0;
+    if (newPart > 0)
+        dvdnav_part_play(dvdnav, title, newPart);
+    else
+        Seek(0,SEEK_SET); // May cause picture to become jumpy.
+}
 
-    dvdnav_part_play(dvdnav, title, newPart);
+uint DVDRingBufferPriv::GetTotalTimeOfTitle(void)
+{
+    return pgcLength/90000; // 90000 ticks = 1 second
 }
 
+uint DVDRingBufferPriv::GetCellStart(void)
+{
+    return cellStart/90000;
+}
+
 #endif // HAVE_DVDNAV
Index: DVDRingBuffer.h
===================================================================
--- DVDRingBuffer.h	(revision 8040)
+++ DVDRingBuffer.h	(working copy)
@@ -2,7 +2,7 @@
 #ifndef DVD_RING_BUFFER_H_
 #define DVD_RING_BUFFER_H_
 
-#define DVD_BLOCK_SIZE 2048
+#define DVD_BLOCK_SIZE 2048LL
 #define DVD_MENU_MAX 7
 
 #include <qstring.h>
@@ -58,11 +59,13 @@
     void GetDescForPos(QString &desc) const;
     void GetPartAndTitle(int &_part, int &_title) const
         { _part  = part; _title = _title; }
+    uint GetTotalTimeOfTitle(void);
+    uint GetCellStart(void);
 
     // commands
     bool OpenFile(const QString &filename);
     void close(void);
-    void nextTrack(void);
+    bool nextTrack(void);
     void prevTrack(void);
     int  safe_read(void *data, unsigned sz);
     long long Seek(long long pos, int whence);
Index: tv_play.cpp
===================================================================
--- tv_play.cpp	(revision 8040)
+++ tv_play.cpp	(working copy)
@@ -2027,7 +2027,7 @@
         {
             if (prbuffer->isDVD())
             {
-                prbuffer->prevTrack();
+                nvp->ChangeDVDTrack(0);
                 UpdateOSDSeekMessage(tr("Previous Chapter"),
                                      osd_general_timeout);
             }
@@ -2040,7 +2040,7 @@
         {
             if (prbuffer->isDVD())
             {
-                prbuffer->nextTrack();
+                nvp->ChangeDVDTrack(1);
                 UpdateOSDSeekMessage(tr("Next Chapter"), osd_general_timeout);
             }
             else
@@ -2320,7 +2320,7 @@
             {
                 if (prbuffer->isDVD())
                 {
-                    prbuffer->prevTrack();
+                    nvp->ChangeDVDTrack(0);
                     UpdateOSDSeekMessage(tr("Previous Chapter"),
                                          osd_general_timeout);
                 }
@@ -2333,7 +2333,7 @@
             {
                 if (prbuffer->isDVD())
                 {
-                    prbuffer->nextTrack();
+                    nvp->ChangeDVDTrack(1);
                     UpdateOSDSeekMessage(tr("Next Chapter"),
                                          osd_general_timeout);
                 }
@@ -2554,25 +2554,13 @@
         return;
 
     oset = GetOSD()->GetSet("status");
-    if ((oset) && (oset->Displaying()) && !prbuffer->isDVD())
-    {
-        InfoMap infoMap;
-        pbinfoLock.lock();
-        playbackinfo->ToMap(infoMap);
-        pbinfoLock.unlock();
-        GetOSD()->HideSet("status");
-        GetOSD()->ClearAllText("program_info");
-        GetOSD()->SetText("program_info", infoMap, osd_prog_info_timeout);
-    }
-    else
-    {
-        QString desc = "";
-        int pos = nvp->calcSliderPos(desc);
-        GetOSD()->HideSet("program_info");
-        GetOSD()->StartPause(pos, false, tr("Position"), desc,
-                             osd_prog_info_timeout);
-        update_osd_pos = true;
-    }
+    QString desc = "";
+    int pos = nvp->calcSliderPos(desc);
+    GetOSD()->HideSet("program_info");
+    GetOSD()->StartPause(pos, false, tr("Position"), desc,
+                         osd_prog_info_timeout);
+    update_osd_pos = true;
+
 }
 
 bool TV::DoNVPSeek(float time)
@@ -3330,6 +3318,9 @@
     if (activenvp != nvp)
         return;
 
+    if (prbuffer->isDVD())
+       usleep(100000);
+
     QString desc = "";
     int pos = nvp->calcSliderPos(desc);
     bool slidertype = StateIsLiveTV(GetState());
