diff options
author | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
---|---|---|
committer | louis <louis.braun@gmx.de> | 2014-09-27 09:25:14 +0200 |
commit | b0509b5182b6e0d04f05e6b3d5676b0d21f51966 (patch) | |
tree | 22b302342f22843e0815eb5f516c85f1478cbf0b /views | |
download | vdr-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')
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 |