summaryrefslogtreecommitdiff
path: root/views/displaymenudetailview.c
diff options
context:
space:
mode:
authorlouis <louis.braun@gmx.de>2014-09-27 09:25:14 +0200
committerlouis <louis.braun@gmx.de>2014-09-27 09:25:14 +0200
commitb0509b5182b6e0d04f05e6b3d5676b0d21f51966 (patch)
tree22b302342f22843e0815eb5f516c85f1478cbf0b /views/displaymenudetailview.c
downloadvdr-plugin-skindesigner-0.0.1.tar.gz
vdr-plugin-skindesigner-0.0.1.tar.bz2
initial commit version 0.0.10.0.1
Diffstat (limited to 'views/displaymenudetailview.c')
-rw-r--r--views/displaymenudetailview.c929
1 files changed, 929 insertions, 0 deletions
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;
+}