r2412 - in vdr/vdr-plugin-dvd/trunk/debian: . patches

Thomas Günther tom-guest at costa.debian.org
Fri Apr 14 19:23:21 UTC 2006


Author: tom-guest
Date: 2006-04-14 19:23:17 +0000 (Fri, 14 Apr 2006)
New Revision: 2412

Added:
   vdr/vdr-plugin-dvd/trunk/debian/patches/04_vdr-dvd_resume.dpatch
Modified:
   vdr/vdr-plugin-dvd/trunk/debian/changelog
   vdr/vdr-plugin-dvd/trunk/debian/patches/00list
Log:
Added 04_vdr-dvd_resume.dpatch

Modified: vdr/vdr-plugin-dvd/trunk/debian/changelog
===================================================================
--- vdr/vdr-plugin-dvd/trunk/debian/changelog	2006-04-13 20:15:29 UTC (rev 2411)
+++ vdr/vdr-plugin-dvd/trunk/debian/changelog	2006-04-14 19:23:17 UTC (rev 2412)
@@ -1,3 +1,10 @@
+vdr-plugin-dvd (0.3.5.2+0.3.6b03-18) unstable; urgency=low
+
+  * Thomas Günther <tom at toms-cafe.de>
+    - Added 04_vdr-dvd_resume.dpatch
+
+ -- Debian VDR Team <pkg-vdr-dvb-devel at lists.alioth.debian.org>  Fri, 14 Apr 2006 21:19:52 +0200
+
 vdr-plugin-dvd (0.3.5.2+0.3.6b03-17) unstable; urgency=low
 
   * Thomas Schmidt <tschmidt at debian.org>

Modified: vdr/vdr-plugin-dvd/trunk/debian/patches/00list
===================================================================
--- vdr/vdr-plugin-dvd/trunk/debian/patches/00list	2006-04-13 20:15:29 UTC (rev 2411)
+++ vdr/vdr-plugin-dvd/trunk/debian/patches/00list	2006-04-14 19:23:17 UTC (rev 2412)
@@ -1,4 +1,5 @@
 01_Makefile-fPIC-fix
 02_ignore_not_existing_drive
 03_vdr-1.3.38-fix
+04_vdr-dvd_resume
 10_dvd.c

