diff options
-rw-r--r-- | Directory.cpp | 6 | ||||
-rw-r--r-- | Directory.h | 10 | ||||
-rw-r--r-- | Makefile | 11 | ||||
-rw-r--r-- | PVideo.cpp | 6 | ||||
-rw-r--r-- | PVideo.h | 10 | ||||
-rw-r--r-- | PlexServer.h | 5 | ||||
-rw-r--r-- | Plexservice.cpp | 6 | ||||
-rw-r--r-- | Plexservice.h | 1 | ||||
-rw-r--r-- | XmlObject.h | 4 | ||||
-rw-r--r-- | browserGrid.cpp | 153 | ||||
-rw-r--r-- | browserGrid.h | 54 | ||||
-rw-r--r-- | hlsPlayer.cpp | 3 | ||||
-rw-r--r-- | libskindesigner/osdelements.cpp | 205 | ||||
-rw-r--r-- | libskindesigner/osdelements.h | 93 | ||||
-rw-r--r-- | libskindesigner/services.h | 131 | ||||
-rw-r--r-- | libskindesigner/skindesignerosdbase.cpp | 211 | ||||
-rw-r--r-- | libskindesigner/skindesignerosdbase.h | 86 | ||||
-rw-r--r-- | plex.cpp | 32 | ||||
-rw-r--r-- | plexOsd.cpp | 46 | ||||
-rw-r--r-- | plexOsd.h | 12 | ||||
-rw-r--r-- | plexSdOsd.cpp | 104 | ||||
-rw-r--r-- | plexSdOsd.h | 55 | ||||
-rw-r--r-- | po/de_DE.po | 10 | ||||
-rw-r--r-- | skins/blackhole/xmlfiles/plug-plex-root.xml | 58 | ||||
-rw-r--r-- | viewGridNavigator.cpp | 158 | ||||
-rw-r--r-- | viewGridNavigator.h | 61 | ||||
-rw-r--r-- | viewHeader.cpp | 61 | ||||
-rw-r--r-- | viewHeader.h | 27 |
28 files changed, 1549 insertions, 70 deletions
diff --git a/Directory.cpp b/Directory.cpp index e6e240b..5102015 100644 --- a/Directory.cpp +++ b/Directory.cpp @@ -41,4 +41,10 @@ std::string Directory::GetTitle() } } +void Directory::AddTokens(std::shared_ptr<cViewGrid> grid) +{ + grid->ClearTokens(); + grid->AddStringToken("title", m_sTitle); +} + } diff --git a/Directory.h b/Directory.h index 19bd17f..b4a78d1 100644 --- a/Directory.h +++ b/Directory.h @@ -11,8 +11,12 @@ #include <Poco/Timestamp.h> #include <Poco/String.h> +#include <memory> +#include "libskindesigner/osdelements.h" + #include "XmlObject.h" #include "MediaContainer.h" +#include "viewGridNavigator.h" using Poco::XML::DOMParser; using Poco::XML::Document; @@ -26,7 +30,7 @@ namespace plexclient { class MediaContainer; -class Directory: XmlObject +class Directory: private XmlObject, public cGridElement { public: Directory(Poco::XML::Node* pNode, MediaContainer* parent); @@ -48,7 +52,9 @@ public: std::string m_sKey; MediaType m_eType; - std::string GetTitle(); + virtual std::string GetTitle(); + // gridElement + virtual void AddTokens(std::shared_ptr<cViewGrid> grid); }; } @@ -28,6 +28,7 @@ PKGCFG = $(if $(VDRDIR),$(shell pkg-config --variable=$(1) $(VDRDIR)/vdr.pc),$(s LIBDIR = $(call PKGCFG,libdir) LOCDIR = $(call PKGCFG,locdir) PLGCFG = $(call PKGCFG,plgcfg) +PLGRESDIR = $(call PKGCFG,resdir)/plugins/skindesigner # TMPDIR ?= /tmp @@ -87,6 +88,12 @@ OBJS = $(PLUGIN).o \ Stream.o \ Media.o \ plexOsd.o \ + plexSdOsd.o \ + viewGridNavigator.o \ + browserGrid.o \ + viewHeader.o \ + libskindesigner/skindesignerosdbase.o \ + libskindesigner/osdelements.o \ SRCS = $(wildcard $(OBJS:.o=.c)) $(PLUGIN).cpp @@ -144,6 +151,10 @@ $(SOFILE): $(OBJS) install-lib: $(SOFILE) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) +install-skins: + mkdir -p $(DESTDIR)$(PLGRESDIR)/skins + cp -r skins/* $(DESTDIR)$(PLGRESDIR)/skins + install: install-lib install-i18n dist: $(I18Npo) clean @@ -204,5 +204,11 @@ bool Video::SetWatched() } } +void Video::AddTokens(std::shared_ptr<cViewGrid>grid) +{ + grid->ClearTokens(); + grid->AddStringToken("title", m_sTitle); +} + } // Namespace @@ -14,6 +14,9 @@ #include <vector> #include <iostream> +#include <memory> +#include "libskindesigner/osdelements.h" +#include "viewGridNavigator.h" #include "XmlObject.h" #include "MediaContainer.h" @@ -32,7 +35,7 @@ namespace plexclient { class MediaContainer; -class Video: XmlObject +class Video: private XmlObject, public cGridElement { private: void Parse(Poco::XML::Node* pNode); @@ -72,11 +75,14 @@ public: int m_iIndex; int m_iParentIndex; - std::string GetTitle(); + virtual std::string GetTitle(); bool SetStream(Stream* stream); bool UpdateFromServer(); bool SetWatched(); bool SetUnwatched(); + + // gridElement + virtual void AddTokens(std::shared_ptr<cViewGrid> grid); }; } diff --git a/PlexServer.h b/PlexServer.h index a3d6ee1..3879878 100644 --- a/PlexServer.h +++ b/PlexServer.h @@ -6,6 +6,7 @@ #include <sstream> #include <iostream> #include <vector> +#include <memory> #include <Poco/String.h> #include <Poco/Net/HTTPClientSession.h> @@ -15,7 +16,7 @@ namespace plexclient { - + class PlexServer { public: @@ -59,7 +60,7 @@ public: } std::string GetUri(); - + void DiscoverSettings(); private: diff --git a/Plexservice.cpp b/Plexservice.cpp index dc01721..41f9579 100644 --- a/Plexservice.cpp +++ b/Plexservice.cpp @@ -11,6 +11,12 @@ Plexservice::Plexservice(PlexServer *server) pServer = server; } +Plexservice::Plexservice(PlexServer *server, std::string startUri) +{ + pServer = server; + StartUri = startUri; +} + std::string Plexservice::GetMyPlexToken() { static bool done; diff --git a/Plexservice.h b/Plexservice.h index d20c5ee..e30e346 100644 --- a/Plexservice.h +++ b/Plexservice.h @@ -40,6 +40,7 @@ class Plexservice { public: Plexservice(PlexServer *server); + Plexservice(PlexServer *server, std::string startUri); void DisplaySections(); std::shared_ptr<MediaContainer> GetSection(std::string section, bool putOnStack = true); diff --git a/XmlObject.h b/XmlObject.h index 5b8b2ca..22626b4 100644 --- a/XmlObject.h +++ b/XmlObject.h @@ -15,9 +15,7 @@ enum MediaType {UNDEF = 0, PHOTO, MOVIE, MUSIC, SHOW, SEASON, EPISODE}; enum StreamType {sUNDEF = 0, sVIDEO = 1, sAUDIO = 2, sSUBTITLE = 3}; class XmlObject -{ -public: - +{ protected: static std::string GetNodeValue(Poco::XML::Node* pNode); static int GetNodeValueAsInt(Poco::XML::Node* pNode); diff --git a/browserGrid.cpp b/browserGrid.cpp new file mode 100644 index 0000000..95d74a0 --- /dev/null +++ b/browserGrid.cpp @@ -0,0 +1,153 @@ +#include "browserGrid.h" +#include "plexSdOsd.h" +#include "XmlObject.h" +#include "PVideo.h" +#include "Directory.h" + +cBrowserGrid::cBrowserGrid(cViewGrid* viewGrid) : cViewGridNavigator(viewGrid) +{ + m_rows = 2; + m_columns = 5; + m_pService = NULL; + m_pContainer = NULL; + m_bServersAreRoot = true; + SetServerElements(); + ProcessData(); +} + +cBrowserGrid::cBrowserGrid(cViewGrid* viewGrid, std::shared_ptr<plexclient::Plexservice> service) : cViewGridNavigator(viewGrid) +{ + m_rows = 2; + m_columns = 5; + m_bServersAreRoot = false; + m_pService = service; + m_pContainer = m_pService->GetSection(m_pService->StartUri); + ProcessData(); +} + +void cBrowserGrid::SetServerElements() +{ + m_vServerElements.clear(); + + for(std::vector<plexclient::PlexServer>::iterator it = plexclient::plexgdm::GetInstance().GetPlexservers().begin(); it != plexclient::plexgdm::GetInstance().GetPlexservers().end(); ++it) { + m_vServerElements.push_back(cServerElement(&(*it), "/library/sections", "Bibliothek")); + m_vServerElements.push_back(cServerElement(&(*it), "/video", "Video Channels")); + } +} + +void cBrowserGrid::ProcessData() +{ + m_vElements.clear(); + + if(m_vServerElements.size() > 0) { + for(auto it = m_vServerElements.begin(); it !=m_vServerElements.end(); ++it) { + cServerElement *elem = &(*it); + m_vElements.push_back(elem); + } + } else { + m_vElements.push_back(&m_Dummy); + m_Dummy.Dirty(); + + if(m_pContainer->m_vVideos.size() > 0) { + for(std::vector<plexclient::Video>::iterator it = m_pContainer->m_vVideos.begin(); it != m_pContainer->m_vVideos.end(); ++it) { + plexclient::Video *elem = &(*it); + m_vElements.push_back(elem); + } + } + if(m_pContainer->m_vDirectories.size() > 0) { + for(std::vector<plexclient::Directory>::iterator it = m_pContainer->m_vDirectories.begin(); it != m_pContainer->m_vDirectories.end(); ++it) { + plexclient::Directory *elem = &(*it); + m_vElements.push_back(elem); + } + } + + } + + m_firstElementIter = m_vElements.begin(); + + m_pGrid->Clear(); + m_setIterator = true; + FilterElements(0); +} + +eOSState cBrowserGrid::NavigateSelect() +{ + plexclient::Directory* dir = dynamic_cast<plexclient::Directory*>(SelectedObject()); + if(dir) { + m_pContainer = m_pService->GetSection(dir->m_sKey); + ProcessData(); + return eOSState::osContinue; + } else if(dynamic_cast<cDummyElement*>(SelectedObject())) { + return NavigateBack(); + } else if(cServerElement* srv = dynamic_cast<cServerElement*>(SelectedObject())) { + m_pService = std::shared_ptr<plexclient::Plexservice>(new plexclient::Plexservice( srv->Server() ) ); + m_pContainer = m_pService->GetSection(srv->StartPath()); + m_vServerElements.clear(); + ProcessData(); + return eOSState::osContinue; + } else return eOSState::osEnd; +} + +eOSState cBrowserGrid::NavigateBack() +{ + std::shared_ptr<plexclient::MediaContainer> pCont = NULL; + if(m_pService) { + pCont = m_pService->GetLastSection(); + } + + if(pCont) { + m_pContainer = pCont; + ProcessData(); + return eOSState::osBack; + + } else if(m_bServersAreRoot) { + m_pContainer = NULL; + m_pService = NULL; + SetServerElements(); + ProcessData(); + } + return eOSState::osEnd; +} + +/* + * cDummyElement + */ + +void cDummyElement::AddTokens(std::shared_ptr<cViewGrid> grid) +{ + grid->ClearTokens(); + grid->AddIntToken("isdummy", 1); + grid->AddStringToken("title", "../"); +} + +std::string cDummyElement::GetTitle() +{ + return "Dummy"; +} + +/* + * cServerElement + */ + +cServerElement::cServerElement(plexclient::PlexServer* server, std::string startPath, std::string startName) +{ + m_pServer = server; + m_sStartPath = startPath; + m_sStartName = startName; +} + +void cServerElement::AddTokens(std::shared_ptr<cViewGrid> grid) +{ + grid->ClearTokens(); + grid->AddIntToken("isserver", 1); + grid->AddStringToken("title", m_pServer->GetServerName()); + grid->AddStringToken("serverstartpointname", m_sStartName); + grid->AddStringToken("serverip", m_pServer->GetIpAdress()); + grid->AddIntToken("serverport", m_pServer->GetPort()); + grid->AddStringToken("serverversion", m_pServer->GetVersion()); +} + +std::string cServerElement::GetTitle() +{ + return "Server"; +} diff --git a/browserGrid.h b/browserGrid.h new file mode 100644 index 0000000..36fac5c --- /dev/null +++ b/browserGrid.h @@ -0,0 +1,54 @@ +#ifndef CBROWSERGRID_H +#define CBROWSERGRID_H + +#include <memory> +#include <vector> +#include "Plexservice.h" +#include "plexgdm.h" +#include "PlexServer.h" +#include "viewGridNavigator.h" +#include "libskindesigner/osdelements.h" + +class cDummyElement : public cGridElement +{ +public: + virtual std::string GetTitle(); + virtual void AddTokens(std::shared_ptr<cViewGrid> grid); +}; + +class cServerElement : public cGridElement +{ +private: + plexclient::PlexServer* m_pServer; + std::string m_sStartPath; + std::string m_sStartName; +public: + cServerElement(plexclient::PlexServer* server, std::string startPath, std::string startName); + virtual std::string GetTitle(); + virtual void AddTokens(std::shared_ptr<cViewGrid> grid); + std::string StartPath() { return m_sStartPath; } + plexclient::PlexServer* Server() { return m_pServer; } +}; + +class cBrowserGrid : public cViewGridNavigator +{ +private: + bool m_bServersAreRoot; + std::vector<cServerElement> m_vServerElements; + + std::shared_ptr<plexclient::MediaContainer> m_pContainer; + std::shared_ptr<plexclient::Plexservice> m_pService; + cDummyElement m_Dummy; + + void ProcessData(); + void SetServerElements(); + +public: + cBrowserGrid(cViewGrid* viewGrid); + cBrowserGrid(cViewGrid* viewGrid, std::shared_ptr<plexclient::Plexservice> service); + + virtual eOSState NavigateSelect(); + virtual eOSState NavigateBack(); +}; + +#endif // CBROWSERGRID_H diff --git a/hlsPlayer.cpp b/hlsPlayer.cpp index ca1d91f..8d714d5 100644 --- a/hlsPlayer.cpp +++ b/hlsPlayer.cpp @@ -6,6 +6,7 @@ #include <Poco/Exception.h> #include <pcrecpp.h> +#include <algorithm> #include "Plexservice.h" #include "XmlObject.h" @@ -210,7 +211,7 @@ int cHlsSegmentLoader::EstimateSegmentSize() int len = m_indexParser.TargetDuration; double estSize = (bandw) * len; - estSize = max(estSize, 1.0); + estSize = std::max(estSize, 1.0); // default if(estSize <= 1) { estSize = 32; diff --git a/libskindesigner/osdelements.cpp b/libskindesigner/osdelements.cpp new file mode 100644 index 0000000..3722cbf --- /dev/null +++ b/libskindesigner/osdelements.cpp @@ -0,0 +1,205 @@ +#include "osdelements.h" + +using namespace std; + +/********************************************************************** +* cOsdElement +**********************************************************************/ +cOsdElement::cOsdElement(cSkinDisplayPlugin *view) { + this->view = view; +} + +cOsdElement::~cOsdElement() { +} + +void cOsdElement::ClearTokens(void) { + stringTokens.clear(); + intTokens.clear(); + loopTokens.clear(); +} + +void cOsdElement::AddStringToken(string key, string value) { + stringTokens.insert(pair<string,string>(key, value)); +} + +void cOsdElement::AddIntToken(string key, int value) { + intTokens.insert(pair<string,int>(key, value)); +} + +void cOsdElement::AddLoopToken(string loopName, map<string, string> &tokens) { + map<string, vector<map<string, string> > >::iterator hitLoop = loopTokens.find(loopName); + if (hitLoop == loopTokens.end()) { + vector<map<string, string> > tokenVector; + tokenVector.push_back(tokens); + loopTokens.insert(pair<string, vector<map<string, string> > >(loopName, tokenVector)); + } else { + vector<map<string, string> > *tokenVector = &hitLoop->second; + tokenVector->push_back(tokens); + } +} + +bool cOsdElement::ChannelLogoExists(string channelId) { + return view->ChannelLogoExists(channelId); +} + +string cOsdElement::GetEpgImagePath(void) { + return view->GetEpgImagePath(); +} + + +/********************************************************************** +* cViewElement +**********************************************************************/ +cViewElement::cViewElement(cSkinDisplayPlugin *view, int viewElementID) : cOsdElement(view) { + this->viewElementID = viewElementID; +} + +cViewElement::~cViewElement() { +} + +void cViewElement::Clear(void) { + if (!view) + return; + view->ClearViewElement(viewElementID); +} + +void cViewElement::Display(void) { + if (!view) + return; + view->SetViewElementIntTokens(&intTokens); + view->SetViewElementStringTokens(&stringTokens); + view->SetViewElementLoopTokens(&loopTokens); + view->DisplayViewElement(viewElementID); +} + +/********************************************************************** +* cViewGrid +**********************************************************************/ +cViewGrid::cViewGrid(cSkinDisplayPlugin *view, int viewGridID) : cOsdElement(view) { + this->viewGridID = viewGridID; +} + +cViewGrid::~cViewGrid() { +} + +void cViewGrid::SetGrid(long gridID, double x, double y, double width, double height) { + if (!view) + return; + view->SetGrid(viewGridID, gridID, x, y, width, height, &intTokens, &stringTokens); +} + +void cViewGrid::SetCurrent(long gridID, bool current) { + if (!view) + return; + view->SetGridCurrent(viewGridID, gridID, current); +} + +void cViewGrid::MoveGrid(long gridID, double x, double y, double width, double height) { + if (!view) + return; + view->SetGrid(viewGridID, gridID, x, y, width, height, NULL, NULL); +} + +void cViewGrid::Delete(long gridID) { + if (!view) + return; + view->DeleteGrid(viewGridID, gridID); +} + +void cViewGrid::Clear(void) { + if (!view) + return; + view->ClearGrids(viewGridID); +} + +void cViewGrid::Display(void) { + if (!view) + return; + view->DisplayGrids(viewGridID); +} + +/********************************************************************** +* cViewTab +**********************************************************************/ +cViewTab::cViewTab(cSkinDisplayPlugin *view) : cOsdElement(view) { +} + +cViewTab::~cViewTab() { +} + +void cViewTab::Init(void) { + view->SetTabIntTokens(&intTokens); + view->SetTabStringTokens(&stringTokens); + view->SetTabLoopTokens(&loopTokens); + view->SetTabs(); +} + +void cViewTab::Left(void) { + view->TabLeft(); +} + +void cViewTab::Right(void) { + view->TabRight(); +} + +void cViewTab::Up(void) { + view->TabUp(); +} + +void cViewTab::Down(void) { + view->TabDown(); +} + +void cViewTab::Display(void) { + if (!view) + return; + view->DisplayTabs(); +} + +/********************************************************************** +* cOsdView +**********************************************************************/ +cOsdView::cOsdView(cSkinDisplayPlugin *displayPlugin) { + this->displayPlugin = displayPlugin; +} + +cOsdView::~cOsdView() { + delete displayPlugin; +} + +void cOsdView::Deactivate(bool hide) { + if (!displayPlugin) + return; + displayPlugin->Deactivate(hide); +} + +void cOsdView::Activate(void) { + if (!displayPlugin) + return; + displayPlugin->Activate(); +} + +cViewElement *cOsdView::GetViewElement(int viewElementID) { + if (!displayPlugin) + return NULL; + return new cViewElement(displayPlugin, viewElementID); +} + +cViewGrid *cOsdView::GetViewGrid(int viewGridID) { + if (!displayPlugin) + return NULL; + displayPlugin->InitGrids(viewGridID); + return new cViewGrid(displayPlugin, viewGridID); +} + +cViewTab *cOsdView::GetViewTabs(void) { + if (!displayPlugin) + return NULL; + return new cViewTab(displayPlugin); +} + +void cOsdView::Display(void) { + if (!displayPlugin) + return; + displayPlugin->Flush(); +} diff --git a/libskindesigner/osdelements.h b/libskindesigner/osdelements.h new file mode 100644 index 0000000..147de7a --- /dev/null +++ b/libskindesigner/osdelements.h @@ -0,0 +1,93 @@ +#ifndef __OSDELEMENTS_H +#define __OSDELEMENTS_H + +using namespace std; + +#include <vdr/plugin.h> +#include "services.h" + +/********************************************************************** +* cOsdElement +**********************************************************************/ + +class cOsdElement { +protected: + cSkinDisplayPlugin *view; + map < string, string > stringTokens; + map < string, int > intTokens; + map < string, vector< map< string, string > > > loopTokens; +public: + cOsdElement(cSkinDisplayPlugin *view); + virtual ~cOsdElement(); + void AddLoopToken(string loopName, map<string, string> &tokens); + void AddStringToken(string key, string value); + void AddIntToken(string key, int value); + void ClearTokens(void); + bool ChannelLogoExists(string channelId); + string GetEpgImagePath(void); +}; + +/********************************************************************** +* cViewElement +**********************************************************************/ +class cViewElement : public cOsdElement { +private: + int viewElementID; +public: + cViewElement(cSkinDisplayPlugin *view, int viewElementID); + virtual ~cViewElement(); + void Clear(void); + void Display(void); +}; + +/********************************************************************** +* cViewGrid +**********************************************************************/ +class cViewGrid : public cOsdElement { +private: + int viewGridID; +public: + cViewGrid(cSkinDisplayPlugin *view, int viewGridID); + virtual ~cViewGrid(); + void SetGrid(long gridID, double x, double y, double width, double height); + void SetCurrent(long gridID, bool current); + void MoveGrid(long gridID, double x, double y, double width, double height); + void Delete(long gridID); + void Clear(void); + void Display(void); +}; + +/********************************************************************** +* cViewTab +**********************************************************************/ +class cViewTab : public cOsdElement { +private: +public: + cViewTab(cSkinDisplayPlugin *view); + virtual ~cViewTab(); + void Init(void); + void Left(void); + void Right(void); + void Up(void); + void Down(void); + void Display(void); +}; + +/********************************************************************** +* cOsdView +**********************************************************************/ +class cOsdView { +private: + cSkinDisplayPlugin *displayPlugin; +public: + cOsdView(cSkinDisplayPlugin *displayPlugin); + virtual ~cOsdView(); + void Deactivate(bool hide); + void Activate(void); + cViewElement *GetViewElement(int viewElementID); + cViewGrid *GetViewGrid(int viewGridID); + cViewTab *GetViewTabs(void); + void Display(void); +}; + +#endif // __OSDELEMENTS_H
\ No newline at end of file diff --git a/libskindesigner/services.h b/libskindesigner/services.h new file mode 100644 index 0000000..8fa9c69 --- /dev/null +++ b/libskindesigner/services.h @@ -0,0 +1,131 @@ +#ifndef __SKINDESIGNERSERVICES_H +#define __SKINDESIGNERSERVICES_H + +using namespace std; + +#include <string> +#include <vector> +#include <map> + +enum eMenuType { + mtList, + mtText +}; + +class cSDDisplayMenu : public cSkinDisplayMenu { +public: + virtual void SetTitle(const char *Title); + virtual void SetPluginMenu(string name, int menu, int type, bool init); + virtual bool SetItemPlugin(map<string,string> *stringTokens, map<string,int> *intTokens, map<string,vector<map<string,string> > > *loopTokens, int Index, bool Current, bool Selectable); + virtual bool SetPluginText(map<string,string> *stringTokens, map<string,int> *intTokens, map<string,vector<map<string,string> > > *loopTokens); +}; + +class cSkinDisplayPlugin { +public: + cSkinDisplayPlugin(void); + virtual ~cSkinDisplayPlugin(void); + virtual void Deactivate(bool hide); + virtual void Activate(void); + virtual void ClearViewElement(int id); + virtual void DisplayViewElement(int id); + virtual void SetViewElementIntTokens(map<string,int> *intTokens); + virtual void SetViewElementStringTokens(map<string,string> *stringTokens); + virtual void SetViewElementLoopTokens(map<string,vector<map<string,string> > > *loopTokens); + virtual void InitGrids(int viewGridID); + virtual void SetGrid(int viewGridID, long gridID, double x, double y, double width, double height, map<string,int> *intTokens, map<string,string> *stringTokens); + virtual void SetGridCurrent(int viewGridID, long gridID, bool current); + virtual void DeleteGrid(int viewGridID, long gridID); + virtual void DisplayGrids(int viewGridID); + virtual void ClearGrids(int viewGridID); + virtual void SetTabIntTokens(map<string,int> *intTokens); + virtual void SetTabStringTokens(map<string,string> *stringTokens); + virtual void SetTabLoopTokens(map<string,vector<map<string,string> > > *loopTokens); + virtual void SetTabs(void); + virtual void TabLeft(void); + virtual void TabRight(void); + virtual void TabUp(void); + virtual void TabDown(void); + virtual void DisplayTabs(void); + virtual void Flush(void); + virtual bool ChannelLogoExists(string channelId); + virtual string GetEpgImagePath(void); +}; + +/********************************************************************* +* Data Structures for Service Calls +*********************************************************************/ + +// Data structure for service "RegisterPlugin" +class RegisterPlugin { +public: + RegisterPlugin(void) { + name = ""; + }; + void SetMenu(int key, string templateName) { + menus.insert(pair<int, string>(key, templateName)); + } + void SetView(int key, string templateName) { + views.insert(pair<int, string>(key, templateName)); + } + void SetSubView(int view, int subView, string templateName) { + pair<int, string> sub = make_pair(subView, templateName); + subViews.insert(pair<int, pair<int, string> >(view, sub)); + } + void SetViewElement(int view, int viewElement, string name) { + map< int, map<int, string> >::iterator hit = viewElements.find(view); + if (hit == viewElements.end()) { + map<int, string> vE; + vE.insert(pair<int, string >(viewElement, name)); + viewElements.insert(pair<int, map < int, string > >(view, vE)); + } else { + (hit->second).insert(pair<int, string >(viewElement, name)); + } + } + void SetViewGrid(int view, int viewGrid, string name) { + map< int, map<int, string> >::iterator hit = viewGrids.find(view); + if (hit == viewGrids.end()) { + map<int, string> vG; + vG.insert(pair<int, string >(viewGrid, name)); + viewGrids.insert(pair<int, map < int, string > >(view, vG)); + } else { + (hit->second).insert(pair<int, string >(viewGrid, name)); + } + } +// in + string name; //name of plugin + map< int, string > menus; //menus as key -> templatename hashmap + map< int, string> views; //standalone views as key -> templatename hashmap + multimap< int, pair <int, string> > subViews; //subviews of standalone views as view -> (subview, templatename) multimap + map< int, map <int, string> > viewElements; //viewelements as key -> (viewelement, viewelementname) hashmap + map< int, map <int, string> > viewGrids; //viewgrids as key -> (viewgrid, viewgridname) hashmap +//out +}; + +// Data structure for service "GetDisplayMenu" +class GetDisplayMenu { +public: + GetDisplayMenu(void) { + displayMenu = NULL; + }; +// in +//out + cSDDisplayMenu *displayMenu; +}; + +// Data structure for service "GetDisplayPlugin" +class GetDisplayPlugin { +public: + GetDisplayPlugin(void) { + pluginName = ""; + viewID = -1; + subViewID = -1; + displayPlugin = NULL; + }; +// in + string pluginName; + int viewID; + int subViewID; +//out + cSkinDisplayPlugin *displayPlugin; +}; +#endif //__SKINDESIGNERSERVICES_H diff --git a/libskindesigner/skindesignerosdbase.cpp b/libskindesigner/skindesignerosdbase.cpp new file mode 100644 index 0000000..02e1558 --- /dev/null +++ b/libskindesigner/skindesignerosdbase.cpp @@ -0,0 +1,211 @@ +#include "skindesignerosdbase.h" +#include "osdelements.h" + +using namespace std; + +/********************************************************************** +* cSkindesignerOsdObject +**********************************************************************/ + +cSkindesignerOsdObject::cSkindesignerOsdObject(void) { + pSkinDesigner = NULL; + pluginName = ""; +} + +cSkindesignerOsdObject::~cSkindesignerOsdObject() { +} + +bool cSkindesignerOsdObject::InitSkindesignerInterface(string pluginName) { + this->pluginName = pluginName; + pSkinDesigner = cPluginManager::GetPlugin("skindesigner"); + if (!pSkinDesigner) { + return false; + } + return true; +} + +cOsdView *cSkindesignerOsdObject::GetOsdView(int viewID, int subViewID) { + cSkinDisplayPlugin *displayPlugin = NULL; + cOsdView *view = NULL; + GetDisplayPlugin call; + call.pluginName = pluginName; + call.viewID = viewID; + call.subViewID = subViewID; + bool ok = pSkinDesigner->Service("GetDisplayPlugin", &call); + if (ok) { + displayPlugin = call.displayPlugin; + view = new cOsdView(displayPlugin); + } + return view; +} + +/********************************************************************** +* cSkindesignerOsdItem +**********************************************************************/ +cSkindesignerOsdItem::cSkindesignerOsdItem(eOSState State) : cOsdItem(State) { + sdDisplayMenu = NULL; +} + +cSkindesignerOsdItem::cSkindesignerOsdItem(const char *Text, eOSState State, bool Selectable) : cOsdItem(Text, State, Selectable) { + sdDisplayMenu = NULL; +} + +cSkindesignerOsdItem::~cSkindesignerOsdItem() { + +} + +void cSkindesignerOsdItem::SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable) { + if (sdDisplayMenu) { + if (!sdDisplayMenu->SetItemPlugin(&stringTokens, &intTokens, &loopTokens, Index, Current, Selectable)) { + DisplayMenu->SetItem(Text(), Index, Current, Selectable); + } + } else { + DisplayMenu->SetItem(Text(), Index, Current, Selectable); + } +} + +void cSkindesignerOsdItem::AddStringToken(string key, string value) { + stringTokens.insert(pair<string,string>(key, value)); +} + +void cSkindesignerOsdItem::AddIntToken(string key, int value) { + intTokens.insert(pair<string,int>(key, value)); +} + +void cSkindesignerOsdItem::AddLoopToken(string loopName, map<string, string> &tokens) { + map<string, vector<map<string, string> > >::iterator hitLoop = loopTokens.find(loopName); + if (hitLoop == loopTokens.end()) { + vector<map<string, string> > tokenVector; + tokenVector.push_back(tokens); + loopTokens.insert(pair<string, vector<map<string, string> > >(loopName, tokenVector)); + } else { + vector<map<string, string> > *tokenVector = &hitLoop->second; + tokenVector->push_back(tokens); + } +} + + +/********************************************************************** +* cSkindesignerOsdMenu +**********************************************************************/ +cSkindesignerOsdMenu::cSkindesignerOsdMenu(const char *Title, int c0, int c1, int c2, int c3, int c4) : cOsdMenu(Title, c0, c1, c2, c3, c4) { + init = true; + displayText = false; + sdDisplayMenu = NULL; + pluginName = ""; + SetMenuCategory(mcPlugin); + SetSkinDesignerDisplayMenu(); +} + +cSkindesignerOsdMenu::~cSkindesignerOsdMenu() { + +} + +void cSkindesignerOsdMenu::SetPluginMenu(int menu, eMenuType type) { + if (type == mtList) + displayText = false; + else if (type == mtText) + displayText = true; + + if (sdDisplayMenu) { + sdDisplayMenu->SetPluginMenu(pluginName, menu, type, init); + } + init = false; +} + +bool cSkindesignerOsdMenu::SetSkinDesignerDisplayMenu(void) { + static cPlugin *pSkinDesigner = cPluginManager::GetPlugin("skindesigner"); + if (!pSkinDesigner) { + return false; + } + GetDisplayMenu call; + bool ok = pSkinDesigner->Service("GetDisplayMenu", &call); + if (ok && call.displayMenu) { + sdDisplayMenu = call.displayMenu; + return true; + } + return false; +} + +void cSkindesignerOsdMenu::ClearTokens(void) { + text = ""; + stringTokens.clear(); + intTokens.clear(); + loopTokens.clear(); +} + +void cSkindesignerOsdMenu::AddStringToken(string key, string value) { + stringTokens.insert(pair<string,string>(key, value)); +} + +void cSkindesignerOsdMenu::AddIntToken(string key, int value) { + intTokens.insert(pair<string,int>(key, value)); +} + +void cSkindesignerOsdMenu::AddLoopToken(string loopName, map<string, string> &tokens) { + map<string, vector<map<string, string> > >::iterator hitLoop = loopTokens.find(loopName); + if (hitLoop == loopTokens.end()) { + vector<map<string, string> > tokenVector; + tokenVector.push_back(tokens); + loopTokens.insert(pair<string, vector<map<string, string> > >(loopName, tokenVector)); + } else { + vector<map<string, string> > *tokenVector = &hitLoop->second; + tokenVector->push_back(tokens); + } +} + +void cSkindesignerOsdMenu::TextKeyLeft(void) { + if (!displayText) + return; + DisplayMenu()->Scroll(true, true); +} + +void cSkindesignerOsdMenu::TextKeyRight(void) { + if (!displayText) + return; + DisplayMenu()->Scroll(false, true); +} + +void cSkindesignerOsdMenu::TextKeyUp(void) { + if (!displayText) + return; + DisplayMenu()->Scroll(true, false); +} + +void cSkindesignerOsdMenu::TextKeyDown(void) { + if (!displayText) + return; + DisplayMenu()->Scroll(false, false); +} + +void cSkindesignerOsdMenu::Display(void) { + if (displayText) { + if (sdDisplayMenu) { + sdDisplayMenu->SetTitle(Title()); + if (sdDisplayMenu->SetPluginText(&stringTokens, &intTokens, &loopTokens)) { + sdDisplayMenu->Flush(); + } else { + DisplayMenu()->Clear(); + DisplayMenu()->SetTitle(Title()); + DisplayMenu()->SetText(text.c_str(), false); + DisplayMenu()->Flush(); + } + } else { + DisplayMenu()->Clear(); + DisplayMenu()->SetTitle(Title()); + DisplayMenu()->SetText(text.c_str(), false); + DisplayMenu()->Flush(); + } + return; + } + if (sdDisplayMenu) { + sdDisplayMenu->SetTitle(Title()); + for (cOsdItem *item = First(); item; item = Next(item)) { + cSkindesignerOsdItem *sdItem = dynamic_cast<cSkindesignerOsdItem*>(item); + if (sdItem) { + sdItem->SetDisplayMenu(sdDisplayMenu); + } + } + } + cOsdMenu::Display(); +} diff --git a/libskindesigner/skindesignerosdbase.h b/libskindesigner/skindesignerosdbase.h new file mode 100644 index 0000000..4c992f4 --- /dev/null +++ b/libskindesigner/skindesignerosdbase.h @@ -0,0 +1,86 @@ +#ifndef __SKINDESIGNEROSDBASE_H +#define __SKINDESIGNEROSDBASE_H + +using namespace std; + +#include <string> +#include <vector> +#include <map> +#include <set> +#include <sstream> +#include <vdr/osdbase.h> +#include <vdr/plugin.h> +#include "services.h" + +class cOsdView; + +/********************************************************************** +* cSkindesignerOsdObject +**********************************************************************/ +class cSkindesignerOsdObject : public cOsdObject { +protected: + string pluginName; + cPlugin *pSkinDesigner; + bool InitSkindesignerInterface(string pluginName); + cOsdView *GetOsdView(int viewID, int subViewID = -1); +public: + cSkindesignerOsdObject(void); + virtual ~cSkindesignerOsdObject(); + virtual void Show(void) {}; +}; + +/********************************************************************** +* cSkindesignerOsdItem +**********************************************************************/ +class cSkindesignerOsdItem : public cOsdItem { +private: + cSDDisplayMenu *sdDisplayMenu; + map < string, string > stringTokens; + map < string, int > intTokens; + map < string, vector< map< string, string > > > loopTokens; +protected: +public: + cSkindesignerOsdItem(eOSState State = osUnknown); + cSkindesignerOsdItem(const char *Text, eOSState State = osUnknown, bool Selectable = true); + virtual ~cSkindesignerOsdItem(); + virtual void SetMenuItem(cSkinDisplayMenu *DisplayMenu, int Index, bool Current, bool Selectable); + void SetDisplayMenu(cSDDisplayMenu *sdDisplayMenu) { this->sdDisplayMenu = sdDisplayMenu; }; + void AddStringToken(string key, string value); + void AddIntToken(string key, int value); + void AddLoopToken(string loopName, map<string, string> &tokens); +}; + +/********************************************************************** +* cSkindesignerOsdMenu +**********************************************************************/ +class cSkindesignerOsdMenu : public cOsdMenu { +private: + bool init; + bool displayText; + string pluginName; + cSDDisplayMenu *sdDisplayMenu; + string text; + map < string, string > stringTokens; + map < string, int > intTokens; + map < string, vector< map< string, string > > > loopTokens; + bool SetSkinDesignerDisplayMenu(void); +protected: + void ClearTokens(void); + void SetPluginName(string name) {pluginName = name; }; + void SetPluginMenu(int menu, eMenuType type); + void SetText(string text) { this->text = text; }; + void AddStringToken(string key, string value); + void AddIntToken(string key, int value); + void AddLoopToken(string loopName, map<string, string> &tokens); + void TextKeyLeft(void); + void TextKeyRight(void); + void TextKeyUp(void); + void TextKeyDown(void); +public: + cSkindesignerOsdMenu(const char *Title, int c0 = 0, int c1 = 0, int c2 = 0, int c3 = 0, int c4 = 0); + virtual ~cSkindesignerOsdMenu(); + virtual void Display(void); +}; + +#endif // __SKINDESIGNEROSDBASE_H + @@ -2,6 +2,9 @@ #include "SubscriptionManager.h" #include "plex.h" #include "plexOsd.h" +#include "plexSdOsd.h" + +#include "libskindesigner/services.h" ////////////////////////////////////////////////////////////////////////////// // cPlugin @@ -51,6 +54,27 @@ const char *cMyPlugin::Description(void) bool cMyPlugin::Start(void) { + std::string cacheDir = cPlugin::CacheDirectory(PLUGIN_NAME_I18N); + + RegisterPlugin reg; + reg.name = "plex"; + + reg.SetView(viRootView, "root.xml"); + reg.SetViewGrid(eViews::viRootView, eViewGrids::vgBrowser, "browser"); + reg.SetViewElement(viRootView, verHeader, "header"); + + //reg.SetViewElement(viRootView, verHeader, "header"); + //reg.SetViewElement(viRootView, verFooter, "footer"); + + //reg.SetView(eViews::viBrowserView, "browser.xml"); + + + static cPlugin *pSkinDesigner = cPluginManager::GetPlugin("skindesigner"); + if (pSkinDesigner) { + pSkinDesigner->Service("RegisterPlugin", ®); + } else { + esyslog("[plex]: skindesigner not available"); + } return true; } @@ -83,7 +107,13 @@ const char *cMyPlugin::MainMenuEntry(void) cOsdObject *cMyPlugin::MainMenuAction(void) { //dsyslog("[plex]%s:\n", __FUNCTION__); - return cPlexMenu::ProcessMenu(); + /*bool skinDesignerAvailable = InitSkindesignerInterface("plex"); + if (skinDesignerAvailable) { + //cOsdView *rootView = GetOsdView(viRootView); + return new cPlexSdOsd(); + } + return cPlexMenu::ProcessMenu();*/ + return new cPlexSdOsd(); } /** diff --git a/plexOsd.cpp b/plexOsd.cpp index 55f26b3..8a54cc8 100644 --- a/plexOsd.cpp +++ b/plexOsd.cpp @@ -165,48 +165,6 @@ eOSState cPlexBrowser::ProcessSelected() } -cPlexInfo::cPlexInfo(plexclient::Video* video) : cOsdMenu(video->GetTitle().c_str()) -{ - cOsdMenu::Display(); - - Add(new cOsdItem(video->m_sSummary.c_str())); -} - -eOSState cPlexInfo::ProcessKey(eKeys Key) -{ - switch (int(Key)) { - case kUp|k_Repeat: - case kUp: - case kDown|k_Repeat: - case kDown: - case kLeft|k_Repeat: - case kLeft: - case kRight|k_Repeat: - case kRight: - DisplayMenu()->Scroll(NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft, NORMALKEY(Key) == kLeft || NORMALKEY(Key) == kRight); - cStatus::MsgOsdTextItem(NULL, NORMALKEY(Key) == kUp || NORMALKEY(Key) == kLeft); - return osContinue; - case kInfo: - return osBack; - default: - break; - } - - eOSState state = cOsdMenu::ProcessKey(Key); - - if (state == osUnknown) { - switch (Key) { - case kGreen: - cRemote::Put(Key, true); - case kOk: - return osBack; - default: - break; - } - } - return state; -} - ////////////////////////////////////////////////////////////////////////////// // cOsdMenu ////////////////////////////////////////////////////////////////////////////// @@ -214,10 +172,10 @@ eOSState cPlexInfo::ProcessKey(eKeys Key) menuShow cPlexMenu::eShow = MAIN; /** -** Play menu constructor. +** Plex menu constructor. */ cPlexMenu::cPlexMenu(const char *title, int c0, int c1, int c2, int c3, int c4) - :cOsdMenu(title, c0, c1, c2, c3, c4) + :cOsdMenu(title) { SetHasHotkeys(); @@ -19,11 +19,9 @@ enum menuShow { MAIN, - BROWSER, - INFO + BROWSER }; - /* * Plex Browser */ @@ -56,13 +54,6 @@ public: }; -class cPlexInfo : public cOsdMenu -{ - -public: - cPlexInfo(plexclient::Video* video); - virtual eOSState ProcessKey(eKeys Keys); -}; /** ** Play plugin menu class. @@ -71,6 +62,7 @@ class cPlexMenu:public cOsdMenu { private: + void SetRootMenu(); public: cPlexMenu(const char *, int = 0, int = 0, int = 0, int = 0, int = 0); virtual eOSState ProcessKey(eKeys); diff --git a/plexSdOsd.cpp b/plexSdOsd.cpp new file mode 100644 index 0000000..e6dc1f9 --- /dev/null +++ b/plexSdOsd.cpp @@ -0,0 +1,104 @@ +#include "plexSdOsd.h" + +cPlexSdOsd::cPlexSdOsd() +{ +} + +void cPlexSdOsd::Show(void) +{ + bool skinDesignerAvailable = InitSkindesignerInterface("plex"); + if (!skinDesignerAvailable) { + return; + } + + m_pRootView = GetOsdView(eViews::viRootView); + if (!m_pRootView) { + esyslog("[plex]: used skindesigner skin does not support plex"); + return; + } + + m_pViewHeader = std::shared_ptr<cViewHeader>( + new cViewHeader(m_pRootView->GetViewElement(eViewElementsRoot::verHeader)) + ); + m_pBrowserGrid = std::shared_ptr<cBrowserGrid>( + new cBrowserGrid( m_pRootView->GetViewGrid(eViewGrids::vgBrowser)) + ); + + Flush(); +} + +void cPlexSdOsd::Flush() +{ + m_pBrowserGrid->Flush(); + + m_pViewHeader->Draw(); + + m_pRootView->Display(); +} + +eOSState cPlexSdOsd::ProcessKey(eKeys Key) +{ + switch (Key & ~k_Repeat) { + case kUp: + m_pBrowserGrid->NavigateUp(); + Flush(); + break; + case kDown: + m_pBrowserGrid->NavigateDown(); + Flush(); + break; + case kLeft: + m_pBrowserGrid->NavigateLeft(); + Flush(); + break; + case kRight: + m_pBrowserGrid->NavigateRight(); + Flush(); + break; + case kOk: + // Play movie or change dir + m_pBrowserGrid->NavigateSelect(); + Flush(); + break; + case kBack: + m_pBrowserGrid->NavigateBack(); + Flush(); + break; + case kRed: + // Prev Tab + SwitchGrid(m_pViewHeader->NextTab()); + Flush(); + break; + case kGreen: + // Next Tab + SwitchGrid(m_pViewHeader->PrevTab()); + Flush(); + break; + default: + break; + } + return eOSState::osContinue; +} + +void cPlexSdOsd::SwitchGrid(ePlexMenuTab currentTab) +{ + if(currentTab == ePlexMenuTab::pmtOnDeck) { + + auto service = std::shared_ptr<plexclient::Plexservice>(new plexclient::Plexservice( new plexclient::PlexServer("192.168.1.175", 32400), "/hubs/home/onDeck" ) ); + m_pBrowserGrid = std::shared_ptr<cBrowserGrid>( + new cBrowserGrid( m_pRootView->GetViewGrid(eViewGrids::vgBrowser), service) + ); + + } else if(currentTab == ePlexMenuTab::pmtRecentlyAdded) { + auto service = std::shared_ptr<plexclient::Plexservice>(new plexclient::Plexservice( new plexclient::PlexServer("192.168.1.175", 32400), "/library/sections" ) ); + m_pBrowserGrid = std::shared_ptr<cBrowserGrid>( + new cBrowserGrid( m_pRootView->GetViewGrid(eViewGrids::vgBrowser), service) + ); + + } else if(currentTab == ePlexMenuTab::pmtLibrary) { + + m_pBrowserGrid = std::shared_ptr<cBrowserGrid>( + new cBrowserGrid( m_pRootView->GetViewGrid(eViewGrids::vgBrowser)) + ); + } +} diff --git a/plexSdOsd.h b/plexSdOsd.h new file mode 100644 index 0000000..1f7c677 --- /dev/null +++ b/plexSdOsd.h @@ -0,0 +1,55 @@ +#ifndef CPLEXSDOSD_H +#define CPLEXSDOSD_H + +#include <vdr/osdbase.h> + +#include <iostream> +#include <string> +#include <vector> +#include <iterator> +#include <algorithm> +#include <memory> + +#include "Config.h" +#include "Plexservice.h" + +#include "plexgdm.h" +#include "hlsPlayerControl.h" + +#include "browserGrid.h" +#include "viewHeader.h" +#include "libskindesigner/osdelements.h" +#include "libskindesigner/skindesignerosdbase.h" + +enum eViews { + viRootView, + viDetailView +}; + +enum eViewElementsRoot { + verHeader, + verFooter +}; + +enum eViewGrids { + vgBrowser +}; + +class cPlexSdOsd : public cSkindesignerOsdObject +{ +private: + std::shared_ptr<cBrowserGrid> m_pBrowserGrid; + std::shared_ptr<cViewHeader> m_pViewHeader; + cOsdView* m_pRootView; + + void Flush(); + void SwitchGrid(ePlexMenuTab currentTab); + +public: + cPlexSdOsd(); + virtual void Show(void); + virtual eOSState ProcessKey(eKeys Key); + +}; + +#endif // CPLEXSDOSD_H diff --git a/po/de_DE.po b/po/de_DE.po index a283e4e..ce76e7d 100644 --- a/po/de_DE.po +++ b/po/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: vdr-plex 0.1.0\n" "Report-Msgid-Bugs-To: <see README>\n" -"POT-Creation-Date: 2015-03-05 20:04+0100\n" +"POT-Creation-Date: 2015-03-15 11:38+0100\n" "PO-Revision-Date: 2015-03-05 20:08+0200\n" "Last-Translator: Chris <zerov83@gmail.com>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -60,6 +60,10 @@ msgstr "Untertitelspuren" msgid "None" msgstr "Leer" +#, c-format +msgid "To start from %ld minutes, press Ok." +msgstr "Wiedergabe ab Minute %ld starten?" + msgid "Info" msgstr "Info" @@ -87,10 +91,6 @@ msgstr "Kein Plexmediaserver gefunden." msgid "Browse Plex" msgstr "Durchsuche Plex" -#, c-format -msgid "To start from %ld minutes, press Ok." -msgstr "Wiedergabe ab Minute %ld starten?" - msgid "All Movies" msgstr "Alle Filme" diff --git a/skins/blackhole/xmlfiles/plug-plex-root.xml b/skins/blackhole/xmlfiles/plug-plex-root.xml new file mode 100644 index 0000000..c937ce7 --- /dev/null +++ b/skins/blackhole/xmlfiles/plug-plex-root.xml @@ -0,0 +1,58 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE displayplugin SYSTEM "../../../dtd/displayplugin.dtd"> + +<displayplugin x="0" y="0" width="100%" height="100%" fadetime="0" scaletvx="0" scaletvy="0" scaletvwidth="100%" scaletvheight="100%"> + <!-- Tokens available in header + {title} + {istab1active} + {tab1name} + {istab2active} + {tab2name} + {istab3active} + {tab3name} + --> + <viewelement name="header"> + <area layer="1" x="0" y="0" width="100%" height="15%"> + <drawtext x="1%" y="5%" width="98%" font="{light}" fontsize="30%" color="{clrWhite}" text="Plex for VDR" /> + <drawtext condition="{istab1active}" x="1%" y="20%" width="98%" font="{light}" fontsize="30%" color="{clrWhite}" text="{tab1name}" /> + <drawtext condition="{istab2active}" x="1%" y="20%" width="98%" font="{light}" fontsize="30%" color="{clrWhite}" text="{tab2name}" /> + <drawtext condition="{istab3active}" x="1%" y="20%" width="98%" font="{light}" fontsize="305%" color="{clrWhite}" text="{tab3name}" /> + </area> + </viewelement> + + <!-- Tokens available in browser + {current} Currently active element + {title} Name of the element + {year} + {cover} Image + + {isdummy} Condition + + {isserver} Condition + {serverstartpointname} + {serverip} + {serverport} + {serverversion} + + {isdirectory} Condition + {isshow} Condition + {isseason} Condition + + {ismovie} + + {isepisode} + + --> + <grid name="browser" x="0" y="15%" width="100%" height="85%"> + <area layer="2"> + <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" /> + <drawtext condition="{isserver}" x="1%" y="40%" width="98%" font="{light}" fontsize="5%" color="{clrWhite}" text="Server" /> + <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" /> + <drawtext condition="{isepisode}" x="1%" y="40%" width="98%" font="{light}" fontsize="5%" color="{clrWhite}" text="Episode" /> + </area> + </grid> + +</displayplugin> diff --git a/viewGridNavigator.cpp b/viewGridNavigator.cpp new file mode 100644 index 0000000..78781ca --- /dev/null +++ b/viewGridNavigator.cpp @@ -0,0 +1,158 @@ +#include "viewGridNavigator.h" + +unsigned int cGridElement::AbsoluteGridIdCounter = 0; + +cGridElement::cGridElement() +{ + m_iGridId = AbsoluteGridIdCounter++; + Position = -1; + m_bInit = true; +} + +cViewGridNavigator::cViewGridNavigator(cViewGrid* viewGrid) +{ + m_columns = 2; + m_rows = 2; + m_newDimensions = true; + m_setIterator = true; + + m_pGrid = std::shared_ptr<cViewGrid>(viewGrid); +} + + +void cViewGridNavigator::FilterElements(int scrollOffset) +{ + int startOffset = scrollOffset; + int endOffset = startOffset + (m_rows * m_columns); + if(scrollOffset < 0) { + endOffset = (m_rows * m_columns) + scrollOffset; + } + + std::vector<cGridElement*>::iterator begin = m_firstElementIter + startOffset; + std::vector<cGridElement*>::iterator end = m_firstElementIter + endOffset; + if(end > m_vElements.end()) end = m_vElements.end(); + + int pos = 0; + for(std::vector<cGridElement*>::iterator it = begin; it != end; ++it) { + cGridElement *elem = *it; + elem->Position = pos++; + SetGridElementData(elem); + } + + if(m_setIterator) { + m_activeElementIter = begin; + m_pGrid->SetCurrent((*m_activeElementIter)->GridElementId(), true); + m_setIterator = false; + } + + //remove non visible elements from grid + if(scrollOffset !=0 ) { + auto startIt = m_firstElementIter; + auto endIt = m_firstElementIter + scrollOffset; + if(scrollOffset < 0) { + startIt = m_lastElementIter + scrollOffset; + endIt = m_lastElementIter; + } + if(startIt < m_vElements.begin()) startIt = m_vElements.begin(); + if(endIt > m_vElements.end()) endIt = m_vElements.end(); + + for(std::vector<cGridElement*>::iterator it = startIt; it != endIt; ++it) { + m_pGrid->Delete((*it)->GridElementId()); + (*it)->Dirty(); + (*it)->Position = -1; + } + } + + m_firstElementIter = begin; + m_lastElementIter = end; + m_newDimensions = false; +} + +void cViewGridNavigator::SetGridElementData(cGridElement *obj) +{ + // calculate position + double row, column, x, y, height, width; + + row = floor(obj->Position / m_columns); + column = obj->Position - (row * m_columns); + width = 1.0 / m_columns; + height = 1.0 / m_rows; + x = width * column; + y= height * row; + + //std::cout << "ID: " << obj->GridElementId() << "\tPos: " << obj->Position << "\t\tx: " << x << "\t\ty: " << y << "\t\twi: " << width << "\t\thei: " << height << "\tCol: " << column << "\tRow: " << row << std::endl; + + if(obj->IsNew() || m_newDimensions) { + // fill data + obj->AddTokens(m_pGrid); + m_pGrid->SetGrid(obj->GridElementId(), x, y, width, height); + obj->InitFinished(); + } else { + m_pGrid->MoveGrid(obj->GridElementId(), x, y, width, height); + } +} + +void cViewGridNavigator::SetGridDimensions(int rows, int columns) +{ + m_rows = rows; + m_columns = columns; + m_newDimensions = true; +} + +void cViewGridNavigator::NavigateDown() +{ + if(m_activeElementIter + m_columns >= m_vElements.end()) return; + auto next = m_activeElementIter + m_columns; + // scroll down? + if(!(*next)->IsVisible()) { + FilterElements(m_columns); + } + + m_pGrid->SetCurrent((*m_activeElementIter)->GridElementId(), false); + m_pGrid->SetCurrent((*next)->GridElementId(), true); + m_activeElementIter = next; +} + +void cViewGridNavigator::NavigateUp() +{ + if(m_activeElementIter - m_columns < m_vElements.begin()) return; + auto next = m_activeElementIter - m_columns; + //scroll up? + if(!(*next)->IsVisible()) { + FilterElements(-m_columns); + } + + m_pGrid->SetCurrent((*m_activeElementIter)->GridElementId(), false); + m_pGrid->SetCurrent((*next)->GridElementId(), true); + m_activeElementIter = next; +} + +void cViewGridNavigator::NavigateLeft() +{ + auto next = m_activeElementIter - 1; + if(next < m_vElements.begin()) next = m_vElements.begin(); + + if(!(*next)->IsVisible()) { + auto temp = m_activeElementIter; + FilterElements(-m_columns); + m_activeElementIter = temp; + } + + m_pGrid->SetCurrent((*m_activeElementIter)->GridElementId(), false); + m_pGrid->SetCurrent((*next)->GridElementId(), true); + m_activeElementIter = next; +} + +void cViewGridNavigator::NavigateRight() +{ + auto next = m_activeElementIter + 1; + if(next >= m_vElements.end()) next = m_vElements.end()-1; + + if(!(*next)->IsVisible()) { + FilterElements(m_columns); + } + + m_pGrid->SetCurrent((*m_activeElementIter)->GridElementId(), false); + m_pGrid->SetCurrent((*next)->GridElementId(), true); + m_activeElementIter = next; +} diff --git a/viewGridNavigator.h b/viewGridNavigator.h new file mode 100644 index 0000000..cc17dd5 --- /dev/null +++ b/viewGridNavigator.h @@ -0,0 +1,61 @@ +#ifndef CVIEWGRIDNAVIGATOR_H +#define CVIEWGRIDNAVIGATOR_H + +#include <memory> +#include <vector> +#include "libskindesigner/osdelements.h" + +class cGridElement +{ +private: + bool m_bInit; + unsigned int m_iGridId; + static unsigned int AbsoluteGridIdCounter; + +public: + cGridElement(); + + bool IsNew() { return m_bInit; }; + void Dirty() { m_bInit = true; }; + void InitFinished() { m_bInit = false; }; + unsigned int GridElementId() { return m_iGridId; } + bool IsVisible() { return Position > -1; } + virtual void AddTokens(std::shared_ptr<cViewGrid> grid) = 0; + int Position; +}; + +class cViewGridNavigator +{ +protected: + int m_rows; + int m_columns; + + std::shared_ptr<cViewGrid> m_pGrid; + + bool m_newDimensions; + bool m_setIterator; + std::vector<cGridElement*> m_vElements; + std::vector<cGridElement*>::iterator m_activeElementIter; + std::vector<cGridElement*>::iterator m_firstElementIter; + std::vector<cGridElement*>::iterator m_lastElementIter; + + void GenerateServerElements(); + void FilterElements(int scrollOffset); + void SetGridElementData(cGridElement *obj); + +public: + cViewGridNavigator(cViewGrid* viewGrid); + void SetGridDimensions(int rows, int columns); + void Flush() { m_pGrid->Display(); }; + void DrawGrid() { m_pGrid->Display(); } + virtual void NavigateLeft(); + virtual void NavigateRight(); + virtual void NavigateUp(); + virtual void NavigateDown(); + virtual eOSState NavigateSelect() = 0; + virtual eOSState NavigateBack() = 0; + cGridElement* SelectedObject() { return *m_activeElementIter; } + +}; + +#endif // CVIEWGRIDNAVIGATOR_H diff --git a/viewHeader.cpp b/viewHeader.cpp new file mode 100644 index 0000000..932ef24 --- /dev/null +++ b/viewHeader.cpp @@ -0,0 +1,61 @@ +#include "viewHeader.h" + +cViewHeader::cViewHeader(cViewElement* viewElem) +{ + m_pViewElem = std::shared_ptr<cViewElement>(viewElem); + m_eCurrentTab = ePlexMenuTab::pmtOnDeck; +} + +void cViewHeader::Draw() +{ + m_pViewElem->ClearTokens(); + + switch(m_eCurrentTab) { + case ePlexMenuTab::pmtOnDeck: + m_pViewElem->AddIntToken("istab1active", 1); + m_pViewElem->AddStringToken("tab1name", "On Deck"); + break; + case ePlexMenuTab::pmtRecentlyAdded: + m_pViewElem->AddIntToken("istab2active", 1); + m_pViewElem->AddStringToken("tab2name", "Recently Added"); + break; + case ePlexMenuTab::pmtLibrary: + m_pViewElem->AddIntToken("istab3active", 1); + m_pViewElem->AddStringToken("tab3name", "Library"); + break; + } + + m_pViewElem->Display(); +} + +ePlexMenuTab cViewHeader::NextTab() +{ + switch(m_eCurrentTab) { + case ePlexMenuTab::pmtOnDeck: + m_eCurrentTab = ePlexMenuTab::pmtRecentlyAdded; + break; + case ePlexMenuTab::pmtRecentlyAdded: + m_eCurrentTab = ePlexMenuTab::pmtLibrary; + break; + case ePlexMenuTab::pmtLibrary: + m_eCurrentTab = ePlexMenuTab::pmtOnDeck; + break; + } + return m_eCurrentTab; +} + +ePlexMenuTab cViewHeader::PrevTab() +{ + switch(m_eCurrentTab) { + case ePlexMenuTab::pmtOnDeck: + m_eCurrentTab = ePlexMenuTab::pmtLibrary; + break; + case ePlexMenuTab::pmtRecentlyAdded: + m_eCurrentTab = ePlexMenuTab::pmtOnDeck; + break; + case ePlexMenuTab::pmtLibrary: + m_eCurrentTab = ePlexMenuTab::pmtRecentlyAdded; + break; + } + return m_eCurrentTab; +} diff --git a/viewHeader.h b/viewHeader.h new file mode 100644 index 0000000..afdb38f --- /dev/null +++ b/viewHeader.h @@ -0,0 +1,27 @@ +#ifndef CVIEWHEADER_H +#define CVIEWHEADER_H + +#include <memory> +#include "libskindesigner/osdelements.h" + +enum ePlexMenuTab { + pmtOnDeck, + pmtRecentlyAdded, + pmtLibrary +}; + +class cViewHeader +{ +private: + ePlexMenuTab m_eCurrentTab; + std::shared_ptr<cViewElement> m_pViewElem; + +public: + cViewHeader(cViewElement* viewElem); + void Draw(); + ePlexMenuTab NextTab(); + ePlexMenuTab PrevTab(); + ePlexMenuTab CurrentTab() { return m_eCurrentTab; } +}; + +#endif // CVIEWHEADER_H |