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, ¤tTitle, ¤tChapter) &&
++ (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