Added: vdr/vdr-plugin-dvd/trunk/debian/patches/04_vdr-dvd_resume.dpatch
===================================================================
--- vdr/vdr-plugin-dvd/trunk/debian/patches/04_vdr-dvd_resume.dpatch	2006-04-13 20:15:29 UTC (rev 2411)
+++ vdr/vdr-plugin-dvd/trunk/debian/patches/04_vdr-dvd_resume.dpatch	2006-04-14 19:23:17 UTC (rev 2412)
@@ -0,0 +1,532 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 04_vdr-dvd_resume.dpatch by Patrick Cernko <errror at errror.org>
+## http://www.vdrportal.de/board/thread.php?threadid=31685
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: Patch to resume a dvd where it was interupted by the user.
+
+ at DPATCH@
+diff -Naur --exclude CVS dvd.orig/Makefile dvd/Makefile
+--- dvd.orig/Makefile	2005-03-19 15:35:05.000000000 +0100
++++ dvd/Makefile	2005-03-18 17:53:03.000000000 +0100
+@@ -65,6 +65,10 @@
+ LDFLAGS  += -O3 -Wl,--retain-symbols-file,retain-sym
+ endif
+
++ifdef RESUMEDIR
++  DEFINES += -DRESUMEDIR=\"$(RESUMEDIR)\"
++endif
++
+ ### The object files (add further files here):
+
+ OBJS = $(PLUGIN).o dvddev.o player-dvd.o control-dvd.o dvdspu.o     \
+diff -Naur --exclude CVS dvd.orig/player-dvd.c dvd/player-dvd.c
+--- dvd.orig/player-dvd.c	2005-03-19 15:35:05.000000000 +0100
++++ dvd/player-dvd.c	2005-03-19 15:32:27.000000000 +0100
+@@ -21,6 +21,8 @@
+ #include <vdr/thread.h>
+ #include <vdr/device.h>
+ #include <vdr/plugin.h>
++// for VideoDirectory variable
++#include <vdr/videodir.h>
+
+ #ifdef HAVE_CONFIG_H
+ #include "config.h"
+@@ -231,6 +233,216 @@
+ }
+
+
++// --- cResumeEntry ------------------------------------------------------------
++
++// borrowed from the mplayer plugin code and adapted to the dvd resume requirements
++class cResumeEntry : public cListObject {
++public:
++  char *key;
++  int title;
++  int chapter;
++  int64_t second;
++  //
++  cResumeEntry(void);
++  ~cResumeEntry();
++  };
++
++cResumeEntry::cResumeEntry(void)
++{
++  key=0;
++}
++
++cResumeEntry::~cResumeEntry()
++{
++  free(key);
++}
++
++// --- cDVDPlayerResume ----------------------------------------------------------
++
++// store resume database to this file ...
++#define RESUME_FILE "dvdplayer.resume"
++
++// ... in this directory (default: /video)
++#ifndef RESUMEDIR
++#define RESUMEDIR VideoDirectory
++#endif
++
++
++// borrowed from the mplayer plugin code and adapted to the dvd resume requirements
++class cDVDPlayerResume : public cList<cResumeEntry> {
++private:
++  char* resfile; // the full pathname of resume file
++  bool modified; // flag to indicate that memory database was modified and needs to be saved
++  /**
++   * LoadResume():
++   * reads in the resume database file from resfile.
++   */
++  void LoadResume();
++  /**
++   * SaveResume():
++   * saves the resume database to the file resfile.
++   * returns true on successful save.
++   */
++  bool SaveResume(void);
++  /**
++   * search the (loaded) resume database for the given key.
++   * returns the cResumeEntry* if the key was found
++   * or NULL if no resume entry was found for the given key.
++   */
++  cResumeEntry *FindResume(const char* key);
++public:
++  cDVDPlayerResume(void);
++  ~cDVDPlayerResume();
++  /**
++   * SetResume():
++   * set the given resume values for the given key into the resume database.
++   * the resume database is loaded from file if not yet loaded.
++   */
++  void SetResume(const char* key, int title, int chapter, int64_t second);
++  /**
++   * GetResume():
++   * tries looking up the given key into the resume database.
++   * the resume database is loaded from file if not yet loaded.
++   * returns true if resume data could be found. In this case
++   * the givven arguments are filled with the resume data. Otherwise
++   * the arguments are not modified!
++   */
++  bool GetResume(const char* key, int& title, int& chapter, int64_t& second);
++  };
++
++cDVDPlayerResume::cDVDPlayerResume(void)
++{
++  // initialize the resume filename string.
++  asprintf(&resfile, "%s/%s", RESUMEDIR, RESUME_FILE);
++}
++
++cDVDPlayerResume::~cDVDPlayerResume()
++{
++  // save resume data to disc before self-destruction.
++  SaveResume();
++  // free the resume filename string, allocated in C'tor by asprintf
++  free(resfile);
++}
++
++void cDVDPlayerResume::SetResume(const char* key, int title, int chapter, int64_t second)
++{
++  // (re)load resume data from file to be actual
++  LoadResume();
++  cResumeEntry* re = FindResume(key);
++  if (re) {
++    // found a resume entry, so we can update it.
++    DEBUGDVD("resume: setting resume %d:%d:%lld (update)", title, chapter, second);
++  } else {
++    // no resume entry found yet, creating a new one
++    re = new cResumeEntry;
++    re->key = strdup(key);
++    Add(re);
++    DEBUGDVD("resume: setting resume %d:%d:%lld (new)", title, chapter, second);
++  }
++  // set the new resume data for the found/created entry
++  re->title = title;
++  re->chapter = chapter;
++  re->second = second;
++  // and mark memory database as modified to be saved.
++  modified = true;
++  // save it now (sync!)
++  SaveResume();
++}
++
++bool cDVDPlayerResume::GetResume(const char* key, int& title, int& chapter, int64_t& second)
++{
++  // (re)load the resume file to have actual values
++  LoadResume();
++  cResumeEntry* re = FindResume(key);
++  if (re) {
++    // found a resume entry, copy values
++    title = re->title;
++    chapter = re->chapter;
++    second = re->second;
++    // indicate successful search
++    return true;
++  }
++  // no resume entry found in database
++  return false;
++}
++
++void cDVDPlayerResume::LoadResume()
++{
++  // we will load the file for sure and add all entries, clear all old entries.
++  Clear();
++  // no entries == no modifications
++  modified = false;
++  DEBUGDVD("resume: resume file is \"%s\"\n",resfile);
++  FILE *f = fopen(resfile,"r");
++  if (f) {
++    DEBUGDVD("resume: successfully opened resume file\n");
++    char line[768];
++    // read file line by line
++    while(fgets(line,sizeof(line),f)) {
++      char key[512];
++      int t, c;
++      int64_t s;
++      // parse line as "title:chapter:second:key"
++      if(sscanf(line,"%d:%d:%lld:%511[^\n]",&t,&c,&s,key) == 4) {
++        // successful parse, save in resume entry
++        cResumeEntry *re = new cResumeEntry;
++        re->key = strdup(key);
++        re->title = t;
++        re->chapter = c;
++        re->second = s;
++        // and add it to memory database
++        Add(re);
++      }
++    }
++    // don't forget to close what you have opened!
++    fclose(f);
++  }
++  // unsuccessful open leads to empty database as the file does not exists
++}
++
++bool cDVDPlayerResume::SaveResume(void)
++{
++  if(modified) {
++    // modification indicated, save the database to the resume file
++    DEBUGDVD("resume: saving resume file\n");
++    cSafeFile f(resfile);
++    if(f.Open()) {
++      // forall resume entries in the memory database
++      for (cResumeEntry *re=First(); re; re=Next(re)) {
++        // save the as one line in the format "title:chapter:second:key"
++        fprintf(f, "%d:%d:%lld:%s\n", re->title, re->chapter, re->second, re->key);
++      }
++      // don't forget to close what you have opened!
++      f.Close();
++      // signal successful save
++      return true;
++    } else {
++      DEBUGDVD("resume: failed to save resume file\n");
++      // saving did not succeed!!!!
++      return false;
++    }
++  } else {
++    // no modifications -> successful "save" :-)
++    return true;
++  }
++}
++
++cResumeEntry *cDVDPlayerResume::FindResume(const char* key)
++{
++  DEBUGDVD("resume: searching resume  position for \"%s\"\n", key);
++  // iterate over all entries in the memory database
++  for(cResumeEntry *re=First(); re; re=Next(re)) {
++    if (!strcasecmp(re->key, key)) {
++      // return the entry iff the keys match
++      DEBUGDVD("resume: found resume position %d:%d:%lld\n",re->title, re->chapter, re->second);
++      return re;
++    }
++  }
++  DEBUGDVD("resume: no resume position found\n");
++  return NULL;
++}
++
++
+ // --- cDvdPlayer ------------------------------------------------------------
+
+ //XXX+ also used in recorder.c - find a better place???
+@@ -287,6 +499,9 @@
+     skipPlayVideo=false;
+     fastWindFactor=1;
+
++    // resume
++    resume = new cDVDPlayerResume;
++
+     clearSeenSubpStream();
+     clearSeenAudioTrack();
+
+@@ -329,6 +544,7 @@
+     if(titleinfo_str) { free(titleinfo_str); titleinfo_str=0; }
+     if(title_str) { free(title_str); title_str=0; }
+     if(aspect_str) { free(aspect_str); aspect_str=0; }
++    delete resume;
+ }
+
+ void cDvdPlayer::setController (cDvdPlayerControl *ctrl )
+@@ -562,6 +778,100 @@
+ #endif
+ }
+
++char* cDvdPlayer::GetDVDResumeKey() const {
++  // first we fetch the total number of titles of the current dvd
++  int totalTitles;
++  if (dvdnav_get_number_of_titles(nav, &totalTitles)) {
++    // then we sum up the numbers of chapters for each title
++    int totalChapters = 0;
++    for (int t = 1; t <= totalTitles; t++) {
++      int curChapters;
++      dvdnav_get_number_of_parts(nav, t, &curChapters);
++      totalChapters += curChapters;
++      DEBUGDVD("resume: cDvdPlayer::Action() Title %d has %d chapters.\n", t, curChapters);
++    }
++    DEBUGDVD("resume: cDvdPlayer::Action() Titles: %d with %d chapters all together, Title: \"%s\"\n",
++             totalTitles, totalChapters, title_str);
++    // finally the key is build as "DVDName_TotalTitles_OverallChapters"
++    char* key;
++    asprintf(&key, "%s_%d_%d", title_str, totalTitles, totalChapters);
++    // note: this is not completly unique. Maybe some other informations are more suitable, like:
++    // - the "serial number" of the dvd as displayed in the libdvdnav debug output, but:
++    //   it is not available through the current libdvdnav api
++    // - the total bytes of the dvd (quiet unique!!!), but:
++    //   also not available through the libdvdnav api and no idea how to get it for a media not mounted.
++    // - any other ideas???
++    return key;
++  } else {
++    // if we cannot fetch the total number of titles of the current disc, there must be something wrong!
++    // Who needs a key for resuming then?
++    return NULL;
++  }
++}
++
++void cDvdPlayer::SaveResume() {
++  // make sure resume database is allocated (might be a possibility to completly disable resuming!)
++  if (resume) {
++    // fetch the current title and chapter number via libdvdnav api
++    int currentTitle, currentChapter;
++    if (dvdnav_current_title_info(nav, &currentTitle, &currentChapter) &&
++        (0 != currentTitle)) {
++      // fetch current time position through own class api
++      int64_t currentSec, totalSec;
++      GetPositionInSec(currentSec, totalSec);
++      // compute the resume key for the current dvd
++      char* key = GetDVDResumeKey();
++      if (key) {
++        // store computed/fetched resume data in database
++        DEBUGDVD("resume->SetResume(\"%s\", %d, %d, %lld)\n", key, currentTitle, currentChapter, currentSec);
++        resume->SetResume(key, currentTitle, currentChapter, currentSec);
++        // free the key string memory allocated by GetDVDResumeKey()
++        free(key);
++      } else {
++        DEBUGDVD("resume: ERROR computing resume key for this dvd!\n");
++      }
++    } else {
++      // in a menu title and chapter seams to be always 0 -> no way to resume there!
++      DEBUGDVD("resume: ERROR fetching current title and chapter (maybe in menus?).\n");
++    }
++  }
++}
++
++bool cDvdPlayer::LoadResume(int& title, int& chapter, int64_t& second) {
++  // helper variable for the return value
++  bool retval = false;
++  // make sure resume database is allocated (might be a possibility to completly disable resuming!)
++  if(resume) {
++    // compute the resume key for the current dvd
++    char* key = GetDVDResumeKey();
++    if (key) {
++      DEBUGDVD("resume->GetResume(\"%s\", ...): ", key);
++      // try loading the resume data for the computed key into the given arguments
++      if (resume->GetResume(key, title, chapter, second)) {
++        DEBUGDVD("%d:%d:%lld\n", title, chapter, second);
++        // continuing at the very same position might be inappropriate (vdr's recordings also rewind some seconds)
++        int ResumeRewind = 30; // rewind 30s if possible
++        // note: I used a variable here to show up, that this value might be made
++        //       possible to configure (in the setup dialog). Doing so myself was
++        //       not yet nesseccary and is so left to the plugin maintainers.
++        // make sure we do not rewind before the beginning
++        if (second > ResumeRewind) {
++          second -= ResumeRewind;
++        }
++        retval = true;
++      } else {
++        DEBUGDVD("<none>\n");
++        retval = false;
++      }
++      // free the key string memory allocated by GetDVDResumeKey()
++      free(key);
++    } else {
++      DEBUGDVD("resume: ERROR computing resume key for this dvd.\n");
++    }
++  }
++  return retval;
++}
++
+ void cDvdPlayer::Action(void) {
+     memset(event_buf, 0, sizeof(uint8_t)*4096);
+
+@@ -631,6 +941,13 @@
+
+     bool firstClear = true;
+
++    // we need to know the very first VTS change to hook inthe resume call
++    bool first_vts_change = true;
++    // we cannot directly resume to the exact time, so we hook on the next cell change when resuming
++    bool next_cell_change = false;
++    // and seek the the exact time stored here
++    int64_t resSecond = 0;
++
+     while( running && nav ) {
+
+         if (!pframe) {
+@@ -1107,6 +1424,22 @@
+ 	      SetTitleInfoString();
+ 	      SetTitleString();
+ 	      SetAspectString();
++              if (first_vts_change) {
++                first_vts_change = false;
++
++                // now all data for computing the resume key is available, so trying to resume
++                int resTitle, resChapter;
++                if (LoadResume(resTitle, resChapter, resSecond)) {
++                  // if resume data could be found seek to the found title and chapter NOW
++                  GotoTitle(resTitle, resChapter);
++                  // and wait for the next cell change (= title and chapter reached)
++                  // to seek to the exact time
++                  next_cell_change = true;
++                  // note: seeking to the exact time HERE leads to an error on the libdvdnav console:
++                  //       "dvd error dvdnav_sector_search: New position not yet determined." and is
++                  //       slightly ignored :-( .
++                }
++              }
+ 	      break;
+ 	  case DVDNAV_CELL_CHANGE: {
+ 	      DEBUG_NAV("%s:%d:NAV CELL CHANGE\n", __FILE__, __LINE__);
+@@ -1127,6 +1460,11 @@
+ 	      // cell change .. game over ..
+ 	      changeNavSubpStreamOnceInSameCell=false;
+     	      SetTitleInfoString();
++              if (next_cell_change) {
++                next_cell_change = false;
++                // we are resuming the current dvd. NOW its time to seek to the correct second.
++                Goto(resSecond);
++              }
+ 	      break;
+ 	  }
+ 	  case DVDNAV_NAV_PACKET: {
+@@ -1853,7 +2191,16 @@
+     if(!DVDActiveAndRunning()) return;
+
+     if( running && nav ) {
+-	    dvdnav_stop(nav);
++      // we will stop replay now. Its time to save the current possition
++      // for later resuming.
++      SaveResume();
++
++      dvdnav_stop(nav);
++
++      // don't know why Stop() is called twice, but this prevents from
++      // twice save resume data and calling dvdnav_stop() twice.
++      // Comments from maintainers are welcome.
++      running = false;
+     }
+ }
+
+@@ -2163,22 +2510,36 @@
+       (void) GotoAngle(++cur_angle);
+ }
+
+-int cDvdPlayer::GotoTitle(int title)
++// GotoTitle now optionally takes a chapter to seek to in the given title.
++int cDvdPlayer::GotoTitle(int title, int chapter /*= 1*/)
+ {
+       int titleNumber;
++      int targetTitle = title;
++      int chapterNumber;
+       if(!DVDActiveAndRunning()) return -1;
+       LOCK_THREAD;
+       DEBUG_NAV("DVD NAV SPU clear & empty %s:%d\n", __FILE__, __LINE__);
+       Empty();
+
++      // check if the given title is in the title range of this dvd
+       dvdnav_get_number_of_titles(nav, &titleNumber);
+-
+-      if(title>titleNumber) title=1;
+-      if(title<=0) title=titleNumber;
++      if(title>titleNumber) targetTitle=1;
++      if(title<=0) targetTitle=titleNumber;
++
++      // if given title is in the bounds of this dvd's title range
++      if (title == targetTitle) {
++        // check if the chapter is in the title's chapter range
++        dvdnav_get_number_of_parts(nav, title, &chapterNumber);
++        if (chapter>chapterNumber) chapter=1;
++        if (chapter<=0) chapter=chapterNumber;
++      } else {
++        // otherwise reset it to the first chapter.
++        chapter = 1;
++      }
+
+       if (stillTimer == 0)
+       {
+-	      dvdnav_part_play(nav, title, 1);
++	      dvdnav_part_play(nav, title, chapter);
+ 	      // dvdnav_title_play(nav, title);
+       }
+
+diff -Naur --exclude CVS dvd.orig/player-dvd.h dvd/player-dvd.h
+--- dvd.orig/player-dvd.h	2005-03-19 15:35:05.000000000 +0100
++++ dvd/player-dvd.h	2005-03-19 15:15:50.000000000 +0100
+@@ -52,6 +52,7 @@
+
+ class cDvdPlayerControl ;
+ class cIframeAssembler;
++class cDVDPlayerResume;
+
+ class cDvdPlayer : public cPlayer, cThread {
+  private:
+@@ -183,6 +184,31 @@
+     int  playPacket(unsigned char *&cache_buf, bool trickMode, bool noAudio);
+     void playSPU(int spuId, unsigned char *data, int datalen);
+
++    //resuming
++    /**
++     * the resume database
++     */
++    cDVDPlayerResume* resume;
++    /**
++     * GetDVDResumeKey():
++     * computes a (hopefully) unique id for storing the resume data of the current disc.
++     *
++     * this get returns a new allocated memory area ..
++     * must be freed by callee ..
++     */
++    char* GetDVDResumeKey() const;
++    /**
++     * SaveResume():
++     * handles everything to save the current position on the disc for later resuming.
++     */
++    void SaveResume();
++    /**
++     * LoadResume():
++     * loads the resume data for the current disc and stores it in the given arguments.
++     * returns false if no resume data for the disc can be found or and error occured while loading.
++     */
++    bool LoadResume(int& title, int& chapter, int64_t& second);
++
+ protected: //Player
+     virtual void Activate(bool On);
+     virtual void Action(void);
+@@ -313,7 +339,8 @@
+      *
+      * return set title ..
+      */
+-    int GotoTitle(int title);
++    // GotoTitle now optionally takes a chapter to seek to in the given title.
++    int GotoTitle(int title, int chapter = 1);
+
+     /**
+      * jump to the previous Title (rotate)




More information about the pkg-vdr-dvb-changes mailing list