summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchriszero <zerov83@gmail.com>2015-04-05 22:33:05 +0200
committerchriszero <zerov83@gmail.com>2015-04-05 22:33:05 +0200
commitf3d792a866ba602458d5d6c521bafa66e56a5528 (patch)
tree8a0b9c52ca97635cbd682468f629784d0d5b2d6c
parentf7f62b7ff1f12c1563a04560ad87d2f92a3e0af9 (diff)
downloadvdr-plugin-plex-f3d792a866ba602458d5d6c521bafa66e56a5528.tar.gz
vdr-plugin-plex-f3d792a866ba602458d5d6c521bafa66e56a5528.tar.bz2
Fixes some concurency bugs
-rw-r--r--Config.cpp11
-rw-r--r--Config.h10
-rw-r--r--Makefile1
-rw-r--r--MediaContainer.h1
-rw-r--r--browserGrid.cpp30
-rw-r--r--browserGrid.h2
-rw-r--r--detailView.cpp10
-rw-r--r--detailView.h14
-rw-r--r--pictureCache.cpp18
-rw-r--r--pictureCache.h3
-rw-r--r--plex.cpp4
-rw-r--r--plexSdOsd.cpp10
-rw-r--r--plexSdOsd.h1
-rw-r--r--skins/blackhole/themes/default/skinparts/plexplaceholder.svg130
-rw-r--r--skins/blackhole/xmlfiles/plug-plex-root.xml146
15 files changed, 366 insertions, 25 deletions
diff --git a/Config.cpp b/Config.cpp
index df577aa..6b37efb 100644
--- a/Config.cpp
+++ b/Config.cpp
@@ -4,6 +4,8 @@
Config::Config() {
s_username = "username";
s_password = "password";
+ GridColumns = 5;
+ GridRows = 2;
}
std::string Config::GetUUID() {
@@ -70,6 +72,8 @@ cMyMenuSetupPage::cMyMenuSetupPage(void)
UseConfiguredServer = Config::GetInstance().UseConfiguredServer;
HideMainMenuEntry = Config::GetInstance().HideMainMenuEntry;
UseCustomTranscodeProfile = Config::GetInstance().UseCustomTranscodeProfile;
+ GridColumns = Config::GetInstance().GridColumns;
+ GridRows = Config::GetInstance().GridRows;
Add(new cMenuEditBoolItem(tr("Hide main menu entry"), (int*)&HideMainMenuEntry, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("Use custom transcoding profile"), (int*)&UseCustomTranscodeProfile, trVDR("no"), trVDR("yes")));
@@ -81,6 +85,9 @@ cMyMenuSetupPage::cMyMenuSetupPage(void)
Add(new cMenuEditStrItem(tr("Server Host"), ServerHost, STRING_SIZE));
Add(new cMenuEditIntItem(tr("Server Port"), &ServerPort));
+ Add(new cMenuEditIntItem(tr("Grid Columns"), &GridColumns));
+ Add(new cMenuEditIntItem(tr("Grid Rows"), &GridRows));
+
cMenuEditStrItem* devUUID = new cMenuEditStrItem(tr("Current UUID"), Uuid, STRING_SIZE);
devUUID->SetSelectable(false);
Add(devUUID);
@@ -99,6 +106,8 @@ void cMyMenuSetupPage::Store(void)
Config::GetInstance().UseConfiguredServer = UseConfiguredServer;
Config::GetInstance().s_serverHost = std::string(ServerHost);
Config::GetInstance().ServerPort = ServerPort;
+ Config::GetInstance().GridColumns = GridColumns;
+ Config::GetInstance().GridRows = GridRows;
SetupStore("UseCustomTranscodeProfile", Config::GetInstance().UseCustomTranscodeProfile);
SetupStore("HideMainMenuEntry", Config::GetInstance().HideMainMenuEntry);
@@ -109,4 +118,6 @@ void cMyMenuSetupPage::Store(void)
SetupStore("UseConfiguredServer", Config::GetInstance().UseConfiguredServer);
SetupStore("ServerHost", Config::GetInstance().s_serverHost.c_str());
SetupStore("ServerPort", Config::GetInstance().ServerPort);
+ SetupStore("GridColumns", Config::GetInstance().GridColumns);
+ SetupStore("GridRows", Config::GetInstance().GridRows);
} \ No newline at end of file
diff --git a/Config.h b/Config.h
index 39ee8ad..d123864 100644
--- a/Config.h
+++ b/Config.h
@@ -33,6 +33,8 @@ public:
bool UseCustomTranscodeProfile;
bool UsePlexAccount;
bool UseConfiguredServer;
+ int GridColumns;
+ int GridRows;
std::string GetUUID();
void SetUUID(const char* uuid);
@@ -40,6 +42,12 @@ public:
std::string GetLanguage();
std::string GetUsername();
std::string GetPassword();
+ int ThumbHeight() { return 1080 / GridRows; };
+ int ThumbWidth() { return 1920 / GridColumns; };
+ int ArtHeight() { return 1080; };
+ int ArtWidth() { return 1920; };
+ int BannerHeight() { return 1080 / 2; };
+ int BannerWidth() { return 1920 / 2; };
private:
@@ -68,6 +76,8 @@ class cMyMenuSetupPage:public cMenuSetupPage
int HideMainMenuEntry;
int UseCustomTranscodeProfile;
int UsePlexAccount;
+ int GridColumns;
+ int GridRows;
virtual void Store(void);
diff --git a/Makefile b/Makefile
index 5372c45..bb7a5b1 100644
--- a/Makefile
+++ b/Makefile
@@ -92,6 +92,7 @@ OBJS = $(PLUGIN).o \
viewGridNavigator.o \
browserGrid.o \
viewHeader.o \
+ detailView.o \
pictureCache.o \
libskindesigner/skindesignerosdbase.o \
libskindesigner/osdelements.o \
diff --git a/MediaContainer.h b/MediaContainer.h
index d806fd3..da2a210 100644
--- a/MediaContainer.h
+++ b/MediaContainer.h
@@ -18,6 +18,7 @@
#include "Directory.h"
#include "PVideo.h"
#include "PlexServer.h"
+#include "Config.h"
using Poco::XML::DOMParser;
using Poco::XML::InputSource;
diff --git a/browserGrid.cpp b/browserGrid.cpp
index 0ce3fcc..f3637c6 100644
--- a/browserGrid.cpp
+++ b/browserGrid.cpp
@@ -12,36 +12,39 @@ cBrowserGrid::cBrowserGrid(cOsdView* rootView) : cViewGridNavigator(rootView, ro
m_pViewHeader = std::shared_ptr<cViewHeader>( new cViewHeader(rootView->GetViewElement(eViewElementsRoot::verHeader)));
m_pfooter = std::shared_ptr<cViewElement>(rootView->GetViewElement(eViewElementsRoot::verFooter));
- m_rows = 2;
- m_columns = 5;
+ m_rows = Config::GetInstance().GridRows;
+ m_columns = Config::GetInstance().GridColumns;
m_pService = NULL;
m_pContainer = NULL;
- //SwitchGrid(m_pViewHeader->CurrentTab());
+ SwitchGrid(m_pViewHeader->CurrentTab());
}
void cBrowserGrid::Flush()
{
- //cMutexLock MutexLock(&cPlexSdOsd::RedrawMutex);
+ cMutexLock MutexLock(&cPlexSdOsd::RedrawMutex);
+ m_pBackground->Display();
m_pGrid->Display();
m_pRootView->Display();
}
void cBrowserGrid::SwitchGrid(ePlexMenuTab currentTab)
{
+ cPictureCache::GetInstance().RemoveAll();
if(currentTab == ePlexMenuTab::pmtOnDeck) {
- std::cout << "OnDeck" << std::endl;
m_pService = std::shared_ptr<plexclient::Plexservice>(new plexclient::Plexservice( plexclient::plexgdm::GetInstance().GetFirstServer(), "/library/onDeck" ) );
m_pContainer = m_pService->GetSection(m_pService->StartUri);
+ m_bServersAreRoot = false;
+ m_vServerElements.clear();
ProcessData();
} else if(currentTab == ePlexMenuTab::pmtRecentlyAdded) {
- std::cout << "Recently Added" << std::endl;
m_pService = std::shared_ptr<plexclient::Plexservice>(new plexclient::Plexservice( plexclient::plexgdm::GetInstance().GetFirstServer(), "/library/recentlyAdded" ) );
m_pContainer = m_pService->GetSection(m_pService->StartUri);
+ m_bServersAreRoot = false;
+ m_vServerElements.clear();
ProcessData();
} else if(currentTab == ePlexMenuTab::pmtLibrary) {
- std::cout << "Lib" << std::endl;
//Server View
m_pService = NULL;
m_pContainer = NULL;
@@ -88,8 +91,6 @@ void cBrowserGrid::ProcessData()
m_vElements.push_back(elem);
}
}
- // Cache Images
- //m_pContainer->PreCache();
}
m_firstElementIter = m_vElements.begin();
@@ -144,6 +145,7 @@ eOSState cBrowserGrid::NavigateBack()
void cBrowserGrid::DrawGrid()
{
DrawBackground();
+ m_pViewHeader->Draw(SelectedObject());
DrawFooter();
}
@@ -222,6 +224,16 @@ void cBrowserGrid::DrawFooter()
m_pfooter->Display();
}
+void cBrowserGrid::NextTab()
+{
+ SwitchGrid(m_pViewHeader->NextTab());
+}
+
+void cBrowserGrid::PrevTab()
+{
+ SwitchGrid(m_pViewHeader->PrevTab());
+}
+
/*
* cDummyElement
*/
diff --git a/browserGrid.h b/browserGrid.h
index b91c30c..2eed86c 100644
--- a/browserGrid.h
+++ b/browserGrid.h
@@ -60,6 +60,8 @@ public:
void SwitchGrid(ePlexMenuTab currentTab);
virtual eOSState NavigateSelect();
virtual eOSState NavigateBack();
+ void NextTab();
+ void PrevTab();
virtual void Flush();
};
diff --git a/detailView.cpp b/detailView.cpp
new file mode 100644
index 0000000..b9bc9a1
--- /dev/null
+++ b/detailView.cpp
@@ -0,0 +1,10 @@
+#include "detailView.h"
+
+cDetailView::cDetailView(cOsdView *detailView, const cGridElement *element)
+{
+}
+
+cDetailView::~cDetailView()
+{
+}
+
diff --git a/detailView.h b/detailView.h
new file mode 100644
index 0000000..9917fd0
--- /dev/null
+++ b/detailView.h
@@ -0,0 +1,14 @@
+#ifndef CDETAILVIEW_H
+#define CDETAILVIEW_H
+
+#include "viewGridNavigator.h"
+
+class cDetailView
+{
+public:
+ cDetailView(cOsdView *detailView, const cGridElement *element);
+ ~cDetailView();
+
+};
+
+#endif // CDETAILVIEW_H
diff --git a/pictureCache.cpp b/pictureCache.cpp
index 67e2fd4..42885ec 100644
--- a/pictureCache.cpp
+++ b/pictureCache.cpp
@@ -26,13 +26,13 @@ cPictureCache::cPictureCache()
Poco::File f(path.toString());
f.createDirectories();
HTTPStreamFactory::registerFactory();
+ m_bAllInvalidated = false;
}
void cPictureCache::Action()
{
while(Running()) {
while (m_qImagesToLoad.size() > 0) {
- //LOCK_THREAD;
CacheInfo info = m_qImagesToLoad.front();
m_qImagesToLoad.pop_front();
@@ -42,8 +42,8 @@ void cPictureCache::Action()
auto stream = DownloadFile(transcodeUri);
if(stream) {
SaveFileToDisk(stream, file);
- cMutexLock MutexLock(&cPlexSdOsd::RedrawMutex);
- if (info.onCached && info.calle && info.calle->IsVisible()) {
+ LOCK_THREAD;
+ if (!m_bAllInvalidated && info.onCached && info.calle && info.calle->IsVisible()) {
info.onCached(info.calle);
}
}
@@ -83,7 +83,7 @@ void cPictureCache::SaveFileToDisk(std::shared_ptr<std::istream> file, std::stri
std::string cPictureCache::FileName(std::string uri, int width)
{
Poco::URI u(uri);
- std::string file = Poco::format("%s_%d", u.getPath(), width);
+ std::string file = Poco::format("%s_%d", u.getPathAndQuery(), width);
Poco::Path path(m_cacheDir);
path.append(file);
@@ -108,12 +108,12 @@ bool cPictureCache::Cached(std::string uri, int width)
std::string cPictureCache::GetPath(std::string uri, int width, int height, bool& cached, std::function<void(cGridElement*)> OnCached, cGridElement* calle)
{
+ m_bAllInvalidated = false;
cached = Cached(uri, width);
std::string file = FileName(uri, width);
if(cached) {
return file;
} else {
- //LOCK_THREAD;
CacheInfo info(uri, width, height, OnCached, calle);
m_qImagesToLoad.push_back(info);
}
@@ -137,6 +137,7 @@ void cPictureCache::Remove(cGridElement* element)
void cPictureCache::Remove(std::string uri)
{
+ LOCK_THREAD;
for(std::deque<CacheInfo>::iterator it = m_qImagesToLoad.begin() ; it != m_qImagesToLoad.end(); ++it) {
if(it->uri == uri) {
m_qImagesToLoad.erase(it);
@@ -144,3 +145,10 @@ void cPictureCache::Remove(std::string uri)
}
}
}
+
+void cPictureCache::RemoveAll()
+{
+ LOCK_THREAD;
+ m_bAllInvalidated = true;
+ m_qImagesToLoad.clear();
+}
diff --git a/pictureCache.h b/pictureCache.h
index e63d44b..3d66726 100644
--- a/pictureCache.h
+++ b/pictureCache.h
@@ -38,7 +38,7 @@ private:
};
cPictureCache();
std::deque<CacheInfo> m_qImagesToLoad;
-
+ volatile bool m_bAllInvalidated;
std::string FileName(std::string uri, int width);
@@ -62,6 +62,7 @@ public:
std::string GetPath(std::string uri, int width, int height, bool& cached, std::function<void(cGridElement*)> OnCached = NULL, cGridElement* calle = NULL);
void Remove(cGridElement* element);
void Remove(std::string uri);
+ void RemoveAll();
};
#endif // CPICTURECACHE_H
diff --git a/plex.cpp b/plex.cpp
index fc84f99..f8961cf 100644
--- a/plex.cpp
+++ b/plex.cpp
@@ -160,8 +160,10 @@ bool cMyPlugin::SetupParse(const char *name, const char *value)
else if (strcasecmp(name, "UseConfiguredServer") == 0) Config::GetInstance().UseConfiguredServer = atoi(value) ? true : false;
else if (strcasecmp(name, "ServerHost") == 0) Config::GetInstance().s_serverHost = std::string(value);
else if (strcasecmp(name, "ServerPort") == 0) Config::GetInstance().ServerPort = atoi(value);
+ else if (strcasecmp(name, "GridColumns") == 0) Config::GetInstance().GridColumns = atoi(value);
+ else if (strcasecmp(name, "GridRows") == 0) Config::GetInstance().GridRows = atoi(value);
else return false;
-
+
return true;
}
diff --git a/plexSdOsd.cpp b/plexSdOsd.cpp
index 0379dd7..db50168 100644
--- a/plexSdOsd.cpp
+++ b/plexSdOsd.cpp
@@ -9,6 +9,11 @@ cPlexSdOsd::cPlexSdOsd()
{
}
+cPlexSdOsd::~cPlexSdOsd()
+{
+ cPictureCache::GetInstance().RemoveAll();
+}
+
void cPlexSdOsd::Show(void)
{
bool skinDesignerAvailable = InitSkindesignerInterface("plex");
@@ -23,7 +28,6 @@ void cPlexSdOsd::Show(void)
}
m_pBrowserGrid = std::shared_ptr<cBrowserGrid>(new cBrowserGrid(m_pRootView));
- m_pBrowserGrid->SwitchGrid(ePlexMenuTab::pmtOnDeck);
Flush();
}
@@ -65,12 +69,12 @@ eOSState cPlexSdOsd::ProcessKey(eKeys Key)
break;
case kRed:
// Prev Tab
- //SwitchGrid(m_pViewHeader->NextTab());
+ m_pBrowserGrid->NextTab();
Flush();
break;
case kGreen:
// Next Tab
- //SwitchGrid(m_pViewHeader->PrevTab());
+ m_pBrowserGrid->PrevTab();
Flush();
break;
default:
diff --git a/plexSdOsd.h b/plexSdOsd.h
index 2dbe59f..433522b 100644
--- a/plexSdOsd.h
+++ b/plexSdOsd.h
@@ -49,6 +49,7 @@ private:
public:
cPlexSdOsd();
+ ~cPlexSdOsd();
virtual void Show(void);
virtual eOSState ProcessKey(eKeys Key);
diff --git a/skins/blackhole/themes/default/skinparts/plexplaceholder.svg b/skins/blackhole/themes/default/skinparts/plexplaceholder.svg
new file mode 100644
index 0000000..747b38d
--- /dev/null
+++ b/skins/blackhole/themes/default/skinparts/plexplaceholder.svg
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
+ 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:xlink="http://www.w3.org/1999/xlink"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="280"
+ height="420"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="Neues Dokument 1">
+ <defs
+ id="defs4">
+ <radialGradient
+ id="radialGradient-1"
+ r="722.62571"
+ fy="388.73516"
+ fx="3496.9578"
+ cy="388.73516"
+ cx="3496.9578"
+ gradientTransform="scale(0.78082978,1.2806889)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop3011"
+ offset="0%"
+ stop-color="#F9BE03" />
+ <stop
+ id="stop3013"
+ offset="100%"
+ stop-color="#CC7C19" />
+ </radialGradient>
+ <radialGradient
+ id="radialGradient-1-2"
+ r="722.62573"
+ fy="388.73517"
+ fx="3496.9578"
+ cy="388.73517"
+ cx="3496.9578"
+ gradientTransform="scale(0.78082978,1.2806889)"
+ gradientUnits="userSpaceOnUse">
+ <stop
+ id="stop3011-5"
+ offset="0%"
+ stop-color="#F9BE03" />
+ <stop
+ id="stop3013-8"
+ offset="100%"
+ stop-color="#CC7C19" />
+ </radialGradient>
+ <radialGradient
+ r="722.62573"
+ fy="388.73517"
+ fx="3496.9578"
+ cy="388.73517"
+ cx="3496.9578"
+ gradientTransform="matrix(0.14560777,0,0,0.23882061,2068.5676,-690.71428)"
+ gradientUnits="userSpaceOnUse"
+ id="radialGradient3058"
+ xlink:href="#radialGradient-1-2"
+ inkscape:collect="always" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.8"
+ inkscape:cx="-13.217746"
+ inkscape:cy="194.86305"
+ inkscape:document-units="px"
+ inkscape:current-layer="g3017"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="2564"
+ inkscape:window-height="1592"
+ inkscape:window-x="0"
+ inkscape:window-y="34"
+ inkscape:window-maximized="0" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Ebene 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-214.28569,-336.64789)">
+ <g
+ sketch:type="MSPage"
+ id="Page-1"
+ transform="translate(-2179.0664,1142.8264)"
+ style="fill:none;stroke:none">
+ <g
+ sketch:type="MSArtboardGroup"
+ id="plex-logo-light">
+ <g
+ id="g3017"
+ sketch:type="MSLayerGroup">
+ <path
+ sketch:type="MSShapeGroup"
+ id="chevron-4"
+ d="m 2476.2091,-690.71428 54.0789,0 59.6729,93.28575 -59.6729,93.28575 -54.0789,0 59.6729,-93.28575 -59.6729,-93.28575"
+ inkscape:connector-curvature="0"
+ style="fill:url(#radialGradient3058);fill-opacity:1;stroke:none" />
+ </g>
+ </g>
+ </g>
+ </g>
+</svg>
diff --git a/skins/blackhole/xmlfiles/plug-plex-root.xml b/skins/blackhole/xmlfiles/plug-plex-root.xml
index 4f29e14..b67e9c1 100644
--- a/skins/blackhole/xmlfiles/plug-plex-root.xml
+++ b/skins/blackhole/xmlfiles/plug-plex-root.xml
@@ -10,7 +10,13 @@
-->
<viewelement name="background">
<area x="0" y="0" width="100%" height="100%" layer="1">
- <drawimage imagetype="image" path="{selecteditembackground}" x="0" y="0" width="100%" height="100%" />
+ <drawimage imagetype="skinpart" path="displaymenuback" x="0" y="0" width="100%" height="100%"/>
+ </area>
+ <area x="0" y="0" width="83%" height="8%" layer="2">
+ <drawimage imagetype="skinpart" path="displaymenuheader" x="0" y="0" width="100%" height="100%"/>
+ </area>
+ <area x="74%" y="0" width="26%" height="46%" layer="3">
+ <drawimage imagetype="skinpart" path="displaymenucorner" x="0" y="0" width="100%" height="100%"/>
</area>
</viewelement>
@@ -49,8 +55,10 @@
{current} Currently active element
{title} Name of the element
{year}
- {thumb} Image/Cover
- {art} Fanart
+ {hasthumb}
+ {thumb} Image/Cover
+ {hasart}
+ {art} Fanart
{isdummy} Condition
@@ -71,7 +79,7 @@
{banner}
-->
- <grid name="browser" x="0" y="15%" width="100%" height="85%">
+ <grid name="browser" x="0" y="15%" width="100%" height="75%">
<area layer="3">
<drawtext x="1%" y="2%" width="98%" font="{light}" fontsize="5%" color="{clrWhite}" text="{title}" />
<drawtext condition="{current}" x="1%" y="20%" width="98%" font="{light}" fontsize="5%" color="{clrWhite}" text="Active" />
@@ -79,10 +87,136 @@
<drawtext condition="{isserver}" x="1%" y="60%" width="98%" font="{light}" fontsize="5%" color="{clrWhite}" text="{serverstartpointname}" />
<drawtext condition="{isdirectory}" x="1%" y="40%" width="98%" font="{light}" fontsize="5%" color="{clrWhite}" text="Directory" />
<drawtext condition="{ismovie}" x="1%" y="40%" width="98%" font="{light}" fontsize="5%" color="{clrWhite}" text="Movie" />
- <drawimage condition="{ismovie}" imagetype="image" path="{thumb}" x="10%" y="20%" width="80%" height="80%" />
+
+ <drawimage condition="not{hasthumb}" imagetype="skinpart" path="plexplaceholder" x="10%" y="20%" width="80%" height="80%" />
+ <drawimage condition="{hasthumb}" imagetype="image" path="{thumb}" x="10%" y="20%" width="80%" height="80%" />
+
<drawtext condition="{isepisode}" x="1%" y="40%" width="98%" font="{light}" fontsize="5%" color="{clrWhite}" text="Episode" />
- <drawimage condition="{isepisode}" imagetype="image" path="{grandparentthumb}" x="10%" y="20%" width="80%" height="80%" />
</area>
</grid>
+ <!-- Available Variables Footer:
+ {red1} true if red button is button 1
+ {red2} true if red button is button 2
+ {red3} true if red button is button 3
+ {red4} true if red button is button 4
+ {green1} true if green button is button 1
+ {green2} true if green button is button 2
+ {green3} true if green button is button 3
+ {green4} true if green button is button 4
+ {yellow1} true if yellow button is button 1
+ {yellow2} true if yellow button is button 2
+ {yellow3} true if yellow button is button 3
+ {yellow4} true if yellow button is button 4
+ {blue1} true if blue button is button 1
+ {blue2} true if blue button is button 2
+ {blue3} true if blue button is button 3
+ {blue4} true if blue button is button 4
+ {red} label of red button
+ {green} label of green button
+ {yellow} label of yellow button
+ {blue} label of blue button
+ -->
+ <viewelement name="footer">
+ <area condition="{red1}" x="0" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonred" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{red1}" x="0" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{red}" />
+ </area>
+ <area condition="{green1}" x="0" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttongreen" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{green1}" x="0" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{green}" />
+ </area>
+ <area condition="{yellow1}" x="0" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonyellow" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{yellow1}" x="0" y="90%" width="25%" height="10%" layer="4">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{yellow}" />
+ </area>
+ <area condition="{blue1}" x="0" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonblue" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{blue1}" x="0" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{blue}" />
+ </area>
+
+ <area condition="{red2}" x="25%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonred" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{red2}" x="25%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{red}" />
+ </area>
+ <area condition="{green2}" x="25%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttongreen" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{green2}" x="25%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{green}" />
+ </area>
+ <area condition="{yellow2}" x="25%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonyellow" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{yellow2}" x="25%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{yellow}" />
+ </area>
+ <area condition="{blue2}" x="25%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonblue" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{blue2}" x="25%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{blue}" />
+ </area>
+
+ <area condition="{red3}" x="50%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonred" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{red3}" x="50%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{red}" />
+ </area>
+ <area condition="{green3}" x="50%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttongreen" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{green3}" x="50%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{green}" />
+ </area>
+ <area condition="{yellow3}" x="50%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonyellow" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{yellow3}" x="50%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{yellow}" />
+ </area>
+ <area condition="{blue3}" x="50%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonblue" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{blue3}" x="50%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{blue}" />
+ </area>
+
+ <area condition="{red4}" x="75%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonred" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{red4}" x="75%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{red}" />
+ </area>
+ <area condition="{green4}" x="75%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttongreen" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{green4}" x="60%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{green}" />
+ </area>
+ <area condition="{yellow4}" x="75%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonyellow" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{yellow4}" x="75%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{yellow}" />
+ </area>
+ <area condition="{blue4}" x="75%" y="90%" width="25%" height="10%" layer="2">
+ <drawimage imagetype="skinpart" path="buttonblue" align="center" valign="center" width="90%" height="60%"/>
+ </area>
+ <area condition="{blue4}" x="75%" y="90%" width="25%" height="10%" layer="3">
+ <drawtext align="center" valign="center" font="{regular}" fontsize="50%" color="{clrWhite}" text="{blue}" />
+ </area>
+ </viewelement>
+
</displayplugin>