mirror of
https://projects.vdr-developer.org/git/vdr-plugin-skindesigner.git
synced 2023-10-19 17:58:31 +02:00
1033 lines
51 KiB
C
1033 lines
51 KiB
C
#include "viewdetail.h"
|
|
#include "../config.h"
|
|
#include "../extensions/helpers.h"
|
|
/******************************************************************
|
|
* cViewDetail
|
|
******************************************************************/
|
|
cViewDetail::cViewDetail(void) {
|
|
activeTab = NULL;
|
|
activeTabIndex = -1;
|
|
numTabs = 0;
|
|
plugId = -1;
|
|
plugMenuId = -1;
|
|
}
|
|
|
|
cViewDetail::~cViewDetail(void) {
|
|
}
|
|
|
|
void cViewDetail::SetActiveTab(void) {
|
|
for (cAreaNode *node = areaNodes.First(); node; node = areaNodes.Next(node)) {
|
|
if (node->ActiveTab()) {
|
|
activeTab = dynamic_cast<cArea*>(node);
|
|
activeTabIndex = 0;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
int cViewDetail::GetWidth(void) {
|
|
cAreaNode *node = areaNodes.First();
|
|
if (!node)
|
|
return 0;
|
|
return node->GetWidth();
|
|
}
|
|
|
|
void cViewDetail::ResetTabs(void) {
|
|
activeTab = NULL;
|
|
activeTabIndex = -1;
|
|
}
|
|
|
|
void cViewDetail::Clear(bool forceClearBackground) {
|
|
cViewElement::Close();
|
|
}
|
|
|
|
void cViewDetail::Close(void) {
|
|
cViewElement::Close();
|
|
activeTab = NULL;
|
|
activeTabIndex = -1;
|
|
numTabs = 0;
|
|
}
|
|
|
|
void cViewDetail::Render(void) {
|
|
if (!dirty || blocked)
|
|
return;
|
|
|
|
if (attribs->DoDebug())
|
|
Debug();
|
|
|
|
if (!activeTab)
|
|
SetActiveTab();
|
|
if (!activeTab)
|
|
return;
|
|
|
|
activeTab->Clear();
|
|
if (activeTab->Execute()) {
|
|
activeTab->Render();
|
|
}
|
|
|
|
dirty = false;
|
|
}
|
|
|
|
void cViewDetail::Scrollbar(int &barheight, int &offset, bool &end) {
|
|
if (!activeTab)
|
|
return;
|
|
cRect tabViewPort = activeTab->ViewPort();
|
|
cRect tabDrawPort = activeTab->DrawPort();
|
|
int totalHeight = tabDrawPort.Height();
|
|
int screenHeight = tabViewPort.Height();
|
|
int y = (-1)*tabDrawPort.Y();
|
|
if (totalHeight == 0) {
|
|
return;
|
|
}
|
|
if (totalHeight <= screenHeight)
|
|
barheight = 1000;
|
|
else {
|
|
barheight = (double)screenHeight / (double) totalHeight * 1000;
|
|
}
|
|
offset = (double)y / (double) totalHeight * 1000;
|
|
end = true;
|
|
}
|
|
|
|
bool cViewDetail::ScrollUp(bool page) {
|
|
if (!activeTab)
|
|
return false;
|
|
cRect tabDrawPort = activeTab->DrawPort();
|
|
int scrollStep = activeTab->ScrollStep();
|
|
if (page) {
|
|
cRect tabViewPort = activeTab->ViewPort();
|
|
scrollStep = tabViewPort.Height();
|
|
}
|
|
int aktHeight = tabDrawPort.Y();
|
|
if (aktHeight >= 0) {
|
|
return false;
|
|
}
|
|
int newY = aktHeight + scrollStep;
|
|
if (newY > 0)
|
|
newY = 0;
|
|
cPoint dp(0, newY);
|
|
activeTab->SetDrawPort(dp);
|
|
return true;
|
|
}
|
|
|
|
bool cViewDetail::ScrollDown(bool page) {
|
|
if (!activeTab)
|
|
return false;
|
|
cRect tabViewPort = activeTab->ViewPort();
|
|
cRect tabDrawPort = activeTab->DrawPort();
|
|
int scrollStep = activeTab->ScrollStep();
|
|
if (page) {
|
|
scrollStep = tabViewPort.Height();
|
|
}
|
|
int aktHeight = tabDrawPort.Y();
|
|
int totalHeight = tabDrawPort.Height();
|
|
int screenHeight = tabViewPort.Height();
|
|
|
|
if (totalHeight - ((-1)*aktHeight) == screenHeight) {
|
|
return false;
|
|
}
|
|
int newY = aktHeight - scrollStep;
|
|
if ((-1)*newY > totalHeight - screenHeight)
|
|
newY = (-1)*(totalHeight - screenHeight);
|
|
cPoint dp(0, newY);
|
|
activeTab->SetDrawPort(dp);
|
|
return true;
|
|
}
|
|
|
|
int cViewDetail::GetTabs(vector<const char*> &tabs) {
|
|
int i=0;
|
|
for (cAreaNode *node = areaNodes.First(); node; node = areaNodes.Next(node)) {
|
|
if (!node->Execute())
|
|
continue;
|
|
tabs.push_back(node->Name());
|
|
if (node->ActiveTab()) {
|
|
activeTabIndex = i;
|
|
}
|
|
i++;
|
|
}
|
|
numTabs = i;
|
|
return activeTabIndex;
|
|
}
|
|
|
|
void cViewDetail::NextTab(void) {
|
|
cArea *nextActiveTab = NULL;
|
|
for (cAreaNode *node = areaNodes.Next(activeTab); node; node = areaNodes.Next(node)) {
|
|
if (node->Execute()) {
|
|
nextActiveTab = dynamic_cast<cArea*>(node);
|
|
activeTabIndex++;
|
|
break;
|
|
}
|
|
}
|
|
if (!nextActiveTab) {
|
|
nextActiveTab = dynamic_cast<cArea*>(areaNodes.First());
|
|
activeTabIndex = 0;
|
|
}
|
|
activeTab = nextActiveTab;
|
|
}
|
|
|
|
void cViewDetail::PrevTab(void) {
|
|
cArea *prevActiveTab = NULL;
|
|
for (cAreaNode *node = areaNodes.Prev(activeTab); node; node = areaNodes.Prev(node)) {
|
|
if (node->Execute()) {
|
|
prevActiveTab = dynamic_cast<cArea*>(node);
|
|
activeTabIndex--;
|
|
break;
|
|
}
|
|
}
|
|
if (!prevActiveTab) {
|
|
int numActiveTabs = 0;
|
|
for (cAreaNode *node = areaNodes.First(); node; node = areaNodes.Next(node)) {
|
|
if (node->Execute()) {
|
|
numActiveTabs++;
|
|
}
|
|
}
|
|
for (cAreaNode *node = areaNodes.Last(); node; node = areaNodes.Prev(node)) {
|
|
if (node->Execute()) {
|
|
prevActiveTab = dynamic_cast<cArea*>(node);
|
|
activeTabIndex = numActiveTabs-1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
activeTab = prevActiveTab;
|
|
}
|
|
|
|
void cViewDetail::SetTransparency(int transparency, bool forceDetached) {
|
|
if (activeTab)
|
|
activeTab->SetTransparency(transparency);
|
|
}
|
|
|
|
/******************************************************************
|
|
* cViewDetailEpg
|
|
******************************************************************/
|
|
cViewDetailEpg::cViewDetailEpg(void) {
|
|
event = NULL;
|
|
rerunsIndex = -1;
|
|
actorsIndex = -1;
|
|
}
|
|
|
|
cViewDetailEpg::~cViewDetailEpg(void) {
|
|
}
|
|
|
|
void cViewDetailEpg::SetTokenContainer(void) {
|
|
tokenContainer = new skindesignerapi::cTokenContainer();
|
|
tokenContainer->DefineStringToken("{title}", (int)eDmDetailedEpgST::title);
|
|
tokenContainer->DefineStringToken("{shorttext}", (int)eDmDetailedEpgST::shorttext);
|
|
tokenContainer->DefineStringToken("{description}", (int)eDmDetailedEpgST::description);
|
|
tokenContainer->DefineStringToken("{start}", (int)eDmDetailedEpgST::start);
|
|
tokenContainer->DefineStringToken("{stop}", (int)eDmDetailedEpgST::stop);
|
|
tokenContainer->DefineStringToken("{day}", (int)eDmDetailedEpgST::day);
|
|
tokenContainer->DefineStringToken("{date}", (int)eDmDetailedEpgST::date);
|
|
tokenContainer->DefineStringToken("{durationminutes}", (int)eDmDetailedEpgST::durationminutes);
|
|
tokenContainer->DefineStringToken("{vps}", (int)eDmDetailedEpgST::vps);
|
|
tokenContainer->DefineStringToken("{channelname}", (int)eDmDetailedEpgST::channelname);
|
|
tokenContainer->DefineStringToken("{channelid}", (int)eDmDetailedEpgST::channelid);
|
|
tokenContainer->DefineStringToken("{epgpic1path}", (int)eDmDetailedEpgST::epgpic1path);
|
|
tokenContainer->DefineStringToken("{epgpic2path}", (int)eDmDetailedEpgST::epgpic2path);
|
|
tokenContainer->DefineStringToken("{epgpic3path}", (int)eDmDetailedEpgST::epgpic3path);
|
|
tokenContainer->DefineStringToken("{movietitle}", (int)eScraperST::movietitle);
|
|
tokenContainer->DefineStringToken("{movieoriginalTitle}", (int)eScraperST::movieoriginalTitle);
|
|
tokenContainer->DefineStringToken("{movietagline}", (int)eScraperST::movietagline);
|
|
tokenContainer->DefineStringToken("{movieoverview}", (int)eScraperST::movieoverview);
|
|
tokenContainer->DefineStringToken("{moviegenres}", (int)eScraperST::moviegenres);
|
|
tokenContainer->DefineStringToken("{moviehomepage}", (int)eScraperST::moviehomepage);
|
|
tokenContainer->DefineStringToken("{moviereleasedate}", (int)eScraperST::moviereleasedate);
|
|
tokenContainer->DefineStringToken("{moviepopularity}", (int)eScraperST::moviepopularity);
|
|
tokenContainer->DefineStringToken("{movievoteaverage}", (int)eScraperST::movievoteaverage);
|
|
tokenContainer->DefineStringToken("{posterpath}", (int)eScraperST::posterpath);
|
|
tokenContainer->DefineStringToken("{fanartpath}", (int)eScraperST::fanartpath);
|
|
tokenContainer->DefineStringToken("{moviecollectionName}", (int)eScraperST::moviecollectionName);
|
|
tokenContainer->DefineStringToken("{collectionposterpath}", (int)eScraperST::collectionposterpath);
|
|
tokenContainer->DefineStringToken("{collectionfanartpath}", (int)eScraperST::collectionfanartpath);
|
|
tokenContainer->DefineStringToken("{seriesname}", (int)eScraperST::seriesname);
|
|
tokenContainer->DefineStringToken("{seriesoverview}", (int)eScraperST::seriesoverview);
|
|
tokenContainer->DefineStringToken("{seriesfirstaired}", (int)eScraperST::seriesfirstaired);
|
|
tokenContainer->DefineStringToken("{seriesnetwork}", (int)eScraperST::seriesnetwork);
|
|
tokenContainer->DefineStringToken("{seriesgenre}", (int)eScraperST::seriesgenre);
|
|
tokenContainer->DefineStringToken("{seriesrating}", (int)eScraperST::seriesrating);
|
|
tokenContainer->DefineStringToken("{seriesstatus}", (int)eScraperST::seriesstatus);
|
|
tokenContainer->DefineStringToken("{episodetitle}", (int)eScraperST::episodetitle);
|
|
tokenContainer->DefineStringToken("{episodefirstaired}", (int)eScraperST::episodefirstaired);
|
|
tokenContainer->DefineStringToken("{episodegueststars}", (int)eScraperST::episodegueststars);
|
|
tokenContainer->DefineStringToken("{episodeoverview}", (int)eScraperST::episodeoverview);
|
|
tokenContainer->DefineStringToken("{episoderating}", (int)eScraperST::episoderating);
|
|
tokenContainer->DefineStringToken("{episodeimagepath}", (int)eScraperST::episodeimagepath);
|
|
tokenContainer->DefineStringToken("{seasonposterpath}", (int)eScraperST::seasonposterpath);
|
|
tokenContainer->DefineStringToken("{seriesposter1path}", (int)eScraperST::seriesposter1path);
|
|
tokenContainer->DefineStringToken("{seriesposter2path}", (int)eScraperST::seriesposter2path);
|
|
tokenContainer->DefineStringToken("{seriesposter3path}", (int)eScraperST::seriesposter3path);
|
|
tokenContainer->DefineStringToken("{seriesfanart1path}", (int)eScraperST::seriesfanart1path);
|
|
tokenContainer->DefineStringToken("{seriesfanart2path}", (int)eScraperST::seriesfanart2path);
|
|
tokenContainer->DefineStringToken("{seriesfanart3path}", (int)eScraperST::seriesfanart3path);
|
|
tokenContainer->DefineStringToken("{seriesbanner1path}", (int)eScraperST::seriesbanner1path);
|
|
tokenContainer->DefineStringToken("{seriesbanner2path}", (int)eScraperST::seriesbanner2path);
|
|
tokenContainer->DefineStringToken("{seriesbanner3path}", (int)eScraperST::seriesbanner3path);
|
|
tokenContainer->DefineIntToken("{daynumeric}", (int)eDmDetailedEpgIT::daynumeric);
|
|
tokenContainer->DefineIntToken("{month}", (int)eDmDetailedEpgIT::month);
|
|
tokenContainer->DefineIntToken("{year}", (int)eDmDetailedEpgIT::year);
|
|
tokenContainer->DefineIntToken("{running}", (int)eDmDetailedEpgIT::running);
|
|
tokenContainer->DefineIntToken("{elapsed}", (int)eDmDetailedEpgIT::elapsed);
|
|
tokenContainer->DefineIntToken("{duration}", (int)eDmDetailedEpgIT::duration);
|
|
tokenContainer->DefineIntToken("{durationhours}", (int)eDmDetailedEpgIT::durationhours);
|
|
tokenContainer->DefineIntToken("{channelnumber}", (int)eDmDetailedEpgIT::channelnumber);
|
|
tokenContainer->DefineIntToken("{channellogoexists}", (int)eDmDetailedEpgIT::channellogoexists);
|
|
tokenContainer->DefineIntToken("{hasreruns}", (int)eDmDetailedEpgIT::hasreruns);
|
|
tokenContainer->DefineIntToken("{epgpic1available}", (int)eDmDetailedEpgIT::epgpic1available);
|
|
tokenContainer->DefineIntToken("{epgpic2available}", (int)eDmDetailedEpgIT::epgpic2available);
|
|
tokenContainer->DefineIntToken("{epgpic3available}", (int)eDmDetailedEpgIT::epgpic3available);
|
|
tokenContainer->DefineIntToken("{ismovie}", (int)eScraperIT::ismovie);
|
|
tokenContainer->DefineIntToken("{moviebudget}", (int)eScraperIT::moviebudget);
|
|
tokenContainer->DefineIntToken("{movierevenue}", (int)eScraperIT::movierevenue);
|
|
tokenContainer->DefineIntToken("{movieadult}", (int)eScraperIT::movieadult);
|
|
tokenContainer->DefineIntToken("{movieruntime}", (int)eScraperIT::movieruntime);
|
|
tokenContainer->DefineIntToken("{isseries}", (int)eScraperIT::isseries);
|
|
tokenContainer->DefineIntToken("{posterwidth}", (int)eScraperIT::posterwidth);
|
|
tokenContainer->DefineIntToken("{posterheight}", (int)eScraperIT::posterheight);
|
|
tokenContainer->DefineIntToken("{fanartwidth}", (int)eScraperIT::fanartwidth);
|
|
tokenContainer->DefineIntToken("{fanartheight}", (int)eScraperIT::fanartheight);
|
|
tokenContainer->DefineIntToken("{movieiscollection}", (int)eScraperIT::movieiscollection);
|
|
tokenContainer->DefineIntToken("{collectionposterwidth}", (int)eScraperIT::collectionposterwidth);
|
|
tokenContainer->DefineIntToken("{collectionposterheight}", (int)eScraperIT::collectionposterheight);
|
|
tokenContainer->DefineIntToken("{collectionfanartwidth}", (int)eScraperIT::collectionfanartwidth);
|
|
tokenContainer->DefineIntToken("{collectionfanartheight}", (int)eScraperIT::collectionfanartheight);
|
|
tokenContainer->DefineIntToken("{epgpicavailable}", (int)eScraperIT::epgpicavailable);
|
|
tokenContainer->DefineIntToken("{episodenumber}", (int)eScraperIT::episodenumber);
|
|
tokenContainer->DefineIntToken("{episodeseason}", (int)eScraperIT::episodeseason);
|
|
tokenContainer->DefineIntToken("{episodeimagewidth}", (int)eScraperIT::episodeimagewidth);
|
|
tokenContainer->DefineIntToken("{episodeimageheight}", (int)eScraperIT::episodeimageheight);
|
|
tokenContainer->DefineIntToken("{seasonposterwidth}", (int)eScraperIT::seasonposterwidth);
|
|
tokenContainer->DefineIntToken("{seasonposterheight}", (int)eScraperIT::seasonposterheight);
|
|
tokenContainer->DefineIntToken("{seriesposter1width}", (int)eScraperIT::seriesposter1width);
|
|
tokenContainer->DefineIntToken("{seriesposter1height}", (int)eScraperIT::seriesposter1height);
|
|
tokenContainer->DefineIntToken("{seriesposter2width}", (int)eScraperIT::seriesposter2width);
|
|
tokenContainer->DefineIntToken("{seriesposter2height}", (int)eScraperIT::seriesposter2height);
|
|
tokenContainer->DefineIntToken("{seriesposter3width}", (int)eScraperIT::seriesposter3width);
|
|
tokenContainer->DefineIntToken("{seriesposter3height}", (int)eScraperIT::seriesposter3height);
|
|
tokenContainer->DefineIntToken("{seriesfanart1width}", (int)eScraperIT::seriesfanart1width);
|
|
tokenContainer->DefineIntToken("{seriesfanart1height}", (int)eScraperIT::seriesfanart1height);
|
|
tokenContainer->DefineIntToken("{seriesfanart2width}", (int)eScraperIT::seriesfanart2width);
|
|
tokenContainer->DefineIntToken("{seriesfanart2height}", (int)eScraperIT::seriesfanart2height);
|
|
tokenContainer->DefineIntToken("{seriesfanart3width}", (int)eScraperIT::seriesfanart3width);
|
|
tokenContainer->DefineIntToken("{seriesfanart3height}", (int)eScraperIT::seriesfanart3height);
|
|
tokenContainer->DefineIntToken("{seriesbanner1width}", (int)eScraperIT::seriesbanner1width);
|
|
tokenContainer->DefineIntToken("{seriesbanner1height}", (int)eScraperIT::seriesbanner1height);
|
|
tokenContainer->DefineIntToken("{seriesbanner2width}", (int)eScraperIT::seriesbanner2width);
|
|
tokenContainer->DefineIntToken("{seriesbanner2height}", (int)eScraperIT::seriesbanner2height);
|
|
tokenContainer->DefineIntToken("{seriesbanner3width}", (int)eScraperIT::seriesbanner3width);
|
|
tokenContainer->DefineIntToken("{seriesbanner3height}", (int)eScraperIT::seriesbanner3height);
|
|
tokenContainer->DefineLoopToken("{reruns[title]}", (int)eRerunsLT::title);
|
|
tokenContainer->DefineLoopToken("{reruns[shorttext]}", (int)eRerunsLT::shorttext);
|
|
tokenContainer->DefineLoopToken("{reruns[date]}", (int)eRerunsLT::date);
|
|
tokenContainer->DefineLoopToken("{reruns[day]}", (int)eRerunsLT::day);
|
|
tokenContainer->DefineLoopToken("{reruns[start]}", (int)eRerunsLT::start);
|
|
tokenContainer->DefineLoopToken("{reruns[stop]}", (int)eRerunsLT::stop);
|
|
tokenContainer->DefineLoopToken("{reruns[channelname]}", (int)eRerunsLT::channelname);
|
|
tokenContainer->DefineLoopToken("{reruns[channelnumber]}", (int)eRerunsLT::channelnumber);
|
|
tokenContainer->DefineLoopToken("{reruns[channelid]}", (int)eRerunsLT::channelid);
|
|
tokenContainer->DefineLoopToken("{reruns[channellogoexists]}", (int)eRerunsLT::channellogoexists);
|
|
tokenContainer->DefineLoopToken("{actors[name]}", (int)eScraperLT::name);
|
|
tokenContainer->DefineLoopToken("{actors[role]}", (int)eScraperLT::role);
|
|
tokenContainer->DefineLoopToken("{actors[thumb]}", (int)eScraperLT::thumb);
|
|
tokenContainer->DefineLoopToken("{actors[thumbwidth]}", (int)eScraperLT::thumbwidth);
|
|
tokenContainer->DefineLoopToken("{actors[thumbheight]}", (int)eScraperLT::thumbheight);
|
|
rerunsIndex = tokenContainer->LoopIndex("reruns");
|
|
actorsIndex = tokenContainer->LoopIndex("actors");
|
|
InheritTokenContainer();
|
|
}
|
|
|
|
bool cViewDetailEpg::Parse(bool forced) {
|
|
if (!cViewElement::Parse())
|
|
return false;
|
|
if (!event)
|
|
return false;
|
|
|
|
tokenContainer->Clear();
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::title, event->Title());
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::shorttext, event->ShortText());
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::description, event->Description());
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::start, *(event->GetTimeString()));
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::stop, *(event->GetEndTimeString()));
|
|
time_t startTime = event->StartTime();
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::day, *WeekDayName(startTime));
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::date, *ShortDateString(startTime));
|
|
struct tm * sStartTime = localtime(&startTime);
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::year, sStartTime->tm_year + 1900);
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::daynumeric, sStartTime->tm_mday);
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::month, sStartTime->tm_mon+1);
|
|
const cChannel* channel = NULL;
|
|
#if defined (APIVERSNUM) && (APIVERSNUM >= 20301)
|
|
{
|
|
LOCK_CHANNELS_READ;
|
|
channel = Channels->GetByChannelID(event->ChannelID());
|
|
}
|
|
#else
|
|
channel = Channels.GetByChannelID(event->ChannelID());
|
|
#endif
|
|
if (channel) {
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::channelname, channel->Name());
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::channelnumber, channel->Number());
|
|
}
|
|
cString channelID = event->ChannelID().ToString();
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::channelid, *channelID);
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::channellogoexists, imgCache->LogoExists(*channelID));
|
|
|
|
bool isRunning = false;
|
|
time_t now = time(NULL);
|
|
if ((now >= event->StartTime()) && (now <= event->EndTime()))
|
|
isRunning = true;
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::running, isRunning);
|
|
if (isRunning) {
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::elapsed, (now - event->StartTime())/60);
|
|
} else {
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::elapsed, 0);
|
|
}
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::duration, event->Duration() / 60);
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::durationhours, event->Duration() / 3600);
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::durationminutes, *cString::sprintf("%.2d", (event->Duration() / 60)%60));
|
|
if (event->Vps())
|
|
tokenContainer->AddStringToken((int)eDmDetailedEpgST::vps, *event->GetVpsString());
|
|
|
|
cList<Epgsearch_searchresults_v1_0::cServiceSearchResult> *reruns = LoadReruns();
|
|
int numReruns = 0;
|
|
if (reruns && reruns->Count() > 0)
|
|
numReruns = reruns->Count();
|
|
|
|
vector<int> loopInfo;
|
|
//num reruns
|
|
loopInfo.push_back(numReruns);
|
|
//num actors
|
|
bool scrapInfoAvailable = LoadFullScrapInfo(event, NULL);
|
|
int numActors = NumActors();
|
|
loopInfo.push_back(numActors);
|
|
tokenContainer->CreateLoopTokenContainer(&loopInfo);
|
|
if (numReruns > 0) {
|
|
tokenContainer->AddIntToken((int)eDmDetailedEpgIT::hasreruns, numReruns);
|
|
SetReruns(reruns);
|
|
}
|
|
if (scrapInfoAvailable) {
|
|
SetFullScrapInfo(tokenContainer, actorsIndex);
|
|
}
|
|
SetEpgPictures(event->EventID());
|
|
SetDirty();
|
|
return true;
|
|
}
|
|
|
|
cList<Epgsearch_searchresults_v1_0::cServiceSearchResult> *cViewDetailEpg::LoadReruns(void) {
|
|
cPlugin *epgSearchPlugin = cPluginManager::GetPlugin("epgsearch");
|
|
if (!epgSearchPlugin)
|
|
return NULL;
|
|
|
|
if (!event || isempty(event->Title()))
|
|
return NULL;
|
|
|
|
Epgsearch_searchresults_v1_0 data;
|
|
std::string strQuery = event->Title();
|
|
|
|
if (config.useSubtitleRerun && !isempty(event->ShortText())) {
|
|
strQuery += "~";
|
|
strQuery += event->ShortText();
|
|
}
|
|
|
|
data.query = (char *)strQuery.c_str();
|
|
data.mode = 0;
|
|
data.channelNr = 0;
|
|
data.useTitle = true;
|
|
data.useSubTitle = true;
|
|
data.useDescription = false;
|
|
|
|
int maxNumReruns = config.rerunAmount;
|
|
int rerunDistance = config.rerunDistance * 3600;
|
|
int rerunMaxChannel = config.rerunMaxChannel;
|
|
|
|
int i = 0;
|
|
|
|
cList<Epgsearch_searchresults_v1_0::cServiceSearchResult> *reruns = NULL;
|
|
if (epgSearchPlugin->Service("Epgsearch-searchresults-v1.0", &data)) {
|
|
cList<Epgsearch_searchresults_v1_0::cServiceSearchResult> *result = data.pResultList;
|
|
if (result) {
|
|
for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = result->First(); r && i < maxNumReruns; r = result->Next(r)) {
|
|
time_t eventStart = event->StartTime();
|
|
time_t rerunStart = r->event->StartTime();
|
|
#if defined (APIVERSNUM) && (APIVERSNUM >= 20301)
|
|
LOCK_CHANNELS_READ;
|
|
const cChannel *channel = Channels->GetByChannelID(r->event->ChannelID(), true, true);
|
|
#else
|
|
const cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true);
|
|
#endif
|
|
//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 (rerunMaxChannel > 0)
|
|
if (channel && channel->Number() > rerunMaxChannel)
|
|
continue;
|
|
if (!reruns) reruns = new cList<Epgsearch_searchresults_v1_0::cServiceSearchResult>;
|
|
reruns->Add(r);
|
|
i++;
|
|
}
|
|
}
|
|
}
|
|
return reruns;
|
|
}
|
|
|
|
void cViewDetailEpg::SetReruns(cList<Epgsearch_searchresults_v1_0::cServiceSearchResult> *reruns) {
|
|
if (!reruns || reruns->Count() < 1)
|
|
return;
|
|
|
|
int i = 0;
|
|
for (Epgsearch_searchresults_v1_0::cServiceSearchResult *r = reruns->First(); r; r = reruns->Next(r)) {
|
|
#if defined (APIVERSNUM) && (APIVERSNUM >= 20301)
|
|
LOCK_CHANNELS_READ;
|
|
const cChannel *channel = Channels->GetByChannelID(r->event->ChannelID(), true, true);
|
|
#else
|
|
const cChannel *channel = Channels.GetByChannelID(r->event->ChannelID(), true, true);
|
|
#endif
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::title, r->event->Title());
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::shorttext, r->event->ShortText());
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::start, *(r->event->GetTimeString()));
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::stop, *(r->event->GetEndTimeString()));
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::date, *ShortDateString(r->event->StartTime()));
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::day, *WeekDayName(r->event->StartTime()));
|
|
cString channelID = r->event->ChannelID().ToString();
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelid, *channelID);
|
|
bool logoExists = imgCache->LogoExists(*channelID);
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channellogoexists, logoExists ? "1" : "0");
|
|
if (channel) {
|
|
cString channelNumber = cString::sprintf("%d", channel->Number());
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelname, channel->ShortName(true));
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelnumber, *channelNumber);
|
|
} else {
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelname, "");
|
|
tokenContainer->AddLoopToken(rerunsIndex, i, (int)eRerunsLT::channelnumber, "");
|
|
}
|
|
if (r == reruns->Last())
|
|
break;
|
|
i++;
|
|
}
|
|
}
|
|
|
|
void cViewDetailEpg::SetEpgPictures(int eventId) {
|
|
for (int i=0; i<3; i++) {
|
|
cString epgPic = cString::sprintf("%s%d_%d.jpg", *config.epgImagePath, eventId, i);
|
|
bool epgPicAvailable = FileExists(*epgPic);
|
|
int indexAvailable = (int)eDmDetailedEpgIT::epgpic1available + i;
|
|
int indexPath = (int)eDmDetailedEpgST::epgpic1path + i;
|
|
tokenContainer->AddIntToken(indexAvailable, epgPicAvailable);
|
|
tokenContainer->AddStringToken(indexPath, *epgPic);
|
|
}
|
|
}
|
|
|
|
/******************************************************************
|
|
* cViewDetailRec
|
|
******************************************************************/
|
|
cViewDetailRec::cViewDetailRec(void) {
|
|
recording = NULL;
|
|
actorsIndex = -1;
|
|
}
|
|
|
|
cViewDetailRec::~cViewDetailRec(void) {
|
|
}
|
|
|
|
void cViewDetailRec::SetTokenContainer(void) {
|
|
tokenContainer = new skindesignerapi::cTokenContainer();
|
|
tokenContainer->DefineStringToken("{name}", (int)eDmDetailedRecST::name);
|
|
tokenContainer->DefineStringToken("{epgname}", (int)eDmDetailedRecST::epgname);
|
|
tokenContainer->DefineStringToken("{shorttext}", (int)eDmDetailedRecST::shorttext);
|
|
tokenContainer->DefineStringToken("{description}", (int)eDmDetailedRecST::description);
|
|
tokenContainer->DefineStringToken("{day}", (int)eDmDetailedRecST::day);
|
|
tokenContainer->DefineStringToken("{date}", (int)eDmDetailedRecST::date);
|
|
tokenContainer->DefineStringToken("{time}", (int)eDmDetailedRecST::time);
|
|
tokenContainer->DefineStringToken("{durationminutes}", (int)eDmDetailedRecST::durationminutes);
|
|
tokenContainer->DefineStringToken("{durationeventminutes}", (int)eDmDetailedRecST::durationeventminutes);
|
|
tokenContainer->DefineStringToken("{recchannelname}", (int)eDmDetailedRecST::recchannelname);
|
|
tokenContainer->DefineStringToken("{recchannelid}", (int)eDmDetailedRecST::recchannelid);
|
|
tokenContainer->DefineStringToken("{recordingsize}", (int)eDmDetailedRecST::recordingsize);
|
|
tokenContainer->DefineStringToken("{recordingsizecutted}", (int)eDmDetailedRecST::recordingsizecutted);
|
|
tokenContainer->DefineStringToken("{recordinglength}", (int)eDmDetailedRecST::recordinglength);
|
|
tokenContainer->DefineStringToken("{recordinglengthcutted}", (int)eDmDetailedRecST::recordinglengthcutted);
|
|
tokenContainer->DefineStringToken("{recordingbitrate}", (int)eDmDetailedRecST::recordingbitrate);
|
|
tokenContainer->DefineStringToken("{recordingformat}", (int)eDmDetailedRecST::recordingformat);
|
|
tokenContainer->DefineStringToken("{searchtimer}", (int)eDmDetailedRecST::searchtimer);
|
|
tokenContainer->DefineStringToken("{recimg1path}", (int)eDmDetailedRecST::recimg1path);
|
|
tokenContainer->DefineStringToken("{recimg2path}", (int)eDmDetailedRecST::recimg2path);
|
|
tokenContainer->DefineStringToken("{recimg3path}", (int)eDmDetailedRecST::recimg3path);
|
|
tokenContainer->DefineStringToken("{movietitle}", (int)eScraperST::movietitle);
|
|
tokenContainer->DefineStringToken("{movieoriginalTitle}", (int)eScraperST::movieoriginalTitle);
|
|
tokenContainer->DefineStringToken("{movietagline}", (int)eScraperST::movietagline);
|
|
tokenContainer->DefineStringToken("{movieoverview}", (int)eScraperST::movieoverview);
|
|
tokenContainer->DefineStringToken("{moviegenres}", (int)eScraperST::moviegenres);
|
|
tokenContainer->DefineStringToken("{moviehomepage}", (int)eScraperST::moviehomepage);
|
|
tokenContainer->DefineStringToken("{moviereleasedate}", (int)eScraperST::moviereleasedate);
|
|
tokenContainer->DefineStringToken("{moviepopularity}", (int)eScraperST::moviepopularity);
|
|
tokenContainer->DefineStringToken("{movievoteaverage}", (int)eScraperST::movievoteaverage);
|
|
tokenContainer->DefineStringToken("{posterpath}", (int)eScraperST::posterpath);
|
|
tokenContainer->DefineStringToken("{fanartpath}", (int)eScraperST::fanartpath);
|
|
tokenContainer->DefineStringToken("{moviecollectionName}", (int)eScraperST::moviecollectionName);
|
|
tokenContainer->DefineStringToken("{collectionposterpath}", (int)eScraperST::collectionposterpath);
|
|
tokenContainer->DefineStringToken("{collectionfanartpath}", (int)eScraperST::collectionfanartpath);
|
|
tokenContainer->DefineStringToken("{seriesname}", (int)eScraperST::seriesname);
|
|
tokenContainer->DefineStringToken("{seriesoverview}", (int)eScraperST::seriesoverview);
|
|
tokenContainer->DefineStringToken("{seriesfirstaired}", (int)eScraperST::seriesfirstaired);
|
|
tokenContainer->DefineStringToken("{seriesnetwork}", (int)eScraperST::seriesnetwork);
|
|
tokenContainer->DefineStringToken("{seriesgenre}", (int)eScraperST::seriesgenre);
|
|
tokenContainer->DefineStringToken("{seriesrating}", (int)eScraperST::seriesrating);
|
|
tokenContainer->DefineStringToken("{seriesstatus}", (int)eScraperST::seriesstatus);
|
|
tokenContainer->DefineStringToken("{episodetitle}", (int)eScraperST::episodetitle);
|
|
tokenContainer->DefineStringToken("{episodefirstaired}", (int)eScraperST::episodefirstaired);
|
|
tokenContainer->DefineStringToken("{episodegueststars}", (int)eScraperST::episodegueststars);
|
|
tokenContainer->DefineStringToken("{episodeoverview}", (int)eScraperST::episodeoverview);
|
|
tokenContainer->DefineStringToken("{episoderating}", (int)eScraperST::episoderating);
|
|
tokenContainer->DefineStringToken("{episodeimagepath}", (int)eScraperST::episodeimagepath);
|
|
tokenContainer->DefineStringToken("{seasonposterpath}", (int)eScraperST::seasonposterpath);
|
|
tokenContainer->DefineStringToken("{seriesposter1path}", (int)eScraperST::seriesposter1path);
|
|
tokenContainer->DefineStringToken("{seriesposter2path}", (int)eScraperST::seriesposter2path);
|
|
tokenContainer->DefineStringToken("{seriesposter3path}", (int)eScraperST::seriesposter3path);
|
|
tokenContainer->DefineStringToken("{seriesfanart1path}", (int)eScraperST::seriesfanart1path);
|
|
tokenContainer->DefineStringToken("{seriesfanart2path}", (int)eScraperST::seriesfanart2path);
|
|
tokenContainer->DefineStringToken("{seriesfanart3path}", (int)eScraperST::seriesfanart3path);
|
|
tokenContainer->DefineStringToken("{seriesbanner1path}", (int)eScraperST::seriesbanner1path);
|
|
tokenContainer->DefineStringToken("{seriesbanner2path}", (int)eScraperST::seriesbanner2path);
|
|
tokenContainer->DefineStringToken("{seriesbanner3path}", (int)eScraperST::seriesbanner3path);
|
|
tokenContainer->DefineIntToken("{daynumeric}", (int)eDmDetailedRecIT::daynumeric);
|
|
tokenContainer->DefineIntToken("{month}", (int)eDmDetailedRecIT::month);
|
|
tokenContainer->DefineIntToken("{year}", (int)eDmDetailedRecIT::year);
|
|
tokenContainer->DefineIntToken("{duration}", (int)eDmDetailedRecIT::duration);
|
|
tokenContainer->DefineIntToken("{durationhours}", (int)eDmDetailedRecIT::durationhours);
|
|
tokenContainer->DefineIntToken("{durationevent}", (int)eDmDetailedRecIT::durationevent);
|
|
tokenContainer->DefineIntToken("{durationeventhours}", (int)eDmDetailedRecIT::durationeventhours);
|
|
tokenContainer->DefineIntToken("{recchannelnumber}", (int)eDmDetailedRecIT::recchannelnumber);
|
|
tokenContainer->DefineIntToken("{cutted}", (int)eDmDetailedRecIT::cutted);
|
|
tokenContainer->DefineIntToken("{recimg1avaialble}", (int)eDmDetailedRecIT::recimg1avaialble);
|
|
tokenContainer->DefineIntToken("{recimg2avaialble}", (int)eDmDetailedRecIT::recimg2avaialble);
|
|
tokenContainer->DefineIntToken("{recimg3avaialble}", (int)eDmDetailedRecIT::recimg3avaialble);
|
|
tokenContainer->DefineIntToken("{fps}", (int)eDmDetailedRecIT::framesPerSecond);
|
|
tokenContainer->DefineIntToken("{isHD}", (int)eDmDetailedRecIT::isHD);
|
|
tokenContainer->DefineIntToken("{isUHD}", (int)eDmDetailedRecIT::isUHD);
|
|
tokenContainer->DefineIntToken("{isRadio}", (int)eDmDetailedRecIT::isRadio);
|
|
tokenContainer->DefineIntToken("{isRecording}", (int)eDmDetailedRecIT::isRecording);
|
|
tokenContainer->DefineIntToken("{isInUse}", (int)eDmDetailedRecIT::isInUse);
|
|
tokenContainer->DefineIntToken("{errors}", (int)eDmDetailedRecIT::errors);
|
|
tokenContainer->DefineIntToken("{ismovie}", (int)eScraperIT::ismovie);
|
|
tokenContainer->DefineIntToken("{moviebudget}", (int)eScraperIT::moviebudget);
|
|
tokenContainer->DefineIntToken("{movierevenue}", (int)eScraperIT::movierevenue);
|
|
tokenContainer->DefineIntToken("{movieadult}", (int)eScraperIT::movieadult);
|
|
tokenContainer->DefineIntToken("{movieruntime}", (int)eScraperIT::movieruntime);
|
|
tokenContainer->DefineIntToken("{isseries}", (int)eScraperIT::isseries);
|
|
tokenContainer->DefineIntToken("{posterwidth}", (int)eScraperIT::posterwidth);
|
|
tokenContainer->DefineIntToken("{posterheight}", (int)eScraperIT::posterheight);
|
|
tokenContainer->DefineIntToken("{fanartwidth}", (int)eScraperIT::fanartwidth);
|
|
tokenContainer->DefineIntToken("{fanartheight}", (int)eScraperIT::fanartheight);
|
|
tokenContainer->DefineIntToken("{movieiscollection}", (int)eScraperIT::movieiscollection);
|
|
tokenContainer->DefineIntToken("{collectionposterwidth}", (int)eScraperIT::collectionposterwidth);
|
|
tokenContainer->DefineIntToken("{collectionposterheight}", (int)eScraperIT::collectionposterheight);
|
|
tokenContainer->DefineIntToken("{collectionfanartwidth}", (int)eScraperIT::collectionfanartwidth);
|
|
tokenContainer->DefineIntToken("{collectionfanartheight}", (int)eScraperIT::collectionfanartheight);
|
|
tokenContainer->DefineIntToken("{epgpicavailable}", (int)eScraperIT::epgpicavailable);
|
|
tokenContainer->DefineIntToken("{episodenumber}", (int)eScraperIT::episodenumber);
|
|
tokenContainer->DefineIntToken("{episodeseason}", (int)eScraperIT::episodeseason);
|
|
tokenContainer->DefineIntToken("{episodeimagewidth}", (int)eScraperIT::episodeimagewidth);
|
|
tokenContainer->DefineIntToken("{episodeimageheight}", (int)eScraperIT::episodeimageheight);
|
|
tokenContainer->DefineIntToken("{seasonposterwidth}", (int)eScraperIT::seasonposterwidth);
|
|
tokenContainer->DefineIntToken("{seasonposterheight}", (int)eScraperIT::seasonposterheight);
|
|
tokenContainer->DefineIntToken("{seriesposter1width}", (int)eScraperIT::seriesposter1width);
|
|
tokenContainer->DefineIntToken("{seriesposter1height}", (int)eScraperIT::seriesposter1height);
|
|
tokenContainer->DefineIntToken("{seriesposter2width}", (int)eScraperIT::seriesposter2width);
|
|
tokenContainer->DefineIntToken("{seriesposter2height}", (int)eScraperIT::seriesposter2height);
|
|
tokenContainer->DefineIntToken("{seriesposter3width}", (int)eScraperIT::seriesposter3width);
|
|
tokenContainer->DefineIntToken("{seriesposter3height}", (int)eScraperIT::seriesposter3height);
|
|
tokenContainer->DefineIntToken("{seriesfanart1width}", (int)eScraperIT::seriesfanart1width);
|
|
tokenContainer->DefineIntToken("{seriesfanart1height}", (int)eScraperIT::seriesfanart1height);
|
|
tokenContainer->DefineIntToken("{seriesfanart2width}", (int)eScraperIT::seriesfanart2width);
|
|
tokenContainer->DefineIntToken("{seriesfanart2height}", (int)eScraperIT::seriesfanart2height);
|
|
tokenContainer->DefineIntToken("{seriesfanart3width}", (int)eScraperIT::seriesfanart3width);
|
|
tokenContainer->DefineIntToken("{seriesfanart3height}", (int)eScraperIT::seriesfanart3height);
|
|
tokenContainer->DefineIntToken("{seriesbanner1width}", (int)eScraperIT::seriesbanner1width);
|
|
tokenContainer->DefineIntToken("{seriesbanner1height}", (int)eScraperIT::seriesbanner1height);
|
|
tokenContainer->DefineIntToken("{seriesbanner2width}", (int)eScraperIT::seriesbanner2width);
|
|
tokenContainer->DefineIntToken("{seriesbanner2height}", (int)eScraperIT::seriesbanner2height);
|
|
tokenContainer->DefineIntToken("{seriesbanner3width}", (int)eScraperIT::seriesbanner3width);
|
|
tokenContainer->DefineIntToken("{seriesbanner3height}", (int)eScraperIT::seriesbanner3height);
|
|
tokenContainer->DefineLoopToken("{actors[name]}", (int)eScraperLT::name);
|
|
tokenContainer->DefineLoopToken("{actors[role]}", (int)eScraperLT::role);
|
|
tokenContainer->DefineLoopToken("{actors[thumb]}", (int)eScraperLT::thumb);
|
|
tokenContainer->DefineLoopToken("{actors[thumbwidth]}", (int)eScraperLT::thumbwidth);
|
|
tokenContainer->DefineLoopToken("{actors[thumbheight]}", (int)eScraperLT::thumbheight);
|
|
actorsIndex = tokenContainer->LoopIndex("actors");
|
|
InheritTokenContainer();
|
|
}
|
|
|
|
bool cViewDetailRec::Parse(bool forced) {
|
|
if (!cViewElement::Parse())
|
|
return false;
|
|
if (!recording)
|
|
return false;
|
|
tokenContainer->Clear();
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::name, recording->Name());
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::cutted, recording->IsEdited());
|
|
|
|
const cRecordingInfo *info = recording->Info();
|
|
if (info) {
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::epgname, info->Title());
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::shorttext, info->ShortText());
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::description, info->Description());
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::framesPerSecond, info->FramesPerSecond());
|
|
int errors = -1;
|
|
// ENABLE_ERRORS is only used in VDR-2.5.4 if the coresponding patch is installed, so it can be ignored in other versions
|
|
#if (defined (APIVERSNUM) && (APIVERSNUM >= 20505)) || defined (ENABLE_ERRORS)
|
|
errors = info->Errors();
|
|
#endif
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::errors, errors);
|
|
const cEvent *event = info->GetEvent();
|
|
if (event) {
|
|
cString recDate = event->GetDateString();
|
|
cString recTime = event->GetTimeString();
|
|
if (strstr(*recDate, "1970")) {
|
|
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;
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::date, *recDate);
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::time, *recTime);
|
|
time_t startTime = event->StartTime();
|
|
struct tm * sStartTime = localtime(&startTime);
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::year, sStartTime->tm_year + 1900);
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::daynumeric, sStartTime->tm_mday);
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::month, sStartTime->tm_mon+1);
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::duration, recDuration);
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::durationhours, recDuration / 60);
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::durationminutes, *cString::sprintf("%.2d", recDuration%60));
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::durationevent, duration);
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::durationeventhours, duration / 60);
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::durationeventminutes, *cString::sprintf("%.2d", duration%60));
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::isHD, RecordingIsHD(event)); // detect HD from 'info'
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::isUHD, RecordingIsUHD(event)); // detect UHD from 'info'
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::isRadio, RecordingIsRadio(event, info->FramesPerSecond())); // detect Radio from 'info' and FPS
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::isRecording, recording->IsInUse() & ruTimer);
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::isInUse, recording->IsInUse());
|
|
}
|
|
}
|
|
SetRecInfos();
|
|
SetRecordingImages(recording->FileName());
|
|
|
|
vector<int> loopInfo;
|
|
bool scrapInfoAvailable = LoadFullScrapInfo(NULL, recording);
|
|
int numActors = NumActors();
|
|
loopInfo.push_back(numActors);
|
|
tokenContainer->CreateLoopTokenContainer(&loopInfo);
|
|
if (scrapInfoAvailable) {
|
|
SetFullScrapInfo(tokenContainer, actorsIndex);
|
|
}
|
|
|
|
SetDirty();
|
|
return true;
|
|
}
|
|
|
|
void cViewDetailRec::SetRecInfos(void) {
|
|
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;
|
|
}
|
|
}
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recordingsize, *strRecSize);
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recordingsizecutted, *strRecSizeCut);
|
|
}
|
|
|
|
const cRecordingInfo *info = recording->Info();
|
|
if (info) {
|
|
if (info->ChannelName() && (strlen(info->ChannelName()) > 0)) {
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelname, info->ChannelName());
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelid, info->ChannelID().ToString());
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::recchannelnumber, 0); // cannot be provided, for backward compatibility only
|
|
} else {
|
|
#if defined (APIVERSNUM) && (APIVERSNUM >= 20301)
|
|
LOCK_CHANNELS_READ;
|
|
const cChannel *channel = Channels->GetByChannelID(info->ChannelID());
|
|
#else
|
|
const cChannel *channel = Channels.GetByChannelID(info->ChannelID());
|
|
#endif
|
|
if (channel) {
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelname, channel->Name());
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recchannelid, *channel->GetChannelID().ToString());
|
|
tokenContainer->AddIntToken((int)eDmDetailedRecIT::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));
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recordinglength, strLength.c_str());
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recordinglengthcutted, strLengthCutted.c_str());
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recordingbitrate, strBitrate.c_str());
|
|
}
|
|
delete index;
|
|
}
|
|
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::recordingformat, recording->IsPesRecording() ? "PES" : "TS");
|
|
|
|
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()) {
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::searchtimer, searchTimer.c_str());
|
|
searchTimerFound = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!searchTimerFound)
|
|
tokenContainer->AddStringToken((int)eDmDetailedRecST::searchtimer, "n.a.");
|
|
}
|
|
|
|
int cViewDetailRec::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;
|
|
}
|
|
|
|
string cViewDetailRec::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);
|
|
}
|
|
|
|
void cViewDetailRec::SetRecordingImages(const char *recPath) {
|
|
if (!recPath) {
|
|
return;
|
|
}
|
|
DIR *dirHandle;
|
|
struct dirent *dirEntry;
|
|
dirHandle = opendir(recPath);
|
|
if (!dirHandle) {
|
|
return;
|
|
}
|
|
int picsFound = 0;
|
|
int indexStr = (int)eDmDetailedRecST::recimg1path;
|
|
int indexInt = (int)eDmDetailedRecIT::recimg1avaialble;
|
|
while ( 0 != (dirEntry = readdir(dirHandle))) {
|
|
if (endswith(dirEntry->d_name, "jpg")) {
|
|
tokenContainer->AddStringToken(indexStr, *cString::sprintf("%s/%s", recPath, dirEntry->d_name));
|
|
tokenContainer->AddIntToken(indexInt, 1);
|
|
picsFound++;
|
|
}
|
|
if (picsFound == 3) {
|
|
break;
|
|
}
|
|
}
|
|
closedir(dirHandle);
|
|
}
|
|
|
|
/******************************************************************
|
|
* cViewDetailText
|
|
******************************************************************/
|
|
cViewDetailText::cViewDetailText(void) {
|
|
text = NULL;
|
|
}
|
|
|
|
cViewDetailText::~cViewDetailText(void) {
|
|
}
|
|
|
|
void cViewDetailText::SetTokenContainer(void) {
|
|
tokenContainer = new skindesignerapi::cTokenContainer();
|
|
tokenContainer->DefineStringToken("{text}", (int)eDmDetailedTextST::text);
|
|
InheritTokenContainer();
|
|
}
|
|
|
|
bool cViewDetailText::Parse(bool forced) {
|
|
if (!cViewElement::Parse())
|
|
return false;
|
|
if (!text)
|
|
return false;
|
|
tokenContainer->Clear();
|
|
tokenContainer->AddStringToken((int)eDmDetailedTextST::text, text);
|
|
SetDirty();
|
|
return true;
|
|
}
|
|
|
|
/******************************************************************
|
|
* cViewDetailPlugin
|
|
******************************************************************/
|
|
cViewDetailPlugin::cViewDetailPlugin(void) {
|
|
}
|
|
|
|
cViewDetailPlugin::~cViewDetailPlugin(void) {
|
|
}
|
|
|
|
void cViewDetailPlugin::SetTokenContainer(void) {
|
|
if (plugId == -1 || plugMenuId == -1)
|
|
return;
|
|
skindesignerapi::cTokenContainer *tkPlugMenu = plgManager->GetTokenContainer(plugId, plugMenuId);
|
|
tokenContainer = new skindesignerapi::cTokenContainer(*tkPlugMenu);
|
|
InheritTokenContainer();
|
|
}
|
|
|
|
void cViewDetailPlugin::Set(skindesignerapi::cTokenContainer *tk) {
|
|
tokenContainer->Clear();
|
|
tokenContainer->SetTokens(tk);
|
|
}
|
|
|
|
bool cViewDetailPlugin::Parse(bool forced) {
|
|
if (!cViewElement::Parse())
|
|
return false;
|
|
SetDirty();
|
|
return true;
|
|
}
|
|
|
|
/******************************************************************
|
|
* cViewDetailAdvancedPlugin
|
|
******************************************************************/
|
|
cViewDetailAdvancedPlugin::cViewDetailAdvancedPlugin(int viewId, int plugId) {
|
|
this->plugId = plugId;
|
|
plugViewId = viewId;
|
|
}
|
|
|
|
cViewDetailAdvancedPlugin::~cViewDetailAdvancedPlugin(void) {
|
|
}
|
|
|
|
void cViewDetailAdvancedPlugin::SetTokenContainer(void) {
|
|
if (plugId == -1 || plugViewId == -1)
|
|
return;
|
|
skindesignerapi::cTokenContainer *tkDetail = plgManager->GetTokenContainerTab(plugId, plugViewId);
|
|
tokenContainer = new skindesignerapi::cTokenContainer(*tkDetail);
|
|
InheritTokenContainer();
|
|
}
|
|
|
|
void cViewDetailAdvancedPlugin::Set(skindesignerapi::cTokenContainer *tk) {
|
|
tokenContainer->Clear();
|
|
tokenContainer->SetTokens(tk);
|
|
}
|
|
|
|
bool cViewDetailAdvancedPlugin::Parse(bool forced) {
|
|
if (!cViewElement::Parse())
|
|
return false;
|
|
SetDirty();
|
|
return true;
|
|
}
|