summaryrefslogtreecommitdiff
path: root/views
diff options
context:
space:
mode:
authorlouis <louis.braun@gmx.de>2014-09-27 09:25:14 +0200
committerlouis <louis.braun@gmx.de>2014-09-27 09:25:14 +0200
commitb0509b5182b6e0d04f05e6b3d5676b0d21f51966 (patch)
tree22b302342f22843e0815eb5f516c85f1478cbf0b /views
downloadvdr-plugin-skindesigner-0.0.1.tar.gz
vdr-plugin-skindesigner-0.0.1.tar.bz2
initial commit version 0.0.10.0.1
Diffstat (limited to 'views')
-rw-r--r--views/displayaudiotracksview.c79
-rw-r--r--views/displayaudiotracksview.h24
-rw-r--r--views/displaychannelview.c452
-rw-r--r--views/displaychannelview.h49
-rw-r--r--views/displaymenudetailview.c929
-rw-r--r--views/displaymenudetailview.h50
-rw-r--r--views/displaymenuitemcurrentview.c561
-rw-r--r--views/displaymenuitemcurrentview.h94
-rw-r--r--views/displaymenuitemview.c731
-rw-r--r--views/displaymenuitemview.h141
-rw-r--r--views/displaymenulistview.c216
-rw-r--r--views/displaymenulistview.h35
-rw-r--r--views/displaymenurootview.c495
-rw-r--r--views/displaymenurootview.h57
-rw-r--r--views/displaymenutabview.c126
-rw-r--r--views/displaymenutabview.h27
-rw-r--r--views/displaymenuview.c539
-rw-r--r--views/displaymenuview.h60
-rw-r--r--views/displaymessageview.c49
-rw-r--r--views/displaymessageview.h19
-rw-r--r--views/displayreplayview.c376
-rw-r--r--views/displayreplayview.h32
-rw-r--r--views/displayvolumeview.c55
-rw-r--r--views/displayvolumeview.h21
-rw-r--r--views/view.c809
-rw-r--r--views/view.h72
26 files changed, 6098 insertions, 0 deletions
diff --git a/views/displayaudiotracksview.c b/views/displayaudiotracksview.c
new file mode 100644
index 0000000..c4b9f9a
--- /dev/null
+++ b/views/displayaudiotracksview.c
@@ -0,0 +1,79 @@
+#define __STL_CONFIG_H
+#include <vdr/menu.h>
+#include "displayaudiotracksview.h"
+
+cDisplayAudiotracksView::cDisplayAudiotracksView(int numTracks, cTemplateView *tmplView) : cView(tmplView) {
+ DeleteOsdOnExit();
+ SetFadeTime(tmplView->GetNumericParameter(ptFadeTime));
+
+ this->numTracks = numTracks;
+
+ cTemplateViewList *tmplMenuItems = tmplView->GetViewList(vlMenuItem);
+ listView = NULL;
+ if (tmplMenuItems) {
+ listView = new cDisplayMenuListView(tmplMenuItems, numTracks);
+ }
+}
+
+cDisplayAudiotracksView::~cDisplayAudiotracksView() {
+ if (listView)
+ delete listView;
+ CancelSave();
+ FadeOut();
+}
+
+bool cDisplayAudiotracksView::createOsd(void) {
+ cRect osdSize = tmplView->GetOsdSize();
+ bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(),
+ cOsd::OsdTop() + osdSize.Y(),
+ osdSize.Width(),
+ osdSize.Height());
+ return ok;
+}
+
+void cDisplayAudiotracksView::DrawBackground(void) {
+ if (!ViewElementImplemented(veBackground)) {
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ intTokens.insert(pair<string,int>("numtracks", numTracks));
+
+ DrawViewElement(veBackground, &stringTokens, &intTokens);
+}
+
+void cDisplayAudiotracksView::DrawHeader(const char *title, int audioChannel) {
+ if (!ViewElementImplemented(veHeader)) {
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ intTokens.insert(pair<string,int>("numtracks", numTracks));
+ if (audioChannel < 0) {
+ intTokens.insert(pair<string,int>("isac3", true));
+ intTokens.insert(pair<string,int>("isstereo", false));
+ } else {
+ intTokens.insert(pair<string,int>("isac3", false));
+ intTokens.insert(pair<string,int>("isstereo", true));
+ }
+ stringTokens.insert(pair<string,string>("title", title));
+
+ ClearViewElement(veHeader);
+ DrawViewElement(veHeader, &stringTokens, &intTokens);
+}
+
+void cDisplayAudiotracksView::RenderMenuItems(void) {
+ if (listView)
+ listView->Render();
+}
+
+void cDisplayAudiotracksView::Action(void) {
+ SetInitFinished();
+ FadeIn();
+ DoFlush();
+ cView::Action();
+}
diff --git a/views/displayaudiotracksview.h b/views/displayaudiotracksview.h
new file mode 100644
index 0000000..3414d66
--- /dev/null
+++ b/views/displayaudiotracksview.h
@@ -0,0 +1,24 @@
+#ifndef __DISPLAYAUDIOTRACKSVIEW_H
+#define __DISPLAYAUDIOTRACKSVIEW_H
+
+#include "../libtemplate/template.h"
+#include "displaymenulistview.h"
+
+class cDisplayAudiotracksView : public cView {
+protected:
+ int numTracks;
+ cDisplayMenuListView *listView;
+ virtual void Action(void);
+public:
+ cDisplayAudiotracksView(int numTracks, cTemplateView *tmplView);
+ virtual ~cDisplayAudiotracksView();
+ bool createOsd(void);
+ void DrawBackground(void);
+ void DrawHeader(const char *title, int audioChannel);
+ cDisplayMenuListView *GetListView(void) { return listView; };
+ void DoFadeIn(void) { Start(); };
+ void Flush(void) { DoFlush(); };
+ void RenderMenuItems(void);
+};
+
+#endif //__DISPLAYAUDIOTRACKSVIEW_H
diff --git a/views/displaychannelview.c b/views/displaychannelview.c
new file mode 100644
index 0000000..66155a1
--- /dev/null
+++ b/views/displaychannelview.c
@@ -0,0 +1,452 @@
+#define __STL_CONFIG_H
+#include <vdr/menu.h>
+#include "../services/scraper2vdr.h"
+#include "displaychannelview.h"
+#include "../libcore/timers.h"
+#include "../libcore/helpers.h"
+
+
+cDisplayChannelView::cDisplayChannelView(cTemplateView *tmplView) : cView(tmplView) {
+ lastDate = "";
+ lastScreenWidth = 0;
+ lastScreenHeight = 0;
+ lastSignalDisplay = 0;
+ lastSignalStrength = 0;
+ lastSignalQuality = 0;
+ DeleteOsdOnExit();
+ SetFadeTime(tmplView->GetNumericParameter(ptFadeTime));
+}
+
+cDisplayChannelView::~cDisplayChannelView() {
+ CancelSave();
+ FadeOut();
+}
+
+bool cDisplayChannelView::createOsd(void) {
+ cRect osdSize = tmplView->GetOsdSize();
+ bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(),
+ cOsd::OsdTop() + osdSize.Y(),
+ osdSize.Width(),
+ osdSize.Height());
+ return ok;
+}
+
+void cDisplayChannelView::DrawBackground(void) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ DrawViewElement(veBackground, &stringTokens, &intTokens);
+}
+
+void cDisplayChannelView::DrawChannel(cString &number, cString &name, cString &id, bool switching) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ stringTokens.insert(pair<string,string>("channelname", *name));
+ stringTokens.insert(pair<string,string>("channelnumber", *number));
+ stringTokens.insert(pair<string,string>("channelid", *id));
+
+ intTokens.insert(pair<string, int>("switching", switching));
+ bool logoExisis = imgCache->LogoExists(*id);
+ intTokens.insert(pair<string, int>("channellogoexists", logoExisis));
+
+ DrawViewElement(veChannelInfo, &stringTokens, &intTokens);
+}
+
+void cDisplayChannelView::ClearChannel(void) {
+ ClearViewElement(veChannelInfo);
+}
+
+void cDisplayChannelView::DrawDate(void) {
+ if (!ViewElementImplemented(veDateTime)) {
+ return;
+ }
+ cString curDate = DayDateTime();
+ if (strcmp(curDate, lastDate)) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ time_t t = time(0); // get time now
+ struct tm * now = localtime(&t);
+
+ intTokens.insert(pair<string, int>("year", now->tm_year + 1900));
+ intTokens.insert(pair<string, int>("day", now->tm_mday));
+
+ char monthname[20];
+ char monthshort[10];
+ strftime(monthshort, sizeof(monthshort), "%b", now);
+ strftime(monthname, sizeof(monthname), "%B", now);
+
+ stringTokens.insert(pair<string,string>("monthname", monthname));
+ stringTokens.insert(pair<string,string>("monthnameshort", monthshort));
+ stringTokens.insert(pair<string,string>("month", *cString::sprintf("%02d", now->tm_mon + 1)));
+ stringTokens.insert(pair<string,string>("dayleadingzero", *cString::sprintf("%02d", now->tm_mday)));
+ stringTokens.insert(pair<string,string>("dayname", *WeekDayNameFull(now->tm_wday)));
+ stringTokens.insert(pair<string,string>("daynameshort", *WeekDayName(now->tm_wday)));
+ stringTokens.insert(pair<string,string>("time", *TimeString(t)));
+
+ ClearViewElement(veDateTime);
+ DrawViewElement(veDateTime, &stringTokens, &intTokens);
+
+ lastDate = curDate;
+ }
+}
+
+void cDisplayChannelView::DrawProgressBar(cString &start, cString &stop, int Current, int Total) {
+ if (!ViewElementImplemented(veProgressBar)) {
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ stringTokens.insert(pair<string, string>("start", *start));
+ stringTokens.insert(pair<string, string>("stop", *stop));
+
+ intTokens.insert(pair<string, int>("duration", Total));
+ intTokens.insert(pair<string, int>("elapsed", Current));
+ intTokens.insert(pair<string, int>("remaining", Total - Current));
+
+ DrawViewElement(veProgressBar, &stringTokens, &intTokens);
+}
+
+void cDisplayChannelView::ClearProgressBar(void) {
+ ClearViewElement(veProgressBar);
+}
+
+void cDisplayChannelView::DrawProgressBarBack(void) {
+ DrawViewElement(veProgressBarBack);
+}
+
+void cDisplayChannelView::ClearProgressBarBack(void) {
+ ClearViewElement(veProgressBarBack);
+}
+
+void cDisplayChannelView::DrawEPGInfo(const cEvent *present, const cEvent *next, bool presentRecording, bool nextRecording) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ if (present) {
+ stringTokens.insert(pair<string,string>("currenttitle", (present->Title())?present->Title():""));
+ stringTokens.insert(pair<string,string>("currentsubtitle", (present->ShortText())?present->ShortText():""));
+ stringTokens.insert(pair<string,string>("currentstart", *present->GetTimeString()));
+ stringTokens.insert(pair<string,string>("currentstop", *present->GetEndTimeString()));
+
+ intTokens.insert(pair<string,int>("currentduration", present->Duration() / 60));
+ intTokens.insert(pair<string,int>("currentelapsed", (int)round((time(NULL) - present->StartTime())/60)));
+ intTokens.insert(pair<string,int>("currentremaining", (int)round((present->EndTime() - time(NULL))/60)));
+ intTokens.insert(pair<string,int>("currentrecording", presentRecording ? 1 : 0));
+ } else {
+ stringTokens.insert(pair<string,string>("currenttitle", ""));
+ stringTokens.insert(pair<string,string>("currentsubtitle", ""));
+ stringTokens.insert(pair<string,string>("currentstart", ""));
+ stringTokens.insert(pair<string,string>("currentstop", ""));
+
+ intTokens.insert(pair<string,int>("currentduration", 0));
+ intTokens.insert(pair<string,int>("currentelapsed", 0));
+ intTokens.insert(pair<string,int>("currentremaining", 0));
+ intTokens.insert(pair<string,int>("currentrecording", 0));
+ }
+
+ if (next) {
+ stringTokens.insert(pair<string,string>("nexttitle", (next->Title())?next->Title():""));
+ stringTokens.insert(pair<string,string>("nextsubtitle", (next->ShortText())?next->ShortText():""));
+ stringTokens.insert(pair<string,string>("nextstart", *next->GetTimeString()));
+ stringTokens.insert(pair<string,string>("nextstop", *next->GetEndTimeString()));
+
+ intTokens.insert(pair<string,int>("nextduration", next->Duration() / 60));
+ intTokens.insert(pair<string,int>("nextrecording", nextRecording ? 1 : 0));
+ } else {
+ stringTokens.insert(pair<string,string>("nexttitle", ""));
+ stringTokens.insert(pair<string,string>("nextsubtitle", ""));
+ stringTokens.insert(pair<string,string>("nextstart", ""));
+ stringTokens.insert(pair<string,string>("nextstop", ""));
+
+ intTokens.insert(pair<string,int>("nextduration", 0));
+ intTokens.insert(pair<string,int>("nextrecording", 0));
+ }
+ DrawViewElement(veEpgInfo, &stringTokens, &intTokens);
+}
+
+void cDisplayChannelView::ClearEPGInfo(void) {
+ ClearViewElement(veEpgInfo);
+}
+
+void cDisplayChannelView::DrawStatusIcons(const cChannel *Channel) {
+ if (!ViewElementImplemented(veStatusInfo)) {
+ return;
+ }
+
+ bool isRadio = !Channel->Vpid() && Channel->Apid(0);
+ bool hasVT = Channel->Vpid() && Channel->Tpid();
+ bool isStereo = Channel->Apid(0);
+ bool isDolby = Channel->Dpid(0);
+ bool isEncrypted = Channel->Ca();
+ bool isRecording = cRecordControls::Active();
+ cGlobalSortedTimers SortedTimers;// local and remote timers
+ for (int i = 0; i < SortedTimers.Size() && !isRecording; i++)
+ if (const cTimer *Timer = SortedTimers[i])
+ if (Timer->Recording())
+ isRecording = true;
+
+ map < string, int > intTokens;
+ intTokens.insert(pair<string,int>("isRadio", isRadio));
+ intTokens.insert(pair<string,int>("hasVT", hasVT));
+ intTokens.insert(pair<string,int>("isStereo", isStereo));
+ intTokens.insert(pair<string,int>("isDolby", isDolby));
+ intTokens.insert(pair<string,int>("isEncrypted", isEncrypted));
+ intTokens.insert(pair<string,int>("isRecording", isRecording));
+
+ DrawViewElement(veStatusInfo, NULL, &intTokens);
+}
+
+void cDisplayChannelView::ClearStatusIcons(void) {
+ ClearViewElement(veStatusInfo);
+}
+
+void cDisplayChannelView::DrawScreenResolution(void) {
+ if (!ViewElementImplemented(veScreenResolution)) {
+ return;
+ }
+
+ int screenWidth = 0;
+ int screenHeight = 0;
+ double aspect = 0;
+
+ cDevice::PrimaryDevice()->GetVideoSize(screenWidth, screenHeight, aspect);
+
+ if ((lastScreenWidth == screenWidth) && (lastScreenHeight == screenHeight))
+ return;
+
+ if ((screenWidth == 0) && (screenHeight == 0))
+ return;
+
+ lastScreenWidth = screenWidth;
+ lastScreenHeight = screenHeight;
+
+ bool isHD = false;
+ string resName = GetScreenResolutionString(screenWidth, screenHeight, &isHD);
+
+ bool isWideScreen = false;
+ string aspectName = GetScreenAspectString(aspect, &isWideScreen);
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ intTokens.insert(pair<string,int>("screenwidth", screenWidth));
+ intTokens.insert(pair<string,int>("screenheight", screenHeight));
+ intTokens.insert(pair<string,int>("isHD", isHD));
+ intTokens.insert(pair<string,int>("isWideScreen", isWideScreen));
+ stringTokens.insert(pair<string,string>("resolution", resName));
+ stringTokens.insert(pair<string,string>("aspect", aspectName));
+
+ ClearViewElement(veScreenResolution);
+ DrawViewElement(veScreenResolution, &stringTokens, &intTokens);
+}
+
+void cDisplayChannelView::ClearScreenResolution(void) {
+ ClearViewElement(veScreenResolution);
+ lastScreenWidth = 0;
+ lastScreenHeight = 0;
+}
+
+string cDisplayChannelView::GetScreenResolutionString(int width, int height, bool *isHD) {
+ string name = "";
+ switch (width) {
+ case 1920:
+ case 1440:
+ name = "hd1080i";
+ *isHD = true;
+ break;
+ case 1280:
+ if (height == 720)
+ name = "hd720p";
+ else
+ name = "hd1080i";
+ *isHD = true;
+ break;
+ case 720:
+ name = "sd576i";
+ break;
+ default:
+ name = "sd576i";
+ break;
+ }
+ return name;
+}
+
+string cDisplayChannelView::GetScreenAspectString(double aspect, bool *isWideScreen) {
+ string name = "";
+ *isWideScreen = false;
+ if (aspect == 4.0/3.0) {
+ name = "4:3";
+ *isWideScreen = false;
+ } else if (aspect == 16.0/9.0) {
+ name = "16:9";
+ *isWideScreen = true;
+ } else if (aspect == 2.21) {
+ name = "21:9";
+ *isWideScreen = true;
+ }
+ return name;
+}
+
+void cDisplayChannelView::DrawScraperContent(const cEvent *event) {
+ if (!event)
+ return;
+
+ if (!ViewElementImplemented(veScraperContent)) {
+ return;
+ }
+
+ static cPlugin *pScraper = GetScraperPlugin();
+ if (!pScraper) {
+ return;
+ }
+
+ ScraperGetPosterBanner call;
+ call.event = event;
+ if (pScraper->Service("GetPosterBanner", &call)) {
+ int mediaWidth = 0;
+ int mediaHeight = 0;
+ std::string mediaPath = "";
+ bool isBanner = false;
+
+ if ((call.type == tSeries) && call.banner.path.size() > 0) {
+ mediaWidth = call.banner.width;
+ mediaHeight = call.banner.height;
+ mediaPath = call.banner.path;
+ isBanner = true;
+ } else if (call.type == tMovie && call.poster.path.size() > 0 && call.poster.height > 0) {
+ mediaWidth = call.poster.width;
+ mediaHeight = call.poster.height;
+ mediaPath = call.poster.path;
+ } else
+ return;
+
+ map < string, int > intTokens;
+ map < string, string > stringTokens;
+ intTokens.insert(pair<string,int>("mediawidth", mediaWidth));
+ intTokens.insert(pair<string,int>("mediaheight", mediaHeight));
+ intTokens.insert(pair<string,int>("isbanner", isBanner));
+ stringTokens.insert(pair<string,string>("mediapath", mediaPath));
+ ClearViewElement(veScraperContent);
+ DrawViewElement(veScraperContent, &stringTokens, &intTokens);
+ }
+}
+
+void cDisplayChannelView::ClearScraperContent(void) {
+ ClearViewElement(veScraperContent);
+}
+
+void cDisplayChannelView::DrawSignal(void) {
+ if (!ViewElementImplemented(veSignalQuality)) {
+ return;
+ }
+ time_t Now = time(NULL);
+ if (Now != lastSignalDisplay) {
+ int SignalStrength = cDevice::ActualDevice()->SignalStrength();
+ int SignalQuality = cDevice::ActualDevice()->SignalQuality();
+ if (SignalStrength < 0) SignalStrength = 0;
+ if (SignalQuality < 0) SignalQuality = 0;
+ if ((SignalStrength == 0)&&(SignalQuality==0))
+ return;
+ if ((lastSignalStrength != SignalStrength) || (lastSignalQuality != SignalQuality)) {
+ map < string, int > intTokens;
+ map < string, string > stringTokens;
+ intTokens.insert(pair<string,int>("signalstrength", SignalStrength));
+ intTokens.insert(pair<string,int>("signalquality", SignalQuality));
+ ClearViewElement(veSignalQuality);
+ DrawViewElement(veSignalQuality, &stringTokens, &intTokens);
+ }
+ lastSignalStrength = SignalStrength;
+ lastSignalQuality = SignalQuality;
+ lastSignalDisplay = Now;
+ }
+}
+
+void cDisplayChannelView::DrawSignalBackground(void) {
+ if (!ViewElementImplemented(veSignalQualityBack)) {
+ return;
+ }
+ DrawViewElement(veSignalQualityBack);
+}
+
+
+void cDisplayChannelView::ClearSignal(void) {
+ ClearViewElement(veSignalQuality);
+}
+
+void cDisplayChannelView::ClearSignalBackground(void) {
+ ClearViewElement(veSignalQualityBack);
+}
+
+void cDisplayChannelView::DrawChannelGroups(const cChannel *Channel, cString ChannelName) {
+ if (!ViewElementImplemented(veChannelGroup)) {
+ return;
+ }
+
+ bool separatorExists = imgCache->SeparatorLogoExists(*ChannelName);
+ string separatorPath = separatorExists ? *ChannelName : "";
+
+ std::string prevChannelSep = GetChannelSep(Channel, true);
+ std::string nextChannelSep = GetChannelSep(Channel, false);
+ bool prevAvailable = (prevChannelSep.size() > 0)?true:false;
+ bool nextAvailable = (nextChannelSep.size() > 0)?true:false;
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ intTokens.insert(pair<string,int>("sepexists", separatorExists));
+ intTokens.insert(pair<string,int>("prevAvailable", prevAvailable));
+ intTokens.insert(pair<string,int>("nextAvailable", nextAvailable));
+ stringTokens.insert(pair<string,string>("group", *ChannelName));
+ stringTokens.insert(pair<string,string>("nextgroup", nextChannelSep));
+ stringTokens.insert(pair<string,string>("prevgroup", prevChannelSep));
+ stringTokens.insert(pair<string,string>("seppath", separatorPath));
+
+ ClearViewElement(veChannelGroup);
+ DrawViewElement(veChannelGroup, &stringTokens, &intTokens);
+}
+
+void cDisplayChannelView::ClearChannelGroups(void) {
+ ClearViewElement(veChannelGroup);
+}
+
+string cDisplayChannelView::GetChannelSep(const cChannel *channel, bool prev) {
+ std::string sepName = "";
+ const cChannel *sep = prev ? Channels.Prev(channel) :
+ Channels.Next(channel);
+ for (; sep; (prev)?(sep = Channels.Prev(sep)):(sep = Channels.Next(sep))) {
+ if (sep->GroupSep()) {
+ sepName = sep->Name();
+ break;
+ }
+ }
+ return sepName;
+}
+
+void cDisplayChannelView::DisplayMessage(eMessageType Type, const char *Text) {
+ if (!Text) {
+ ClearViewElement(veMessage);
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ stringTokens.insert(pair<string,string>("text", Text));
+
+ intTokens.insert(pair<string,int>("status", (Type == mtStatus) ? true : false));
+ intTokens.insert(pair<string,int>("info", (Type == mtInfo) ? true : false));
+ intTokens.insert(pair<string,int>("warning", (Type == mtWarning) ? true : false));
+ intTokens.insert(pair<string,int>("error", (Type == mtError) ? true : false));
+
+ ClearViewElement(veMessage);
+ DrawViewElement(veMessage, &stringTokens, &intTokens);
+}
+
+void cDisplayChannelView::Action(void) {
+ SetInitFinished();
+ FadeIn();
+ DoFlush();
+ cView::Action();
+}
diff --git a/views/displaychannelview.h b/views/displaychannelview.h
new file mode 100644
index 0000000..599ac5f
--- /dev/null
+++ b/views/displaychannelview.h
@@ -0,0 +1,49 @@
+#ifndef __DISPLAYCHANNELVIEW_H
+#define __DISPLAYCHANNELVIEW_H
+
+#include "../libtemplate/template.h"
+#include "view.h"
+
+class cDisplayChannelView : public cView {
+private:
+ cString lastDate;
+ int lastScreenWidth;
+ int lastScreenHeight;
+ int lastSignalDisplay;
+ int lastSignalStrength;
+ int lastSignalQuality;
+ string GetScreenResolutionString(int width, int height, bool *isHD);
+ string GetScreenAspectString(double aspect, bool *isWideScreen);
+ string GetChannelSep(const cChannel *channel, bool prev);
+ virtual void Action(void);
+public:
+ cDisplayChannelView(cTemplateView *tmplView);
+ virtual ~cDisplayChannelView();
+ bool createOsd(void);
+ void DrawBackground(void);
+ void DrawChannel(cString &number, cString &name, cString &id, bool switching);
+ void ClearChannel(void);
+ void DrawDate(void);
+ void DrawProgressBar(cString &start, cString &stop, int Current, int Total);
+ void ClearProgressBar(void);
+ void DrawProgressBarBack(void);
+ void ClearProgressBarBack(void);
+ void DrawEPGInfo(const cEvent *present, const cEvent *next, bool presentRecording, bool nextRecording);
+ void ClearEPGInfo(void);
+ void DrawStatusIcons(const cChannel *Channel);
+ void ClearStatusIcons(void);
+ void DrawScreenResolution(void);
+ void ClearScreenResolution(void);
+ void DrawScraperContent(const cEvent *event);
+ void ClearScraperContent(void);
+ void DrawSignal(void);
+ void DrawSignalBackground(void);
+ void ClearSignal(void);
+ void ClearSignalBackground(void);
+ void DrawChannelGroups(const cChannel *Channel, cString ChannelName);
+ void ClearChannelGroups(void);
+ void DisplayMessage(eMessageType Type, const char *Text);
+ void DoStart(void) { Start(); };
+ void Flush(void) { DoFlush(); };
+};
+#endif //__DISPLAYCHANNELVIEW_H
diff --git a/views/displaymenudetailview.c b/views/displaymenudetailview.c
new file mode 100644
index 0000000..acba9c6
--- /dev/null
+++ b/views/displaymenudetailview.c
@@ -0,0 +1,929 @@
+#include "displaymenudetailview.h"
+#include "../libcore/helpers.h"
+#include "../services/scraper2vdr.h"
+#include "../services/epgsearch.h"
+
+cDisplayMenuDetailView::cDisplayMenuDetailView(cTemplateView *tmplDetailView) : cView(tmplDetailView) {
+ event = NULL;
+ recording = NULL;
+ text = NULL;
+ detailViewInit = true;
+ currentTmplTab = NULL;
+ tabView = NULL;
+}
+
+cDisplayMenuDetailView::~cDisplayMenuDetailView() {
+ CancelSave();
+ if (tabView)
+ delete tabView;
+}
+
+void cDisplayMenuDetailView::Clear(void) {
+ ClearViewElement(veDetailHeader);
+ ClearViewElement(veScrollbar);
+ ClearViewElement(veTabLabels);
+}
+
+void cDisplayMenuDetailView::Render(void) {
+ if (detailViewInit) {
+ DrawHeader();
+ DoFlush();
+ SetTokens();
+ InitTabs();
+ currentTmplTab = *atIt;
+ detailViewInit = false;
+ }
+ if (!tabView) {
+ tabView = new cDisplayMenuTabView(currentTmplTab);
+ tabView->SetTokens(&intTokens, &stringTokens, &loopTokens);
+ tabView->CreateTab();
+ tabView->Start();
+ }
+ DrawScrollbar();
+ DrawTabLabels();
+}
+
+void cDisplayMenuDetailView::KeyLeft(void) {
+ if (activeTabs.size() > 1) {
+ currentTmplTab = GetPrevTab();
+ delete tabView;
+ tabView = NULL;
+ Render();
+ DoFlush();
+ } else {
+ bool scrolled = tabView->KeyLeft();
+ if (scrolled) {
+ DrawScrollbar();
+ DoFlush();
+ }
+ }
+}
+
+void cDisplayMenuDetailView::KeyRight(void) {
+ if (activeTabs.size() > 1) {
+ currentTmplTab = GetNextTab();
+ delete tabView;
+ tabView = NULL;
+ Render();
+ DoFlush();
+ } else {
+ bool scrolled = tabView->KeyRight();
+ if (scrolled) {
+ DrawScrollbar();
+ DoFlush();
+ }
+ }
+}
+
+void cDisplayMenuDetailView::KeyUp(void) {
+ if (!tabView)
+ return;
+ bool scrolled = tabView->KeyUp();
+ if (scrolled) {
+ DrawScrollbar();
+ DoFlush();
+ }
+}
+
+void cDisplayMenuDetailView::KeyDown(void) {
+ if (!tabView)
+ return;
+ bool scrolled = tabView->KeyDown();
+ if (scrolled) {
+ DrawScrollbar();
+ DoFlush();
+ }
+}
+
+
+void cDisplayMenuDetailView::SetTokens(void) {
+ if (event) {
+ stringTokens.insert(pair<string,string>("title", event->Title() ? event->Title() : ""));
+ stringTokens.insert(pair<string,string>("shorttext", event->ShortText() ? event->ShortText() : ""));
+ stringTokens.insert(pair<string,string>("description", event->Description() ? event->Description() : ""));
+ stringTokens.insert(pair<string,string>("start", *(event->GetTimeString())));
+ stringTokens.insert(pair<string,string>("stop", *(event->GetEndTimeString())));
+ stringTokens.insert(pair<string,string>("day", *WeekDayName(event->StartTime())));
+ stringTokens.insert(pair<string,string>("date", *ShortDateString(event->StartTime())));
+ stringTokens.insert(pair<string,string>("channelid", *(event->ChannelID().ToString())));
+
+ bool isRunning = false;
+ time_t now = time(NULL);
+ if ((now >= event->StartTime()) && (now <= event->EndTime()))
+ isRunning = true;
+ intTokens.insert(pair<string,int>("running", isRunning));
+ if (isRunning) {
+ intTokens.insert(pair<string,int>("elapsed", (now - event->StartTime())/60));
+ } else {
+ intTokens.insert(pair<string,int>("elapsed", 0));
+ }
+ intTokens.insert(pair<string,int>("duration", event->Duration() / 60));
+
+ vector< map< string, string > > reruns;
+ bool hasReruns = LoadReruns(&reruns);
+ loopTokens.insert(pair<string, vector< map< string, string > > >("reruns", reruns));
+
+ intTokens.insert(pair<string,int>("hasreruns", hasReruns));
+
+ SetScraperTokens();
+ SetEpgPictures(event->EventID());
+
+ } else if (recording) {
+ string name = recording->Name() ? recording->Name() : "";
+ stringTokens.insert(pair<string,string>("name", name));
+
+ const cRecordingInfo *info = recording->Info();
+ if (info) {
+ stringTokens.insert(pair<string,string>("shorttext", info->ShortText() ? info->ShortText() : ""));
+ stringTokens.insert(pair<string,string>("description", info->Description() ? info->Description() : ""));
+ const cEvent *event = info->GetEvent();
+ if (event) {
+ string recDate = *(event->GetDateString());
+ string recTime = *(event->GetTimeString());
+ if (recDate.find("1970") != string::npos) {
+ time_t start = recording->Start();
+ recDate = *DateString(start);
+ recTime = *TimeString(start);
+ }
+ int duration = event->Duration() / 60;
+ int recDuration = recording->LengthInSeconds();
+ recDuration = (recDuration>0)?(recDuration / 60):0;
+ stringTokens.insert(pair<string,string>("date", recDate.c_str()));
+ stringTokens.insert(pair<string,string>("time", recTime.c_str()));
+ intTokens.insert(pair<string,int>("duration", recDuration));
+ intTokens.insert(pair<string,int>("durationevent", duration));
+ }
+ } else {
+ stringTokens.insert(pair<string,string>("shorttext", ""));
+ stringTokens.insert(pair<string,string>("description", ""));
+ int recDuration = recording->LengthInSeconds();
+ recDuration = (recDuration>0)?(recDuration / 60):0;
+ stringTokens.insert(pair<string,string>("date", ""));
+ stringTokens.insert(pair<string,string>("time", ""));
+ intTokens.insert(pair<string,int>("duration", recDuration));
+ intTokens.insert(pair<string,int>("durationevent", 0));
+ }
+ LoadRecordingInformation();
+ SetScraperTokens();
+ SetRecordingImages(recording->FileName());
+ } else if (text) {
+ stringTokens.insert(pair<string,string>("text", text));
+ } else {
+ intTokens.insert(pair<string,int>("running", false));
+ intTokens.insert(pair<string,int>("hasreruns", false));
+ }
+}
+
+void cDisplayMenuDetailView::SetScraperTokens(void) {
+ static cPlugin *pScraper = GetScraperPlugin();
+ if (!pScraper || (!event && !recording)) {
+ intTokens.insert(pair<string,int>("ismovie", false));
+ intTokens.insert(pair<string,int>("isseries", false));
+ return;
+ }
+
+ ScraperGetEventType getType;
+ getType.event = event;
+ getType.recording = recording;
+ if (!pScraper->Service("GetEventType", &getType)) {
+ intTokens.insert(pair<string,int>("ismovie", false));
+ intTokens.insert(pair<string,int>("isseries", false));
+ return;
+ }
+
+ if (getType.type == tMovie) {
+ cMovie movie;
+ movie.movieId = getType.movieId;
+ pScraper->Service("GetMovie", &movie);
+ intTokens.insert(pair<string,int>("ismovie", true));
+ intTokens.insert(pair<string,int>("isseries", false));
+
+ stringTokens.insert(pair<string,string>("movietitle", movie.title));
+ stringTokens.insert(pair<string,string>("movieoriginalTitle", movie.originalTitle));
+ stringTokens.insert(pair<string,string>("movietagline", movie.tagline));
+ stringTokens.insert(pair<string,string>("movieoverview", movie.overview));
+ stringTokens.insert(pair<string,string>("moviegenres", movie.genres));
+ stringTokens.insert(pair<string,string>("moviehomepage", movie.homepage));
+ stringTokens.insert(pair<string,string>("moviereleasedate", movie.releaseDate));
+ stringstream pop;
+ pop << movie.popularity;
+ stringTokens.insert(pair<string,string>("moviepopularity", pop.str()));
+ stringstream vote;
+ vote << movie.voteAverage;
+ stringTokens.insert(pair<string,string>("movievoteaverage", pop.str()));
+ stringTokens.insert(pair<string,string>("posterpath", movie.poster.path));
+ stringTokens.insert(pair<string,string>("fanartpath", movie.fanart.path));
+ stringTokens.insert(pair<string,string>("collectionposterpath", movie.collectionPoster.path));
+ stringTokens.insert(pair<string,string>("collectionfanartpath", movie.collectionFanart.path));
+
+ intTokens.insert(pair<string,int>("movieadult", movie.adult));
+ intTokens.insert(pair<string,int>("moviebudget", movie.budget));
+ intTokens.insert(pair<string,int>("movierevenue", movie.revenue));
+ intTokens.insert(pair<string,int>("movieruntime", movie.runtime));
+ intTokens.insert(pair<string,int>("posterwidth", movie.poster.width));
+ intTokens.insert(pair<string,int>("posterheight", movie.poster.height));
+ intTokens.insert(pair<string,int>("fanartwidth", movie.fanart.width));
+ intTokens.insert(pair<string,int>("fanartheight", movie.fanart.height));
+ intTokens.insert(pair<string,int>("collectionposterwidth", movie.collectionPoster.width));
+ intTokens.insert(pair<string,int>("collectionposterheight", movie.collectionPoster.height));
+ intTokens.insert(pair<string,int>("collectionfanartwidth", movie.collectionFanart.width));
+ intTokens.insert(pair<string,int>("collectionfanartheight", movie.collectionFanart.height));
+
+ vector< map< string, string > > actors;
+ for (vector<cActor>::iterator act = movie.actors.begin(); act != movie.actors.end(); act++) {
+ map< string, string > actor;
+ actor.insert(pair<string, string>("actors[name]", (*act).name));
+ actor.insert(pair<string, string>("actors[role]", (*act).role));
+ actor.insert(pair<string, string>("actors[thumb]", (*act).actorThumb.path));
+ stringstream actWidth, actHeight;
+ actWidth << (*act).actorThumb.width;
+ actHeight << (*act).actorThumb.height;
+ actor.insert(pair<string, string>("actors[thumbwidth]", actWidth.str()));
+ actor.insert(pair<string, string>("actors[thumbheight]", actHeight.str()));
+ actors.push_back(actor);
+ }
+ loopTokens.insert(pair<string, vector< map< string, string > > >("actors", actors));
+
+ } else if (getType.type == tSeries) {
+ cSeries series;
+ series.seriesId = getType.seriesId;
+ series.episodeId = getType.episodeId;
+ pScraper->Service("GetSeries", &series);
+ intTokens.insert(pair<string,int>("ismovie", false));
+ intTokens.insert(pair<string,int>("isseries", true));
+ //Series Basics
+ stringTokens.insert(pair<string,string>("seriesname", series.name));
+ stringTokens.insert(pair<string,string>("seriesoverview", series.overview));
+ stringTokens.insert(pair<string,string>("seriesfirstaired", series.firstAired));
+ stringTokens.insert(pair<string,string>("seriesnetwork", series.network));
+ stringTokens.insert(pair<string,string>("seriesgenre", series.genre));
+ stringstream rating;
+ rating << series.rating;
+ stringTokens.insert(pair<string,string>("seriesrating", rating.str()));
+ stringTokens.insert(pair<string,string>("seriesstatus", series.status));
+ //Episode Information
+ intTokens.insert(pair<string,int>("episodenumber", series.episode.number));
+ intTokens.insert(pair<string,int>("episodeseason", series.episode.season));
+ stringTokens.insert(pair<string,string>("episodetitle", series.episode.name));
+ stringTokens.insert(pair<string,string>("episodefirstaired", series.episode.firstAired));
+ stringTokens.insert(pair<string,string>("episodegueststars", series.episode.guestStars));
+ stringTokens.insert(pair<string,string>("episodeoverview", series.episode.overview));
+ stringstream eprating;
+ eprating << series.episode.rating;
+ stringTokens.insert(pair<string,string>("episoderating", eprating.str()));
+ intTokens.insert(pair<string,int>("episodeimagewidth", series.episode.episodeImage.width));
+ intTokens.insert(pair<string,int>("episodeimageheight", series.episode.episodeImage.height));
+ stringTokens.insert(pair<string,string>("episodeimagepath", series.episode.episodeImage.path));
+ //Seasonposter
+ intTokens.insert(pair<string,int>("seasonposterwidth", series.seasonPoster.width));
+ intTokens.insert(pair<string,int>("seasonposterheight", series.seasonPoster.height));
+ stringTokens.insert(pair<string,string>("seasonposterpath", series.seasonPoster.path));
+
+ //Posters
+ int current = 1;
+ for(vector<cTvMedia>::iterator poster = series.posters.begin(); poster != series.posters.end(); poster++) {
+ stringstream labelWidth, labelHeight, labelPath;
+ labelWidth << "seriesposter" << current << "width";
+ labelHeight << "seriesposter" << current << "height";
+ labelPath << "seriesposter" << current << "path";
+
+ intTokens.insert(pair<string,int>(labelWidth.str(), (*poster).width));
+ intTokens.insert(pair<string,int>(labelHeight.str(), (*poster).height));
+ stringTokens.insert(pair<string,string>(labelPath.str(), (*poster).path));
+ current++;
+ }
+ if (current < 3) {
+ for (; current < 4; current++) {
+ stringstream labelWidth, labelHeight, labelPath;
+ labelWidth << "seriesposter" << current << "width";
+ labelHeight << "seriesposter" << current << "height";
+ labelPath << "seriesposter" << current << "path";
+
+ intTokens.insert(pair<string,int>(labelWidth.str(), 0));
+ intTokens.insert(pair<string,int>(labelHeight.str(), 0));
+ stringTokens.insert(pair<string,string>(labelPath.str(), ""));
+ }
+ }
+
+ //Banners
+ current = 1;
+ for(vector<cTvMedia>::iterator banner = series.banners.begin(); banner != series.banners.end(); banner++) {
+ stringstream labelWidth, labelHeight, labelPath;
+ labelWidth << "seriesbanner" << current << "width";
+ labelHeight << "seriesbanner" << current << "height";
+ labelPath << "seriesbanner" << current << "path";
+
+ intTokens.insert(pair<string,int>(labelWidth.str(), (*banner).width));
+ intTokens.insert(pair<string,int>(labelHeight.str(), (*banner).height));
+ stringTokens.insert(pair<string,string>(labelPath.str(), (*banner).path));
+ current++;
+ }
+ if (current < 3) {
+ for (; current < 4; current++) {
+ stringstream labelWidth, labelHeight, labelPath;
+ labelWidth << "seriesbanner" << current << "width";
+ labelHeight << "seriesbanner" << current << "height";
+ labelPath << "seriesbanner" << current << "path";
+
+ intTokens.insert(pair<string,int>(labelWidth.str(), 0));
+ intTokens.insert(pair<string,int>(labelHeight.str(), 0));
+ stringTokens.insert(pair<string,string>(labelPath.str(), ""));
+ }
+ }
+
+ //Fanarts
+ current = 1;
+ for(vector<cTvMedia>::iterator fanart = series.fanarts.begin(); fanart != series.fanarts.end(); fanart++) {
+ stringstream labelWidth, labelHeight, labelPath;
+ labelWidth << "seriesfanart" << current << "width";
+ labelHeight << "seriesfanart" << current << "height";
+ labelPath << "seriesfanart" << current << "path";
+
+ intTokens.insert(pair<string,int>(labelWidth.str(), (*fanart).width));
+ intTokens.insert(pair<string,int>(labelHeight.str(), (*fanart).height));
+ stringTokens.insert(pair<string,string>(labelPath.str(), (*fanart).path));
+ current++;
+ }
+ if (current < 3) {
+ for (; current < 4; current++) {
+ stringstream labelWidth, labelHeight, labelPath;
+ labelWidth << "seriesfanart" << current << "width";
+ labelHeight << "seriesfanart" << current << "height";
+ labelPath << "seriesfanart" << current << "path";
+
+ intTokens.insert(pair<string,int>(labelWidth.str(), 0));
+ intTokens.insert(pair<string,int>(labelHeight.str(), 0));
+ stringTokens.insert(pair<string,string>(labelPath.str(), ""));
+ }
+ }
+
+ //Actors
+ vector< map< string, string > > actors;
+ for (vector<cActor>::iterator act = series.actors.begin(); act != series.actors.end(); act++) {
+ map< string, string > actor;
+ actor.insert(pair<string, string>("actors[name]", (*act).name));
+ actor.insert(pair<string, string>("actors[role]", (*act).role));
+ actor.insert(pair<string, string>("actors[thumb]", (*act).actorThumb.path));
+ stringstream actWidth, actHeight;
+ actWidth << (*act).actorThumb.width;
+ actHeight << (*act).actorThumb.height;
+ actor.insert(pair<string, string>("actors[thumbwidth]", actWidth.str()));
+ actor.insert(pair<string, string>("actors[thumbheight]", actHeight.str()));
+ actors.push_back(actor);
+ }
+ loopTokens.insert(pair<string, vector< map< string, string > > >("actors", actors));
+
+ } else {
+ intTokens.insert(pair<string,int>("ismovie", false));
+ intTokens.insert(pair<string,int>("isseries", false));
+ }
+
+}
+
+void cDisplayMenuDetailView::InitTabs(void) {
+ tmplView->InitViewTabIterator();
+ cTemplateViewTab *tmplTab = NULL;
+ while(tmplTab = tmplView->GetNextViewTab()) {
+ tmplTab->ParseDynamicParameters(&intTokens, true);
+ tmplTab->ClearDynamicFunctionParameters();
+ tmplTab->ParseDynamicFunctionParameters(&stringTokens, &intTokens);
+ if (tmplTab->DoExecute()) {
+ activeTabs.push_back(tmplTab);
+ }
+ }
+ atIt = activeTabs.begin();
+}
+
+bool cDisplayMenuDetailView::LoadReruns(vector< map< string, string > > *reruns) {
+ if (!event)
+ return false;
+
+ cPlugin *epgSearchPlugin = cPluginManager::GetPlugin("epgsearch");
+ if (!epgSearchPlugin)
+ return false;
+
+ if (isempty(event->Title()))
+ return false;
+
+ int maxNumReruns = 10;
+
+ Epgsearch_searchresults_v1_0 data;
+ string strQuery = event->Title();
+ data.useSubTitle = true;
+ data.query = (char *)strQuery.c_str();
+ data.mode = 0;
+ data.channelNr = 0;
+ data.useTitle = true;
+ data.useDescription = false;
+
+ bool foundRerun = false;
+ if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) {
+ cList<Epgsearch_searchresults_v1_0::cServiceSearchResult>* list = data.pResultList;
+ if (list && (list->Count() > 1)) {
+ foundRerun = true;
+ int i = 0;
+ for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = list->First(); r && i < maxNumReruns; r = list->Next(r)) {
+ if ((event->ChannelID() == r->event->ChannelID()) && (event->StartTime() == r->event->StartTime()))
+ continue;
+ i++;
+ map< string, string > rerun;
+ rerun.insert(pair<string, string>("reruns[title]", r->event->Title() ? r->event->Title() : ""));
+ rerun.insert(pair<string, string>("reruns[shorttext]", r->event->ShortText() ? r->event->ShortText() : ""));
+ rerun.insert(pair<string, string>("reruns[start]", *(r->event->GetTimeString())));
+ rerun.insert(pair<string, string>("reruns[start]", *(r->event->GetTimeString())));
+ rerun.insert(pair<string, string>("reruns[stop]", *(r->event->GetEndTimeString())));
+ rerun.insert(pair<string, string>("reruns[date]", *ShortDateString(r->event->StartTime())));
+ rerun.insert(pair<string, string>("reruns[day]", *WeekDayName(r->event->StartTime())));
+ string channelID = *(r->event->ChannelID().ToString());
+ rerun.insert(pair<string, string>("reruns[channelid]", channelID));
+ bool logoExists = imgCache->LogoExists(channelID);
+ rerun.insert(pair<string, string>("reruns[channellogoexists]", logoExists ? "1" : "0"));
+
+ cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true);
+ if (channel) {
+ stringstream channelNumber;
+ channelNumber << channel->Number();
+ rerun.insert(pair<string, string>("reruns[channelname]", channel->ShortName(true)));
+ rerun.insert(pair<string, string>("reruns[channelnumber]", channelNumber.str()));
+ } else {
+ rerun.insert(pair<string, string>("reruns[channelname]", ""));
+ rerun.insert(pair<string, string>("reruns[channelnumber]", ""));
+ }
+ reruns->push_back(rerun);
+ }
+ delete list;
+ }
+ }
+ return foundRerun;
+}
+
+void cDisplayMenuDetailView::LoadRecordingInformation(void) {
+ const cRecordingInfo *Info = recording->Info();
+ if (!Info)
+ return;
+ unsigned long long nRecSize = -1;
+ unsigned long long nFileSize[1000];
+ nFileSize[0] = 0;
+ int i = 0;
+ struct stat filebuf;
+ cString filename;
+ int rc = 0;
+ do {
+ if (recording->IsPesRecording())
+ filename = cString::sprintf("%s/%03d.vdr", recording->FileName(), ++i);
+ else
+ filename = cString::sprintf("%s/%05d.ts", recording->FileName(), ++i);
+ rc = stat(filename, &filebuf);
+ if (rc == 0)
+ nFileSize[i] = nFileSize[i-1] + filebuf.st_size;
+ else
+ if (ENOENT != errno) {
+ nRecSize = -1;
+ }
+ } while (i <= 999 && !rc);
+ nRecSize = nFileSize[i-1];
+
+ cMarks marks;
+ bool fHasMarks = marks.Load(recording->FileName(), recording->FramesPerSecond(), recording->IsPesRecording()) && marks.Count();
+ cIndexFile *index = new cIndexFile(recording->FileName(), false, recording->IsPesRecording());
+
+ int nCutLength = 0;
+ long nCutInFrame = 0;
+ unsigned long long nRecSizeCut = nRecSize < 0 ? -1 : 0;
+ unsigned long long nCutInOffset = 0;
+
+ if (fHasMarks && index) {
+ uint16_t FileNumber;
+ off_t FileOffset;
+
+ bool fCutIn = true;
+ cMark *mark = marks.First();
+ while (mark) {
+ int pos = mark->Position();
+ index->Get(pos, &FileNumber, &FileOffset); //TODO: will disc spin up?
+ if (fCutIn) {
+ nCutInFrame = pos;
+ fCutIn = false;
+ if (nRecSize >= 0)
+ nCutInOffset = nFileSize[FileNumber-1] + FileOffset;
+ } else {
+ nCutLength += pos - nCutInFrame;
+ fCutIn = true;
+ if (nRecSize >= 0)
+ nRecSizeCut += nFileSize[FileNumber-1] + FileOffset - nCutInOffset;
+ }
+ cMark *nextmark = marks.Next(mark);
+ mark = nextmark;
+ }
+ if (!fCutIn) {
+ nCutLength += index->Last() - nCutInFrame;
+ index->Get(index->Last() - 1, &FileNumber, &FileOffset);
+ if (nRecSize >= 0)
+ nRecSizeCut += nFileSize[FileNumber-1] + FileOffset - nCutInOffset;
+ }
+ }
+
+ if (nRecSize < 0) {
+ if ((nRecSize = ReadSizeVdr(recording->FileName())) < 0) {
+ nRecSize = DirSizeMB(recording->FileName());
+ }
+ }
+ if (nRecSize >= 0) {
+ cString strRecSize = "";
+ cString strRecSizeCut = "";
+
+ if (fHasMarks) {
+ if (nRecSize > MEGABYTE(1023)) {
+ strRecSize = cString::sprintf("%.2f GB", (float)nRecSize / MEGABYTE(1024));
+ strRecSizeCut = cString::sprintf("%.2f GB", (float)nRecSizeCut / MEGABYTE(1024));
+ } else {
+ strRecSize = cString::sprintf("%lld MB", nRecSize / MEGABYTE(1));
+ strRecSizeCut = cString::sprintf("%lld MB", nRecSizeCut / MEGABYTE(1));
+ }
+ } else {
+ if (nRecSize > MEGABYTE(1023)) {
+ strRecSize = cString::sprintf("%.2f GB", (float)nRecSize / MEGABYTE(1024));
+ strRecSizeCut = strRecSize;
+ } else {
+ strRecSize = cString::sprintf("%lld MB", nRecSize / MEGABYTE(1));
+ strRecSizeCut = strRecSize;
+ }
+ }
+ stringTokens.insert(pair<string,string>("recordingsize", *strRecSize));
+ stringTokens.insert(pair<string,string>("recordingsizecutted", *strRecSizeCut));
+ } else {
+ stringTokens.insert(pair<string,string>("recordingsize", ""));
+ stringTokens.insert(pair<string,string>("recordingsizecutted", ""));
+ }
+
+ cChannel *channel = Channels.GetByChannelID(Info->ChannelID());
+ if (channel) {
+ stringTokens.insert(pair<string,string>("recchannelname", channel->Name()));
+ intTokens.insert(pair<string,int>("recchannelnumber", channel->Number()));
+ }
+
+ if (index) {
+ int nLastIndex = index->Last();
+ if (nLastIndex) {
+ string strLength = *IndexToHMSF(nLastIndex, false, recording->FramesPerSecond());
+ string strLengthCutted = "";
+ if (fHasMarks) {
+ strLengthCutted = *IndexToHMSF(nCutLength, false, recording->FramesPerSecond());
+ } else {
+ strLengthCutted = strLength;
+ }
+ string strBitrate = *cString::sprintf("%.2f MBit/s", (float)nRecSize / nLastIndex * recording->FramesPerSecond() * 8 / MEGABYTE(1));
+ stringTokens.insert(pair<string,string>("recordinglength", strLength));
+ stringTokens.insert(pair<string,string>("recordinglengthcutted", strLengthCutted));
+ stringTokens.insert(pair<string,string>("recordingbitrate", strBitrate));
+ }
+ delete index;
+ }
+
+ string recFormat = recording->IsPesRecording() ? "PES" : "TS";
+ stringTokens.insert(pair<string,string>("recordingformat", recFormat));
+
+ bool searchTimerFound = false;
+ if (Info) {
+ const char *aux = NULL;
+ aux = Info->Aux();
+ if (aux) {
+ string strAux = aux;
+ string auxEpgsearch = StripXmlTag(strAux, "epgsearch");
+ if (!auxEpgsearch.empty()) {
+ string searchTimer = StripXmlTag(auxEpgsearch, "searchtimer");
+ if (!searchTimer.empty()) {
+ stringTokens.insert(pair<string,string>("searchtimer", searchTimer));
+ searchTimerFound = true;
+ }
+ }
+ }
+ }
+ if (!searchTimerFound)
+ stringTokens.insert(pair<string,string>("searchtimer", "n.a."));
+}
+
+string cDisplayMenuDetailView::StripXmlTag(string &Line, const char *Tag) {
+ // set the search strings
+ stringstream strStart, strStop;
+ strStart << "<" << Tag << ">";
+ strStop << "</" << Tag << ">";
+ // find the strings
+ string::size_type locStart = Line.find(strStart.str());
+ string::size_type locStop = Line.find(strStop.str());
+ if (locStart == string::npos || locStop == string::npos)
+ return "";
+ // extract relevant text
+ int pos = locStart + strStart.str().size();
+ int len = locStop - pos;
+ return len < 0 ? "" : Line.substr(pos, len);
+}
+
+
+int cDisplayMenuDetailView::ReadSizeVdr(const char *strPath) {
+ int dirSize = -1;
+ char buffer[20];
+ char *strFilename = NULL;
+ if (-1 != asprintf(&strFilename, "%s/size.vdr", strPath)) {
+ struct stat st;
+ if (stat(strFilename, &st) == 0) {
+ int fd = open(strFilename, O_RDONLY);
+ if (fd >= 0) {
+ if (safe_read(fd, &buffer, sizeof(buffer)) >= 0) {
+ dirSize = atoi(buffer);
+ }
+ close(fd);
+ }
+ }
+ free(strFilename);
+ }
+ return dirSize;
+}
+
+void cDisplayMenuDetailView::SetEpgPictures(int eventId) {
+ for (int i=0; i<3; i++) {
+ stringstream picName;
+ picName << eventId << "_" << i;
+ bool epgPicAvailable = FileExists(*config.epgImagePath, picName.str(), "jpg");
+ stringstream available;
+ stringstream path;
+ available << "epgpic" << i+1 << "avaialble";
+ path << "epgpic" << i+1 << "path";
+ if (epgPicAvailable) {
+ intTokens.insert(pair<string,int>(available.str(), true));
+ stringTokens.insert(pair<string,string>(path.str(), *cString::sprintf("%s%s.jpg", *config.epgImagePath, picName.str().c_str())));
+ } else {
+ intTokens.insert(pair<string,int>(available.str(), false));
+ stringTokens.insert(pair<string,string>(path.str(), ""));
+ }
+ }
+}
+
+void cDisplayMenuDetailView::SetRecordingImages(const char *recPath) {
+ if (!recPath) {
+ intTokens.insert(pair<string,int>("recimg1avaialble", false));
+ intTokens.insert(pair<string,int>("recimg2avaialble", false));
+ intTokens.insert(pair<string,int>("recimg3avaialble", false));
+ stringTokens.insert(pair<string,string>("recimg1path", ""));
+ stringTokens.insert(pair<string,string>("recimg2path", ""));
+ stringTokens.insert(pair<string,string>("recimg3path", ""));
+ return;
+ }
+
+ string path = recPath;
+ DIR *dirHandle;
+ struct dirent *dirEntry;
+ dirHandle = opendir(recPath);
+ if (!dirHandle) {
+ intTokens.insert(pair<string,int>("recimg1avaialble", false));
+ intTokens.insert(pair<string,int>("recimg2avaialble", false));
+ intTokens.insert(pair<string,int>("recimg3avaialble", false));
+ stringTokens.insert(pair<string,string>("recimg1path", ""));
+ stringTokens.insert(pair<string,string>("recimg2path", ""));
+ stringTokens.insert(pair<string,string>("recimg3path", ""));
+ return;
+ }
+
+ int picsFound = 0;
+ while ( 0 != (dirEntry = readdir(dirHandle))) {
+ if (endswith(dirEntry->d_name, "jpg")) {
+ string fileName = dirEntry->d_name;
+ stringstream available;
+ available << "recimg" << picsFound+1 << "avaialble";
+ stringstream path;
+ path << "recimg" << picsFound+1 << "path";
+ intTokens.insert(pair<string,int>(available.str(), true));
+ stringTokens.insert(pair<string,string>(path.str(), *cString::sprintf("%s/%s", recPath, fileName.c_str())));
+ picsFound++;
+ }
+ if (picsFound == 3) {
+ break;
+ }
+ }
+ for (int i=picsFound; i<3; i++) {
+ stringstream available;
+ available << "recimg" << i+1 << "avaialble";
+ stringstream path;
+ path << "recimg" << i+1 << "path";
+ intTokens.insert(pair<string,int>(available.str(), false));
+ stringTokens.insert(pair<string,string>(path.str(), ""));
+ }
+ closedir(dirHandle);
+}
+
+void cDisplayMenuDetailView::DrawHeader(void) {
+ map < string, string > headerStringTokens;
+ map < string, int > headerIntTokens;
+
+ if (event || recording) {
+ static cPlugin *pScraper = GetScraperPlugin();
+ if (!pScraper) {
+ headerIntTokens.insert(pair<string,int>("ismovie", false));
+ headerIntTokens.insert(pair<string,int>("isseries", false));
+ headerIntTokens.insert(pair<string,int>("posteravailable", false));
+ headerIntTokens.insert(pair<string,int>("banneravailable", false));
+ } else {
+ ScraperGetEventType getType;
+ getType.event = event;
+ getType.recording = recording;
+ if (!pScraper->Service("GetEventType", &getType)) {
+ headerIntTokens.insert(pair<string,int>("ismovie", false));
+ headerIntTokens.insert(pair<string,int>("isseries", false));
+ headerIntTokens.insert(pair<string,int>("posteravailable", false));
+ headerIntTokens.insert(pair<string,int>("banneravailable", false));
+ } else {
+ if (getType.type == tMovie) {
+ cMovie movie;
+ movie.movieId = getType.movieId;
+ pScraper->Service("GetMovie", &movie);
+ headerIntTokens.insert(pair<string,int>("ismovie", true));
+ headerIntTokens.insert(pair<string,int>("isseries", false));
+ headerIntTokens.insert(pair<string,int>("posteravailable", true));
+ headerIntTokens.insert(pair<string,int>("banneravailable", false));
+ headerStringTokens.insert(pair<string,string>("posterpath", movie.poster.path));
+ headerIntTokens.insert(pair<string,int>("posterwidth", movie.poster.width));
+ headerIntTokens.insert(pair<string,int>("posterheight", movie.poster.height));
+ } else if (getType.type == tSeries) {
+ cSeries series;
+ series.seriesId = getType.seriesId;
+ series.episodeId = getType.episodeId;
+ pScraper->Service("GetSeries", &series);
+ headerIntTokens.insert(pair<string,int>("ismovie", false));
+ headerIntTokens.insert(pair<string,int>("isseries", true));
+ vector<cTvMedia>::iterator poster = series.posters.begin();
+ if (poster != series.posters.end()) {
+ headerIntTokens.insert(pair<string,int>("posterwidth", (*poster).width));
+ headerIntTokens.insert(pair<string,int>("posterheight", (*poster).height));
+ headerStringTokens.insert(pair<string,string>("posterpath", (*poster).path));
+ headerIntTokens.insert(pair<string,int>("posteravailable", true));
+ } else {
+ headerIntTokens.insert(pair<string,int>("posterwidth", 0));
+ headerIntTokens.insert(pair<string,int>("posterheight", 0));
+ headerStringTokens.insert(pair<string,string>("posterpath", ""));
+ headerIntTokens.insert(pair<string,int>("posteravailable", false));
+ }
+ vector<cTvMedia>::iterator banner = series.banners.begin();
+ if (banner != series.banners.end()) {
+ headerIntTokens.insert(pair<string,int>("bannerwidth", (*banner).width));
+ headerIntTokens.insert(pair<string,int>("bannerheight", (*banner).height));
+ headerStringTokens.insert(pair<string,string>("bannerpath", (*banner).path));
+ headerIntTokens.insert(pair<string,int>("banneravailable", true));
+ } else {
+ headerIntTokens.insert(pair<string,int>("bannerwidth", 0));
+ headerIntTokens.insert(pair<string,int>("bannerheight", 0));
+ headerStringTokens.insert(pair<string,string>("bannerpath", ""));
+ headerIntTokens.insert(pair<string,int>("banneravailable", false));
+ }
+ } else {
+ headerIntTokens.insert(pair<string,int>("ismovie", false));
+ headerIntTokens.insert(pair<string,int>("isseries", false));
+ headerIntTokens.insert(pair<string,int>("posteravailable", false));
+ headerIntTokens.insert(pair<string,int>("banneravailable", false));
+ }
+ }
+ }
+ }
+
+ if (event) {
+ headerStringTokens.insert(pair<string,string>("title", event->Title() ? event->Title() : ""));
+ headerStringTokens.insert(pair<string,string>("shorttext", event->ShortText() ? event->ShortText() : ""));
+ headerStringTokens.insert(pair<string,string>("start", *(event->GetTimeString())));
+ headerStringTokens.insert(pair<string,string>("stop", *(event->GetEndTimeString())));
+ headerStringTokens.insert(pair<string,string>("day", *WeekDayName(event->StartTime())));
+ headerStringTokens.insert(pair<string,string>("date", *ShortDateString(event->StartTime())));
+ headerStringTokens.insert(pair<string,string>("channelid", *(event->ChannelID().ToString())));
+
+ bool isRunning = false;
+ time_t now = time(NULL);
+ if ((now >= event->StartTime()) && (now <= event->EndTime()))
+ isRunning = true;
+ headerIntTokens.insert(pair<string,int>("running", isRunning));
+ if (isRunning) {
+ headerIntTokens.insert(pair<string,int>("elapsed", (now - event->StartTime())/60));
+ } else {
+ headerIntTokens.insert(pair<string,int>("elapsed", 0));
+ }
+ headerIntTokens.insert(pair<string,int>("duration", event->Duration() / 60));
+
+ stringstream epgImageName;
+ epgImageName << event->EventID();
+ bool epgPicAvailable = FileExists(*config.epgImagePath, epgImageName.str(), "jpg");
+ if (epgPicAvailable) {
+ headerIntTokens.insert(pair<string,int>("epgpicavailable", true));
+ headerStringTokens.insert(pair<string,string>("epgpicpath", *cString::sprintf("%s%s.jpg", *config.epgImagePath, epgImageName.str().c_str())));
+ } else {
+ epgImageName << "_0";
+ epgPicAvailable = FileExists(*config.epgImagePath, epgImageName.str(), "jpg");
+ if (epgPicAvailable) {
+ headerIntTokens.insert(pair<string,int>("epgpicavailable", true));
+ headerStringTokens.insert(pair<string,string>("epgpicpath", *cString::sprintf("%s%s.jpg", *config.epgImagePath, epgImageName.str().c_str())));
+ } else {
+ headerIntTokens.insert(pair<string,int>("epgpicavailable", false));
+ headerStringTokens.insert(pair<string,string>("epgpicpath", ""));
+ }
+ }
+
+ DrawViewElement(veDetailHeader, &headerStringTokens, &headerIntTokens);
+ } else if (recording) {
+ string name = recording->Name() ? recording->Name() : "";
+ headerStringTokens.insert(pair<string,string>("name", name));
+
+ const cRecordingInfo *info = recording->Info();
+ if (info) {
+ headerStringTokens.insert(pair<string,string>("shorttext", info->ShortText() ? info->ShortText() : ""));
+ const cEvent *event = info->GetEvent();
+ if (event) {
+ string recDate = *(event->GetDateString());
+ string recTime = *(event->GetTimeString());
+ if (recDate.find("1970") != string::npos) {
+ time_t start = recording->Start();
+ recDate = *DateString(start);
+ recTime = *TimeString(start);
+ }
+ int duration = event->Duration() / 60;
+ int recDuration = recording->LengthInSeconds();
+ recDuration = (recDuration>0)?(recDuration / 60):0;
+ headerStringTokens.insert(pair<string,string>("date", recDate.c_str()));
+ headerStringTokens.insert(pair<string,string>("time", recTime.c_str()));
+ headerIntTokens.insert(pair<string,int>("duration", recDuration));
+ headerIntTokens.insert(pair<string,int>("durationevent", duration));
+ }
+ } else {
+ headerStringTokens.insert(pair<string,string>("shorttext", ""));
+ int recDuration = recording->LengthInSeconds();
+ recDuration = (recDuration>0)?(recDuration / 60):0;
+ headerStringTokens.insert(pair<string,string>("date", ""));
+ headerStringTokens.insert(pair<string,string>("time", ""));
+ headerIntTokens.insert(pair<string,int>("duration", recDuration));
+ headerIntTokens.insert(pair<string,int>("durationevent", 0));
+ }
+
+ string recImage = "";
+ string path = recording->FileName() ? recording->FileName() : "";
+ string extension = ".jpg";
+ if (FirstFileInFolder(path, extension, recImage)) {
+ headerIntTokens.insert(pair<string,int>("recimgavailable", true));
+ headerStringTokens.insert(pair<string,string>("recimgpath", *cString::sprintf("%s/%s", path.c_str(), recImage.c_str())));
+ } else {
+ headerIntTokens.insert(pair<string,int>("recimgavailable", false));
+ headerStringTokens.insert(pair<string,string>("recimgpath", ""));
+ }
+ DrawViewElement(veDetailHeader, &headerStringTokens, &headerIntTokens);
+ }
+}
+
+void cDisplayMenuDetailView::DrawScrollbar(void) {
+ map < string, string > scrollbarStringTokens;
+ map < string, int > scrollbarIntTokens;
+
+ int barTop = 0;
+ int barHeight = 0;
+ tabView->GetScrollbarPosition(barTop, barHeight);
+
+ scrollbarIntTokens.insert(pair<string,int>("height", barHeight));
+ scrollbarIntTokens.insert(pair<string,int>("offset", barTop));
+ ClearViewElement(veScrollbar);
+ DrawViewElement(veScrollbar, &scrollbarStringTokens, &scrollbarIntTokens);
+}
+
+void cDisplayMenuDetailView::DrawTabLabels(void) {
+ if (!ViewElementImplemented(veTabLabels)) {
+ return;
+ }
+ map < string, string > labelStringTokens;
+ map < string, int > labelIntTokens;
+ map < string, vector< map< string, string > > > labelLoopTokens;
+
+ vector< map< string, string > > tabLabels;
+ for (list<cTemplateViewTab*>::iterator it = activeTabs.begin(); it != activeTabs.end(); it++) {
+ cTemplateViewTab *tab = *it;
+ map< string, string > tabLabel;
+ tabLabel.insert(pair< string, string >("tabs[title]", tab->GetName()));
+ if (tab == currentTmplTab) {
+ tabLabel.insert(pair< string, string >("tabs[current]", "1"));
+ } else {
+ tabLabel.insert(pair< string, string >("tabs[current]", "0"));
+ }
+ tabLabels.push_back(tabLabel);
+ }
+ labelLoopTokens.insert(pair< string, vector< map< string, string > > >("tabs", tabLabels));
+
+ ClearViewElement(veTabLabels);
+ DrawViewElement(veTabLabels, &labelStringTokens, &labelIntTokens, &labelLoopTokens);
+}
+
+cTemplateViewTab *cDisplayMenuDetailView::GetPrevTab(void) {
+ if (atIt == activeTabs.begin()) {
+ atIt = activeTabs.end();
+ }
+ atIt--;
+ return *atIt;
+}
+
+cTemplateViewTab *cDisplayMenuDetailView::GetNextTab(void) {
+ atIt++;
+ if (atIt == activeTabs.end()) {
+ atIt = activeTabs.begin();
+ }
+ return *atIt;
+}
diff --git a/views/displaymenudetailview.h b/views/displaymenudetailview.h
new file mode 100644
index 0000000..c739a28
--- /dev/null
+++ b/views/displaymenudetailview.h
@@ -0,0 +1,50 @@
+#ifndef __DISPLAYMENUDETAILVIEW_H
+#define __DISPLAYMENUDETAILVIEW_H
+
+#include <list>
+#include "../libtemplate/template.h"
+#include "view.h"
+#include "displaymenutabview.h"
+
+class cDisplayMenuDetailView : public cView {
+private:
+ bool detailViewInit;
+ const cEvent *event;
+ const cRecording *recording;
+ const char *text;
+ cTemplateViewTab *currentTmplTab;
+ list<cTemplateViewTab*> activeTabs;
+ list<cTemplateViewTab*>::iterator atIt;
+ cDisplayMenuTabView *tabView;
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ map < string, vector< map< string, string > > > loopTokens;
+ void SetTokens(void);
+ void SetScraperTokens(void);
+ void InitTabs(void);
+ bool LoadReruns(vector< map< string, string > > *reruns);
+ void LoadRecordingInformation(void);
+ void SetEpgPictures(int eventId);
+ void SetRecordingImages(const char *recPath);
+ string StripXmlTag(string &Line, const char *Tag);
+ int ReadSizeVdr(const char *strPath);
+ void DrawHeader(void);
+ void DrawScrollbar(void);
+ void DrawTabLabels(void);
+ cTemplateViewTab *GetPrevTab(void);
+ cTemplateViewTab *GetNextTab(void);
+public:
+ cDisplayMenuDetailView(cTemplateView *tmplDetailView);
+ virtual ~cDisplayMenuDetailView();
+ void SetEvent(const cEvent *event) { this->event = event; };
+ void SetRecording(const cRecording *recording) { this->recording = recording; };
+ void SetText(const char *text) { this->text = text; };
+ void Clear(void);
+ void Render(void);
+ void KeyLeft(void);
+ void KeyRight(void);
+ void KeyUp(void);
+ void KeyDown(void);
+};
+
+#endif //__DISPLAYMENUDETAILVIEW_H
diff --git a/views/displaymenuitemcurrentview.c b/views/displaymenuitemcurrentview.c
new file mode 100644
index 0000000..a615794
--- /dev/null
+++ b/views/displaymenuitemcurrentview.c
@@ -0,0 +1,561 @@
+#include "../services/scraper2vdr.h"
+#include "../libcore/helpers.h"
+#include "displaymenuitemcurrentview.h"
+
+
+cDisplayMenuItemCurrentView::cDisplayMenuItemCurrentView(cTemplateViewElement *tmplCurrent) : cView(tmplCurrent) {
+ delay = tmplItem->GetNumericParameter(ptDelay);
+ SetFadeTime(tmplItem->GetNumericParameter(ptFadeTime));
+}
+
+cDisplayMenuItemCurrentView::~cDisplayMenuItemCurrentView() {
+ CancelSave();
+}
+
+void cDisplayMenuItemCurrentView::SetPosMenuItem(cRect &pos) {
+ posMenuItem.SetX(pos.X());
+ posMenuItem.SetY(pos.Y());
+ posMenuItem.SetWidth(pos.Width());
+ posMenuItem.SetHeight(pos.Height());
+}
+
+void cDisplayMenuItemCurrentView::SetTokensPosMenuItem(void) {
+ intTokens.insert(pair<string,int>("menuitemx", posMenuItem.X()));
+ intTokens.insert(pair<string,int>("menuitemy", posMenuItem.Y()));
+ intTokens.insert(pair<string,int>("menuitemwidth", posMenuItem.Width()));
+ intTokens.insert(pair<string,int>("menuitemheight", posMenuItem.Height()));
+}
+
+void cDisplayMenuItemCurrentView::SetScraperPoster(const cEvent *event, const cRecording *recording) {
+ static cPlugin *pScraper = GetScraperPlugin();
+ if (!pScraper || (!event && !recording)) {
+ intTokens.insert(pair<string,int>("hasposter", false));
+ intTokens.insert(pair<string,int>("posterwidth", -1));
+ intTokens.insert(pair<string,int>("posterheight", -1));
+ stringTokens.insert(pair<string,string>("posterpath", ""));
+ return;
+ }
+
+ ScraperGetPoster call;
+ call.event = event;
+ call.recording = recording;
+ if (pScraper->Service("GetPoster", &call)) {
+ intTokens.insert(pair<string,int>("hasposter", true));
+ intTokens.insert(pair<string,int>("posterwidth", call.poster.width));
+ intTokens.insert(pair<string,int>("posterheight", call.poster.height));
+ stringTokens.insert(pair<string,string>("posterpath", call.poster.path));
+ } else {
+ intTokens.insert(pair<string,int>("hasposter", false));
+ intTokens.insert(pair<string,int>("posterwidth", -1));
+ intTokens.insert(pair<string,int>("posterheight", -1));
+ stringTokens.insert(pair<string,string>("posterpath", ""));
+ }
+}
+
+/*************************************************************
+* cDisplayMenuItemCurrentMainView
+*************************************************************/
+
+cDisplayMenuItemCurrentMainView::cDisplayMenuItemCurrentMainView(cTemplateViewElement *tmplCurrent, string number, string label, string icon)
+ : cDisplayMenuItemCurrentView(tmplCurrent) {
+ this->number = number;
+ this->label = label;
+ this->icon = icon;
+}
+
+cDisplayMenuItemCurrentMainView::~cDisplayMenuItemCurrentMainView() {
+}
+
+void cDisplayMenuItemCurrentMainView::Prepare(void) {
+}
+
+
+void cDisplayMenuItemCurrentMainView::Render(void) {
+ stringTokens.insert(pair<string,string>("number", number));
+ stringTokens.insert(pair<string,string>("label", label));
+ stringTokens.insert(pair<string,string>("icon", icon));
+ SetTokensPosMenuItem();
+ DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens);
+}
+
+void cDisplayMenuItemCurrentMainView::Clear(void) {
+
+}
+
+void cDisplayMenuItemCurrentMainView::Action(void) {
+ SetInitFinished();
+ DoSleep(delay);
+ Render();
+ FadeIn();
+ DoFlush();
+ if (scrolling) {
+ DoSleep(scrollDelay);
+ if (scrollOrientation == orHorizontal) {
+ ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode);
+ } else {
+ ScrollVertical(scrollingPix, scrollDelay, scrollSpeed);
+ }
+ }
+}
+
+/*************************************************************
+* cDisplayMenuItemCurrentSchedulesView
+*************************************************************/
+
+cDisplayMenuItemCurrentSchedulesView::cDisplayMenuItemCurrentSchedulesView(cTemplateViewElement *tmplCurrent, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch, eMenuCategory cat)
+ : cDisplayMenuItemCurrentView(tmplCurrent) {
+ this->event = event;
+ this->channel = channel;
+ this->timerMatch = timerMatch;
+ this->cat = cat;
+}
+
+cDisplayMenuItemCurrentSchedulesView::~cDisplayMenuItemCurrentSchedulesView() {
+}
+
+void cDisplayMenuItemCurrentSchedulesView::Prepare(void) {
+}
+
+
+void cDisplayMenuItemCurrentSchedulesView::Render(void) {
+ intTokens.insert(pair<string,int>("whatson", (cat == mcSchedule) ? true: false));
+ intTokens.insert(pair<string,int>("whatsonnow", (cat == mcScheduleNow) ? true: false));
+ intTokens.insert(pair<string,int>("whatsonnext", (cat == mcScheduleNext) ? true: false));
+ if (timerMatch == tmFull) {
+ intTokens.insert(pair<string,int>("timerpartitial", false));
+ intTokens.insert(pair<string,int>("timerfull", true));
+ } else if (timerMatch == tmPartial) {
+ intTokens.insert(pair<string,int>("timerpartitial", true));
+ intTokens.insert(pair<string,int>("timerfull", false));
+ } else {
+ intTokens.insert(pair<string,int>("timerpartitial", false));
+ intTokens.insert(pair<string,int>("timerfull", false));
+ }
+
+ if (event) {
+ stringTokens.insert(pair<string,string>("title", event->Title() ? event->Title() : ""));
+ stringTokens.insert(pair<string,string>("shorttext", event->ShortText() ? event->ShortText() : ""));
+ stringTokens.insert(pair<string,string>("description", event->Description() ? event->Description() : ""));
+ stringTokens.insert(pair<string,string>("start", *(event->GetTimeString())));
+ stringTokens.insert(pair<string,string>("stop", *(event->GetEndTimeString())));
+ stringTokens.insert(pair<string,string>("day", *WeekDayName(event->StartTime())));
+ stringTokens.insert(pair<string,string>("date", *ShortDateString(event->StartTime())));
+ bool isRunning = false;
+ time_t now = time(NULL);
+ if ((now >= event->StartTime()) && (now <= event->EndTime()))
+ isRunning = true;
+ intTokens.insert(pair<string,int>("running", isRunning));
+ if (isRunning) {
+ intTokens.insert(pair<string,int>("elapsed", (now - event->StartTime())/60));
+ } else {
+ intTokens.insert(pair<string,int>("elapsed", 0));
+ }
+ intTokens.insert(pair<string,int>("duration", event->Duration() / 60));
+ SetScraperPoster(event);
+ }
+ if (channel) {
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+ }
+
+ vector< map<string,string> > schedulesTokens;
+ if (cat == mcScheduleNow || cat == mcScheduleNext) {
+ ReadSchedules(&schedulesTokens);
+ }
+ map < string, vector< map< string, string > > > loopTokens;
+ loopTokens.insert(pair<string, vector< map< string, string > > >("schedule", schedulesTokens));
+ SetTokensPosMenuItem();
+ DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens, &loopTokens);
+}
+
+void cDisplayMenuItemCurrentSchedulesView::Clear(void) {
+
+}
+
+void cDisplayMenuItemCurrentSchedulesView::Action(void) {
+ SetInitFinished();
+ DoSleep(delay);
+ Render();
+ FadeIn();
+ DoFlush();
+ if (scrolling) {
+ DoSleep(scrollDelay);
+ if (scrollOrientation == orHorizontal) {
+ ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode);
+ } else {
+ ScrollVertical(scrollingPix, scrollDelay, scrollSpeed);
+ }
+ }
+}
+
+void cDisplayMenuItemCurrentSchedulesView::ReadSchedules(vector< map<string,string> > *schedulesTokens) {
+ if (!event)
+ return;
+ const cSchedule *schedule = event->Schedule();
+ const cEvent *curEvent = event;
+ int num = 0;
+ for (; curEvent; curEvent = schedule->Events()->Next(curEvent)) {
+ if (num == 0) {
+ num++;
+ continue;
+ }
+ map<string,string> element;
+ element.insert(pair<string,string>("schedule[start]", *(curEvent->GetTimeString())));
+ element.insert(pair<string,string>("schedule[stop]", *(curEvent->GetEndTimeString())));
+ element.insert(pair<string,string>("schedule[title]", curEvent->Title() ? curEvent->Title() : ""));
+ element.insert(pair<string,string>("schedule[shorttext]", curEvent->ShortText() ? curEvent->ShortText() : ""));
+ schedulesTokens->push_back(element);
+ num++;
+ if (num > 10)
+ break;
+ }
+}
+
+/*************************************************************
+* cDisplayMenuItemCurrentChannelView
+*************************************************************/
+
+cDisplayMenuItemCurrentChannelView::cDisplayMenuItemCurrentChannelView(cTemplateViewElement *tmplCurrent, const cChannel *channel)
+ : cDisplayMenuItemCurrentView(tmplCurrent) {
+ this->channel = channel;
+}
+
+cDisplayMenuItemCurrentChannelView::~cDisplayMenuItemCurrentChannelView() {
+}
+
+void cDisplayMenuItemCurrentChannelView::Prepare(void) {
+}
+
+
+void cDisplayMenuItemCurrentChannelView::Render(void) {
+ if (!channel)
+ return;
+ //general channel information
+ intTokens.insert(pair<string,int>("number", channel->Number()));
+ intTokens.insert(pair<string,int>("transponder", channel->Transponder()));
+ intTokens.insert(pair<string,int>("frequency", channel->Frequency()));
+
+ stringTokens.insert(pair<string,string>("name", channel->Name() ? channel->Name() : ""));
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+
+ //Channel Source Information
+ const cSource *source = Sources.Get(channel->Source());
+ if (source) {
+ stringTokens.insert(pair<string,string>("source", *cSource::ToString(source->Code())));
+ stringTokens.insert(pair<string,string>("sourcedescription", source->Description() ? source->Description() : ""));
+ stringTokens.insert(pair<string,string>("source", *cSource::ToString(source->Code())));
+ intTokens.insert(pair<string,int>("isAtsc", source->IsAtsc(source->Code())));
+ intTokens.insert(pair<string,int>("isCable", source->IsCable(source->Code())));
+ intTokens.insert(pair<string,int>("isSat", source->IsSat(source->Code())));
+ intTokens.insert(pair<string,int>("isTerr", source->IsTerr(source->Code())));
+ }
+
+ //current schedule
+ cSchedulesLock schedulesLock;
+ const cSchedules *schedules = cSchedules::Schedules(schedulesLock);
+ const cSchedule *schedule = NULL;
+ schedule = schedules->GetSchedule(channel);
+ if (schedule) {
+ const cEvent *presentEvent = schedule->GetPresentEvent();
+ if (presentEvent) {
+ stringTokens.insert(pair<string,string>("presenteventtitle", presentEvent->Title() ? presentEvent->Title() : ""));
+ stringTokens.insert(pair<string,string>("presenteventshorttext", presentEvent->ShortText() ? presentEvent->ShortText() : ""));
+ stringTokens.insert(pair<string,string>("presenteventdescription", presentEvent->Description() ? presentEvent->Description() : ""));
+ stringTokens.insert(pair<string,string>("presenteventstart", *presentEvent->GetTimeString()));
+ stringTokens.insert(pair<string,string>("presenteventstop", *presentEvent->GetEndTimeString()));
+ stringTokens.insert(pair<string,string>("presenteventday", *WeekDayName(presentEvent->StartTime())));
+ stringTokens.insert(pair<string,string>("presenteventdate", *ShortDateString(presentEvent->StartTime())));
+ intTokens.insert(pair<string,int>("presenteventelapsed", (time(0) - presentEvent->StartTime())/60));
+ intTokens.insert(pair<string,int>("presenteventduration", presentEvent->Duration() / 60));
+ SetScraperPoster(presentEvent);
+ } else {
+ stringTokens.insert(pair<string,string>("presenteventtitle", ""));
+ stringTokens.insert(pair<string,string>("presenteventshorttext", ""));
+ stringTokens.insert(pair<string,string>("presenteventdescription", ""));
+ stringTokens.insert(pair<string,string>("presenteventstart", ""));
+ stringTokens.insert(pair<string,string>("presenteventstop", ""));
+ stringTokens.insert(pair<string,string>("presenteventday", ""));
+ stringTokens.insert(pair<string,string>("presenteventdate", ""));
+ intTokens.insert(pair<string,int>("presenteventelapsed", 0));
+ intTokens.insert(pair<string,int>("presenteventduration", 0));
+ }
+ const cList<cEvent> *events = schedule->Events();
+ bool inserted = false;
+ if (events && presentEvent) {
+ const cEvent *nextEvent = events->Next(presentEvent);
+ if (nextEvent) {
+ stringTokens.insert(pair<string,string>("nexteventtitle", nextEvent->Title() ? nextEvent->Title() : ""));
+ stringTokens.insert(pair<string,string>("nexteventshorttext", nextEvent->ShortText() ? nextEvent->ShortText() : ""));
+ stringTokens.insert(pair<string,string>("nexteventdescription", nextEvent->Description() ? nextEvent->Description() : ""));
+ stringTokens.insert(pair<string,string>("nexteventstart", *nextEvent->GetTimeString()));
+ stringTokens.insert(pair<string,string>("nexteventstop", *nextEvent->GetEndTimeString()));
+ stringTokens.insert(pair<string,string>("nexteventday", *WeekDayName(nextEvent->StartTime())));
+ stringTokens.insert(pair<string,string>("nexteventdate", *ShortDateString(nextEvent->StartTime())));
+ intTokens.insert(pair<string,int>("nexteventduration", nextEvent->Duration() / 60));
+ inserted = true;
+ }
+ }
+ if (!inserted) {
+ stringTokens.insert(pair<string,string>("nexteventtitle", ""));
+ stringTokens.insert(pair<string,string>("nexteventshorttext", ""));
+ stringTokens.insert(pair<string,string>("nexteventdescription", ""));
+ stringTokens.insert(pair<string,string>("nexteventstart", ""));
+ stringTokens.insert(pair<string,string>("nexteventstop", ""));
+ stringTokens.insert(pair<string,string>("nexteventday", ""));
+ stringTokens.insert(pair<string,string>("nexteventdate", ""));
+ intTokens.insert(pair<string,int>("nexteventduration", 0));
+ }
+ }
+
+ vector< map<string,string> > schedulesTokens;
+ ReadSchedules(&schedulesTokens);
+
+ map < string, vector< map< string, string > > > loopTokens;
+ loopTokens.insert(pair<string, vector< map< string, string > > >("schedule", schedulesTokens));
+ SetTokensPosMenuItem();
+ DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens, &loopTokens);
+}
+
+void cDisplayMenuItemCurrentChannelView::Clear(void) {
+
+}
+
+void cDisplayMenuItemCurrentChannelView::Action(void) {
+ SetInitFinished();
+ DoSleep(delay);
+ Render();
+ FadeIn();
+ DoFlush();
+ if (scrolling) {
+ DoSleep(scrollDelay);
+ if (scrollOrientation == orHorizontal) {
+ ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode);
+ } else {
+ ScrollVertical(scrollingPix, scrollDelay, scrollSpeed);
+ }
+ }
+}
+
+void cDisplayMenuItemCurrentChannelView::ReadSchedules(vector< map<string,string> > *schedulesTokens) {
+ cSchedulesLock schedulesLock;
+ const cSchedules *schedules = cSchedules::Schedules(schedulesLock);
+ const cSchedule *schedule = NULL;
+ schedule = schedules->GetSchedule(channel);
+ if (!schedule) {
+ return;
+ }
+ const cEvent *curEvent = schedule->GetPresentEvent();
+ int num = 0;
+ for (; curEvent; curEvent = schedule->Events()->Next(curEvent)) {
+ if (num < 2) {
+ num++;
+ continue;
+ }
+ map<string,string> element;
+ element.insert(pair<string,string>("schedule[start]", *(curEvent->GetTimeString())));
+ element.insert(pair<string,string>("schedule[stop]", *(curEvent->GetEndTimeString())));
+ element.insert(pair<string,string>("schedule[title]", curEvent->Title() ? curEvent->Title() : ""));
+ element.insert(pair<string,string>("schedule[shorttext]", curEvent->ShortText() ? curEvent->ShortText() : ""));
+ schedulesTokens->push_back(element);
+ num++;
+ if (num > 11)
+ break;
+ }
+}
+
+/*************************************************************
+* cDisplayMenuItemCurrentTimerView
+*************************************************************/
+
+cDisplayMenuItemCurrentTimerView::cDisplayMenuItemCurrentTimerView(cTemplateViewElement *tmplCurrent, const cTimer *timer)
+ : cDisplayMenuItemCurrentView(tmplCurrent) {
+ this->timer = timer;
+}
+
+cDisplayMenuItemCurrentTimerView::~cDisplayMenuItemCurrentTimerView() {
+}
+
+void cDisplayMenuItemCurrentTimerView::Prepare(void) {
+}
+
+
+void cDisplayMenuItemCurrentTimerView::Render(void) {
+ if (!timer)
+ return;
+ intTokens.insert(pair<string,int>("flagactive", timer->HasFlags(tfActive)));
+ intTokens.insert(pair<string,int>("flaginstant", timer->HasFlags(tfInstant)));
+ intTokens.insert(pair<string,int>("flagvps", timer->HasFlags(tfVps)));
+ intTokens.insert(pair<string,int>("flagrecording", timer->Recording()));
+ intTokens.insert(pair<string,int>("flagpending", timer->Pending()));
+
+ const char *file = Setup.FoldersInTimerMenu ? NULL : strrchr(timer->File(), FOLDERDELIMCHAR);
+ if (file && strcmp(file + 1, TIMERMACRO_TITLE) && strcmp(file + 1, TIMERMACRO_EPISODE))
+ file++;
+ else
+ file = timer->File();
+ stringTokens.insert(pair<string,string>("title", file));
+ stringTokens.insert(pair<string,string>("timerstart", *cString::sprintf("%02d:%02d", timer->Start() / 100, timer->Start() % 100)));
+ stringTokens.insert(pair<string,string>("timerstop", *cString::sprintf("%02d:%02d", timer->Stop() / 100, timer->Stop() % 100)));
+
+ string day = "";
+ string dayName = "";
+ if (timer->WeekDays())
+ day = timer->PrintDay(0, timer->WeekDays(), false);
+ else if (timer->Day() - time(NULL) < 28 * SECSINDAY) {
+ day = itoa(timer->GetMDay(timer->Day()));
+ dayName = WeekDayName(timer->Day());
+ } else {
+ struct tm tm_r;
+ time_t Day = timer->Day();
+ localtime_r(&Day, &tm_r);
+ char buffer[16];
+ strftime(buffer, sizeof(buffer), "%Y%m%d", &tm_r);
+ day = buffer;
+ }
+ stringTokens.insert(pair<string,string>("day", day));
+ stringTokens.insert(pair<string,string>("dayname", dayName));
+
+ const cChannel *channel = timer->Channel();
+ if (channel) {
+ stringTokens.insert(pair<string,string>("channelname", channel->Name() ? channel->Name() : ""));
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+ intTokens.insert(pair<string,int>("channelnumber", channel->Number()));
+ } else {
+ stringTokens.insert(pair<string,string>("channelname", ""));
+ stringTokens.insert(pair<string,string>("channelid", ""));
+ intTokens.insert(pair<string,int>("channelnumber", 0));
+ }
+
+ const cEvent *event = timer->Event();
+ if (event) {
+ stringTokens.insert(pair<string,string>("eventtitle", event->Title() ? event->Title() : ""));
+ stringTokens.insert(pair<string,string>("eventstart", *event->GetTimeString()));
+ stringTokens.insert(pair<string,string>("eventstop", *event->GetEndTimeString()));
+ stringTokens.insert(pair<string,string>("eventshorttext", event->ShortText() ? event->ShortText() : ""));
+ stringTokens.insert(pair<string,string>("eventdescription", event->Description() ? event->Description() : ""));
+ SetScraperPoster(event);
+ } else {
+ stringTokens.insert(pair<string,string>("eventtitle", ""));
+ stringTokens.insert(pair<string,string>("eventtitle", ""));
+ stringTokens.insert(pair<string,string>("eventstop", ""));
+ stringTokens.insert(pair<string,string>("eventshorttext", ""));
+ stringTokens.insert(pair<string,string>("eventdescription", ""));
+ }
+ SetTokensPosMenuItem();
+ DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens);
+}
+
+void cDisplayMenuItemCurrentTimerView::Clear(void) {
+
+}
+
+void cDisplayMenuItemCurrentTimerView::Action(void) {
+ SetInitFinished();
+ DoSleep(delay);
+ Render();
+ FadeIn();
+ DoFlush();
+ if (scrolling) {
+ DoSleep(scrollDelay);
+ if (scrollOrientation == orHorizontal) {
+ ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode);
+ } else {
+ ScrollVertical(scrollingPix, scrollDelay, scrollSpeed);
+ }
+ }
+}
+
+/*************************************************************
+* cDisplayMenuItemCurrentRecordingView
+*************************************************************/
+
+cDisplayMenuItemCurrentRecordingView::cDisplayMenuItemCurrentRecordingView(cTemplateViewElement *tmplCurrent, const cRecording *recording, int level, int total, int newRecs)
+ : cDisplayMenuItemCurrentView(tmplCurrent) {
+ this->recording = recording;
+ this->level = level;
+ this->total = total;
+ this->newRecs = newRecs;
+}
+
+cDisplayMenuItemCurrentRecordingView::~cDisplayMenuItemCurrentRecordingView() {
+}
+
+void cDisplayMenuItemCurrentRecordingView::Prepare(void) {
+}
+
+
+void cDisplayMenuItemCurrentRecordingView::Render(void) {
+ if (!recording)
+ return;
+ bool isFolder = (total > 0) ? true : false;
+ intTokens.insert(pair<string,int>("folder", isFolder));
+
+ string name = recording->Name() ? recording->Name() : "";
+ string buffer = "";
+ try {
+ vector<string> tokens;
+ istringstream f(name.c_str());
+ string s;
+ while (getline(f, s, FOLDERDELIMCHAR)) {
+ tokens.push_back(s);
+ }
+ buffer = tokens.at(level);
+ if (!isFolder && recording->IsEdited()) {
+ buffer = buffer.substr(1);
+ }
+ } catch (...) {
+ buffer = name.c_str();
+ }
+ stringTokens.insert(pair<string,string>("name", buffer.c_str()));
+ intTokens.insert(pair<string,int>("new", recording->IsNew()));
+ intTokens.insert(pair<string,int>("newrecordingsfolder", newRecs));
+ intTokens.insert(pair<string,int>("numrecordingsfolder", total));
+ intTokens.insert(pair<string,int>("cutted", recording->IsEdited()));
+
+ SetScraperPoster(NULL, recording);
+
+ const cRecordingInfo *info = recording->Info();
+ if (!info) return;
+
+ stringTokens.insert(pair<string,string>("shorttext", info->ShortText() ? info->ShortText() : ""));
+ stringTokens.insert(pair<string,string>("description", info->Description() ? info->Description() : ""));
+
+ const cEvent *event = info->GetEvent();
+ if (!event) return;
+
+ string recDate = *(event->GetDateString());
+ string recTime = *(event->GetTimeString());
+ if (recDate.find("1970") != string::npos) {
+ time_t start = recording->Start();
+ recDate = *DateString(start);
+ recTime = *TimeString(start);
+ }
+ int duration = event->Duration() / 60;
+ int recDuration = recording->LengthInSeconds();
+ recDuration = (recDuration>0)?(recDuration / 60):0;
+ stringTokens.insert(pair<string,string>("date", recDate.c_str()));
+ stringTokens.insert(pair<string,string>("time", recTime.c_str()));
+ intTokens.insert(pair<string,int>("duration", recDuration));
+ intTokens.insert(pair<string,int>("durationevent", duration));
+ SetTokensPosMenuItem();
+ DrawViewElement(veMenuCurrentItemDetail, &stringTokens, &intTokens);
+}
+
+void cDisplayMenuItemCurrentRecordingView::Clear(void) {
+
+}
+
+void cDisplayMenuItemCurrentRecordingView::Action(void) {
+ SetInitFinished();
+ DoSleep(delay);
+ Render();
+ FadeIn();
+ DoFlush();
+ if (scrolling) {
+ DoSleep(scrollDelay);
+ if (scrollOrientation == orHorizontal) {
+ ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode);
+ } else {
+ ScrollVertical(scrollingPix, scrollDelay, scrollSpeed);
+ }
+ }
+}
diff --git a/views/displaymenuitemcurrentview.h b/views/displaymenuitemcurrentview.h
new file mode 100644
index 0000000..12f31e3
--- /dev/null
+++ b/views/displaymenuitemcurrentview.h
@@ -0,0 +1,94 @@
+#ifndef __DISPLAYMENUITEMCURRENTVIEW_H
+#define __DISPLAYMENUITEMCURRENTVIEW_H
+
+#include "../libtemplate/template.h"
+#include "view.h"
+
+class cDisplayMenuItemCurrentView : public cView {
+private:
+protected:
+ int delay;
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ cRect posMenuItem;
+ void SetTokensPosMenuItem(void);
+ void SetScraperPoster(const cEvent *event, const cRecording *recording=NULL);
+public:
+ cDisplayMenuItemCurrentView(cTemplateViewElement *tmplCurrent);
+ virtual ~cDisplayMenuItemCurrentView();
+ void SetPosMenuItem(cRect &pos);
+ virtual void Prepare(void) {};
+ virtual void Render(void) {};
+ virtual void Clear(void) {};
+};
+
+class cDisplayMenuItemCurrentMainView: public cDisplayMenuItemCurrentView {
+private:
+ string number;
+ string label;
+ string icon;
+ void Action(void);
+public:
+ cDisplayMenuItemCurrentMainView(cTemplateViewElement *tmplCurrent, string number, string label, string icon);
+ virtual ~cDisplayMenuItemCurrentMainView();
+ void Prepare(void);
+ void Render(void);
+ void Clear(void);
+};
+
+class cDisplayMenuItemCurrentSchedulesView: public cDisplayMenuItemCurrentView {
+private:
+ const cEvent *event;
+ const cChannel *channel;
+ eTimerMatch timerMatch;
+ eMenuCategory cat;
+ void Action(void);
+ void ReadSchedules(vector< map<string,string> > *schedulesTokens);
+public:
+ cDisplayMenuItemCurrentSchedulesView(cTemplateViewElement *tmplCurrent, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch, eMenuCategory cat);
+ virtual ~cDisplayMenuItemCurrentSchedulesView();
+ void Prepare(void);
+ void Render(void);
+ void Clear(void);
+};
+
+class cDisplayMenuItemCurrentChannelView: public cDisplayMenuItemCurrentView {
+private:
+ const cChannel *channel;
+ void Action(void);
+ void ReadSchedules(vector< map<string,string> > *schedulesTokens);
+public:
+ cDisplayMenuItemCurrentChannelView(cTemplateViewElement *tmplCurrent, const cChannel *channel);
+ virtual ~cDisplayMenuItemCurrentChannelView();
+ void Prepare(void);
+ void Render(void);
+ void Clear(void);
+};
+
+class cDisplayMenuItemCurrentTimerView: public cDisplayMenuItemCurrentView {
+private:
+ const cTimer *timer;
+ void Action(void);
+public:
+ cDisplayMenuItemCurrentTimerView(cTemplateViewElement *tmplCurrent, const cTimer *timer);
+ virtual ~cDisplayMenuItemCurrentTimerView();
+ void Prepare(void);
+ void Render(void);
+ void Clear(void);
+};
+
+class cDisplayMenuItemCurrentRecordingView: public cDisplayMenuItemCurrentView {
+private:
+ const cRecording *recording;
+ int level;
+ int total;
+ int newRecs;
+ void Action(void);
+public:
+ cDisplayMenuItemCurrentRecordingView(cTemplateViewElement *tmplCurrent, const cRecording *recording, int level, int total, int newRecs);
+ virtual ~cDisplayMenuItemCurrentRecordingView();
+ void Prepare(void);
+ void Render(void);
+ void Clear(void);
+};
+#endif //__DISPLAYMENUITEMCURRENTVIEW_H
diff --git a/views/displaymenuitemview.c b/views/displaymenuitemview.c
new file mode 100644
index 0000000..b103cf3
--- /dev/null
+++ b/views/displaymenuitemview.c
@@ -0,0 +1,731 @@
+#include "displaymenuitemview.h"
+#include "../services/scraper2vdr.h"
+#include "../config.h"
+#include "../libcore/helpers.h"
+#include <sstream>
+#include <algorithm>
+
+/*************************************************************
+* cDisplayMenuItemView
+*************************************************************/
+
+cDisplayMenuItemView::cDisplayMenuItemView(cTemplateViewList *tmplList, bool current, bool selectable) : cViewListItem(tmplList->GetListElement()) {
+ this->tmplList = tmplList;
+ this->current = current;
+ this->selectable = selectable;
+ itemInit = true;
+ dirty = true;
+ num = 0;
+ currentView = NULL;
+}
+
+cDisplayMenuItemView::~cDisplayMenuItemView() {
+ if (currentView)
+ delete currentView;
+ CancelSave();
+}
+
+void cDisplayMenuItemView::SetCurrent(bool cur) {
+ current = cur;
+ intTokens.erase("current");
+ intTokens.insert(pair<string,int>("current", current));
+ dirty = true;
+};
+
+
+void cDisplayMenuItemView::ArrangeContainer(void) {
+ if (pos > -1)
+ return;
+ SetInitFinished();
+ pos = num;
+ numTotal = tmplList->GetNumericParameter(ptNumElements);
+ container.SetX(tmplList->GetNumericParameter(ptX));
+ container.SetY(tmplList->GetNumericParameter(ptY));
+ container.SetWidth(tmplList->GetNumericParameter(ptWidth));
+ container.SetHeight(tmplList->GetNumericParameter(ptHeight));
+ align = tmplList->GetNumericParameter(ptAlign);
+ listOrientation = tmplList->GetNumericParameter(ptOrientation);
+}
+
+void cDisplayMenuItemView::Clear(void) {
+ ClearListItem();
+ if (currentView) {
+ delete currentView;
+ currentView = NULL;
+ }
+}
+
+void cDisplayMenuItemView::PrepareScrolling(void) {
+ currentlyScrolling = true;
+ ClearListItem();
+ DrawListItem(&stringTokens, &intTokens);
+}
+
+void cDisplayMenuItemView::EndScrolling(void) {
+ const cPoint p(0,0);
+ SetDrawPortPoint(scrollingPix, p);
+ currentlyScrolling = false;
+ ClearListItem();
+ DrawListItem(&stringTokens, &intTokens);
+}
+
+void cDisplayMenuItemView::Action(void) {
+ if (scrolling) {
+ DoSleep(scrollDelay);
+ PrepareScrolling();
+ if (scrollOrientation == orHorizontal) {
+ ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode);
+ } else {
+ ScrollVertical(scrollingPix, scrollDelay, scrollSpeed);
+ }
+ }
+}
+
+void cDisplayMenuItemView::Stop(void) {
+ if (Running()) {
+ CancelSave();
+ EndScrolling();
+ }
+}
+
+
+void cDisplayMenuItemView::Debug(void) {
+ esyslog("skindesigner: current %d, selectable %d", current, selectable);
+ esyslog("skindesigner: pos %d, numTotal %d", pos, numTotal);
+ esyslog("skindesigner: container x = %d, y = %d, width = %d, height = %d", container.X(), container.Y(), container.Width(), container.Height());
+}
+
+/*************************************************************
+* cDisplayMenuItemDefaultView
+*************************************************************/
+
+cDisplayMenuItemDefaultView::cDisplayMenuItemDefaultView(cTemplateViewList *tmplList, string *tabTexts, int *tabs, int *tabWidths, bool current, bool selectable)
+ : cDisplayMenuItemView(tmplList, current, selectable) {
+ this->tabTexts = tabTexts;
+ this->tabs = tabs;
+ this->tabWidths = tabWidths;
+ maxTabs = cSkinDisplayMenu::MaxTabs;
+}
+
+cDisplayMenuItemDefaultView::~cDisplayMenuItemDefaultView() {
+ delete[] tabTexts;
+}
+
+void cDisplayMenuItemDefaultView::SetTabTexts(string *tabTexts) {
+ delete[] this->tabTexts;
+ this->tabTexts = tabTexts;
+}
+
+void cDisplayMenuItemDefaultView::SetTokens(void) {
+ stringTokens.clear();
+ intTokens.clear();
+ for (int i=0; i<maxTabs; i++) {
+ stringstream name;
+ name << "column" << (i+1);
+ stringstream nameUsed;
+ nameUsed << name.str() << "set";
+ stringstream nameX;
+ nameX << name.str() << "x";
+ stringstream nameWidth;
+ nameWidth << name.str() << "width";
+ stringTokens.insert(pair<string,string>(name.str(), tabTexts[i]));
+ if (i>0)
+ intTokens.insert(pair<string,int>(nameUsed.str(), (tabTexts[i].size() > 0) ? 1 : 0 ));
+ intTokens.insert(pair<string,int>(nameX.str(), tabs[i]));
+ intTokens.insert(pair<string,int>(nameWidth.str(), tabWidths[i]));
+ }
+ intTokens.insert(pair<string,int>("current", current));
+ intTokens.insert(pair<string,int>("separator", !selectable));
+}
+
+void cDisplayMenuItemDefaultView::Prepare(void) {
+ ArrangeContainer();
+}
+
+
+void cDisplayMenuItemDefaultView::Render(void) {
+ DrawListItem(&stringTokens, &intTokens);
+ dirty = false;
+}
+
+void cDisplayMenuItemDefaultView::Debug(void) {
+ esyslog("skindesigner: Default Menu Item ---------------");
+ cDisplayMenuItemView::Debug();
+ for (int i=0; i<maxTabs; i++) {
+ esyslog("skindesigner: tab %d: text: %s, x: %d", i, tabTexts[i].c_str(), tabs[i]);
+ }
+}
+
+/*************************************************************
+* Private Functions
+*************************************************************/
+
+
+/*************************************************************
+* cDisplayMenuItemMainView
+*************************************************************/
+
+cDisplayMenuItemMainView::cDisplayMenuItemMainView(cTemplateViewList *tmplList, string itemText, bool current, bool selectable)
+ : cDisplayMenuItemView(tmplList, current, selectable) {
+ text = itemText;
+ number = "";
+ label = "";
+ icon = "";
+}
+
+cDisplayMenuItemMainView::~cDisplayMenuItemMainView() {
+}
+
+void cDisplayMenuItemMainView::SetTokens(void) {
+ if (!itemInit)
+ return;
+ itemInit = false;
+ stringTokens.insert(pair<string,string>("number", number));
+ stringTokens.insert(pair<string,string>("label", label));
+ stringTokens.insert(pair<string,string>("icon", icon));
+
+ intTokens.insert(pair<string,int>("current", current));
+ intTokens.insert(pair<string,int>("separator", !selectable));
+}
+
+void cDisplayMenuItemMainView::Prepare(void) {
+ ArrangeContainer();
+ SplitMenuText();
+ icon = imgCache->GetIconName(label);
+}
+
+
+void cDisplayMenuItemMainView::Render(void) {
+
+ cRect pos = DrawListItem(&stringTokens, &intTokens);
+
+ if (current) {
+ cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent();
+ if (tmplCurrent) {
+ currentView = new cDisplayMenuItemCurrentMainView(tmplCurrent, number, label, icon);
+ currentView->SetPosMenuItem(pos);
+ currentView->Start();
+ }
+ }
+
+ dirty = false;
+}
+
+void cDisplayMenuItemMainView::Debug(void) {
+ esyslog("skindesigner: Main Menu Item ---------------");
+ cDisplayMenuItemView::Debug();
+ esyslog("skindesigner: item Text: %s", text.c_str());
+ esyslog("skindesigner: item Number: %s, Label: %s", number.c_str(), label.c_str());
+ esyslog("skindesigner: Icon: %s", icon.c_str());
+}
+
+/*************************************************************
+* Private Functions
+*************************************************************/
+
+void cDisplayMenuItemMainView::SplitMenuText(void) {
+ string textPlain = skipspace(text.c_str());
+ bool found = false;
+ bool doBreak = false;
+ size_t i = 0;
+ for (; i < textPlain.length(); i++) {
+ char s = textPlain.at(i);
+ if (i==0) {
+ //if text directly starts with nonnumeric, break
+ if (!(s >= '0' && s <= '9')) {
+ break;
+ }
+ }
+ if (found) {
+ if (!(s >= '0' && s <= '9')) {
+ doBreak = true;
+ }
+ }
+ if (s >= '0' && s <= '9') {
+ found = true;
+ }
+ if (doBreak)
+ break;
+ if (i>4)
+ break;
+ }
+ if (found) {
+ number = skipspace(textPlain.substr(0,i).c_str());
+ label = skipspace(textPlain.substr(i).c_str());
+ } else {
+ number = "";
+ label = textPlain.c_str();
+ }
+}
+
+/*************************************************************
+* cDisplayMenuItemSchedulesView
+*************************************************************/
+
+cDisplayMenuItemSchedulesView::cDisplayMenuItemSchedulesView(cTemplateViewList *tmplList, const cEvent *event,
+ const cChannel *channel, eTimerMatch timerMatch,
+ eMenuCategory cat, bool current, bool selectable)
+ : cDisplayMenuItemView(tmplList, current, selectable) {
+ this->event = event;
+ this->channel = channel;
+ this->timerMatch = timerMatch;
+ this->cat = cat;
+}
+
+cDisplayMenuItemSchedulesView::~cDisplayMenuItemSchedulesView() {
+}
+
+void cDisplayMenuItemSchedulesView::SetTokens(void) {
+ if (!itemInit)
+ return;
+ itemInit = false;
+ intTokens.insert(pair<string,int>("current", current));
+ intTokens.insert(pair<string,int>("separator", !selectable));
+ intTokens.insert(pair<string,int>("whatson", (cat == mcSchedule) ? true: false));
+ intTokens.insert(pair<string,int>("whatsonnow", (cat == mcScheduleNow) ? true: false));
+ intTokens.insert(pair<string,int>("whatsonnext", (cat == mcScheduleNext) ? true: false));
+ if (timerMatch == tmFull) {
+ intTokens.insert(pair<string,int>("timerpartitial", false));
+ intTokens.insert(pair<string,int>("timerfull", true));
+ } else if (timerMatch == tmPartial) {
+ intTokens.insert(pair<string,int>("timerpartitial", true));
+ intTokens.insert(pair<string,int>("timerfull", false));
+ } else {
+ intTokens.insert(pair<string,int>("timerpartitial", false));
+ intTokens.insert(pair<string,int>("timerfull", false));
+ }
+
+ if (event) {
+ if (selectable) {
+ stringTokens.insert(pair<string,string>("title", event->Title() ? event->Title() : ""));
+ stringTokens.insert(pair<string,string>("shorttext", event->ShortText() ? event->ShortText() : ""));
+ stringTokens.insert(pair<string,string>("start", *(event->GetTimeString())));
+ stringTokens.insert(pair<string,string>("stop", *(event->GetEndTimeString())));
+ stringTokens.insert(pair<string,string>("day", *WeekDayName(event->StartTime())));
+ stringTokens.insert(pair<string,string>("date", *ShortDateString(event->StartTime())));
+ bool isRunning = false;
+ time_t now = time(NULL);
+ if ((now >= event->StartTime()) && (now <= event->EndTime()))
+ isRunning = true;
+ intTokens.insert(pair<string,int>("running", isRunning));
+ if (isRunning) {
+ intTokens.insert(pair<string,int>("elapsed", (now - event->StartTime())/60));
+ } else {
+ intTokens.insert(pair<string,int>("elapsed", 0));
+ }
+ intTokens.insert(pair<string,int>("duration", event->Duration() / 60));
+ } else {
+ stringTokens.insert(pair<string,string>("title", event->Title() ? ParseSeparator(event->Title()) : ""));
+ }
+ }
+ if (channel) {
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+ if (!event && !selectable) {
+ stringTokens.insert(pair<string,string>("title", channel->Name() ? ParseSeparator(channel->Name()) : ""));
+ }
+ }
+}
+
+
+void cDisplayMenuItemSchedulesView::Prepare(void) {
+ ArrangeContainer();
+}
+
+void cDisplayMenuItemSchedulesView::Render(void) {
+
+ DrawListItem(&stringTokens, &intTokens);
+
+ if (current) {
+ cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent();
+ if (tmplCurrent) {
+ currentView = new cDisplayMenuItemCurrentSchedulesView(tmplCurrent, event, channel, timerMatch, cat);
+ currentView->Start();
+ }
+ }
+
+ dirty = false;
+}
+
+void cDisplayMenuItemSchedulesView::Debug(void) {
+ esyslog("skindesigner: Schedules Menu Item ---------------");
+ cDisplayMenuItemView::Debug();
+ esyslog("skindesigner: Event: %s", event ? event->Title() : "Event is NULL");
+}
+
+/*************************************************************
+* Private Functions
+*************************************************************/
+
+string cDisplayMenuItemSchedulesView::ParseSeparator(string sep) {
+ string separator = sep;
+ try {
+ if (separator.find_first_not_of("-") > 0)
+ separator.erase(0, separator.find_first_not_of("-")+1);
+ if (separator.find_last_not_of("-") != string::npos)
+ separator.erase(separator.find_last_not_of("-")+1);
+ } catch (...) {}
+ return separator;
+}
+
+/*************************************************************
+* cDisplayMenuItemChannelsView
+*************************************************************/
+
+cDisplayMenuItemChannelsView::cDisplayMenuItemChannelsView(cTemplateViewList *tmplList, const cChannel *channel,
+ bool withProvider, bool current, bool selectable)
+ : cDisplayMenuItemView(tmplList, current, selectable) {
+ this->channel = channel;
+ this->withProvider = withProvider;
+}
+
+cDisplayMenuItemChannelsView::~cDisplayMenuItemChannelsView() {
+}
+
+void cDisplayMenuItemChannelsView::SetTokens(void) {
+ if (!itemInit)
+ return;
+ itemInit = false;
+ if (!channel)
+ return;
+ //general channel information
+ intTokens.insert(pair<string,int>("current", current));
+ intTokens.insert(pair<string,int>("separator", !selectable));
+ intTokens.insert(pair<string,int>("number", channel->Number()));
+ intTokens.insert(pair<string,int>("transponder", channel->Transponder()));
+ intTokens.insert(pair<string,int>("frequency", channel->Frequency()));
+
+ stringTokens.insert(pair<string,string>("name", channel->Name() ? channel->Name() : ""));
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+
+ //Channel Source Information
+ const cSource *source = Sources.Get(channel->Source());
+ if (source) {
+ stringTokens.insert(pair<string,string>("source", *cSource::ToString(source->Code())));
+ stringTokens.insert(pair<string,string>("sourcedescription", source->Description() ? source->Description() : ""));
+ stringTokens.insert(pair<string,string>("source", *cSource::ToString(source->Code())));
+ intTokens.insert(pair<string,int>("isAtsc", source->IsAtsc(source->Code())));
+ intTokens.insert(pair<string,int>("isCable", source->IsCable(source->Code())));
+ intTokens.insert(pair<string,int>("isSat", source->IsSat(source->Code())));
+ intTokens.insert(pair<string,int>("isTerr", source->IsTerr(source->Code())));
+ }
+
+ //current schedule
+ cSchedulesLock schedulesLock;
+ const cSchedules *schedules = cSchedules::Schedules(schedulesLock);
+ const cSchedule *schedule = NULL;
+ schedule = schedules->GetSchedule(channel);
+ bool inserted = false;
+ if (schedule) {
+ const cEvent *presentEvent = schedule->GetPresentEvent();
+ if (presentEvent) {
+ stringTokens.insert(pair<string,string>("presenteventtitle", presentEvent->Title() ? presentEvent->Title() : ""));
+ stringTokens.insert(pair<string,string>("presenteventstart", *presentEvent->GetTimeString()));
+ stringTokens.insert(pair<string,string>("presenteventstop", *presentEvent->GetEndTimeString()));
+ inserted = true;
+ }
+ }
+ if (!inserted) {
+ stringTokens.insert(pair<string,string>("presenteventtitle", ""));
+ stringTokens.insert(pair<string,string>("presenteventstart", ""));
+ stringTokens.insert(pair<string,string>("presenteventstop", ""));
+ }
+}
+
+
+void cDisplayMenuItemChannelsView::Prepare(void) {
+ ArrangeContainer();
+}
+
+void cDisplayMenuItemChannelsView::Render(void) {
+
+ DrawListItem(&stringTokens, &intTokens);
+
+ if (current) {
+ cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent();
+ if (tmplCurrent) {
+ currentView = new cDisplayMenuItemCurrentChannelView(tmplCurrent, channel);
+ currentView->Start();
+ }
+ }
+
+ dirty = false;
+}
+
+void cDisplayMenuItemChannelsView::Debug(void) {
+ esyslog("skindesigner: Channels Menu Item ---------------");
+ cDisplayMenuItemView::Debug();
+ esyslog("skindesigner: Channel: %s", channel ? channel->Name() : "Channel is NULL");
+}
+
+/*************************************************************
+* Private Functions
+*************************************************************/
+
+/*************************************************************
+* cDisplayMenuItemTimersView
+*************************************************************/
+
+cDisplayMenuItemTimersView::cDisplayMenuItemTimersView(cTemplateViewList *tmplList, const cTimer *timer, bool current, bool selectable)
+ : cDisplayMenuItemView(tmplList, current, selectable) {
+ this->timer = timer;
+}
+
+cDisplayMenuItemTimersView::~cDisplayMenuItemTimersView() {
+}
+
+void cDisplayMenuItemTimersView::SetTokens(void) {
+ if (!timer)
+ return;
+ if (!itemInit) {
+ intTokens.erase("flagactive");
+ intTokens.insert(pair<string,int>("flagactive", timer->HasFlags(tfActive)));
+ return;
+ }
+ itemInit = false;
+
+ intTokens.insert(pair<string,int>("current", current));
+ intTokens.insert(pair<string,int>("flagactive", timer->HasFlags(tfActive)));
+ intTokens.insert(pair<string,int>("flaginstant", timer->HasFlags(tfInstant)));
+ intTokens.insert(pair<string,int>("flagvps", timer->HasFlags(tfVps)));
+ intTokens.insert(pair<string,int>("flagrecording", timer->Recording()));
+ intTokens.insert(pair<string,int>("flagpending", timer->Pending()));
+
+
+ const char *file = Setup.FoldersInTimerMenu ? NULL : strrchr(timer->File(), FOLDERDELIMCHAR);
+ if (file && strcmp(file + 1, TIMERMACRO_TITLE) && strcmp(file + 1, TIMERMACRO_EPISODE))
+ file++;
+ else
+ file = timer->File();
+ stringTokens.insert(pair<string,string>("title", file));
+ stringTokens.insert(pair<string,string>("timerstart", *cString::sprintf("%02d:%02d", timer->Start() / 100, timer->Start() % 100)));
+ stringTokens.insert(pair<string,string>("timerstop", *cString::sprintf("%02d:%02d", timer->Stop() / 100, timer->Stop() % 100)));
+
+ string day = "";
+ string dayName = "";
+ if (timer->WeekDays())
+ day = timer->PrintDay(0, timer->WeekDays(), false);
+ else if (timer->Day() - time(NULL) < 28 * SECSINDAY) {
+ day = itoa(timer->GetMDay(timer->Day()));
+ dayName = WeekDayName(timer->Day());
+ } else {
+ struct tm tm_r;
+ time_t Day = timer->Day();
+ localtime_r(&Day, &tm_r);
+ char buffer[16];
+ strftime(buffer, sizeof(buffer), "%Y%m%d", &tm_r);
+ day = buffer;
+ }
+ stringTokens.insert(pair<string,string>("day", day));
+ stringTokens.insert(pair<string,string>("dayname", dayName));
+
+ const cChannel *channel = timer->Channel();
+ if (channel) {
+ stringTokens.insert(pair<string,string>("channelname", channel->Name() ? channel->Name() : ""));
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+ intTokens.insert(pair<string,int>("channelnumber", channel->Number()));
+ } else {
+ stringTokens.insert(pair<string,string>("channelname", ""));
+ stringTokens.insert(pair<string,string>("channelid", ""));
+ intTokens.insert(pair<string,int>("channelnumber", 0));
+ }
+
+ const cEvent *event = timer->Event();
+ if (event) {
+ stringTokens.insert(pair<string,string>("eventtitle", event->Title() ? event->Title() : ""));
+ stringTokens.insert(pair<string,string>("eventstart", *event->GetTimeString()));
+ stringTokens.insert(pair<string,string>("eventstop", *event->GetEndTimeString()));
+ } else {
+ stringTokens.insert(pair<string,string>("eventtitle", ""));
+ stringTokens.insert(pair<string,string>("eventtitle", ""));
+ stringTokens.insert(pair<string,string>("eventstop", ""));
+ }
+}
+
+
+void cDisplayMenuItemTimersView::Prepare(void) {
+ ArrangeContainer();
+}
+
+void cDisplayMenuItemTimersView::Render(void) {
+
+ DrawListItem(&stringTokens, &intTokens);
+
+ if (current) {
+ cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent();
+ if (tmplCurrent) {
+ currentView = new cDisplayMenuItemCurrentTimerView(tmplCurrent, timer);
+ currentView->Start();
+ }
+ }
+
+ dirty = false;
+}
+
+void cDisplayMenuItemTimersView::Debug(void) {
+ esyslog("skindesigner: Timers Menu Item ---------------");
+ cDisplayMenuItemView::Debug();
+ esyslog("skindesigner: Timer: %s", timer ? *(timer->ToDescr()) : "Timer is NULL");
+}
+
+/*************************************************************
+* Private Functions
+*************************************************************/
+
+
+/*************************************************************
+* cDisplayMenuItemRecordingView
+*************************************************************/
+
+cDisplayMenuItemRecordingView::cDisplayMenuItemRecordingView(cTemplateViewList *tmplList, const cRecording *recording, int level, int total, int newRecs, bool current, bool selectable)
+ : cDisplayMenuItemView(tmplList, current, selectable) {
+ this->recording = recording;
+ this->level = level;
+ this->total = total;
+ this->newRecs = newRecs;
+}
+
+cDisplayMenuItemRecordingView::~cDisplayMenuItemRecordingView() {
+}
+
+void cDisplayMenuItemRecordingView::SetTokens(void) {
+ if (!itemInit) return;
+ itemInit = false;
+ if (!recording) return;
+
+ intTokens.insert(pair<string,int>("current", current));
+ bool isFolder = (total > 0) ? true : false;
+ intTokens.insert(pair<string,int>("folder", isFolder));
+
+ string name = recording->Name() ? recording->Name() : "";
+ string buffer = "";
+ try {
+ vector<string> tokens;
+ istringstream f(name.c_str());
+ string s;
+ while (getline(f, s, FOLDERDELIMCHAR)) {
+ tokens.push_back(s);
+ }
+ buffer = tokens.at(level);
+ if (!isFolder && recording->IsEdited()) {
+ buffer = buffer.substr(1);
+ }
+ } catch (...) {
+ buffer = name.c_str();
+ }
+ stringTokens.insert(pair<string,string>("name", buffer.c_str()));
+ intTokens.insert(pair<string,int>("new", recording->IsNew()));
+ intTokens.insert(pair<string,int>("newrecordingsfolder", newRecs));
+ intTokens.insert(pair<string,int>("numrecordingsfolder", total));
+ intTokens.insert(pair<string,int>("cutted", recording->IsEdited()));
+
+ const cEvent *event = NULL;
+ const cRecordingInfo *info = recording->Info();
+ if (!info) return;
+ event = info->GetEvent();
+ if (!event) return;
+
+ string recDate = *(event->GetDateString());
+ string recTime = *(event->GetTimeString());
+ if (recDate.find("1970") != string::npos) {
+ time_t start = recording->Start();
+ recDate = *DateString(start);
+ recTime = *TimeString(start);
+ }
+ int duration = event->Duration() / 60;
+ int recDuration = recording->LengthInSeconds();
+ recDuration = (recDuration>0)?(recDuration / 60):0;
+ stringTokens.insert(pair<string,string>("date", recDate.c_str()));
+ stringTokens.insert(pair<string,string>("time", recTime.c_str()));
+ intTokens.insert(pair<string,int>("duration", recDuration));
+ intTokens.insert(pair<string,int>("durationevent", duration));
+
+ static cPlugin *pScraper = GetScraperPlugin();
+ if (!pScraper || !recording) {
+ intTokens.insert(pair<string,int>("hasposterthumbnail", false));
+ intTokens.insert(pair<string,int>("thumbnailbwidth", -1));
+ intTokens.insert(pair<string,int>("thumbnailheight", -1));
+ stringTokens.insert(pair<string,string>("thumbnailpath", ""));
+ return;
+ }
+
+ ScraperGetPosterThumb call;
+ call.event = NULL;
+ call.recording = recording;
+ if (pScraper->Service("GetPosterThumb", &call)) {
+ intTokens.insert(pair<string,int>("hasposterthumbnail", true));
+ intTokens.insert(pair<string,int>("thumbnailbwidth", call.poster.width));
+ intTokens.insert(pair<string,int>("thumbnailheight", call.poster.height));
+ stringTokens.insert(pair<string,string>("thumbnailpath", call.poster.path));
+ } else {
+ intTokens.insert(pair<string,int>("hasposterthumbnail", false));
+ intTokens.insert(pair<string,int>("thumbnailbwidth", -1));
+ intTokens.insert(pair<string,int>("thumbnailheight", -1));
+ stringTokens.insert(pair<string,string>("thumbnailpath", ""));
+ }
+}
+
+
+void cDisplayMenuItemRecordingView::Prepare(void) {
+ ArrangeContainer();
+}
+
+void cDisplayMenuItemRecordingView::Render(void) {
+
+ DrawListItem(&stringTokens, &intTokens);
+
+ if (current) {
+ cTemplateViewElement *tmplCurrent = tmplList->GetListElementCurrent();
+ if (tmplCurrent) {
+ currentView = new cDisplayMenuItemCurrentRecordingView(tmplCurrent, recording, level, total, newRecs);
+ currentView->Start();
+ }
+ }
+
+ dirty = false;
+}
+
+void cDisplayMenuItemRecordingView::Debug(void) {
+ esyslog("skindesigner: Recording Menu Item ---------------");
+ cDisplayMenuItemView::Debug();
+ esyslog("skindesigner: Recording: %s", recording ? recording->Title() : "Recording is NULL");
+}
+
+/*************************************************************
+* cDisplayMenuItemTrackView
+*************************************************************/
+
+cDisplayMenuItemTrackView::cDisplayMenuItemTrackView(cTemplateViewList *tmplList, const char *title, bool current, bool selectable, int numTracks)
+ : cDisplayMenuItemView(tmplList, current, selectable) {
+ this->title = title;
+ this->numTracks = numTracks;
+}
+
+cDisplayMenuItemTrackView::~cDisplayMenuItemTrackView() {
+}
+
+void cDisplayMenuItemTrackView::SetTokens(void) {
+ if (!itemInit) return;
+ itemInit = false;
+ if (!title) return;
+
+ stringTokens.insert(pair<string,string>("title", title));
+}
+
+
+void cDisplayMenuItemTrackView::Prepare(void) {
+ ArrangeContainer();
+}
+
+void cDisplayMenuItemTrackView::Render(void) {
+
+ DrawListItem(&stringTokens, &intTokens);
+
+ dirty = false;
+}
+
+void cDisplayMenuItemTrackView::Debug(void) {
+ esyslog("skindesigner: Tracks Menu Item ---------------");
+ cDisplayMenuItemView::Debug();
+ esyslog("skindesigner: Title: %s", title);
+}
+
diff --git a/views/displaymenuitemview.h b/views/displaymenuitemview.h
new file mode 100644
index 0000000..724fed5
--- /dev/null
+++ b/views/displaymenuitemview.h
@@ -0,0 +1,141 @@
+#ifndef __DISPLAYMENUITEMVIEW_H
+#define __DISPLAYMENUITEMVIEW_H
+
+#include "../libtemplate/template.h"
+#include "view.h"
+#include "displaymenuitemcurrentview.h"
+
+class cDisplayMenuItemView : public cViewListItem {
+private:
+protected:
+ bool itemInit;
+ bool dirty;
+ bool current;
+ bool selectable;
+ int num;
+ cTemplateViewList *tmplList;
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ cDisplayMenuItemCurrentView *currentView;
+ virtual void Action(void);
+public:
+ cDisplayMenuItemView(cTemplateViewList *tmplList, bool current, bool selectable);
+ virtual ~cDisplayMenuItemView();
+ void SetCurrent(bool cur);
+ void SetNumber(int n) { num = n; };
+ void ArrangeContainer(void);
+ bool Current(void) { return current; };
+ void PrepareScrolling(void);
+ void EndScrolling(void);
+ virtual void SetTokens(void) {};
+ virtual void Prepare(void) {};
+ virtual void Render(void) {};
+ virtual void Clear(void);
+ bool Dirty(void) { return dirty; };
+ void Stop(void);
+ virtual void Debug(void);
+};
+
+class cDisplayMenuItemDefaultView: public cDisplayMenuItemView {
+private:
+ int *tabs;
+ int *tabWidths;
+ string *tabTexts;
+ int maxTabs;
+public:
+ cDisplayMenuItemDefaultView(cTemplateViewList *tmplList, string *tabTexts, int *tabs, int *tabWidths, bool current, bool selectable);
+ virtual ~cDisplayMenuItemDefaultView();
+ void SetTabTexts(string *tabTexts);
+ void SetTokens(void);
+ void Prepare(void);
+ void Render(void);
+ void Debug(void);
+};
+
+class cDisplayMenuItemMainView: public cDisplayMenuItemView {
+private:
+ string text;
+ string number;
+ string label;
+ string icon;
+ void SplitMenuText(void);
+public:
+ cDisplayMenuItemMainView(cTemplateViewList *tmplList, string itemText, bool current, bool selectable);
+ virtual ~cDisplayMenuItemMainView();
+ void SetTokens(void);
+ void Prepare(void);
+ void Render(void);
+ void Debug(void);
+};
+
+class cDisplayMenuItemSchedulesView: public cDisplayMenuItemView {
+private:
+ const cEvent *event;
+ const cChannel *channel;
+ eTimerMatch timerMatch;
+ eMenuCategory cat;
+ string ParseSeparator(string sep);
+public:
+ cDisplayMenuItemSchedulesView(cTemplateViewList *tmplList, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch,
+ eMenuCategory cat, bool current, bool selectable);
+ virtual ~cDisplayMenuItemSchedulesView();
+ void SetTokens(void);
+ void Prepare(void);
+ void Render(void);
+ void Debug(void);
+};
+
+class cDisplayMenuItemChannelsView: public cDisplayMenuItemView {
+private:
+ const cChannel *channel;
+ bool withProvider;
+public:
+ cDisplayMenuItemChannelsView(cTemplateViewList *tmplList, const cChannel *channel, bool withProvider, bool current, bool selectable);
+ virtual ~cDisplayMenuItemChannelsView();
+ void SetTokens(void);
+ void Prepare(void);
+ void Render(void);
+ void Debug(void);
+};
+
+class cDisplayMenuItemTimersView: public cDisplayMenuItemView {
+private:
+ const cTimer *timer;
+public:
+ cDisplayMenuItemTimersView(cTemplateViewList *tmplList, const cTimer *timer, bool current, bool selectable);
+ virtual ~cDisplayMenuItemTimersView();
+ void SetTokens(void);
+ void Prepare(void);
+ void Render(void);
+ void Debug(void);
+};
+
+class cDisplayMenuItemRecordingView: public cDisplayMenuItemView {
+private:
+ const cRecording *recording;
+ int level;
+ int total;
+ int newRecs;
+public:
+ cDisplayMenuItemRecordingView(cTemplateViewList *tmplList, const cRecording *recording, int level, int total, int newRecs, bool current, bool selectable);
+ virtual ~cDisplayMenuItemRecordingView();
+ void SetTokens(void);
+ void Prepare(void);
+ void Render(void);
+ void Debug(void);
+};
+
+class cDisplayMenuItemTrackView: public cDisplayMenuItemView {
+private:
+ const char *title;
+ int numTracks;
+public:
+ cDisplayMenuItemTrackView(cTemplateViewList *tmplList, const char *title, bool current, bool selectable, int numTracks);
+ virtual ~cDisplayMenuItemTrackView();
+ void SetTokens(void);
+ void Prepare(void);
+ void Render(void);
+ void Debug(void);
+};
+
+#endif //__DISPLAYMENUITEMVIEW_H
diff --git a/views/displaymenulistview.c b/views/displaymenulistview.c
new file mode 100644
index 0000000..eb8581e
--- /dev/null
+++ b/views/displaymenulistview.c
@@ -0,0 +1,216 @@
+#include <vdr/menu.h>
+#include "displaymenulistview.h"
+
+
+cDisplayMenuListView::cDisplayMenuListView(cTemplateViewList *tmplList, int count) {
+ oneColumn = true;
+ this->tmplList = tmplList;
+ if (count < 0) {
+ //if count is not set, the fixed number of items is configured in the template
+ itemCount = tmplList->GetNumericParameter(ptNumElements);
+ } else {
+ //else use the actual numbers of elements
+ itemCount = count;
+ map < string, int > intTokens;
+ intTokens.insert(pair<string,int>("numelements", count));
+ tmplList->CalculateListParameters(&intTokens);
+ }
+ menuItems = new cDisplayMenuItemView*[itemCount];
+ for (int i=0; i<itemCount; i++)
+ menuItems[i] = NULL;
+ tabs = new int[cSkinDisplayMenu::MaxTabs];
+ for (int i=0; i<cSkinDisplayMenu::MaxTabs; i++)
+ tabs[i] = 0;
+ tabWidths = new int[cSkinDisplayMenu::MaxTabs];
+ for (int i=0; i<cSkinDisplayMenu::MaxTabs; i++)
+ tabWidths[i] = 0;
+}
+
+cDisplayMenuListView::~cDisplayMenuListView() {
+ Clear();
+ delete[] menuItems;
+ delete[] tabs;
+ delete[] tabWidths;
+}
+
+void cDisplayMenuListView::SetTabs(int tab1, int tab2, int tab3, int tab4, int tab5) {
+
+ int menuItemWidth = 1920;
+ int averageFontWidth = 20;
+ if (tmplList) {
+ menuItemWidth = tmplList->GetMenuItemWidth();
+ averageFontWidth = tmplList->GetAverageFontWidth();
+ }
+
+ if (!tab1) {
+ tabs[0] = 0;
+ tabWidths[0] = menuItemWidth;
+ } else {
+ tabs[0] = 0;
+ if (!tab2) {
+ tabs[1] = menuItemWidth/2;
+ tabWidths[0] = tabs[1];
+ tabWidths[1] = tabs[1];
+ } else {
+ tabs[0] = 0;
+ tabs[1] = tab1 ? tabs[0] + tab1 : 0;
+ tabs[2] = tab2 ? tabs[1] + tab2 : 0;
+ tabs[3] = tab3 ? tabs[2] + tab3 : 0;
+ tabs[4] = tab4 ? tabs[3] + tab4 : 0;
+ tabs[5] = tab5 ? tabs[4] + tab5 : 0;
+ for (int i = 1; i < cSkinDisplayMenu::MaxTabs; i++)
+ tabs[i] *= averageFontWidth;
+
+ for (int i = 0; i < cSkinDisplayMenu::MaxTabs; i++) {
+ if (i == cSkinDisplayMenu::MaxTabs - 1) {
+ tabWidths[i] = menuItemWidth - tabs[i];
+ } else {
+ tabWidths[i] = tabs[i+1] - tabs[i];
+ }
+ }
+ }
+ }
+}
+
+int cDisplayMenuListView::GetListWidth(void) {
+ if (tmplList) {
+ return tmplList->GetMenuItemWidth();
+ }
+ return 1920;
+}
+
+
+void cDisplayMenuListView::Clear(void) {
+ for (int i=0; i<itemCount; i++) {
+ if (menuItems[i]) {
+ delete menuItems[i];
+ menuItems[i] = NULL;
+ }
+ }
+ oneColumn = true;
+ for (int i=0; i<cSkinDisplayMenu::MaxTabs; i++) {
+ tabs[i] = 0;
+ tabWidths[i] = 0;
+ }
+}
+
+void cDisplayMenuListView::AddDefaultMenuItem(int index, string *tabTexts, bool current, bool selectable) {
+ if (menuItems[index]) {
+ cDisplayMenuItemDefaultView *menuItem = dynamic_cast<cDisplayMenuItemDefaultView*>(menuItems[index]);
+ if (!menuItem)
+ return;
+ menuItem->SetCurrent(current);
+ menuItem->SetTabTexts(tabTexts);
+ return;
+ }
+ for (int i=1; i<cSkinDisplayMenu::MaxTabs; i++) {
+ if (tabTexts[i].size() > 0) {
+ oneColumn = false;
+ break;
+ }
+ }
+ cDisplayMenuItemView *item = new cDisplayMenuItemDefaultView(tmplList, tabTexts, tabs, tabWidths, current, selectable);
+ menuItems[index] = item;
+}
+
+void cDisplayMenuListView::AddMainMenuItem(int index, const char *itemText, bool current, bool selectable) {
+ if (menuItems[index]) {
+ menuItems[index]->SetCurrent(current);
+ return;
+ }
+ cDisplayMenuItemView *item = new cDisplayMenuItemMainView(tmplList, itemText, current, selectable);
+ menuItems[index] = item;
+}
+
+void cDisplayMenuListView::AddSetupMenuItem(int index, const char *itemText, bool current, bool selectable) {
+ if (menuItems[index]) {
+ menuItems[index]->SetCurrent(current);
+ return;
+ }
+ cDisplayMenuItemView *item = new cDisplayMenuItemMainView(tmplList, itemText, current, selectable);
+ menuItems[index] = item;
+}
+
+void cDisplayMenuListView::AddSchedulesMenuItem(int index, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch,
+ eMenuCategory cat, bool current, bool selectable) {
+ if (menuItems[index]) {
+ menuItems[index]->SetCurrent(current);
+ return;
+ }
+ cDisplayMenuItemView *item = new cDisplayMenuItemSchedulesView(tmplList, event, channel, timerMatch, cat, current, selectable);
+ menuItems[index] = item;
+}
+
+void cDisplayMenuListView::AddChannelsMenuItem(int index, const cChannel *channel, bool withProvider, bool current, bool selectable) {
+ if (menuItems[index]) {
+ menuItems[index]->SetCurrent(current);
+ return;
+ }
+ cDisplayMenuItemView *item = new cDisplayMenuItemChannelsView(tmplList, channel, withProvider, current, selectable);
+ menuItems[index] = item;
+}
+
+void cDisplayMenuListView::AddTimersMenuItem(int index, const cTimer *timer, bool current, bool selectable) {
+ if (menuItems[index]) {
+ menuItems[index]->SetCurrent(current);
+ return;
+ }
+ cDisplayMenuItemView *item = new cDisplayMenuItemTimersView(tmplList, timer, current, selectable);
+ menuItems[index] = item;
+}
+
+void cDisplayMenuListView::AddRecordingMenuItem(int index, const cRecording *recording, int level, int total, int isNew, bool current, bool selectable) {
+ if (menuItems[index]) {
+ menuItems[index]->SetCurrent(current);
+ return;
+ }
+ cDisplayMenuItemView *item = new cDisplayMenuItemRecordingView(tmplList, recording, level, total, isNew, current, selectable);
+ menuItems[index] = item;
+}
+
+void cDisplayMenuListView::AddTracksMenuItem(int index, const char *title, bool current, bool selectable) {
+ if (menuItems[index]) {
+ menuItems[index]->SetCurrent(current);
+ return;
+ }
+ cDisplayMenuItemView *item = new cDisplayMenuItemTrackView(tmplList, title, current, selectable, itemCount);
+ menuItems[index] = item;
+}
+
+void cDisplayMenuListView::Render(void) {
+ if (tabs[1] && oneColumn) {
+ tabs[0] = 0;
+ tabWidths[0] = tmplList->GetMenuItemWidth();
+ for (int i=1; i<cSkinDisplayMenu::MaxTabs; i++) {
+ tabs[i] = 0;
+ tabWidths[i] = 0;
+ }
+ }
+ int current = -1;
+ for (int i=0; i<itemCount; i++) {
+ if (menuItems[i] && menuItems[i]->Dirty()) {
+ menuItems[i]->Clear();
+ menuItems[i]->SetNumber(i);
+ menuItems[i]->Prepare();
+ menuItems[i]->SetTokens();
+ menuItems[i]->Render();
+ if (menuItems[i]->Current()) {
+ current = i;
+ } else {
+ menuItems[i]->Stop();
+ }
+ }
+ }
+ if (current > -1) {
+ menuItems[current]->Start();
+ }
+}
+
+void cDisplayMenuListView::Debug(void) {
+ for (int i=0; i<itemCount; i++) {
+ esyslog("skindesigner: item %d", i);
+ if (menuItems[i]) {
+ menuItems[i]->Debug();
+ }
+ }
+}
diff --git a/views/displaymenulistview.h b/views/displaymenulistview.h
new file mode 100644
index 0000000..1c2c85f
--- /dev/null
+++ b/views/displaymenulistview.h
@@ -0,0 +1,35 @@
+#ifndef __DISPLAYMENULISTVIEW_H
+#define __DISPLAYMENULISTVIEW_H
+
+#include "../libtemplate/template.h"
+#include "view.h"
+#include "displaymenuitemview.h"
+
+class cDisplayMenuListView {
+private:
+ cTemplateViewList *tmplList;
+ int itemCount;
+ cDisplayMenuItemView **menuItems;
+ int *tabs;
+ int *tabWidths;
+ bool oneColumn;
+public:
+ cDisplayMenuListView(cTemplateViewList *tmplList, int count = -1);
+ virtual ~cDisplayMenuListView();
+ void Clear(void);
+ void SetTabs(int tab1, int tab2, int tab3, int tab4, int tab5);
+ int GetMaxItems(void) { return itemCount; };
+ int GetListWidth(void);
+ void AddDefaultMenuItem(int index, string *tabTexts, bool current, bool selectable);
+ void AddMainMenuItem(int index, const char *itemText, bool current, bool selectable);
+ void AddSetupMenuItem(int index, const char *itemText, bool current, bool selectable);
+ void AddSchedulesMenuItem(int index, const cEvent *event, const cChannel *channel, eTimerMatch timerMatch, eMenuCategory cat, bool current, bool selectable);
+ void AddChannelsMenuItem(int index, const cChannel *channel, bool withProvider, bool current, bool selectable);
+ void AddTimersMenuItem(int index, const cTimer *timer, bool current, bool selectable);
+ void AddRecordingMenuItem(int index, const cRecording *recording, int level, int total, int isNew, bool current, bool selectable);
+ void AddTracksMenuItem(int index, const char *title, bool current, bool selectable);
+ void Render(void);
+ void Debug(void);
+};
+
+#endif //__DISPLAYMENULISTVIEW_H
diff --git a/views/displaymenurootview.c b/views/displaymenurootview.c
new file mode 100644
index 0000000..9ee1bcf
--- /dev/null
+++ b/views/displaymenurootview.c
@@ -0,0 +1,495 @@
+#define __STL_CONFIG_H
+#include <vdr/menu.h>
+#include "displaymenurootview.h"
+#include "../config.h"
+#include "../libcore/helpers.h"
+
+cDisplayMenuRootView::cDisplayMenuRootView(cTemplateView *rootView) : cView(rootView) {
+ viewType = svUndefined;
+ subView = NULL;
+ subViewAvailable = false;
+ view = NULL;
+ listView = NULL;
+ detailView = NULL;
+ defaultBackgroundDrawn = false;
+ defaultHeaderDrawn = false;
+ defaultButtonsDrawn = false;
+ defaultDateTimeDrawn = false;
+ defaultMessageDrawn = false;
+ DeleteOsdOnExit();
+ SetFadeTime(tmplView->GetNumericParameter(ptFadeTime));
+}
+
+cDisplayMenuRootView::~cDisplayMenuRootView() {
+ if (view)
+ delete view;
+ if (listView)
+ delete listView;
+ if (detailView)
+ delete detailView;
+}
+
+/*******************************************************************
+* Public Functions
+*******************************************************************/
+
+bool cDisplayMenuRootView::createOsd(void) {
+ cRect osdSize = tmplView->GetOsdSize();
+ bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(),
+ cOsd::OsdTop() + osdSize.Y(),
+ osdSize.Width(),
+ osdSize.Height());
+ return ok;
+}
+
+/* Categories:
+mcUndefined = -1,
+mcUnknown = 0,
+1 mcMain,
+2 mcSchedule,
+3 mcScheduleNow,
+4 mcScheduleNext,
+5 mcChannel,
+6 mcChannelEdit,
+7 mcTimer,
+8 mcTimerEdit,
+9 mcRecording,
+10 mcRecordingInfo,
+11 mcPlugin,
+12 mcPluginSetup,
+13 mcSetup,
+14 mcSetupOsd,
+15 mcSetupEpg,
+16 mcSetupDvb,
+17 mcSetupLnb,
+18 mcSetupCam,
+19 mcSetupRecord,
+20 mcSetupReplay,
+21 mcSetupMisc,
+22 mcSetupPlugins,
+23 mcCommand,
+24 mcEvent,
+25 mcText,
+26 mcFolder,
+27 mcCam
+*/
+
+void cDisplayMenuRootView::SetMenu(eMenuCategory menuCat, bool menuInit) {
+ eSubView newViewType = svUndefined;
+ bool isListView = true;
+ switch (menuCat) {
+ case mcMain:
+ newViewType = svMenuMain;
+ break;
+ case mcSetup:
+ newViewType = svMenuSetup;
+ break;
+ case mcSchedule:
+ case mcScheduleNow:
+ case mcScheduleNext:
+ newViewType = svMenuSchedules;
+ if (view)
+ view->SetMenuCat(menuCat);
+ break;
+ case mcChannel:
+ newViewType = svMenuChannels;
+ break;
+ case mcTimer:
+ newViewType = svMenuTimers;
+ break;
+ case mcRecording:
+ newViewType = svMenuRecordings;
+ break;
+ case mcEvent:
+ newViewType = svMenuDetailedEpg;
+ isListView = false;
+ break;
+ case mcRecordingInfo:
+ newViewType = svMenuDetailedRecording;
+ isListView = false;
+ break;
+ case mcText:
+ newViewType = svMenuDetailedText;
+ isListView = false;
+ break;
+ default:
+ newViewType = svMenuDefault;
+ break;
+ }
+ if (newViewType != viewType) {
+ subView = tmplView->GetSubView(newViewType);
+ if (!subView) {
+ subViewAvailable = false;
+ subView = tmplView->GetSubView(svMenuDefault);
+ } else {
+ subViewAvailable = true;
+ }
+ //Cleanup
+ if (view) {
+ delete view;
+ view = NULL;
+ }
+ if (listView) {
+ delete listView;
+ listView = NULL;
+ }
+ if (detailView) {
+ delete detailView;
+ detailView = NULL;
+ }
+
+ //Create new View
+ switch (newViewType) {
+ case svMenuMain:
+ view = new cDisplayMenuMainView(subView, menuInit);
+ break;
+ case svMenuSchedules:
+ if (subViewAvailable)
+ view = new cDisplayMenuSchedulesView(subView, menuCat, menuInit);
+ else
+ view = new cDisplayMenuView(subView, menuInit);
+ break;
+ default:
+ view = new cDisplayMenuView(subView, menuInit);
+ }
+
+ //Cleanup root view
+ ClearRootView();
+
+ if (isListView) {
+ //Create menu item list
+ cTemplateViewList *tmplMenuItems = subView->GetViewList(vlMenuItem);
+ if (!tmplMenuItems)
+ return;
+ listView = new cDisplayMenuListView(tmplMenuItems);
+ } else {
+ //Create detailed view
+ detailView = new cDisplayMenuDetailView(subView);
+ }
+ viewType = newViewType;
+ }
+}
+
+void cDisplayMenuRootView::SetTitle(const char *title) {
+ menuTitle = title;
+ if (view)
+ view->SetTitle(title);
+}
+
+void cDisplayMenuRootView::SetButtonTexts(const char *Red, const char *Green, const char *Yellow, const char *Blue) {
+ if (Red)
+ buttonTexts[0] = Red;
+ else
+ buttonTexts[0] = "";
+ if (Green)
+ buttonTexts[1] = Green;
+ else
+ buttonTexts[1] = "";
+ if (Yellow)
+ buttonTexts[2] = Yellow;
+ else
+ buttonTexts[2] = "";
+ if (Blue)
+ buttonTexts[3] = Blue;
+ else
+ buttonTexts[3] = "";
+ if (view)
+ view->SetButtonTexts(buttonTexts);
+}
+
+void cDisplayMenuRootView::SetTabs(int tab1, int tab2, int tab3, int tab4, int tab5) {
+ if (listView) {
+ listView->SetTabs(tab1, tab2, tab3, tab4, tab5);
+ }
+}
+
+void cDisplayMenuRootView::SetMessage(eMessageType type, const char *text) {
+ if (!view)
+ return;
+ if (!view->DrawMessage(type, text)) {
+ defaultMessageDrawn = true;
+ DrawMessage(type, text);
+ } else {
+ defaultMessageDrawn = false;
+ }
+}
+
+void cDisplayMenuRootView::SetDetailedViewEvent(const cEvent *event) {
+ if (!detailView)
+ detailView = new cDisplayMenuDetailView(subView);
+ detailView->SetEvent(event);
+}
+
+void cDisplayMenuRootView::SetDetailedViewRecording(const cRecording *recording) {
+ if (!detailView)
+ detailView = new cDisplayMenuDetailView(subView);
+ detailView->SetRecording(recording);
+}
+
+void cDisplayMenuRootView::SetDetailedViewText(const char *text) {
+ if (!detailView)
+ detailView = new cDisplayMenuDetailView(subView);
+ detailView->SetText(text);
+}
+
+void cDisplayMenuRootView::KeyInput(bool up, bool page) {
+ if (!detailView)
+ return;
+
+ if (up && page) {
+ detailView->KeyLeft();
+ } else if (!up && page) {
+ detailView->KeyRight();
+ } else if (up && !page) {
+ detailView->KeyUp();
+ } else if (!up && !page) {
+ detailView->KeyDown();
+ }
+}
+
+void cDisplayMenuRootView::Clear(void) {
+ if (listView) {
+ listView->Clear();
+ }
+ if (detailView) {
+ delete detailView;
+ detailView = NULL;
+ }
+}
+
+void cDisplayMenuRootView::ClearRootView(void) {
+ if (defaultBackgroundDrawn && view->BackgroundImplemented())
+ ClearViewElement(veBackground);
+ if (defaultHeaderDrawn)
+ ClearViewElement(veHeader);
+ if (defaultButtonsDrawn)
+ ClearViewElement(veButtons);
+ if (defaultDateTimeDrawn)
+ ClearViewElement(veDateTime);
+ if (defaultMessageDrawn)
+ ClearViewElement(veMessage);
+}
+
+int cDisplayMenuRootView::GetMaxItems(void) {
+ if (listView) {
+ return listView->GetMaxItems();
+ }
+ return 0;
+}
+
+int cDisplayMenuRootView::GetListViewWidth(void) {
+ if (listView) {
+ return listView->GetListWidth();
+ }
+ return 0;
+}
+
+int cDisplayMenuRootView::GetTextAreaWidth(void) {
+ if (!tmplView)
+ return 1900;
+ cTemplateView *tempSubView = tmplView->GetSubView(svMenuDefault);
+ if (!tempSubView)
+ return 1900;
+ int areaWidth = tempSubView->GetNumericParameter(ptWidth);
+ if (areaWidth > 0)
+ return areaWidth;
+ return 1900;
+}
+
+
+void cDisplayMenuRootView::Render(void) {
+
+ if (!view->DrawBackground()) {
+ if (!defaultBackgroundDrawn) {
+ defaultBackgroundDrawn = true;
+ DrawBackground();
+ }
+ } else {
+ defaultBackgroundDrawn = false;
+ }
+
+ if (!view->DrawHeader()) {
+ defaultHeaderDrawn = true;
+ DrawHeader();
+ } else {
+ defaultHeaderDrawn = false;
+ }
+
+ if (!view->DrawColorButtons()) {
+ defaultButtonsDrawn = true;
+ DrawColorButtons();
+ } else {
+ defaultButtonsDrawn = false;
+ }
+
+ if (!view->DrawDateTime()) {
+ defaultDateTimeDrawn = true;
+ DrawDateTime();
+ } else {
+ defaultDateTimeDrawn = false;
+ }
+
+ view->DrawStaticViewElements();
+ view->DrawDynamicViewElements();
+}
+
+void cDisplayMenuRootView::RenderMenuItems(void) {
+ if (listView)
+ listView->Render();
+}
+
+void cDisplayMenuRootView::RenderDetailView(void) {
+ if (detailView)
+ detailView->Render();
+}
+
+void cDisplayMenuRootView::RenderMenuScrollBar(int Total, int Offset) {
+ if (!listView)
+ return;
+ view->DrawScrollbar(listView->GetMaxItems(), Total, Offset);
+}
+
+bool cDisplayMenuRootView::RenderDynamicElements(void) {
+ return view->DrawDynamicViewElements();
+}
+
+/*******************************************************************
+* Private Functions
+*******************************************************************/
+
+void cDisplayMenuRootView::DrawBackground(void) {
+ DrawViewElement(veBackground);
+}
+void cDisplayMenuRootView::DrawHeader(void) {
+ if (!ViewElementImplemented(veHeader)) {
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ stringTokens.insert(pair<string,string>("title", menuTitle));
+ stringTokens.insert(pair<string,string>("vdrversion", VDRVERSION));
+
+ //check for standard menu entries
+ bool hasIcon = false;
+ string icon = imgCache->GetIconName(menuTitle);
+ if (icon.size() > 0)
+ hasIcon = true;
+
+ stringTokens.insert(pair<string,string>("icon", icon));
+ intTokens.insert(pair<string,int>("hasicon", hasIcon));
+
+ ClearViewElement(veHeader);
+ DrawViewElement(veHeader, &stringTokens, &intTokens);
+}
+
+void cDisplayMenuRootView::DrawDateTime(void) {
+ if (!ViewElementImplemented(veDateTime)) {
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ time_t t = time(0); // get time now
+ struct tm * now = localtime(&t);
+
+ intTokens.insert(pair<string, int>("year", now->tm_year + 1900));
+ intTokens.insert(pair<string, int>("day", now->tm_mday));
+
+ char monthname[20];
+ char monthshort[10];
+ strftime(monthshort, sizeof(monthshort), "%b", now);
+ strftime(monthname, sizeof(monthname), "%B", now);
+
+ stringTokens.insert(pair<string,string>("monthname", monthname));
+ stringTokens.insert(pair<string,string>("monthnameshort", monthshort));
+ stringTokens.insert(pair<string,string>("month", *cString::sprintf("%02d", now->tm_mon + 1)));
+ stringTokens.insert(pair<string,string>("dayleadingzero", *cString::sprintf("%02d", now->tm_mday)));
+ stringTokens.insert(pair<string,string>("dayname", *WeekDayNameFull(now->tm_wday)));
+ stringTokens.insert(pair<string,string>("daynameshort", *WeekDayName(now->tm_wday)));
+ stringTokens.insert(pair<string,string>("time", *TimeString(t)));
+
+ ClearViewElement(veDateTime);
+ DrawViewElement(veDateTime, &stringTokens, &intTokens);
+
+}
+
+
+void cDisplayMenuRootView::DrawColorButtons(void) {
+ if (!ViewElementImplemented(veButtons)) {
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ stringTokens.insert(pair<string,string>("red", buttonTexts[0]));
+ stringTokens.insert(pair<string,string>("green", buttonTexts[1]));
+ stringTokens.insert(pair<string,string>("yellow", buttonTexts[2]));
+ stringTokens.insert(pair<string,string>("blue", buttonTexts[3]));
+
+ int colorKeys[4] = { Setup.ColorKey0, Setup.ColorKey1, Setup.ColorKey2, Setup.ColorKey3 };
+
+ for (int button = 1; button < 5; button++) {
+ string red = *cString::sprintf("red%d", button);
+ string green = *cString::sprintf("green%d", button);
+ string yellow = *cString::sprintf("yellow%d", button);
+ string blue = *cString::sprintf("blue%d", button);
+ bool isRed = false;
+ bool isGreen = false;
+ bool isYellow = false;
+ bool isBlue = false;
+ switch (colorKeys[button-1]) {
+ case 0:
+ isRed = true;
+ break;
+ case 1:
+ isGreen = true;
+ break;
+ case 2:
+ isYellow = true;
+ break;
+ case 3:
+ isBlue = true;
+ break;
+ default:
+ break;
+ }
+ intTokens.insert(pair<string, int>(red, isRed));
+ intTokens.insert(pair<string, int>(green, isGreen));
+ intTokens.insert(pair<string, int>(yellow, isYellow));
+ intTokens.insert(pair<string, int>(blue, isBlue));
+ }
+
+ ClearViewElement(veButtons);
+ DrawViewElement(veButtons, &stringTokens, &intTokens);
+}
+
+void cDisplayMenuRootView::DrawMessage(eMessageType type, const char *text) {
+ if (!text) {
+ ClearViewElement(veMessage);
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ intTokens.insert(pair<string, int>("status", (type == mtStatus) ? true : false));
+ intTokens.insert(pair<string, int>("info", (type == mtInfo) ? true : false));
+ intTokens.insert(pair<string, int>("warning", (type == mtWarning) ? true : false));
+ intTokens.insert(pair<string, int>("error", (type == mtError) ? true : false));
+ stringTokens.insert(pair<string,string>("text", text));
+
+ ClearViewElement(veMessage);
+ DrawViewElement(veMessage, &stringTokens, &intTokens);
+}
+
+void cDisplayMenuRootView::Action(void) {
+ SetInitFinished();
+ Render();
+ view->Start();
+ FadeIn();
+ DoFlush();
+}
diff --git a/views/displaymenurootview.h b/views/displaymenurootview.h
new file mode 100644
index 0000000..b3f4c62
--- /dev/null
+++ b/views/displaymenurootview.h
@@ -0,0 +1,57 @@
+#ifndef __DISPLAYMENUROOTVIEW_H
+#define __DISPLAYMENUROOTVIEW_H
+
+#include "../libtemplate/template.h"
+#include "displaymenuview.h"
+#include "displaymenulistview.h"
+#include "displaymenudetailview.h"
+
+class cDisplayMenuRootView : public cView {
+private:
+ eSubView viewType;
+ cTemplateView *subView;
+ bool subViewAvailable;
+ cDisplayMenuView *view;
+ cDisplayMenuListView *listView;
+ cDisplayMenuDetailView *detailView;
+ string menuTitle;
+ string buttonTexts[4];
+ bool defaultBackgroundDrawn;
+ bool defaultHeaderDrawn;
+ bool defaultButtonsDrawn;
+ bool defaultDateTimeDrawn;
+ bool defaultMessageDrawn;
+ void DrawBackground(void);
+ void DrawHeader(void);
+ void DrawDateTime(void);
+ void DrawColorButtons(void);
+ void DrawMessage(eMessageType type, const char *text);
+ void ClearRootView(void);
+ virtual void Action(void);
+public:
+ cDisplayMenuRootView(cTemplateView *rootView);
+ virtual ~cDisplayMenuRootView();
+ bool createOsd(void);
+ void SetMenu(eMenuCategory menuCat, bool menuInit);
+ void SetTitle(const char *title);
+ void SetChannel(const cChannel *channel) { view->SetChannel(channel); };
+ void SetButtonTexts(const char *Red, const char *Green, const char *Yellow, const char *Blue);
+ void SetTabs(int tab1, int tab2, int tab3, int tab4, int tab5);
+ void SetMessage(eMessageType type, const char *text);
+ void SetDetailedViewEvent(const cEvent *event);
+ void SetDetailedViewRecording(const cRecording *recording);
+ void SetDetailedViewText(const char *text);
+ void KeyInput(bool up, bool page);
+ void Clear(void);
+ int GetMaxItems(void);
+ int GetListViewWidth(void);
+ int GetTextAreaWidth(void);
+ bool SubViewAvailable(void) { return subViewAvailable; };
+ cDisplayMenuListView *GetListView(void) { return listView; };
+ void Render(void);
+ void RenderMenuItems(void);
+ void RenderDetailView(void);
+ void RenderMenuScrollBar(int Total, int Offset);
+ bool RenderDynamicElements(void);
+};
+#endif //__DISPLAYMENUROOTVIEW_H
diff --git a/views/displaymenutabview.c b/views/displaymenutabview.c
new file mode 100644
index 0000000..f9e03f9
--- /dev/null
+++ b/views/displaymenutabview.c
@@ -0,0 +1,126 @@
+#include "displaymenutabview.h"
+
+
+cDisplayMenuTabView::cDisplayMenuTabView(cTemplateViewTab *tmplTab) : cView(tmplTab) {
+}
+
+cDisplayMenuTabView::~cDisplayMenuTabView() {
+ CancelSave();
+}
+
+void cDisplayMenuTabView::SetTokens(map < string, int > *intTokens, map < string, string > *stringTokens, map < string, vector< map< string, string > > > *loopTokens) {
+ this->intTokens = intTokens;
+ this->stringTokens = stringTokens;
+ this->loopTokens = loopTokens;
+}
+
+void cDisplayMenuTabView::Clear(void) {
+ Fill(0, clrTransparent);
+}
+
+void cDisplayMenuTabView::CreateTab(void) {
+ //Create Pixmap
+ if (!PixmapExists(0)) {
+ cSize drawportSize;
+ scrolling = tmplTab->CalculateDrawPortSize(drawportSize, loopTokens);
+ if (scrolling) {
+ CreateScrollingPixmap(0, tmplTab, drawportSize);
+ scrollingPix = 0;
+ scrollOrientation = orVertical;
+ scrollMode = smNone;
+ } else {
+ CreateViewPixmap(0, tmplTab);
+ }
+ }
+}
+
+
+void cDisplayMenuTabView::Render(void) {
+ if (tmplTab->DoDebug()) {
+ tmplTab->Debug();
+ }
+ //Draw Tab, flushing every loop
+ DrawPixmap(0, tmplTab, loopTokens, true);
+}
+
+bool cDisplayMenuTabView::KeyUp(void) {
+ if (!scrolling)
+ return false;
+ int scrollStep = tmplTab->GetScrollStep();
+ int aktHeight = DrawportY(0);
+ if (aktHeight >= 0) {
+ return false;
+ }
+ int newY = aktHeight + scrollStep;
+ if (newY > 0)
+ newY = 0;
+ SetDrawPortPoint(0, cPoint(0, newY));
+ return true;
+}
+
+bool cDisplayMenuTabView::KeyDown(void) {
+ if (!scrolling)
+ return false;
+
+ int scrollStep = tmplTab->GetScrollStep();
+ int aktHeight = DrawportY(0);
+ int totalHeight = DrawportHeight(0);
+ int screenHeight = Height(0);
+
+ if (totalHeight - ((-1)*aktHeight) == screenHeight) {
+ return false;
+ }
+ int newY = aktHeight - scrollStep;
+ if ((-1)*newY > totalHeight - screenHeight)
+ newY = (-1)*(totalHeight - screenHeight);
+ SetDrawPortPoint(0, cPoint(0, newY));
+ return true;
+}
+
+bool cDisplayMenuTabView::KeyLeft(void) {
+ if (!scrolling)
+ return false;
+ if (!PixmapExists(0))
+ return false;
+ int aktHeight = DrawportY(0);
+ int screenHeight = Height(0);
+ int newY = aktHeight + screenHeight;
+ if (newY > 0)
+ newY = 0;
+ SetDrawPortPoint(0, cPoint(0, newY));
+ return true;
+}
+
+bool cDisplayMenuTabView::KeyRight(void) {
+ if (!scrolling)
+ return false;
+ if (!PixmapExists(0))
+ return false;
+ int aktHeight = DrawportY(0);
+ int screenHeight = Height(0);
+ int totalHeight = DrawportHeight(0);
+ int newY = aktHeight - screenHeight;
+ if ((-1)*newY > totalHeight - screenHeight)
+ newY = (-1)*(totalHeight - screenHeight);
+ SetDrawPortPoint(0, cPoint(0, newY));
+ return true;
+}
+
+void cDisplayMenuTabView::GetScrollbarPosition(int &barTop, int &barHeight) {
+ int y = (-1)*DrawportY(0);
+ int totalHeight = DrawportHeight(0);
+ int screenHeight = Height(0);
+ if (totalHeight == 0)
+ return;
+ if (totalHeight <= screenHeight)
+ barHeight = 1000;
+ else {
+ barHeight = (double)screenHeight / (double) totalHeight * 1000;
+ }
+ barTop = (double)y / (double) totalHeight * 1000;
+}
+
+void cDisplayMenuTabView::Action(void) {
+ Render();
+ DoFlush();
+} \ No newline at end of file
diff --git a/views/displaymenutabview.h b/views/displaymenutabview.h
new file mode 100644
index 0000000..70a7447
--- /dev/null
+++ b/views/displaymenutabview.h
@@ -0,0 +1,27 @@
+#ifndef __DISPLAYMENUTABVIEW_H
+#define __DISPLAYMENUTABVIEW_H
+
+#include "../libtemplate/template.h"
+#include "view.h"
+
+class cDisplayMenuTabView : public cView {
+private:
+ map < string, string > *stringTokens;
+ map < string, int > *intTokens;
+ map < string, vector< map< string, string > > > *loopTokens;
+ void Action(void);
+public:
+ cDisplayMenuTabView(cTemplateViewTab *tmplTab);
+ virtual ~cDisplayMenuTabView();
+ void SetTokens(map < string, int > *intTokens, map < string, string > *stringTokens, map < string, vector< map< string, string > > > *loopTokens);
+ void Clear(void);
+ void CreateTab(void);
+ void Render(void);
+ bool KeyUp(void);
+ bool KeyDown(void);
+ bool KeyLeft(void);
+ bool KeyRight(void);
+ void GetScrollbarPosition(int &barTop, int &barHeight);
+};
+
+#endif //__DISPLAYMENUTABVIEW_H
diff --git a/views/displaymenuview.c b/views/displaymenuview.c
new file mode 100644
index 0000000..3b8c657
--- /dev/null
+++ b/views/displaymenuview.c
@@ -0,0 +1,539 @@
+#define __STL_CONFIG_H
+#include <vdr/menu.h>
+#include <vdr/videodir.h>
+#include "displaymenuview.h"
+#include "../config.h"
+#include "../libcore/helpers.h"
+#include "../libcore/timers.h"
+
+cDisplayMenuView::cDisplayMenuView(cTemplateView *tmplView, bool menuInit) : cView(tmplView) {
+ if (menuInit)
+ SetFadeTime(tmplView->GetNumericParameter(ptFadeTime));
+ else
+ SetFadeTime(0);
+ cat = mcUndefined;
+}
+
+cDisplayMenuView::~cDisplayMenuView() {
+ CancelSave();
+ FadeOut();
+}
+
+bool cDisplayMenuView::DrawBackground(void) {
+ if (!ViewElementImplemented(veBackground)) {
+ return false;
+ }
+ DrawViewElement(veBackground);
+ return true;
+}
+
+bool cDisplayMenuView::DrawHeader(void) {
+ if (!ViewElementImplemented(veHeader)) {
+ return false;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ stringTokens.insert(pair<string,string>("title", menuTitle));
+ stringTokens.insert(pair<string,string>("vdrversion", VDRVERSION));
+
+ //check for standard menu entries
+ bool hasIcon = false;
+ string icon = imgCache->GetIconName(menuTitle);
+ if (icon.size() > 0)
+ hasIcon = true;
+ stringTokens.insert(pair<string,string>("icon", icon));
+ intTokens.insert(pair<string,int>("hasicon", hasIcon));
+
+ ClearViewElement(veHeader);
+ DrawViewElement(veHeader, &stringTokens, &intTokens);
+ return true;
+}
+
+bool cDisplayMenuView::DrawDateTime(void) {
+ if (!ViewElementImplemented(veDateTime)) {
+ return false;
+ }
+
+ cString curDate = DayDateTime();
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ time_t t = time(0); // get time now
+ struct tm * now = localtime(&t);
+
+ intTokens.insert(pair<string, int>("year", now->tm_year + 1900));
+ intTokens.insert(pair<string, int>("day", now->tm_mday));
+
+ char monthname[20];
+ char monthshort[10];
+ strftime(monthshort, sizeof(monthshort), "%b", now);
+ strftime(monthname, sizeof(monthname), "%B", now);
+
+ stringTokens.insert(pair<string,string>("monthname", monthname));
+ stringTokens.insert(pair<string,string>("monthnameshort", monthshort));
+ stringTokens.insert(pair<string,string>("month", *cString::sprintf("%02d", now->tm_mon + 1)));
+ stringTokens.insert(pair<string,string>("dayleadingzero", *cString::sprintf("%02d", now->tm_mday)));
+ stringTokens.insert(pair<string,string>("dayname", *WeekDayNameFull(now->tm_wday)));
+ stringTokens.insert(pair<string,string>("daynameshort", *WeekDayName(now->tm_wday)));
+ stringTokens.insert(pair<string,string>("time", *TimeString(t)));
+
+ ClearViewElement(veDateTime);
+ DrawViewElement(veDateTime, &stringTokens, &intTokens);
+ return true;
+}
+
+bool cDisplayMenuView::DrawColorButtons(void) {
+ if (!ViewElementImplemented(veButtons)) {
+ return false;
+ }
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ stringTokens.insert(pair<string,string>("red", buttonTexts[0]));
+ stringTokens.insert(pair<string,string>("green", buttonTexts[1]));
+ stringTokens.insert(pair<string,string>("yellow", buttonTexts[2]));
+ stringTokens.insert(pair<string,string>("blue", buttonTexts[3]));
+
+ int colorKeys[4] = { Setup.ColorKey0, Setup.ColorKey1, Setup.ColorKey2, Setup.ColorKey3 };
+
+ for (int button = 1; button < 5; button++) {
+ string red = *cString::sprintf("red%d", button);
+ string green = *cString::sprintf("green%d", button);
+ string yellow = *cString::sprintf("yellow%d", button);
+ string blue = *cString::sprintf("blue%d", button);
+ bool isRed = false;
+ bool isGreen = false;
+ bool isYellow = false;
+ bool isBlue = false;
+ switch (colorKeys[button-1]) {
+ case 0:
+ isRed = true;
+ break;
+ case 1:
+ isGreen = true;
+ break;
+ case 2:
+ isYellow = true;
+ break;
+ case 3:
+ isBlue = true;
+ break;
+ default:
+ break;
+ }
+ intTokens.insert(pair<string, int>(red, isRed));
+ intTokens.insert(pair<string, int>(green, isGreen));
+ intTokens.insert(pair<string, int>(yellow, isYellow));
+ intTokens.insert(pair<string, int>(blue, isBlue));
+ }
+
+ ClearViewElement(veButtons);
+ DrawViewElement(veButtons, &stringTokens, &intTokens);
+ return true;
+}
+
+bool cDisplayMenuView::DrawMessage(eMessageType type, const char *text) {
+ if (!ViewElementImplemented(veMessage)) {
+ return false;
+ }
+ if (!text) {
+ ClearViewElement(veMessage);
+ return true;
+ }
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ intTokens.insert(pair<string, int>("status", (type == mtStatus) ? true : false));
+ intTokens.insert(pair<string, int>("info", (type == mtInfo) ? true : false));
+ intTokens.insert(pair<string, int>("warning", (type == mtWarning) ? true : false));
+ intTokens.insert(pair<string, int>("error", (type == mtError) ? true : false));
+ stringTokens.insert(pair<string,string>("text", text));
+
+ ClearViewElement(veMessage);
+ DrawViewElement(veMessage, &stringTokens, &intTokens);
+ return true;
+}
+
+void cDisplayMenuView::DrawScrollbar(int numMax, int numDisplayed, int offset) {
+ if (!ViewElementImplemented(veScrollbar)) {
+ return;
+ }
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ if (numDisplayed < 1)
+ return;
+
+ int barHeight = 0;
+ if (numDisplayed < numMax)
+ barHeight = 1000;
+ else
+ barHeight = (double)numMax * 1000 / (double)numDisplayed;
+
+ int barOffset = (double)offset * 1000 / (double)numDisplayed;
+
+ intTokens.insert(pair<string, int>("height", barHeight));
+ intTokens.insert(pair<string, int>("offset", barOffset));
+
+ ClearViewElement(veScrollbar);
+ DrawViewElement(veScrollbar, &stringTokens, &intTokens);
+}
+
+bool cDisplayMenuView::BackgroundImplemented(void) {
+ if (!ViewElementImplemented(veBackground)) {
+ return false;
+ }
+ return true;
+}
+
+
+void cDisplayMenuView::Action(void) {
+ SetInitFinished();
+ FadeIn();
+ DoFlush();
+}
+
+/************************************************************************
+* cDisplayMenuMainView
+************************************************************************/
+
+cDisplayMenuMainView::cDisplayMenuMainView(cTemplateView *tmplView, bool menuInit) : cDisplayMenuView(tmplView, menuInit) {
+ initial = true;
+ lastSystemLoad = 0.0;
+ InitDevices();
+}
+
+cDisplayMenuMainView::~cDisplayMenuMainView() {
+ CancelSave();
+ FadeOut();
+ delete[] lastSignalStrength;
+ delete[] lastSignalQuality;
+ delete[] recDevices;
+}
+
+void cDisplayMenuMainView::DrawStaticViewElements(void) {
+ DrawTimers();
+ DrawDiscUsage();
+}
+
+bool cDisplayMenuMainView::DrawDynamicViewElements(void) {
+ bool loadChanged = DrawLoad();
+ bool devicesChanged = DrawDevices();
+ initial = false;
+ return loadChanged || devicesChanged;
+
+}
+
+void cDisplayMenuMainView::DrawTimers(void) {
+ if (!ViewElementImplemented(veTimers)) {
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ map < string, vector< map< string, string > > > timerLoopTokens;
+ vector< map< string, string > > timers;
+
+ cGlobalSortedTimers SortedTimers;// local and remote timers
+ int numTimers = SortedTimers.Size();
+
+ intTokens.insert(pair<string, int>("numtimers", numTimers));
+
+ int numTimerConflicts = SortedTimers.NumTimerConfilicts();
+ intTokens.insert(pair<string, int>("numtimerconflicts", numTimerConflicts));
+
+ for (int i=0; i<15; i++) {
+ stringstream name;
+ name << "timer" << i+1 << "exists";
+ if (i < numTimers) {
+ intTokens.insert(pair<string, int>(name.str(), true));
+ } else {
+ intTokens.insert(pair<string, int>(name.str(), false));
+ }
+ }
+
+ for (int i = 0; i < numTimers; i++) {
+ if (i >=15)
+ break;
+ map< string, string > timerVals;
+ const cTimer *Timer = SortedTimers[i];
+ const cEvent *event = Timer->Event();
+ if (event) {
+ timerVals.insert(pair< string, string >("timers[title]", event->Title()));
+ } else {
+ const char *File = Setup.FoldersInTimerMenu ? NULL : strrchr(Timer->File(), FOLDERDELIMCHAR);
+ if (File && strcmp(File + 1, TIMERMACRO_TITLE) && strcmp(File + 1, TIMERMACRO_EPISODE))
+ File++;
+ else
+ File = Timer->File();
+ timerVals.insert(pair< string, string >("timers[title]", File));
+ }
+ const cChannel *channel = Timer->Channel();
+ if (channel) {
+ timerVals.insert(pair< string, string >("timers[channelname]", channel->Name()));
+ stringstream chanNum;
+ chanNum << channel->Number();
+ timerVals.insert(pair< string, string >("timers[channelnumber]", chanNum.str()));
+ string channelID = *(channel->GetChannelID().ToString());
+ timerVals.insert(pair< string, string >("timers[channelid]", channelID));
+ bool logoExists = imgCache->LogoExists(channelID);
+ timerVals.insert(pair< string, string >("timers[channellogoexists]", logoExists ? "1" : "0"));
+ } else {
+ timerVals.insert(pair< string, string >("timers[channelname]", ""));
+ timerVals.insert(pair< string, string >("timers[channelnumber]", "0"));
+ timerVals.insert(pair< string, string >("timers[channelid]", ""));
+ timerVals.insert(pair< string, string >("timers[channellogoexists]", "0"));
+ }
+
+ timerVals.insert(pair< string, string >("timers[recording]", Timer->Recording() ? "1" : "0"));
+
+ cString timerDate("");
+ if (Timer->Recording()) {
+ timerDate = cString::sprintf("-%s", *TimeString(Timer->StopTime()));
+ } else {
+ time_t Now = time(NULL);
+ cString Today = WeekDayName(Now);
+ cString Time = TimeString(Timer->StartTime());
+ cString Day = WeekDayName(Timer->StartTime());
+ if (Timer->StartTime() > Now + 6 * SECSINDAY) {
+ time_t ttm = Timer->StartTime();
+ struct tm * timerTime = localtime(&ttm);
+ timerDate = cString::sprintf("%02d.%02d %s", timerTime->tm_mday, timerTime->tm_mon + 1, *Time);
+ } else if (strcmp(Day, Today) != 0)
+ timerDate = cString::sprintf("%s %s", *Day, *Time);
+ else
+ timerDate = Time;
+ if (Timer->Flags() & tfVps)
+ timerDate = cString::sprintf("VPS %s", *timerDate);
+ }
+ timerVals.insert(pair< string, string >("timers[datetime]", *timerDate));
+
+ timers.push_back(timerVals);
+ }
+
+ timerLoopTokens.insert(pair< string, vector< map< string, string > > >("timers", timers));
+
+ ClearViewElement(veTimers);
+ DrawViewElement(veTimers, &stringTokens, &intTokens, &timerLoopTokens);
+}
+
+void cDisplayMenuMainView::DrawDiscUsage(void) {
+ if (!ViewElementImplemented(veDiscUsage)) {
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ string vdrUsageString = *cVideoDiskUsage::String();
+ int discUsage = cVideoDiskUsage::UsedPercent();
+ bool discAlert = (discUsage > 95) ? true : false;
+ string freeTime = *cString::sprintf("%02d:%02d", cVideoDiskUsage::FreeMinutes() / 60, cVideoDiskUsage::FreeMinutes() % 60);
+ int freeGB = cVideoDiskUsage::FreeMB() / 1024;
+
+ intTokens.insert(pair<string, int>("usedpercent", discUsage));
+ intTokens.insert(pair<string, int>("freepercent", 100-discUsage));
+ intTokens.insert(pair<string, int>("discalert", discAlert));
+ intTokens.insert(pair<string, int>("freegb", freeGB));
+ stringTokens.insert(pair<string,string>("freetime", freeTime));
+ stringTokens.insert(pair<string,string>("vdrusagestring", vdrUsageString));
+
+ ClearViewElement(veDiscUsage);
+ DrawViewElement(veDiscUsage, &stringTokens, &intTokens);
+}
+
+void cDisplayMenuMainView::InitDevices(void) {
+ int numDevices = cDevice::NumDevices();
+ lastSignalStrength = new int[numDevices];
+ lastSignalQuality = new int[numDevices];
+ recDevices = new bool[numDevices];
+ for (int i=0; i<numDevices; i++) {
+ lastSignalStrength[i] = 0;
+ lastSignalQuality[i] = 0;
+ recDevices[i] = false;
+ }
+}
+
+bool cDisplayMenuMainView::DrawLoad(void) {
+ if (!ViewElementImplemented(veSystemLoad)) {
+ return false;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ double systemLoad;
+ if (getloadavg(&systemLoad, 1) > 0) {
+ if (lastSystemLoad == systemLoad) {
+ return false;
+ }
+ string load = *cString::sprintf("%.2f", systemLoad);
+ stringTokens.insert(pair<string,string>("load", load));
+ lastSystemLoad = systemLoad;
+ }
+
+ ClearViewElement(veSystemLoad);
+ DrawViewElement(veSystemLoad, &stringTokens, &intTokens);
+
+ return true;
+}
+
+bool cDisplayMenuMainView::DrawDevices(void) {
+ if (!ViewElementImplemented(veDevices)) {
+ return false;
+ }
+ int numDevices = cDevice::NumDevices();
+ if (!initial) {
+ //check if drawing is necessary
+ bool changed = false;
+ for (int i = 0; i < numDevices; i++) {
+ const cDevice *device = cDevice::GetDevice(i);
+ if (!device || !device->NumProvidedSystems()) {
+ continue;
+ }
+ if ((device->SignalStrength() != lastSignalStrength[i]) || (device->SignalQuality() != lastSignalQuality[i])) {
+ changed = true;
+ break;
+ }
+ }
+ if (!changed) {
+ return false;
+ }
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ map < string, vector< map< string, string > > > deviceLoopTokens;
+ vector< map< string, string > > devices;
+
+ //check device which currently displays live tv
+ int deviceLiveTV = -1;
+ cDevice *primaryDevice = cDevice::PrimaryDevice();
+ if (primaryDevice) {
+ if (!primaryDevice->Replaying() || primaryDevice->Transferring())
+ deviceLiveTV = cDevice::ActualDevice()->DeviceNumber();
+ else
+ deviceLiveTV = primaryDevice->DeviceNumber();
+ }
+
+ //check currently recording devices
+ for (cTimer *timer = Timers.First(); timer; timer = Timers.Next(timer)) {
+ if (!timer->Recording()) {
+ continue;
+ }
+ if (cRecordControl *RecordControl = cRecordControls::GetRecordControl(timer)) {
+ const cDevice *recDevice = RecordControl->Device();
+ if (recDevice) {
+ recDevices[recDevice->DeviceNumber()] = true;
+ }
+ }
+ }
+ int actualNumDevices = 0;
+ for (int i = 0; i < numDevices; i++) {
+ const cDevice *device = cDevice::GetDevice(i);
+ if (!device || !device->NumProvidedSystems()) {
+ continue;
+ }
+ actualNumDevices++;
+ map< string, string > deviceVals;
+ stringstream strNum;
+ strNum << actualNumDevices;
+ deviceVals.insert(pair< string, string >("devices[num]", strNum.str()));
+ deviceVals.insert(pair< string, string >("devices[type]", *(device->DeviceType())));
+ cCamSlot *camSlot = device->CamSlot();
+ int camNumber = -1;
+ if (camSlot) {
+ camNumber = camSlot->SlotNumber();
+ deviceVals.insert(pair< string, string >("devices[hascam]", "1"));
+ } else {
+ deviceVals.insert(pair< string, string >("devices[hascam]", "0"));
+ }
+ int signalStrength = device->SignalStrength();
+ int signalQuality = device->SignalQuality();
+ stringstream strCamNumber;
+ strCamNumber << camNumber;
+ deviceVals.insert(pair< string, string >("devices[cam]", strCamNumber.str()));
+ stringstream strStrength;
+ strStrength << signalStrength;
+ deviceVals.insert(pair< string, string >("devices[signalstrength]", strStrength.str()));
+ stringstream strQuality;
+ strQuality << signalQuality;
+ deviceVals.insert(pair< string, string >("devices[signalquality]", strQuality.str()));
+
+ deviceVals.insert(pair< string, string >("devices[livetv]", i == deviceLiveTV ? "1" : "0"));
+ deviceVals.insert(pair< string, string >("devices[recording]", recDevices[i] ? "1" : "0"));
+
+ const cChannel *channel = device->GetCurrentlyTunedTransponder();
+ const cSource *source = (channel) ? Sources.Get(channel->Source()) : NULL;
+ if (channel && channel->Number() > 0) {
+ stringstream strChanNum;
+ strChanNum << channel->Number();
+ deviceVals.insert(pair< string, string >("devices[channelnumber]", strChanNum.str()));
+ deviceVals.insert(pair< string, string >("devices[channelname]", channel->Name()));
+ deviceVals.insert(pair< string, string >("devices[channelid]", *(channel->GetChannelID().ToString())));
+ deviceVals.insert(pair< string, string >("devices[istuned]", "1"));
+ } else {
+ deviceVals.insert(pair< string, string >("devices[channelnumber]", "0"));
+ deviceVals.insert(pair< string, string >("devices[channelname]", ""));
+ deviceVals.insert(pair< string, string >("devices[channelid]", ""));
+ deviceVals.insert(pair< string, string >("devices[istuned]", "0"));
+ }
+
+ deviceVals.insert(pair< string, string >("devices[source]", source ? source->Description() : ""));
+
+ devices.push_back(deviceVals);
+
+ lastSignalStrength[i] = signalStrength;
+ lastSignalQuality[i] = signalQuality;
+ }
+ deviceLoopTokens.insert(pair< string, vector< map< string, string > > >("devices", devices));
+
+ intTokens.insert(pair<string, int>("numdevices", actualNumDevices));
+
+ ClearViewElement(veDevices);
+ DrawViewElement(veDevices, &stringTokens, &intTokens, &deviceLoopTokens);
+ return true;
+}
+
+/************************************************************************
+* cDisplayMenuSchedulesView
+************************************************************************/
+
+cDisplayMenuSchedulesView::cDisplayMenuSchedulesView(cTemplateView *tmplView, eMenuCategory menuCat, bool menuInit) : cDisplayMenuView(tmplView, menuInit) {
+ cat = menuCat;
+ channel = NULL;
+}
+
+cDisplayMenuSchedulesView::~cDisplayMenuSchedulesView() {
+ CancelSave();
+ FadeOut();
+}
+
+bool cDisplayMenuSchedulesView::DrawHeader(void) {
+ if (!ViewElementImplemented(veHeader)) {
+ return false;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ intTokens.insert(pair<string,int>("whatson", (cat == mcSchedule) ? true: false));
+ intTokens.insert(pair<string,int>("whatsonnow", (cat == mcScheduleNow) ? true: false));
+ intTokens.insert(pair<string,int>("whatsonnext", (cat == mcScheduleNext) ? true: false));
+
+ stringTokens.insert(pair<string,string>("title", menuTitle));
+ stringTokens.insert(pair<string,string>("vdrversion", VDRVERSION));
+ if (channel) {
+ stringTokens.insert(pair<string,string>("channelnumber", *cString::sprintf("%d", channel->Number())));
+ stringTokens.insert(pair<string,string>("channelname", channel->Name()));
+ stringTokens.insert(pair<string,string>("channelid", *(channel->GetChannelID().ToString())));
+
+ }
+ ClearViewElement(veHeader);
+ DrawViewElement(veHeader, &stringTokens, &intTokens);
+ return true;
+} \ No newline at end of file
diff --git a/views/displaymenuview.h b/views/displaymenuview.h
new file mode 100644
index 0000000..52f5361
--- /dev/null
+++ b/views/displaymenuview.h
@@ -0,0 +1,60 @@
+#ifndef __DISPLAYMENUVIEW_H
+#define __DISPLAYMENUVIEW_H
+
+#include "../libtemplate/template.h"
+#include "displaymenulistview.h"
+
+class cDisplayMenuView : public cView {
+protected:
+ eMenuCategory cat;
+ string menuTitle;
+ string *buttonTexts;
+ virtual void Action(void);
+public:
+ cDisplayMenuView(cTemplateView *tmplView, bool menuInit);
+ virtual ~cDisplayMenuView();
+ void SetMenuCat(eMenuCategory newCat) { cat = newCat; };
+ void SetTitle(const char *title) {menuTitle = title; };
+ virtual void SetChannel(const cChannel *channel) {};
+ void SetButtonTexts(string *buttonTexts) { this->buttonTexts = buttonTexts; };
+ bool DrawBackground(void);
+ virtual bool DrawHeader(void);
+ bool DrawDateTime(void);
+ bool DrawColorButtons(void);
+ bool DrawMessage(eMessageType type, const char *text);
+ void DrawScrollbar(int numMax, int numDisplayed, int offset);
+ virtual void DrawStaticViewElements(void) {};
+ virtual bool DrawDynamicViewElements(void) { return false; };
+ bool BackgroundImplemented(void);
+};
+
+class cDisplayMenuMainView : public cDisplayMenuView {
+private:
+ bool initial;
+ int* lastSignalStrength;
+ int* lastSignalQuality;
+ double lastSystemLoad;
+ bool* recDevices;
+ void DrawTimers(void);
+ void DrawDiscUsage(void);
+ bool DrawLoad(void);
+ void InitDevices(void);
+ bool DrawDevices(void);
+public:
+ cDisplayMenuMainView(cTemplateView *tmplView, bool menuInit);
+ virtual ~cDisplayMenuMainView();
+ void DrawStaticViewElements(void);
+ bool DrawDynamicViewElements(void);
+};
+
+class cDisplayMenuSchedulesView : public cDisplayMenuView {
+private:
+ const cChannel *channel;
+public:
+ cDisplayMenuSchedulesView(cTemplateView *tmplView, eMenuCategory menuCat, bool menuInit);
+ virtual ~cDisplayMenuSchedulesView();
+ void SetChannel(const cChannel *channel) { this->channel = channel; };
+ bool DrawHeader(void);
+};
+
+#endif //__DISPLAYMENUVIEW_H
diff --git a/views/displaymessageview.c b/views/displaymessageview.c
new file mode 100644
index 0000000..f4cedc2
--- /dev/null
+++ b/views/displaymessageview.c
@@ -0,0 +1,49 @@
+#define __STL_CONFIG_H
+#include <vdr/menu.h>
+#include "displaymessageview.h"
+
+cDisplayMessageView::cDisplayMessageView(cTemplateView *tmplView) : cView(tmplView) {
+ DeleteOsdOnExit();
+ SetFadeTime(tmplView->GetNumericParameter(ptFadeTime));
+}
+
+cDisplayMessageView::~cDisplayMessageView() {
+ CancelSave();
+ FadeOut();
+}
+
+bool cDisplayMessageView::createOsd(void) {
+ cRect osdSize = tmplView->GetOsdSize();
+ bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(),
+ cOsd::OsdTop() + osdSize.Y(),
+ osdSize.Width(),
+ osdSize.Height());
+ return ok;
+}
+
+void cDisplayMessageView::DrawBackground(void) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ DrawViewElement(veBackground, &stringTokens, &intTokens);
+}
+
+void cDisplayMessageView::DrawMessage(eMessageType type, const char *text) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ stringTokens.insert(pair<string,string>("text", text));
+
+ intTokens.insert(pair<string,int>("status", (type == mtStatus) ? true : false));
+ intTokens.insert(pair<string,int>("info", (type == mtInfo) ? true : false));
+ intTokens.insert(pair<string,int>("warning", (type == mtWarning) ? true : false));
+ intTokens.insert(pair<string,int>("error", (type == mtError) ? true : false));
+
+ DrawViewElement(veMessage, &stringTokens, &intTokens);
+}
+
+void cDisplayMessageView::Action(void) {
+ SetInitFinished();
+ FadeIn();
+ DoFlush();
+ cView::Action();
+}
diff --git a/views/displaymessageview.h b/views/displaymessageview.h
new file mode 100644
index 0000000..1bcc908
--- /dev/null
+++ b/views/displaymessageview.h
@@ -0,0 +1,19 @@
+#ifndef __DISPLAYMESSAGEVIEW_H
+#define __DISPLAYMESSAGEVIEW_H
+
+#include "../libtemplate/template.h"
+#include "view.h"
+
+class cDisplayMessageView : public cView {
+private:
+ virtual void Action(void);
+public:
+ cDisplayMessageView(cTemplateView *tmplView);
+ virtual ~cDisplayMessageView();
+ bool createOsd(void);
+ void DrawBackground(void);
+ void DrawMessage(eMessageType type, const char *text);
+ void DoFadeIn(void) { Start(); };
+ void Flush(void) { DoFlush(); };
+};
+#endif //__DISPLAYMESSAGEVIEW_H
diff --git a/views/displayreplayview.c b/views/displayreplayview.c
new file mode 100644
index 0000000..bea64b7
--- /dev/null
+++ b/views/displayreplayview.c
@@ -0,0 +1,376 @@
+#define __STL_CONFIG_H
+#include <vdr/menu.h>
+#include "../services/scraper2vdr.h"
+#include "displayreplayview.h"
+#include "../libcore/helpers.h"
+
+cDisplayReplayView::cDisplayReplayView(cTemplateView *tmplView) : cView(tmplView) {
+ lastDate = "";
+ DeleteOsdOnExit();
+ SetFadeTime(tmplView->GetNumericParameter(ptFadeTime));
+}
+
+cDisplayReplayView::~cDisplayReplayView() {
+ CancelSave();
+ FadeOut();
+}
+
+bool cDisplayReplayView::createOsd(void) {
+ cRect osdSize = tmplView->GetOsdSize();
+ bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(),
+ cOsd::OsdTop() + osdSize.Y(),
+ osdSize.Width(),
+ osdSize.Height());
+ return ok;
+}
+
+void cDisplayReplayView::DrawBackground(bool modeOnly) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ if (modeOnly)
+ DrawViewElement(veBackgroundModeOnly, &stringTokens, &intTokens);
+ else
+ DrawViewElement(veBackground, &stringTokens, &intTokens);
+}
+
+void cDisplayReplayView::DrawDate(bool modeOnly) {
+ if (modeOnly)
+ return;
+ if (!ViewElementImplemented(veDateTime)) {
+ return;
+ }
+ cString curDate = DayDateTime();
+ if (strcmp(curDate, lastDate)) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ time_t t = time(0); // get time now
+ struct tm * now = localtime(&t);
+
+ intTokens.insert(pair<string, int>("year", now->tm_year + 1900));
+ intTokens.insert(pair<string, int>("day", now->tm_mday));
+
+ char monthname[20];
+ char monthshort[10];
+ strftime(monthshort, sizeof(monthshort), "%b", now);
+ strftime(monthname, sizeof(monthname), "%B", now);
+ stringTokens.insert(pair<string,string>("monthname", monthname));
+ stringTokens.insert(pair<string,string>("monthnameshort", monthshort));
+ stringTokens.insert(pair<string,string>("month", *cString::sprintf("%02d", now->tm_mon + 1)));
+ stringTokens.insert(pair<string,string>("dayleadingzero", *cString::sprintf("%02d", now->tm_mday)));
+ stringTokens.insert(pair<string,string>("dayname", *WeekDayNameFull(now->tm_wday)));
+ stringTokens.insert(pair<string,string>("daynameshort", *WeekDayName(now->tm_wday)));
+ stringTokens.insert(pair<string,string>("time", *TimeString(t)));
+
+ ClearViewElement(veDateTime);
+ DrawViewElement(veDateTime, &stringTokens, &intTokens);
+
+ lastDate = curDate;
+ }
+}
+
+void cDisplayReplayView::DrawTitle(const cRecording *recording) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ const char *recName = NULL;
+ const cRecordingInfo *recInfo = recording->Info();
+ if (recInfo) {
+ recName = recInfo->Title();
+ }
+ if (!recName)
+ recName = recording->Name();
+ string recShortText = recInfo->ShortText() ? recInfo->ShortText() : "";
+ string recDate = *ShortDateString(recording->Start());
+ string recTime = *TimeString(recording->Start());
+
+ stringTokens.insert(pair<string,string>("rectitle", recName ? recName : ""));
+ stringTokens.insert(pair<string,string>("recsubtitle", recShortText));
+ stringTokens.insert(pair<string,string>("recdate", recDate));
+ stringTokens.insert(pair<string,string>("rectime", recTime));
+
+ DrawViewElement(veRecTitle, &stringTokens, &intTokens);
+}
+
+void cDisplayReplayView::DrawRecordingInformation(const cRecording *recording) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ int screenWidth = 0;
+ int screenHeight = 0;
+ double aspect = 0;
+ cDevice::PrimaryDevice()->GetVideoSize(screenWidth, screenHeight, aspect);
+ bool isHD = false;
+ string resName = GetScreenResolutionString(screenWidth, screenHeight, &isHD);
+ bool isWideScreen = false;
+ string aspectName = GetScreenAspectString(aspect, &isWideScreen);
+
+ intTokens.insert(pair<string,int>("screenwidth", screenWidth));
+ intTokens.insert(pair<string,int>("screenheight", screenHeight));
+ intTokens.insert(pair<string,int>("isHD", isHD));
+ intTokens.insert(pair<string,int>("isWideScreen", isWideScreen));
+ stringTokens.insert(pair<string,string>("resolution", resName));
+ stringTokens.insert(pair<string,string>("aspect", aspectName));
+
+ ClearViewElement(veRecInfo);
+ DrawViewElement(veRecInfo, &stringTokens, &intTokens);
+}
+
+void cDisplayReplayView::DrawScraperContent(const cRecording *recording) {
+ if (!recording)
+ return;
+
+ if (!ViewElementImplemented(veScraperContent)) {
+ return;
+ }
+
+ static cPlugin *pScraper = GetScraperPlugin();
+ if (!pScraper) {
+ return;
+ }
+
+ ScraperGetPosterBannerV2 call;
+ call.event = NULL;
+ call.recording = recording;
+ if (pScraper->Service("GetPosterBannerV2", &call)) {
+ int mediaWidth = 0;
+ int mediaHeight = 0;
+ std::string mediaPath = "";
+ bool isBanner = false;
+
+ if ((call.type == tSeries) && call.banner.path.size() > 0) {
+ mediaWidth = call.banner.width;
+ mediaHeight = call.banner.height;
+ mediaPath = call.banner.path;
+ isBanner = true;
+ } else if (call.type == tMovie && call.poster.path.size() > 0 && call.poster.height > 0) {
+ mediaWidth = call.poster.width;
+ mediaHeight = call.poster.height;
+ mediaPath = call.poster.path;
+ } else
+ return;
+
+ map < string, int > intTokens;
+ map < string, string > stringTokens;
+ intTokens.insert(pair<string,int>("mediawidth", mediaWidth));
+ intTokens.insert(pair<string,int>("mediaheight", mediaHeight));
+ intTokens.insert(pair<string,int>("isbanner", isBanner));
+ stringTokens.insert(pair<string,string>("mediapath", mediaPath));
+ ClearViewElement(veScraperContent);
+ DrawViewElement(veScraperContent, &stringTokens, &intTokens);
+ }
+}
+
+void cDisplayReplayView::DrawCurrent(const char *current) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ stringTokens.insert(pair<string,string>("reccurrent", current));
+
+ ClearViewElement(veRecCurrent);
+ DrawViewElement(veRecCurrent, &stringTokens, &intTokens);
+}
+
+void cDisplayReplayView::DrawTotal(const char *total) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ stringTokens.insert(pair<string,string>("rectotal", total));
+
+ ClearViewElement(veRecTotal);
+ DrawViewElement(veRecTotal, &stringTokens, &intTokens);
+}
+
+void cDisplayReplayView::DrawProgressBar(int current, int total) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ intTokens.insert(pair<string,int>("current", current));
+ intTokens.insert(pair<string,int>("total", total));
+ stringTokens.insert(pair<string,string>("dummy", ""));
+ ClearViewElement(veRecProgressBar);
+ DrawViewElement(veRecProgressBar, &stringTokens, &intTokens);
+}
+
+void cDisplayReplayView::DrawMarks(const cMarks *marks, int total) {
+ if (!marks)
+ return;
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ map < string, vector< map< string, string > > > loopTokens;
+ vector< map< string, string > > markTokens;
+ stringstream tot;
+ tot << total;
+
+ bool isStartMark = true;
+ for (const cMark *m = marks->First(); m; m = marks->Next(m)) {
+ map< string, string > markVals;
+ stringstream pos;
+ pos << m->Position();
+ markVals.insert(pair< string, string >("marks[position]", pos.str()));
+ markVals.insert(pair< string, string >("marks[total]", tot.str()));
+ markVals.insert(pair< string, string >("marks[startmark]", isStartMark ? "1" : "0"));
+ const cMark *m2 = marks->Next(m);
+ if (m2) {
+ stringstream posNext;
+ posNext << m2->Position();
+ markVals.insert(pair< string, string >("marks[endposition]", posNext.str()));
+ } else {
+ markVals.insert(pair< string, string >("marks[endposition]", tot.str()));
+ }
+ isStartMark = !isStartMark;
+ markTokens.push_back(markVals);
+ }
+ loopTokens.insert(pair< string, vector< map< string, string > > >("marks", markTokens));
+
+ ClearViewElement(veCuttingMarks);
+ DrawViewElement(veCuttingMarks, &stringTokens, &intTokens, &loopTokens);
+}
+
+void cDisplayReplayView::DrawControlIcons(bool play, bool forward, int speed, bool modeOnly) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ bool isPlay = false;
+ bool isPause = false;
+ bool isFF = false;
+ bool isFF1x = false;
+ bool isFF2x = false;
+ bool isFF3x = false;
+ bool isRew = false;
+ bool isRew1x = false;
+ bool isRew2x = false;
+ bool isRew3x = false;
+
+ if (speed == -1) {
+ if (play) {
+ isPlay = true;
+ } else {
+ isPause = true;
+ }
+ } else if (forward) {
+ if (!play) {
+ isPause = true;
+ }
+ if (speed == 1) {
+ isFF1x = true;
+ } else if (speed == 2) {
+ isFF2x = true;
+ } else if (speed == 3) {
+ isFF3x = true;
+ } else {
+ isFF = true;
+ }
+ } else {
+ if (!play) {
+ isPause = true;
+ }
+ if (speed == 1) {
+ isRew1x = true;
+ } else if (speed == 2) {
+ isRew2x = true;
+ } else if (speed == 3) {
+ isRew3x = true;
+ } else {
+ isRew = true;
+ }
+ }
+ intTokens.insert(pair<string,int>("play", isPlay));
+ intTokens.insert(pair<string,int>("pause", isPause));
+ intTokens.insert(pair<string,int>("forward", isFF));
+ intTokens.insert(pair<string,int>("forward1x", isFF1x));
+ intTokens.insert(pair<string,int>("forward2x", isFF2x));
+ intTokens.insert(pair<string,int>("forward3x", isFF3x));
+ intTokens.insert(pair<string,int>("rewind", isRew));
+ intTokens.insert(pair<string,int>("rewind1x", isRew1x));
+ intTokens.insert(pair<string,int>("rewind2x", isRew2x));
+ intTokens.insert(pair<string,int>("rewind3x", isRew3x));
+
+ if (modeOnly) {
+ ClearViewElement(veControlIconsModeOnly);
+ DrawViewElement(veControlIconsModeOnly, &stringTokens, &intTokens);
+ } else {
+ ClearViewElement(veControlIcons);
+ DrawViewElement(veControlIcons, &stringTokens, &intTokens);
+ }
+}
+
+void cDisplayReplayView::DrawJump(const char *jump) {
+ if (!jump) {
+ ClearViewElement(veRecJump);
+ return;
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ stringTokens.insert(pair<string,string>("jump", jump));
+
+ ClearViewElement(veRecJump);
+ DrawViewElement(veRecJump, &stringTokens, &intTokens);
+}
+
+void cDisplayReplayView::DrawMessage(eMessageType type, const char *text) {
+ if (!text) {
+ ClearViewElement(veMessage);
+ }
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ stringTokens.insert(pair<string,string>("text", text));
+
+ intTokens.insert(pair<string,int>("status", (type == mtStatus) ? true : false));
+ intTokens.insert(pair<string,int>("info", (type == mtInfo) ? true : false));
+ intTokens.insert(pair<string,int>("warning", (type == mtWarning) ? true : false));
+ intTokens.insert(pair<string,int>("error", (type == mtError) ? true : false));
+
+ ClearViewElement(veMessage);
+ DrawViewElement(veMessage, &stringTokens, &intTokens);
+}
+
+
+void cDisplayReplayView::Action(void) {
+ SetInitFinished();
+ FadeIn();
+ DoFlush();
+ cView::Action();
+}
+
+string cDisplayReplayView::GetScreenResolutionString(int width, int height, bool *isHD) {
+ string name = "";
+ switch (width) {
+ case 1920:
+ case 1440:
+ name = "hd1080i";
+ *isHD = true;
+ break;
+ case 1280:
+ if (height == 720)
+ name = "hd720p";
+ else
+ name = "hd1080i";
+ *isHD = true;
+ break;
+ case 720:
+ name = "sd576i";
+ break;
+ default:
+ name = "sd576i";
+ break;
+ }
+ return name;
+}
+
+string cDisplayReplayView::GetScreenAspectString(double aspect, bool *isWideScreen) {
+ string name = "";
+ *isWideScreen = false;
+ if (aspect == 4.0/3.0) {
+ name = "4:3";
+ *isWideScreen = false;
+ } else if (aspect == 16.0/9.0) {
+ name = "16:9";
+ *isWideScreen = true;
+ } else if (aspect == 2.21) {
+ name = "21:9";
+ *isWideScreen = true;
+ }
+ return name;
+} \ No newline at end of file
diff --git a/views/displayreplayview.h b/views/displayreplayview.h
new file mode 100644
index 0000000..9c81917
--- /dev/null
+++ b/views/displayreplayview.h
@@ -0,0 +1,32 @@
+#ifndef __DISPLAYREPLAYVIEW_H
+#define __DISPLAYREPLAYVIEW_H
+
+#include "../libtemplate/template.h"
+#include "view.h"
+
+class cDisplayReplayView : public cView {
+private:
+ cString lastDate;
+ string GetScreenResolutionString(int width, int height, bool *isHD);
+ string GetScreenAspectString(double aspect, bool *isWideScreen);
+ virtual void Action(void);
+public:
+ cDisplayReplayView(cTemplateView *tmplView);
+ virtual ~cDisplayReplayView();
+ bool createOsd(void);
+ void DrawBackground(bool modeOnly);
+ void DrawDate(bool modeOnly);
+ void DrawTitle(const cRecording *recording);
+ void DrawRecordingInformation(const cRecording *recording);
+ void DrawScraperContent(const cRecording *recording);
+ void DrawCurrent(const char *current);
+ void DrawTotal(const char *total);
+ void DrawProgressBar(int current, int total);
+ void DrawMarks(const cMarks *marks, int total);
+ void DrawControlIcons(bool play, bool forward, int speed, bool modeOnly);
+ void DrawJump(const char *jump);
+ void DrawMessage(eMessageType type, const char *text);
+ void DoFadeIn(void) { Start(); };
+ void Flush(void) { DoFlush(); };
+};
+#endif //__DISPLAYREPLAYVIEW_H
diff --git a/views/displayvolumeview.c b/views/displayvolumeview.c
new file mode 100644
index 0000000..e3700dd
--- /dev/null
+++ b/views/displayvolumeview.c
@@ -0,0 +1,55 @@
+#define __STL_CONFIG_H
+#include <vdr/menu.h>
+#include "displayvolumeview.h"
+
+cDisplayVolumeView::cDisplayVolumeView(cTemplateView *tmplView) : cView(tmplView) {
+ volumeLast = -1;
+ muteLast = false;
+ DeleteOsdOnExit();
+ SetFadeTime(tmplView->GetNumericParameter(ptFadeTime));
+}
+
+cDisplayVolumeView::~cDisplayVolumeView() {
+ CancelSave();
+ FadeOut();
+}
+
+bool cDisplayVolumeView::createOsd(void) {
+ cRect osdSize = tmplView->GetOsdSize();
+ bool ok = CreateOsd(cOsd::OsdLeft() + osdSize.X(),
+ cOsd::OsdTop() + osdSize.Y(),
+ osdSize.Width(),
+ osdSize.Height());
+ return ok;
+}
+
+void cDisplayVolumeView::DrawBackground(void) {
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+ DrawViewElement(veBackground, &stringTokens, &intTokens);
+}
+
+void cDisplayVolumeView::DrawVolume(int current, int total, bool mute) {
+ if ((volumeLast == current) && (muteLast == mute))
+ return;
+ volumeLast = current;
+ muteLast = mute;
+
+ map < string, string > stringTokens;
+ map < string, int > intTokens;
+
+ intTokens.insert(pair<string,int>("volume", current));
+ intTokens.insert(pair<string,int>("maxvolume", total));
+ intTokens.insert(pair<string,int>("volumepercent", (double)current *100 / (double)total));
+ intTokens.insert(pair<string,int>("mute", mute));
+
+ ClearViewElement(veVolume);
+ DrawViewElement(veVolume, &stringTokens, &intTokens);
+}
+
+void cDisplayVolumeView::Action(void) {
+ SetInitFinished();
+ FadeIn();
+ DoFlush();
+ cView::Action();
+}
diff --git a/views/displayvolumeview.h b/views/displayvolumeview.h
new file mode 100644
index 0000000..544426e
--- /dev/null
+++ b/views/displayvolumeview.h
@@ -0,0 +1,21 @@
+#ifndef __DISPLAYVOLUMEVIEW_H
+#define __DISPLAYVOLUMEVIEW_H
+
+#include "../libtemplate/template.h"
+#include "view.h"
+
+class cDisplayVolumeView : public cView {
+private:
+ int volumeLast;
+ bool muteLast;
+ virtual void Action(void);
+public:
+ cDisplayVolumeView(cTemplateView *tmplView);
+ virtual ~cDisplayVolumeView();
+ bool createOsd(void);
+ void DrawBackground(void);
+ void DrawVolume(int current, int total, bool mute);
+ void DoFadeIn(void) { Start(); };
+ void Flush(void) { DoFlush(); };
+};
+#endif //__DISPLAYVOLUMEVIEW_H
diff --git a/views/view.c b/views/view.c
new file mode 100644
index 0000000..3b72253
--- /dev/null
+++ b/views/view.c
@@ -0,0 +1,809 @@
+#include "view.h"
+#include "../config.h"
+#include "../libcore/helpers.h"
+#include "../libcore/imageloader.h"
+
+using namespace std;
+
+cView::cView(cTemplateView *tmplView) : cPixmapContainer(tmplView->GetNumPixmaps()) {
+ this->tmplView = tmplView;
+ tvScaled = tmplView->GetScalingWindow(scalingWindow);
+ if (tvScaled) {
+ cDevice::PrimaryDevice()->ScaleVideo(scalingWindow);
+ }
+ tmplItem = NULL;
+ tmplTab = NULL;
+ Init();
+}
+
+cView::cView(cTemplateViewElement *tmplItem) : cPixmapContainer(tmplItem->GetNumPixmaps()) {
+ this->tmplItem = tmplItem;
+ tmplView = NULL;
+ tmplTab = NULL;
+ tvScaled = false;
+ Init();
+}
+
+cView::cView(cTemplateViewTab *tmplTab) : cPixmapContainer(1) {
+ this->tmplTab = tmplTab;
+ tmplView = NULL;
+ tmplItem = NULL;
+ tvScaled = false;
+ Init();
+}
+
+cView::~cView() {
+ if (tvScaled) {
+ cDevice::PrimaryDevice()->ScaleVideo(cRect::Null);
+ }
+}
+
+void cView::Init(void) {
+ viewInit = true;
+ scrolling = false;
+ veScroll = veUndefined;
+ scrollingPix = -1;
+ scrollOrientation = orHorizontal;
+ scrollDelay = 0;
+ scrollMode = smNone;
+ scrollSpeed = ssMedium;
+ currentlyScrolling = false;
+}
+
+void cView::Action(void) {
+ if (scrolling) {
+ DoSleep(scrollDelay);
+ if (scrollOrientation == orHorizontal) {
+ ActivateScrolling();
+ ScrollHorizontal(scrollingPix, scrollDelay, scrollSpeed, scrollMode);
+ } else {
+ ScrollVertical(scrollingPix, scrollDelay, scrollSpeed);
+ }
+ }
+}
+
+void cView::Stop(void) {
+ CancelSave();
+}
+
+/********************************************************************************
+* Protected Functions
+********************************************************************************/
+
+void cView::DrawViewElement(eViewElement ve, map <string,string> *stringTokens, map <string,int> *intTokens, map < string, vector< map< string, string > > > *loopTokens) {
+ //setting correct ViewElement, depending which constructor was used
+ cTemplateViewElement *viewElement;
+ if (tmplItem && ve == veMenuCurrentItemDetail) {
+ viewElement = tmplItem;
+ } else if (tmplView) {
+ viewElement = tmplView->GetViewElement(ve);
+ }
+ if (!viewElement)
+ return;
+
+ if (viewElement->DebugTokens()) {
+ DebugTokens(tmplView ? (tmplView->GetViewElementName(ve)) : "current view", stringTokens, intTokens, loopTokens);
+ }
+
+ //iterate through pixmaps of viewelement
+ int pixCurrent = viewElement->GetPixOffset();
+ if (pixCurrent < 0)
+ return;
+ viewElement->InitIterator();
+ cTemplatePixmap *pix = NULL;
+ while(pix = viewElement->GetNextPixmap()) {
+ //reset Template
+ pix->ClearDynamicParameters();
+ //create Pixmap if already fully parsed
+ if (!PixmapExists(pixCurrent) && pix->Ready() && pix->DoExecute() && !pix->Scrolling()) {
+ CreateViewPixmap(pixCurrent, pix);
+ }
+ //check if pixmap needs dynamic parameters
+ if ((!pix->Ready() || !pix->DoExecute()) && !pix->Scrolling()) {
+ //parse dynamic parameters and initiate functions
+ pix->ParseDynamicParameters(intTokens, true);
+ if (pix->Ready() && pix->DoExecute()) {
+ CreateViewPixmap(pixCurrent, pix);
+ }
+ } else {
+ //parse dynamic parameters but not initiate functions
+ pix->ParseDynamicParameters(intTokens, false);
+ }
+ //if pixmap still not valid, skip
+ if (!pix->Ready() && !pix->Scrolling()) {
+ pixCurrent++;
+ continue;
+ }
+ //if condition for pixmap set, check if cond is true
+ if (!pix->DoExecute()) {
+ pixCurrent++;
+ continue;
+ }
+ //parse dynamic tokens of pixmap functions
+ pix->ClearDynamicFunctionParameters();
+ pix->ParseDynamicFunctionParameters(stringTokens, intTokens);
+
+ if (!PixmapExists(pixCurrent) && pix->Scrolling()) {
+ cSize drawportSize;
+ scrolling = pix->CalculateDrawPortSize(drawportSize, loopTokens);
+ if (scrolling) {
+ CreateScrollingPixmap(pixCurrent, pix, drawportSize);
+ pix->SetScrollingTextWidth();
+ veScroll = ve;
+ scrollingPix = pixCurrent;
+ scrollOrientation = pix->GetNumericParameter(ptOrientation);
+ scrollMode = pix->GetNumericParameter(ptScrollMode);
+ scrollDelay = pix->GetNumericParameter(ptDelay);
+ scrollSpeed = pix->GetNumericParameter(ptScrollSpeed);
+ } else {
+ CreateViewPixmap(pixCurrent, pix);
+ }
+ }
+ if (pix->DoDebug()) {
+ pix->Debug();
+ }
+
+ DrawPixmap(pixCurrent, pix, loopTokens);
+ pixCurrent++;
+ }
+}
+
+void cView::ClearViewElement(eViewElement ve) {
+ if (!tmplView)
+ return;
+ cTemplateViewElement *viewElement = tmplView->GetViewElement(ve);
+ if (!viewElement)
+ return;
+ int pixCurrent = viewElement->GetPixOffset();
+ if (pixCurrent < 0)
+ return;
+ cTemplatePixmap *pix = NULL;
+ viewElement->InitIterator();
+ while(pix = viewElement->GetNextPixmap()) {
+ Fill(pixCurrent, clrTransparent);
+ pixCurrent++;
+ }
+}
+
+void cView::ActivateScrolling(void) {
+ if (veScroll == veUndefined)
+ return;
+ cTemplateViewElement *scrollViewElement = NULL;
+ if (tmplView) {
+ scrollViewElement = tmplView->GetViewElement(veScroll);
+ }
+ if (!scrollViewElement)
+ return;
+
+ ClearViewElement(veScroll);
+ currentlyScrolling = true;
+
+ int pixCurrent = scrollViewElement->GetPixOffset();
+ if (pixCurrent < 0)
+ return;
+ scrollViewElement->InitIterator();
+ cTemplatePixmap *pix = NULL;
+ while(pix = scrollViewElement->GetNextPixmap()) {
+ DrawPixmap(pixCurrent, pix);
+ pixCurrent++;
+ }
+}
+
+bool cView::ViewElementImplemented(eViewElement ve) {
+ return tmplView->GetNumPixmapsViewElement(ve);
+}
+
+void cView::CreateViewPixmap(int num, cTemplatePixmap *pix, cRect *size) {
+ cRect pixSize;
+ if (size) {
+ pixSize = *size;
+ } else {
+ pixSize = pix->GetPixmapSize();
+ }
+ int layer = pix->GetNumericParameter(ptLayer);
+ int transparency = pix->GetNumericParameter(ptTransparency);
+ SetTransparency(num, transparency);
+ CreatePixmap(num, layer, pixSize);
+}
+
+void cView::CreateScrollingPixmap(int num, cTemplatePixmap *pix, cSize &drawportSize) {
+ cRect pixViewPort = pix->GetPixmapSize();
+ cRect drawPort;
+ drawPort.SetX(0);
+ drawPort.SetY(0);
+ drawPort.SetWidth(drawportSize.Width());
+ drawPort.SetHeight(drawportSize.Height());
+ int layer = pix->GetNumericParameter(ptLayer);
+ int transparency = pix->GetNumericParameter(ptTransparency);
+ SetTransparency(num, transparency);
+ CreatePixmap(num, layer, pixViewPort, drawPort);
+}
+
+void cView::DrawPixmap(int num, cTemplatePixmap *pix, map < string, vector< map< string, string > > > *loopTokens, bool flushPerLoop) {
+ pix->InitIterator();
+ cTemplateFunction *func = NULL;
+ while(func = pix->GetNextFunction()) {
+ eFuncType type = func->GetType();
+ if (func->DoDebug()) {
+ func->Debug();
+ }
+ if (!func->DoExecute()) {
+ continue;
+ }
+ switch (type) {
+ case ftFill:
+ DoFill(num, func);
+ break;
+ case ftDrawText:
+ DoDrawText(num, func);
+ break;
+ case ftDrawTextBox: {
+ int floating = func->GetNumericParameter(ptFloat);
+ if (floating > flNone) {
+ DoDrawFloatingTextBox(num, func);
+ } else {
+ DoDrawTextBox(num, func);
+ }
+ break; }
+ case ftDrawRectangle:
+ DoDrawRectangle(num, func);
+ break;
+ case ftDrawEllipse:
+ DoDrawEllipse(num, func);
+ break;
+ case ftDrawImage:
+ DoDrawImage(num, func);
+ break;
+ case ftLoop:
+ if (loopTokens)
+ DrawLoop(num, func, loopTokens);
+ break;
+ default:
+ break;
+ }
+ if (flushPerLoop) {
+ DoFlush();
+ }
+ }
+}
+
+void cView::DrawLoop(int numPixmap, cTemplateFunction *func, map < string, vector< map< string, string > > > *loopTokens) {
+ cTemplateLoopFunction *loopFunc = dynamic_cast<cTemplateLoopFunction*>(func);
+ if (!loopFunc)
+ return;
+
+ int loopX0 = loopFunc->GetNumericParameter(ptX);
+ if (loopX0 < 0) loopX0 = 0;
+ int loopY0 = loopFunc->GetNumericParameter(ptY);
+ if (loopY0 < 0) loopY0 = 0;
+ int orientation = loopFunc->GetNumericParameter(ptOrientation);
+ int loopWidth = loopFunc->GetNumericParameter(ptWidth);
+ if (loopWidth <= 0)
+ loopWidth = loopFunc->GetContainerWidth();
+ int loopHeight = loopFunc->GetNumericParameter(ptHeight);
+ if (loopHeight <= 0)
+ loopHeight = loopFunc->GetContainerHeight();
+ int columnWidth = loopFunc->GetNumericParameter(ptColumnWidth);
+ int rowHeight = loopFunc->GetNumericParameter(ptRowHeight);
+ int overflow = loopFunc->GetNumericParameter(ptOverflow);
+ int maxItems = loopFunc->GetNumericParameter(ptNumElements);
+
+ int x0 = loopX0;
+ int y0 = loopY0;
+
+ string loopTokenName = loopFunc->GetParameter(ptName);
+
+ map < string, vector< map< string, string > > >::iterator hit = loopTokens->find(loopTokenName);
+ if (hit == loopTokens->end())
+ return;
+ vector< map<string,string> > loopToken = hit->second;
+ int lineNumber=0;
+ for (vector< map<string,string> >::iterator line = loopToken.begin(); line != loopToken.end(); line++) {
+ //check overflow behaviour
+ if (overflow == otCut) {
+ if (orientation == orHorizontal) {
+ if (lineNumber * columnWidth > loopWidth) {
+ return;
+ }
+ } else if (orientation == orVertical) {
+ if (lineNumber * rowHeight > loopHeight) {
+ return;
+ }
+ }
+ } else if (overflow == otWrap && orientation == orHorizontal) {
+ if (x0 + columnWidth > loopWidth) {
+ x0 = loopX0;
+ if (rowHeight > 0) {
+ y0 += rowHeight;
+ } else {
+ y0 += loopFunc->GetLoopElementsHeight();
+ }
+ }
+ }
+ map<string,string> tokens = *line;
+ loopFunc->ClearDynamicParameters();
+ loopFunc->ParseDynamicParameters(&tokens);
+ loopFunc->InitIterator();
+ cTemplateFunction *func = NULL;
+ while(func = loopFunc->GetNextFunction()) {
+ //do debug?
+ if (func->DoDebug())
+ func->Debug();
+ //check if set condition is true
+ if (!func->DoExecute()) {
+ continue;
+ }
+ //execute
+ eFuncType type = func->GetType();
+ switch (type) {
+ case ftDrawText:
+ DoDrawText(numPixmap, func, x0, y0);
+ break;
+ case ftDrawTextBox:
+ DoDrawTextBox(numPixmap, func, x0, y0);
+ break;
+ case ftDrawRectangle:
+ DoDrawRectangle(numPixmap, func, x0, y0);
+ break;
+ case ftDrawEllipse:
+ DoDrawEllipse(numPixmap, func, x0, y0);
+ break;
+ case ftDrawImage:
+ DoDrawImage(numPixmap, func, x0, y0);
+ break;
+ default:
+ break;
+ }
+ }
+ //calculate position of next loop element
+ if (orientation == orHorizontal) {
+ if (columnWidth > 0) {
+ x0 += columnWidth;
+ } else {
+ x0 += loopFunc->GetLoopElementsWidth();
+ }
+ } else if (orientation == orVertical) {
+ if (rowHeight > 0) {
+ y0 += rowHeight;
+ } else {
+ y0 += loopFunc->GetLoopElementsHeight();
+ }
+ }
+ lineNumber++;
+ //DoFlush();
+ }
+}
+
+void cView::DebugTokens(string viewElement, map<string,string> *stringTokens, map<string,int> *intTokens, map < string, vector< map< string, string > > > *loopTokens) {
+ esyslog("skindesigner: ------------------------------ Tokens for %s:", viewElement.c_str());
+ if (stringTokens) {
+ for (map<string,string>::iterator st = stringTokens->begin(); st != stringTokens->end(); st++) {
+ esyslog("skindesigner: string var \"%s\" = \"%s\"", (st->first).c_str(), (st->second).c_str());
+ }
+ }
+ if (intTokens) {
+ for (map<string,int>::iterator it = intTokens->begin(); it != intTokens->end(); it++) {
+ esyslog("skindesigner: int var \"%s\" = %d", (it->first).c_str(), it->second);
+ }
+ }
+ if (loopTokens) {
+ for(map < string, vector< map< string, string > > >::iterator it1 = loopTokens->begin(); it1 != loopTokens->end(); it1++) {
+ int line = 0;
+ string tokenName = it1->first;
+ vector< map<string,string> > tokens = it1->second;
+ esyslog("skindesigner: loop token %s", tokenName.c_str());
+ for (vector< map<string,string> >::iterator it2 = tokens.begin(); it2 != tokens.end(); it2++) {
+ esyslog("skindesigner: loop tokens line %d:", line++);
+ map<string,string> element = *it2;
+ for (map<string,string>::iterator el = element.begin(); el != element.end(); el++) {
+ esyslog("skindesigner: name: %s, value: %s", (el->first).c_str(), (el->second).c_str());
+ }
+ }
+ }
+ }
+}
+
+/*****************************************************************
+* Private Functions
+*****************************************************************/
+
+void cView::DoFill(int num, cTemplateFunction *func) {
+ tColor col = func->GetColorParameter(ptColor);
+ Fill(num, col);
+}
+
+void cView::DoDrawText(int num, cTemplateFunction *func, int x0, int y0) {
+ int x = func->GetNumericParameter(ptX);
+ if (x < 0) x = 0;
+ x += x0;
+ int y = func->GetNumericParameter(ptY);
+ if (y < 0) y = 0;
+ y += y0;
+ cPoint pos(x,y);
+ string fontName = func->GetFontName();
+ int fontSize = func->GetNumericParameter(ptFontSize);
+ tColor clr = func->GetColorParameter(ptColor);
+ tColor clrBack = clrTransparent;
+ string text = "";
+ if (!currentlyScrolling) {
+ text = func->GetText(true);
+ } else {
+ text = func->GetText(false);
+ }
+ DrawText(num, pos, text.c_str(), clr, clrBack, fontName, fontSize);
+}
+
+void cView::DoDrawTextBox(int num, cTemplateFunction *func, int x0, int y0) {
+ string text = func->GetText(false);
+ if (text.size() < 3)
+ return;
+ int x = func->GetNumericParameter(ptX);
+ int y = func->GetNumericParameter(ptY);
+ if (x < 0) x = 0;
+ x += x0;
+ if (y < 0) y = 0;
+ y += y0;
+ int width = func->GetNumericParameter(ptWidth);
+ int height = func->GetNumericParameter(ptHeight);
+ string fontName = func->GetFontName();
+ int fontSize = func->GetNumericParameter(ptFontSize);
+ int align = func->GetNumericParameter(ptAlign);
+ int maxLines = func->GetNumericParameter(ptMaxLines);
+ tColor clr = func->GetColorParameter(ptColor);
+ tColor clrBack = clrTransparent;
+ const cFont *font = fontManager->Font(fontName, fontSize);
+ if (!font)
+ return;
+ cTextWrapper wrapper;
+ wrapper.Set(text.c_str(), font, width);
+ int fontHeight = fontManager->Height(fontName, fontSize);
+ int lines = wrapper.Lines();
+ int yLine = y;
+ for (int line=0; line < lines; line++) {
+ int xLine = x;
+ if (align == alCenter) {
+ int textWidth = font->Width(wrapper.GetLine(line));
+ xLine += (width - textWidth)/2;
+ } else if (align == alRight) {
+ int textWidth = font->Width(wrapper.GetLine(line));
+ xLine += (width - textWidth);
+ }
+ cPoint pos(xLine, yLine);
+ if (maxLines > 0 && line == maxLines-1) {
+ string lastLine = wrapper.GetLine(line);
+ if (lines > maxLines) {
+ lastLine += "...";
+ }
+ DrawText(num, pos, lastLine.c_str(), clr, clrBack, fontName, fontSize);
+ break;
+ } else if (height > 0 && yLine - y + 2*fontHeight > height) {
+ DrawText(num, pos, "...", clr, clrBack, fontName, fontSize);
+ break;
+ }
+ DrawText(num, pos, wrapper.GetLine(line), clr, clrBack, fontName, fontSize);
+ yLine += fontHeight;
+ }
+}
+
+void cView::DoDrawFloatingTextBox(int num, cTemplateFunction *func) {
+ string text = func->GetText(false);
+ if (text.size() < 3)
+ return;
+ int x = func->GetNumericParameter(ptX);
+ int y = func->GetNumericParameter(ptY);
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ int width = func->GetNumericParameter(ptWidth);
+ int height = func->GetNumericParameter(ptHeight);
+ string fontName = func->GetFontName();
+ int fontSize = func->GetNumericParameter(ptFontSize);
+ tColor clr = func->GetColorParameter(ptColor);
+ tColor clrBack = clrTransparent;
+ const cFont *font = fontManager->Font(fontName, fontSize);
+ if (!font)
+ return;
+ int floatType = func->GetNumericParameter(ptFloat);
+ int floatWidth = func->GetNumericParameter(ptFloatWidth);
+ int floatHeight = func->GetNumericParameter(ptFloatHeight);
+
+ cTextWrapper wTextTall;
+ cTextWrapper wTextFull;
+
+ int fontHeight = fontManager->Height(fontName, fontSize);
+ int linesNarrow = floatHeight / fontHeight;
+ int widthNarrow = width - floatWidth;
+ int linesDrawn = 0;
+ int curY = 0;
+ bool drawNarrow = true;
+
+ splitstring s(text.c_str());
+ std::vector<std::string> flds = s.split('\n', 1);
+
+ if (flds.size() < 1)
+ return;
+
+ std::stringstream sstrTextTall;
+ std::stringstream sstrTextFull;
+
+ for (int i=0; i<flds.size(); i++) {
+ if (!flds[i].size()) {
+ //empty line
+ linesDrawn++;
+ curY += fontHeight;
+ if (drawNarrow)
+ sstrTextTall << "\n";
+ else
+ sstrTextFull << "\n";
+ } else {
+ cTextWrapper wrapper;
+ if (drawNarrow) {
+ wrapper.Set((flds[i].c_str()), font, widthNarrow);
+ int newLines = wrapper.Lines();
+ //check if wrapper fits completely into narrow area
+ if (linesDrawn + newLines < linesNarrow) {
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ sstrTextTall << wrapper.GetLine(line) << " ";
+ }
+ sstrTextTall << "\n";
+ linesDrawn += newLines;
+ } else {
+ //this wrapper has to be splitted
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ if (line + linesDrawn < linesNarrow) {
+ sstrTextTall << wrapper.GetLine(line) << " ";
+ } else {
+ sstrTextFull << wrapper.GetLine(line) << " ";
+ }
+ }
+ sstrTextFull << "\n";
+ drawNarrow = false;
+ }
+ } else {
+ wrapper.Set((flds[i].c_str()), font, width);
+ for (int line = 0; line < wrapper.Lines(); line++) {
+ sstrTextFull << wrapper.GetLine(line) << " ";
+ }
+ sstrTextFull << "\n";
+ }
+ }
+ }
+ //VDRs textwrapper swallows linebreaks at the end, so we have to fix that manually
+ string textTall = sstrTextTall.str();
+ size_t posLastCarriageReturn = textTall.find_last_not_of("\n");
+
+ int numLinesToAddAtTall = 0;
+ if (posLastCarriageReturn != string::npos && (posLastCarriageReturn < textTall.size() - 1)) {
+ numLinesToAddAtTall = textTall.size() - posLastCarriageReturn - 2;
+ }
+
+ wTextTall.Set(textTall.c_str(), font, widthNarrow);
+ wTextFull.Set(sstrTextFull.str().c_str(), font, width);
+
+ int textLinesTall = wTextTall.Lines();
+ int textLinesFull = wTextFull.Lines();
+
+ int textXTall = x;
+ if (floatType == flTopLeft)
+ textXTall = x + floatWidth;
+
+ int yLine = y;
+ for (int line=0; line < textLinesTall; line++) {
+ cPoint pos(textXTall, yLine);
+ DrawText(num, pos, wTextTall.GetLine(line), clr, clrBack, fontName, fontSize);
+ yLine += fontHeight;
+ }
+
+ if (numLinesToAddAtTall) {
+ yLine += numLinesToAddAtTall * fontHeight;
+ }
+
+ for (int line=0; line < textLinesFull; line++) {
+ cPoint pos(x, yLine);
+ if (height > 0 && yLine - y + 2*fontHeight > height) {
+ DrawText(num, pos, "...", clr, clrBack, fontName, fontSize);
+ break;
+ }
+ DrawText(num, pos, wTextFull.GetLine(line), clr, clrBack, fontName, fontSize);
+ yLine += fontHeight;
+ }
+}
+
+void cView::DoDrawRectangle(int num, cTemplateFunction *func, int x0, int y0) {
+ int x = func->GetNumericParameter(ptX);
+ int y = func->GetNumericParameter(ptY);
+ if (x < 0) x = 0;
+ x += x0;
+ if (y < 0) y = 0;
+ y += y0;
+ int w = func->GetNumericParameter(ptWidth);
+ int h = func->GetNumericParameter(ptHeight);
+ cRect size(x, y, w, h);
+ tColor clr = func->GetColorParameter(ptColor);
+ DrawRectangle(num, size, clr);
+}
+
+void cView::DoDrawEllipse(int num, cTemplateFunction *func, int x0, int y0) {
+ int x = func->GetNumericParameter(ptX);
+ int y = func->GetNumericParameter(ptY);
+ if (x < 0) x = 0;
+ x += x0;
+ if (y < 0) y = 0;
+ y += y0;
+ int w = func->GetNumericParameter(ptWidth);
+ int h = func->GetNumericParameter(ptHeight);
+ cRect size(x, y, w, h);
+ tColor clr = func->GetColorParameter(ptColor);
+ int quadrant = func->GetNumericParameter(ptQuadrant);
+ DrawEllipse(num, size, clr, quadrant);
+}
+
+void cView::DoDrawImage(int num, cTemplateFunction *func, int x0, int y0) {
+ int x = func->GetNumericParameter(ptX);
+ int y = func->GetNumericParameter(ptY);
+ if (x < 0) x = 0;
+ x += x0;
+ if (y < 0) y = 0;
+ y += y0;
+ cPoint pos(x,y);
+ int width = func->GetNumericParameter(ptWidth);
+ int height = func->GetNumericParameter(ptHeight);
+ string path = func->GetImagePath();
+ eImageType type = (eImageType)func->GetNumericParameter(ptImageType);
+ switch (type) {
+ case itChannelLogo: {
+ cImage *logo = imgCache->GetLogo(path, width, height);
+ if (logo) {
+ DrawImage(num, pos, *logo);
+ }
+ break; }
+ case itSepLogo: {
+ cImage *sepLogo = imgCache->GetSeparatorLogo(path, width, height);
+ if (sepLogo) {
+ DrawImage(num, pos, *sepLogo);
+ }
+ break; }
+ case itSkinPart: {
+ cImage *skinpart = imgCache->GetSkinpart(path, width, height);
+ if (skinpart) {
+ DrawImage(num, pos, *skinpart);
+ }
+ break; }
+ case itIcon: {
+ cImage *icon = imgCache->GetIcon(type, path, width, height);
+ if (icon) {
+ DrawImage(num, pos, *icon);
+ }
+ break; }
+ case itMenuIcon: {
+ cImage *icon = imgCache->GetIcon(type, path, width, height);
+ if (icon) {
+ DrawImage(num, pos, *icon);
+ }
+ break; }
+ case itImage: {
+ cImageLoader imgLoader;
+ if (imgLoader.LoadImage(path.c_str(), width, height)) {
+ DrawImage(num, pos, imgLoader.GetImage());
+ }
+ break; }
+ default:
+ break;
+ }
+}
+
+/***********************************************************************
+* cViewListItem
+************************************************************************/
+
+cViewListItem::cViewListItem(cTemplateViewElement *tmplItem) : cView(tmplItem) {
+ pos = -1;
+ numTotal = 0;
+ align = alLeft;
+ listOrientation = orVertical;
+}
+
+cViewListItem::~cViewListItem() {
+
+}
+
+cRect cViewListItem::DrawListItem(map <string,string> *stringTokens, map <string,int> *intTokens) {
+ cRect posItem;
+ if (!tmplItem)
+ return posItem;
+
+ if (tmplItem->DebugTokens()) {
+ DebugTokens("ListItem", stringTokens, intTokens);
+ }
+
+ tmplItem->InitIterator();
+ cTemplatePixmap *pix = NULL;
+ int pixCurrent = 0;
+
+ while(pix = tmplItem->GetNextPixmap()) {
+ SetListElementPosition(pix);
+ if (pixCurrent == 0) {
+ posItem = pix->GetPixmapSize();
+ }
+ if (!PixmapExists(pixCurrent)) {
+ pix->ParseDynamicParameters(intTokens, true);
+ } else {
+ pix->ParseDynamicParameters(intTokens, false);
+ }
+ if (!PixmapExists(pixCurrent) && pix->Ready() && pix->DoExecute() && !pix->Scrolling()) {
+ CreateViewPixmap(pixCurrent, pix);
+ }
+ //if pixmap still not valid, skip
+ if (!pix->Ready() && !pix->Scrolling()) {
+ pixCurrent++;
+ continue;
+ }
+ //if condition for pixmap set, check if cond is true
+ if (!pix->DoExecute()) {
+ pixCurrent++;
+ continue;
+ }
+
+ pix->ClearDynamicFunctionParameters();
+ pix->ParseDynamicFunctionParameters(stringTokens, intTokens);
+
+ if (!PixmapExists(pixCurrent) && pix->Scrolling()) {
+ cSize drawportSize;
+ scrolling = pix->CalculateDrawPortSize(drawportSize);
+ pix->SetScrollingTextWidth();
+ if (scrolling) {
+ CreateScrollingPixmap(pixCurrent, pix, drawportSize);
+ scrollingPix = pixCurrent;
+ scrollOrientation = pix->GetNumericParameter(ptOrientation);
+ scrollMode = pix->GetNumericParameter(ptScrollMode);
+ scrollDelay = pix->GetNumericParameter(ptDelay);
+ scrollSpeed = pix->GetNumericParameter(ptScrollSpeed);
+ } else {
+ CreateViewPixmap(pixCurrent, pix);
+ }
+ }
+ if (pix->DoDebug()) {
+ pix->Debug();
+ }
+ DrawPixmap(pixCurrent, pix);
+ pixCurrent++;
+ }
+ return posItem;
+}
+
+void cViewListItem::ClearListItem(void) {
+ int pixMax = NumPixmaps();
+ for (int pixCurrent = 0; pixCurrent < pixMax; pixCurrent++) {
+ Fill(pixCurrent, clrTransparent);
+ }
+}
+
+void cViewListItem::SetListElementPosition(cTemplatePixmap *pix) {
+ int itemWidth = pix->GetNumericParameter(ptWidth);
+ int itemHeight = pix->GetNumericParameter(ptHeight);
+ int x = 0;
+ int y = 0;
+ if (listOrientation == orHorizontal) {
+ x = container.X();
+ int totalWidth = numTotal * itemWidth;
+ if (align == alCenter) {
+ y += (container.Width() - totalWidth) / 2;
+ } else if (align == alBottom) {
+ y += (container.Width() - totalWidth);
+ }
+ x += pos * itemWidth;
+ y = pix->GetNumericParameter(ptY);
+ } else if (listOrientation == orVertical) {
+ y = container.Y();
+ int totalHeight = numTotal * itemHeight;
+ if (align == alCenter) {
+ y += (container.Height() - totalHeight) / 2;
+ } else if (align == alBottom) {
+ y += (container.Height() - totalHeight);
+ }
+ y += pos * itemHeight;
+ x = pix->GetNumericParameter(ptX);
+ }
+ pix->SetX(x);
+ pix->SetY(y);
+}
+
diff --git a/views/view.h b/views/view.h
new file mode 100644
index 0000000..4609935
--- /dev/null
+++ b/views/view.h
@@ -0,0 +1,72 @@
+#ifndef __VIEW_H
+#define __VIEW_H
+
+#include "string"
+#include "map"
+#include "../libcore/pixmapcontainer.h"
+#include "../libtemplate/template.h"
+
+using namespace std;
+
+class cView : public cPixmapContainer {
+private:
+ void Init(void);
+ void DoFill(int num, cTemplateFunction *func);
+ void DoDrawText(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0);
+ void DoDrawTextBox(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0);
+ void DoDrawFloatingTextBox(int num, cTemplateFunction *func);
+ void DoDrawRectangle(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0);
+ void DoDrawEllipse(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0);
+ void DoDrawImage(int num, cTemplateFunction *func, int x0 = 0, int y0 = 0);
+ void ActivateScrolling(void);
+protected:
+ cTemplateView *tmplView;
+ cTemplateViewElement *tmplItem;
+ cTemplateViewTab *tmplTab;
+ //scaling window
+ cRect scalingWindow;
+ bool tvScaled;
+ bool viewInit;
+ //true if view is scrollable in general
+ bool scrolling;
+ //true if view is actually starting scrolling
+ bool currentlyScrolling;
+ eViewElement veScroll;
+ int scrollingPix;
+ int scrollOrientation;
+ int scrollDelay;
+ int scrollMode;
+ int scrollSpeed;
+ void DrawViewElement(eViewElement ve, map <string,string> *stringTokens = NULL, map <string,int> *intTokens = NULL, map < string, vector< map< string, string > > > *loopTokens = NULL);
+ void ClearViewElement(eViewElement ve);
+ bool ViewElementImplemented(eViewElement ve);
+ void CreateViewPixmap(int num, cTemplatePixmap *pix, cRect *size = NULL);
+ void CreateScrollingPixmap(int num, cTemplatePixmap *pix, cSize &drawportSize);
+ void DrawPixmap(int num, cTemplatePixmap *pix, map < string, vector< map< string, string > > > *loopTokens = NULL, bool flushPerLoop = false);
+ void DrawLoop(int numPixmap, cTemplateFunction *func, map < string, vector< map< string, string > > > *loopTokens);
+ void DebugTokens(string viewElement, map<string,string> *stringTokens, map<string,int> *intTokens, map < string, vector< map< string, string > > > *loopTokens = NULL);
+ virtual void Action(void);
+public:
+ cView(cTemplateView *tmplView);
+ cView(cTemplateViewElement *tmplItem);
+ cView(cTemplateViewTab *tmplTab);
+ virtual ~cView();
+ virtual void Stop(void);
+};
+
+class cViewListItem : public cView {
+protected:
+ int pos;
+ int numTotal;
+ cRect container;
+ int align;
+ int listOrientation;
+ void SetListElementPosition(cTemplatePixmap *pix);
+public:
+ cViewListItem(cTemplateViewElement *tmplItem);
+ virtual ~cViewListItem();
+ cRect DrawListItem(map <string,string> *stringTokens, map <string,int> *intTokens);
+ void ClearListItem(void);
+};
+
+#endif //__VIEW_H \ No newline at end of file