#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; isPluginTextView = false; currentTmplTab = NULL; tabView = NULL; } cDisplayMenuDetailView::~cDisplayMenuDetailView() { CancelSave(); if (tabView) delete tabView; } void cDisplayMenuDetailView::SetPluginTokens(map *plugStringTokens, map *plugIntTokens, map > > *plugLoopTokens) { for (map::iterator it = plugStringTokens->begin(); it != plugStringTokens->end(); it++) { stringTokens.insert(pair(it->first, it->second)); } for (map::iterator it = plugIntTokens->begin(); it != plugIntTokens->end(); it++) { intTokens.insert(pair(it->first, it->second)); } for(map > >::iterator it = plugLoopTokens->begin(); it != plugLoopTokens->end(); it++) { loopTokens.insert(pair > >(it->first, it->second)); } isPluginTextView = true; } 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("title", event->Title() ? event->Title() : "")); stringTokens.insert(pair("shorttext", event->ShortText() ? event->ShortText() : "")); stringTokens.insert(pair("description", event->Description() ? event->Description() : "")); stringTokens.insert(pair("start", *(event->GetTimeString()))); stringTokens.insert(pair("stop", *(event->GetEndTimeString()))); time_t startTime = event->StartTime(); stringTokens.insert(pair("day", *WeekDayName(startTime))); stringTokens.insert(pair("date", *ShortDateString(startTime))); struct tm * sStartTime = localtime(&startTime); intTokens.insert(pair("year", sStartTime->tm_year + 1900)); intTokens.insert(pair("daynumeric", sStartTime->tm_mday)); intTokens.insert(pair("month", sStartTime->tm_mon+1)); string channelID = *(event->ChannelID().ToString()); stringTokens.insert(pair("channelid", channelID)); intTokens.insert(pair("channellogoexists", imgCache->LogoExists(channelID))); bool isRunning = false; time_t now = time(NULL); if ((now >= event->StartTime()) && (now <= event->EndTime())) isRunning = true; intTokens.insert(pair("running", isRunning)); if (isRunning) { intTokens.insert(pair("elapsed", (now - event->StartTime())/60)); } else { intTokens.insert(pair("elapsed", 0)); } intTokens.insert(pair("duration", event->Duration() / 60)); intTokens.insert(pair("durationhours", event->Duration() / 3600)); stringTokens.insert(pair("durationminutes", *cString::sprintf("%.2d", (event->Duration() / 60)%60))); if (event->Vps()) stringTokens.insert(pair("vps", *event->GetVpsString())); else stringTokens.insert(pair("vps", "")); vector< map< string, string > > reruns; bool hasReruns = LoadReruns(&reruns); loopTokens.insert(pair > >("reruns", reruns)); intTokens.insert(pair("hasreruns", hasReruns)); SetScraperTokens(event, recording, stringTokens, intTokens, loopTokens); SetEpgPictures(event->EventID()); } else if (recording) { string name = recording->Name() ? recording->Name() : ""; stringTokens.insert(pair("name", name)); intTokens.insert(pair("cutted", recording->IsEdited())); const cRecordingInfo *info = recording->Info(); if (info) { stringTokens.insert(pair("epgname", info->Title() ? info->Title() : name)); stringTokens.insert(pair("shorttext", info->ShortText() ? info->ShortText() : "")); stringTokens.insert(pair("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); } stringTokens.insert(pair("date", recDate.c_str())); stringTokens.insert(pair("time", recTime.c_str())); time_t startTime = event->StartTime(); struct tm * sStartTime = localtime(&startTime); intTokens.insert(pair("year", sStartTime->tm_year + 1900)); intTokens.insert(pair("daynumeric", sStartTime->tm_mday)); intTokens.insert(pair("month", sStartTime->tm_mon+1)); int duration = event->Duration() / 60; int recDuration = recording->LengthInSeconds(); recDuration = (recDuration>0)?(recDuration / 60):0; intTokens.insert(pair("duration", recDuration)); intTokens.insert(pair("durationhours", recDuration / 60)); stringTokens.insert(pair("durationminutes", *cString::sprintf("%.2d", recDuration%60))); intTokens.insert(pair("durationevent", duration)); intTokens.insert(pair("durationeventhours", duration / 60)); stringTokens.insert(pair("durationeventminutes", *cString::sprintf("%.2d", duration%60))); } } else { stringTokens.insert(pair("epgname", "")); stringTokens.insert(pair("shorttext", "")); stringTokens.insert(pair("description", "")); int recDuration = recording->LengthInSeconds(); recDuration = (recDuration>0)?(recDuration / 60):0; stringTokens.insert(pair("date", "")); stringTokens.insert(pair("time", "")); intTokens.insert(pair("duration", recDuration)); intTokens.insert(pair("durationhours", recDuration / 60)); stringTokens.insert(pair("durationminutes", *cString::sprintf("%.2d", recDuration%60))); intTokens.insert(pair("durationevent", 0)); intTokens.insert(pair("durationeventhours", 0)); stringTokens.insert(pair("durationeventminutes", "")); } LoadRecordingInformation(); SetScraperTokens(event, recording, stringTokens, intTokens, loopTokens); SetRecordingImages(recording->FileName()); } else if (text) { stringTokens.insert(pair("text", text)); } else { intTokens.insert(pair("running", false)); intTokens.insert(pair("hasreruns", 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 = config.rerunAmount; int rerunDistance = config.rerunDistance * 3600; int rerunNaxChannel = config.rerunMaxChannel; Epgsearch_searchresults_v1_0 data; string strQuery = (event->Title()) ? event->Title() : ""; data.query = (char *)strQuery.c_str(); data.mode = 0; data.channelNr = 0; data.useTitle = true; data.useSubTitle = true; data.useDescription = false; bool foundRerun = false; if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) { cList* 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)) { time_t eventStart = event->StartTime(); time_t rerunStart = r->event->StartTime(); cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true); //check for identical event if ((event->ChannelID() == r->event->ChannelID()) && (eventStart == rerunStart)) continue; //check for timely distance if (rerunDistance > 0) { if (rerunStart - eventStart < rerunDistance) { continue; } } //check for maxchannel if (rerunNaxChannel > 0) { if (channel && channel->Number() > rerunNaxChannel) { continue; } } i++; map< string, string > rerun; rerun.insert(pair("reruns[title]", r->event->Title() ? r->event->Title() : "")); rerun.insert(pair("reruns[shorttext]", r->event->ShortText() ? r->event->ShortText() : "")); rerun.insert(pair("reruns[start]", *(r->event->GetTimeString()))); rerun.insert(pair("reruns[start]", *(r->event->GetTimeString()))); rerun.insert(pair("reruns[stop]", *(r->event->GetEndTimeString()))); rerun.insert(pair("reruns[date]", *ShortDateString(r->event->StartTime()))); rerun.insert(pair("reruns[day]", *WeekDayName(r->event->StartTime()))); string channelID = *(r->event->ChannelID().ToString()); rerun.insert(pair("reruns[channelid]", channelID)); bool logoExists = imgCache->LogoExists(channelID); rerun.insert(pair("reruns[channellogoexists]", logoExists ? "1" : "0")); if (channel) { stringstream channelNumber; channelNumber << channel->Number(); rerun.insert(pair("reruns[channelname]", channel->ShortName(true))); rerun.insert(pair("reruns[channelnumber]", channelNumber.str())); } else { rerun.insert(pair("reruns[channelname]", "")); rerun.insert(pair("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("recordingsize", *strRecSize)); stringTokens.insert(pair("recordingsizecutted", *strRecSizeCut)); } else { stringTokens.insert(pair("recordingsize", "")); stringTokens.insert(pair("recordingsizecutted", "")); } cChannel *channel = Channels.GetByChannelID(Info->ChannelID()); if (channel) { stringTokens.insert(pair("recchannelname", channel->Name())); stringTokens.insert(pair("recchannelid", *channel->GetChannelID().ToString())); intTokens.insert(pair("recchannelnumber", channel->Number())); } else { stringTokens.insert(pair("recchannelname", "")); stringTokens.insert(pair("recchannelid", "")); intTokens.insert(pair("recchannelnumber", 0)); } 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("recordinglength", strLength)); stringTokens.insert(pair("recordinglengthcutted", strLengthCutted)); stringTokens.insert(pair("recordingbitrate", strBitrate)); } delete index; } string recFormat = recording->IsPesRecording() ? "PES" : "TS"; stringTokens.insert(pair("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("searchtimer", searchTimer)); searchTimerFound = true; } } } } if (!searchTimerFound) stringTokens.insert(pair("searchtimer", "n.a.")); } string cDisplayMenuDetailView::StripXmlTag(string &Line, const char *Tag) { // set the search strings stringstream strStart, strStop; strStart << "<" << Tag << ">"; strStop << ""; // 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(available.str(), true)); stringTokens.insert(pair(path.str(), *cString::sprintf("%s%s.jpg", *config.epgImagePath, picName.str().c_str()))); } else { intTokens.insert(pair(available.str(), false)); stringTokens.insert(pair(path.str(), "")); } } } void cDisplayMenuDetailView::SetRecordingImages(const char *recPath) { if (!recPath) { intTokens.insert(pair("recimg1avaialble", false)); intTokens.insert(pair("recimg2avaialble", false)); intTokens.insert(pair("recimg3avaialble", false)); stringTokens.insert(pair("recimg1path", "")); stringTokens.insert(pair("recimg2path", "")); stringTokens.insert(pair("recimg3path", "")); return; } string path = recPath; DIR *dirHandle; struct dirent *dirEntry; dirHandle = opendir(recPath); if (!dirHandle) { intTokens.insert(pair("recimg1avaialble", false)); intTokens.insert(pair("recimg2avaialble", false)); intTokens.insert(pair("recimg3avaialble", false)); stringTokens.insert(pair("recimg1path", "")); stringTokens.insert(pair("recimg2path", "")); stringTokens.insert(pair("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(available.str(), true)); stringTokens.insert(pair(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(available.str(), false)); stringTokens.insert(pair(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("ismovie", false)); headerIntTokens.insert(pair("isseries", false)); headerIntTokens.insert(pair("posteravailable", false)); headerIntTokens.insert(pair("banneravailable", false)); } else { ScraperGetEventType getType; getType.event = event; getType.recording = recording; if (!pScraper->Service("GetEventType", &getType)) { headerIntTokens.insert(pair("ismovie", false)); headerIntTokens.insert(pair("isseries", false)); headerIntTokens.insert(pair("posteravailable", false)); headerIntTokens.insert(pair("banneravailable", false)); } else { if (getType.type == tMovie) { cMovie movie; movie.movieId = getType.movieId; pScraper->Service("GetMovie", &movie); headerIntTokens.insert(pair("ismovie", true)); headerIntTokens.insert(pair("isseries", false)); headerIntTokens.insert(pair("posteravailable", true)); headerIntTokens.insert(pair("banneravailable", false)); headerStringTokens.insert(pair("posterpath", movie.poster.path)); headerIntTokens.insert(pair("posterwidth", movie.poster.width)); headerIntTokens.insert(pair("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("ismovie", false)); headerIntTokens.insert(pair("isseries", true)); vector::iterator poster = series.posters.begin(); if (poster != series.posters.end()) { headerIntTokens.insert(pair("posterwidth", (*poster).width)); headerIntTokens.insert(pair("posterheight", (*poster).height)); headerStringTokens.insert(pair("posterpath", (*poster).path)); headerIntTokens.insert(pair("posteravailable", true)); } else { headerIntTokens.insert(pair("posterwidth", 0)); headerIntTokens.insert(pair("posterheight", 0)); headerStringTokens.insert(pair("posterpath", "")); headerIntTokens.insert(pair("posteravailable", false)); } vector::iterator banner = series.banners.begin(); if (banner != series.banners.end()) { headerIntTokens.insert(pair("bannerwidth", (*banner).width)); headerIntTokens.insert(pair("bannerheight", (*banner).height)); headerStringTokens.insert(pair("bannerpath", (*banner).path)); headerIntTokens.insert(pair("banneravailable", true)); } else { headerIntTokens.insert(pair("bannerwidth", 0)); headerIntTokens.insert(pair("bannerheight", 0)); headerStringTokens.insert(pair("bannerpath", "")); headerIntTokens.insert(pair("banneravailable", false)); } } else { headerIntTokens.insert(pair("ismovie", false)); headerIntTokens.insert(pair("isseries", false)); headerIntTokens.insert(pair("posteravailable", false)); headerIntTokens.insert(pair("banneravailable", false)); } } } } if (event) { headerStringTokens.insert(pair("title", event->Title() ? event->Title() : "")); headerStringTokens.insert(pair("shorttext", event->ShortText() ? event->ShortText() : "")); headerStringTokens.insert(pair("start", *(event->GetTimeString()))); headerStringTokens.insert(pair("stop", *(event->GetEndTimeString()))); time_t startTime = event->StartTime(); headerStringTokens.insert(pair("day", *WeekDayName(startTime))); headerStringTokens.insert(pair("date", *ShortDateString(startTime))); struct tm * sStartTime = localtime(&startTime); headerIntTokens.insert(pair("year", sStartTime->tm_year + 1900)); headerIntTokens.insert(pair("daynumeric", sStartTime->tm_mday)); headerIntTokens.insert(pair("month", sStartTime->tm_mon+1)); const cChannel *channel = Channels.GetByChannelID(event->ChannelID()); if (channel) { headerStringTokens.insert(pair("channelname", channel->Name() ? channel->Name() : "")); headerIntTokens.insert(pair("channelnumber", channel->Number())); } else { headerStringTokens.insert(pair("channelname", "")); headerIntTokens.insert(pair("channelnumber", 0)); } string channelID = *(channel->GetChannelID().ToString()); headerStringTokens.insert(pair("channelid", channelID)); headerIntTokens.insert(pair("channellogoexists", imgCache->LogoExists(channelID))); bool isRunning = false; time_t now = time(NULL); if ((now >= event->StartTime()) && (now <= event->EndTime())) isRunning = true; headerIntTokens.insert(pair("running", isRunning)); if (isRunning) { headerIntTokens.insert(pair("elapsed", (now - event->StartTime())/60)); } else { headerIntTokens.insert(pair("elapsed", 0)); } headerIntTokens.insert(pair("duration", event->Duration() / 60)); headerIntTokens.insert(pair("durationhours", event->Duration() / 3600)); headerStringTokens.insert(pair("durationminutes", *cString::sprintf("%.2d", (event->Duration() / 60)%60))); if (event->Vps()) headerStringTokens.insert(pair("vps", *event->GetVpsString())); else headerStringTokens.insert(pair("vps", "")); stringstream epgImageName; epgImageName << event->EventID(); bool epgPicAvailable = FileExists(*config.epgImagePath, epgImageName.str(), "jpg"); if (epgPicAvailable) { headerIntTokens.insert(pair("epgpicavailable", true)); headerStringTokens.insert(pair("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("epgpicavailable", true)); headerStringTokens.insert(pair("epgpicpath", *cString::sprintf("%s%s.jpg", *config.epgImagePath, epgImageName.str().c_str()))); } else { headerIntTokens.insert(pair("epgpicavailable", false)); headerStringTokens.insert(pair("epgpicpath", "")); } } DrawViewElement(veDetailHeader, &headerStringTokens, &headerIntTokens); return; } else if (recording) { string name = recording->Name() ? recording->Name() : ""; headerStringTokens.insert(pair("name", name)); const cRecordingInfo *info = recording->Info(); if (info) { headerStringTokens.insert(pair("epgname", info->Title() ? info->Title() : name)); headerStringTokens.insert(pair("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("date", recDate.c_str())); headerStringTokens.insert(pair("time", recTime.c_str())); time_t startTime = event->StartTime(); struct tm * sStartTime = localtime(&startTime); headerIntTokens.insert(pair("year", sStartTime->tm_year + 1900)); headerIntTokens.insert(pair("daynumeric", sStartTime->tm_mday)); headerIntTokens.insert(pair("month", sStartTime->tm_mon+1)); headerIntTokens.insert(pair("duration", recDuration)); headerIntTokens.insert(pair("durationhours", recDuration / 60)); headerStringTokens.insert(pair("durationminutes", *cString::sprintf("%.2d", recDuration%60))); headerIntTokens.insert(pair("durationevent", duration)); headerIntTokens.insert(pair("durationeventhours", duration / 60)); headerStringTokens.insert(pair("durationeventminutes", *cString::sprintf("%.2d", duration%60))); } cChannel *channel = Channels.GetByChannelID(info->ChannelID()); if (channel) { headerStringTokens.insert(pair("recchannelname", channel->Name())); headerStringTokens.insert(pair("recchannelid", *channel->GetChannelID().ToString())); headerIntTokens.insert(pair("recchannelnumber", channel->Number())); } else { headerStringTokens.insert(pair("recchannelname", "")); headerStringTokens.insert(pair("recchannelid", "")); headerIntTokens.insert(pair("recchannelnumber", 0)); } } else { headerStringTokens.insert(pair("shorttext", "")); int recDuration = recording->LengthInSeconds(); recDuration = (recDuration>0)?(recDuration / 60):0; headerStringTokens.insert(pair("date", "")); headerStringTokens.insert(pair("time", "")); headerIntTokens.insert(pair("duration", recDuration)); headerIntTokens.insert(pair("durationhours", recDuration / 60)); headerStringTokens.insert(pair("durationminutes", *cString::sprintf("%.2d", recDuration%60))); headerIntTokens.insert(pair("durationevent", 0)); headerIntTokens.insert(pair("durationeventhours", 0)); headerStringTokens.insert(pair("durationeventminutes", "")); headerStringTokens.insert(pair("recchannelname", "")); headerStringTokens.insert(pair("recchannelid", "")); headerIntTokens.insert(pair("recchannelnumber", 0)); } string recImage = ""; string path = recording->FileName() ? recording->FileName() : ""; string extension = ".jpg"; if (FirstFileInFolder(path, extension, recImage)) { headerIntTokens.insert(pair("recimgavailable", true)); headerStringTokens.insert(pair("recimgpath", *cString::sprintf("%s/%s", path.c_str(), recImage.c_str()))); } else { headerIntTokens.insert(pair("recimgavailable", false)); headerStringTokens.insert(pair("recimgpath", "")); } DrawViewElement(veDetailHeader, &headerStringTokens, &headerIntTokens); return; } if (isPluginTextView) { DrawViewElement(veDetailHeader, &stringTokens, &intTokens); } } 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("height", barHeight)); scrollbarIntTokens.insert(pair("offset", barTop)); ClearViewElement(veScrollbar); DrawViewElement(veScrollbar, &scrollbarStringTokens, &scrollbarIntTokens); } void cDisplayMenuDetailView::DrawTabLabels(void) { if (!ExecuteViewElement(veTabLabels)) { return; } map < string, string > labelStringTokens; map < string, int > labelIntTokens; map < string, vector< map< string, string > > > labelLoopTokens; string labelPrev = ""; string labelPrevTemp = ""; string labelCurrent = ""; string labelNext = ""; bool wasCurrent = false; vector< map< string, string > > tabLabels; for (list::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 (wasCurrent) { labelNext = tab->GetName(); } if (tab == currentTmplTab) { wasCurrent = true; labelCurrent = tab->GetName(); labelPrev = labelPrevTemp; tabLabel.insert(pair< string, string >("tabs[current]", "1")); } else { wasCurrent = false; tabLabel.insert(pair< string, string >("tabs[current]", "0")); } labelPrevTemp = tab->GetName(); tabLabels.push_back(tabLabel); } if (labelNext.size() == 0 && activeTabs.size() > 0) { cTemplateViewTab *firstTab = activeTabs.front(); labelNext = firstTab->GetName(); } if (labelPrev.size() == 0 && activeTabs.size() > 0) { cTemplateViewTab *lastTab = activeTabs.back(); labelPrev = lastTab->GetName(); } labelStringTokens.insert(pair< string, string >("currenttab", labelCurrent)); labelStringTokens.insert(pair< string, string >("nexttab", labelNext)); labelStringTokens.insert(pair< string, string >("prevtab", labelPrev)); 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; }