From 71023584dc849dc3705c6db303878fd27e8704c7 Mon Sep 17 00:00:00 2001 From: Andreas Brugger Date: Sat, 22 Oct 2005 12:00:00 +0200 Subject: 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) --- HISTORY | 8 ++++++++ status.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- xml/string.c | 2 +- xml/string.h | 5 +++++ 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/HISTORY b/HISTORY index e861639..0c8913a 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,14 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +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/status.c b/status.c index 9052267..16ce124 100644 --- a/status.c +++ b/status.c @@ -4,6 +4,8 @@ #include "status.h" #include "render.h" +#include +#include const std::string ReplayNames[__REPLAY_COUNT__] = { "", "normal", "mp3", "mplayer", "dvd", "vcd", "image" }; @@ -117,7 +119,67 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) switch (Token.Type) { case tReplayMode: return ReplayNames[mReplayMode]; - + + case tNextTimerName: + { + cTimer *tim = Timers.GetNextActiveTimer(); + if (tim) + { + const char *timText = tim->File(); + return timText; + } + else + { + return false; + } + } + + case tNextTimerStart: + { + cTimer *tim = Timers.GetNextActiveTimer(); + if (tim) + { + char *buffer = NULL; + asprintf(&buffer, "%02d:%02d", tim->Start() / 100, tim->Start() % 100); + return buffer; + } + else + { + return false; + } + } + + case tNextTimerChannel: + { + cTimer *tim = Timers.GetNextActiveTimer(); + if (tim) + { + const char *timChan = tim->Channel()->Name(); + return timChan; + } + else + { + return false; + } + } + + case tTimerConflict: + { + bool conflict = false; + + if (cPluginManager::CallFirstService("CheckTimerConflict-v1.0", &conflict) ) + { + return conflict; + } + else + { + return false; + } + } + + case tCurrentRecordingsCount: + return (int)mRecordings.size(); + case tCurrentRecording: Dprintf("token attrib type is: %d, number: %d\n", Token.Attrib.Type, Token.Attrib.Number); if (Token.Attrib.Type == aNumber) { @@ -127,7 +189,7 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) } else if (mRecordings.size() > 0) { mRecordingsLock.Lock(); uint now = time_ms(); - if (mNextRecording == 0) + if (mNextRecording == 0) mNextRecording = now + 2000; else if (now >= mNextRecording) { mCurrentRecording = (mCurrentRecording + 1) % mRecordings.size(); diff --git a/xml/string.c b/xml/string.c index afc0c7a..845b766 100644 --- a/xml/string.c +++ b/xml/string.c @@ -10,7 +10,7 @@ static const char *Tokens[__COUNT_TOKEN__] = { // Channel Display "ChannelNumber", "ChannelName", "ChannelShortName", "ChannelBouquet", "ChannelPortal", - "ChannelSource", "ChannelID", "PresentStartDateTime", "PresentVPSDateTime", + "ChannelSource", "ChannelID", "NextTimerName", "NextTimerStart", "NextTimerChannel", "TimerConflict", "CurrentRecordingsCount", "PresentStartDateTime", "PresentVPSDateTime", "PresentEndDateTime", "PresentDuration", "PresentProgress", "PresentRemaining", "PresentTitle", "PresentShortText", "PresentDescription", "FollowingStartDateTime", "FollowingVPSDateTime", "FollowingEndDateTime", "FollowingDuration", diff --git a/xml/string.h b/xml/string.h index 7c3f30f..6c78373 100644 --- a/xml/string.h +++ b/xml/string.h @@ -24,6 +24,11 @@ enum exToken { tChannelSource, tTChannelID, // (name clash) // next 9 also in Menu + tNextTimerName, + tNextTimerStart, + tNextTimerChannel, + tTimerConflict, + tCurrentRecordingsCount, tPresentStartDateTime, tPresentVPSDateTime, tPresentEndDateTime, -- cgit v1.2.3 From 662dd62488f6f842fe5d940e986f798abe1c7691 Mon Sep 17 00:00:00 2001 From: Andreas Brugger Date: Sat, 19 Nov 2005 12:00:00 +0100 Subject: 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 --- HISTORY | 19 +++++ display.c | 222 ++++++++++++++++++++++++++++++++++++++++++++---- i18n.c | 131 ++++++++++++++++++++++++++++- menu.c | 6 ++ render.c | 22 ++++- render.h | 12 +++ setup.c | 9 +- setup.h | 3 + status.c | 271 ++++++++++++++++++++++++++++++++++++++++++++++++----------- status.h | 26 ++++++ text2skin.c | 12 +++ text2skin.h | 1 + xml/object.c | 6 ++ xml/object.h | 1 + xml/string.c | 9 +- xml/string.h | 36 ++++++-- 16 files changed, 711 insertions(+), 75 deletions(-) diff --git a/HISTORY b/HISTORY index 0c8913a..634b500 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,25 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +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: diff --git a/display.c b/display.c index a8fca2c..72b42cd 100644 --- a/display.c +++ b/display.c @@ -243,7 +243,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); @@ -584,6 +593,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; @@ -757,6 +792,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(); } @@ -1051,7 +1089,74 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) return mEvent != NULL ? (cxType)mEvent->Description() : (cxType)false; - + + 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; + case tHasVPS: case tChannelHasVPS: return mEvent != NULL && mEvent->Vps() != 0; @@ -1096,27 +1201,112 @@ 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: + if (mRecording != NULL) { + bool bRet=false; + long long size = 0; + int nFiles; + struct stat fileinfo; // Holds file information structure + char *cmd = NULL; + cReadLine reader; + asprintf(&cmd, "find '%s' -follow -type f -name '*.*'|sort ", mRecording->FileName()); + + FILE *p = popen(cmd, "r"); + int ret=0; + if (p) + { + char *s; + + while ((s = reader.Read(p)) != NULL) + { + if ((ret=stat(s, &fileinfo)) != -1) + { + size += (long long)fileinfo.st_size; + nFiles++; + } + } + + bRet=true; + } + + pclose(p); + delete cmd; + + return (long)(size / 1024 / 1024); // [MB] + } + else + { + return 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..8ccaf58 100644 --- a/menu.c +++ b/menu.c @@ -9,6 +9,9 @@ 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"))); + Add(new cMenuEditBoolItem(tr("Use 'timeline' to check timer-conflicts"), &mData.CheckTimerConflict, tr("no"), tr("yes"))); Add(new cOsdItem(tr("Flush image cache"), osUser1)); Add(new cMenuEditIntItem(tr("Max. image cache size"), &mData.MaxCacheFill)); } @@ -17,6 +20,9 @@ cText2SkinSetupPage::~cText2SkinSetupPage() { } void cText2SkinSetupPage::Store(void) { + SetupStore("MarqueeLeftRight", mData.MarqueeLeftRight); + SetupStore("MarqueeReset", mData.MarqueeReset); + SetupStore("CheckTimerConflict", mData.CheckTimerConflict); SetupStore("MaxCacheFill", mData.MaxCacheFill); Text2SkinSetup = mData; } diff --git a/render.c b/render.c index 3d3b4d7..4c15f26 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 #include @@ -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; } 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 16ce124..8e376b3 100644 --- a/status.c +++ b/status.c @@ -4,6 +4,7 @@ #include "status.h" #include "render.h" +#include "menu.h" #include #include @@ -52,8 +53,11 @@ void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name) mReplayIsShuffle = Name[2] == 'S'; } } - else if (GetRecordingByName(Name) != NULL) - mReplayMode = replayNormal; + else if (const cRecording *rec = GetRecordingByName(Name)) + { + mReplay = rec; + mReplayMode = replayNormal; + } else if (strcmp(Name, "DVD") == 0) mReplayMode = replayDVD; else if (strcmp(Name, "VCD") == 0) @@ -114,72 +118,245 @@ 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 tNextTimerName: + + 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 (Text2SkinSetup.CheckTimerConflict) { - cTimer *tim = Timers.GetNextActiveTimer(); - if (tim) - { - const char *timText = tim->File(); - return timText; - } - else + bool conflict; + + if (mRender->mUpdate.timerConflict) { - return false; + mRender->mUpdate.timerConflict = false; + + if (cPluginManager::CallFirstService("CheckTimerConflict-v1.0", &conflict) ) + { + mTimerConflict = conflict; + } + else + { + mTimerConflict = false; + } } + + return mTimerConflict; } - - case tNextTimerStart: + else { - cTimer *tim = Timers.GetNextActiveTimer(); - if (tim) - { - char *buffer = NULL; - asprintf(&buffer, "%02d:%02d", tim->Start() / 100, tim->Start() % 100); - return buffer; - } - else - { - return false; - } + return false; } - case tNextTimerChannel: + 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; + + case tReplayLanguageCode: + if (mReplay) { - cTimer *tim = Timers.GetNextActiveTimer(); - if (tim) - { - const char *timChan = tim->Channel()->Name(); - return timChan; - } - else + const cComponents *components = mReplay->Info()->Components(); + if (components) { - return false; + 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->language; + } } } - - case tTimerConflict: + return false; + + case tReplayLanguageDescription: + if (mReplay) { - bool conflict = false; - - if (cPluginManager::CallFirstService("CheckTimerConflict-v1.0", &conflict) ) + const cComponents *components = mReplay->Info()->Components(); + if (components) { - return conflict; + 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; + } } - else + } + return false; + + /* + case tReplayVideoAR: + if (mReplay) + { + const cComponents *components = mReplay->Info()->Components(); + if (components) { - return false; + 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"; + } + } + } } } - - case tCurrentRecordingsCount: - return (int)mRecordings.size(); - + return false; + */ + case tCurrentRecording: Dprintf("token attrib type is: %d, number: %d\n", Token.Attrib.Type, Token.Attrib.Number); if (Token.Attrib.Type == aNumber) { @@ -189,7 +366,7 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) } else if (mRecordings.size() > 0) { mRecordingsLock.Lock(); uint now = time_ms(); - if (mNextRecording == 0) + if (mNextRecording == 0) mNextRecording = now + 2000; else if (now >= mNextRecording) { mCurrentRecording = (mCurrentRecording + 1) % mRecordings.size(); diff --git a/status.h b/status.h index 0aacd70..92c06de 100644 --- a/status.h +++ b/status.h @@ -27,21 +27,47 @@ public: typedef std::string tRecordingInfo; typedef std::vector 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 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: virtual void Replaying(const cControl *Control, const char *Name); virtual void Recording(const cDevice *Device, const char *Name); virtual void OsdClear(void); + virtual void OsdCurrentItem(const char *Text); public: cText2SkinStatus(void); diff --git a/text2skin.c b/text2skin.c index be63af4..6ca80d0 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,17 @@ cText2SkinPlugin::cText2SkinPlugin(void) { cText2SkinPlugin::~cText2SkinPlugin() { } +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; +} + bool cText2SkinPlugin::Start(void) { RegisterI18n(Phrases); Text2SkinStatus.SetLanguage(Setup.OSDLanguage); diff --git a/text2skin.h b/text2skin.h index b40ea54..e67366c 100644 --- a/text2skin.h +++ b/text2skin.h @@ -21,6 +21,7 @@ public: virtual ~cText2SkinPlugin(); virtual const char *Version(void) { return VERSION; } virtual const char *Description(void) { return tr(DESCRIPTION); } + virtual bool Service(const char *Id, void *Data); 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..73d8a26 100644 --- a/xml/object.c +++ b/xml/object.c @@ -140,10 +140,14 @@ 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() + "/fonts", mFontFace, mFontSize, mFontWidth)) != NULL) return font; @@ -152,6 +156,8 @@ const cFont *cxObject::Font(void) const 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 845b766..c64fbb1 100644 --- a/xml/string.c +++ b/xml/string.c @@ -10,8 +10,12 @@ static const char *Tokens[__COUNT_TOKEN__] = { // Channel Display "ChannelNumber", "ChannelName", "ChannelShortName", "ChannelBouquet", "ChannelPortal", - "ChannelSource", "ChannelID", "NextTimerName", "NextTimerStart", "NextTimerChannel", "TimerConflict", "CurrentRecordingsCount", "PresentStartDateTime", "PresentVPSDateTime", + "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", "RecordingLanguageDescription", "ButtonRed", "ButtonGreen", "ButtonYellow", "ButtonBlue", "CanScrollUp", "CanScrollDown" }; diff --git a/xml/string.h b/xml/string.h index 6c78373..8b3d4a4 100644 --- a/xml/string.h +++ b/xml/string.h @@ -24,17 +24,34 @@ enum exToken { tChannelSource, tTChannelID, // (name clash) // next 9 also in Menu - tNextTimerName, - tNextTimerStart, - tNextTimerChannel, - tTimerConflict, - tCurrentRecordingsCount, 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, @@ -90,6 +107,13 @@ enum exToken { tReplayPositionIndex, tReplayDurationIndex, tReplayPrompt, + tReplayName, + tReplayDateTime, + tReplayShortText, + tReplayDescription, + tReplayLanguageCode, + tReplayLanguageDescription, + tReplayVideoAR, tIsPlaying, tReplayIsPlaying, // alias tIsFastForward, @@ -125,6 +149,8 @@ enum exToken { tRecordingShortText, tRecordingDescription, tRecordingLanguageCode, + tRecordingVideoAR, + tRecordingSize, tRecordingLanguageDescription, // next four also in Channel and Replay display (if supported by vdr/plugin) tButtonRed, -- cgit v1.2.3 From bb39010021b5fd8a1046200839c678afc76227d5 Mon Sep 17 00:00:00 2001 From: Andreas Brugger Date: Sun, 11 Dec 2005 12:00:00 +0100 Subject: 2005-12-11: Version 1.1-cvs_ext-0.3 (vdr-text2skin-1.1-cvs_ext-0.3.diff) - added recording-tokens: RecordingLength, RecordingCuttedLength --- HISTORY | 5 +++ common.c | 140 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ common.h | 4 ++ display.c | 51 ++++++---------------- status.c | 19 +++++--- status.h | 6 +++ xml/string.c | 2 +- xml/string.h | 2 + 8 files changed, 185 insertions(+), 44 deletions(-) diff --git a/HISTORY b/HISTORY index 634b500..fa23b5c 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,11 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +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, diff --git a/common.c b/common.c index f45ed1c..f7011d6 100644 --- a/common.c +++ b/common.c @@ -115,6 +115,146 @@ const cRecording *GetRecordingByName(const char *Name) return NULL; } +const cRecording *GetRecordingByFileName(const char *FileName) +{ + return Recordings.GetByName(FileName); +} + +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; + cReadLine reader; + asprintf(&cmd, "find '%s' -follow -type f -name '*.*'|sort ", FileName); + + FILE *p = popen(cmd, "r"); + int ret=0; + if (p) + { + char *s; + + while ((s = reader.Read(p)) != NULL) + { + 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]; + 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); + } + } + + 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 72b42cd..371c4bc 100644 --- a/display.c +++ b/display.c @@ -1270,43 +1270,20 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) #endif case tRecordingSize: - if (mRecording != NULL) { - bool bRet=false; - long long size = 0; - int nFiles; - struct stat fileinfo; // Holds file information structure - char *cmd = NULL; - cReadLine reader; - asprintf(&cmd, "find '%s' -follow -type f -name '*.*'|sort ", mRecording->FileName()); - - FILE *p = popen(cmd, "r"); - int ret=0; - if (p) - { - char *s; - - while ((s = reader.Read(p)) != NULL) - { - if ((ret=stat(s, &fileinfo)) != -1) - { - size += (long long)fileinfo.st_size; - nFiles++; - } - } - - bRet=true; - } - - pclose(p); - delete cmd; - - return (long)(size / 1024 / 1024); // [MB] - } - else - { - return false; - } - + 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/status.c b/status.c index 8e376b3..f35f45c 100644 --- a/status.c +++ b/status.c @@ -7,6 +7,7 @@ #include "menu.h" #include #include +#include const std::string ReplayNames[__REPLAY_COUNT__] = { "", "normal", "mp3", "mplayer", "dvd", "vcd", "image" }; @@ -53,11 +54,11 @@ void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name) mReplayIsShuffle = Name[2] == 'S'; } } - else if (const cRecording *rec = GetRecordingByName(Name)) - { - mReplay = rec; - mReplayMode = replayNormal; - } + else if (const cRecording *rec = GetRecordingByFileName(cReplayControl::LastReplayed())) + { + mReplay = rec; + mReplayMode = replayNormal; + } else if (strcmp(Name, "DVD") == 0) mReplayMode = replayDVD; else if (strcmp(Name, "VCD") == 0) @@ -308,7 +309,13 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) { const tComponent *c = components->Component(i); if (c->stream != 2) index++; // only audio-streams - if (i == index) return (cxType)c->language; + { + 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(); + } } } } diff --git a/status.h b/status.h index 92c06de..7527aaa 100644 --- a/status.h +++ b/status.h @@ -5,8 +5,14 @@ #ifndef VDR_TEXT2SKIN_STATUS_H #define VDR_TEXT2SKIN_STATUS_H +#ifndef __STL_CONFIG_H +#define __STL_CONFIG_H +#endif + #include "common.h" #include +#include +#include class cText2SkinRender; diff --git a/xml/string.c b/xml/string.c index c64fbb1..76aa317 100644 --- a/xml/string.c +++ b/xml/string.c @@ -46,7 +46,7 @@ static const char *Tokens[__COUNT_TOKEN__] = { "MenuTitle", "MenuGroup", "IsMenuGroup", "MenuItem", "IsMenuItem", "MenuCurrent", "IsMenuCurrent", "MenuText", "RecordingName", "RecordingDateTime", "RecordingTitle", "RecordingShortText", "RecordingDescription", "RecordingLanguageCode", - "RecordingVideoAR", "RecordingSize", + "RecordingVideoAR", "RecordingSize", "RecordingLength", "RecordingCuttedLength", "RecordingLanguageDescription", "ButtonRed", "ButtonGreen", "ButtonYellow", "ButtonBlue", "CanScrollUp", "CanScrollDown" }; diff --git a/xml/string.h b/xml/string.h index 8b3d4a4..098e43b 100644 --- a/xml/string.h +++ b/xml/string.h @@ -151,6 +151,8 @@ enum exToken { tRecordingLanguageCode, tRecordingVideoAR, tRecordingSize, + tRecordingLength, + tRecordingCuttedLength, tRecordingLanguageDescription, // next four also in Channel and Replay display (if supported by vdr/plugin) tButtonRed, -- cgit v1.2.3 From eeda27b9d069161db0261f6e2f51ac9463bde910 Mon Sep 17 00:00:00 2001 From: Andreas Brugger Date: Sun, 18 Dec 2005 12:00:00 +0100 Subject: 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) --- HISTORY | 8 ++++++++ common.c | 2 +- display.c | 6 ++---- status.c | 18 +++++++++++++++++- 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/HISTORY b/HISTORY index fa23b5c..74723c0 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,14 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +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: diff --git a/common.c b/common.c index f7011d6..c6b0a24 100644 --- a/common.c +++ b/common.c @@ -117,7 +117,7 @@ const cRecording *GetRecordingByName(const char *Name) const cRecording *GetRecordingByFileName(const char *FileName) { - return Recordings.GetByName(FileName); + return (FileName) ? Recordings.GetByName(FileName) : NULL; } int GetRecordingSize(const char *FileName) diff --git a/display.c b/display.c index 371c4bc..3db4063 100644 --- a/display.c +++ b/display.c @@ -16,7 +16,7 @@ cText2SkinDisplayChannel::cText2SkinDisplayChannel(cText2SkinLoader *Loader, bool WithInfo): cText2SkinRender(Loader, WithInfo ? cxDisplay::channelInfo : cxDisplay::channelSmall), mFallbackDisplay(NULL), - mChannel(NULL), + mChannel(NULL), mNumber(0), mPresent(NULL), mFollowing(NULL), @@ -116,9 +116,7 @@ cxType cText2SkinDisplayChannel::GetTokenData(const txToken &Token) { switch (Token.Type) { case tChannelNumber: - return mChannel != NULL - ? (cxType)ChannelNumber(mChannel, mNumber) - : (cxType)false; + return (cxType)ChannelNumber(mChannel, mNumber); case tChannelName: return mChannel != NULL diff --git a/status.c b/status.c index f35f45c..b23683a 100644 --- a/status.c +++ b/status.c @@ -53,12 +53,28 @@ void cText2SkinStatus::Replaying(const cControl* /*Control*/, const char *Name) mReplayIsLoop = Name[1] == 'L'; mReplayIsShuffle = Name[2] == 'S'; } - } + } + /* + I tried the following, but this is not thread-safe and it seems that + 'LastReplayed()' is not allways up to date, when cStatus::Replaying() + is called: + else if (const cRecording *rec = GetRecordingByFileName(cReplayControl::LastReplayed())) { mReplay = rec; mReplayMode = replayNormal; } + + so here is a temporary implementation which has the problem, that several + recordings with the same name cannot be seperated. This is deactivated + in Enigma (as it is more ore less useless), till there is a decent fix for + that. + */ + else if (const cRecording *rec = GetRecordingByName(Name)) + { + mReplay = rec; + mReplayMode = replayNormal; + } else if (strcmp(Name, "DVD") == 0) mReplayMode = replayDVD; else if (strcmp(Name, "VCD") == 0) -- cgit v1.2.3 From eb6eaf285edd82c212810f066313f93dc4a8a129 Mon Sep 17 00:00:00 2001 From: Andreas Brugger Date: Sat, 7 Jan 2006 12:00:00 +0100 Subject: 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 --- HISTORY | 7 +++++++ common.c | 10 ++++++++++ display.c | 8 ++++++-- menu.c | 4 ++++ render.c | 6 +++++- status.c | 8 +++++--- status.h | 9 +++------ text2skin.c | 2 ++ text2skin.h | 2 ++ xml/string.c | 2 +- xml/string.h | 4 +++- 11 files changed, 48 insertions(+), 14 deletions(-) diff --git a/HISTORY b/HISTORY index 74723c0..4d9da34 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,13 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +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: diff --git a/common.c b/common.c index c6b0a24..904c417 100644 --- a/common.c +++ b/common.c @@ -128,7 +128,9 @@ int GetRecordingSize(const char *FileName) 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"); @@ -137,7 +139,11 @@ int GetRecordingSize(const char *FileName) { char *s; +#if VDRVERSNUM >= 10318 while ((s = reader.Read(p)) != NULL) +#else + while ((s = readline(p)) != NULL) +#endif { if ((ret=stat(s, &fileinfo)) != -1) { @@ -188,7 +194,11 @@ int GetRecordingLength(const char *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); diff --git a/display.c b/display.c index 3db4063..ac00950 100644 --- a/display.c +++ b/display.c @@ -16,7 +16,7 @@ cText2SkinDisplayChannel::cText2SkinDisplayChannel(cText2SkinLoader *Loader, bool WithInfo): cText2SkinRender(Loader, WithInfo ? cxDisplay::channelInfo : cxDisplay::channelSmall), mFallbackDisplay(NULL), - mChannel(NULL), + mChannel(NULL), mNumber(0), mPresent(NULL), mFollowing(NULL), @@ -116,7 +116,9 @@ cxType cText2SkinDisplayChannel::GetTokenData(const txToken &Token) { switch (Token.Type) { case tChannelNumber: - return (cxType)ChannelNumber(mChannel, mNumber); + return mChannel != NULL + ? (cxType)ChannelNumber(mChannel, mNumber) + : (cxType)false; case tChannelName: return mChannel != NULL @@ -1088,6 +1090,7 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) ? (cxType)mEvent->Description() : (cxType)false; +#if VDRVERSNUM >= 10318 case tPresentLanguageCode: if (mEvent) { @@ -1154,6 +1157,7 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) } } return false; +#endif case tHasVPS: case tChannelHasVPS: diff --git a/menu.c b/menu.c index 8ccaf58..47ca136 100644 --- a/menu.c +++ b/menu.c @@ -11,7 +11,9 @@ 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)); } @@ -22,7 +24,9 @@ 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 4c15f26..78c5ac6 100644 --- a/render.c +++ b/render.c @@ -679,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/status.c b/status.c index b23683a..3df40ab 100644 --- a/status.c +++ b/status.c @@ -267,6 +267,7 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) : (cxType)false; case tTimerConflict: +#if VDRVERSNUM >= 10330 if (Text2SkinSetup.CheckTimerConflict) { bool conflict; @@ -291,7 +292,9 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) { return false; } - +#endif + +#if VDRVERSNUM >= 10325 case tReplayName: return mReplay != NULL ? (cxType)mReplay->Name() @@ -356,7 +359,6 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) } return false; - /* case tReplayVideoAR: if (mReplay) { @@ -378,7 +380,7 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) } } return false; - */ +#endif case tCurrentRecording: Dprintf("token attrib type is: %d, number: %d\n", Token.Attrib.Type, Token.Attrib.Number); diff --git a/status.h b/status.h index 7527aaa..a39d680 100644 --- a/status.h +++ b/status.h @@ -5,14 +5,11 @@ #ifndef VDR_TEXT2SKIN_STATUS_H #define VDR_TEXT2SKIN_STATUS_H -#ifndef __STL_CONFIG_H -#define __STL_CONFIG_H -#endif - -#include "common.h" -#include #include #include +#include "common.h" +#include + class cText2SkinRender; diff --git a/text2skin.c b/text2skin.c index 6ca80d0..cf4f618 100644 --- a/text2skin.c +++ b/text2skin.c @@ -24,6 +24,7 @@ cText2SkinPlugin::cText2SkinPlugin(void) { cText2SkinPlugin::~cText2SkinPlugin() { } +#if VDRVERSNUM >= 10330 bool cText2SkinPlugin::Service(const char *Id, void *Data) { if (strcmp(Id,"Text2Skin-TTF") == 0) { @@ -34,6 +35,7 @@ bool cText2SkinPlugin::Service(const char *Id, void *Data) } return false; } +#endif bool cText2SkinPlugin::Start(void) { RegisterI18n(Phrases); diff --git a/text2skin.h b/text2skin.h index e67366c..cdd95ca 100644 --- a/text2skin.h +++ b/text2skin.h @@ -21,7 +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/string.c b/xml/string.c index 76aa317..b8fc1f9 100644 --- a/xml/string.c +++ b/xml/string.c @@ -46,7 +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", + "RecordingVideoAR", "RecordingSize", "RecordingLength", "RecordingCuttedLength", "OsdWidth", "OsdHeight", "RecordingLanguageDescription", "ButtonRed", "ButtonGreen", "ButtonYellow", "ButtonBlue", "CanScrollUp", "CanScrollDown" }; diff --git a/xml/string.h b/xml/string.h index 098e43b..68cd8fa 100644 --- a/xml/string.h +++ b/xml/string.h @@ -153,6 +153,8 @@ enum exToken { tRecordingSize, tRecordingLength, tRecordingCuttedLength, + tOsdWidth, + tOsdHeight, tRecordingLanguageDescription, // next four also in Channel and Replay display (if supported by vdr/plugin) tButtonRed, @@ -161,7 +163,7 @@ enum exToken { tButtonBlue, tCanScrollUp, tCanScrollDown, - + #define __COUNT_TOKEN__ (tCanScrollDown + 1) }; -- cgit v1.2.3 From c1bf83aec2961a4e84dbc1c36042bd985f044a91 Mon Sep 17 00:00:00 2001 From: Andreas Brugger Date: Sat, 4 Feb 2006 11:49:02 +0100 Subject: 2006-02-04: Version 1.1-cvs_ext-0.7 (vdr-text2skin-1.1-cvs_ext-0.7.diff) - changed the routines to determine the next timers - added the possibility to have a scrollbar in every menu - not fully implemented yet (to position in menu-lists is not necessarily correct, if there are more items with the same osd-text) --- HISTORY | 7 +++++ common.c | 27 +++++++------------ display.h | 3 ++- render.c | 1 + render.h | 13 ++++++++- status.c | 92 +++++++++++++++++++++++++++++++++++++++++---------------------- status.h | 43 +++++++++++++++++------------ 7 files changed, 117 insertions(+), 69 deletions(-) diff --git a/HISTORY b/HISTORY index 16d54d9..8e2ccb8 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,13 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +2006-02-04: Version 1.1-cvs_ext-0.7 (vdr-text2skin-1.1-cvs_ext-0.7.diff) + +- changed the routines to determine the next timers +- added the possibility to have a scrollbar in every menu - not fully + implemented yet (to position in menu-lists is not necessarily correct, + if there are more items with the same osd-text) + 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 diff --git a/common.c b/common.c index 904c417..b9e1daf 100644 --- a/common.c +++ b/common.c @@ -121,6 +121,14 @@ const cRecording *GetRecordingByFileName(const char *FileName) } int GetRecordingSize(const char *FileName) +#if VDRVERSNUM >= 10338 +// use VDR's routine +{ + const cRecording *rec = GetRecordingByFileName(FileName); + return (rec) ? DirSizeMB(FileName) : 0; +} +#else +// use our own approach { if (FileName != NULL) { bool bRet=false; @@ -165,6 +173,7 @@ int GetRecordingSize(const char *FileName) return 0; } } +#endif int GetRecordingLength(const char *FileName) { @@ -217,27 +226,9 @@ int GetRecordingCuttedLength(const char *FileName) 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 diff --git a/display.h b/display.h index 9f592c2..3865431 100644 --- a/display.h +++ b/display.h @@ -169,7 +169,8 @@ protected: virtual void SetEditableWidth(int Width) { cSkinDisplayMenu::SetEditableWidth(Width); } virtual int MaxItems(void) { return mMaxItems; } virtual void SetMaxItems(int MaxItems) { mMaxItems = MaxItems; } - + virtual int GetMaxItems(void) { return mMaxItems; } + public: cText2SkinDisplayMenu(cText2SkinLoader *Loader); virtual ~cText2SkinDisplayMenu(); diff --git a/render.c b/render.c index 78c5ac6..f523e63 100644 --- a/render.c +++ b/render.c @@ -263,6 +263,7 @@ void cText2SkinRender::DrawObject(const cxObject *Object) // there is no "next tab", use the rightmost edge obj.mPos2.x += Object->mPos1.x; SetEditableWidth(obj.Size().w); + //printf("EditableWidth von '%s': %d Pixels\n", obj.Text().c_str(), obj.Size().w); } obj.mPos2.y += Object->mPos1.y + yoffset; diff --git a/render.h b/render.h index b0e50cf..4748a0d 100644 --- a/render.h +++ b/render.h @@ -134,8 +134,19 @@ public: static bool ItemColor(const std::string &Color, tColor &Result); static std::string ImagePath(const std::string &Filename); static cxType GetToken(const txToken &Token); + + // provide scrollbar in every menu + struct tMenuScrollbar + { + int current; + int total; + std::vector items; - // update infos + tMenuScrollbar(void) : current(0), total(0) {} + //bool available(void) { printf("%d / %d\n", total, GetMaxItems(); return total > GetMaxItems(); } + } mMenuScrollbar; + + // update infos (e.g. timerConflict) struct tUpdate { bool timerConflict; diff --git a/status.c b/status.c index 9155bf6..0616f7a 100644 --- a/status.c +++ b/status.c @@ -134,18 +134,56 @@ void cText2SkinStatus::OsdClear(void) mLastLanguage = Setup.OSDLanguage; cxString::Reparse(); } + + if (mRender != NULL) + { + mRender->mMenuScrollbar.total = 0; + } } void cText2SkinStatus::OsdCurrentItem(const char *Text) { if (mRender != NULL) { + // update infos + cText2SkinRender::tUpdate *u = &mRender->mUpdate; static std::string lastItem; - lastItem = mRender->mUpdate.currentItem; - mRender->mUpdate.currentItem = Text; - mRender->mUpdate.resetMarquee = true; - mRender->mUpdate.foundFirstItem = false; + lastItem = u->currentItem; + u->currentItem = Text; + u->resetMarquee = true; + u->foundFirstItem = false; + + // find current item in scrollbar + cText2SkinRender::tMenuScrollbar *sb = &mRender->mMenuScrollbar; + for (int i = 0; i < sb->total; i++) + { + if (sb->items[i] == Text) + { + sb->current = i; + break; + } + } + } +} + +void cText2SkinStatus::OsdItem(const char *Text, int Index) +{ + if (mRender != NULL) + { + cText2SkinRender::tMenuScrollbar *sb = &mRender->mMenuScrollbar; + + if ((unsigned int)Index < sb->items.size()) + { + sb->items[Index] = Text; + } + else + { + sb->items.push_back(Text); + sb->total = Index + 1; + } + + if (Index + 1 > sb->total) sb->total = Index + 1; } } @@ -155,31 +193,21 @@ void cText2SkinStatus::UpdateEvents(void) { mRender->mUpdate.events = false; - mEvents.clear(); + mEvents.Clear(); Timers.IncBeingEdited(); - for (cTimer *tim = Timers.First(); tim != NULL; tim = Timers.Next(tim)) + for (cTimer *tim = Timers.First(); tim; tim = Timers.Next(tim)) { if (tim->HasFlags(tfActive)) { int i = 0; cTimer dummy; - dummy = *tim; // copy the timer + dummy = *tim; do { - tEvent ev; + mEvents.Add(new tEvent(&dummy)); - 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 @@ -195,13 +223,13 @@ void cText2SkinStatus::UpdateEvents(void) } Timers.DecBeingEdited(); - std::sort(mEvents.rbegin(), mEvents.rend()); + mEvents.Sort(); } } cxType cText2SkinStatus::GetTokenData(const txToken &Token) { - uint event = 0; + int event = 0; switch (Token.Type) { case tReplayMode: @@ -213,8 +241,8 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) event++; case tCurrentEventsTitle1: UpdateEvents(); - return mEvents.size() > event - ? (cxType)mEvents[event].title.c_str() + return mEvents.Count() > event + ? (cxType)mEvents.Get(event)->title.c_str() : (cxType)false; case tCurrentEventsStartDateTime3: @@ -223,8 +251,8 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) event++; case tCurrentEventsStartDateTime1: UpdateEvents(); - return mEvents.size() > event - ? (cxType)TimeType(mEvents[event].startTime, Token.Attrib.Text) + return mEvents.Count() > event + ? (cxType)TimeType(mEvents.Get(event)->startTime, Token.Attrib.Text) : (cxType)false; case tCurrentEventsStopDateTime3: @@ -233,8 +261,8 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) event++; case tCurrentEventsStopDateTime1: UpdateEvents(); - return mEvents.size() > event - ? (cxType)TimeType(mEvents[event].stopTime, Token.Attrib.Text) + return mEvents.Count() > event + ? (cxType)TimeType(mEvents.Get(event)->stopTime, Token.Attrib.Text) : (cxType)false; case tCurrentEventsChannelNumber3: @@ -243,8 +271,8 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) event++; case tCurrentEventsChannelNumber1: UpdateEvents(); - return mEvents.size() > event - ? (cxType)mEvents[event].channelNumber + return mEvents.Count() > event + ? (cxType)mEvents.Get(event)->channelNumber : (cxType)false; case tCurrentEventsChannelName3: @@ -253,8 +281,8 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) event++; case tCurrentEventsChannelName1: UpdateEvents(); - return mEvents.size() > event - ? (cxType)mEvents[event].channelName.c_str() + return mEvents.Count() > event + ? (cxType)mEvents.Get(event)->channelName.c_str() : (cxType)false; case tCurrentEventsIsRecording3: @@ -263,8 +291,8 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) event++; case tCurrentEventsIsRecording1: UpdateEvents(); - return mEvents.size() > event - ? (cxType)mEvents[event].isRecording + return mEvents.Count() > event + ? (cxType)mEvents.Get(event)->isRecording : (cxType)false; case tTimerConflict: diff --git a/status.h b/status.h index 2047595..8bd0f96 100644 --- a/status.h +++ b/status.h @@ -5,8 +5,6 @@ #ifndef VDR_TEXT2SKIN_STATUS_H #define VDR_TEXT2SKIN_STATUS_H -#include -#include #include "common.h" #include @@ -30,22 +28,32 @@ public: typedef std::string tRecordingInfo; typedef std::vector tRecordings; - struct tEvent + struct tEvent : public cListObject { - std::string title; - bool isRecording; - std::string channelName; - int channelNumber; - time_t startTime; - time_t stopTime; - int priority; + time_t startTime; + time_t stopTime; + int channelNumber; + std::string channelName; + int priority; + bool isRecording; + std::string title; - bool tEvent::operator< (const tEvent &b) const + tEvent(cTimer *timer) : + startTime(timer->StartTime()), + stopTime(timer->StopTime()), + channelNumber(timer->Channel()->Number()), + channelName(timer->Channel()->Name()), + priority(timer->Priority()), + isRecording(timer->Recording()), + title(timer->File()) {} + + virtual int Compare(const cListObject &listObj) const { - int r = startTime - b.startTime; - r = r == 0 ? b.priority - priority : r; - return r > 0 ? true : false; - }; + tEvent *e = (tEvent *)&listObj; + int r = startTime - e->startTime; + if (r == 0) r = e->priority - priority; + return r; + } }; typedef std::vector tEvents; @@ -58,8 +66,8 @@ private: bool mReplayIsLoop; bool mReplayIsShuffle; tRecordings mRecordings; - tEvents mEvents; const cRecording *mReplay; + cList mEvents; cMutex mRecordingsLock; uint mCurrentRecording; uint mNextRecording; @@ -76,7 +84,8 @@ protected: #endif virtual void OsdClear(void); virtual void OsdCurrentItem(const char *Text); - + virtual void OsdItem(const char *Text, int Index); + public: cText2SkinStatus(void); -- cgit v1.2.3 From 8d32cf88bbe5b69a2710029cdaa896470a0fe20c Mon Sep 17 00:00:00 2001 From: Andreas Brugger Date: Sat, 4 Feb 2006 18:25:22 +0100 Subject: 2006-02-04: Version 1.1-cvs_ext-0.8 (vdr-text2skin-1.1-cvs_ext-0.8.diff) - added a configuration option for showing the scrollbar in the menus and finished implementation --- HISTORY | 5 +++++ display.c | 2 ++ i18n.c | 25 +++++++++++++++++++++++++ menu.c | 2 ++ render.c | 41 +++++++++++++++++++++++++++++++++++++---- render.h | 17 +++++++++++++---- setup.c | 4 +++- setup.h | 3 ++- status.c | 24 ++++++++++++++---------- 9 files changed, 103 insertions(+), 20 deletions(-) diff --git a/HISTORY b/HISTORY index 8e2ccb8..bc2c26f 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,11 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +2006-02-04: Version 1.1-cvs_ext-0.8 (vdr-text2skin-1.1-cvs_ext-0.8.diff) + +- added a configuration option for showing the scrollbar in the menus and + finished implementation + 2006-02-04: Version 1.1-cvs_ext-0.7 (vdr-text2skin-1.1-cvs_ext-0.7.diff) - changed the routines to determine the next timers diff --git a/display.c b/display.c index 227b41a..7dc8f5c 100644 --- a/display.c +++ b/display.c @@ -873,6 +873,8 @@ void cText2SkinDisplayMenu::SetItem(const char *Text, int Index, bool Current, b mCurrentItem = Index; SetDirty(); } + + if (Current) mRender->mMenuScrollbar.currentOnScreen = (uint)Index; UpdateUnlock(); } diff --git a/i18n.c b/i18n.c index ab583fc..295c677 100644 --- a/i18n.c +++ b/i18n.c @@ -125,6 +125,31 @@ const tI18nPhrase Phrases[] = { #if VDRVERSNUM >= 10313 "", #endif +#if VDRVERSNUM >= 10316 + "", +#endif + }, + { "Show scrollbar in the menus", + "Zeige Bildlaufleiste in Menüs", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", +#if VDRVERSNUM >= 10313 + "", +#endif #if VDRVERSNUM >= 10316 "", #endif diff --git a/menu.c b/menu.c index 47ca136..e8f2306 100644 --- a/menu.c +++ b/menu.c @@ -9,6 +9,7 @@ cText2SkinSetupPage::cText2SkinSetupPage(void) { mData = Text2SkinSetup; + Add(new cMenuEditBoolItem(tr("Show scrollbar in the menus"), &mData.MenuScrollbar, tr("no"), tr("yes"))); 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 @@ -22,6 +23,7 @@ cText2SkinSetupPage::~cText2SkinSetupPage() { } void cText2SkinSetupPage::Store(void) { + SetupStore("MenuScrollbar", mData.MenuScrollbar); SetupStore("MarqueeLeftRight", mData.MarqueeLeftRight); SetupStore("MarqueeReset", mData.MarqueeReset); #if VDRVERSNUM >= 10330 diff --git a/render.c b/render.c index f523e63..06096b1 100644 --- a/render.c +++ b/render.c @@ -11,7 +11,6 @@ #include "screen.h" #include "display.h" #include "scroller.h" -#include "setup.h" #include "xml/display.h" #include #include @@ -222,7 +221,8 @@ void cText2SkinRender::DrawObject(const cxObject *Object) uint itemheight = item->Size().h; uint maxitems = areasize.h / itemheight; uint yoffset = 0; - + + mMenuScrollbar.maxItems = maxitems; SetMaxItems(maxitems); //Dprintf("setmaxitems %d\n", maxitems); for (uint i = 0; i < maxitems; ++i, yoffset += itemheight) { for (uint j = 1; j < Object->Objects(); ++j) { @@ -564,6 +564,29 @@ void cText2SkinRender::DrawScrollbar(const txPoint &Pos, const txSize &Size, con DrawRectangle(sp, ss, Fg); } } + else if (mMenuScrollbar.Available()) + { + DrawRectangle(Pos, Size, Bg); + txPoint sbPoint = Pos; + txSize sbSize = Size; + if (sbSize.h > sbSize.w) + { + // -1 to get at least 1 pixel height + double top = double(mMenuScrollbar.Top()) / mMenuScrollbar.total * (sbSize.h - 1); + double bottom = double(mMenuScrollbar.Bottom()) / mMenuScrollbar.total * (sbSize.h - 1); + sbPoint.y += (uint)top; + sbSize.h -= (uint)top + (uint)bottom; + } + else + { + // -1 to get at least 1 pixel height + double left = double(mMenuScrollbar.Top()) / mMenuScrollbar.total * (sbSize.w - 1); + double right = double(mMenuScrollbar.Bottom()) / mMenuScrollbar.total * (sbSize.w - 1); + sbPoint.x += (uint)left; + sbSize.w -= (uint)left + (uint)right; + } + DrawRectangle(sbPoint, sbSize, Fg); + } } txPoint cText2SkinRender::Transform(const txPoint &Pos) @@ -675,9 +698,19 @@ cxType cText2SkinRender::GetTokenData(const txToken &Token) case tDateTime: return TimeType(time(NULL), Token.Attrib.Text); - case tCanScrollUp: return mScroller != NULL && mScroller->CanScrollUp(); + case tCanScrollUp: + { + if (mScroller) return mScroller->CanScrollUp(); + else if (mMenuScrollbar.Available()) return mMenuScrollbar.CanScrollUp(); + else return false; + } - case tCanScrollDown: return mScroller != NULL && mScroller->CanScrollDown(); + case tCanScrollDown: + { + if (mScroller) return mScroller->CanScrollDown(); + else if (mMenuScrollbar.Available()) return mMenuScrollbar.CanScrollDown(); + else return false; + } case tIsRecording: return cRecordControls::Active(); diff --git a/render.h b/render.h index 4748a0d..cee31ab 100644 --- a/render.h +++ b/render.h @@ -7,6 +7,7 @@ #include "common.h" #include "scroller.h" +#include "setup.h" #include "xml/skin.h" #include "xml/type.h" #include @@ -47,6 +48,7 @@ private: std::string mBasePath; bool mDirty; + uint mMaxItems; cSkin *mFallback; // update thread @@ -115,6 +117,7 @@ protected: virtual bool HasTabText(int Index, int n) { return false; } virtual void SetEditableWidth(int Width) {} virtual void SetMaxItems(int MaxItems) {} + inline int GetmMaxItems(void) { return mMaxItems; } // functions for display renderer to control behaviour void Flush(bool Force = false); @@ -138,12 +141,18 @@ public: // provide scrollbar in every menu struct tMenuScrollbar { - int current; - int total; + uint current; // overall (0 ... toal-1) + uint currentOnScreen; // on the current screen (0 ... maxItems-1) + uint total; + uint maxItems; // viewable on current screen std::vector items; - tMenuScrollbar(void) : current(0), total(0) {} - //bool available(void) { printf("%d / %d\n", total, GetMaxItems(); return total > GetMaxItems(); } + tMenuScrollbar(void) : current(0), currentOnScreen(0), total(0), maxItems(0) {} + bool Available(void) { return Text2SkinSetup.MenuScrollbar ? total > maxItems : false; } + uint Top(void) { return current - currentOnScreen; } + uint Bottom(void) { return total - Top() - maxItems; } + bool CanScrollUp(void) { return Text2SkinSetup.MenuScrollbar ? Top() > 0 : false; } + bool CanScrollDown(void) { return Text2SkinSetup.MenuScrollbar ? Bottom() > 0 : false; } } mMenuScrollbar; // update infos (e.g. timerConflict) diff --git a/setup.c b/setup.c index 504c4e4..a2ea090 100644 --- a/setup.c +++ b/setup.c @@ -9,6 +9,7 @@ cText2SkinSetup Text2SkinSetup; // --- cText2SkinSetup -------------------------------------------------------- cText2SkinSetup::cText2SkinSetup(void) { + MenuScrollbar = false; MarqueeLeftRight = true; MarqueeReset = false; CheckTimerConflict = false; @@ -16,7 +17,8 @@ cText2SkinSetup::cText2SkinSetup(void) { } bool cText2SkinSetup::SetupParse(const char *Name, const char *Value) { - if (strcmp(Name, "MarqueeLeftRight") == 0) MarqueeLeftRight = atoi(Value); + if (strcmp(Name, "MenuScrollbar") == 0) MenuScrollbar = atoi(Value); + else 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); diff --git a/setup.h b/setup.h index a21b15e..cee476a 100644 --- a/setup.h +++ b/setup.h @@ -12,7 +12,8 @@ public: cText2SkinSetup(void); bool SetupParse(const char *Name, const char *Value); - + + int MenuScrollbar; int MarqueeLeftRight; int MarqueeReset; int CheckTimerConflict; diff --git a/status.c b/status.c index 0616f7a..95e4bec 100644 --- a/status.c +++ b/status.c @@ -155,13 +155,16 @@ void cText2SkinStatus::OsdCurrentItem(const char *Text) u->foundFirstItem = false; // find current item in scrollbar - cText2SkinRender::tMenuScrollbar *sb = &mRender->mMenuScrollbar; - for (int i = 0; i < sb->total; i++) + if (Text2SkinSetup.MenuScrollbar) { - if (sb->items[i] == Text) + cText2SkinRender::tMenuScrollbar *sb = &mRender->mMenuScrollbar; + for (uint i = 0; i < sb->total; i++) { - sb->current = i; - break; + if (sb->items[i] == Text) + { + sb->current = i; + break; + } } } } @@ -169,21 +172,22 @@ void cText2SkinStatus::OsdCurrentItem(const char *Text) void cText2SkinStatus::OsdItem(const char *Text, int Index) { - if (mRender != NULL) + if (mRender && Text2SkinSetup.MenuScrollbar) { + uint curr = (uint)Index; cText2SkinRender::tMenuScrollbar *sb = &mRender->mMenuScrollbar; - if ((unsigned int)Index < sb->items.size()) + if (curr < sb->items.size()) { - sb->items[Index] = Text; + sb->items[curr] = Text; } else { sb->items.push_back(Text); - sb->total = Index + 1; + sb->total = curr + 1; } - if (Index + 1 > sb->total) sb->total = Index + 1; + if (curr + 1 > sb->total) sb->total = curr + 1; } } -- cgit v1.2.3 From 74a5cc8e14900d48386e33cb576f154a6dd7e557 Mon Sep 17 00:00:00 2001 From: Andreas Brugger Date: Sun, 19 Nov 2006 16:58:14 +0100 Subject: 2006-11-19: Version 1.1-cvs_ext-0.9 (vdr-text2skin-1.1-cvs_ext-0.9.diff) - added a test-feature to search for reruns of a program and add the information to the extended epg-info (trigger DEVELOPMENT_FEATURES). This uses a service-interface of the epgsearch-plugin "Epgsearch-searchresults-v1.0" - the timer-conflicts are now checked with epgsearch (service-interface "Epgsearch-lastconflictinfo-v1.0", as it works more reliable and is supported by the plugin author - the extended epg-info and the recording-info are extended by AUX-Infos (configurable) there is also an option to strip known tags - the tab-widths are scaled for taking into account that different TT-Fonts have a different width than the default font from VDR - added tokens for signal-info: FrontendSTR, FrontendSNR, FrontendHasLock, FrontendHasSignal - changed token TimerConflict to TimerConflicts - added token PresentEventID for EPG-images - added tokens for recordings: RecordingFilename, RecordingPriority, RecordingLifetime - removed Text2skin.diff from the rotor-plugin --- HISTORY | 22 +++++++ Makefile | 9 ++- common.c | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ common.h | 45 ++++++++++++++ display.c | 92 ++++++++++++++++++++++++++--- display.h | 2 + graphtft/font.c | 13 +++-- i18n.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++- menu.c | 23 ++++++++ menu.h | 1 + render.c | 24 +++++++- setup.c | 12 ++++ setup.h | 6 ++ status.c | 64 +++++++++++--------- status.h | 2 +- text2skin.c | 32 ++++++---- text2skin.h | 5 +- xml/object.c | 6 -- xml/object.h | 1 - xml/string.c | 7 ++- xml/string.h | 10 +++- xml/xml.c | 2 +- 22 files changed, 635 insertions(+), 75 deletions(-) diff --git a/HISTORY b/HISTORY index bc2c26f..b8b96de 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,28 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +2006-11-19: Version 1.1-cvs_ext-0.9 (vdr-text2skin-1.1-cvs_ext-0.9.diff) + +- added a test-feature to search for reruns of a program and add the + information to the extended epg-info (trigger DEVELOPMENT_FEATURES). + This uses a service-interface of the epgsearch-plugin + "Epgsearch-searchresults-v1.0" +- the timer-conflicts are now checked with epgsearch (service-interface + "Epgsearch-lastconflictinfo-v1.0", as it works more reliable and is + supported by the plugin author +- the extended epg-info and the recording-info are extended by AUX-Infos + (configurable) + there is also an option to strip known tags +- the tab-widths are scaled for taking into account that different TT-Fonts + have a different width than the default font from VDR +- added tokens for signal-info: + FrontendSTR, FrontendSNR, FrontendHasLock, FrontendHasSignal +- changed token TimerConflict to TimerConflicts +- added token PresentEventID for EPG-images +- added tokens for recordings: + RecordingFilename, RecordingPriority, RecordingLifetime +- removed Text2skin.diff from the rotor-plugin + 2006-02-04: Version 1.1-cvs_ext-0.8 (vdr-text2skin-1.1-cvs_ext-0.8.diff) - added a configuration option for showing the scrollbar in the menus and diff --git a/Makefile b/Makefile index a06aa12..e143762 100644 --- a/Makefile +++ b/Makefile @@ -2,8 +2,11 @@ # Imlib2 for loading images. BEWARE that you can not use GraphTFT together with # Text2Skin if you use Imlib2! (That's why I actually implemented ImageMagick) +#DEBUG=1 +#BENCH=1 + HAVE_IMAGEMAGICK=1 -#HAVE_IMLIB2=1 +#HAVE_IMLIB2=1 # not recommended # comment this out if you don't want to use FreeType font rendering @@ -62,6 +65,10 @@ OBJS = $(PLUGIN).o loader.o display.o render.o common.o bitmap.o \ ### Includes and Defines (add further entries here): +ifdef DEVELOPMENT_FEATURES + DEFINES += -DDEVELOPMENT_FEATURES +endif + ifdef HAVE_IMLIB2 DEFINES += -DHAVE_IMLIB2 LIBS += -lImlib2 diff --git a/common.c b/common.c index b9e1daf..d5bb0b4 100644 --- a/common.c +++ b/common.c @@ -3,7 +3,13 @@ */ #include "common.h" +#include #include +#include +#include +#include + +#define FRONTEND_DEVICE "/dev/dvb/adapter%d/frontend%d" const std::string &SkinPath(void) { @@ -69,6 +75,14 @@ const char *ChannelShortName(const cChannel *Channel, int Number) return buffer; } + +const char *EventType(uint Number) +{ + static char buffer[25]; + buffer[0] = '\0'; + snprintf(buffer, sizeof(buffer), "%d", Number); + return buffer; +} /* const char *ChannelBouquet(const cChannel *Channel, int Number) { static char buffer[256]; @@ -120,6 +134,137 @@ const cRecording *GetRecordingByFileName(const char *FileName) return (FileName) ? Recordings.GetByName(FileName) : NULL; } +int GetFrontendSTR(void) +{ + uint16_t value = 0; + char *dev = NULL; + + asprintf(&dev, FRONTEND_DEVICE, cDevice::ActualDevice()->CardIndex(), 0); + int fe = open(dev, O_RDONLY | O_NONBLOCK); + free(dev); + if (fe >= 0) { + CHECK(ioctl(fe, FE_READ_SIGNAL_STRENGTH, &value)); + close(fe); + } + return value / 655; +} + +int GetFrontendSNR(void) +{ + uint16_t value = 0; + char *dev = NULL; + + asprintf(&dev, FRONTEND_DEVICE, cDevice::ActualDevice()->CardIndex(), 0); + int fe = open(dev, O_RDONLY | O_NONBLOCK); + free(dev); + if (fe >= 0) { + CHECK(ioctl(fe, FE_READ_SNR, &value)); + close(fe); + } + return value / 655; +} + +bool GetFrontendHasLock(void) +{ + uint16_t value = 0; + char *dev = NULL; + + asprintf(&dev, FRONTEND_DEVICE, cDevice::ActualDevice()->CardIndex(), 0); + int fe = open(dev, O_RDONLY | O_NONBLOCK); + free(dev); + if (fe >= 0) { + CHECK(ioctl(fe, FE_READ_STATUS, &value)); + close(fe); + } + return value & FE_HAS_LOCK; +} + +bool GetFrontendHasSignal(void) +{ + uint16_t value = 0; + char *dev = NULL; + + asprintf(&dev, FRONTEND_DEVICE, cDevice::ActualDevice()->CardIndex(), 0); + int fe = open(dev, O_RDONLY | O_NONBLOCK); + free(dev); + if (fe >= 0) { + CHECK(ioctl(fe, FE_READ_STATUS, &value)); + close(fe); + } + return value & FE_HAS_SIGNAL; +} + +std::string AddExtInfoToDescription(const char *Title, const char *ShortText, const char *Description, const char *Aux, bool StripAux) +{ + // max. width so lines don't get wrapped + #define MAX_CHARS 50 + + // prepare the description + std::stringstream desc(""); + + if (!isempty(Description)) { + // it seems that sometimes the description ends with a newline + // and sometimes it does not + std::string buf(Description); + while (!buf.empty() && buf[buf.size() - 1] == '\n') buf.erase(buf.size() - 1); + desc << buf << "\n"; // keep one newline + } + +#ifdef DEVELOPMENT_FEATURES + // try to find a rerun of the show using epgsearch-service + if (!isempty(Title)) { + Epgsearch_searchresults_v1_0 data; + data.query = strdup(Title); + data.mode = 0; + data.channelNr = 0; + data.useTitle = true; + data.useSubTitle = false; + data.useDescription = false; + if (cPluginManager::CallFirstService("Epgsearch-searchresults-v1.0", &data)) { + cList* list = data.pResultList; + if (list) { + // die aktuelle Sendung wird noch als WH angezeigt !!! + if (!desc.str().empty()) desc << "\n"; + desc << tr("RERUNS OF THIS SHOW") << ":\n"; + int i = 0; + for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = + list->First(); r && i < 5; r = list->Next(r)) { + i++; + std::stringstream buf; + buf << " - "; + buf << *DayDateTime(r->event->StartTime()); + buf << ": " << r->event->Title(); + if (!isempty(r->event->ShortText())) buf << "~" << r->event->ShortText(); + desc << FitToWidth(buf, MAX_CHARS) << "\n"; + } + delete list; + } + } + } +#endif // DEVELOPMENT_FEATURES + + // Add the AUX-Info of the Recording + if (Aux) { + if (StripAux) { + std::string auxRaw(Aux); + std::string auxEpgsearch = StripXmlTag(auxRaw, "epgsearch"); + if (!auxEpgsearch.empty()) { + if (!desc.str().empty()) desc << "\n"; + desc << tr("AUXILIARY INFOS") << ":\n"; + std::stringstream buf; + buf << " - " << tr("Search timer") << ": " << StripXmlTag(auxRaw, "Search timer"); + desc << FitToWidth(buf, MAX_CHARS) << "\n"; + } + } else { + if (!desc.str().empty()) desc << "\n"; + desc << tr("AUXILIARY INFOS") << ":\n"; + desc << Aux << "\n"; + } + } + + return desc.str(); +} + int GetRecordingSize(const char *FileName) #if VDRVERSNUM >= 10338 // use VDR's routine @@ -404,3 +549,36 @@ void SkipQuotes(std::string &Value) { else esyslog("ERROR: text2skin: missing closing %c", quote); } + +std::string FitToWidth(std::string &Line, uint Width) { + std::string buf(Line); + if (buf.size() > Width) { + buf.erase(Width - 3); + buf.append("..."); + } + return buf; +} + +std::string FitToWidth(std::stringstream &Line, uint Width) { + std::string buf(Line.str()); + if (buf.size() > Width) { + buf.erase(Width - 3); + buf.append("..."); + } + return buf; +} + +std::string StripXmlTag(std::string &Line, const char *Tag) { + // set the search strings + std::stringstream strStart, strStop; + strStart << "<" << Tag << ">"; + strStop << ""; + // find the strings + std::string::size_type locStart = Line.find(strStart.str()); + std::string::size_type locStop = Line.find(strStop.str()); + if (locStart == std::string::npos || locStop == std::string::npos) return ""; + // extract relevant text + int pos = locStart + strStart.str().size(); + int len = locStop - pos; + return len < 0 ? "" : Line.substr(pos, len); +} diff --git a/common.h b/common.h index 4c9e74d..f4ec281 100644 --- a/common.h +++ b/common.h @@ -9,6 +9,7 @@ #include #include #include +#include #if defined(DEBUG) || defined(BENCH) # ifdef DEBUG @@ -24,6 +25,9 @@ # define Ddiff(t,x) #endif +#define DStartBench(x) uint64 bench_##x = time_ms() +#define DShowBench(t,x) fprintf(stderr, "%s took %llu ms\n", t, time_ms() - bench_##x) + #if VDRVERSNUM >= 10318 # define time_ms() cTimeMs::Now() # define Apid1() Apid(0) @@ -47,11 +51,17 @@ const std::string &SkinPath(void); const char *ChannelNumber(const cChannel *Channel, int Number); const char *ChannelName(const cChannel *Channel, int Number); const char *ChannelShortName(const cChannel *Channel, int Number); +const char *EventType(uint Number); //const char *ChannelBouquet(const cChannel *Channel, int Number); bool StoppedTimer(const char *Name); const cRecording *GetRecordingByName(const char *Name); const cRecording *GetRecordingByFileName(const char *FileName); +int GetFrontendSTR(void); // Signal strength [%] +int GetFrontendSNR(void); // Signal to Noise ratio [%] +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] @@ -63,5 +73,40 @@ bool ParseVar(const char *Text, const char *Name, std::string &Value); bool ParseVar(const char *Text, const char *Name, tColor *Value); void SkipQuotes(std::string &Value); +std::string FitToWidth(std::string &Line, uint Width); +std::string FitToWidth(std::stringstream &Line, uint Width); +std::string StripXmlTag(std::string &Line, const char *Tag); + +// Data structure for service "Epgsearch-searchresults-v1.0" +struct Epgsearch_searchresults_v1_0 +{ +// in + char* query; // search term + int mode; // search mode (0=phrase, 1=and, 2=or, 3=regular expression) + int channelNr; // channel number to search in (0=any) + bool useTitle; // search in title + bool useSubTitle; // search in subtitle + bool useDescription; // search in description +// out + + class cServiceSearchResult : public cListObject + { + public: + const cEvent* event; + cServiceSearchResult(const cEvent* Event) : event(Event) {} + }; + + cList* pResultList; // pointer to the results +}; + +// Data structure for service "Epgsearch-lastconflictinfo-v1.0" +struct Epgsearch_lastconflictinfo_v1_0 +{ +// in +// out + time_t nextConflict; // next conflict date, 0 if none + int relevantConflicts; // number of relevant conflicts + int totalConflicts; // total number of conflicts +}; #endif // VDR_TEXT2SKIN_COMMON_H diff --git a/display.c b/display.c index 7dc8f5c..fa71016 100644 --- a/display.c +++ b/display.c @@ -10,6 +10,7 @@ #include "common.h" #include "xml/string.h" #include +#include // --- cText2SkinDisplayChannel ----------------------------------------------- @@ -772,7 +773,9 @@ void cText2SkinDisplayMenu::Clear(void) mItems.clear(); mCurrentItem = (uint)-1; mEvent = NULL; + ExtPresentDescription = ""; mRecording = NULL; + ExtRecordingDescription = ""; mText = ""; cText2SkinRender::Clear(); SetDirty(); @@ -888,6 +891,7 @@ void cText2SkinDisplayMenu::SetEvent(const cEvent *Event) UpdateLock(); if (mEvent != Event) { mEvent = Event; + ExtPresentDescription = ""; if (mEvent != NULL) SetDirty(); } @@ -905,6 +909,7 @@ void cText2SkinDisplayMenu::SetRecording(const cRecording *Recording) // yet unused if (mRecording != Recording) { mRecording = Recording; + ExtRecordingDescription = ""; if (mRecording != NULL) SetDirty(); } @@ -1086,9 +1091,22 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) : (cxType)false; case tPresentDescription: - return mEvent != NULL - ? (cxType)mEvent->Description() - : (cxType)false; + if (mEvent) { + if (ExtPresentDescription == "") { +#if VDRVERSNUM >= 10344 + // find corresponding timer + const char *aux = NULL; + for (cTimer *tim = Timers.First(); tim; tim = Timers.Next(tim)) { + if (tim->Event() == mEvent) aux = tim->Aux(); + } + ExtPresentDescription = AddExtInfoToDescription(mEvent->Title(), mEvent->ShortText(), mEvent->Description(), aux, Text2SkinSetup.StripAux); +#else + ExtPresentDescription = AddExtInfoToDescription(mEvent->Title(), mEvent->ShortText(), mEvent->Description()); +#endif + } + return (cxType)ExtPresentDescription; + } else + return (cxType)false; #if VDRVERSNUM >= 10318 case tPresentLanguageCode: @@ -1108,7 +1126,7 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) { std::string buffer(c->language); if (c->type == 1) buffer.append("MONO"); - if (c->type == 2) buffer.append("DUAL"); + if ((c->type == 2) || (c->type == 4)) buffer.append("DUAL"); if (c->type == 5) buffer.append("DD"); return (cxType)buffer.c_str(); } @@ -1159,10 +1177,45 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) return false; #endif + case tPresentEventID: + return mEvent != NULL + ? (cxType)EventType(mEvent->EventID()) + : (cxType)false; + case tHasVPS: case tChannelHasVPS: return mEvent != NULL && mEvent->Vps() != 0; + case tChannelName: + if (mEvent) { // extended EPG + cChannel *channel = Channels.GetByChannelID(mEvent->ChannelID(), true); + return channel != NULL + ? (cxType)ChannelName(channel, 0) + : (cxType)false; + } else if (mRecording) { // recording Info + cRecordingInfo *recInfo = const_cast(mRecording->Info()); + tChannelID chID = recInfo->ChannelID(); + cChannel *channel = Channels.GetByChannelID(recInfo->ChannelID(), true); + return channel != NULL + ? (cxType)ChannelName(channel, 0) + : (cxType)false; + } else return (cxType)false; + + case tChannelShortName: + if (mEvent) { // extended EPG + cChannel *channel = Channels.GetByChannelID(mEvent->ChannelID(), true); + return channel != NULL + ? (cxType)ChannelShortName(channel, 0) + : (cxType)false; + } else if (mRecording) { // recording Info + cRecordingInfo *recInfo = const_cast(mRecording->Info()); + tChannelID chID = recInfo->ChannelID(); + cChannel *channel = Channels.GetByChannelID(recInfo->ChannelID(), true); + return channel != NULL + ? (cxType)ChannelShortName(channel, 0) + : (cxType)false; + } else return (cxType)false; + case tPresentHasVPS: return mEvent != NULL && mEvent->Vps() != 0 && mEvent->Vps() != mEvent->StartTime(); @@ -1183,6 +1236,21 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) ? (cxType)mRecording->Name() : (cxType)false; + case tRecordingFilename: + return mRecording != NULL + ? (cxType)mRecording->FileName() + : (cxType)false; + + case tRecordingPriority: + return mRecording != NULL + ? (cxType)mRecording->priority + : (cxType)false; + + case tRecordingLifetime: + return mRecording != NULL + ? (cxType)mRecording->lifetime + : (cxType)false; + case tRecordingDateTime: return mRecording != NULL ? (cxType)TimeType(mRecording->start, Token.Attrib.Text) @@ -1199,9 +1267,17 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) : (cxType)false; case tRecordingDescription: - return mRecording != NULL - ? (cxType)mRecording->Info()->Description() - : (cxType)false; + if (mRecording) { + if (ExtRecordingDescription == "") { +#if VDRVERSNUM >= 10344 + ExtRecordingDescription = AddExtInfoToDescription(mRecording->Info()->Title(), mRecording->Info()->ShortText(), mRecording->Info()->Description(), Text2SkinSetup.ShowAux ? mRecording->Info()->Aux() : NULL, Text2SkinSetup.StripAux); +#else + ExtRecordingDescription = AddExtInfoToDescription(mRecording->Info()->Title(), mRecording->Info()->ShortText(), mRecording->Info()->Description()); +#endif + } + return (cxType)ExtRecordingDescription; + } else + return (cxType)false; case tRecordingLanguageCode: if (mRecording) @@ -1220,7 +1296,7 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) { std::string buffer(c->language); if (c->type == 1) buffer.append("MONO"); - if (c->type == 2) buffer.append("DUAL"); + if ((c->type == 2) || (c->type == 4)) buffer.append("DUAL"); if (c->type == 5) buffer.append("DD"); return (cxType)buffer.c_str(); } diff --git a/display.h b/display.h index 3865431..8bb62da 100644 --- a/display.h +++ b/display.h @@ -142,8 +142,10 @@ private: // detailed event view const cEvent *mEvent; + std::string ExtPresentDescription; // detailed recording const cRecording *mRecording; + std::string ExtRecordingDescription; // long text std::string mText; diff --git a/graphtft/font.c b/graphtft/font.c index 7941b74..9cfa812 100644 --- a/graphtft/font.c +++ b/graphtft/font.c @@ -138,21 +138,22 @@ bool cGraphtftFont::Load(string Filename, string CacheName, int Size, int Langua //Load the char error = FT_Load_Glyph( _face, glyph_index, FT_LOAD_DEFAULT ); if ( error ) continue; /* ignore errors */ - - // convert to a mono bitmap - error = FT_Render_Glyph( _face->glyph, ft_render_mode_mono ); - if ( error ) continue; // now, convert to vdr font data int width = (_slot->metrics.horiAdvance / 64) + 1; int bearingX = (_slot->metrics.horiBearingX / 64) +1; width = (width > (int)sizeof(cFont::tPixelData) * 8) ? (((int)sizeof(cFont::tPixelData) * 8)-2) :width ; - int top = _slot->bitmap_top; - int y_off = Size - top; font_data[(num_char_array*num_rows)+0]=width; font_data[(num_char_array*num_rows)+1]=num_rows_global; + // convert to a mono bitmap + error = FT_Render_Glyph( _face->glyph, ft_render_mode_mono ); + if ( error ) continue; + + int top = _slot->bitmap_top; + int y_off = Size - top; + unsigned char *bmp = _slot->bitmap.buffer; for (int y = 0; y < _slot->bitmap.rows; ++y , y_off++) { diff --git a/i18n.c b/i18n.c index 295c677..28cd46e 100644 --- a/i18n.c +++ b/i18n.c @@ -100,6 +100,56 @@ const tI18nPhrase Phrases[] = { #if VDRVERSNUM >= 10313 "", #endif +#if VDRVERSNUM >= 10316 + "", +#endif + }, + { "RERUNS OF THIS SHOW", + "WIEDERHOLUNGEN DIESER SENDUNG", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", +#if VDRVERSNUM >= 10313 + "", +#endif +#if VDRVERSNUM >= 10316 + "", +#endif + }, + { "Scale factor of the tab-widths [%]", + "Skalierungsfaktor für die Tabolatorweiten [%]", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", +#if VDRVERSNUM >= 10313 + "", +#endif #if VDRVERSNUM >= 10316 "", #endif @@ -179,8 +229,8 @@ const tI18nPhrase Phrases[] = { "", #endif }, - { "Use 'timeline' to check timer-conflicts", - "Timerkonflikte mit 'timeline' überprüfen", + { "Use 'epgsearch' to check timer-conflicts", + "Timerkonflikte mit 'epgsearch' überprüfen", "", "", "", @@ -250,6 +300,106 @@ const tI18nPhrase Phrases[] = { #if VDRVERSNUM >= 10313 "", #endif +#if VDRVERSNUM >= 10316 + "", +#endif + }, + { "AUXILIARY INFOS", + "ZUSATZINFOS", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", +#if VDRVERSNUM >= 10313 + "", +#endif +#if VDRVERSNUM >= 10316 + "", +#endif + }, + { "Show auxiliary infos of recordings", + "Zusatzinfos der Aufnahmen anzeigen", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", +#if VDRVERSNUM >= 10313 + "", +#endif +#if VDRVERSNUM >= 10316 + "", +#endif + }, + { " Extract known tags", + " Bekannte Tags extrahieren", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", +#if VDRVERSNUM >= 10313 + "", +#endif +#if VDRVERSNUM >= 10316 + "", +#endif + }, + { "Search timer", + "Suchtimer", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", + "", +#if VDRVERSNUM >= 10313 + "", +#endif #if VDRVERSNUM >= 10316 "", #endif diff --git a/menu.c b/menu.c index e8f2306..3117022 100644 --- a/menu.c +++ b/menu.c @@ -9,14 +9,28 @@ cText2SkinSetupPage::cText2SkinSetupPage(void) { mData = Text2SkinSetup; + Setup(); +} + +void cText2SkinSetupPage::Setup(void) { + int current = Current(); + Clear(); + Add(new cMenuEditBoolItem(tr("Show scrollbar in the menus"), &mData.MenuScrollbar, tr("no"), tr("yes"))); 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 >= 10344 + Add(new cMenuEditBoolItem(tr("Show auxiliary infos of recordings"), &mData.ShowAux, tr("no"), tr("yes"))); + if (mData.ShowAux) Add(new cMenuEditBoolItem(tr(" Extract known tags"), &mData.StripAux, tr("no"), tr("yes"))); +#endif #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)); + + SetCurrent(Get(current)); + Display(); } cText2SkinSetupPage::~cText2SkinSetupPage() { @@ -26,6 +40,10 @@ void cText2SkinSetupPage::Store(void) { SetupStore("MenuScrollbar", mData.MenuScrollbar); SetupStore("MarqueeLeftRight", mData.MarqueeLeftRight); SetupStore("MarqueeReset", mData.MarqueeReset); +#if VDRVERSNUM >= 10344 + SetupStore("ShowAux", mData.ShowAux); + SetupStore("StripAux", mData.StripAux); +#endif #if VDRVERSNUM >= 10330 SetupStore("CheckTimerConflict", mData.CheckTimerConflict); #endif @@ -34,6 +52,8 @@ void cText2SkinSetupPage::Store(void) { } eOSState cText2SkinSetupPage::ProcessKey(eKeys Key) { + int oldShowAux = mData.ShowAux; + eOSState state = cMenuSetupPage::ProcessKey(Key); if (state == osUser1) { Skins.Message(mtInfo, tr("Flushing image cache...")); @@ -41,6 +61,9 @@ eOSState cText2SkinSetupPage::ProcessKey(eKeys Key) { Skins.Message(mtInfo, NULL); return osContinue; } + + if (mData.ShowAux != oldShowAux) Setup(); + return state; } diff --git a/menu.h b/menu.h index 5cd1563..f9aace7 100644 --- a/menu.h +++ b/menu.h @@ -17,6 +17,7 @@ public: cText2SkinSetupPage(void); virtual ~cText2SkinSetupPage(); + void cText2SkinSetupPage::Setup(void); virtual void Store(void); eOSState ProcessKey(eKeys Key); }; diff --git a/render.c b/render.c index 06096b1..d536c22 100644 --- a/render.c +++ b/render.c @@ -145,15 +145,22 @@ void cText2SkinRender::Action(void) void cText2SkinRender::Update(void) { + //DStartBench(malen); + //DStartBench(ges); Dbench(update); for (uint i = 0; i < mDisplay->Objects(); ++i) DrawObject(mDisplay->GetObject(i)); + //DShowBench("---\t", malen); + //DStartBench(flushen); Dbench(flush); mScreen->Flush(); Ddiff("flush only", flush); Ddiff("complete flush", update); + //DShowBench("===\t", flushen); + //DShowBench("=== ges\t", ges); + //printf("====\t%d\n", mDisplay->Objects()); } void cText2SkinRender::DrawObject(const cxObject *Object) @@ -262,8 +269,17 @@ void cText2SkinRender::DrawObject(const cxObject *Object) else { // there is no "next tab", use the rightmost edge obj.mPos2.x += Object->mPos1.x; - SetEditableWidth(obj.Size().w); - //printf("EditableWidth von '%s': %d Pixels\n", obj.Text().c_str(), obj.Size().w); + if (obj.Type() == cxObject::text && t == 1) { + // VDR assumes, that the font in the menu is fontOsd, + // so the EditableWidth is not necessarily correct + // for TTF + const cFont *defFont = cFont::GetFont(fontOsd); + const char *dummy = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "; + int editableWidth = obj.Size().w; + if (defFont != obj.Font()) + editableWidth = (int)(editableWidth * defFont->Width(dummy) / (1.1 * obj.Font()->Width(dummy))); + SetEditableWidth(editableWidth); + } } obj.mPos2.y += Object->mPos1.y + yoffset; @@ -610,7 +626,9 @@ bool cText2SkinRender::ItemColor(const std::string &Color, tColor &Result) std::string cText2SkinRender::ImagePath(const std::string &Filename) { if (mRender) - return mRender->mBasePath + "/" + Filename; + return (*Filename.data() == '/') + ? Filename + : mRender->mBasePath + "/" + Filename; return ""; } diff --git a/setup.c b/setup.c index a2ea090..6a27f6d 100644 --- a/setup.c +++ b/setup.c @@ -12,7 +12,13 @@ cText2SkinSetup::cText2SkinSetup(void) { MenuScrollbar = false; MarqueeLeftRight = true; MarqueeReset = false; +#if VDRVERSNUM >= 10344 + ShowAux = true; + StripAux = true; +#endif +#if VDRVERSNUM >= 10330 CheckTimerConflict = false; +#endif MaxCacheFill = 25; } @@ -20,7 +26,13 @@ bool cText2SkinSetup::SetupParse(const char *Name, const char *Value) { if (strcmp(Name, "MenuScrollbar") == 0) MenuScrollbar = atoi(Value); else if (strcmp(Name, "MarqueeLeftRight") == 0) MarqueeLeftRight = atoi(Value); else if (strcmp(Name, "MarqueeReset") == 0) MarqueeReset = atoi(Value); +#if VDRVERSNUM >= 10344 + else if (strcmp(Name, "ShowAux") == 0) ShowAux = atoi(Value); + else if (strcmp(Name, "StripAux") == 0) StripAux = atoi(Value); +#endif +#if VDRVERSNUM >= 10330 else if (strcmp(Name, "CheckTimerConflict") == 0) CheckTimerConflict = atoi(Value); +#endif else if (strcmp(Name, "MaxCacheFill") == 0) MaxCacheFill = atoi(Value); else return false; diff --git a/setup.h b/setup.h index cee476a..d76291c 100644 --- a/setup.h +++ b/setup.h @@ -16,7 +16,13 @@ public: int MenuScrollbar; int MarqueeLeftRight; int MarqueeReset; +#if VDRVERSNUM >= 10344 + int ShowAux; + int StripAux; +#endif +#if VDRVERSNUM >= 10330 int CheckTimerConflict; +#endif int MaxCacheFill; }; diff --git a/status.c b/status.c index 95e4bec..35be7a5 100644 --- a/status.c +++ b/status.c @@ -143,13 +143,13 @@ void cText2SkinStatus::OsdClear(void) void cText2SkinStatus::OsdCurrentItem(const char *Text) { - if (mRender != NULL) + if (mRender && Text) { // update infos cText2SkinRender::tUpdate *u = &mRender->mUpdate; - static std::string lastItem; + //static std::string lastItem; - lastItem = u->currentItem; + //lastItem = u->currentItem; u->currentItem = Text; u->resetMarquee = true; u->foundFirstItem = false; @@ -172,7 +172,7 @@ void cText2SkinStatus::OsdCurrentItem(const char *Text) void cText2SkinStatus::OsdItem(const char *Text, int Index) { - if (mRender && Text2SkinSetup.MenuScrollbar) + if (mRender && Text2SkinSetup.MenuScrollbar && Text) { uint curr = (uint)Index; cText2SkinRender::tMenuScrollbar *sb = &mRender->mMenuScrollbar; @@ -214,11 +214,13 @@ void cText2SkinStatus::UpdateEvents(void) if (!dummy.IsSingleEvent()) // add 4 additional rep. timer { + int j = 0; do { + j++; // just to avoid a endless loop dummy.Skip(); dummy.Matches(); // Refresh start- and end-time - } while (!dummy.DayMatches(dummy.Day())); + } while (!dummy.DayMatches(dummy.StartTime()) && (j < 7)); } i++; @@ -238,7 +240,19 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) switch (Token.Type) { case tReplayMode: return ReplayNames[mReplayMode]; - + + case tFrontendSTR: + return GetFrontendSTR(); + + case tFrontendSNR: + return GetFrontendSNR(); + + case tFrontendHasLock: + return GetFrontendHasLock(); + + case tFrontendHasSignal: + return GetFrontendHasSignal(); + case tCurrentEventsTitle3: event++; case tCurrentEventsTitle2: @@ -299,34 +313,26 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) ? (cxType)mEvents.Get(event)->isRecording : (cxType)false; - case tTimerConflict: + case tTimerConflicts: #if VDRVERSNUM >= 10330 - if (Text2SkinSetup.CheckTimerConflict) - { - bool conflict; - - if (mRender->mUpdate.timerConflict) - { + if (Text2SkinSetup.CheckTimerConflict) { + if (mRender->mUpdate.timerConflict) { + Epgsearch_lastconflictinfo_v1_0 conflict; mRender->mUpdate.timerConflict = false; - if (cPluginManager::CallFirstService("CheckTimerConflict-v1.0", &conflict) ) - { - mTimerConflict = conflict; - } - else - { - mTimerConflict = false; + if (cPluginManager::CallFirstService("Epgsearch-lastconflictinfo-v1.0", &conflict)) { + mTimerConflicts = conflict.relevantConflicts; + } else { + mTimerConflicts = 0; } } - - return mTimerConflict; - } - else + return mTimerConflicts; + } else +#endif { - return false; + return 0; } -#endif - + #if VDRVERSNUM >= 10325 #if VDRVERSNUM >= 10338 case tReplayName: @@ -338,7 +344,7 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) return mReplay != NULL ? (cxType)TimeType(mReplay->start, Token.Attrib.Text) : (cxType)false; - + case tReplayShortText: return mReplay != NULL ? (cxType)mReplay->Info()->ShortText() @@ -378,7 +384,7 @@ cxType cText2SkinStatus::GetTokenData(const txToken &Token) { std::string buffer(c->language); if (c->type == 1) buffer.append("MONO"); - if (c->type == 2) buffer.append("DUAL"); + if ((c->type == 2) || (c->type == 4)) buffer.append("DUAL"); if (c->type == 5) buffer.append("DD"); return (cxType)buffer.c_str(); } diff --git a/status.h b/status.h index 8bd0f96..2481a1a 100644 --- a/status.h +++ b/status.h @@ -72,7 +72,7 @@ private: uint mCurrentRecording; uint mNextRecording; int mLastLanguage; - bool mTimerConflict; + int mTimerConflicts; protected: #if VDRVERSNUM >= 10338 diff --git a/text2skin.c b/text2skin.c index cf4f618..86869e2 100644 --- a/text2skin.c +++ b/text2skin.c @@ -7,14 +7,14 @@ */ #include "text2skin.h" +#include "bitmap.h" #include "setup.h" #include "menu.h" #include "i18n.h" #include "loader.h" #include "status.h" -#include "xml/object.h" -const char *cText2SkinPlugin::VERSION = "1.1-cvs"; +const char *cText2SkinPlugin::VERSION = "1.1-cvs_ext-0.9"; const char *cText2SkinPlugin::SKINVERSION = "1.0"; const char *cText2SkinPlugin::DESCRIPTION = "Loader for text-based skins"; @@ -24,16 +24,26 @@ cText2SkinPlugin::cText2SkinPlugin(void) { cText2SkinPlugin::~cText2SkinPlugin() { } -#if VDRVERSNUM >= 10330 -bool cText2SkinPlugin::Service(const char *Id, void *Data) +#if VDRVERSNUM >= 10331 +const char **cText2SkinPlugin::SVDRPHelpPages(void) { - if (strcmp(Id,"Text2Skin-TTF") == 0) { - if (Data == NULL) - return true; - cxObject::UseTTF = *(int*)Data; - return true; - } - return false; + static const char *HelpPages[] = { + "FLUS\n" + " Flush the image cache (useful if images have changed and the" + " current version should be loaded).", + NULL + }; + return HelpPages; +} + +cString cText2SkinPlugin::SVDRPCommand(const char *Command, const char *Option, int &ReplyCode) +{ + if (strcasecmp(Command, "FLUS") == 0) { + // we use the default reply code here + cText2SkinBitmap::FlushCache(); + return "image cache flushed."; + } + return NULL; } #endif diff --git a/text2skin.h b/text2skin.h index cdd95ca..19fa341 100644 --- a/text2skin.h +++ b/text2skin.h @@ -21,8 +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); +#if VDRVERSNUM >= 10331 + virtual const char **SVDRPHelpPages(void); + virtual cString SVDRPCommand(const char *Command, const char *Option, int &ReplyCode); #endif virtual bool Start(void); virtual cMenuSetupPage *SetupMenu(void); diff --git a/xml/object.c b/xml/object.c index 3979384..c63c2ea 100644 --- a/xml/object.c +++ b/xml/object.c @@ -140,14 +140,10 @@ 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; @@ -156,8 +152,6 @@ const cFont *cxObject::Font(void) const != NULL) return font; - } - return cFont::GetFont(fontOsd); } diff --git a/xml/object.h b/xml/object.h index 96cdd14..bbc37a0 100644 --- a/xml/object.h +++ b/xml/object.h @@ -45,7 +45,6 @@ class cxObject { friend class VSkinnerItem; public: - static int UseTTF; enum eType { image, text, diff --git a/xml/string.c b/xml/string.c index b8fc1f9..7568b37 100644 --- a/xml/string.c +++ b/xml/string.c @@ -13,9 +13,9 @@ static const char *Tokens[__COUNT_TOKEN__] = { "ChannelSource", "ChannelID", "PresentStartDateTime", "PresentVPSDateTime", "CurrentEventsTitle1", "CurrentEventsStartDateTime1", "CurrentEventsStopDateTime1", "CurrentEventsChannelNumber1", "CurrentEventsChannelName1", "CurrentEventsIsRecording1", "CurrentEventsTitle2", "CurrentEventsStartDateTime2", "CurrentEventsStopDateTime2", "CurrentEventsChannelNumber2", "CurrentEventsChannelName2", "CurrentEventsIsRecording2", "CurrentEventsTitle3", "CurrentEventsStartDateTime3", "CurrentEventsStopDateTime3", "CurrentEventsChannelNumber3", "CurrentEventsChannelName3", "CurrentEventsIsRecording3", - "TimerConflict", + "TimerConflicts", "PresentEndDateTime", "PresentDuration", "PresentProgress", "PresentRemaining", - "PresentLanguageCode", "PresentLanguageDescription", "PresentVideoAR", + "PresentLanguageCode", "PresentLanguageDescription", "PresentVideoAR", "PresentEventID", "PresentTitle", "PresentShortText", "PresentDescription", "FollowingStartDateTime", "FollowingVPSDateTime", "FollowingEndDateTime", "FollowingDuration", "FollowingTitle", "FollowingShortText", "FollowingDescription", "Language", @@ -44,8 +44,9 @@ static const char *Tokens[__COUNT_TOKEN__] = { // Menu Page "MenuTitle", "MenuGroup", "IsMenuGroup", "MenuItem", "IsMenuItem", "MenuCurrent", - "IsMenuCurrent", "MenuText", "RecordingName", "RecordingDateTime", "RecordingTitle", + "IsMenuCurrent", "MenuText", "RecordingName", "RecordingFilename", "RecordingDateTime", "RecordingTitle", "RecordingShortText", "RecordingDescription", "RecordingLanguageCode", + "FrontendSTR", "FrontendSNR", "FrontendHasLock", "FrontendHasSignal", "RecordingPriority", "RecordingLifetime", "RecordingVideoAR", "RecordingSize", "RecordingLength", "RecordingCuttedLength", "OsdWidth", "OsdHeight", "RecordingLanguageDescription", "ButtonRed", "ButtonGreen", "ButtonYellow", "ButtonBlue", "CanScrollUp", "CanScrollDown" diff --git a/xml/string.h b/xml/string.h index 68cd8fa..55adbcf 100644 --- a/xml/string.h +++ b/xml/string.h @@ -44,7 +44,7 @@ enum exToken { tCurrentEventsChannelNumber3, tCurrentEventsChannelName3, tCurrentEventsIsRecording3, - tTimerConflict, + tTimerConflicts, tPresentEndDateTime, tPresentDuration, tPresentProgress, @@ -52,6 +52,7 @@ enum exToken { tPresentLanguageCode, tPresentLanguageDescription, tPresentVideoAR, + tPresentEventID, tPresentTitle, tPresentShortText, tPresentDescription, @@ -144,11 +145,18 @@ enum exToken { tMenuText, // Recordings Page tRecordingName, + tRecordingFilename, tRecordingDateTime, tRecordingTitle, tRecordingShortText, tRecordingDescription, tRecordingLanguageCode, + tFrontendSTR, + tFrontendSNR, + tFrontendHasLock, + tFrontendHasSignal, + tRecordingPriority, + tRecordingLifetime, tRecordingVideoAR, tRecordingSize, tRecordingLength, diff --git a/xml/xml.c b/xml/xml.c index a91f5d6..a6b33c3 100644 --- a/xml/xml.c +++ b/xml/xml.c @@ -35,7 +35,7 @@ XML::XML(const string &file) { ifstream f(file.c_str(), ios::in|ios::binary|ios::ate); size = f.tellg(); f.seekg(0, ios::beg); - buffer = new char [size]; + buffer = new char [size+1]; f.read(buffer, size); f.close(); data = buffer; -- cgit v1.2.3 From ac64ce03ec6b5766691ff2da3af6f51ed800792a Mon Sep 17 00:00:00 2001 From: Andreas Brugger Date: Sun, 3 Dec 2006 17:45:17 +0100 Subject: 2006-12-03: Version 1.1-cvs_ext-0.10 (vdr-text2skin-1.1-cvs_ext-0.10.diff) - set EditableWidth. This is important for plugins like 'rotor' or 'extrecmenu' - now setting the locale setting LC_TIME according to the language-selection in VDR --- HISTORY | 7 +++++++ common.c | 2 ++ display.c | 2 -- i18n.c | 29 +++++++++++++++++++++++++++-- render.c | 17 +++++++++++++++-- text2skin.c | 2 +- 6 files changed, 52 insertions(+), 7 deletions(-) diff --git a/HISTORY b/HISTORY index 505b431..90fbcfe 100644 --- a/HISTORY +++ b/HISTORY @@ -1,6 +1,13 @@ VDR Plugin 'text2skin' Revision History --------------------------------------- +2006-12-03: Version 1.1-cvs_ext-0.10 (vdr-text2skin-1.1-cvs_ext-0.10.diff) + +- set EditableWidth. This is important for plugins like 'rotor' or + 'extrecmenu' +- now setting the locale setting LC_TIME according to the language-selection + in VDR + 2006-11-19: Version 1.1-cvs_ext-0.9a (vdr-text2skin-1.1-cvs_ext-0.9a.diff) - added APIVERSION to the Makefile for vdr-1.3.47 diff --git a/common.c b/common.c index d5bb0b4..0bfb1d4 100644 --- a/common.c +++ b/common.c @@ -4,6 +4,7 @@ #include "common.h" #include +#include #include #include #include @@ -409,6 +410,7 @@ cxType TimeType(time_t Time, const std::string &Format) if (Time > 0) { if (Format.length() > 0) { + setlocale(LC_TIME, tr("en_US")); strftime(result, sizeof(result), Format.c_str(), tm); cxType r = result; diff --git a/display.c b/display.c index fa71016..9960eac 100644 --- a/display.c +++ b/display.c @@ -1194,7 +1194,6 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) : (cxType)false; } else if (mRecording) { // recording Info cRecordingInfo *recInfo = const_cast(mRecording->Info()); - tChannelID chID = recInfo->ChannelID(); cChannel *channel = Channels.GetByChannelID(recInfo->ChannelID(), true); return channel != NULL ? (cxType)ChannelName(channel, 0) @@ -1209,7 +1208,6 @@ cxType cText2SkinDisplayMenu::GetTokenData(const txToken &Token) : (cxType)false; } else if (mRecording) { // recording Info cRecordingInfo *recInfo = const_cast(mRecording->Info()); - tChannelID chID = recInfo->ChannelID(); cChannel *channel = Channels.GetByChannelID(recInfo->ChannelID(), true); return channel != NULL ? (cxType)ChannelShortName(channel, 0) diff --git a/i18n.c b/i18n.c index 28cd46e..4f97840 100644 --- a/i18n.c +++ b/i18n.c @@ -329,8 +329,8 @@ const tI18nPhrase Phrases[] = { "", #endif }, - { "Show auxiliary infos of recordings", - "Zusatzinfos der Aufnahmen anzeigen", + { "Auxiliary infos in recordings/timers", + "Zusatzinfos bei Aufnahmen/Timer anzeigen", "", "", "", @@ -452,6 +452,31 @@ const tI18nPhrase Phrases[] = { #endif #if VDRVERSNUM >= 10316 "", +#endif + }, + { "en_US", + "de_DE", + "sl_SI", + "it_IT", + "nl_NL", + "pt_PT", + "fr_FR", + "no_NO", + "fi_FI", + "pl_PL", + "es_ES", + "el_GR", + "sv_SE", + "ro_RO", + "hu_HU", + "ca_AD", + "ru_RU", + "hr_HR", +#if VDRVERSNUM >= 10313 + "et_EE", +#endif +#if VDRVERSNUM >= 10316 + "da_DK", #endif }, { NULL } diff --git a/render.c b/render.c index 4fafdbe..87df8a3 100644 --- a/render.c +++ b/render.c @@ -227,6 +227,7 @@ void cText2SkinRender::DrawObject(const cxObject *Object) uint itemheight = item->Size().h; uint maxitems = areasize.h / itemheight; uint yoffset = 0; + bool initialEditableWidthSet = false; mMenuScrollbar.maxItems = maxitems; SetMaxItems(maxitems); //Dprintf("setmaxitems %d\n", maxitems); @@ -262,13 +263,23 @@ void cText2SkinRender::DrawObject(const cxObject *Object) nexttab = GetTab(n); } + // set initial EditableWidth + // this is for plugins like 'extrecmenu' and 'rotor' + if ((obj.Type() == cxObject::text || obj.Type() == cxObject::marquee || obj.Type() == cxObject::blink) && !initialEditableWidthSet) { + initialEditableWidthSet = true; + SetEditableWidth(obj.Size().w); + } + if (t >= 0 && nexttab > 0 && nexttab < obj.mPos1.x + obj.Size().w - 1) // there is a "next tab" with text obj.mPos2.x = Object->mPos1.x + o->mPos1.x + nexttab; else { // there is no "next tab", use the rightmost edge obj.mPos2.x += Object->mPos1.x; - if (obj.Type() == cxObject::text && t == 1) { + /* not used anymore due to change to fontOsd + but could be usefull if someone uses a differnt font + + if ((obj.Type() == cxObject::text || obj.Type() == cxObject::marquee || obj.Type() == cxObject::blink) && t == 1) { // VDR assumes, that the font in the menu is fontOsd, // so the EditableWidth is not necessarily correct // for TTF @@ -278,7 +289,9 @@ void cText2SkinRender::DrawObject(const cxObject *Object) if (defFont != obj.Font()) editableWidth = (int)(editableWidth * defFont->Width(dummy) / (1.1 * obj.Font()->Width(dummy))); SetEditableWidth(editableWidth); - } + } */ + if ((obj.Type() == cxObject::text || obj.Type() == cxObject::marquee || obj.Type() == cxObject::blink) && t == 1) + SetEditableWidth(obj.Size().w); } obj.mPos2.y += Object->mPos1.y + yoffset; diff --git a/text2skin.c b/text2skin.c index 2f18e4d..dc41f15 100644 --- a/text2skin.c +++ b/text2skin.c @@ -14,7 +14,7 @@ #include "loader.h" #include "status.h" -const char *cText2SkinPlugin::VERSION = "1.1-cvs_ext-0.9a"; +const char *cText2SkinPlugin::VERSION = "1.1-cvs_ext-0.10"; const char *cText2SkinPlugin::SKINVERSION = "1.0"; const char *cText2SkinPlugin::DESCRIPTION = "Loader for text-based skins"; -- cgit v1.2.3