summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--HISTORY55
-rw-r--r--common.c150
-rw-r--r--common.h4
-rw-r--r--display.c201
-rw-r--r--i18n.c131
-rw-r--r--menu.c10
-rw-r--r--render.c28
-rw-r--r--render.h12
-rw-r--r--setup.c9
-rw-r--r--setup.h3
-rw-r--r--status.c287
-rw-r--r--status.h34
-rw-r--r--text2skin.c14
-rw-r--r--text2skin.h3
-rw-r--r--xml/object.c12
-rw-r--r--xml/object.h1
-rw-r--r--xml/string.c7
-rw-r--r--xml/string.h37
18 files changed, 967 insertions, 31 deletions
diff --git a/HISTORY b/HISTORY
index 75b7448..16d54d9 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,6 +1,61 @@
VDR Plugin 'text2skin' Revision History
---------------------------------------
+2006-01-10: Version 1.1-cvs_ext-0.6 (vdr-text2skin-1.1-cvs_ext-0.6.diff)
+
+- updated to cvs-version of text2skin
+- since vdr-1.3.38 it is possible to exactly identify the replayed
+ recording, so the replay-tokens work now
+- switched the search-order for the fonts to priorise the skin-folder
+ (this avoids error-messages in the log)
+
+2006-01-07: Version 1.1-cvs_ext-0.5 (vdr-text2skin-1.1-cvs_ext-0.5.diff)
+
+- modifications to compile with vdr-versions >= 1.3.18
+- added tokens:
+ OsdWidth, OsdHeight
+- activating the token ReplayVideoAR
+
+2005-12-18: Version 1.1-cvs_ext-0.4 (vdr-text2skin-1.1-cvs_ext-0.4.diff)
+
+- modified the way, the current replayed recording is determined (status.c:
+ cText2SkinStatus::Replaying)
+ There remains a problem that recordings with the same name cannot be
+ distinguished, so information optained from mReplay are not necessarily
+ correct (all the ones added in vdr-text2skin-1.1-cvs_ext-0.2.diff)
+
+2005-12-11: Version 1.1-cvs_ext-0.3 (vdr-text2skin-1.1-cvs_ext-0.3.diff)
+
+- added recording-tokens:
+ RecordingLength, RecordingCuttedLength
+
+2005-11-19: Version 1.1-cvs_ext-0.2 (vdr-text2skin-1.1-cvs_ext-0.2.diff)
+
+- removed the previously introduced tokens NextTimerName, NextTimerStart,
+ NextTimerChannel, CurrentRecordingsCount and added tokens for the next
+ 3 timers: CurrentEventsTitle[123], CurrentEventsStartDateTime[123],
+ CurrentEventsStopDateTime[123], CurrentEventsChannelNumber[123],
+ CurrentEventsChannelName[123], CurrentEventsIsRecording[123]
+- added audio- and video-tokens:
+ PresentLanguageCode, PresentLanguageDescription, PresentVideoAR and
+ implemented the missing code for the Language-token
+- added tokens for replay:
+ ReplayName, ReplayDateTime, ReplayShortText, ReplayDescription,
+ ReplayLanguageCode, ReplayLanguageDescription, ReplayVideoAR
+ (not activated yet)
+- additional recording-tokens:
+ RecordingVideoAR, RecordingSize
+- added a reset for scrolling text (configurable)
+- included Text2skin.diff from the rotor-plugin
+
+2005-10-22: Version 1.1-cvs_ext-0.1 (vdr-text2skin-1.1-cvs_ext-0.1.diff)
+
+- added several tokens:
+ NextTimerName, NextTimerStart, NextTimerChannel, TimerConflict,
+ CurrentRecordingsCount, using the service "CheckTimerConflict-v1.0" to
+ check timer conflicts. A patch for the timeline-plugin is included in
+ Enigma-0.4pre2 (timeline_CheckTimerConflictService-0.1.diff)
+
2005-06-xx: Version 1.1
- fixed crash due to uninitialized pointer (thanks to Frank Enderle)
diff --git a/common.c b/common.c
index f45ed1c..904c417 100644
--- a/common.c
+++ b/common.c
@@ -115,6 +115,156 @@ const cRecording *GetRecordingByName(const char *Name)
return NULL;
}
+const cRecording *GetRecordingByFileName(const char *FileName)
+{
+ return (FileName) ? Recordings.GetByName(FileName) : NULL;
+}
+
+int GetRecordingSize(const char *FileName)
+{
+ if (FileName != NULL) {
+ bool bRet=false;
+ long long size = 0;
+ int nFiles;
+ struct stat fileinfo; // Holds file information structure
+ char *cmd = NULL;
+#if VDRVERSNUM >= 10318
+ cReadLine reader;
+#endif
+ asprintf(&cmd, "find '%s' -follow -type f -name '*.*'|sort ", FileName);
+
+ FILE *p = popen(cmd, "r");
+ int ret=0;
+ if (p)
+ {
+ char *s;
+
+#if VDRVERSNUM >= 10318
+ while ((s = reader.Read(p)) != NULL)
+#else
+ while ((s = readline(p)) != NULL)
+#endif
+ {
+ if ((ret=stat(s, &fileinfo)) != -1)
+ {
+ size += (long long)fileinfo.st_size;
+ nFiles++;
+ }
+ }
+
+ bRet=true;
+ }
+
+ pclose(p);
+ delete cmd;
+
+ return (int)(size / 1024 / 1024); // [MB]
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+int GetRecordingLength(const char *FileName)
+{
+ // based on the enAIO-Patch for VDR
+ #define INDEXFILESUFFIX "/index.vdr"
+
+ 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'", buf.st_size, filename);
+ }
+ last = (buf.st_size + delta) / sizeof(tIndex) - 1;
+ char hour[2], min[3];
+#if VDRVERSNUM >= 10318
+ snprintf(RecLength, sizeof(RecLength), "%s", *IndexToHMSF(last, true));
+#else
+ snprintf(RecLength, sizeof(RecLength), "%s", IndexToHMSF(last, true));
+#endif
+ 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);
+ }
+ }
+
+ return 0;
+}
+
+int GetRecordingCuttedLength(const char *FileName)
+{
+ cMarks marks;
+ double length = 0;
+ int totalLength = GetRecordingLength(FileName);
+ const double diffIFrame = FRAMESPERSEC / 2; // approx. 1/2 sec.
+ /*
+ // not useful
+ static std::string lastFileName = "";
+ static uint64 nextUpdate = 0;
+ static int totalLength = 0;
+ const uint64 bufferTime = 30 * 1000; // [ms]
+ */
+
+
+ marks.Load(FileName);
+
+ /*
+ // buffer the result of 'GetRecordingLength'
+ if (FileName != lastFileName || time_ms() >= nextUpdate)
+ {
+ lastFileName = FileName;
+ nextUpdate = time_ms() + bufferTime;
+ totalLength = GetRecordingLength(FileName);
+ }
+ */
+
+ if (marks.Count())
+ {
+ int start = 1; // first frame
+ bool isStart = true;
+
+ for (cMark *m = marks.First(); m; m = marks.GetNext(m->position))
+ {
+ if (isStart)
+ {
+ start = m->position;
+ }
+ else
+ {
+ length += (double)(m->position - start + 1 + diffIFrame) / (FRAMESPERSEC * 60); // [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]
+ }
+
+ // just to avoid, that the cutted length is bigger than the total length
+ return (int)length > totalLength ? totalLength : (int)length;
+}
+
cxType TimeType(time_t Time, const std::string &Format)
{
static char result[1000];
diff --git a/common.h b/common.h
index a86dc81..4c9e74d 100644
--- a/common.h
+++ b/common.h
@@ -51,6 +51,10 @@ const char *ChannelShortName(const cChannel *Channel, int Number);
bool StoppedTimer(const char *Name);
const cRecording *GetRecordingByName(const char *Name);
+const cRecording *GetRecordingByFileName(const char *FileName);
+int GetRecordingSize(const char *FileName); // [MB]
+int GetRecordingLength(const char *FileName); // [min]
+int GetRecordingCuttedLength(const char *FileName); // [min]
cxType TimeType(time_t Time, const std::string &Format);
cxType DurationType(uint Index, const std::string &Format);
diff --git a/display.c b/display.c
index c274080..227b41a 100644
--- a/display.c
+++ b/display.c
@@ -241,7 +241,16 @@ cxType cText2SkinDisplayChannel::GetTokenData(const txToken &Token)
case tLanguage: {
#if VDRVERSNUM >= 10318
- // TODO !!!
+ cDevice *dev = cDevice::PrimaryDevice();
+ eTrackType trackType = dev->GetCurrentAudioTrack();
+ const tTrackId *track = dev->GetTrack(trackType);
+ if (track)
+ {
+ std::string buffer(track->language);
+ if (trackType >= ttDolby) buffer.append("DD");
+ return (cxType)buffer.c_str();
+ }
+ return (cxType)false;
#else
int cur;
const char **tracks = cDevice::PrimaryDevice()->GetAudioTracks(&cur);
@@ -582,6 +591,32 @@ cxType cText2SkinDisplayReplay::GetTokenData(const txToken &Token)
}
return false;
+ case tLanguage: {
+#if VDRVERSNUM >= 10318
+ cDevice *dev = cDevice::PrimaryDevice();
+ eTrackType trackType = dev->GetCurrentAudioTrack();
+ const tTrackId *track = dev->GetTrack(trackType);
+ if (track)
+ {
+ std::string buffer(track->language);
+ if (trackType >= ttDolby) buffer.append("DD");
+ return (cxType)buffer.c_str();
+ }
+ return (cxType)false;
+#else
+ int cur;
+ const char **tracks = cDevice::PrimaryDevice()->GetAudioTracks(&cur);
+ if (tracks) {
+ int i = 0;
+ while (tracks[i] != NULL)
+ ++i;
+ if (cur < i)
+ return tracks[cur];
+ }
+#endif
+ }
+ return false;
+
case tMessage:
return mText;
@@ -755,6 +790,9 @@ void cText2SkinDisplayMenu::SetTitle(const char *Title)
UpdateLock();
if (Title == NULL) Title = "";
if (mTitle != Title) {
+ mUpdate.timerConflict = true;
+ mUpdate.events = true;
+ mUpdate.resetMarquee = true;
mTitle = Title;
SetDirty();
}
@@ -1049,7 +1087,76 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token)
return mEvent != NULL
? (cxType)mEvent->Description()
: (cxType)false;
-
+
+#if VDRVERSNUM >= 10318
+ case tPresentLanguageCode:
+ if (mEvent)
+ {
+ const cComponents *components = mEvent->Components();
+ if (components)
+ {
+ int index = Token.Attrib.Number;
+
+ // don't return language-code for the video-stream
+ for (int i = 0; i < components->NumComponents(); i++)
+ {
+ const tComponent *c = components->Component(i);
+ if (c->stream != 2) index++; // only audio-streams
+ if (i == index)
+ {
+ std::string buffer(c->language);
+ if (c->type == 1) buffer.append("MONO");
+ if (c->type == 2) buffer.append("DUAL");
+ if (c->type == 5) buffer.append("DD");
+ return (cxType)buffer.c_str();
+ }
+ }
+ }
+ }
+ return false;
+
+ case tPresentLanguageDescription:
+ if (mEvent)
+ {
+ const cComponents *components = mEvent->Components();
+ if (components)
+ {
+ int index = Token.Attrib.Number;
+
+ // don't return language-code for the video-stream
+ for (int i = 0; i < components->NumComponents(); i++)
+ {
+ const tComponent *c = components->Component(i);
+ if (c->stream != 2) index++; // only audio-streams
+ if (i == index) return (cxType)c->description;
+ }
+ }
+ }
+ return false;
+
+ case tPresentVideoAR:
+ if (mEvent)
+ {
+ const cComponents *components = mEvent->Components();
+ if (components)
+ {
+ for (int i = 0; i < components->NumComponents(); i++)
+ {
+ const tComponent *c = components->Component(i);
+ if (c->stream == 1)
+ {
+ switch (c->type)
+ {
+ case 1: return "4:3";
+ case 3: return "16:9";
+ }
+ }
+ }
+ }
+ }
+ return false;
+#endif
+
case tHasVPS:
case tChannelHasVPS:
return mEvent != NULL && mEvent->Vps() != 0;
@@ -1094,27 +1201,89 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token)
? (cxType)mRecording->Info()->Description()
: (cxType)false;
- case tRecordingLanguageCode:
- if (mRecording != NULL) {
- const tComponent *c
- = mRecording->Info()->Components()->Component(Token.Attrib.Number);
- return c != NULL
- ? (cxType)c->language
- : (cxType)false;
+ case tRecordingLanguageCode:
+ if (mRecording)
+ {
+ const cComponents *components = mRecording->Info()->Components();
+ if (components)
+ {
+ int index = Token.Attrib.Number;
+
+ // don't return language-code for the video-stream
+ for (int i = 0; i < components->NumComponents(); i++)
+ {
+ const tComponent *c = components->Component(i);
+ if (c->stream != 2) index++; // only audio-streams
+ if (i == index)
+ {
+ std::string buffer(c->language);
+ if (c->type == 1) buffer.append("MONO");
+ if (c->type == 2) buffer.append("DUAL");
+ if (c->type == 5) buffer.append("DD");
+ return (cxType)buffer.c_str();
+ }
+ }
+ }
}
return false;
-
+
case tRecordingLanguageDescription:
- if (mRecording != NULL) {
- const tComponent *c
- = mRecording->Info()->Components()->Component(Token.Attrib.Number);
- return c != NULL
- ? (cxType)c->description
- : (cxType)false;
+ if (mRecording)
+ {
+ const cComponents *components = mRecording->Info()->Components();
+ if (components)
+ {
+ int index = Token.Attrib.Number;
+
+ // don't return language-code for the video-stream
+ for (int i = 0; i < components->NumComponents(); i++)
+ {
+ const tComponent *c = components->Component(i);
+ if (c->stream != 2) index++; // only audio-streams
+ if (i == index) return (cxType)c->description;
+ }
+ }
+ }
+ return false;
+
+ case tRecordingVideoAR:
+ if (mRecording)
+ {
+ const cComponents *components = mRecording->Info()->Components();
+ if (components)
+ {
+ for (int i = 0; i < components->NumComponents(); i++)
+ {
+ const tComponent *c = components->Component(i);
+ if (c->stream == 1)
+ {
+ switch (c->type)
+ {
+ case 1: return "4:3";
+ case 3: return "16:9";
+ }
+ }
+ }
+ }
}
return false;
#endif
+ case tRecordingSize:
+ return mRecording != NULL
+ ? (cxType)GetRecordingSize(mRecording->FileName())
+ : (cxType)false;
+
+ case tRecordingLength:
+ return mRecording != NULL
+ ? (cxType)GetRecordingLength(mRecording->FileName())
+ : (cxType)false;
+
+ case tRecordingCuttedLength:
+ return mRecording != NULL
+ ? (cxType)GetRecordingCuttedLength(mRecording->FileName())
+ : (cxType)false;
+
default:
return cText2SkinRender::GetTokenData(Token);
}
diff --git a/i18n.c b/i18n.c
index c8a0fdc..ab583fc 100644
--- a/i18n.c
+++ b/i18n.c
@@ -79,15 +79,140 @@ const tI18nPhrase Phrases[] = {
"",
#endif
},
- { "Flushing image cache...",
- "Bildspeicher wird geleert...",
+ { "Flush image cache",
+ "Bildspeicher leeren",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "Tyhjennä kuvat välimuistista",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+#if VDRVERSNUM >= 10313
+ "",
+#endif
+#if VDRVERSNUM >= 10316
+ "",
+#endif
+ },
+ { "Scrolling behaviour",
+ "Scroll-Verhalten",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+#if VDRVERSNUM >= 10313
+ "",
+#endif
+#if VDRVERSNUM >= 10316
+ "",
+#endif
+ },
+ { "Reset Marquee for new item",
+ "Marquee für neues Item zurücksetzen",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+#if VDRVERSNUM >= 10313
+ "",
+#endif
+#if VDRVERSNUM >= 10316
+ "",
+#endif
+ },
+ { "Use 'timeline' to check timer-conflicts",
+ "Timerkonflikte mit 'timeline' überprüfen",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+#if VDRVERSNUM >= 10313
+ "",
+#endif
+#if VDRVERSNUM >= 10316
+ "",
+#endif
+ },
+ { "to the left",
+ "nach links",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+ "",
+#if VDRVERSNUM >= 10313
+ "",
+#endif
+#if VDRVERSNUM >= 10316
+ "",
+#endif
+ },
+ { "left and right",
+ "links und rechts",
+ "",
"",
"",
"",
"",
"",
"",
- "Tyhjennetään välimuistia...",
"",
"",
"",
diff --git a/menu.c b/menu.c
index 6bc478d..47ca136 100644
--- a/menu.c
+++ b/menu.c
@@ -9,6 +9,11 @@
cText2SkinSetupPage::cText2SkinSetupPage(void) {
mData = Text2SkinSetup;
+ Add(new cMenuEditBoolItem(tr("Scrolling behaviour"), &mData.MarqueeLeftRight, tr("to the left"), tr("left and right")));
+ Add(new cMenuEditBoolItem(tr("Reset Marquee for new item"), &mData.MarqueeReset, tr("no"), tr("yes")));
+#if VDRVERSNUM >= 10330
+ Add(new cMenuEditBoolItem(tr("Use 'timeline' to check timer-conflicts"), &mData.CheckTimerConflict, tr("no"), tr("yes")));
+#endif
Add(new cOsdItem(tr("Flush image cache"), osUser1));
Add(new cMenuEditIntItem(tr("Max. image cache size"), &mData.MaxCacheFill));
}
@@ -17,6 +22,11 @@ cText2SkinSetupPage::~cText2SkinSetupPage() {
}
void cText2SkinSetupPage::Store(void) {
+ SetupStore("MarqueeLeftRight", mData.MarqueeLeftRight);
+ SetupStore("MarqueeReset", mData.MarqueeReset);
+#if VDRVERSNUM >= 10330
+ SetupStore("CheckTimerConflict", mData.CheckTimerConflict);
+#endif
SetupStore("MaxCacheFill", mData.MaxCacheFill);
Text2SkinSetup = mData;
}
diff --git a/render.c b/render.c
index 3d3b4d7..78c5ac6 100644
--- a/render.c
+++ b/render.c
@@ -11,6 +11,7 @@
#include "screen.h"
#include "display.h"
#include "scroller.h"
+#include "setup.h"
#include "xml/display.h"
#include <vdr/channels.h>
#include <vdr/epg.h>
@@ -353,13 +354,30 @@ void cText2SkinRender::DrawMarquee(const txPoint &Pos, const txSize &Size, const
uint Delay, uint Index)
{
bool scrolling = Font->Width(Text.c_str()) > Size.w;
-
+
tState &state = mStates[Index];
if (state.text != Text) {
state = tState();
state.text = Text;
}
+ if (Text2SkinSetup.MarqueeReset && mUpdate.resetMarquee && mUpdate.currentItem.find(Text, 0) != std::string::npos)
+ {
+ state.offset = 0;
+ state.direction = 1;
+ state.nexttime = 0;
+ state.scrolling = false;
+ mUpdate.foundFirstItem = true;
+ }
+ else
+ {
+ if (mUpdate.foundFirstItem)
+ {
+ mUpdate.resetMarquee = false;
+ mUpdate.foundFirstItem = false;
+ }
+ }
+
if (state.nexttime == 0)
state.nexttime = mNow + 1500;
else if (mNow >= state.nexttime) {
@@ -376,7 +394,7 @@ void cText2SkinRender::DrawMarquee(const txPoint &Pos, const txSize &Size, const
++state.direction;
nextin = 1500;
} else
- --state.offset;
+ Text2SkinSetup.MarqueeLeftRight ? --state.offset : state.offset = 0;
}
state.nexttime = mNow + nextin;
}
@@ -661,7 +679,11 @@ cxType cText2SkinRender::GetTokenData(const txToken &Token)
case tCanScrollDown: return mScroller != NULL && mScroller->CanScrollDown();
case tIsRecording: return cRecordControls::Active();
-
+
+ case tOsdWidth: return (cxType)mBaseSize.w;
+
+ case tOsdHeight: return (cxType)mBaseSize.h;
+
#if VDRVERSNUM >=10318
case tAudioTrack: {
cDevice *dev = cDevice::PrimaryDevice();
diff --git a/render.h b/render.h
index 6797e1a..b0e50cf 100644
--- a/render.h
+++ b/render.h
@@ -134,6 +134,18 @@ public:
static bool ItemColor(const std::string &Color, tColor &Result);
static std::string ImagePath(const std::string &Filename);
static cxType GetToken(const txToken &Token);
+
+ // update infos
+ struct tUpdate
+ {
+ bool timerConflict;
+ bool events;
+ std::string currentItem;
+ bool resetMarquee;
+ bool foundFirstItem;
+
+ tUpdate(void) : timerConflict(true), events(true), currentItem(""), resetMarquee(true), foundFirstItem(false) {}
+ } mUpdate;
};
inline void cText2SkinRender::Flush(bool Force)
diff --git a/setup.c b/setup.c
index 575bda6..504c4e4 100644
--- a/setup.c
+++ b/setup.c
@@ -9,12 +9,19 @@ cText2SkinSetup Text2SkinSetup;
// --- cText2SkinSetup --------------------------------------------------------
cText2SkinSetup::cText2SkinSetup(void) {
+ MarqueeLeftRight = true;
+ MarqueeReset = false;
+ CheckTimerConflict = false;
MaxCacheFill = 25;
}
bool cText2SkinSetup::SetupParse(const char *Name, const char *Value) {
- if (strcmp(Name, "MaxCacheFill") == 0) MaxCacheFill = atoi(Value);
+ if (strcmp(Name, "MarqueeLeftRight") == 0) MarqueeLeftRight = atoi(Value);
+ else if (strcmp(Name, "MarqueeReset") == 0) MarqueeReset = atoi(Value);
+ else if (strcmp(Name, "CheckTimerConflict") == 0) CheckTimerConflict = atoi(Value);
+ else if (strcmp(Name, "MaxCacheFill") == 0) MaxCacheFill = atoi(Value);
else return false;
+
return true;
}
diff --git a/setup.h b/setup.h
index bf9e8e1..a21b15e 100644
--- a/setup.h
+++ b/setup.h
@@ -13,6 +13,9 @@ public:
bool SetupParse(const char *Name, const char *Value);
+ int MarqueeLeftRight;
+ int MarqueeReset;
+ int CheckTimerConflict;
int MaxCacheFill;
};
diff --git a/status.c b/status.c
index 9052267..9155bf6 100644
--- a/status.c
+++ b/status.c
@@ -4,6 +4,10 @@
#include "status.h"
#include "render.h"
+#include "menu.h"
+#include <vdr/timers.h>
+#include <vdr/plugin.h>
+#include <vdr/menu.h>
const std::string ReplayNames[__REPLAY_COUNT__] =
{ "", "normal", "mp3", "mplayer", "dvd", "vcd", "image" };
@@ -29,7 +33,12 @@ void cText2SkinStatus::SetRender(cText2SkinRender *Render)
mNextRecording = 0;
}
-void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name) {
+#if VDRVERSNUM >= 10338
+void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name, const char *FileName, bool On)
+#else
+void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name)
+#endif
+{
Dprintf("cText2SkinStatus::Replaying(%s)\n", Name);
eReplayMode oldMode = mReplayMode;
@@ -49,9 +58,20 @@ void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name)
mReplayIsLoop = Name[1] == 'L';
mReplayIsShuffle = Name[2] == 'S';
}
- }
- else if (GetRecordingByName(Name) != NULL)
+ }
+#if VDRVERSNUM >= 10338
+ else if (const cRecording *rec = GetRecordingByFileName(FileName))
+ {
+ mReplay = rec;
mReplayMode = replayNormal;
+ }
+#else
+ else if (const cRecording *rec = GetRecordingByName(Name))
+ {
+ mReplay = rec;
+ mReplayMode = replayNormal;
+ }
+#endif
else if (strcmp(Name, "DVD") == 0)
mReplayMode = replayDVD;
else if (strcmp(Name, "VCD") == 0)
@@ -83,7 +103,11 @@ void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name)
}
}
-void cText2SkinStatus::Recording(const cDevice *Device, const char *Name)
+#if VDRVERSNUM >= 10338
+void cText2SkinStatus::Recording(const cDevice *Device, const char *Name, const char *FileName, bool On)
+#else
+void cText2SkinStatus::Recording(const cDevice *Device, const char *Name)
+#endif
{
if (mRender != NULL)
mRender->UpdateLock();
@@ -112,12 +136,267 @@ void cText2SkinStatus::OsdClear(void)
}
}
+void cText2SkinStatus::OsdCurrentItem(const char *Text)
+{
+ if (mRender != NULL)
+ {
+ static std::string lastItem;
+
+ lastItem = mRender->mUpdate.currentItem;
+ mRender->mUpdate.currentItem = Text;
+ mRender->mUpdate.resetMarquee = true;
+ mRender->mUpdate.foundFirstItem = false;
+ }
+}
+
+void cText2SkinStatus::UpdateEvents(void)
+{
+ if (mRender->mUpdate.events)
+ {
+ mRender->mUpdate.events = false;
+
+ mEvents.clear();
+ Timers.IncBeingEdited();
+
+ for (cTimer *tim = Timers.First(); tim != NULL; tim = Timers.Next(tim))
+ {
+ if (tim->HasFlags(tfActive))
+ {
+ int i = 0;
+ cTimer dummy;
+ dummy = *tim; // copy the timer
+
+ do
+ {
+ tEvent ev;
+
+ ev.title = dummy.File();
+ ev.isRecording = dummy.Recording();
+ ev.channelName = dummy.Channel()->Name();
+ ev.channelNumber = dummy.Channel()->Number();
+ ev.startTime = dummy.StartTime();
+ ev.stopTime = dummy.StopTime();
+ ev.priority = dummy.Priority();
+
+ mEvents.push_back(ev);
+
+ if (!dummy.IsSingleEvent()) // add 4 additional rep. timer
+ {
+ do
+ {
+ dummy.Skip();
+ dummy.Matches(); // Refresh start- and end-time
+ } while (!dummy.DayMatches(dummy.Day()));
+ }
+
+ i++;
+ } while (!dummy.IsSingleEvent() && i < 5);
+ }
+ }
+
+ Timers.DecBeingEdited();
+ std::sort(mEvents.rbegin(), mEvents.rend());
+ }
+}
+
cxType cText2SkinStatus::GetTokenData(const txToken &Token)
{
+ uint event = 0;
+
switch (Token.Type) {
case tReplayMode:
return ReplayNames[mReplayMode];
+ case tCurrentEventsTitle3:
+ event++;
+ case tCurrentEventsTitle2:
+ event++;
+ case tCurrentEventsTitle1:
+ UpdateEvents();
+ return mEvents.size() > event
+ ? (cxType)mEvents[event].title.c_str()
+ : (cxType)false;
+
+ case tCurrentEventsStartDateTime3:
+ event++;
+ case tCurrentEventsStartDateTime2:
+ event++;
+ case tCurrentEventsStartDateTime1:
+ UpdateEvents();
+ return mEvents.size() > event
+ ? (cxType)TimeType(mEvents[event].startTime, Token.Attrib.Text)
+ : (cxType)false;
+
+ case tCurrentEventsStopDateTime3:
+ event++;
+ case tCurrentEventsStopDateTime2:
+ event++;
+ case tCurrentEventsStopDateTime1:
+ UpdateEvents();
+ return mEvents.size() > event
+ ? (cxType)TimeType(mEvents[event].stopTime, Token.Attrib.Text)
+ : (cxType)false;
+
+ case tCurrentEventsChannelNumber3:
+ event++;
+ case tCurrentEventsChannelNumber2:
+ event++;
+ case tCurrentEventsChannelNumber1:
+ UpdateEvents();
+ return mEvents.size() > event
+ ? (cxType)mEvents[event].channelNumber
+ : (cxType)false;
+
+ case tCurrentEventsChannelName3:
+ event++;
+ case tCurrentEventsChannelName2:
+ event++;
+ case tCurrentEventsChannelName1:
+ UpdateEvents();
+ return mEvents.size() > event
+ ? (cxType)mEvents[event].channelName.c_str()
+ : (cxType)false;
+
+ case tCurrentEventsIsRecording3:
+ event++;
+ case tCurrentEventsIsRecording2:
+ event++;
+ case tCurrentEventsIsRecording1:
+ UpdateEvents();
+ return mEvents.size() > event
+ ? (cxType)mEvents[event].isRecording
+ : (cxType)false;
+
+ case tTimerConflict:
+#if VDRVERSNUM >= 10330
+ if (Text2SkinSetup.CheckTimerConflict)
+ {
+ bool conflict;
+
+ if (mRender->mUpdate.timerConflict)
+ {
+ mRender->mUpdate.timerConflict = false;
+
+ if (cPluginManager::CallFirstService("CheckTimerConflict-v1.0", &conflict) )
+ {
+ mTimerConflict = conflict;
+ }
+ else
+ {
+ mTimerConflict = false;
+ }
+ }
+
+ return mTimerConflict;
+ }
+ else
+ {
+ return false;
+ }
+#endif
+
+#if VDRVERSNUM >= 10325
+#if VDRVERSNUM >= 10338
+ case tReplayName:
+ return mReplay != NULL
+ ? (cxType)mReplay->Name()
+ : (cxType)false;
+
+ case tReplayDateTime:
+ return mReplay != NULL
+ ? (cxType)TimeType(mReplay->start, Token.Attrib.Text)
+ : (cxType)false;
+
+ case tReplayShortText:
+ return mReplay != NULL
+ ? (cxType)mReplay->Info()->ShortText()
+ : (cxType)false;
+
+ case tReplayDescription:
+ return mReplay != NULL
+ ? (cxType)mReplay->Info()->Description()
+ : (cxType)false;
+#else
+ case tReplayName:
+ return (cxType)false;
+
+ case tReplayDateTime:
+ return (cxType)false;
+
+ case tReplayShortText:
+ return (cxType)false;
+
+ case tReplayDescription:
+ return (cxType)false;
+#endif
+
+ case tReplayLanguageCode:
+ if (mReplay)
+ {
+ const cComponents *components = mReplay->Info()->Components();
+ if (components)
+ {
+ int index = Token.Attrib.Number;
+
+ // don't return language-code for the video-stream
+ for (int i = 0; i < components->NumComponents(); i++)
+ {
+ const tComponent *c = components->Component(i);
+ if (c->stream != 2) index++; // only audio-streams
+ {
+ std::string buffer(c->language);
+ if (c->type == 1) buffer.append("MONO");
+ if (c->type == 2) buffer.append("DUAL");
+ if (c->type == 5) buffer.append("DD");
+ return (cxType)buffer.c_str();
+ }
+ }
+ }
+ }
+ return false;
+
+ case tReplayLanguageDescription:
+ if (mReplay)
+ {
+ const cComponents *components = mReplay->Info()->Components();
+ if (components)
+ {
+ int index = Token.Attrib.Number;
+
+ // don't return language-code for the video-stream
+ for (int i = 0; i < components->NumComponents(); i++)
+ {
+ const tComponent *c = components->Component(i);
+ if (c->stream != 2) index++; // only audio-streams
+ if (i == index) return (cxType)c->description;
+ }
+ }
+ }
+ return false;
+
+ case tReplayVideoAR:
+ if (mReplay)
+ {
+ const cComponents *components = mReplay->Info()->Components();
+ if (components)
+ {
+ for (int i = 0; i < components->NumComponents(); i++)
+ {
+ const tComponent *c = components->Component(i);
+ if (c->stream == 1)
+ {
+ switch (c->type)
+ {
+ case 1: return "4:3";
+ case 3: return "16:9";
+ }
+ }
+ }
+ }
+ }
+ return false;
+#endif
+
case tCurrentRecording:
Dprintf("token attrib type is: %d, number: %d\n", Token.Attrib.Type, Token.Attrib.Number);
if (Token.Attrib.Type == aNumber) {
diff --git a/status.h b/status.h
index 0aacd70..2047595 100644
--- a/status.h
+++ b/status.h
@@ -5,9 +5,12 @@
#ifndef VDR_TEXT2SKIN_STATUS_H
#define VDR_TEXT2SKIN_STATUS_H
+#include <algorithm>
+#include <vector>
#include "common.h"
#include <vdr/status.h>
+
class cText2SkinRender;
class cText2SkinStatus: public cStatus {
@@ -27,21 +30,52 @@ public:
typedef std::string tRecordingInfo;
typedef std::vector<tRecordingInfo> tRecordings;
+ struct tEvent
+ {
+ std::string title;
+ bool isRecording;
+ std::string channelName;
+ int channelNumber;
+ time_t startTime;
+ time_t stopTime;
+ int priority;
+
+ bool tEvent::operator< (const tEvent &b) const
+ {
+ int r = startTime - b.startTime;
+ r = r == 0 ? b.priority - priority : r;
+ return r > 0 ? true : false;
+ };
+ };
+
+ typedef std::vector<tEvent> tEvents;
+
private:
+ void UpdateEvents(void);
+
cText2SkinRender *mRender;
eReplayMode mReplayMode;
bool mReplayIsLoop;
bool mReplayIsShuffle;
tRecordings mRecordings;
+ tEvents mEvents;
+ const cRecording *mReplay;
cMutex mRecordingsLock;
uint mCurrentRecording;
uint mNextRecording;
int mLastLanguage;
+ bool mTimerConflict;
protected:
+#if VDRVERSNUM >= 10338
+ virtual void Replaying(const cControl *Control, const char *Name, const char *FileName, bool On);
+ virtual void Recording(const cDevice *Device, const char *Name, const char *FileName, bool On);
+#else
virtual void Replaying(const cControl *Control, const char *Name);
virtual void Recording(const cDevice *Device, const char *Name);
+#endif
virtual void OsdClear(void);
+ virtual void OsdCurrentItem(const char *Text);
public:
cText2SkinStatus(void);
diff --git a/text2skin.c b/text2skin.c
index be63af4..cf4f618 100644
--- a/text2skin.c
+++ b/text2skin.c
@@ -12,6 +12,7 @@
#include "i18n.h"
#include "loader.h"
#include "status.h"
+#include "xml/object.h"
const char *cText2SkinPlugin::VERSION = "1.1-cvs";
const char *cText2SkinPlugin::SKINVERSION = "1.0";
@@ -23,6 +24,19 @@ cText2SkinPlugin::cText2SkinPlugin(void) {
cText2SkinPlugin::~cText2SkinPlugin() {
}
+#if VDRVERSNUM >= 10330
+bool cText2SkinPlugin::Service(const char *Id, void *Data)
+{
+ if (strcmp(Id,"Text2Skin-TTF") == 0) {
+ if (Data == NULL)
+ return true;
+ cxObject::UseTTF = *(int*)Data;
+ return true;
+ }
+ return false;
+}
+#endif
+
bool cText2SkinPlugin::Start(void) {
RegisterI18n(Phrases);
Text2SkinStatus.SetLanguage(Setup.OSDLanguage);
diff --git a/text2skin.h b/text2skin.h
index b40ea54..cdd95ca 100644
--- a/text2skin.h
+++ b/text2skin.h
@@ -21,6 +21,9 @@ public:
virtual ~cText2SkinPlugin();
virtual const char *Version(void) { return VERSION; }
virtual const char *Description(void) { return tr(DESCRIPTION); }
+#if VDRVERSNUM >= 10330
+ virtual bool Service(const char *Id, void *Data);
+#endif
virtual bool Start(void);
virtual cMenuSetupPage *SetupMenu(void);
virtual bool SetupParse(const char *Name, const char *Value);
diff --git a/xml/object.c b/xml/object.c
index 6ea0ab6..3979384 100644
--- a/xml/object.c
+++ b/xml/object.c
@@ -140,17 +140,23 @@ const std::string &cxObject::TypeName(void) const
return ObjectNames[mType];
}
+int cxObject::UseTTF = true;
+
const cFont *cxObject::Font(void) const
{
const cFont *font;
+ if (UseTTF) {
+
+ if ((font = cText2SkinFont::Load(SkinPath() + "/" + mSkin->Name(), mFontFace, mFontSize,
+ mFontWidth)) != NULL)
+ return font;
+
if ((font = cText2SkinFont::Load(SkinPath() + "/fonts", mFontFace, mFontSize, mFontWidth))
!= NULL)
return font;
- if ((font = cText2SkinFont::Load(SkinPath() + "/" + mSkin->Name(), mFontFace, mFontSize,
- mFontWidth)) != NULL)
- return font;
+ }
return cFont::GetFont(fontOsd);
}
diff --git a/xml/object.h b/xml/object.h
index bbc37a0..96cdd14 100644
--- a/xml/object.h
+++ b/xml/object.h
@@ -45,6 +45,7 @@ class cxObject {
friend class VSkinnerItem;
public:
+ static int UseTTF;
enum eType {
image,
text,
diff --git a/xml/string.c b/xml/string.c
index afc0c7a..b8fc1f9 100644
--- a/xml/string.c
+++ b/xml/string.c
@@ -11,7 +11,11 @@ static const char *Tokens[__COUNT_TOKEN__] = {
// Channel Display
"ChannelNumber", "ChannelName", "ChannelShortName", "ChannelBouquet", "ChannelPortal",
"ChannelSource", "ChannelID", "PresentStartDateTime", "PresentVPSDateTime",
+ "CurrentEventsTitle1", "CurrentEventsStartDateTime1", "CurrentEventsStopDateTime1", "CurrentEventsChannelNumber1", "CurrentEventsChannelName1", "CurrentEventsIsRecording1", "CurrentEventsTitle2", "CurrentEventsStartDateTime2", "CurrentEventsStopDateTime2", "CurrentEventsChannelNumber2", "CurrentEventsChannelName2", "CurrentEventsIsRecording2",
+ "CurrentEventsTitle3", "CurrentEventsStartDateTime3", "CurrentEventsStopDateTime3", "CurrentEventsChannelNumber3", "CurrentEventsChannelName3", "CurrentEventsIsRecording3",
+ "TimerConflict",
"PresentEndDateTime", "PresentDuration", "PresentProgress", "PresentRemaining",
+ "PresentLanguageCode", "PresentLanguageDescription", "PresentVideoAR",
"PresentTitle", "PresentShortText", "PresentDescription", "FollowingStartDateTime",
"FollowingVPSDateTime", "FollowingEndDateTime", "FollowingDuration",
"FollowingTitle", "FollowingShortText", "FollowingDescription", "Language",
@@ -30,6 +34,8 @@ static const char *Tokens[__COUNT_TOKEN__] = {
// Replay Display
"ReplayTitle", "ReplayPositionIndex", "ReplayDurationIndex", "ReplayPrompt",
+ "ReplayName", "ReplayDateTime", "ReplayShortText", "ReplayDescription",
+ "ReplayLanguageCode", "ReplayLanguageDescription", "ReplayVideoAR",
"IsPlaying", "ReplayIsPlaying", "IsFastForward", "ReplayIsFastForward", "IsFastRewind",
"ReplayIsFastRewind", "IsSlowForward", "ReplayIsSlowForward", "IsSlowRewind",
"ReplayIsSlowRewind", "IsPausing", "ReplayIsPausing",
@@ -40,6 +46,7 @@ static const char *Tokens[__COUNT_TOKEN__] = {
"MenuTitle", "MenuGroup", "IsMenuGroup", "MenuItem", "IsMenuItem", "MenuCurrent",
"IsMenuCurrent", "MenuText", "RecordingName", "RecordingDateTime", "RecordingTitle",
"RecordingShortText", "RecordingDescription", "RecordingLanguageCode",
+ "RecordingVideoAR", "RecordingSize", "RecordingLength", "RecordingCuttedLength", "OsdWidth", "OsdHeight",
"RecordingLanguageDescription", "ButtonRed", "ButtonGreen",
"ButtonYellow", "ButtonBlue", "CanScrollUp", "CanScrollDown"
};
diff --git a/xml/string.h b/xml/string.h
index 7c3f30f..68cd8fa 100644
--- a/xml/string.h
+++ b/xml/string.h
@@ -26,10 +26,32 @@ enum exToken {
// next 9 also in Menu
tPresentStartDateTime,
tPresentVPSDateTime,
+ tCurrentEventsTitle1,
+ tCurrentEventsStartDateTime1,
+ tCurrentEventsStopDateTime1,
+ tCurrentEventsChannelNumber1,
+ tCurrentEventsChannelName1,
+ tCurrentEventsIsRecording1,
+ tCurrentEventsTitle2,
+ tCurrentEventsStartDateTime2,
+ tCurrentEventsStopDateTime2,
+ tCurrentEventsChannelNumber2,
+ tCurrentEventsChannelName2,
+ tCurrentEventsIsRecording2,
+ tCurrentEventsTitle3,
+ tCurrentEventsStartDateTime3,
+ tCurrentEventsStopDateTime3,
+ tCurrentEventsChannelNumber3,
+ tCurrentEventsChannelName3,
+ tCurrentEventsIsRecording3,
+ tTimerConflict,
tPresentEndDateTime,
tPresentDuration,
tPresentProgress,
tPresentRemaining,
+ tPresentLanguageCode,
+ tPresentLanguageDescription,
+ tPresentVideoAR,
tPresentTitle,
tPresentShortText,
tPresentDescription,
@@ -85,6 +107,13 @@ enum exToken {
tReplayPositionIndex,
tReplayDurationIndex,
tReplayPrompt,
+ tReplayName,
+ tReplayDateTime,
+ tReplayShortText,
+ tReplayDescription,
+ tReplayLanguageCode,
+ tReplayLanguageDescription,
+ tReplayVideoAR,
tIsPlaying,
tReplayIsPlaying, // alias
tIsFastForward,
@@ -120,6 +149,12 @@ enum exToken {
tRecordingShortText,
tRecordingDescription,
tRecordingLanguageCode,
+ tRecordingVideoAR,
+ tRecordingSize,
+ tRecordingLength,
+ tRecordingCuttedLength,
+ tOsdWidth,
+ tOsdHeight,
tRecordingLanguageDescription,
// next four also in Channel and Replay display (if supported by vdr/plugin)
tButtonRed,
@@ -128,7 +163,7 @@ enum exToken {
tButtonBlue,
tCanScrollUp,
tCanScrollDown,
-
+
#define __COUNT_TOKEN__ (tCanScrollDown + 1)
};