summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Günther <tom@toms-cafe.de>2009-07-17 00:58:49 +0200
committerThomas Günther <tom@toms-cafe.de>2009-07-17 01:17:52 +0200
commit56ecb9dadf63f61d227c6b8acd05dcc1da17365f (patch)
treef1ff697bceb66877e08c18b55c897f875cc3e320
parent97c5f35c27dc65f3bc2ee9fe338f7341d65f1446 (diff)
downloadvdr-plugin-text2skin-56ecb9dadf63f61d227c6b8acd05dcc1da17365f.tar.gz
vdr-plugin-text2skin-56ecb9dadf63f61d227c6b8acd05dcc1da17365f.tar.bz2
Adapted to new recording format and variable frame rate (VDR >= 1.7.3)
-rw-r--r--HISTORY2
-rw-r--r--common.c78
-rw-r--r--common.h10
-rw-r--r--display.c42
-rw-r--r--render.c2
-rw-r--r--status.c10
-rw-r--r--status.h3
7 files changed, 78 insertions, 69 deletions
diff --git a/HISTORY b/HISTORY
index 4cb1c61..ae8feca 100644
--- a/HISTORY
+++ b/HISTORY
@@ -93,6 +93,8 @@ ____-__-__: Version 1.3
- Compile internal image quantizing code only in Imlib2 builds.
- Add support for building with GraphicsMagick.
- Draw replay progress bar symmetrically
+- Adapted to new recording format and variable frame rate (VDR >= 1.7.3 -
+ closes #150)
2009-06-01: Version 1.2
diff --git a/common.c b/common.c
index c676fdb..374a82f 100644
--- a/common.c
+++ b/common.c
@@ -223,55 +223,29 @@ int GetRecordingSize(const char *FileName)
return (rec) ? DirSizeMB(FileName) : 0;
}
-int GetRecordingLength(const char *FileName)
+int GetRecordingLength(const char *FileName, double FramesPerSecond, bool IsPesRecording)
{
- // based on the enAIO-Patch for VDR
- #define INDEXFILESUFFIX "/index.vdr"
-
+#define INDEXFILESUFFIX "/index"
struct tIndex { int offset; uchar type; uchar number; short reserved; };
- tIndex *index;
- char RecLength[21];
- char *filename = NULL;
- int last = -1;
- index = NULL;
- if (FileName) {
- filename = MALLOC(char, strlen(FileName) + strlen(INDEXFILESUFFIX) + 1);
- if (filename) {
- strcpy(filename, FileName);
- char *pFileExt = filename + strlen(filename);
- strcpy(pFileExt, INDEXFILESUFFIX);
- int delta = 0;
- if (access(filename, R_OK) == 0) {
- struct stat buf;
- if (stat(filename, &buf) == 0) {
- delta = buf.st_size % sizeof(tIndex);
- if (delta) {
- delta = sizeof(tIndex) - delta;
- esyslog("ERROR: invalid file size (%ld) in '%s'", (long)buf.st_size, filename);
- }
- last = (buf.st_size + delta) / sizeof(tIndex) - 1;
- char hour[2], min[3];
- snprintf(RecLength, sizeof(RecLength), "%s", *IndexToHMSF(last, true));
- snprintf(hour, sizeof(hour), "%c", RecLength[0]);
- snprintf(min, sizeof(min), "%c%c", RecLength[2], RecLength[3]);
- return (atoi(hour) * 60) + atoi(min);
- }
- }
- free(filename);
- }
- }
-
+ struct stat buf;
+ cString fullname = cString::sprintf("%s%s", FileName, IsPesRecording ? INDEXFILESUFFIX ".vdr" : INDEXFILESUFFIX);
+ if (FileName && *fullname && access(fullname, R_OK) == 0 && stat(fullname, &buf) == 0)
+ return buf.st_size ? ((buf.st_size - 1) / sizeof(tIndex) + 1) / (60 * FramesPerSecond) : 0;
return 0;
}
-int GetRecordingCuttedLength(const char *FileName)
+int GetRecordingCuttedLength(const char *FileName, double FramesPerSecond, bool IsPesRecording)
{
cMarks marks;
double length = 0;
- int totalLength = GetRecordingLength(FileName);
- const double diffIFrame = FRAMESPERSEC / 2; // approx. 1/2 sec.
+ int totalLength = GetRecordingLength(FileName, FramesPerSecond, IsPesRecording);
+ const double diffIFrame = FramesPerSecond / 2; // approx. 1/2 sec.
+#if VDRVERSNUM >= 10703
+ marks.Load(FileName, FramesPerSecond, IsPesRecording);
+#else
marks.Load(FileName);
+#endif
if (marks.Count()) {
int start = 1; // first frame
@@ -281,14 +255,14 @@ int GetRecordingCuttedLength(const char *FileName)
if (isStart)
start = m->position;
else
- length += (double)(m->position - start + 1 + diffIFrame) / (FRAMESPERSEC * 60); // [min]
+ length += (double)(m->position - start + 1 + diffIFrame) / (60 * FramesPerSecond); // [min]
isStart = !isStart;
}
// if there is no end-mark the last segment goes to the end of the rec.
if (!isStart)
- length += totalLength - (double)(start - 1 - diffIFrame) / (FRAMESPERSEC * 60); // [min]
+ length += totalLength - (double)(start - 1 - diffIFrame) / (60 * FramesPerSecond); // [min]
}
// just to avoid, that the cutted length is bigger than the total length
@@ -321,18 +295,27 @@ cxType TimeType(time_t Time, const std::string &Format)
return false;
}
-cxType DurationType(uint Index, const std::string &Format)
+cxType DurationType(uint Index, double FramesPerSecond, const std::string &Format)
+{
+ if (FramesPerSecond && Format.length() > 0) {
+ double Seconds = (Index + 0.5) / FramesPerSecond;
+ int Frame = int((Seconds - int(Seconds)) * FramesPerSecond) + 1;
+ return DurationType(int(Seconds), Format, Frame);
+ }
+ return int(Index);
+}
+
+cxType DurationType(int Seconds, const std::string &Format, int Frame)
{
static char result[1000];
- if (Index > 0) {
+ if (Seconds >= 0) {
if (Format.length() > 0) {
uint update = 0;
const char *ptr = Format.c_str();
char *res = result;
enum { normal, format } state = normal;
int n = 0;
- int f = (Index % FRAMESPERSEC) + 1;
- int s = (Index / FRAMESPERSEC);
+ int s = Seconds;
int m = s / 60 % 60;
int h = s / 3600;
s %= 60;
@@ -371,7 +354,8 @@ cxType DurationType(uint Index, const std::string &Format)
break;
case 'f':
- n = snprintf(res, sizeof(result) - (res - result), "%d", f);
+ if (Frame)
+ n = snprintf(res, sizeof(result) - (res - result), "%02d", Frame);
update = 1000;
break;
@@ -391,7 +375,7 @@ cxType DurationType(uint Index, const std::string &Format)
r.SetUpdate(update);
return r;
} else
- return (int)Index;
+ return Seconds;
}
return false;
}
diff --git a/common.h b/common.h
index c5f0645..8cb0acd 100644
--- a/common.h
+++ b/common.h
@@ -11,9 +11,6 @@
#include <vdr/config.h>
#include <vdr/epg.h>
-// from recording.h (VDR <= 1.7.2)
-#define FRAMESPERSEC 25
-
#if defined(DEBUG) || defined(BENCH)
# ifdef DEBUG
# define Dprintf(x...) fprintf(stderr, x)
@@ -58,11 +55,12 @@ bool GetFrontendHasLock(void);
bool GetFrontendHasSignal(void);
std::string AddExtInfoToDescription(const char *Title, const char *ShortText, const char *Description, const char *Aux = NULL, bool StripAux = false);
int GetRecordingSize(const char *FileName); // [MB]
-int GetRecordingLength(const char *FileName); // [min]
-int GetRecordingCuttedLength(const char *FileName); // [min]
+int GetRecordingLength(const char *FileName, double FramesPerSecond, bool IsPesRecording); // [min]
+int GetRecordingCuttedLength(const char *FileName, double FramesPerSecond, bool IsPesRecording); // [min]
cxType TimeType(time_t Time, const std::string &Format);
-cxType DurationType(uint Index, const std::string &Format);
+cxType DurationType(uint Index, double FramesPerSecond, const std::string &Format);
+cxType DurationType(int Seconds, const std::string &Format, int Frame = 0);
bool ParseVar(const char *Text, const char *Name, std::string &Value);
bool ParseVar(const char *Text, const char *Name, tColor *Value);
diff --git a/display.c b/display.c
index 15d0de3..c8fa7d3 100644
--- a/display.c
+++ b/display.c
@@ -165,20 +165,20 @@ cxType cText2SkinDisplayChannel::GetTokenData(const txToken &Token)
case tPresentProgress:
return mPresent != NULL
- ? (cxType)DurationType((time(NULL) - mPresent->StartTime()) * FRAMESPERSEC,
+ ? (cxType)DurationType(time(NULL) - mPresent->StartTime(),
Token.Attrib.Text)
: (cxType)false;
case tPresentDuration:
return mPresent != NULL
- ? (cxType)DurationType(mPresent->Duration() * FRAMESPERSEC, Token.Attrib.Text)
+ ? (cxType)DurationType(mPresent->Duration(), Token.Attrib.Text)
: (cxType)false;
case tPresentRemaining:
if (mPresent != NULL && time(NULL) - mPresent->StartTime()
<= mPresent->Duration()) {
- return (cxType)DurationType((mPresent->Duration() - (time(NULL) - mPresent->StartTime()))
- * FRAMESPERSEC, Token.Attrib.Text);
+ return (cxType)DurationType(mPresent->Duration() - (time(NULL) - mPresent->StartTime()),
+ Token.Attrib.Text);
}
return false;
@@ -214,7 +214,7 @@ cxType cText2SkinDisplayChannel::GetTokenData(const txToken &Token)
case tFollowingDuration:
return mFollowing != NULL
- ? (cxType)DurationType(mFollowing->Duration() * FRAMESPERSEC, Token.Attrib.Text)
+ ? (cxType)DurationType(mFollowing->Duration(), Token.Attrib.Text)
: (cxType)false;
case tFollowingTitle:
@@ -511,10 +511,14 @@ cxType cText2SkinDisplayReplay::GetTokenData(const txToken &Token)
return mTitle;
case tReplayPositionIndex:
- return DurationType(mCurrent, Token.Attrib.Text);
+ return DurationType(mCurrent,
+ Text2SkinStatus.ReplayFramesPerSecond(),
+ Token.Attrib.Text);
case tReplayDurationIndex:
- return DurationType(mTotal, Token.Attrib.Text);
+ return DurationType(mTotal,
+ Text2SkinStatus.ReplayFramesPerSecond(),
+ Token.Attrib.Text);
case tReplayPosition:
return mPosition;
@@ -523,7 +527,9 @@ cxType cText2SkinDisplayReplay::GetTokenData(const txToken &Token)
return mDuration;
case tReplayRemaining:
- return DurationType(mTotal - mCurrent, Token.Attrib.Text);
+ return DurationType(mTotal - mCurrent,
+ Text2SkinStatus.ReplayFramesPerSecond(),
+ Token.Attrib.Text);
case tReplayPrompt:
return mPrompt;
@@ -1060,19 +1066,19 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token)
case tPresentProgress:
return mEvent != NULL
- ? (cxType)DurationType((time(NULL) - mEvent->StartTime()) * FRAMESPERSEC,
+ ? (cxType)DurationType(time(NULL) - mEvent->StartTime(),
Token.Attrib.Text)
: (cxType)false;
case tPresentDuration:
return mEvent != NULL
- ? (cxType)DurationType(mEvent->Duration() * FRAMESPERSEC, Token.Attrib.Text)
+ ? (cxType)DurationType(mEvent->Duration(), Token.Attrib.Text)
: (cxType)false;
case tPresentRemaining:
return mEvent != NULL
- ? (cxType)DurationType((mEvent->Duration() - (time(NULL) - mEvent->StartTime()))
- * FRAMESPERSEC, Token.Attrib.Text)
+ ? (cxType)DurationType(mEvent->Duration() - (time(NULL) - mEvent->StartTime()),
+ Token.Attrib.Text)
: (cxType)false;
case tPresentTitle:
@@ -1330,12 +1336,20 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token)
case tRecordingLength:
return mRecording != NULL
- ? (cxType)GetRecordingLength(mRecording->FileName())
+#if VDRVERSNUM >= 10703
+ ? (cxType)GetRecordingLength(mRecording->FileName(), mRecording->FramesPerSecond(), mRecording->IsPesRecording())
+#else
+ ? (cxType)GetRecordingLength(mRecording->FileName(), FRAMESPERSEC, true)
+#endif
: (cxType)false;
case tRecordingCuttedLength:
return mRecording != NULL
- ? (cxType)GetRecordingCuttedLength(mRecording->FileName())
+#if VDRVERSNUM >= 10703
+ ? (cxType)GetRecordingCuttedLength(mRecording->FileName(), mRecording->FramesPerSecond(), mRecording->IsPesRecording())
+#else
+ ? (cxType)GetRecordingCuttedLength(mRecording->FileName(), FRAMESPERSEC, true)
+#endif
: (cxType)false;
default:
diff --git a/render.c b/render.c
index 1b7cf9c..6efd473 100644
--- a/render.c
+++ b/render.c
@@ -817,7 +817,7 @@ cxType cText2SkinRender::GetTokenData(const txToken &Token)
VideoDiskSpace(&FreeMB);
Dprintf("FreeMB: %d, attrib type is %d\n", FreeMB,Token.Attrib.Type);
return Token.Attrib.Type == aString && Token.Attrib.Text.length() > 0
- ? (cxType)DurationType((int)(FreeMB * 60 * FRAMESPERSEC / MB_PER_MINUTE),
+ ? (cxType)DurationType(FreeMB * 60 / MB_PER_MINUTE,
Token.Attrib.Text)
: (cxType)FreeMB;
}
diff --git a/status.c b/status.c
index 25dae2d..442eb30 100644
--- a/status.c
+++ b/status.c
@@ -22,7 +22,8 @@ cText2SkinStatus::cText2SkinStatus(void):
mRecordings(),
mCurrentRecording(0),
mNextRecording(0),
- mLastLanguage(0)
+ mLastLanguage(0),
+ mReplayFramesPerSecond(0)
{
}
@@ -84,6 +85,13 @@ void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name,
mReplayIsShuffle = false;
}
+#if VDRVERSNUM >= 10703
+ // Workaround: Control->FramesPerSecond() not possible because its not const
+ mReplayFramesPerSecond = mReplay != NULL ? mReplay->FramesPerSecond() : DEFAULTFRAMESPERSECOND;
+#else
+ mReplayFramesPerSecond = FRAMESPERSEC;
+#endif
+
if (mRender != NULL) {
if (mReplayMode != oldMode)
mRender->SetDirty();
diff --git a/status.h b/status.h
index 515214c..f759645 100644
--- a/status.h
+++ b/status.h
@@ -71,6 +71,7 @@ private:
uint mNextRecording;
int mLastLanguage;
int mTimerConflicts;
+ double mReplayFramesPerSecond;
protected:
virtual void Replaying(const cControl *Control, const char *Name,
@@ -91,6 +92,8 @@ public:
cxType GetTokenData(const txToken &Token);
eReplayMode ReplayMode(void) const { return mReplayMode; }
+
+ double ReplayFramesPerSecond(void) const { return mReplayFramesPerSecond; }
};
extern cText2SkinStatus Text2SkinStatus;