summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlouis <louis.braun@gmx.de>2016-05-26 10:47:45 +0200
committerlouis <louis.braun@gmx.de>2016-05-26 10:47:45 +0200
commita57c44b06874ba146ca27a5c87868c1e3c304875 (patch)
tree844945c2f05d05ae80eb6fb1126db267253a1deb
parentffb414cdee209097f19f925c46de9f105cf5358e (diff)
downloadvdr-plugin-skindesigner-a57c44b06874ba146ca27a5c87868c1e3c304875.tar.gz
vdr-plugin-skindesigner-a57c44b06874ba146ca27a5c87868c1e3c304875.tar.bz2
introduced zapcockpit extension
-rw-r--r--coreengine/area.c12
-rw-r--r--coreengine/attributes.c23
-rw-r--r--coreengine/attributes.h7
-rw-r--r--coreengine/definitions.h279
-rw-r--r--coreengine/listelements.c127
-rw-r--r--coreengine/listelements.h31
-rw-r--r--coreengine/view.c44
-rw-r--r--coreengine/view.h6
-rw-r--r--coreengine/viewdisplaychannel.c447
-rw-r--r--coreengine/viewdisplaychannel.h62
-rw-r--r--coreengine/viewelement.c22
-rw-r--r--coreengine/viewelement.h9
-rw-r--r--coreengine/viewelementsdisplaychannel.c258
-rw-r--r--coreengine/viewelementsdisplaychannel.h49
-rw-r--r--coreengine/viewelementsdisplaymenu.c8
-rw-r--r--coreengine/viewlist.c221
-rw-r--r--coreengine/viewlist.h44
-rw-r--r--coreengine/xmlparser.c36
-rw-r--r--coreengine/xmlparser.h2
-rw-r--r--displaychannel.c57
-rw-r--r--displaychannel.h15
-rw-r--r--dtd/displaychannel.dtd158
-rw-r--r--extensions/globaltimers.c2
-rw-r--r--patches/vdr-2.2.0_zapcockpit.patch1015
-rw-r--r--skindesigner.c5
-rw-r--r--skins/estuary4vdr/setup.xml140
-rw-r--r--skins/estuary4vdr/svgtemplates/icons/folder.svg65
-rw-r--r--skins/estuary4vdr/svgtemplates/icons/folder_active.svg65
-rw-r--r--skins/estuary4vdr/themes/default/theme.xml1
-rw-r--r--skins/estuary4vdr/xmlfiles/displaychannel.xml176
-rw-r--r--skinskeleton/xmlfiles/displaychannel.xml189
31 files changed, 3410 insertions, 165 deletions
diff --git a/coreengine/area.c b/coreengine/area.c
index a2a9641..6e4beb1 100644
--- a/coreengine/area.c
+++ b/coreengine/area.c
@@ -425,8 +425,14 @@ void cArea::SetViewPort(cRect &vp) {
void cArea::SetPosition(cPoint &pos, cPoint &ref) {
if (!pix)
return;
- int x = (attribs->X() - ref.X()) + pos.X();
- int y = (attribs->Y() - ref.Y()) + pos.Y();
+ int x0 = attribs->X() == -1 ? 0 : attribs->X();
+ int y0 = attribs->Y() == -1 ? 0 : attribs->Y();
+ int x = (x0 - ref.X()) + pos.X();
+ int y = (y0 - ref.Y()) + pos.Y();
+/* Enable for xineliboutput OSD Bug
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+*/
pix->SetViewPort(cRect(x, y, pix->ViewPort().Width(), pix->ViewPort().Height()));
}
@@ -518,7 +524,7 @@ void cArea::CreatePixmap(cRect drawPort) {
}
int layer = attribs->Layer();
- cRect viewPort(attribs->X(), attribs->Y(), attribs->Width(), attribs->Height());
+ cRect viewPort(attribs->X() == -1 ? 0 : attribs->X(), attribs->Y() == -1 ? 0 : attribs->Y(), attribs->Width(), attribs->Height());
pix = sdOsd->CreatePixmap(layer, viewPort, drawPort);
if (pix)
pix->Clear();
diff --git a/coreengine/attributes.c b/coreengine/attributes.c
index 8e71c1a..4840dbc 100644
--- a/coreengine/attributes.c
+++ b/coreengine/attributes.c
@@ -126,15 +126,18 @@ void cViewAttribs::SetOrientationDynamic(int id, const char *val) {
***************************************************************************/
cViewElementAttribs::cViewElementAttribs(int numAttributes) : cAttributes(numAttributes) {
name = NULL;
+ clearOnDisplay = NULL;
SetAttributesDefs();
}
cViewElementAttribs::cViewElementAttribs(const cViewElementAttribs &other) : cAttributes(other) {
name = NULL;
+ clearOnDisplay = NULL;
}
cViewElementAttribs::~cViewElementAttribs(void) {
free(name);
+ free(clearOnDisplay);
}
void cViewElementAttribs::Set(vector<stringpair> &attributes) {
@@ -158,6 +161,8 @@ void cViewElementAttribs::Set(vector<stringpair> &attributes) {
SetOrientation(id, attVal);
} else if (IdEqual(id, (int)eViewElementAttribs::name)) {
name = strdup(attVal);
+ } else if (IdEqual(id, (int)eViewElementAttribs::clearondisplay)) {
+ clearOnDisplay = strdup(attVal);
} else {
attribCtors[id] = new cNumericExpr(attVal);
if (id == (int)eViewElementAttribs::starty + (int)eCommonAttribs::count) {
@@ -178,6 +183,7 @@ void cViewElementAttribs::SetAttributesDefs(void) {
attribIDs.insert(pair<string, int>("orientation", (int)eViewElementAttribs::orientation));
attribIDs.insert(pair<string, int>("mode", (int)eViewElementAttribs::mode));
attribIDs.insert(pair<string, int>("name", (int)eViewElementAttribs::name));
+ attribIDs.insert(pair<string, int>("clearondisplay", (int)eViewElementAttribs::clearondisplay));
attribNames.insert(pair<int, string>((int)eViewElementAttribs::delay, "delay"));
attribNames.insert(pair<int, string>((int)eViewElementAttribs::fadetime, "fadetime"));
attribNames.insert(pair<int, string>((int)eViewElementAttribs::shifttime, "shifttime"));
@@ -188,6 +194,7 @@ void cViewElementAttribs::SetAttributesDefs(void) {
attribNames.insert(pair<int, string>((int)eViewElementAttribs::orientation, "orientation"));
attribNames.insert(pair<int, string>((int)eViewElementAttribs::mode, "mode"));
attribNames.insert(pair<int, string>((int)eViewElementAttribs::name, "name"));
+ attribNames.insert(pair<int, string>((int)eViewElementAttribs::clearondisplay, "clearondisplay"));
}
eOrientation cViewElementAttribs::Orientation(void) {
@@ -233,6 +240,10 @@ void cViewListAttribs::Set(vector<stringpair> &attributes) {
determinateFont = strdup(attVal);
} else if (IdEqual(id, (int)eViewListAttribs::orientation)) {
SetOrientation(id, attVal);
+ } else if (IdEqual(id, (int)eViewListAttribs::shifttype)) {
+ SetShiftType(id, attVal);
+ } else if (IdEqual(id, (int)eViewListAttribs::shiftmode)) {
+ SetShiftMode(id, attVal);
} else {
attribCtors[id] = new cNumericExpr(attVal);
}
@@ -271,12 +282,24 @@ void cViewListAttribs::SetAttributesDefs(void) {
attribIDs.insert(pair<string, int>("determinatefont", (int)eViewListAttribs::determinatefont));
attribIDs.insert(pair<string, int>("numlistelements", (int)eViewListAttribs::numlistelements));
attribIDs.insert(pair<string, int>("orientation", (int)eViewListAttribs::orientation));
+ attribIDs.insert(pair<string, int>("fadetime", (int)eViewListAttribs::fadetime));
+ attribIDs.insert(pair<string, int>("shifttime", (int)eViewListAttribs::shifttime));
+ attribIDs.insert(pair<string, int>("shifttype", (int)eViewListAttribs::shifttype));
+ attribIDs.insert(pair<string, int>("shiftmode", (int)eViewListAttribs::shiftmode));
+ attribIDs.insert(pair<string, int>("startx", (int)eViewListAttribs::startx));
+ attribIDs.insert(pair<string, int>("starty", (int)eViewListAttribs::starty));
attribIDs.insert(pair<string, int>("condition", (int)eViewListAttribs::condition));
attribNames.insert(pair<int, string>((int)eViewListAttribs::align, "align"));
attribNames.insert(pair<int, string>((int)eViewListAttribs::menuitemwidth, "menuitemwidth"));
attribNames.insert(pair<int, string>((int)eViewListAttribs::determinatefont, "determinatefont"));
attribNames.insert(pair<int, string>((int)eViewListAttribs::numlistelements, "numlistelements"));
attribNames.insert(pair<int, string>((int)eViewListAttribs::orientation, "orientation"));
+ attribNames.insert(pair<int, string>((int)eViewListAttribs::fadetime, "fadetime"));
+ attribNames.insert(pair<int, string>((int)eViewListAttribs::shifttime, "shifttime"));
+ attribNames.insert(pair<int, string>((int)eViewListAttribs::shifttype, "shifttype"));
+ attribNames.insert(pair<int, string>((int)eViewListAttribs::shiftmode, "shiftmode"));
+ attribNames.insert(pair<int, string>((int)eViewListAttribs::startx, "startx"));
+ attribNames.insert(pair<int, string>((int)eViewListAttribs::starty, "starty"));
attribNames.insert(pair<int, string>((int)eViewListAttribs::condition, "condition"));
}
diff --git a/coreengine/attributes.h b/coreengine/attributes.h
index 1af17ef..228964d 100644
--- a/coreengine/attributes.h
+++ b/coreengine/attributes.h
@@ -30,6 +30,7 @@ public:
class cViewElementAttribs : public cAttributes {
private:
char *name;
+ char *clearOnDisplay;
void SetAttributesDefs(void);
public:
cViewElementAttribs(int numAttributes);
@@ -45,6 +46,7 @@ public:
int ShiftType(void) { return GetValue((int)eViewElementAttribs::shifttype); };
int ShiftMode(void) { return GetValue((int)eViewElementAttribs::shiftmode); };
const char *Name(void) { return name; };
+ const char *ClearOnDisplay(void) { return clearOnDisplay; };
void Debug(void);
};
/******************************************************************
@@ -63,6 +65,11 @@ public:
const char *DeterminateFont(void);
eAlign Align(void);
eOrientation Orientation(void);
+ int FadeTime(void) { return GetValue((int)eViewListAttribs::fadetime); };
+ int ShiftTime(void) { return GetValue((int)eViewListAttribs::shifttime); };
+ cPoint ShiftStartpoint(void) { return cPoint(GetValue((int)eViewListAttribs::startx), GetValue((int)eViewListAttribs::starty)); };
+ int ShiftType(void) { return GetValue((int)eViewListAttribs::shifttype); };
+ int ShiftMode(void) { return GetValue((int)eViewListAttribs::shiftmode); };
void Debug(void);
};
/******************************************************************
diff --git a/coreengine/definitions.h b/coreengine/definitions.h
index ccb9acb..51f298d 100644
--- a/coreengine/definitions.h
+++ b/coreengine/definitions.h
@@ -45,6 +45,13 @@ enum class eVeDisplayChannel {
signalquality,
scrapercontent,
ecminfo,
+ channelhints,
+ channeldetail,
+ channellistback,
+ channellistdetail,
+ grouplistback,
+ groupchannellistback,
+ groupchannellistdetail,
count
};
/******************************************************************
@@ -276,6 +283,101 @@ enum class eScraperPosterBannerIT {
count
};
+enum class eScraperST {
+ movietitle = 0,
+ movieoriginalTitle,
+ movietagline,
+ movieoverview,
+ moviegenres,
+ moviehomepage,
+ moviereleasedate,
+ moviepopularity,
+ movievoteaverage,
+ posterpath,
+ fanartpath,
+ moviecollectionName,
+ collectionposterpath,
+ collectionfanartpath,
+ seriesname,
+ seriesoverview,
+ seriesfirstaired,
+ seriesnetwork,
+ seriesgenre,
+ seriesrating,
+ seriesstatus,
+ episodetitle,
+ episodefirstaired,
+ episodegueststars,
+ episodeoverview,
+ episoderating,
+ episodeimagepath,
+ seasonposterpath,
+ seriesposter1path,
+ seriesposter2path,
+ seriesposter3path,
+ seriesfanart1path,
+ seriesfanart2path,
+ seriesfanart3path,
+ seriesbanner1path,
+ seriesbanner2path,
+ seriesbanner3path,
+ count
+};
+
+enum class eScraperIT {
+ ismovie = 0,
+ moviebudget,
+ movierevenue,
+ movieadult,
+ movieruntime,
+ isseries,
+ posterwidth,
+ posterheight,
+ fanartwidth,
+ fanartheight,
+ movieiscollection,
+ collectionposterwidth,
+ collectionposterheight,
+ collectionfanartwidth,
+ collectionfanartheight,
+ epgpicavailable,
+ episodenumber,
+ episodeseason,
+ episodeimagewidth,
+ episodeimageheight,
+ seasonposterwidth,
+ seasonposterheight,
+ seriesposter1width,
+ seriesposter1height,
+ seriesposter2width,
+ seriesposter2height,
+ seriesposter3width,
+ seriesposter3height,
+ seriesfanart1width,
+ seriesfanart1height,
+ seriesfanart2width,
+ seriesfanart2height,
+ seriesfanart3width,
+ seriesfanart3height,
+ seriesbanner1width,
+ seriesbanner1height,
+ seriesbanner2width,
+ seriesbanner2height,
+ seriesbanner3width,
+ seriesbanner3height,
+ count
+};
+
+enum class eScraperLT {
+ //actors
+ name = 0,
+ role,
+ thumb,
+ thumbwidth,
+ thumbheight,
+ count
+};
+
/******************************************************************
* Tokens displaychannel viewelements
*******************************************************************/
@@ -417,6 +519,46 @@ enum class eDCSignalQualityIT {
count
};
+enum class eDCChannelHintsIT {
+ numhints = 0,
+ count
+};
+
+enum class eDCChannelHintsLT {
+ channelnumber = 0,
+ channelname,
+ channelid,
+ channellogoexists,
+ count
+};
+
+enum class eDCChannelDetailST {
+ channelname = (int)eScraperST::count,
+ currenttitle,
+ currentshorttext,
+ currentdescription,
+ currentstart,
+ currentstop,
+ currentdurationminutes,
+ nexttitle,
+ nextshorttext,
+ nextdescription,
+ nextstart,
+ nextstop,
+ nextdurationminutes,
+ count
+};
+
+enum class eDCChannelDetailIT {
+ channelnumber = (int)eScraperIT::count,
+ currentduration,
+ currentdurationhours,
+ currentelapsed,
+ currentremaining,
+ nextduration,
+ nextdurationhours,
+ count
+};
/******************************************************************
* Tokens displaymenu viewelements
*******************************************************************/
@@ -601,7 +743,7 @@ enum class eDMTemperaturesIT {
};
/******************************************************************
-* Tokens displaymenu listelements
+* Tokens listelements
*******************************************************************/
enum class eLeMenuDefaultST {
column1 = 0,
@@ -1057,6 +1199,39 @@ enum class eCeMenuRecordingsIT {
count
};
+enum class eLeChannelListST {
+ name = 0,
+ channelid,
+ presenteventtitle,
+ presenteventstart,
+ presenteventstop,
+ nexteventtitle,
+ nexteventstart,
+ nexteventstop,
+ count
+};
+
+enum class eLeChannelListIT {
+ nummenuitem = 0,
+ current,
+ number,
+ channellogoexists,
+ presenteventelapsed,
+ presenteventremaining,
+ count
+};
+
+enum class eLeGroupListST {
+ groupname = 0,
+ count
+};
+
+enum class eLeGroupListIT {
+ nummenuitem = 0,
+ current,
+ numchannels,
+ count
+};
/******************************************************************
* Tokens displaymenu detailed views
*******************************************************************/
@@ -1151,101 +1326,6 @@ enum class eDmTabsLT {
count
};
-enum class eScraperST {
- movietitle = 0,
- movieoriginalTitle,
- movietagline,
- movieoverview,
- moviegenres,
- moviehomepage,
- moviereleasedate,
- moviepopularity,
- movievoteaverage,
- posterpath,
- fanartpath,
- moviecollectionName,
- collectionposterpath,
- collectionfanartpath,
- seriesname,
- seriesoverview,
- seriesfirstaired,
- seriesnetwork,
- seriesgenre,
- seriesrating,
- seriesstatus,
- episodetitle,
- episodefirstaired,
- episodegueststars,
- episodeoverview,
- episoderating,
- episodeimagepath,
- seasonposterpath,
- seriesposter1path,
- seriesposter2path,
- seriesposter3path,
- seriesfanart1path,
- seriesfanart2path,
- seriesfanart3path,
- seriesbanner1path,
- seriesbanner2path,
- seriesbanner3path,
- count
-};
-
-enum class eScraperIT {
- ismovie = 0,
- moviebudget,
- movierevenue,
- movieadult,
- movieruntime,
- isseries,
- posterwidth,
- posterheight,
- fanartwidth,
- fanartheight,
- movieiscollection,
- collectionposterwidth,
- collectionposterheight,
- collectionfanartwidth,
- collectionfanartheight,
- epgpicavailable,
- episodenumber,
- episodeseason,
- episodeimagewidth,
- episodeimageheight,
- seasonposterwidth,
- seasonposterheight,
- seriesposter1width,
- seriesposter1height,
- seriesposter2width,
- seriesposter2height,
- seriesposter3width,
- seriesposter3height,
- seriesfanart1width,
- seriesfanart1height,
- seriesfanart2width,
- seriesfanart2height,
- seriesfanart3width,
- seriesfanart3height,
- seriesbanner1width,
- seriesbanner1height,
- seriesbanner2width,
- seriesbanner2height,
- seriesbanner3width,
- seriesbanner3height,
- count
-};
-
-enum class eScraperLT {
- //actors
- name = 0,
- role,
- thumb,
- thumbwidth,
- thumbheight,
- count
-};
-
enum class eDmDetailedEpgST {
title = (int)eScraperST::count,
shorttext,
@@ -1567,6 +1647,7 @@ enum class eViewElementAttribs {
mode,
orientation,
name,
+ clearondisplay,
count
};
@@ -1576,6 +1657,12 @@ enum class eViewListAttribs {
determinatefont,
numlistelements,
orientation,
+ fadetime,
+ shifttime,
+ shifttype,
+ shiftmode,
+ startx,
+ starty,
condition,
count
};
diff --git a/coreengine/listelements.c b/coreengine/listelements.c
index e5dfd93..8f7c2ee 100644
--- a/coreengine/listelements.c
+++ b/coreengine/listelements.c
@@ -2021,3 +2021,130 @@ bool cLeAudioTracks::Parse(bool forced) {
tokenContainer->AddStringToken((int)eLeDisplayTracksST::title, text);
return true;
}
+
+/******************************************************************
+* cLeChannelList
+******************************************************************/
+cLeChannelList::cLeChannelList(void) {
+ channel = NULL;
+}
+
+cLeChannelList::cLeChannelList(const cLeChannelList &other) : cListElement(other) {
+ channel = NULL;
+}
+
+cLeChannelList::~cLeChannelList(void) {
+}
+
+void cLeChannelList::SetTokenContainer(void) {
+ tokenContainer = new skindesignerapi::cTokenContainer();
+ tokenContainer->DefineStringToken("{name}", (int)eLeChannelListST::name);
+ tokenContainer->DefineStringToken("{channelid}", (int)eLeChannelListST::channelid);
+ tokenContainer->DefineStringToken("{presenteventtitle}", (int)eLeChannelListST::presenteventtitle);
+ tokenContainer->DefineStringToken("{presenteventstart}", (int)eLeChannelListST::presenteventstart);
+ tokenContainer->DefineStringToken("{presenteventstop}", (int)eLeChannelListST::presenteventstop);
+ tokenContainer->DefineStringToken("{nexteventtitle}", (int)eLeChannelListST::nexteventtitle);
+ tokenContainer->DefineStringToken("{nexteventstart}", (int)eLeChannelListST::nexteventstart);
+ tokenContainer->DefineStringToken("{nexteventstop}", (int)eLeChannelListST::nexteventstop);
+ tokenContainer->DefineIntToken("{nummenuitem}", (int)eLeChannelListIT::nummenuitem);
+ tokenContainer->DefineIntToken("{current}", (int)eLeChannelListIT::current);
+ tokenContainer->DefineIntToken("{number}", (int)eLeChannelListIT::number);
+ tokenContainer->DefineIntToken("{channellogoexists}", (int)eLeChannelListIT::channellogoexists);
+ tokenContainer->DefineIntToken("{presenteventelapsed}", (int)eLeChannelListIT::presenteventelapsed);
+ tokenContainer->DefineIntToken("{presenteventremaining}", (int)eLeChannelListIT::presenteventremaining);
+ InheritTokenContainer();
+}
+
+void cLeChannelList::Set(const cChannel *channel) {
+ dirty = true;
+ this->channel = channel;
+}
+
+bool cLeChannelList::Parse(bool forced) {
+ if (!cViewElement::Parse(forced))
+ return false;
+ if (!dirty)
+ return false;
+ tokenContainer->Clear();
+ tokenContainer->AddIntToken((int)eLeChannelListIT::nummenuitem, num);
+ tokenContainer->AddIntToken((int)eLeChannelListIT::current, current);
+ tokenContainer->AddIntToken((int)eLeChannelListIT::number, channel->Number());
+ tokenContainer->AddStringToken((int)eLeChannelListST::name, channel->Name());
+ cString channelID = channel->GetChannelID().ToString();
+ tokenContainer->AddStringToken((int)eLeChannelListST::channelid, *channelID);
+ tokenContainer->AddIntToken((int)eLeChannelListIT::channellogoexists, imgCache->LogoExists(*channelID));
+
+#if defined (APIVERSNUM) && (APIVERSNUM >= 20301)
+ LOCK_SCHEDULES_READ;
+ const cSchedules* schedules = Schedules;
+#else
+ cSchedulesLock schedulesLock;
+ const cSchedules* schedules = (cSchedules*)cSchedules::Schedules(schedulesLock);
+#endif
+ const cSchedule *schedule = schedules->GetSchedule(channel);
+ if (schedule) {
+ const cEvent *presentEvent = schedule->GetPresentEvent();
+ if (presentEvent) {
+ tokenContainer->AddStringToken((int)eLeChannelListST::presenteventtitle, presentEvent->Title());
+ tokenContainer->AddStringToken((int)eLeChannelListST::presenteventstart, *presentEvent->GetTimeString());
+ tokenContainer->AddStringToken((int)eLeChannelListST::presenteventstop, *presentEvent->GetEndTimeString());
+ tokenContainer->AddIntToken((int)eLeChannelListIT::presenteventelapsed, (time(0) - presentEvent->StartTime())/60);
+ tokenContainer->AddIntToken((int)eLeChannelListIT::presenteventremaining, presentEvent->Duration()/60 - (time(0) - presentEvent->StartTime())/60);
+ }
+ const cList<cEvent> *events = schedule->Events();
+ if (events && presentEvent) {
+ const cEvent *nextEvent = events->Next(presentEvent);
+ if (nextEvent) {
+ tokenContainer->AddStringToken((int)eLeChannelListST::nexteventtitle, nextEvent->Title());
+ tokenContainer->AddStringToken((int)eLeChannelListST::nexteventstart, *nextEvent->GetTimeString());
+ tokenContainer->AddStringToken((int)eLeChannelListST::nexteventstop, *nextEvent->GetEndTimeString());
+ }
+ }
+ }
+
+ return true;
+}
+
+/******************************************************************
+* cLeGroupList
+******************************************************************/
+cLeGroupList::cLeGroupList(void) {
+ group = NULL;
+ numChannels = 0;
+}
+
+cLeGroupList::cLeGroupList(const cLeGroupList &other) : cListElement(other) {
+ group = NULL;
+ numChannels = 0;
+}
+
+cLeGroupList::~cLeGroupList(void) {
+}
+
+void cLeGroupList::SetTokenContainer(void) {
+ tokenContainer = new skindesignerapi::cTokenContainer();
+ tokenContainer->DefineStringToken("{groupname}", (int)eLeGroupListST::groupname);
+ tokenContainer->DefineIntToken("{numchannels}", (int)eLeGroupListIT::numchannels);
+ tokenContainer->DefineIntToken("{nummenuitem}", (int)eLeGroupListIT::nummenuitem);
+ tokenContainer->DefineIntToken("{current}", (int)eLeGroupListIT::current);
+ InheritTokenContainer();
+}
+
+void cLeGroupList::Set(const char *group, int numChannels) {
+ dirty = true;
+ this->group = group;
+ this->numChannels = numChannels;
+}
+
+bool cLeGroupList::Parse(bool forced) {
+ if (!cViewElement::Parse(forced))
+ return false;
+ if (!dirty)
+ return false;
+ tokenContainer->Clear();
+ tokenContainer->AddIntToken((int)eLeGroupListIT::nummenuitem, num);
+ tokenContainer->AddIntToken((int)eLeGroupListIT::current, current);
+ tokenContainer->AddIntToken((int)eLeGroupListIT::numchannels, numChannels);
+ tokenContainer->AddStringToken((int)eLeGroupListST::groupname, group);
+ return true;
+}
diff --git a/coreengine/listelements.h b/coreengine/listelements.h
index 8f2b5b2..a63fa4d 100644
--- a/coreengine/listelements.h
+++ b/coreengine/listelements.h
@@ -339,4 +339,35 @@ public:
bool Parse(bool forced = true);
};
+/******************************************************************
+* cLeChannelList
+******************************************************************/
+class cLeChannelList : public cListElement {
+private:
+ const cChannel *channel;
+public:
+ cLeChannelList(void);
+ cLeChannelList(const cLeChannelList &other);
+ virtual ~cLeChannelList(void);
+ void SetTokenContainer(void);
+ void Set(const cChannel *channel);
+ bool Parse(bool forced = true);
+};
+
+/******************************************************************
+* cLeGroupList
+******************************************************************/
+class cLeGroupList : public cListElement {
+private:
+ const char *group;
+ int numChannels;
+public:
+ cLeGroupList(void);
+ cLeGroupList(const cLeGroupList &other);
+ virtual ~cLeGroupList(void);
+ void SetTokenContainer(void);
+ void Set(const char *group, int numChannels);
+ bool Parse(bool forced = true);
+};
+
#endif //__LISTELEMENTS_H \ No newline at end of file
diff --git a/coreengine/view.c b/coreengine/view.c
index ae7cee5..f9db80d 100644
--- a/coreengine/view.c
+++ b/coreengine/view.c
@@ -141,6 +141,12 @@ bool cView::ValidViewElement(const char *viewElement) {
bool cView::ValidViewList(const char *viewList) {
if (!strcmp(viewList, "menuitems"))
return true;
+ else if (!strcmp(viewList, "channellist"))
+ return true;
+ else if (!strcmp(viewList, "grouplist"))
+ return true;
+ else if (!strcmp(viewList, "groupchannellist"))
+ return true;
return false;
}
@@ -162,6 +168,8 @@ void cView::PreCache(void) {
continue;
viewElements[i]->SetContainer(contX, contY, attribs->Width(), attribs->Height());
viewElements[i]->Cache();
+ if (const char *clearOnDisplay = viewElements[i]->ClearOnDisplay())
+ SetClearOnDisplay(i, clearOnDisplay);
}
if (viewElementsHorizontal) {
for (int i=0; i < numViewElements; i++) {
@@ -209,6 +217,13 @@ void cView::Clear(int ve, bool forceClearBackground) {
viewElements[ve]->Clear(forceClearBackground);
}
+void cView::SetDirty(int ve) {
+ if (!viewElements[ve])
+ return;
+ viewElements[ve]->SetDirty();
+ viewElements[ve]->SetRestartAnimation();
+}
+
void cView::Render(int ve, bool force) {
if (!viewElements[ve])
return;
@@ -216,6 +231,18 @@ void cView::Render(int ve, bool force) {
viewElements[ve]->Render();
}
+void cView::Hide(int ve) {
+ if (!viewElements[ve])
+ return;
+ viewElements[ve]->Hide();
+}
+
+void cView::Show(int ve) {
+ if (!viewElements[ve])
+ return;
+ viewElements[ve]->Show();
+}
+
void cView::Close(void) {
delete fader;
fader = NULL;
@@ -435,3 +462,20 @@ void cView::DoScaleTv(const cRect *frame) {
}
}
}
+
+void cView::SetClearOnDisplay(int ve, const char *clearOnDisplay) {
+ if (!strcmp(clearOnDisplay, "all")) {
+ viewElements[ve]->SetClearAll();
+ return;
+ }
+ vector<int> clearVEs;
+ for (map<string,int>::iterator it = viewElementNames.begin(); it != viewElementNames.end(); it++) {
+ string name = it->first;
+ int id = it->second;
+ if (strstr(clearOnDisplay, name.c_str())) {
+ clearVEs.push_back(id);
+ }
+ }
+ viewElements[ve]->SetClearOnDisplay(clearVEs);
+}
+
diff --git a/coreengine/view.h b/coreengine/view.h
index efdd351..a27ed7a 100644
--- a/coreengine/view.h
+++ b/coreengine/view.h
@@ -26,6 +26,7 @@ using namespace std;
class cView : public cFadable, public cShiftable {
private:
void DoScaleTv(const cRect *frame);
+ void SetClearOnDisplay(int ve, const char *clearOnDisplay);
protected:
cSdOsd sdOsd;
cViewAttribs *attribs;
@@ -76,13 +77,16 @@ public:
//View API
virtual bool Init(void);
void Clear(int ve, bool forceClearBackground = false);
+ void SetDirty(int ve);
void Render(int ve, bool force = false);
+ void Hide(int ve);
+ void Show(int ve);
virtual void Close(void);
virtual void Flush(bool animFlush);
virtual void Debug(void);
+ //Fadable
bool Detached(void) { return false; };
int Delay(void) { return 0; };
- //Fadable
int FadeTime(void);
virtual void SetTransparency(int transparency, bool force = false);
//Shiftable
diff --git a/coreengine/viewdisplaychannel.c b/coreengine/viewdisplaychannel.c
index f8e163a..7ab36ce 100644
--- a/coreengine/viewdisplaychannel.c
+++ b/coreengine/viewdisplaychannel.c
@@ -24,9 +24,66 @@ cViewChannel::cViewChannel(void) {
veStatusInfo = NULL;
veScraperContent = NULL;
veEcmInfo = NULL;
+#ifdef USE_ZAPCOCKPIT
+ veChannelHints = NULL;
+ veChannelDetail = NULL;
+ veChannelListDetail = NULL;
+ veGroupChannelListDetail = NULL;
+ channelList = NULL;
+ groupList = NULL;
+ groupChannelList = NULL;
+#endif
}
cViewChannel::~cViewChannel() {
+#ifdef USE_ZAPCOCKPIT
+ delete channelList;
+ delete groupList;
+ delete groupChannelList;
+#endif
+}
+
+void cViewChannel::SetGlobals(cGlobals *globals) {
+ cView::SetGlobals(globals);
+#ifdef USE_ZAPCOCKPIT
+ if (channelList)
+ channelList->SetGlobals(globals);
+ if (groupList)
+ groupList->SetGlobals(globals);
+ if (groupChannelList)
+ groupChannelList->SetGlobals(globals);
+#endif
+}
+
+void cViewChannel::PreCache(void) {
+ cView::PreCache();
+#ifdef USE_ZAPCOCKPIT
+ if (channelList) {
+ channelList->SetContainer(attribs->X(), attribs->Y(), attribs->Width(), attribs->Height());
+ channelList->PreCache();
+ }
+ if (groupList) {
+ groupList->SetContainer(attribs->X(), attribs->Y(), attribs->Width(), attribs->Height());
+ groupList->PreCache();
+ }
+ if (groupChannelList) {
+ groupChannelList->SetContainer(attribs->X(), attribs->Y(), attribs->Width(), attribs->Height());
+ groupChannelList->PreCache();
+ }
+#endif
+}
+
+void cViewChannel::AddChannelViewList(const char *listName, cViewList *viewList) {
+#ifdef USE_ZAPCOCKPIT
+ if (!strcmp(listName, "channellist"))
+ channelList = dynamic_cast<cViewListChannelList*>(viewList);
+ else if (!strcmp(listName, "grouplist"))
+ groupList = dynamic_cast<cViewListGroupList*>(viewList);
+ else if (!strcmp(listName, "groupchannellist"))
+ groupChannelList = dynamic_cast<cViewListChannelList*>(viewList);
+ else
+ esyslog("skindesigner: invalid view list %s in displaychannel", listName);
+#endif
}
void cViewChannel::SetViewElements(void) {
@@ -43,6 +100,13 @@ void cViewChannel::SetViewElements(void) {
viewElementNames.insert(pair<string, int>("devices", (int)eVeDisplayChannel::devices));
viewElementNames.insert(pair<string, int>("currentweather", (int)eVeDisplayChannel::currentweather));
viewElementNames.insert(pair<string, int>("scrapercontent", (int)eVeDisplayChannel::scrapercontent));
+ viewElementNames.insert(pair<string, int>("channelhints", (int)eVeDisplayChannel::channelhints));
+ viewElementNames.insert(pair<string, int>("channeldetail", (int)eVeDisplayChannel::channeldetail));
+ viewElementNames.insert(pair<string, int>("channellistback", (int)eVeDisplayChannel::channellistback));
+ viewElementNames.insert(pair<string, int>("channellistdetail", (int)eVeDisplayChannel::channellistdetail));
+ viewElementNames.insert(pair<string, int>("grouplistback", (int)eVeDisplayChannel::grouplistback));
+ viewElementNames.insert(pair<string, int>("groupchannellistback", (int)eVeDisplayChannel::groupchannellistback));
+ viewElementNames.insert(pair<string, int>("groupchannellistdetail", (int)eVeDisplayChannel::groupchannellistdetail));
viewElementNames.insert(pair<string, int>("datetime", (int)eVeDisplayChannel::datetime));
viewElementNames.insert(pair<string, int>("time", (int)eVeDisplayChannel::time));
viewElementNames.insert(pair<string, int>("message", (int)eVeDisplayChannel::message));
@@ -83,6 +147,24 @@ void cViewChannel::SetViewElementObjects(void) {
{
veScraperContent = dynamic_cast<cVeDcScraperContent*>(viewElements[i]);
}
+#ifdef USE_ZAPCOCKPIT
+ else if (dynamic_cast<cVeDcChannelListDetail*>(viewElements[i]))
+ {
+ veChannelListDetail = dynamic_cast<cVeDcChannelListDetail*>(viewElements[i]);
+ }
+ else if (dynamic_cast<cVeDcGroupChannelListDetail*>(viewElements[i]))
+ {
+ veGroupChannelListDetail = dynamic_cast<cVeDcGroupChannelListDetail*>(viewElements[i]);
+ }
+ else if (dynamic_cast<cVeDcChannelHints*>(viewElements[i]))
+ {
+ veChannelHints = dynamic_cast<cVeDcChannelHints*>(viewElements[i]);
+ }
+ else if (dynamic_cast<cVeDcChannelDetail*>(viewElements[i]))
+ {
+ veChannelDetail = dynamic_cast<cVeDcChannelDetail*>(viewElements[i]);
+ }
+#endif
else if (dynamic_cast<cVeDcEcmInfo*>(viewElements[i]))
{
veEcmInfo = dynamic_cast<cVeDcEcmInfo*>(viewElements[i]);
@@ -100,8 +182,16 @@ void cViewChannel::SetViewElementObjects(void) {
void cViewChannel::ClearVariables(void) {
cView::ClearVariables();
+#ifdef USE_ZAPCOCKPIT
+ viewType = dcDefault;
+ viewTypeLast = dcDefault;
+ initExtended = true;
+ displayList = false;
+ initList = false;
+ channelInput = false;
+#endif
channelChange = false;
- displayChannelGroups = false;
+ mode = dmDefault;
if (veCustomTokens)
veCustomTokens->Reset();
timersLoaded = false;
@@ -114,8 +204,23 @@ void cViewChannel::SetChannel(const cChannel *channel, int number) {
globalTimers.LoadTimers();
}
channelChange = true;
- bool wasChannelGroups = displayChannelGroups;
- displayChannelGroups = false;
+
+ //check if channelgroups have to be cleared
+ bool clearChannelGroups = (mode == dmChannelGroups) ? true : false;
+ mode = dmDefault;
+
+#ifdef USE_ZAPCOCKPIT
+ //check if channel hints have to be cleared
+ if (number) {
+ channelInput = true;
+ } else if (channelInput) {
+ channelInput = false;
+ if (veChannelHints)
+ veChannelHints->Close();
+ }
+ if (veChannelDetail)
+ veChannelDetail->Clear(true);
+#endif
if (veChannelInfo) {
veChannelInfo->Clear();
@@ -124,24 +229,15 @@ void cViewChannel::SetChannel(const cChannel *channel, int number) {
if (channel) {
if (!channel->GroupSep()) {
- if (wasChannelGroups)
+ if (clearChannelGroups)
Clear((int)eVeDisplayChannel::channelgroup);
if (veStatusInfo)
veStatusInfo->Set(channel);
if (veEcmInfo)
veEcmInfo->Set(channel);
} else {
- displayChannelGroups = true;
- Clear((int)eVeDisplayChannel::channelinfo, true);
- Clear((int)eVeDisplayChannel::epginfo, true);
- Clear((int)eVeDisplayChannel::statusinfo, true);
- Clear((int)eVeDisplayChannel::progressbar, true);
- Clear((int)eVeDisplayChannel::screenresolution, true);
- Clear((int)eVeDisplayChannel::signalquality, true);
- Clear((int)eVeDisplayChannel::audioinfo, true);
- Clear((int)eVeDisplayChannel::ecminfo, true);
- Clear((int)eVeDisplayChannel::devices, true);
- Clear((int)eVeDisplayChannel::customtokens, true);
+ mode = dmChannelGroups;
+ ClearBasic(false);
if (veChannelGroup)
veChannelGroup->Set(channel);
}
@@ -178,31 +274,310 @@ void cViewChannel::SetMessage(eMessageType type, const char *text) {
}
}
+#ifdef USE_ZAPCOCKPIT
+
+void cViewChannel::SetViewType(eDisplaychannelView viewType) {
+ viewTypeLast = this->viewType;
+ this->viewType = viewType;
+}
+
+int cViewChannel::MaxItems(void) {
+ initList = true;
+ if (viewType == dcChannelList && channelList)
+ return channelList->NumItems();
+ else if (viewType == dcGroupsList && groupList)
+ return groupList->NumItems();
+ else if (viewType == dcGroupsChannelList && groupChannelList)
+ return groupChannelList->NumItems();
+ return 0;
+}
+
+void cViewChannel::SetChannelInfo(const cChannel *channel) {
+ if (!channel)
+ return;
+ if (viewType == dcChannelInfo && veChannelDetail) {
+ ClearOnDisplay();
+ veChannelDetail->Set(channel);
+ Render((int)eVeDisplayChannel::channeldetail);
+ } else if (viewType == dcChannelListInfo && veChannelListDetail) {
+ veChannelListDetail->Set(channel);
+ Render((int)eVeDisplayChannel::channellistdetail);
+ } else if (viewType == dcGroupsChannelListInfo && veGroupChannelListDetail) {
+ veGroupChannelListDetail->Set(channel);
+ Render((int)eVeDisplayChannel::groupchannellistdetail);
+ }
+}
+
+void cViewChannel::SetChannelList(const cChannel *channel, int index, bool current) {
+ displayList = true;
+ if (viewType == dcChannelList && channelList) {
+ channelList->Set(channel, index, current);
+ } else if (viewType == dcGroupsChannelList && groupChannelList) {
+ groupChannelList->Set(channel, index, current);
+ }
+}
+
+void cViewChannel::SetGroupList(const char *group, int numChannels, int index, bool current) {
+ displayList = true;
+ if (groupList) {
+ groupList->Set(group, numChannels, index, current);
+ }
+}
+
+void cViewChannel::ClearList(void) {
+ if (viewType == dcChannelList && channelList)
+ channelList->Clear();
+ if (viewType == dcGroupsList && groupList)
+ groupList->Clear();
+}
+
+void cViewChannel::SetNumChannelHints(int num) {
+ if (veChannelHints)
+ veChannelHints->SetNumHints(num);
+ channelHints = true;
+}
+
+void cViewChannel::SetChannelHint(const cChannel *channel) {
+ if (veChannelHints)
+ veChannelHints->SetHint(channel);
+}
+
+#endif //USE_ZAPCOCKPIT
+
+void cViewChannel::Close(void) {
+ delete fader;
+ fader = NULL;
+ delete shifter;
+ shifter = NULL;
+ if (initFinished && ShiftTime() > 0) {
+ cRect shiftbox = CoveredArea();
+ cPoint ref = cPoint(shiftbox.X(), shiftbox.Y());
+ cPoint end = ShiftStart(shiftbox);
+ shifter = new cAnimation((cShiftable*)this, end, ref, false);
+ shifter->Shift();
+ delete shifter;
+ shifter = NULL;
+ } else if (initFinished && FadeTime() > 0) {
+ fader = new cAnimation((cFadable*)this, false);
+ fader->Fade();
+ delete fader;
+ fader = NULL;
+ }
+ UnScaleTv();
+ ClearVariables();
+ for (int i=0; i < numViewElements; i++) {
+ if (!viewElements[i])
+ continue;
+ viewElements[i]->Close();
+ }
+#ifdef USE_ZAPCOCKPIT
+ if (channelList)
+ channelList->Close();
+ if (groupList)
+ groupList->Close();
+ if (groupChannelList)
+ groupChannelList->Close();
+#endif
+ sdOsd.Flush();
+ sdOsd.DeleteOsd();
+}
+
+void cViewChannel::ClearBasic(bool clearBackground) {
+ if (clearBackground) {
+ Clear((int)eVeDisplayChannel::background, true);
+ Clear((int)eVeDisplayChannel::currentweather, true);
+ }
+ Clear((int)eVeDisplayChannel::channelinfo, true);
+ Clear((int)eVeDisplayChannel::epginfo, true);
+ Clear((int)eVeDisplayChannel::statusinfo, true);
+ Clear((int)eVeDisplayChannel::scrapercontent, true);
+ Clear((int)eVeDisplayChannel::progressbar, true);
+ Clear((int)eVeDisplayChannel::screenresolution, true);
+ Clear((int)eVeDisplayChannel::signalquality, true);
+ Clear((int)eVeDisplayChannel::audioinfo, true);
+ Clear((int)eVeDisplayChannel::ecminfo, true);
+ Clear((int)eVeDisplayChannel::devices, true);
+ Clear((int)eVeDisplayChannel::customtokens, true);
+}
+
+void cViewChannel::ClearExtended(void) {
+#ifdef USE_ZAPCOCKPIT
+ //exit from channel list
+ if ((viewTypeLast == dcChannelList || viewTypeLast == dcChannelListInfo) && viewType == dcDefault && channelList) {
+ channelList->Clear();
+ Clear((int)eVeDisplayChannel::channellistback);
+ Clear((int)eVeDisplayChannel::channellistdetail);
+ SetDirty((int)eVeDisplayChannel::channellistback);
+ initExtended = true;
+ ShowBasic();
+ }
+ //exit from channellist info to channel list
+ if (viewTypeLast == dcChannelListInfo && viewType == dcChannelList) {
+ Clear((int)eVeDisplayChannel::channellistdetail);
+ SetDirty((int)eVeDisplayChannel::channellistdetail);
+ }
+ //exit from group list
+ if (viewTypeLast == dcGroupsList && viewType == dcDefault && groupList) {
+ groupList->Clear();
+ Clear((int)eVeDisplayChannel::grouplistback);
+ SetDirty((int)eVeDisplayChannel::grouplistback);
+ initExtended = true;
+ ShowBasic();
+ }
+ //exit from group channel list to group list
+ if (viewTypeLast == dcGroupsChannelList && viewType == dcGroupsList && groupChannelList) {
+ groupChannelList->Clear();
+ Clear((int)eVeDisplayChannel::groupchannellistback);
+ SetDirty((int)eVeDisplayChannel::groupchannellistback);
+ }
+ //exit from groupchannellist info to groupchannel list
+ if (viewTypeLast == dcGroupsChannelListInfo && viewType == dcGroupsChannelList) {
+ Clear((int)eVeDisplayChannel::groupchannellistdetail);
+ SetDirty((int)eVeDisplayChannel::groupchannellistdetail);
+ }
+ //exit from channel list
+ if ((viewTypeLast == dcGroupsChannelList || viewTypeLast == dcGroupsChannelListInfo) && viewType == dcDefault && groupList && groupChannelList) {
+ groupList->Clear();
+ groupChannelList->Clear();
+ Clear((int)eVeDisplayChannel::grouplistback);
+ Clear((int)eVeDisplayChannel::groupchannellistback);
+ Clear((int)eVeDisplayChannel::groupchannellistdetail);
+ SetDirty((int)eVeDisplayChannel::groupchannellistback);
+ SetDirty((int)eVeDisplayChannel::grouplistback);
+ SetDirty((int)eVeDisplayChannel::groupchannellistdetail);
+ initExtended = true;
+ ShowBasic();
+ }
+ //exit from channel info to channel or group list
+ if (viewTypeLast == dcChannelInfo && (viewType == dcChannelList || viewType == dcGroupsList)) {
+ Clear((int)eVeDisplayChannel::channeldetail, true);
+ }
+ viewTypeLast = dcDefault;
+#endif
+}
+
+void cViewChannel::ClearOnDisplay(void) {
+#ifdef USE_ZAPCOCKPIT
+ if (viewType == dcChannelInfo && veChannelDetail) {
+ vector<int> clear = veChannelDetail->GetClearOnDisplay();
+ for (vector<int>::iterator ve = clear.begin(); ve != clear.end(); ve++) {
+ Hide(*ve);
+ }
+ } else {
+ cViewElement *listBack = NULL;
+ if (viewType == dcChannelList)
+ listBack = viewElements[(int)eVeDisplayChannel::channellistback];
+ else if (viewType == dcGroupsList)
+ listBack = viewElements[(int)eVeDisplayChannel::grouplistback];
+ if (!listBack)
+ return;
+ if (listBack->DoClearAll()) {
+ HideBasic();
+ return;
+ }
+ vector<int> clear = listBack->GetClearOnDisplay();
+ for (vector<int>::iterator ve = clear.begin(); ve != clear.end(); ve++) {
+ Hide(*ve);
+ }
+ }
+#endif
+}
+
+void cViewChannel::DrawBasic(bool initial) {
+ if (initial) {
+ Render((int)eVeDisplayChannel::background);
+ Render((int)eVeDisplayChannel::currentweather);
+ }
+ Render((int)eVeDisplayChannel::channelinfo);
+ Render((int)eVeDisplayChannel::epginfo);
+ Render((int)eVeDisplayChannel::statusinfo);
+ Render((int)eVeDisplayChannel::scrapercontent);
+ Render((int)eVeDisplayChannel::progressbar, channelChange);
+ Render((int)eVeDisplayChannel::screenresolution);
+ Render((int)eVeDisplayChannel::signalquality);
+ Render((int)eVeDisplayChannel::audioinfo);
+ Render((int)eVeDisplayChannel::ecminfo);
+ Render((int)eVeDisplayChannel::devices);
+ Render((int)eVeDisplayChannel::customtokens);
+ Render((int)eVeDisplayChannel::message);
+
+#ifdef USE_ZAPCOCKPIT
+ if (channelHints) {
+ channelHints = false;
+ if (veChannelHints) {
+ if (veChannelHints->Active())
+ veChannelHints->Close();
+ veChannelHints->Parse();
+ veChannelHints->Render();
+ }
+ }
+#endif
+}
+
+void cViewChannel::HideBasic(void) {
+ for (int ve = (int)eVeDisplayChannel::background; ve <= (int)eVeDisplayChannel::ecminfo; ve++) {
+ Hide(ve);
+ }
+}
+
+void cViewChannel::ShowBasic(void) {
+ for (int ve = (int)eVeDisplayChannel::background; ve <= (int)eVeDisplayChannel::ecminfo; ve++) {
+ Show(ve);
+ }
+}
+
+void cViewChannel::DrawExtended(void) {
+#ifdef USE_ZAPCOCKPIT
+ if (!displayList)
+ return;
+ if (initExtended) {
+ ClearOnDisplay();
+ initExtended = false;
+ }
+ if (!init && initList)
+ sdOsd.LockFlush();
+ if (viewType == dcChannelList && channelList) {
+ Render((int)eVeDisplayChannel::channellistback);
+ channelList->Draw(mcUndefined);
+ if (initList)
+ channelList->StartAnimation();
+ } else if (viewType == dcGroupsList && groupList) {
+ Render((int)eVeDisplayChannel::grouplistback);
+ groupList->Draw(mcUndefined);
+ if (initList)
+ groupList->StartAnimation();
+ } else if (viewType == dcGroupsChannelList && groupChannelList) {
+ Render((int)eVeDisplayChannel::groupchannellistback);
+ groupChannelList->Draw(mcUndefined);
+ if (initList)
+ groupChannelList->StartAnimation();
+ }
+ if (!init && initList)
+ sdOsd.UnlockFlush();
+ displayList = false;
+ initList = false;
+#endif
+}
+
void cViewChannel::Flush(bool animFlush) {
if (init) {
sdOsd.LockFlush();
- Render((int)eVeDisplayChannel::background);
- Render((int)eVeDisplayChannel::currentweather);
}
- if (!displayChannelGroups) {
- //normal display
+#ifdef USE_ZAPCOCKPIT
+ ClearExtended();
+#endif
+
+ //Basic Display Handling
+ if (mode == dmDefault) {
if (!shifting) {
- Render((int)eVeDisplayChannel::channelinfo);
- Render((int)eVeDisplayChannel::epginfo);
- Render((int)eVeDisplayChannel::statusinfo);
- Render((int)eVeDisplayChannel::scrapercontent);
- Render((int)eVeDisplayChannel::progressbar, channelChange);
- Render((int)eVeDisplayChannel::screenresolution);
- Render((int)eVeDisplayChannel::signalquality);
- Render((int)eVeDisplayChannel::audioinfo);
- Render((int)eVeDisplayChannel::ecminfo);
- Render((int)eVeDisplayChannel::devices);
- Render((int)eVeDisplayChannel::customtokens);
- Render((int)eVeDisplayChannel::message);
+ DrawBasic(init);
+ }
+ } else if (mode == dmChannelGroups) {
+ if (init) {
+ Render((int)eVeDisplayChannel::background);
+ Render((int)eVeDisplayChannel::currentweather);
}
- } else {
- //channelgroup display
Render((int)eVeDisplayChannel::channelgroup);
}
if (!shifting) {
@@ -210,6 +585,10 @@ void cViewChannel::Flush(bool animFlush) {
Render((int)eVeDisplayChannel::time);
}
channelChange = false;
+
+#ifdef USE_ZAPCOCKPIT
+ DrawExtended();
+#endif
+
cView::Flush(animFlush);
}
-
diff --git a/coreengine/viewdisplaychannel.h b/coreengine/viewdisplaychannel.h
index 623ec14..aa7c278 100644
--- a/coreengine/viewdisplaychannel.h
+++ b/coreengine/viewdisplaychannel.h
@@ -4,30 +4,72 @@
#include "view.h"
#include "../extensions/globaltimers.h"
+enum eDisplayMode {
+ dmDefault,
+ dmChannelGroups
+};
+
class cViewChannel : public cView {
private:
- cVeMessage *veMessage;
- cVeCustomTokens *veCustomTokens;
- cVeDcChannelInfo *veChannelInfo;
- cVeDcChannelGroup *veChannelGroup;
- cVeDcEpgInfo *veEpgInfo;
- cVeDcProgressBar *veProgressBar;
- cVeDcStatusInfo *veStatusInfo;
- cVeDcScraperContent *veScraperContent;
- cVeDcEcmInfo *veEcmInfo;
+ cVeMessage *veMessage;
+ cVeCustomTokens *veCustomTokens;
+ cVeDcChannelInfo *veChannelInfo;
+ cVeDcChannelGroup *veChannelGroup;
+ cVeDcEpgInfo *veEpgInfo;
+ cVeDcProgressBar *veProgressBar;
+ cVeDcStatusInfo *veStatusInfo;
+ cVeDcScraperContent *veScraperContent;
+ cVeDcEcmInfo *veEcmInfo;
+#ifdef USE_ZAPCOCKPIT
+ cVeDcChannelHints *veChannelHints;
+ cVeDcChannelDetail *veChannelDetail;
+ cVeDcChannelListDetail *veChannelListDetail;
+ cVeDcGroupChannelListDetail *veGroupChannelListDetail;
+ cViewListChannelList *channelList;
+ cViewListGroupList *groupList;
+ cViewListChannelList *groupChannelList;
+ eDisplaychannelView viewType;
+ eDisplaychannelView viewTypeLast;
+ bool initExtended;
+ bool displayList;
+ bool initList;
+ bool channelHints;
+ bool channelInput;
+#endif
bool channelChange;
- bool displayChannelGroups;
+ eDisplayMode mode;
bool timersLoaded;
cGlobalTimers globalTimers;
void SetViewElements(void);
void ClearVariables(void);
void SetViewElementObjects(void);
+ void ClearBasic(bool clearBackground);
+ void ClearExtended(void);
+ void ClearOnDisplay(void);
+ void DrawBasic(bool initial);
+ void HideBasic(void);
+ void ShowBasic(void);
+ void DrawExtended(void);
public:
cViewChannel(void);
virtual ~cViewChannel(void);
+ void SetGlobals(cGlobals *globals);
+ void PreCache(void);
+ void AddChannelViewList(const char *listName, cViewList *viewList);
void SetChannel(const cChannel *channel, int number);
void SetEvents(const cEvent *present, const cEvent *following);
void SetMessage(eMessageType type, const char *text);
+#ifdef USE_ZAPCOCKPIT
+ void SetViewType(eDisplaychannelView viewType);
+ int MaxItems(void);
+ void SetChannelInfo(const cChannel *channel);
+ void SetChannelList(const cChannel *channel, int index, bool current);
+ void SetGroupList(const char *group, int numChannels, int index, bool current);
+ void ClearList(void);
+ void SetNumChannelHints(int num);
+ void SetChannelHint(const cChannel *channel);
+#endif
+ void Close(void);
void Flush(bool animFlush);
};
diff --git a/coreengine/viewelement.c b/coreengine/viewelement.c
index 06ca23e..eaa9814 100644
--- a/coreengine/viewelement.c
+++ b/coreengine/viewelement.c
@@ -15,9 +15,11 @@ cViewElement::cViewElement(void) {
detached = false;
waitOnWakeup = true;
startAnimation = true;
+ restartAnimation = false;
globals = NULL;
tokenContainer = NULL;
attribs = new cViewElementAttribs((int)eViewElementAttribs::count);
+ clearAll = false;
detacher = NULL;
fader = NULL;
shifter = NULL;
@@ -34,10 +36,12 @@ cViewElement::cViewElement(const cViewElement &other) {
detached = false;
waitOnWakeup = true;
startAnimation = true;
+ restartAnimation = false;
globals = other.globals;
container.Set(other.container.X(), other.container.Y(), other.container.Width(), other.container.Height());
tokenContainer = NULL;
attribs = new cViewElementAttribs(*other.attribs);
+ clearAll = false;
for (const cAreaNode *node = other.areaNodes.First(); node; node = other.areaNodes.Next(node)) {
if (cArea *a = dynamic_cast<cArea*>((cAreaNode*)node)) {
@@ -101,6 +105,20 @@ cViewElement *cViewElement::CreateViewElement(const char *name, const char *view
e = new cVeDcSignalQuality();
else if (!strcmp(name, "scrapercontent") && !strcmp(viewname, "displaychannel"))
e = new cVeDcScraperContent();
+ else if (!strcmp(name, "channelhints"))
+ e = new cVeDcChannelHints();
+ else if (!strcmp(name, "channeldetail"))
+ e = new cVeDcChannelDetail();
+ else if (!strcmp(name, "channellistback"))
+ e = new cViewElement();
+ else if (!strcmp(name, "grouplistback"))
+ e = new cViewElement();
+ else if (!strcmp(name, "groupchannellistback"))
+ e = new cViewElement();
+ else if (!strcmp(name, "channellistdetail"))
+ e = new cVeDcChannelListDetail();
+ else if (!strcmp(name, "groupchannellistdetail"))
+ e = new cVeDcGroupChannelListDetail();
else if (!strcmp(name, "ecminfo"))
e = new cVeDcEcmInfo();
@@ -326,6 +344,7 @@ void cViewElement::Close(void) {
dirty = true;
init = true;
startAnimation = true;
+ restartAnimation = false;
drawn = false;
scrollingStarted = false;
blocked = false;
@@ -378,8 +397,9 @@ void cViewElement::Render(void) {
}
dirty = false;
drawn = true;
- if (startAnimation) {
+ if (startAnimation || restartAnimation) {
startAnimation = false;
+ restartAnimation = false;
StartAnimation();
}
}
diff --git a/coreengine/viewelement.h b/coreengine/viewelement.h
index 9341ddf..fb5e7dd 100644
--- a/coreengine/viewelement.h
+++ b/coreengine/viewelement.h
@@ -27,9 +27,12 @@ protected:
bool waitOnWakeup;
bool scrollingStarted;
bool startAnimation;
+ bool restartAnimation;
cGlobals *globals;
cRect container;
cViewElementAttribs *attribs;
+ vector<int> clearOnDisplay;
+ bool clearAll;
cList<cAreaNode> areaNodes;
skindesignerapi::cTokenContainer *tokenContainer;
cList<cAnimation> scrollers;
@@ -74,6 +77,11 @@ public:
void StopScrolling(bool deletePixmaps = true);
eOrientation Orientation(void) { return attribs->Orientation(); };
virtual int Delay(void) { return attribs->Delay(); };
+ const char *ClearOnDisplay(void) { return attribs->ClearOnDisplay(); };
+ void SetClearOnDisplay(vector<int> clearOnDisplay) { this->clearOnDisplay = clearOnDisplay; };
+ vector<int> GetClearOnDisplay(void) { return clearOnDisplay; };
+ void SetClearAll(void) { clearAll = true; };
+ bool DoClearAll(void) { return clearAll; };
void ParseDetached(void);
void RenderDetached(void);
bool Shifting(void);
@@ -82,6 +90,7 @@ public:
int ShiftTime(void);
int ShiftMode(void);
void StartAnimation(void);
+ void SetRestartAnimation(void) { restartAnimation = true; };
virtual void SetTransparency(int transparency, bool force = false);
virtual void SetPosition(cPoint &position, cPoint &reference, bool force = false);
void SetStartShifting(void) { };
diff --git a/coreengine/viewelementsdisplaychannel.c b/coreengine/viewelementsdisplaychannel.c
index b4a2f89..c73807e 100644
--- a/coreengine/viewelementsdisplaychannel.c
+++ b/coreengine/viewelementsdisplaychannel.c
@@ -676,3 +676,261 @@ bool cVeDcEcmInfo::CompareECMInfos(sDVBAPIEcmInfo *ecmInfo) {
return false;
return true;
}
+
+/******************************************************************
+* cVeDcChannelHints
+******************************************************************/
+cVeDcChannelHints::cVeDcChannelHints(void) {
+ hints = NULL;
+ numHints = 0;
+ current = 0;
+ hintsIndex = -1;
+ active = false;
+}
+
+cVeDcChannelHints::~cVeDcChannelHints(void) {
+ delete[] hints;
+}
+
+void cVeDcChannelHints::Close(void) {
+ cViewElement::Close();
+}
+
+void cVeDcChannelHints::SetTokenContainer(void) {
+ tokenContainer = new skindesignerapi::cTokenContainer();
+ tokenContainer->DefineIntToken("{numhints}", (int)eDCChannelHintsIT::numhints);
+ tokenContainer->DefineLoopToken("{hints[channelnumber]}", (int)eDCChannelHintsLT::channelnumber);
+ tokenContainer->DefineLoopToken("{hints[channelname]}", (int)eDCChannelHintsLT::channelname);
+ tokenContainer->DefineLoopToken("{hints[channelid]}", (int)eDCChannelHintsLT::channelid);
+ tokenContainer->DefineLoopToken("{hints[channellogoexists]}", (int)eDCChannelHintsLT::channellogoexists);
+ hintsIndex = tokenContainer->LoopIndex("hints");
+ InheritTokenContainer();
+}
+
+void cVeDcChannelHints::SetNumHints(int num) {
+ delete[] hints;
+ numHints = num;
+ hints = new const cChannel*[num];
+ current = 0;
+ active = true;
+ SetDirty();
+}
+
+
+void cVeDcChannelHints::SetHint(const cChannel *c) {
+ hints[current++] = c;
+}
+
+bool cVeDcChannelHints::Parse(bool forced) {
+ if (!cViewElement::Parse(forced))
+ return false;
+ if (!Dirty())
+ return false;
+ if (!hints)
+ return false;
+ tokenContainer->Clear();
+ tokenContainer->AddIntToken((int)eDCChannelHintsIT::numhints, numHints);
+
+ vector<int> loopInfo;
+ loopInfo.push_back(numHints);
+ tokenContainer->CreateLoopTokenContainer(&loopInfo);
+
+ for (int i=0; i < numHints; i++) {
+ if (hints[i]) {
+ tokenContainer->AddLoopToken(hintsIndex, i, (int)eDCChannelHintsLT::channelnumber, *cString::sprintf("%d", hints[i]->Number()));
+ tokenContainer->AddLoopToken(hintsIndex, i, (int)eDCChannelHintsLT::channelname, hints[i]->Name());
+ cString channelID = hints[i]->GetChannelID().ToString();
+ tokenContainer->AddLoopToken(hintsIndex, i, (int)eDCChannelHintsLT::channelid, *channelID);
+ bool logoExists = imgCache->LogoExists(*channelID);
+ tokenContainer->AddLoopToken(hintsIndex, i, (int)eDCChannelHintsLT::channellogoexists, *cString::sprintf("%d", logoExists ? 1 : 0));
+ }
+ }
+ return true;
+}
+
+/******************************************************************
+* cVeDcChannelDetail
+******************************************************************/
+cVeDcChannelDetail::cVeDcChannelDetail(void) {
+ channel = NULL;
+}
+
+cVeDcChannelDetail::~cVeDcChannelDetail(void) {
+ channel = NULL;
+}
+
+void cVeDcChannelDetail::Close(void) {
+ channel = NULL;
+ cViewElement::Close();
+}
+
+void cVeDcChannelDetail::SetTokenContainer(void) {
+ tokenContainer = new skindesignerapi::cTokenContainer();
+ tokenContainer->DefineStringToken("{channelname}", (int)eDCChannelDetailST::channelname);
+ tokenContainer->DefineStringToken("{currenttitle}", (int)eDCChannelDetailST::currenttitle);
+ tokenContainer->DefineStringToken("{currentshorttext}", (int)eDCChannelDetailST::currentshorttext);
+ tokenContainer->DefineStringToken("{currentdescription}", (int)eDCChannelDetailST::currentdescription);
+ tokenContainer->DefineStringToken("{currentstart}", (int)eDCChannelDetailST::currentstart);
+ tokenContainer->DefineStringToken("{currentstop}", (int)eDCChannelDetailST::currentstop);
+ tokenContainer->DefineStringToken("{currentdurationminutes}", (int)eDCChannelDetailST::currentdurationminutes);
+ tokenContainer->DefineStringToken("{nexttitle}", (int)eDCChannelDetailST::nexttitle);
+ tokenContainer->DefineStringToken("{nextshorttext}", (int)eDCChannelDetailST::nextshorttext);
+ tokenContainer->DefineStringToken("{nextdescription}", (int)eDCChannelDetailST::nextdescription);
+ tokenContainer->DefineStringToken("{nextstart}", (int)eDCChannelDetailST::nextstart);
+ tokenContainer->DefineStringToken("{nextstop}", (int)eDCChannelDetailST::nextstop);
+ tokenContainer->DefineStringToken("{nextdurationminutes}", (int)eDCChannelDetailST::nextdurationminutes);
+ tokenContainer->DefineIntToken("{channelnumber}", (int)eDCChannelDetailIT::channelnumber);
+ tokenContainer->DefineIntToken("{currentduration}", (int)eDCChannelDetailIT::currentduration);
+ tokenContainer->DefineIntToken("{currentdurationhours}", (int)eDCChannelDetailIT::currentdurationhours);
+ tokenContainer->DefineIntToken("{currentelapsed}", (int)eDCChannelDetailIT::currentelapsed);
+ tokenContainer->DefineIntToken("{currentremaining}", (int)eDCChannelDetailIT::currentremaining);
+ tokenContainer->DefineIntToken("{nextduration}", (int)eDCChannelDetailIT::nextduration);
+ tokenContainer->DefineIntToken("{nextdurationhours}", (int)eDCChannelDetailIT::nextdurationhours);
+ 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("{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();
+}
+
+void cVeDcChannelDetail::Set(const cChannel *c) {
+ channel = c;
+}
+
+bool cVeDcChannelDetail::Parse(bool forced) {
+ if (!cViewElement::Parse(forced))
+ return false;
+ if (!channel)
+ return false;
+
+ SetDirty();
+ tokenContainer->Clear();
+ tokenContainer->AddIntToken((int)eDCChannelDetailIT::channelnumber, channel->Number());
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::channelname, channel->Name());
+
+#if defined (APIVERSNUM) && (APIVERSNUM >= 20301)
+ LOCK_SCHEDULES_READ;
+ const cSchedules* schedules = Schedules;
+#else
+ cSchedulesLock schedulesLock;
+ const cSchedules* schedules = (cSchedules*)cSchedules::Schedules(schedulesLock);
+#endif
+ const cSchedule *schedule = schedules->GetSchedule(channel);
+ if (schedule) {
+ const cEvent *presentEvent = schedule->GetPresentEvent();
+ if (presentEvent) {
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::currenttitle, presentEvent->Title());
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::currentshorttext, presentEvent->ShortText());
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::currentdescription, presentEvent->Description());
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::currentstart, *presentEvent->GetTimeString());
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::currentstop, *presentEvent->GetEndTimeString());
+ tokenContainer->AddIntToken((int)eDCChannelDetailIT::currentduration, presentEvent->Duration()/60);
+ tokenContainer->AddIntToken((int)eDCChannelDetailIT::currentelapsed, (time(0) - presentEvent->StartTime())/60);
+ tokenContainer->AddIntToken((int)eDCChannelDetailIT::currentremaining, presentEvent->Duration()/60 - (time(0) - presentEvent->StartTime())/60);
+ tokenContainer->AddIntToken((int)eDCChannelDetailIT::currentdurationhours, presentEvent->Duration() / 3600);
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::currentdurationminutes, *cString::sprintf("%.2d", (presentEvent->Duration() / 60)%60));
+ vector<int> loopInfo;
+ bool scrapInfoAvailable = LoadFullScrapInfo(presentEvent, NULL);
+ int numActors = NumActors();
+ loopInfo.push_back(numActors);
+ tokenContainer->CreateLoopTokenContainer(&loopInfo);
+ if (scrapInfoAvailable) {
+ SetFullScrapInfo(tokenContainer, actorsIndex);
+ }
+ }
+ const cList<cEvent> *events = schedule->Events();
+ if (events && presentEvent) {
+ const cEvent *nextEvent = events->Next(presentEvent);
+ if (nextEvent) {
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::nexttitle, nextEvent->Title());
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::nextshorttext, nextEvent->ShortText());
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::nextdescription, nextEvent->Description());
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::nextstart, *nextEvent->GetTimeString());
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::nextstop, *nextEvent->GetEndTimeString());
+ tokenContainer->AddIntToken((int)eDCChannelDetailIT::nextduration, nextEvent->Duration() / 60);
+ tokenContainer->AddIntToken((int)eDCChannelDetailIT::nextdurationhours, nextEvent->Duration() / 3600);
+ tokenContainer->AddStringToken((int)eDCChannelDetailST::nextdurationminutes, *cString::sprintf("%.2d", (nextEvent->Duration() / 60)%60));
+ }
+ }
+ }
+ return true;
+}
diff --git a/coreengine/viewelementsdisplaychannel.h b/coreengine/viewelementsdisplaychannel.h
index 799456d..b1a7691 100644
--- a/coreengine/viewelementsdisplaychannel.h
+++ b/coreengine/viewelementsdisplaychannel.h
@@ -150,4 +150,53 @@ public:
bool Parse(bool forced = false);
};
+/******************************************************************
+* cVeDcChannelHints
+******************************************************************/
+class cVeDcChannelHints : public cViewElement {
+private:
+ const cChannel **hints;
+ int numHints;
+ int current;
+ int hintsIndex;
+ bool active;
+public:
+ cVeDcChannelHints(void);
+ virtual ~cVeDcChannelHints(void);
+ void Close(void);
+ void SetTokenContainer(void);
+ void SetNumHints(int num);
+ void SetHint(const cChannel *c);
+ bool Parse(bool forced = false);
+ bool Active(void) { return active; };
+};
+
+
+/******************************************************************
+* cVeDcChannelDetail
+******************************************************************/
+class cVeDcChannelDetail : public cViewElement, public cScrapManager {
+private:
+ const cChannel *channel;
+ int actorsIndex;
+public:
+ cVeDcChannelDetail(void);
+ virtual ~cVeDcChannelDetail(void);
+ void Close(void);
+ void SetTokenContainer(void);
+ void Set(const cChannel *c);
+ bool Parse(bool forced = false);
+};
+
+class cVeDcChannelListDetail : public cVeDcChannelDetail {
+public:
+ cVeDcChannelListDetail(void) {};
+ virtual ~cVeDcChannelListDetail(void) {};
+};
+
+class cVeDcGroupChannelListDetail : public cVeDcChannelDetail {
+public:
+ cVeDcGroupChannelListDetail(void) {};
+ virtual ~cVeDcGroupChannelListDetail(void) {};
+};
#endif //__VIEWELEMENTSDC_H \ No newline at end of file
diff --git a/coreengine/viewelementsdisplaymenu.c b/coreengine/viewelementsdisplaymenu.c
index 4397ffa..8e8599f 100644
--- a/coreengine/viewelementsdisplaymenu.c
+++ b/coreengine/viewelementsdisplaymenu.c
@@ -411,10 +411,10 @@ bool cVeDmTimers::Parse(bool forced) {
}
bool isRecording = Timer->Recording();
if (!isRecording) {
- if (cEpgTimer_Interface_V1* epgTimer = dynamic_cast<cEpgTimer_Interface_V1*>((cTimer*)Timer)) {
- if (epgTimer->State() == 'R')
- isRecording = true;
- }
+ if (cEpgTimer_Interface_V1* epgTimer = dynamic_cast<cEpgTimer_Interface_V1*>((cTimer*)Timer)) {
+ if (epgTimer->State() == 'R')
+ isRecording = true;
+ }
}
tokenContainer->AddLoopToken(timerIndex, i, (int)eDMTimersLT::recording, isRecording ? "1" : "0");
diff --git a/coreengine/viewlist.c b/coreengine/viewlist.c
index 83e75f8..1ed5432 100644
--- a/coreengine/viewlist.c
+++ b/coreengine/viewlist.c
@@ -9,6 +9,8 @@ cViewList::cViewList(void) {
listElements = NULL;
plugId = -1;
plugMenuId = -1;
+ fader = NULL;
+ shifter = NULL;
}
cViewList::~cViewList(void) {
@@ -25,6 +27,8 @@ cViewList::~cViewList(void) {
}
delete[] listElements;
delete tokenContainer;
+ delete fader;
+ delete shifter;
}
void cViewList::SetGlobals(cGlobals *globals) {
@@ -66,6 +70,12 @@ cViewList *cViewList::CreateViewList(const char *name) {
l = new cViewListAudioTracks();
else if (startswith(name, "menuplugin"))
l = new cViewListPlugin();
+ else if (startswith(name, "channellist"))
+ l = new cViewListChannelList();
+ else if (startswith(name, "grouplist"))
+ l = new cViewListGroupList();
+ else if (startswith(name, "groupchannellist"))
+ l = new cViewListChannelList();
else
esyslog("skindesigner: unknown viewlist %s", name);
return l;
@@ -91,6 +101,12 @@ cViewElement *cViewList::CreateListElement(const char *name) {
le = new cLeAudioTracks();
else if (startswith(name, "menuplugin"))
le = new cLeMenuPlugin();
+ else if (startswith(name, "channellist"))
+ le = new cLeChannelList();
+ else if (startswith(name, "grouplist"))
+ le = new cLeGroupList();
+ else if (startswith(name, "groupchannellist"))
+ le = new cLeChannelList();
else
esyslog("skindesigner: unknown viewlist %s", name);
return le;
@@ -207,21 +223,85 @@ void cViewList::Clear(void) {
}
void cViewList::Close(void) {
+ delete fader;
+ fader = NULL;
+ delete shifter;
+ shifter = NULL;
if (!listElements)
return;
for (int i = 0; i < numElements; i++) {
listElements[i]->StopBlinking();
listElements[i]->StopScrolling();
}
- for (int i = 0; i < numElements; i++) {
+ for (int i = 0; i < numElements; i++)
listElements[i]->Close();
+}
+
+void cViewList::SetTransparency(int transparency, bool force) {
+ for (int i = 0; i < numElements; i++) {
+ if (listElements[i])
+ listElements[i]->SetTransparency(transparency, force);
}
}
-void cViewList::SetTransparency(int transparency) {
+cRect cViewList::CoveredArea(void) {
+ cRect unionArea;
for (int i = 0; i < numElements; i++) {
+ if (listElements[i])
+ unionArea.Combine(listElements[i]->CoveredArea());
+ }
+ return unionArea;
+}
+
+void cViewList::SetPosition(cPoint &position, cPoint &reference, bool force) {
+ for (int i = 0; i < numElements; i++) {
+ if (listElements[i])
+ listElements[i]->SetPosition(position, reference, force);
+ }
+}
+
+void cViewList::RegisterAnimation(void) {
+ for (int i = 0; i < numElements; i++) {
if (listElements[i]) {
- listElements[i]->SetTransparency(transparency);
+ listElements[i]->RegisterAnimation();
+ break;
+ }
+ }
+}
+
+void cViewList::UnregisterAnimation(void) {
+ for (int i = 0; i < numElements; i++) {
+ if (listElements[i]) {
+ listElements[i]->UnregisterAnimation();
+ break;
+ }
+ }
+}
+
+void cViewList::StartAnimation(void) {
+ if (ShiftTime() > 0) {
+ cRect shiftbox = CoveredArea();
+ cPoint ref = cPoint(shiftbox.X(), shiftbox.Y());
+ cPoint start = ShiftStart(shiftbox);
+ SetPosition(start, ref);
+ Flush(false);
+ delete shifter;
+ shifter = new cAnimation((cShiftable*)this, start, ref, true);
+ shifter->Start();
+ } else if (FadeTime() > 0) {
+ SetTransparency(100);
+ Flush(false);
+ delete fader;
+ fader = new cAnimation((cFadable*)this, true);
+ fader->Start();
+ }
+}
+
+void cViewList::Flush(bool animFlush) {
+ for (int i = 0; i < numElements; i++) {
+ if (listElements[i]) {
+ listElements[i]->Flush(animFlush);
+ break;
}
}
}
@@ -231,6 +311,27 @@ void cViewList::Debug(void) {
attribs->Debug();
}
+cPoint cViewList::ShiftStart(cRect &shiftbox) {
+ eShiftType type = (eShiftType)attribs->ShiftType();
+ cPoint start;
+ if (type == eShiftType::none) {
+ start = attribs->ShiftStartpoint();
+ } else if (type == eShiftType::left) {
+ start.SetX(-shiftbox.Width());
+ start.SetY(shiftbox.Y());
+ } else if (type == eShiftType::right) {
+ start.SetX(cOsd::OsdWidth());
+ start.SetY(shiftbox.Y());
+ } else if (type == eShiftType::top) {
+ start.SetX(shiftbox.X());
+ start.SetY(-shiftbox.Height());
+ } else if (type == eShiftType::bottom) {
+ start.SetX(shiftbox.X());
+ start.SetY(cOsd::OsdHeight());
+ }
+ return start;
+}
+
/******************************************************************
* cViewListDefault
******************************************************************/
@@ -927,3 +1028,117 @@ void cViewListAudioTracks::Draw(void) {
}
}
}
+
+/******************************************************************
+* cViewListChannelList
+******************************************************************/
+cViewListChannelList::cViewListChannelList(void) {
+ listChannelList = NULL;
+}
+
+cViewListChannelList::~cViewListChannelList(void) {
+ delete[] listChannelList;
+}
+
+void cViewListChannelList::Prepare(int start, int step) {
+ if (!listElement)
+ return;
+
+ cLeChannelList *tpl = dynamic_cast<cLeChannelList*>(listElement);
+ if (!tpl) return;
+
+ listChannelList = new cLeChannelList*[numElements];
+ listElements = new cListElement*[numElements];
+ int pos = start;
+
+ for (int i = 0; i < numElements; i++) {
+ listChannelList[i] = new cLeChannelList(*tpl);
+ listElements[i] = listChannelList[i];
+ listChannelList[i]->SetNumber(i);
+ listChannelList[i]->SetTokenContainer();
+ int x, y, width, height;
+ if (orientation == eOrientation::vertical) {
+ x = attribs->X();
+ y = pos;
+ width = attribs->Width();
+ height = step;
+ listChannelList[i]->SetAreaHeight(height);
+ } else {
+ x = pos;
+ y = attribs->Y();
+ width = step;
+ height = attribs->Height();
+ listChannelList[i]->SetAreaWidth(width);
+ }
+ listChannelList[i]->SetContainer(x, y, width, height);
+ listChannelList[i]->Cache();
+ pos += step;
+ }
+}
+
+void cViewListChannelList::Set(const cChannel *channel, int index, bool current) {
+ if (index < 0 || index >= numElements)
+ return;
+ if (!current)
+ listChannelList[index]->StopScrolling();
+ listChannelList[index]->SetCurrent(current);
+ listChannelList[index]->SetSelectable(true);
+ listChannelList[index]->Set(channel);
+}
+
+/******************************************************************
+* cViewListGroupList
+******************************************************************/
+cViewListGroupList::cViewListGroupList(void) {
+ listGroupList = NULL;
+}
+
+cViewListGroupList::~cViewListGroupList(void) {
+ delete[] listGroupList;
+}
+
+void cViewListGroupList::Prepare(int start, int step) {
+ if (!listElement)
+ return;
+
+ cLeGroupList *tpl = dynamic_cast<cLeGroupList*>(listElement);
+ if (!tpl) return;
+
+ listGroupList = new cLeGroupList*[numElements];
+ listElements = new cListElement*[numElements];
+ int pos = start;
+
+ for (int i = 0; i < numElements; i++) {
+ listGroupList[i] = new cLeGroupList(*tpl);
+ listElements[i] = listGroupList[i];
+ listGroupList[i]->SetNumber(i);
+ listGroupList[i]->SetTokenContainer();
+ int x, y, width, height;
+ if (orientation == eOrientation::vertical) {
+ x = attribs->X();
+ y = pos;
+ width = attribs->Width();
+ height = step;
+ listGroupList[i]->SetAreaHeight(height);
+ } else {
+ x = pos;
+ y = attribs->Y();
+ width = step;
+ height = attribs->Height();
+ listGroupList[i]->SetAreaWidth(width);
+ }
+ listGroupList[i]->SetContainer(x, y, width, height);
+ listGroupList[i]->Cache();
+ pos += step;
+ }
+}
+
+void cViewListGroupList::Set(const char *group, int numChannels, int index, bool current) {
+ if (index < 0 || index >= numElements)
+ return;
+ if (!current)
+ listGroupList[index]->StopScrolling();
+ listGroupList[index]->SetCurrent(current);
+ listGroupList[index]->SetSelectable(true);
+ listGroupList[index]->Set(group, numChannels);
+}
diff --git a/coreengine/viewlist.h b/coreengine/viewlist.h
index 6c14d03..b72123e 100644
--- a/coreengine/viewlist.h
+++ b/coreengine/viewlist.h
@@ -6,7 +6,7 @@
#include "listelements.h"
#include "area.h"
-class cViewList {
+class cViewList : public cFadable, public cShiftable {
protected:
int plugId;
int plugMenuId;
@@ -19,7 +19,10 @@ protected:
cViewElement *listElement;
cViewElement *currentElement;
cListElement **listElements;
+ cAnimation *fader;
+ cAnimation *shifter;
virtual void Prepare(int start, int step) {};
+ cPoint ShiftStart(cRect &shiftbox);
public:
cViewList(void);
virtual ~cViewList(void);
@@ -40,7 +43,22 @@ public:
void Draw(eMenuCategory menuCat);
void Clear(void);
virtual void Close(void);
- void SetTransparency(int transparency);
+ //Fadable
+ bool Detached(void) { return false; };
+ int Delay(void) { return 0; };
+ int FadeTime(void) { return attribs->FadeTime(); };
+ void SetTransparency(int transparency, bool force = false);
+ //Shiftable
+ int ShiftTime(void) { return attribs->ShiftTime(); };
+ int ShiftMode(void) { return attribs->ShiftMode(); };
+ void SetPosition(cPoint &position, cPoint &reference, bool force = false);
+ void SetStartShifting(void) { };
+ void SetEndShifting(void) { };
+ void RegisterAnimation(void);
+ void UnregisterAnimation(void);
+ cRect CoveredArea(void);
+ void StartAnimation(void);
+ void Flush(bool animFlush);
void Debug(void);
};
@@ -154,4 +172,26 @@ public:
void SetCurrentTrack(int index);
void Draw(void);
};
+
+class cViewListChannelList : public cViewList {
+private:
+ cLeChannelList **listChannelList;
+protected:
+ void Prepare(int start, int step);
+public:
+ cViewListChannelList(void);
+ virtual ~cViewListChannelList(void);
+ void Set(const cChannel *channel, int index, bool current);
+};
+
+class cViewListGroupList : public cViewList {
+private:
+ cLeGroupList **listGroupList;
+protected:
+ void Prepare(int start, int step);
+public:
+ cViewListGroupList(void);
+ virtual ~cViewListGroupList(void);
+ void Set(const char *group, int numChannels, int index, bool current);
+};
#endif //__VIEWLIST_H \ No newline at end of file
diff --git a/coreengine/xmlparser.c b/coreengine/xmlparser.c
index 617313a..aa7be10 100644
--- a/coreengine/xmlparser.c
+++ b/coreengine/xmlparser.c
@@ -40,6 +40,7 @@ bool cXmlParser::ParseView(void) {
view->SetAttributes(rootAttribs);
cViewMenu *menuView = dynamic_cast<cViewMenu*>(view);
+ cViewChannel *channelView = dynamic_cast<cViewChannel*>(view);
cViewTracks *tracksView = dynamic_cast<cViewTracks*>(view);
if (!LevelDown())
@@ -48,6 +49,13 @@ bool cXmlParser::ParseView(void) {
do {
if (view->ValidViewElement(NodeName())) {
ParseViewElement(NodeName());
+ } else if (channelView) {
+ if (view->ValidViewList(NodeName())) {
+ ParseViewList(NULL, NodeName());
+ } else {
+ esyslog("skindesigner: unknown node %s", NodeName());
+ return false;
+ }
} else if (menuView) {
if (menuView->ValidSubView(NodeName())) {
ParseSubView(NodeName());
@@ -334,7 +342,7 @@ void cXmlParser::ParsePluginViewElement(bool isScrollbar, bool isTabLabels) {
}
}
-void cXmlParser::ParseViewList(cView *subView) {
+void cXmlParser::ParseViewList(cView *subView, const char *listName) {
if (!view)
return;
@@ -345,7 +353,11 @@ void cXmlParser::ParseViewList(cView *subView) {
name = view->GetViewName();
vector<stringpair> attribs = ParseAttributes();
- cViewList *viewList = cViewList::CreateViewList(name);
+ cViewList *viewList = NULL;
+ if (!listName)
+ viewList = cViewList::CreateViewList(name);
+ else
+ viewList = cViewList::CreateViewList(listName);
viewList->SetAttributes(attribs);
if (!LevelDown())
@@ -353,7 +365,11 @@ void cXmlParser::ParseViewList(cView *subView) {
do {
if (CheckNodeName("currentelement")) {
- cViewElement *currentElement = cViewList::CreateCurrentElement(name);
+ cViewElement *currentElement = NULL;
+ if (!listName)
+ currentElement = cViewList::CreateCurrentElement(name);
+ else
+ currentElement = cViewList::CreateCurrentElement(listName);
currentElement->SetOsd(sdOsd);
vector<stringpair> attribsList = ParseAttributes();
currentElement->SetAttributes(attribsList);
@@ -375,7 +391,11 @@ void cXmlParser::ParseViewList(cView *subView) {
LevelUp();
viewList->AddCurrentElement(currentElement);
} else if (CheckNodeName("listelement")) {
- cViewElement *listElement = cViewList::CreateListElement(name);
+ cViewElement *listElement = NULL;
+ if (!listName)
+ listElement = cViewList::CreateListElement(name);
+ else
+ listElement = cViewList::CreateListElement(listName);
listElement->SetOsd(sdOsd);
vector<stringpair> attribsList = ParseAttributes();
listElement->SetAttributes(attribsList);
@@ -402,8 +422,12 @@ void cXmlParser::ParseViewList(cView *subView) {
if (subView)
subView->AddViewList(viewList);
- else
- view->AddViewList(viewList);
+ else if (listName) {
+ cViewChannel *channelView = dynamic_cast<cViewChannel*>(view);
+ channelView->AddChannelViewList(listName, viewList);
+ } else {
+ view->AddViewList(viewList);
+ }
}
diff --git a/coreengine/xmlparser.h b/coreengine/xmlparser.h
index 398700e..85bb22a 100644
--- a/coreengine/xmlparser.h
+++ b/coreengine/xmlparser.h
@@ -29,7 +29,7 @@ private:
bool ParseSubView(string name);
void ParseViewElement(string name, cView *subView = NULL);
void ParsePluginViewElement(bool isScrollbar = false, bool isTabLabels = false);
- void ParseViewList(cView *subView = NULL);
+ void ParseViewList(cView *subView = NULL, const char *listName = NULL);
void ParseViewTab(cView *subView);
void ParseViewTabPlugin(void);
void ParseGrid(void);
diff --git a/displaychannel.c b/displaychannel.c
index 9eead8f..c9cc832 100644
--- a/displaychannel.c
+++ b/displaychannel.c
@@ -29,6 +29,63 @@ void cSDDisplayChannel::SetMessage(eMessageType Type, const char *Text) {
view->SetMessage(Type, Text);
}
+#ifdef USE_ZAPCOCKPIT
+
+void cSDDisplayChannel::SetViewType(eDisplaychannelView ViewType) {
+ if (!ok)
+ return;
+ view->SetViewType(ViewType);
+}
+
+int cSDDisplayChannel::MaxItems(void) {
+ if (!ok)
+ return 0;
+ return view->MaxItems();
+}
+
+void cSDDisplayChannel::SetChannelInfo(const cChannel *Channel) {
+ if (!ok)
+ return;
+ view->SetChannelInfo(Channel);
+}
+
+void cSDDisplayChannel::SetChannelList(const cChannel *Channel, int Index, bool Current) {
+ if (!ok)
+ return;
+ view->SetChannelList(Channel, Index, Current);
+}
+
+void cSDDisplayChannel::SetGroupList(const char *Group, int NumChannels, int Index, bool Current) {
+ if (!ok)
+ return;
+ view->SetGroupList(Group, NumChannels, Index, Current);
+}
+
+void cSDDisplayChannel::SetGroupChannelList(const cChannel *Channel, int Index, bool Current) {
+ if (!ok)
+ return;
+}
+
+void cSDDisplayChannel::ClearList(void) {
+ if (!ok)
+ return;
+ view->ClearList();
+}
+
+void cSDDisplayChannel::SetNumChannelHints(int Num) {
+ if (!ok)
+ return;
+ view->SetNumChannelHints(Num);
+}
+
+void cSDDisplayChannel::SetChannelHint(const cChannel *Channel) {
+ if (!ok)
+ return;
+ view->SetChannelHint(Channel);
+}
+
+#endif //USE_ZAPCOCKPIT
+
void cSDDisplayChannel::Flush(void) {
if (!ok)
return;
diff --git a/displaychannel.h b/displaychannel.h
index f116f2c..e0f2895 100644
--- a/displaychannel.h
+++ b/displaychannel.h
@@ -6,7 +6,11 @@
#include "coreengine/definitions.h"
#include "coreengine/viewdisplaychannel.h"
+#ifdef USE_ZAPCOCKPIT
+class cSDDisplayChannel : public cSkinDisplayChannelExtended {
+#else
class cSDDisplayChannel : public cSkinDisplayChannel {
+#endif
private:
cViewChannel *view;
bool ok;
@@ -16,6 +20,17 @@ public:
virtual void SetChannel(const cChannel *Channel, int Number);
virtual void SetEvents(const cEvent *Present, const cEvent *Following);
virtual void SetMessage(eMessageType Type, const char *Text);
+#ifdef USE_ZAPCOCKPIT
+ virtual void SetViewType(eDisplaychannelView ViewType);
+ virtual int MaxItems(void);
+ virtual void SetChannelInfo(const cChannel *Channel);
+ virtual void SetChannelList(const cChannel *Channel, int Index, bool Current);
+ virtual void SetGroupList(const char *Group, int NumChannels, int Index, bool Current);
+ virtual void SetGroupChannelList(const cChannel *Channel, int Index, bool Current);
+ virtual void ClearList(void);
+ virtual void SetNumChannelHints(int Num);
+ virtual void SetChannelHint(const cChannel *Channel);
+#endif
virtual void Flush(void);
};
#endif //__DISPLAYCHANNEL_H
diff --git a/dtd/displaychannel.dtd b/dtd/displaychannel.dtd
index 9fb6ada..9ed515c 100644
--- a/dtd/displaychannel.dtd
+++ b/dtd/displaychannel.dtd
@@ -4,7 +4,10 @@
<!ELEMENT displaychannel (background | channelinfo | epginfo | progressbar | progressbarback |
statusinfo | audioinfo | ecminfo | screenresolution | channelgroup |
- signalquality | signalqualityback | devices | currentweather | scrapercontent |
+ signalquality | signalqualityback | devices | currentweather |
+ scrapercontent | channelhints | channeldetail | channellistdetail |
+ channellistback | channellist | grouplistback | grouplist |
+ groupchannellistback | groupchannellist | groupchannellistdetail |
datetime | time | message | customtokens)* >
<!ATTLIST displaychannel
x CDATA #REQUIRED
@@ -220,6 +223,159 @@
condition CDATA #IMPLIED
>
+<!ELEMENT channelhints (areacontainer|area|areascroll)*>
+<!ATTLIST channelhints
+ delay CDATA #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ debug CDATA #IMPLIED
+ condition CDATA #IMPLIED
+>
+
+<!ELEMENT channeldetail (areacontainer|area|areascroll)*>
+<!ATTLIST channeldetail
+ delay CDATA #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ debug CDATA #IMPLIED
+ condition CDATA #IMPLIED
+ clearondisplay CDATA #IMPLIED
+>
+
+<!ELEMENT channellistback (areacontainer|area|areascroll)*>
+<!ATTLIST channellistback
+ delay CDATA #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ debug CDATA #IMPLIED
+ condition CDATA #IMPLIED
+ clearondisplay CDATA #IMPLIED
+>
+
+<!ELEMENT grouplistback (areacontainer|area|areascroll)*>
+<!ATTLIST grouplistback
+ delay CDATA #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ debug CDATA #IMPLIED
+ condition CDATA #IMPLIED
+ clearondisplay CDATA #IMPLIED
+>
+
+<!ELEMENT groupchannellistback (areacontainer|area|areascroll)*>
+<!ATTLIST groupchannellistback
+ delay CDATA #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ debug CDATA #IMPLIED
+ condition CDATA #IMPLIED
+>
+
+<!ELEMENT channellist (listelement)>
+<!ATTLIST channellist
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ align (left|top|center|bottom|right) #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ numlistelements CDATA #REQUIRED
+ orientation CDATA #REQUIRED
+ condition CDATA #IMPLIED
+>
+
+<!ELEMENT grouplist (listelement)>
+<!ATTLIST grouplist
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ align (left|top|center|bottom|right) #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ numlistelements CDATA #REQUIRED
+ orientation CDATA #REQUIRED
+ condition CDATA #IMPLIED
+>
+
+<!ELEMENT groupchannellist (listelement)>
+<!ATTLIST groupchannellist
+ x CDATA #REQUIRED
+ y CDATA #REQUIRED
+ width CDATA #REQUIRED
+ height CDATA #REQUIRED
+ align (left|top|center|bottom|right) #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ numlistelements CDATA #REQUIRED
+ orientation CDATA #REQUIRED
+ condition CDATA #IMPLIED
+>
+
+<!ELEMENT listelement (areacontainer|area|areascroll)*>
+<!ATTLIST listelement
+ debug CDATA #IMPLIED
+>
+
+<!ELEMENT channellistdetail (areacontainer|area|areascroll)*>
+<!ATTLIST channellistdetail
+ delay CDATA #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ debug CDATA #IMPLIED
+ condition CDATA #IMPLIED
+>
+
+<!ELEMENT groupchannellistdetail (areacontainer|area|areascroll)*>
+<!ATTLIST groupchannellistdetail
+ delay CDATA #IMPLIED
+ fadetime CDATA #IMPLIED
+ shifttime CDATA #IMPLIED
+ shifttype CDATA #IMPLIED
+ shiftmode CDATA #IMPLIED
+ startx CDATA #IMPLIED
+ starty CDATA #IMPLIED
+ debug CDATA #IMPLIED
+ condition CDATA #IMPLIED
+>
+
<!ELEMENT datetime (areacontainer|area|areascroll)*>
<!ATTLIST datetime
delay CDATA #IMPLIED
diff --git a/extensions/globaltimers.c b/extensions/globaltimers.c
index 6e7263e..c6b483c 100644
--- a/extensions/globaltimers.c
+++ b/extensions/globaltimers.c
@@ -26,7 +26,6 @@ cGlobalTimers::~cGlobalTimers(void) {
}
void cGlobalTimers::LoadTimers(void) {
- uint64_t start = cTimeMs::Now();
isEpg2VdrTimers = false;
bool epg2vdrOk = false;
if (pEpg2Vdr) {
@@ -38,7 +37,6 @@ void cGlobalTimers::LoadTimers(void) {
SetRemoteTimers(initial);
}
}
- esyslog("skindesigner: loaded %d timers, needed %d ms", Size(), cTimeMs::Now() - start);
initial = false;
}
diff --git a/patches/vdr-2.2.0_zapcockpit.patch b/patches/vdr-2.2.0_zapcockpit.patch
new file mode 100644
index 0000000..1eda556
--- /dev/null
+++ b/patches/vdr-2.2.0_zapcockpit.patch
@@ -0,0 +1,1015 @@
+diff -Naur vdr-2.2.0/config.c vdr-2.2.0_zapcockpit/config.c
+--- vdr-2.2.0/config.c 2015-02-10 13:24:13.000000000 +0100
++++ vdr-2.2.0_zapcockpit/config.c 2016-05-26 07:29:05.736117301 +0200
+@@ -414,6 +414,10 @@
+ SVDRPTimeout = 300;
+ ZapTimeout = 3;
+ ChannelEntryTimeout = 1000;
++ ZapcockpitUseGroups = 1;
++ ZapcockpitUseHints = 1;
++ ZapcockpitUseInfo = 1;
++ ZapcockpitHideLastGroup = 0;
+ RcRepeatDelay = 300;
+ RcRepeatDelta = 100;
+ DefaultPriority = 50;
+@@ -636,6 +640,10 @@
+ else if (!strcasecmp(Name, "SVDRPTimeout")) SVDRPTimeout = atoi(Value);
+ else if (!strcasecmp(Name, "ZapTimeout")) ZapTimeout = atoi(Value);
+ else if (!strcasecmp(Name, "ChannelEntryTimeout")) ChannelEntryTimeout= atoi(Value);
++ else if (!strcasecmp(Name, "ZapcockpitUseGroups")) ZapcockpitUseGroups= atoi(Value);
++ else if (!strcasecmp(Name, "ZapcockpitUseHints")) ZapcockpitUseHints = atoi(Value);
++ else if (!strcasecmp(Name, "ZapcockpitUseInfo")) ZapcockpitUseInfo = atoi(Value);
++ else if (!strcasecmp(Name, "ZapcockpitHideLastGroup")) ZapcockpitHideLastGroup = atoi(Value);
+ else if (!strcasecmp(Name, "RcRepeatDelay")) RcRepeatDelay = atoi(Value);
+ else if (!strcasecmp(Name, "RcRepeatDelta")) RcRepeatDelta = atoi(Value);
+ else if (!strcasecmp(Name, "DefaultPriority")) DefaultPriority = atoi(Value);
+@@ -762,6 +770,10 @@
+ Store("SVDRPTimeout", SVDRPTimeout);
+ Store("ZapTimeout", ZapTimeout);
+ Store("ChannelEntryTimeout",ChannelEntryTimeout);
++ Store("ZapcockpitUseGroups",ZapcockpitUseGroups);
++ Store("ZapcockpitUseHints", ZapcockpitUseHints);
++ Store("ZapcockpitUseInfo", ZapcockpitUseInfo);
++ Store("ZapcockpitHideLastGroup", ZapcockpitHideLastGroup);
+ Store("RcRepeatDelay", RcRepeatDelay);
+ Store("RcRepeatDelta", RcRepeatDelta);
+ Store("DefaultPriority", DefaultPriority);
+diff -Naur vdr-2.2.0/config.h vdr-2.2.0_zapcockpit/config.h
+--- vdr-2.2.0/config.h 2015-02-13 16:39:08.000000000 +0100
++++ vdr-2.2.0_zapcockpit/config.h 2016-05-26 07:29:05.708117300 +0200
+@@ -290,6 +290,10 @@
+ int SVDRPTimeout;
+ int ZapTimeout;
+ int ChannelEntryTimeout;
++ int ZapcockpitUseGroups;
++ int ZapcockpitUseHints;
++ int ZapcockpitUseInfo;
++ int ZapcockpitHideLastGroup;
+ int RcRepeatDelay;
+ int RcRepeatDelta;
+ int DefaultPriority, DefaultLifetime;
+diff -Naur vdr-2.2.0/menu.c vdr-2.2.0_zapcockpit/menu.c
+--- vdr-2.2.0/menu.c 2015-02-10 13:37:06.000000000 +0100
++++ vdr-2.2.0_zapcockpit/menu.c 2016-05-26 07:29:05.880117306 +0200
+@@ -3759,6 +3759,10 @@
+ Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$SVDRP timeout (s)"), &data.SVDRPTimeout));
+ Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Zap timeout (s)"), &data.ZapTimeout));
+ Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Channel entry timeout (ms)"), &data.ChannelEntryTimeout, 0));
++ Add(new cMenuEditBoolItem( tr("Setup.Miscellaneous$Zapcockpit: 2nd ok shows info"), &data.ZapcockpitUseInfo));
++ Add(new cMenuEditBoolItem( tr("Setup.Miscellaneous$Zapcockpit: Use extended channel group display"), &data.ZapcockpitUseGroups));
++ Add(new cMenuEditBoolItem( tr("Setup.Miscellaneous$Zapcockpit: Use channel hints"), &data.ZapcockpitUseHints));
++ Add(new cMenuEditBoolItem( tr("Setup.Miscellaneous$Zapcockpit: Hide last channel group"), &data.ZapcockpitHideLastGroup));
+ Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Remote control repeat delay (ms)"), &data.RcRepeatDelay, 0));
+ Add(new cMenuEditIntItem( tr("Setup.Miscellaneous$Remote control repeat delta (ms)"), &data.RcRepeatDelta, 0));
+ Add(new cMenuEditChanItem(tr("Setup.Miscellaneous$Initial channel"), &data.InitialChannel, tr("Setup.Miscellaneous$as before")));
+@@ -4207,7 +4211,7 @@
+ lastTime.Set();
+ }
+
+-cDisplayChannel::cDisplayChannel(eKeys FirstKey)
++cDisplayChannel::cDisplayChannel(eKeys FirstKey, bool processKey)
+ :cOsdObject(true)
+ {
+ currentDisplayChannel = this;
+@@ -4220,7 +4224,8 @@
+ displayChannel = Skins.Current()->DisplayChannel(withInfo);
+ positioner = NULL;
+ channel = Channels.GetByNumber(cDevice::CurrentChannel());
+- ProcessKey(FirstKey);
++ if (processKey)
++ ProcessKey(FirstKey);
+ }
+
+ cDisplayChannel::~cDisplayChannel()
+@@ -4461,6 +4466,700 @@
+ return osEnd;
+ }
+
++// --- cDisplayChannelExtended -------------------------------------------------------
++cDisplayChannelExtended::cDisplayChannelExtended(int Number, bool Switched)
++:cDisplayChannel(Number, Switched)
++{
++ state = esDefault;
++ numItemsChannel = 0;
++ currentChannel = -1;
++ startChannel = -1;
++ numItemsGroup = 0;
++ currentGroup = -1;
++ startGroup = -1;
++}
++
++cDisplayChannelExtended::cDisplayChannelExtended(eKeys FirstKey)
++:cDisplayChannel(FirstKey, false)
++{
++ state = esInit;
++ numItemsChannel = 0;
++ currentChannel = -1;
++ startChannel = -1;
++ numItemsGroup = 0;
++ currentGroup = -1;
++ startGroup = -1;
++}
++
++cDisplayChannelExtended::~cDisplayChannelExtended()
++{
++}
++
++eOSState cDisplayChannelExtended::ProcessKey(eKeys Key)
++{
++ cSkinDisplayChannelExtended *displayChannelExtended = dynamic_cast<cSkinDisplayChannelExtended*>(displayChannel);
++ if (!displayChannelExtended)
++ return cDisplayChannel::ProcessKey(Key);
++
++ if (Key != kNone)
++ lastTime.Set();
++
++ bool keyHandeled = false;
++ //number keys are always handled by default state
++ if ((int)Key >= k0 && (int)Key <= k9) {
++ displayChannelExtended->SetViewType(dcDefault);
++ StateNumberKey((int)Key, displayChannelExtended);
++ state = esDefault;
++ } else if (number <= 0) {
++ switch (state) {
++ case esInit:
++ keyHandeled = StateInit((int)Key, displayChannelExtended);
++ break;
++ case esDefault:
++ keyHandeled = StateDefault((int)Key, displayChannelExtended);
++ break;
++ case esChannelInfo:
++ keyHandeled = StateChannelInfo((int)Key, displayChannelExtended);
++ break;
++ case esChannelList:
++ case esChannelListInfo:
++ keyHandeled = StateChannelList((int)Key, displayChannelExtended);
++ break;
++ case esGroupsList:
++ keyHandeled = StateGroupList((int)Key, displayChannelExtended);
++ break;
++ case esGroupsChannelList:
++ case esGroupsChannelListInfo:
++ keyHandeled = StateGroupChannelList((int)Key, displayChannelExtended);
++ break;
++ default:
++ break;
++ }
++ }
++ //in extended state, no timeout
++ if (state != esDefault)
++ lastTime.Set();
++
++ //do own flush for all lists
++ if (keyHandeled || (Key == kNone && state > esChannelInfo)) {
++ SetNeedsFastResponse(false);
++ displayChannel->Flush();
++ return osContinue;
++ }
++
++ return cDisplayChannel::ProcessKey(Key);
++}
++
++void cDisplayChannelExtended::StateNumberKey(int key, cSkinDisplayChannelExtended *dcExt)
++{
++ if (!Setup.ZapcockpitUseHints)
++ return;
++ if (number < 0)
++ return;
++ int selectedChannel = number > Channels.MaxNumber() ? key - k0 : number * 10 + key - k0;
++ int candidateStartNumber = selectedChannel * 10;
++ channellist.Clear();
++ cChannel *candidatesStart = Channels.GetByNumber(candidateStartNumber);
++ int numHints = 0;
++ for (cChannel *candidate = candidatesStart; candidate; candidate = Channels.Next(candidate)) {
++ if (candidate->GroupSep())
++ continue;
++ numHints++;
++ if (candidate->Number() >= candidateStartNumber + 9)
++ break;
++ }
++ if (numHints == 0)
++ return;
++ dcExt->SetNumChannelHints(numHints);
++ for (cChannel *candidate = candidatesStart; candidate; candidate = Channels.Next(candidate)) {
++ if (candidate->GroupSep())
++ continue;
++ dcExt->SetChannelHint(candidate);
++ if (candidate->Number() >= candidateStartNumber + 9)
++ break;
++ }
++}
++
++bool cDisplayChannelExtended::StateInit(int key, cSkinDisplayChannelExtended *dcExt)
++{
++ bool keyHandeled = false;
++ switch (key) {
++ //left openes groups list
++ case kLeft|k_Repeat: case kLeft:
++ case kPrev|k_Repeat: case kPrev: {
++ if (!Setup.ZapcockpitUseGroups)
++ return false;
++ cOsdProvider::OsdSizeChanged(osdState); // just to get the current state
++ DisplayChannel();
++ DisplayInfo();
++ InitGroupList(dcExt);
++ state = esGroupsList;
++ keyHandeled = true;
++ break;
++ }
++ //right openes channels list
++ case kRight|k_Repeat: case kRight:
++ case kNext|k_Repeat: case kNext: {
++ if (!Setup.ZapcockpitUseGroups)
++ return false;
++ cOsdProvider::OsdSizeChanged(osdState); // just to get the current state
++ DisplayChannel();
++ DisplayInfo();
++ InitChannelList(dcExt);
++ state = esChannelList;
++ keyHandeled = true;
++ break;
++ }
++ //other keys are handled by cDisplayChannel::ProcessKeys()
++ default:
++ dcExt->SetViewType(dcDefault);
++ state = esDefault;
++ break;
++ }
++ return keyHandeled;
++}
++
++bool cDisplayChannelExtended::StateDefault(int key, cSkinDisplayChannelExtended *dcExt)
++{
++ bool keyHandeled = false;
++ switch (key) {
++ //2nd ok opens extended info for current channel
++ case kOk: {
++ if (!Setup.ZapcockpitUseInfo)
++ return false;
++ dcExt->SetViewType(dcChannelInfo);
++ dcExt->SetChannelInfo(channel);
++ state = esChannelInfo;
++ keyHandeled = true;
++ break;
++ }
++ //left openes groups list
++ case kLeft|k_Repeat: case kLeft:
++ case kPrev|k_Repeat: case kPrev: {
++ if (!Setup.ZapcockpitUseGroups)
++ return false;
++ InitGroupList(dcExt);
++ state = esGroupsList;
++ keyHandeled = true;
++ break;
++ }
++ //right openes channels list
++ case kRight|k_Repeat: case kRight:
++ case kNext|k_Repeat: case kNext: {
++ if (!Setup.ZapcockpitUseGroups)
++ return false;
++ InitChannelList(dcExt);
++ state = esChannelList;
++ keyHandeled = true;
++ break;
++ }
++ //other keys are handled by cDisplayChannel::ProcessKeys()
++ default:
++ break;
++ }
++ return keyHandeled;
++}
++
++bool cDisplayChannelExtended::StateChannelInfo(int key, cSkinDisplayChannelExtended *dcExt)
++{
++ bool keyHandeled = false;
++ switch (key) {
++ //ok closes here
++ case kOk:
++ state = esDefault;
++ break;
++ //channel switching is handled by default state
++ case kUp|k_Repeat: case kUp:
++ case kDown|k_Repeat: case kDown:
++ case kChanUp|k_Repeat: case kChanUp:
++ case kChanDn|k_Repeat: case kChanDn:
++ dcExt->SetViewType(dcDefault);
++ state = esDefault;
++ break;
++ case kUp|k_Release: case kDown|k_Release:
++ case kChanUp|k_Release: case kChanDn|k_Release:
++ case kNext|k_Release: case kPrev|k_Release:
++ dcExt->SetViewType(dcDefault);
++ state = esDefault;
++ break;
++ //left openes groups list
++ case kLeft|k_Repeat: case kLeft:
++ case kPrev|k_Repeat: case kPrev: {
++ if (!Setup.ZapcockpitUseGroups)
++ return false;
++ InitGroupList(dcExt);
++ state = esGroupsList;
++ keyHandeled = true;
++ break;
++ }
++ //right openes channels list
++ case kRight|k_Repeat: case kRight:
++ case kNext|k_Repeat: case kNext: {
++ if (!Setup.ZapcockpitUseGroups)
++ return false;
++ InitChannelList(dcExt);
++ state = esChannelList;
++ keyHandeled = true;
++ break;
++ }
++ default:
++ break;
++ }
++ return keyHandeled;
++}
++
++bool cDisplayChannelExtended::StateChannelList(int key, cSkinDisplayChannelExtended *dcExt)
++{
++ bool keyHandeled = false;
++ switch (key) {
++ //ok switches to the selected channel
++ case kOk: {
++ bool ok = SwitchChannel();
++ dcExt->SetViewType(dcDefault);
++ if (!ok)
++ keyHandeled = true;
++ state = esDefault;
++ break;
++ }
++ //scrolling up / down
++ case kUp|k_Repeat: case kUp:
++ state = esChannelList;
++ dcExt->SetViewType(dcChannelList);
++ CursorUp(dcExt);
++ keyHandeled = true;
++ break;
++ case kDown|k_Repeat: case kDown:
++ state = esChannelList;
++ dcExt->SetViewType(dcChannelList);
++ CursorDown(dcExt);
++ keyHandeled = true;
++ break;
++ //left closes channel list
++ case kLeft|k_Repeat: case kLeft: {
++ if (state == esChannelList) {
++ keyHandeled = true;
++ dcExt->SetViewType(dcDefault);
++ state = esDefault;
++ } else if (state == esChannelListInfo) {
++ keyHandeled = true;
++ dcExt->SetViewType(dcChannelList);
++ state = esChannelList;
++ }
++ break; }
++ //right shows extended info of currently selected channel
++ case kRight|k_Repeat: case kRight: {
++ keyHandeled = true;
++ if (state != esChannelList)
++ break;
++ cChannelListItem *li = channellist.Get(currentChannel);
++ if (li) {
++ const cChannel *selected = li->Channel();
++ if (selected) {
++ dcExt->SetViewType(dcChannelListInfo);
++ dcExt->SetChannelInfo(selected);
++ state = esChannelListInfo;
++ }
++ }
++ break;
++ }
++ default:
++ break;
++ }
++ return keyHandeled;
++}
++
++bool cDisplayChannelExtended::StateGroupList(int key, cSkinDisplayChannelExtended *dcExt)
++{
++ bool keyHandeled = false;
++ switch (key) {
++ //ok switches to first channel in group
++ case kOk: {
++ bool ok = SwitchChannel();
++ dcExt->SetViewType(dcDefault);
++ if (!ok)
++ keyHandeled = true;
++ state = esDefault;
++ break;
++ }
++ //scrolling up / down
++ case kUp|k_Repeat: case kUp:
++ state = esGroupsList;
++ CursorUp(dcExt);
++ dcExt->SetViewType(dcGroupsList);
++ keyHandeled = true;
++ break;
++ case kDown|k_Repeat: case kDown:
++ state = esGroupsList;
++ CursorDown(dcExt);
++ dcExt->SetViewType(dcGroupsList);
++ keyHandeled = true;
++ break;
++ //left shows channel list of selected group
++ case kLeft|k_Repeat: case kLeft:
++ state = esGroupsChannelList;
++ InitGroupChannelList(dcExt);
++ keyHandeled = true;
++ break;
++ //right closes group list
++ case kRight|k_Repeat: case kRight:
++ keyHandeled = true;
++ dcExt->SetViewType(dcDefault);
++ state = esDefault;
++ break;
++ default:
++ break;
++ }
++ return keyHandeled;
++}
++
++bool cDisplayChannelExtended::StateGroupChannelList(int key, cSkinDisplayChannelExtended *dcExt)
++{
++ bool keyHandeled = false;
++ switch (key) {
++ //ok switches to the selected channel
++ case kOk: {
++ bool ok = SwitchChannel();
++ dcExt->SetViewType(dcDefault);
++ if (!ok)
++ keyHandeled = true;
++ state = esDefault;
++ break;
++ }
++ //scrolling up / down
++ case kUp|k_Repeat: case kUp:
++ state = esGroupsChannelList;
++ dcExt->SetViewType(dcGroupsChannelList);
++ CursorUp(dcExt);
++ keyHandeled = true;
++ break;
++ case kDown|k_Repeat: case kDown:
++ state = esGroupsChannelList;
++ dcExt->SetViewType(dcGroupsChannelList);
++ CursorDown(dcExt);
++ keyHandeled = true;
++ break;
++ //left shows extended info of currently selected channel
++ case kLeft|k_Repeat: case kLeft: {
++ keyHandeled = true;
++ if (state != esGroupsChannelList)
++ break;
++ cChannelListItem *li = channellist.Get(currentChannel);
++ if (li) {
++ const cChannel *selected = li->Channel();
++ if (selected) {
++ dcExt->SetViewType(dcGroupsChannelListInfo);
++ dcExt->SetChannelInfo(selected);
++ state = esGroupsChannelListInfo;
++ }
++ }
++ break;
++ }
++ //right closes channel list or channel info
++ case kRight|k_Repeat: case kRight: {
++ if (state == esGroupsChannelList) {
++ state = esGroupsList;
++ dcExt->SetViewType(dcGroupsList);
++ keyHandeled = true;
++ } else if (state == esGroupsChannelListInfo) {
++ state = esGroupsChannelList;
++ dcExt->SetViewType(dcGroupsChannelList);
++ keyHandeled = true;
++ }
++ break;
++ }
++ default:
++ break;
++ }
++ return keyHandeled;
++}
++
++void cDisplayChannelExtended::InitChannelList(cSkinDisplayChannelExtended *dcExt)
++{
++ dcExt->SetViewType(dcChannelList);
++ numItemsChannel = dcExt->MaxItems();
++ if (numItemsChannel < 1)
++ return;
++ SetChannelList();
++ currentChannel = GetIndexChannel(channel);
++ if (currentChannel < 0)
++ currentChannel = 0;
++ startChannel = max(0, currentChannel - numItemsChannel/2 + 1);
++ DisplayChannelList(dcExt);
++}
++
++void cDisplayChannelExtended::SetChannelList(void)
++{
++ channellist.Clear();
++ cChannel *lastSep = NULL;
++ if (Setup.ZapcockpitHideLastGroup)
++ lastSep = LastChannelSep();
++ for (cChannel *c = Channels.First(); c; c = Channels.Next(c)) {
++ if (c->GroupSep()) {
++ if (Setup.ZapcockpitHideLastGroup && c == lastSep)
++ break;
++ else
++ continue;
++ }
++ channellist.Add(new cChannelListItem(c));
++ }
++}
++
++int cDisplayChannelExtended::GetIndexChannel(cChannel *c)
++{
++ int i=0;
++ for (cChannelListItem *li = channellist.First(); li; li = channellist.Next(li)) {
++ if (li->Channel() == c)
++ return i;
++ i++;
++ }
++ return -1;
++}
++
++void cDisplayChannelExtended::InitGroupList(cSkinDisplayChannelExtended *dcExt)
++{
++ dcExt->SetViewType(dcGroupsList);
++ numItemsGroup = dcExt->MaxItems();
++ if (numItemsGroup < 1)
++ return;
++ SetGroupList();
++ currentGroup = GetIndexGroup(channel);
++ if (currentGroup < 0)
++ currentGroup = 0;
++ startGroup = max(0, numItemsGroup >= grouplist.Count() ? 0 : currentGroup - numItemsGroup/2 + 1);
++ DisplayGroupList(dcExt);
++}
++
++void cDisplayChannelExtended::SetGroupList(void)
++{
++ grouplist.Clear();
++ cChannel *lastSep = NULL;
++ if (Setup.ZapcockpitHideLastGroup)
++ lastSep = LastChannelSep();
++ int numChannels = 0;
++ cGroupListItem *item = NULL;
++ for (cChannel *c = Channels.First(); c; c = Channels.Next(c)) {
++ if (c->GroupSep()) {
++ if (item) {
++ item->SetNumChannels(numChannels);
++ numChannels = 0;
++ }
++ if (Setup.ZapcockpitHideLastGroup && c == lastSep)
++ break;
++ item = new cGroupListItem(c);
++ grouplist.Add(item);
++ } else
++ numChannels++;
++ }
++ if (grouplist.Count() > 0 && numChannels)
++ grouplist.Last()->SetNumChannels(numChannels);
++}
++
++int cDisplayChannelExtended::GetIndexGroup(cChannel *cur)
++{
++ cChannel *group = NULL;
++ for (cChannel *c = cur; c; c = Channels.Prev(c)) {
++ if (c->GroupSep()) {
++ group = c;
++ break;
++ }
++ }
++ if (!group)
++ return -1;
++ int i=0;
++ for (cGroupListItem *li = grouplist.First(); li; li = grouplist.Next(li)) {
++ if (li->Channel() == group)
++ return i;
++ i++;
++ }
++ return -1;
++}
++
++void cDisplayChannelExtended::InitGroupChannelList(cSkinDisplayChannelExtended *dcExt)
++{
++ dcExt->SetViewType(dcGroupsChannelList);
++ numItemsChannel = dcExt->MaxItems();
++ if (numItemsChannel < 1)
++ return;
++ SetGroupChannelList(dcExt);
++ currentChannel = 0;
++ startChannel = 0;
++ DisplayChannelList(dcExt);
++}
++
++void cDisplayChannelExtended::SetGroupChannelList(cSkinDisplayChannelExtended *dcExt)
++{
++ cGroupListItem *curGroup = grouplist.Get(currentGroup);
++ if (!curGroup)
++ return;
++ cChannel *curChannel = curGroup->Channel();
++ if (!curChannel)
++ return;
++ channellist.Clear();
++ for (cChannel *c = dynamic_cast<cChannel*>(curChannel->Next()); c; c = Channels.Next(c)) {
++ if (c->GroupSep())
++ break;
++ channellist.Add(new cChannelListItem(c));
++ }
++}
++
++void cDisplayChannelExtended::CursorUp(cSkinDisplayChannelExtended *dcExt)
++{
++ int *start, *current, *numItems;
++ if (state == esChannelList || state == esGroupsChannelList) {
++ start = &startChannel;
++ current = &currentChannel;
++ numItems = &numItemsChannel;
++ } else if (state == esGroupsList) {
++ start = &startGroup;
++ current = &currentGroup;
++ numItems = &numItemsGroup;
++ } else
++ return;
++
++ if (*current == 0) {
++ dcExt->ClearList();
++ int itemsTotal = (state == esChannelList || state == esGroupsChannelList)?channellist.Count():((state == esGroupsList)?grouplist.Count():0);
++ *current = itemsTotal-1;
++ *start = max(0, itemsTotal - *numItems);
++ if (state == esChannelList || state == esGroupsChannelList)
++ DisplayChannelList(dcExt);
++ else if (state == esGroupsList)
++ DisplayGroupList(dcExt);
++ return;
++ }
++ int curRel = *current - *start;
++ if (curRel > 0) {
++ if (state == esChannelList || state == esGroupsChannelList) {
++ const cChannel *prev = channellist.Get(*current-1)->Channel();
++ dcExt->SetChannelList(channellist.Get(*current)->Channel(), curRel, false);
++ dcExt->SetChannelList(prev, curRel-1, true);
++ (*current)--;
++ return;
++ } else if (state = esGroupsList) {
++ cGroupListItem *prev = grouplist.Get(*current-1);
++ cGroupListItem *old = grouplist.Get(*current);
++ dcExt->SetGroupList(old->GroupName(), old->NumChannels(), curRel, false);
++ dcExt->SetGroupList(prev->GroupName(), prev->NumChannels(), curRel-1, true);
++ (*current)--;
++ return;
++ }
++ }
++ dcExt->ClearList();
++ (*current)--;
++ *start = max(0, *start-*numItems);
++
++ if (state == esChannelList || state == esGroupsChannelList)
++ DisplayChannelList(dcExt);
++ else if (state == esGroupsList)
++ DisplayGroupList(dcExt);
++}
++
++void cDisplayChannelExtended::CursorDown(cSkinDisplayChannelExtended *dcExt)
++{
++ int *start, *current, *numItems;
++ if (state == esChannelList || state == esGroupsChannelList) {
++ start = &startChannel;
++ current = &currentChannel;
++ numItems = &numItemsChannel;
++ } else if (state == esGroupsList) {
++ start = &startGroup;
++ current = &currentGroup;
++ numItems = &numItemsGroup;
++ } else
++ return;
++
++ int curRel = *current - *start;
++ if (curRel < *numItems - 1) {
++ if (state == esChannelList || state == esGroupsChannelList) {
++ cChannelListItem *next = channellist.Get(*current+1);
++ if (next) {
++ dcExt->SetChannelList(channellist.Get(*current)->Channel(), curRel, false);
++ dcExt->SetChannelList(next->Channel(), curRel+1, true);
++ (*current)++;
++ return;
++ }
++ } else if (state == esGroupsList) {
++ cGroupListItem *next = grouplist.Get(*current+1);
++ if (next) {
++ cGroupListItem *old = grouplist.Get(*current);
++ dcExt->SetGroupList(old->GroupName(), old->NumChannels(), curRel, false);
++ dcExt->SetGroupList(next->GroupName(), next->NumChannels(), curRel+1, true);
++ (*current)++;
++ return;
++ }
++ }
++ }
++ if (((state == esChannelList || state == esGroupsChannelList) && *current+1 == channellist.Count()) ||
++ (state == esGroupsList && *current+1 == grouplist.Count()))
++ *start = *current = 0;
++ else
++ *start = *current = *current+1;
++ dcExt->ClearList();
++
++ if (state == esChannelList || state == esGroupsChannelList)
++ DisplayChannelList(dcExt);
++ else if (state == esGroupsList)
++ DisplayGroupList(dcExt);
++}
++
++void cDisplayChannelExtended::DisplayChannelList(cSkinDisplayChannelExtended *dcExt)
++{
++ int index = 0;
++ for (cChannelListItem *c = channellist.Get(startChannel); c; c = channellist.Next(c)) {
++ dcExt->SetChannelList(c->Channel(), index, (startChannel + index == currentChannel) ? true : false);
++ if (++index == numItemsChannel)
++ break;
++ }
++}
++
++void cDisplayChannelExtended::DisplayGroupList(cSkinDisplayChannelExtended *dcExt)
++{
++ int index = 0;
++ for (cGroupListItem *g = grouplist.Get(startGroup); g; g = grouplist.Next(g)) {
++ dcExt->SetGroupList(g->GroupName(), g->NumChannels(), index, (startGroup + index == currentGroup) ? true : false);
++ if (++index == numItemsGroup)
++ break;
++ }
++}
++
++bool cDisplayChannelExtended::SwitchChannel(void)
++{
++ cChannel *newChannel = NULL;
++ if ( state == esChannelList ||
++ state == esChannelListInfo ||
++ state == esGroupsChannelList ||
++ state == esGroupsChannelListInfo ) {
++ cChannelListItem *li = channellist.Get(currentChannel);
++ if (li)
++ newChannel = li->Channel();
++ } else if (state == esGroupsList) {
++ cGroupListItem *item = grouplist.Get(currentGroup);
++ if (!item)
++ return false;
++ cChannel *cGroup = item->Channel();
++ for (cChannel *c = cGroup; c; c = Channels.Next(c))
++ if (!c->GroupSep()) {
++ newChannel = c;
++ break;
++ }
++ }
++ if (!newChannel || newChannel == channel)
++ return false;
++ SetTrackDescriptions(newChannel->Number()); // to make them immediately visible in the channel display
++ Channels.SwitchTo(newChannel->Number());
++ SetTrackDescriptions(newChannel->Number()); // switching the channel has cleared them
++ channel = newChannel;
++ return true;
++}
++
++cChannel *cDisplayChannelExtended::LastChannelSep(void)
++{
++ for (cChannel *c = Channels.Last(); c; c = Channels.Prev(c))
++ if (c->GroupSep())
++ return c;
++ return NULL;
++}
++
+ // --- cDisplayVolume --------------------------------------------------------
+
+ #define VOLUMETIMEOUT 1000 //ms
+diff -Naur vdr-2.2.0/menu.h vdr-2.2.0_zapcockpit/menu.h
+--- vdr-2.2.0/menu.h 2015-02-06 10:47:30.000000000 +0100
++++ vdr-2.2.0_zapcockpit/menu.h 2016-05-26 07:29:05.680117299 +0200
+@@ -115,30 +115,99 @@
+
+ class cDisplayChannel : public cOsdObject {
+ private:
+- cSkinDisplayChannel *displayChannel;
+ int group;
+ bool withInfo;
+- cTimeMs lastTime;
+- int number;
+ bool timeout;
+- int osdState;
+ const cPositioner *positioner;
+- cChannel *channel;
+ const cEvent *lastPresent;
+ const cEvent *lastFollowing;
+ static cDisplayChannel *currentDisplayChannel;
+- void DisplayChannel(void);
+- void DisplayInfo(void);
+ void Refresh(void);
+ cChannel *NextAvailableChannel(cChannel *Channel, int Direction);
++protected:
++ cSkinDisplayChannel *displayChannel;
++ cTimeMs lastTime;
++ int number;
++ cChannel *channel;
++ int osdState;
++ void DisplayChannel(void);
++ void DisplayInfo(void);
+ public:
+ cDisplayChannel(int Number, bool Switched);
+- cDisplayChannel(eKeys FirstKey);
++ cDisplayChannel(eKeys FirstKey, bool processKey = true);
+ virtual ~cDisplayChannel();
+ virtual eOSState ProcessKey(eKeys Key);
+ static bool IsOpen(void) { return currentDisplayChannel != NULL; }
+ };
+
++enum eExtendedState {
++ esInit = 0,
++ esDefault,
++ esChannelInfo,
++ esChannelList,
++ esChannelListInfo,
++ esGroupsList,
++ esGroupsChannelList,
++ esGroupsChannelListInfo
++ };
++
++class cChannelListItem : public cListObject {
++private:
++ cChannel *channel;
++public:
++ cChannelListItem(cChannel *Channel) { channel = Channel; };
++ virtual ~cChannelListItem(void) { };
++ cChannel *Channel(void) { return channel; }
++ };
++
++class cGroupListItem : public cListObject {
++private:
++ cChannel *channel;
++ int numChannels;
++public:
++ cGroupListItem(cChannel *Channel) { channel = Channel; numChannels = 0; };
++ virtual ~cGroupListItem(void) { };
++ const char *GroupName(void) { return channel->Name(); }
++ void SetNumChannels(int NumChannels) { numChannels = NumChannels; };
++ int NumChannels(void) { return numChannels; };
++ cChannel *Channel(void) { return channel; }
++ };
++
++class cDisplayChannelExtended : public cDisplayChannel {
++private:
++ eExtendedState state;
++ int numItemsChannel, startChannel, currentChannel;
++ int numItemsGroup, startGroup, currentGroup;
++ cList<cChannelListItem> channellist;
++ cList<cGroupListItem> grouplist;
++ void StateNumberKey(int key, cSkinDisplayChannelExtended *dcExt);
++ bool StateInit(int key, cSkinDisplayChannelExtended *dcExt);
++ bool StateDefault(int key, cSkinDisplayChannelExtended *dcExt);
++ bool StateChannelInfo(int key, cSkinDisplayChannelExtended *dcExt);
++ bool StateChannelList(int key, cSkinDisplayChannelExtended *dcExt);
++ bool StateGroupList(int key, cSkinDisplayChannelExtended *dcExt);
++ bool StateGroupChannelList(int key, cSkinDisplayChannelExtended *dcExt);
++ void InitChannelList(cSkinDisplayChannelExtended *dcExt);
++ void SetChannelList(void);
++ int GetIndexChannel(cChannel *c);
++ void InitGroupList(cSkinDisplayChannelExtended *dcExt);
++ void SetGroupList(void);
++ int GetIndexGroup(cChannel *c);
++ void InitGroupChannelList(cSkinDisplayChannelExtended *dcExt);
++ void SetGroupChannelList(cSkinDisplayChannelExtended *dcExt);
++ void CursorUp(cSkinDisplayChannelExtended *dcExt);
++ void CursorDown(cSkinDisplayChannelExtended *dcExt);
++ void DisplayChannelList(cSkinDisplayChannelExtended *dcExt);
++ void DisplayGroupList(cSkinDisplayChannelExtended *dcExt);
++ bool SwitchChannel(void);
++ cChannel *LastChannelSep(void);
++public:
++ cDisplayChannelExtended(int Number, bool Switched);
++ cDisplayChannelExtended(eKeys FirstKey);
++ virtual ~cDisplayChannelExtended();
++ virtual eOSState ProcessKey(eKeys Key);
++ };
++
+ class cDisplayVolume : public cOsdObject {
+ private:
+ cSkinDisplayVolume *displayVolume;
+diff -Naur vdr-2.2.0/po/de_DE.po vdr-2.2.0_zapcockpit/po/de_DE.po
+--- vdr-2.2.0/po/de_DE.po 2015-02-19 10:12:22.401201125 +0100
++++ vdr-2.2.0_zapcockpit/po/de_DE.po 2016-05-26 07:29:05.836117304 +0200
+@@ -8,7 +8,7 @@
+ msgstr ""
+ "Project-Id-Version: VDR 2.2.0\n"
+ "Report-Msgid-Bugs-To: <vdr-bugs@tvdr.de>\n"
+-"POT-Creation-Date: 2015-02-10 13:40+0100\n"
++"POT-Creation-Date: 2016-05-22 09:17+0200\n"
+ "PO-Revision-Date: 2015-02-10 13:45+0100\n"
+ "Last-Translator: Klaus Schmidinger <vdr@tvdr.de>\n"
+ "Language-Team: German <vdr@linuxtv.org>\n"
+@@ -1284,6 +1284,18 @@
+ msgid "Setup.Miscellaneous$Channel entry timeout (ms)"
+ msgstr "Zeitlimit für Kanaleingabe (ms)"
+
++msgid "Setup.Miscellaneous$Zapcockpit: 2nd ok shows info"
++msgstr "Zapcockpit: zweites OK zeigt Info"
++
++msgid "Setup.Miscellaneous$Zapcockpit: Use extended channel group display"
++msgstr "Zapcockpit: Erweiterte Kanalgruppen Anzeige benutzen"
++
++msgid "Setup.Miscellaneous$Zapcockpit: Use channel hints"
++msgstr "Zapcockpit: Kanalhinweise benutzen"
++
++msgid "Setup.Miscellaneous$Zapcockpit: Hide last channel group"
++msgstr "Zapcockpit: letzte Kanalgruppe ausblenden"
++
+ msgid "Setup.Miscellaneous$Remote control repeat delay (ms)"
+ msgstr "Fernbedienung Wiederholverzögerung (ms)"
+
+diff -Naur vdr-2.2.0/skins.c vdr-2.2.0_zapcockpit/skins.c
+--- vdr-2.2.0/skins.c 2013-08-18 14:07:22.000000000 +0200
++++ vdr-2.2.0_zapcockpit/skins.c 2016-05-26 07:29:05.788117303 +0200
+@@ -79,6 +79,13 @@
+ SetMessage(mtInfo, cString::sprintf(tr("Moving dish to %.1f..."), double(positioner->TargetLongitude()) / 10));
+ }
+
++cSkinDisplayChannelExtended::cSkinDisplayChannelExtended(void)
++: cSkinDisplayChannel()
++{
++
++}
++
++
+ // --- cSkinDisplayMenu ------------------------------------------------------
+
+ cSkinDisplayMenu::cSkinDisplayMenu(void)
+diff -Naur vdr-2.2.0/skins.h vdr-2.2.0_zapcockpit/skins.h
+--- vdr-2.2.0/skins.h 2015-01-15 11:45:47.000000000 +0100
++++ vdr-2.2.0_zapcockpit/skins.h 2016-05-26 07:29:05.740117301 +0200
+@@ -88,6 +88,33 @@
+ */
+ };
+
++#define USE_ZAPCOCKPIT 1
++
++enum eDisplaychannelView {
++ dcDefault = 0,
++ dcChannelInfo,
++ dcChannelList,
++ dcChannelListInfo,
++ dcGroupsList,
++ dcGroupsChannelList,
++ dcGroupsChannelListInfo
++ };
++
++class cSkinDisplayChannelExtended : public cSkinDisplayChannel {
++private:
++public:
++ cSkinDisplayChannelExtended(void);
++ virtual void SetViewType(eDisplaychannelView ViewType) = 0;
++ virtual int MaxItems(void) = 0;
++ virtual void SetChannelInfo(const cChannel *Channel) = 0;
++ virtual void SetChannelList(const cChannel *Channel, int Index, bool Current) = 0;
++ virtual void SetGroupList(const char *Group, int NumChannels, int Index, bool Current) = 0;
++ virtual void SetGroupChannelList(const cChannel *Channel, int Index, bool Current) = 0;
++ virtual void ClearList(void) = 0;
++ virtual void SetNumChannelHints(int Num) = 0;
++ virtual void SetChannelHint(const cChannel *Channel) = 0;
++};
++
+ enum eMenuCategory {
+ mcUndefined = -1,
+ mcUnknown = 0,
+diff -Naur vdr-2.2.0/vdr.c vdr-2.2.0_zapcockpit/vdr.c
+--- vdr-2.2.0/vdr.c 2015-02-10 15:13:12.000000000 +0100
++++ vdr-2.2.0_zapcockpit/vdr.c 2016-05-26 07:29:05.676117299 +0200
+@@ -996,7 +996,7 @@
+ // Channel display:
+ if (!EITScanner.Active() && cDevice::CurrentChannel() != LastChannel) {
+ if (!Menu)
+- Menu = new cDisplayChannel(cDevice::CurrentChannel(), LastChannel >= 0);
++ Menu = new cDisplayChannelExtended(cDevice::CurrentChannel(), LastChannel >= 0);
+ LastChannel = cDevice::CurrentChannel();
+ LastChannelChanged = Now;
+ }
+@@ -1174,8 +1174,10 @@
+ case kChanUp:
+ case kChanDn|k_Repeat:
+ case kChanDn:
+- if (!Interact)
+- Menu = new cDisplayChannel(NORMALKEY(key));
++ if (!Interact) {
++ Menu = new cDisplayChannelExtended(NORMALKEY(key));
++ Menu->ProcessKey(NORMALKEY(key));
++ }
+ else if (cDisplayChannel::IsOpen() || cControl::Control()) {
+ Interact->ProcessKey(key);
+ continue;
+@@ -1368,7 +1370,8 @@
+ case kUp:
+ case kDown|k_Repeat:
+ case kDown:
+- Menu = new cDisplayChannel(NORMALKEY(key));
++ Menu = new cDisplayChannelExtended(NORMALKEY(key));
++ Menu->ProcessKey(NORMALKEY(key));
+ break;
+ // Viewing Control:
+ case kOk: LastChannel = -1; break; // forces channel display
diff --git a/skindesigner.c b/skindesigner.c
index 79b3829..2c64ee7 100644
--- a/skindesigner.c
+++ b/skindesigner.c
@@ -20,7 +20,7 @@
#endif
-static const char *VERSION = "1.0.3";
+static const char *VERSION = "1.0.2";
static const char *DESCRIPTION = trNOOP("Skin Designer");
class cPluginSkinDesigner : public cPlugin, public skindesignerapi::SkindesignerAPI {
@@ -158,6 +158,9 @@ bool cPluginSkinDesigner::Start(void) {
if (!skinAvailable) {
esyslog("skindesigner: no skins found! Using default Skin LCARS!");
}
+#ifdef USE_ZAPCOCKPIT
+ dsyslog("skindesigner: zapcockpit patch available");
+#endif
return true;
}
diff --git a/skins/estuary4vdr/setup.xml b/skins/estuary4vdr/setup.xml
index 7d5a374..cde1826 100644
--- a/skins/estuary4vdr/setup.xml
+++ b/skins/estuary4vdr/setup.xml
@@ -14,6 +14,34 @@
<parameter type="int" name="startstopfontsize" min="0" max="100" displaytext="{tr(startstopfontsize)}">40</parameter>
<parameter type="int" name="channelnamefontsize" min="0" max="100" displaytext="{tr(channelnamefontsize)}">75</parameter>
<parameter type="bool" name="scrollepg" displaytext="{tr(scrollepgtext)}">1</parameter>
+ <parameter type="separator" name="sepzapcockpit" displaytext="{tr(sepzapcockpit)}"/>
+ <parameter type="int" name="fadetimezapcockpit" displaytext="{tr(fadetimezapcockpit)}">0</parameter>
+ <parameter type="int" name="shifttimezapcockpit" displaytext="{tr(shifttimezapcockpit)}">200</parameter>
+ <parameter type="separator" name="sepzapcockpitdetail" displaytext="{tr(sepzapcockpitdetail)}"/>
+ <parameter type="int" name="zapdetaildatetimefs" min="0" max="100" displaytext="{tr(zapdetaildatetimefs)}">80</parameter>
+ <parameter type="int" name="zapdetailheaderfs" min="0" max="100" displaytext="{tr(zapdetailheaderfs)}">80</parameter>
+ <parameter type="int" name="zapdetailshorttextfs" min="0" max="100" displaytext="{tr(zapdetailshorttextfs)}">80</parameter>
+ <parameter type="int" name="zapdetaildescfs" min="0" max="100" displaytext="{tr(zapdetaildescfs)}">6</parameter>
+ <parameter type="separator" name="sepzapcockpitcl" displaytext="{tr(sepzapcockpitcl)}"/>
+ <parameter type="int" name="zapclchannelfs" min="0" max="100" displaytext="{tr(zapclchannelfs)}">38</parameter>
+ <parameter type="int" name="zapclchannely" min="0" max="100" displaytext="{tr(zapclchannely)}">3</parameter>
+ <parameter type="int" name="zapclpresentfs" min="0" max="100" displaytext="{tr(zapclpresentfs)}">38</parameter>
+ <parameter type="int" name="zapclpresenty" min="0" max="100" displaytext="{tr(zapclpresenty)}">35</parameter>
+ <parameter type="int" name="zapclnextfs" min="0" max="100" displaytext="{tr(zapclnextfs)}">28</parameter>
+ <parameter type="int" name="zapclnexty" min="0" max="100" displaytext="{tr(zapclnexty)}">70</parameter>
+ <parameter type="int" name="zapcldetaildatetimefs" min="0" max="100" displaytext="{tr(zapcldetaildatetimefs)}">80</parameter>
+ <parameter type="int" name="zapcldetailheaderfs" min="0" max="100" displaytext="{tr(zapcldetailheaderfs)}">80</parameter>
+ <parameter type="int" name="zapcldetailshorttextfs" min="0" max="100" displaytext="{tr(zapcldetailshorttextfs)}">80</parameter>
+ <parameter type="int" name="zapcldetaildescfs" min="0" max="100" displaytext="{tr(zapcldetaildescfs)}">4</parameter>
+ <parameter type="separator" name="sepzapcockpitgl" displaytext="{tr(sepzapcockpitgl)}"/>
+ <parameter type="int" name="zapglgroupfs" min="0" max="100" displaytext="{tr(zapglgroupfs)}">40</parameter>
+ <parameter type="int" name="zapgcldetaildatetimefs" min="0" max="100" displaytext="{tr(zapgcldetaildatetimefs)}">80</parameter>
+ <parameter type="int" name="zapgcldetailheaderfs" min="0" max="100" displaytext="{tr(zapgcldetailheaderfs)}">80</parameter>
+ <parameter type="int" name="zapgcldetailshorttextfs" min="0" max="100" displaytext="{tr(zapgcldetailshorttextfs)}">80</parameter>
+ <parameter type="int" name="zapgcldetaildescfs" min="0" max="100" displaytext="{tr(zapgcldetaildescfs)}">4</parameter>
+ <parameter type="separator" name="sepzapcockpitchannelhint" displaytext="{tr(sepzapcockpitchannelhint)}"/>
+ <parameter type="int" name="zapchannelhintsheight" min="0" max="100" displaytext="{tr(zapchannelhintsheight)}">30</parameter>
+ <parameter type="int" name="zapchannelhintswidth" min="0" max="100" displaytext="{tr(zapchannelhintswidth)}">30</parameter>
</submenu>
<submenu name="subdisplayreplay" displaytext="{tr(subdisplayreplay)}">
<parameter type="int" name="replaytitlesize" min="0" max="100" displaytext="{tr(replaytitlesize)}">80</parameter>
@@ -242,6 +270,118 @@
<trans lang="en_EN">Scroll EPG</trans>
<trans lang="de_DE">EGP scrollen</trans>
</token>
+ <token name="tr(sepzapcockpit)">
+ <trans lang="en_EN">Settings Zapcockpit</trans>
+ <trans lang="de_DE">Einstellungen Zapcockpit</trans>
+ </token>
+ <token name="tr(sepzapcockpitdetail)">
+ <trans lang="en_EN">Settings Zapcockpit detail view</trans>
+ <trans lang="de_DE">Einstellungen Zapcockpit Detailansicht</trans>
+ </token>
+ <token name="tr(sepzapcockpitcl)">
+ <trans lang="en_EN">Settings Zapcockpit channel list</trans>
+ <trans lang="de_DE">Einstellungen Zapcockpit Kanalliste</trans>
+ </token>
+ <token name="tr(sepzapcockpitgl)">
+ <trans lang="en_EN">Settings Zapcockpit channel groups list</trans>
+ <trans lang="de_DE">Einstellungen Kanalgruppen Liste</trans>
+ </token>
+ <token name="tr(sepzapcockpitchannelhint)">
+ <trans lang="en_EN">Settings Zapcockpit channel hints</trans>
+ <trans lang="de_DE">Einstellungen Zapcockpit Kanal Hinweise</trans>
+ </token>
+ <token name="tr(fadetimezapcockpit)">
+ <trans lang="en_EN">Fade time for zapcockpit elements [ms]</trans>
+ <trans lang="de_DE">Einblendzeit für Zapcockpit Elemente [ms]</trans>
+ </token>
+ <token name="tr(shifttimezapcockpit)">
+ <trans lang="en_EN">Shift time for zapcockpit elements [ms]</trans>
+ <trans lang="de_DE">Einfahrzeit für Zapcockpit Elemente [ms]</trans>
+ </token>
+ <token name="tr(zapclchannelfs)">
+ <trans lang="en_EN">Font size channel</trans>
+ <trans lang="de_DE">Schriftgröße Kanal</trans>
+ </token>
+ <token name="tr(zapclchannely)">
+ <trans lang="en_EN">Vertical position channel</trans>
+ <trans lang="de_DE">Vertikale Position Kanal</trans>
+ </token>
+ <token name="tr(zapclpresentfs)">
+ <trans lang="en_EN">Font size present event</trans>
+ <trans lang="de_DE">Schriftgröße aktuelle Sendung</trans>
+ </token>
+ <token name="tr(zapclpresenty)">
+ <trans lang="en_EN">Vertical position present event</trans>
+ <trans lang="de_DE">Vertikale Position aktuelle Sendung</trans>
+ </token>
+ <token name="tr(zapclnextfs)">
+ <trans lang="en_EN">Font size next event</trans>
+ <trans lang="de_DE">Schriftgröße nächste Sendung</trans>
+ </token>
+ <token name="tr(zapclnexty)">
+ <trans lang="en_EN">Vertical position next event</trans>
+ <trans lang="de_DE">Vertikale Position nächste Sendung</trans>
+ </token>
+ <token name="tr(zapglgroupfs)">
+ <trans lang="en_EN">Font size groups in channel group list</trans>
+ <trans lang="de_DE">Schriftgröße Gruppe in Kanalgruppen Liste</trans>
+ </token>
+ <token name="tr(zapdetaildatetimefs)">
+ <trans lang="en_EN">Font size time</trans>
+ <trans lang="de_DE">Schriftgröße Zeit</trans>
+ </token>
+ <token name="tr(zapdetailheaderfs)">
+ <trans lang="en_EN">Font size title</trans>
+ <trans lang="de_DE">Schriftgröße Titel</trans>
+ </token>
+ <token name="tr(zapdetailshorttextfs)">
+ <trans lang="en_EN">Font size short text</trans>
+ <trans lang="de_DE">Schriftgröße Kurztext</trans>
+ </token>
+ <token name="tr(zapdetaildescfs)">
+ <trans lang="en_EN">Font size description</trans>
+ <trans lang="de_DE">Schriftgröße Beschreibung</trans>
+ </token>
+ <token name="tr(zapcldetaildatetimefs)">
+ <trans lang="en_EN">Font size time in channel list detail view</trans>
+ <trans lang="de_DE">Schriftgröße Zeit in Detailansicht Kanalliste</trans>
+ </token>
+ <token name="tr(zapcldetailheaderfs)">
+ <trans lang="en_EN">Font size title in channel list detail view</trans>
+ <trans lang="de_DE">Schriftgröße Titel in Detailansicht Kanalliste</trans>
+ </token>
+ <token name="tr(zapcldetailshorttextfs)">
+ <trans lang="en_EN">Font size short text in channel list detail view</trans>
+ <trans lang="de_DE">Schriftgröße Kurztext in Detailansicht Kanalliste</trans>
+ </token>
+ <token name="tr(zapcldetaildescfs)">
+ <trans lang="en_EN">Font size description in channel list detail view</trans>
+ <trans lang="de_DE">Schriftgröße Beschreibung in Detailansicht Kanalliste</trans>
+ </token>
+ <token name="tr(zapgcldetaildatetimefs)">
+ <trans lang="en_EN">Font size time in channel group list detail view</trans>
+ <trans lang="de_DE">Schriftgröße Zeit in Detailansicht Kanalgruppen Liste</trans>
+ </token>
+ <token name="tr(zapgcldetailheaderfs)">
+ <trans lang="en_EN">Font size title in channel group list detail view</trans>
+ <trans lang="de_DE">Schriftgröße Titel in Detailansicht Kanalgruppen Liste</trans>
+ </token>
+ <token name="tr(zapgcldetailshorttextfs)">
+ <trans lang="en_EN">Font size short text in channel group list detail view</trans>
+ <trans lang="de_DE">Schriftgröße Kurztext in Detailansicht Kanalgruppen Liste</trans>
+ </token>
+ <token name="tr(zapgcldetaildescfs)">
+ <trans lang="en_EN">Font size description in channel group list detail view</trans>
+ <trans lang="de_DE">Schriftgröße Beschreibung in Detailansicht Kanalgruppen Liste</trans>
+ </token>
+ <token name="tr(zapchannelhintsheight)">
+ <trans lang="en_EN">Height channel hints (% of screen height)</trans>
+ <trans lang="de_DE">Höhe Kanal Hinweise (% der Bildschirmhöhe)</trans>
+ </token>
+ <token name="tr(zapchannelhintswidth)">
+ <trans lang="en_EN">Width channel hints (% of screen width)</trans>
+ <trans lang="de_DE">Breite Kanal Hinweise (% der Bildschirmbreite)</trans>
+ </token>
<!-- recording display -->
<token name="tr(replaytitlesize)">
<trans lang="en_EN">Font size title</trans>
diff --git a/skins/estuary4vdr/svgtemplates/icons/folder.svg b/skins/estuary4vdr/svgtemplates/icons/folder.svg
new file mode 100644
index 0000000..753999a
--- /dev/null
+++ b/skins/estuary4vdr/svgtemplates/icons/folder.svg
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Capa_1"
+ x="0px"
+ y="0px"
+ width="475.082px"
+ height="475.082px"
+ viewBox="0 0 475.082 475.082"
+ style="enable-background:new 0 0 475.082 475.082;"
+ xml:space="preserve"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="folder.svg"><metadata
+ id="metadata41"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs39" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ id="namedview37"
+ showgrid="false"
+ inkscape:zoom="0.49675635"
+ inkscape:cx="-13.084886"
+ inkscape:cy="237.541"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Capa_1" /><g
+ id="g3"
+ style="fill:#{sdcol(icon)};fill-opacity:1"><path
+ d="M456.239,128.475c-12.56-12.562-27.597-18.842-45.11-18.842h-191.86v-9.136c0-17.511-6.283-32.548-18.843-45.107 c-12.562-12.562-27.6-18.846-45.111-18.846H63.953c-17.515,0-32.551,6.283-45.111,18.846C6.28,67.949,0,82.986,0,100.497v274.088 c0,17.508,6.28,32.545,18.842,45.104c12.562,12.565,27.6,18.849,45.111,18.849h347.175c17.514,0,32.551-6.283,45.11-18.849 c12.566-12.56,18.843-27.597,18.843-45.104V173.59C475.082,156.078,468.805,141.042,456.239,128.475z M438.536,374.585 c0,7.611-2.662,14.093-7.99,19.417c-5.328,5.325-11.8,7.987-19.417,7.987H63.953c-7.614,0-14.084-2.662-19.414-7.987 c-5.33-5.324-7.993-11.806-7.993-19.417V100.501c0-7.611,2.663-14.084,7.993-19.414c5.326-5.327,11.799-7.993,19.414-7.993h91.365 c7.614,0,14.087,2.663,19.417,7.993c5.327,5.33,7.993,11.803,7.993,19.414v18.274c0,7.616,2.664,14.083,7.994,19.414 c5.327,5.327,11.798,7.994,19.414,7.994h200.993c7.617,0,14.089,2.666,19.417,7.993c5.328,5.326,7.99,11.799,7.99,19.414V374.585 L438.536,374.585z"
+ id="path5"
+ style="fill:#{sdcol(icon)};fill-opacity:1" /></g><g
+ id="g7" /><g
+ id="g9" /><g
+ id="g11" /><g
+ id="g13" /><g
+ id="g15" /><g
+ id="g17" /><g
+ id="g19" /><g
+ id="g21" /><g
+ id="g23" /><g
+ id="g25" /><g
+ id="g27" /><g
+ id="g29" /><g
+ id="g31" /><g
+ id="g33" /><g
+ id="g35" /></svg> \ No newline at end of file
diff --git a/skins/estuary4vdr/svgtemplates/icons/folder_active.svg b/skins/estuary4vdr/svgtemplates/icons/folder_active.svg
new file mode 100644
index 0000000..72dc8b5
--- /dev/null
+++ b/skins/estuary4vdr/svgtemplates/icons/folder_active.svg
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Capa_1"
+ x="0px"
+ y="0px"
+ width="475.082px"
+ height="475.082px"
+ viewBox="0 0 475.082 475.082"
+ style="enable-background:new 0 0 475.082 475.082;"
+ xml:space="preserve"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="folder.svg"><metadata
+ id="metadata41"><rdf:RDF><cc:Work
+ rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
+ id="defs39" /><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1920"
+ inkscape:window-height="1017"
+ id="namedview37"
+ showgrid="false"
+ inkscape:zoom="0.49675635"
+ inkscape:cx="-13.084886"
+ inkscape:cy="237.541"
+ inkscape:window-x="-8"
+ inkscape:window-y="-8"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="Capa_1" /><g
+ id="g3"
+ style="fill:#{sdcol(iconactive)};fill-opacity:1"><path
+ d="M456.239,128.475c-12.56-12.562-27.597-18.842-45.11-18.842h-191.86v-9.136c0-17.511-6.283-32.548-18.843-45.107 c-12.562-12.562-27.6-18.846-45.111-18.846H63.953c-17.515,0-32.551,6.283-45.111,18.846C6.28,67.949,0,82.986,0,100.497v274.088 c0,17.508,6.28,32.545,18.842,45.104c12.562,12.565,27.6,18.849,45.111,18.849h347.175c17.514,0,32.551-6.283,45.11-18.849 c12.566-12.56,18.843-27.597,18.843-45.104V173.59C475.082,156.078,468.805,141.042,456.239,128.475z M438.536,374.585 c0,7.611-2.662,14.093-7.99,19.417c-5.328,5.325-11.8,7.987-19.417,7.987H63.953c-7.614,0-14.084-2.662-19.414-7.987 c-5.33-5.324-7.993-11.806-7.993-19.417V100.501c0-7.611,2.663-14.084,7.993-19.414c5.326-5.327,11.799-7.993,19.414-7.993h91.365 c7.614,0,14.087,2.663,19.417,7.993c5.327,5.33,7.993,11.803,7.993,19.414v18.274c0,7.616,2.664,14.083,7.994,19.414 c5.327,5.327,11.798,7.994,19.414,7.994h200.993c7.617,0,14.089,2.666,19.417,7.993c5.328,5.326,7.99,11.799,7.99,19.414V374.585 L438.536,374.585z"
+ id="path5"
+ style="fill:#{sdcol(iconactive)};fill-opacity:1" /></g><g
+ id="g7" /><g
+ id="g9" /><g
+ id="g11" /><g
+ id="g13" /><g
+ id="g15" /><g
+ id="g17" /><g
+ id="g19" /><g
+ id="g21" /><g
+ id="g23" /><g
+ id="g25" /><g
+ id="g27" /><g
+ id="g29" /><g
+ id="g31" /><g
+ id="g33" /><g
+ id="g35" /></svg> \ No newline at end of file
diff --git a/skins/estuary4vdr/themes/default/theme.xml b/skins/estuary4vdr/themes/default/theme.xml
index f6eda58..0119815 100644
--- a/skins/estuary4vdr/themes/default/theme.xml
+++ b/skins/estuary4vdr/themes/default/theme.xml
@@ -11,6 +11,7 @@
<color name="menubackactive">FF12B2E7</color>
<color name="menubackactivedark">FF0C4759</color>
<color name="menumainheader">FF000000</color>
+ <color name="channelback">B0000000</color>
<color name="messageback">D0000000</color>
<color name="replayback">B0000000</color>
<color name="fontdefault">FFFFFFFF</color>
diff --git a/skins/estuary4vdr/xmlfiles/displaychannel.xml b/skins/estuary4vdr/xmlfiles/displaychannel.xml
index a91e023..9fb46f9 100644
--- a/skins/estuary4vdr/xmlfiles/displaychannel.xml
+++ b/skins/estuary4vdr/xmlfiles/displaychannel.xml
@@ -132,6 +132,182 @@
</area>
</scrapercontent>
+ <channelhints>
+ <area background="true" x="0" y="{areaheight}*0.75 - {numhints}*{areaheight}*{zapchannelhintsheight}/1000 + 1" width="{zapchannelhintswidth}*{areawidth}/100" height="{numhints}*{areaheight}*{zapchannelhintsheight}/1000" layer="1">
+ <fill color="{channelback}" />
+ </area>
+ <area x="0" y="{areaheight}*0.75 - {numhints}*{areaheight}*{zapchannelhintsheight}/1000" width="{zapchannelhintswidth}*{areawidth}/100" height="{numhints}*{areaheight}*{zapchannelhintsheight}/1000" layer="2">
+ <loop name="hints" x="2%" y="0" width="96%%" orientation="vertical" columnwidth="100%" rowheight="{areaheight}/{numhints}" overflow="cut" >
+ <drawimage condition="{hints[channellogoexists]}" imagetype="channellogo" path="{hints[channelid]}" width="{rowheight}*1.5" height="{rowheight}" x="0" valign="center" />
+ <drawtext x="{rowheight}*2" valign="center" width="{columnwidth} - {rowheight}*2.5" font="{regular}" fontsize="{rowheight}*0.8" color="{fontdefault}" text="{hints[channelnumber]}: {hints[channelname]}" />
+ </loop>
+ </area>
+ </channelhints>
+
+ <channeldetail clearondisplay="scrapercontent">
+ <area background="true" x="5%" y="5%" width="90%" height="65%" layer="1">
+ <fill color="{channelback}" />
+ </area>
+ <area x="7%" y="7%" width="41%" height="5%" layer="2">
+ <drawtext x="0" valign="center" fontsize="{zapdetaildatetimefs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currentstart} - {currentstop}" />
+ </area>
+ <areascroll condition="{ismovie}||{isseries}" scrollelement="title" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="7%" y="10%" width="41%" height="7%" layer="3">
+ <drawtext name="title" x="0" valign="center" fontsize="{zapdetailheaderfs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currenttitle}" />
+ </areascroll>
+ <areascroll condition="{ismovie}||{isseries}" scrollelement="shorttext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="7%" y="15%" width="41%" height="6%" layer="3">
+ <drawtext name="shorttext" x="0" valign="center" fontsize="{zapdetailshorttextfs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currentshorttext}" />
+ </areascroll>
+ <areascroll condition="{ismovie}||{isseries}" orientation="vertical" scrollelement="desc" mode="forthandback" delay="5000" scrollspeed="medium" x="7%" y="21%" width="41%" height="47%" layer="2">
+ <drawtextbox name="desc" x="0" y="0" width="96%" font="{regular}" fontsize="{zapdetaildescfs}*{areaheight}/100" color="{fontdefault}" text="{currentdescription}" />
+ </areascroll>
+ <area condition="{ismovie}" x="52%" y="7%" width="41%" height="30%" layer="1">
+ <drawimage imagetype="image" path="{seriesposter1path}" align="center" valign="center" width="100%" height="100%" />
+ </area>
+ <area condition="{isseries}" x="52%" y="7%" width="41%" height="30%" layer="1">
+ <drawimage imagetype="image" path="{seriesbanner1path}" align="center" valign="center" width="100%" height="100%" />
+ </area>
+ <areascroll condition="{ismovie}||{isseries}" orientation="vertical" scrollelement="actors" mode="forthandback" delay="5000" scrollspeed="medium" x="52%" y="39%" width="41%" height="30%" layer="2">
+ <loop name="actors" x="0" y="0" width="100%" orientation="horizontal" columnwidth="{areawidth}/5" rowheight="{areawidth}/5*1.5" overflow="linewrap" >
+ <drawimage name="thumb" imagetype="image" path="{actors[thumb]}" x="10" y="0" width="{columnwidth}-20" height="{columnwidth} * {actors[thumbheight]} / {actors[thumbwidth]} - 40 * {actors[thumbheight]} / {actors[thumbwidth]}"/>
+ <drawtext align="center" y="{height(thumb)} + 10" width="{columnwidth}" name="actorname" font="{regular}" fontsize="6%" color="{fontdefault}" text="{actors[name]}" />
+ <drawtext align="center" y="{height(thumb)} + 10 + {height(actorname)}" width="{columnwidth}" font="{regular}" fontsize="6%" color="{fontdefault}" text="{actors[role]}" />
+ </loop>
+ </areascroll>
+ <areascroll condition="not{ismovie}++not{isseries}" scrollelement="title" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="7%" y="10%" width="86%" height="7%" layer="3">
+ <drawtext name="title" x="0" valign="center" fontsize="{zapdetailheaderfs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currenttitle}" />
+ </areascroll>
+ <areascroll condition="not{ismovie}++not{isseries}" scrollelement="shorttext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="7%" y="15%" width="86%" height="6%" layer="3">
+ <drawtext name="shorttext" x="0" valign="center" fontsize="{zapdetailshorttextfs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currentshorttext}" />
+ </areascroll>
+ <areascroll condition="not{ismovie}++not{isseries}" orientation="vertical" scrollelement="desc" mode="forthandback" delay="5000" scrollspeed="medium" x="7%" y="21%" width="86%" height="47%" layer="2">
+ <drawtextbox name="desc" x="0" y="0" width="96%" font="{regular}" fontsize="{zapdetaildescfs}*{areaheight}/100" color="{fontdefault}" text="{currentdescription}" />
+ </areascroll>
+ </channeldetail>
+
+ <channellistback clearondisplay="all" fadetime="{fadetimezapcockpit}" shifttime="{shifttimezapcockpit}" shiftmode="slowed" shifttype="left">
+ <area x="0" y="0" width="30%" height="100%" layer="3">
+ <fill color="{channelback}" />
+ </area>
+ </channellistback>
+
+ <channellist x="0" y="0" orientation="vertical" width="30%" height="100%" align="center" numlistelements="16" fadetime="{fadetimezapcockpit}" shifttime="{shifttimezapcockpit}" shiftmode="slowed" shifttype="left">
+ <listelement>
+ <area x="0" width="100%" layer="4">
+ <drawrectangle condition="not{current}" x="0" y="0" width="100%" height="100%" color="{menuback}" />
+ <drawrectangle condition="not{current}" x="0" y="{areaheight}-1" width="100%" height="1" color="{menubackline}" />
+ <drawrectangle condition="{current}" x="0" y="0" width="100%" height="100%" color="{menubackactive}" />
+ </area>
+ <area x="1%" width="25%" layer="5">
+ <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="0" width="100%" height="100%" valign="center" />
+ </area>
+ <area condition="not{current}" x="26%" width="73%" layer="4">
+ <drawtext x="0" y="{zapclchannely}*{areaheight}/100" font="{regular}" fontsize="{zapclchannelfs}*{areaheight}/100" color="{fontdefault}" text="{number} {name}" />
+ <drawtext x="0" y="{zapclpresenty}*{areaheight}/100" font="{regular}" fontsize="{zapclpresentfs}*{areaheight}/100" color="{fontdefault}" text="+{presenteventremaining}min: {presenteventtitle}" />
+ <drawtext x="0" y="{zapclnexty}*{areaheight}/100" font="{regular}" fontsize="{zapclnextfs}*{areaheight}/100" color="{fontdefault}" text="{nexteventstart} {nexteventstop}: {nexteventtitle}" />
+ </area>
+ <area condition="{current}" x="26%" width="73%" layer="4">
+ <drawtext x="0" y="{zapclchannely}*{areaheight}/100" font="{regular}" fontsize="{zapclchannelfs}*{areaheight}/100" color="{fontmenuactive}" text="{number} {name}" />
+ <drawtext x="0" y="{zapclpresenty}*{areaheight}/100" font="{regular}" fontsize="{zapclpresentfs}*{areaheight}/100" color="{fontmenuactive}" text="+{presenteventremaining}min: {presenteventtitle}" />
+ <drawtext x="0" y="{zapclnexty}*{areaheight}/100" font="{regular}" fontsize="{zapclnextfs}*{areaheight}/100" color="{fontmenuactive}" text="{nexteventstart} {nexteventstop}: {nexteventtitle}" />
+ </area>
+ </listelement>
+ </channellist>
+
+ <channellistdetail fadetime="{fadetimezapcockpit}" shifttime="{shifttimezapcockpit}" shiftmode="slowed" startx="{areawidth}*0.3 - {areawidth}*0.6" starty="5%">
+ <area x="30%" y="5%" width="66%" height="90%" layer="1">
+ <fill color="{channelback}" />
+ </area>
+ <area x="32%" y="6%" width="62%" height="5%" layer="2">
+ <drawtext x="0" valign="center" fontsize="{zapcldetaildatetimefs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currentstart} - {currentstop}" />
+ </area>
+ <areascroll scrollelement="title" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="32%" y="10%" width="62%" height="7%" layer="3">
+ <drawtext name="title" x="0" valign="center" fontsize="{zapcldetailheaderfs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currenttitle}" />
+ </areascroll>
+ <areascroll scrollelement="shorttext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="32%" y="16%" width="62%" height="6%" layer="3">
+ <drawtext name="shorttext" x="0" valign="center" fontsize="{zapcldetailshorttextfs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currentshorttext}" />
+ </areascroll>
+ <areascroll orientation="vertical" scrollelement="desc" mode="forthandback" delay="5000" scrollspeed="medium" x="32%" y="22%" width="62%" height="71%" layer="2">
+ <drawtextbox name="desc" x="0" y="0" width="100%" font="{regular}" fontsize="{zapcldetaildescfs}*{areaheight}/100" color="{fontdefault}" text="{currentdescription}" />
+ </areascroll>
+ </channellistdetail>
+
+ <grouplistback fadetime="{fadetimezapcockpit}" shifttime="{shifttimezapcockpit}" shiftmode="slowed" shifttype="right" clearondisplay="all">
+ <area x="70%" y="0" width="30%" height="100%" layer="4">
+ <fill color="{channelback}" />
+ </area>
+ </grouplistback>
+
+ <grouplist x="70%" y="0" orientation="vertical" width="30%" height="100%" align="center" numlistelements="12" fadetime="{fadetimezapcockpit}" shifttime="{shifttimezapcockpit}" shiftmode="slowed" shifttype="right">
+ <listelement>
+ <area x="0" width="100%" layer="5">
+ <drawrectangle condition="not{current}" x="0" y="0" width="100%" height="100%" color="{menuback}" />
+ <drawrectangle condition="not{current}" x="0" y="{areaheight}-1" width="100%" height="1" color="{menubackline}" />
+ <drawrectangle condition="{current}" x="0" y="0" width="100%" height="100%" color="{menubackactive}" />
+ </area>
+ <area x="0" width="24%" layer="5">
+ <drawimage condition="not{current}" imagetype="icon" path="folder" align="center" valign="center" width="90%" height="90%" />
+ <drawimage condition="{current}" imagetype="icon" path="folder_active" align="center" valign="center" width="90%" height="90%" />
+ </area>
+ <area x="0" width="24%" layer="6">
+ <drawtext condition="not{current}" align="center" y="38%" fontsize="40%" font="{regular}" color="{fontdefault}" text="{numchannels}" />
+ <drawtext condition="{current}" align="center" y="38%" fontsize="40%" font="{regular}" color="{fontmenuactive}" text="{numchannels}" />
+ </area>
+ <areascroll condition="not{current}" scrollelement="groupname" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="25%" width="74%" layer="5">
+ <drawtext name="groupname" x="0" valign="center" fontsize="{zapglgroupfs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{groupname}" />
+ </areascroll>
+ <areascroll condition="{current}" scrollelement="groupname" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="25%" width="74%" layer="5">
+ <drawtext name="groupname" x="0" valign="center" fontsize="{zapglgroupfs}*{areaheight}/100" font="{regular}" color="{fontmenuactive}" text="{groupname}" />
+ </areascroll>
+ </listelement>
+ </grouplist>
+
+ <groupchannellistback fadetime="{fadetimezapcockpit}" shifttime="{shifttimezapcockpit}" shiftmode="slowed" startx="70%" starty="3%">
+ <area x="40%" y="3%" width="30%" height="94%" layer="1">
+ <fill color="{channelback}" />
+ </area>
+ </groupchannellistback>
+
+ <groupchannellist x="40%" y="3%" orientation="vertical" width="30%" height="94%" align="center" numlistelements="14" fadetime="{fadetimezapcockpit}" shifttime="{shifttimezapcockpit}" shiftmode="slowed" startx="70%" starty="3%">
+ <listelement>
+ <area x="0" width="100%" layer="2">
+ <drawrectangle condition="not{current}" x="0" y="0" width="100%" height="100%" color="{menuback}" />
+ <drawrectangle condition="not{current}" x="0" y="{areaheight}-1" width="100%" height="1" color="{menubackline}" />
+ <drawrectangle condition="{current}" x="0" y="0" width="100%" height="100%" color="{menubackactive}" />
+ </area>
+ <area x="1%" width="25%" layer="3">
+ <drawimage name="logo" imagetype="channellogo" path="{channelid}" x="0" width="100%" height="100%" valign="center" />
+ </area>
+ <area condition="not{current}" x="26%" width="73%" layer="3">
+ <drawtext x="0" y="{zapclchannely}*{areaheight}/100" font="{regular}" fontsize="{zapclchannelfs}*{areaheight}/100" color="{fontdefault}" text="{number} {name}" />
+ <drawtext x="0" y="{zapclpresenty}*{areaheight}/100" font="{regular}" fontsize="{zapclpresentfs}*{areaheight}/100" color="{fontdefault}" text="+{presenteventremaining}min: {presenteventtitle}" />
+ <drawtext x="0" y="{zapclnexty}*{areaheight}/100" font="{regular}" fontsize="{zapclnextfs}*{areaheight}/100" color="{fontdefault}" text="{nexteventstart} {nexteventstop}: {nexteventtitle}" />
+ </area>
+ <area condition="{current}" x="26%" width="73%" layer="3">
+ <drawtext x="0" y="{zapclchannely}*{areaheight}/100" font="{regular}" fontsize="{zapclchannelfs}*{areaheight}/100" color="{fontmenuactive}" text="{number} {name}" />
+ <drawtext x="0" y="{zapclpresenty}*{areaheight}/100" font="{regular}" fontsize="{zapclpresentfs}*{areaheight}/100" color="{fontmenuactive}" text="+{presenteventremaining}min: {presenteventtitle}" />
+ <drawtext x="0" y="{zapclnexty}*{areaheight}/100" font="{regular}" fontsize="{zapclnextfs}*{areaheight}/100" color="{fontmenuactive}" text="{nexteventstart} {nexteventstop}: {nexteventtitle}" />
+ </area>
+ </listelement>
+ </groupchannellist>
+
+ <groupchannellistdetail fadetime="{fadetimezapcockpit}" shifttime="{shifttimezapcockpit}" shiftmode="slowed" startx="40%" starty="6%">
+ <area x="2%" y="6%" width="38%" height="88%" layer="1">
+ <fill color="{channelback}" />
+ </area>
+ <area x="4%" y="6%" width="36%" height="5%" layer="2">
+ <drawtext x="0" valign="center" fontsize="{zapgcldetaildatetimefs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currentstart} - {currentstop}" />
+ </area>
+ <areascroll scrollelement="title" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="4%" y="10%" width="36%" height="7%" layer="3">
+ <drawtext name="title" x="0" valign="center" fontsize="{zapgcldetailheaderfs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currenttitle}" />
+ </areascroll>
+ <areascroll scrollelement="shorttext" mode="forthandback" orientation="horizontal" delay="1000" scrollspeed="medium" x="4%" y="16%" width="36%" height="6%" layer="3">
+ <drawtext name="shorttext" x="0" valign="center" fontsize="{zapgcldetailshorttextfs}*{areaheight}/100" font="{regular}" color="{fontdefault}" text="{currentshorttext}" />
+ </areascroll>
+ <areascroll orientation="vertical" scrollelement="desc" mode="forthandback" delay="5000" scrollspeed="medium" x="4%" y="22%" width="36%" height="70%" layer="2">
+ <drawtextbox name="desc" x="0" y="0" width="100%" font="{regular}" fontsize="{zapgcldetaildescfs}*{areaheight}/100" color="{fontdefault}" text="{currentdescription}" />
+ </areascroll>
+ </groupchannellistdetail>
+
<time>
<area x="80%" y="80%" width="20%" height="15%" layer="2">
<drawtext name="clock" x="11%" valign="center" fontsize="70%" font="{digital}" color="{fontdefault}" text="{hour}:{printf('%02d', min)}" />
diff --git a/skinskeleton/xmlfiles/displaychannel.xml b/skinskeleton/xmlfiles/displaychannel.xml
index 8bad9f7..bf2ddaa 100644
--- a/skinskeleton/xmlfiles/displaychannel.xml
+++ b/skinskeleton/xmlfiles/displaychannel.xml
@@ -181,6 +181,195 @@
<scrapercontent>
</scrapercontent>
+ <!-- Available Variables channelhints:
+ {numhints} number of hints to display
+ {hints[]} array with available channel hints
+ {hints[channelnumber]} number of current channel
+ {hints[channelname]} name of current channel
+ {hints[channelid]} id of current channel
+ {hints[channellogoexists]} true if channel logo exists
+ -->
+ <channelhints>
+ </channelhints>
+
+ <!-- Available Variables channeldetail:
+ {channelname} name of current channel
+ {channelnumber} number of current channel
+ {currenttitle} title of current event
+ {currentshorttext} short text of current event
+ {currentdescription} description of current event
+ {currentstart} start time of current event in hh:mm
+ {currentstop} end time of current event in hh:mm
+ {currentduration} duration of current Schedule in min
+ {currentdurationhours} duration, full hours
+ {currentdurationminutes} duration, rest of minutes
+ {currentelapsed} elapsed time of current Schedule in min
+ {currentremaining} remaining time of current Schedule in min
+ {nexttitle} title of next event
+ {nextshorttext} short text of next event
+ {nextdescription} description of next event
+ {nextstart} start time of next event in hh:mm
+ {nextstop} end time of next event in hh:mm
+ {nextduration} duration of next Schedule in min
+ {nextdurationhours} duration, full hours
+ {nextdurationminutes} duration, rest of minutes
+
+ {ismovie} true if current event is scraped as a movie
+ Available variables for movies:
+ {movietitle} movie title from themoviedb
+ {movieoriginalTitle} movie original title from themoviedb
+ {movietagline} movie tagline from themoviedb
+ {movieoverview} movie overview from themoviedb
+ {movieadult} true if movie is rated as adult
+ {moviebudget} movie budget from themoviedb in $
+ {movierevenue} movie revenue from themoviedb in $
+ {moviegenres} movie genres from themoviedb
+ {moviehomepage} movie homepage from themoviedb
+ {moviereleasedate} movie release date from themoviedb
+ {movieruntime} movie runtime from themoviedb
+ {moviepopularity} movie popularity from themoviedb
+ {movievoteaverage} movie vote average from themoviedb
+ {posterwidth} width of scraped poster
+ {posterheight} height of scraped poster
+ {posterpath} absolute path of scraped poster
+ {fanartwidth} width of scraped fanart
+ {fanartheight} height of scraped fanart
+ {fanartpath} absolute path of scraped fanart
+ {movieiscollection} true if movie is part of a collection
+ {moviecollectionName} name of movie collection
+ {collectionposterwidth} width of scraped collection poster
+ {collectionposterheight} height of scraped collection poster
+ {collectionposterpath} absolute path of scraped collection poster
+ {collectionfanartwidth} width of scraped collection fanart
+ {collectionfanartheight} height of scraped collection fanart
+ {collectionfanartpath} absolute path of scraped collection fanart
+ {actors[]} array with movie actors
+ {actors[name]} real name of actor
+ {actors[role]} actor role
+ {actors[thumb]} absolute path of scraped actor thumb
+ {actors[thumbwidth]} width of scraped actor thumb
+ {actors[thumbheight]} height of scraped actor thumb
+
+ {isseries} true if current event is scraped as a series
+ Available variables for series:
+ {seriesname} name of series
+ {seriesoverview} series overview
+ {seriesfirstaired} first aired date
+ {seriesnetwork} network which produces series
+ {seriesgenre} series genre
+ {seriesrating} series thetvdb rating
+ {seriesstatus} status of series (running / finished)
+ {episodetitle} title of episode
+ {episodenumber} number of episode
+ {episodeseason} season of episode
+ {episodefirstaired} first aired date of episode
+ {episodegueststars} guest stars of episode
+ {episodeoverview} episode overview
+ {episoderating} user rating for episode
+ {episodeimagewidth} episode image width
+ {episodeimageheight} episode image height
+ {episodeimagepath} episode image path
+ {seasonposterwidth} episode season poster width
+ {seasonposterheight} episode season poster height
+ {seasonposterpath} episode season poster path
+ {seriesposter1width} width of 1st poster
+ {seriesposter1height} height of 1st poster
+ {seriesposter1path} path of 1st poster
+ {seriesposter2width} width of 2nd poster
+ {seriesposter2height} height of 2nd poster
+ {seriesposter2path} path of 2nd poster
+ {seriesposter3width} width of 3rd poster
+ {seriesposter3height} height of 3rd poster
+ {seriesposter3path} path of 3rd poster
+ {seriesfanart1width} width of 1st fanart
+ {seriesfanart1height} height of 1st fanart
+ {seriesfanart1path} path of 1st fanart
+ {seriesfanart2width} width of 2nd fanart
+ {seriesfanart2height} height of 2nd fanart
+ {seriesfanart2path} path of 2nd fanart
+ {seriesfanart3width} width of 3rd fanart
+ {seriesfanart3height} height of 3rd fanart
+ {seriesfanart3path} path of 3rd fanart
+ {seriesbanner1width} width of 1st banner
+ {seriesbanner1height} height of 1st banner
+ {seriesbanner1path} path of 1st banner
+ {seriesbanner2width} width of 2nd banner
+ {seriesbanner2height} height of 2nd banner
+ {seriesbanner2path} path of 2nd banner
+ {seriesbanner3width} width of 3rd banner
+ {seriesbanner3height} height of 3rd banner
+ {seriesbanner3path} path of 3rd fanart
+ {actors[]} array with movie actors
+ {actors[name]} real name of actor
+ {actors[role]} actor role
+ {actors[thumb]} absolute path of scraped actor thumb
+ {actors[thumbwidth]} width of scraped actor thumb
+ {actors[thumbheight]} height of scraped actor thumb
+ -->
+ <channeldetail>
+ </channeldetail>
+
+ <!-- Available Variables channellistback:
+ -->
+ <channellistback>
+ </channellistback>
+
+ <!-- Available Variables channellist:
+ {nummenuitem} number in list of currently displayed channellist item
+ {current} true if currently displayed item is active
+ {name} name of channel
+ {number} number of channel
+ {channelid} if of channel
+ {channellogoexists} true if channel logo exists
+ {presenteventtitle} title of present event
+ {presenteventstart} start of present event in hh:mm
+ {presenteventstop} end of present event in hh:mm
+ {presenteventelapsed} elapsed minutes of present event
+ {presenteventremaining} remaining minutes of present event
+ {nexteventtitle} title of next event
+ {nexteventstart} start time of next event in hh:mm
+ {nexteventstop} end time of next event in hh:mm
+ -->
+ <channellist>
+ </channellist>
+
+ <!-- Available Variables channellistdetail:
+ see <channeldetail> tokens
+ -->
+ <channellistdetail>
+ </channellistdetail>
+
+ <!-- Available Variables grouplistback:
+ -->
+ <grouplistback>
+ </grouplistback>
+
+ <!-- Available Variables grouplist:
+ {nummenuitem} number in list of currently displayed channelgrouplist item
+ {current} true if currently displayed item is active
+ {groupname} name of displayed channel group
+ {numchannels} number of channels in channel group
+ -->
+ <grouplist>
+ </grouplist>
+
+ <!-- Available Variables groupchannellistback:
+ -->
+ <groupchannellistback>
+ </groupchannellistback>
+
+ <!-- Available Variables groupchannellist:
+ see <channellist> tokens
+ -->
+ <groupchannellist>
+ </groupchannellist>
+
+ <!-- Available Variables groupchannellistdetail:
+ see <channeldetail> tokens
+ -->
+ <groupchannellistdetail>
+ </groupchannellistdetail>
+
<!-- Available Variables datetime:
{time} time in hh:mm
{day} day in digits