#include "ControlServer.h" #include "SubscriptionManager.h" #include "plex.h" static const char *DESCRIPTION = "Plex for VDR Plugin"; static const char *MAINMENUENTRY = "Plex for VDR"; ////////////////////////////////////////////////////////////////////////////// //static char ConfigHideMainMenuEntry; ///< hide main menu entry //char ConfigDisableRemote; ///< disable remote during external play /** ** Play a file. ** ** @param filename path and file name */ static void PlayFile(plexclient::Video* pVid) { isyslog("[plex]: play file '%s'\n", pVid->m_sKey.c_str()); cControl::Launch(cHlsPlayerControl::Create(pVid)); } ////////////////////////////////////////////////////////////////////////////// // cOsdMenu ////////////////////////////////////////////////////////////////////////////// static char ShowBrowser; ///< flag show browser static plexclient::PlexServer* pPlexServer; cPlexBrowser::cPlexBrowser(const char *title, plexclient::PlexServer* pServ) :cOsdMenu(title) { dsyslog("[plex]%s:\n", __FUNCTION__); pService = new plexclient::Plexservice(pServ); pService->Authenticate(); pCont = pService->GetAllSections(); CreateMenu(); } cPlexBrowser::~cPlexBrowser() { delete pService; } void cPlexBrowser::CreateMenu() { // Clear Menu Clear(); // Directory or Video? if(pCont->m_vDirectories.size() > 0) { for(std::vector::iterator it = pCont->m_vDirectories.begin(); it != pCont->m_vDirectories.end(); ++it) { plexclient::Directory *pDir = &(*it); Add(new cPlexOsdItem( pDir->m_sTitle.c_str(), pDir) ); } } if(pCont->m_vVideos.size() > 0) { for(std::vector::iterator it = pCont->m_vVideos.begin(); it != pCont->m_vVideos.end(); ++it) { plexclient::Video *vid = &(*it); // cast raw pointer Add(new cPlexOsdItem( vid->m_sTitle.c_str(), vid) ); } } if(Count() < 1) { Add(new cPlexOsdItem("Empty")); } Display(); } eOSState cPlexBrowser::ProcessKey(eKeys key) { eOSState state; // call standard function state = cOsdMenu::ProcessKey(key); if (state || key != kNone) { dsyslog("[plex]%s: state=%d key=%d\n", __FUNCTION__, state, key); } switch (state) { case osUnknown: switch (key) { case kOk: return ProcessSelected(); case kBack: return LevelUp(); default: break; } break; case osBack: state = LevelUp(); if (state == osEnd) { // top level reached return osPlugin; } default: break; } return state; } eOSState cPlexBrowser::LevelUp() { if(m_vStack.size() <= 1){ m_vStack.clear(); ShowBrowser = 0; return osEnd; } m_vStack.pop_back(); std::string uri; for(unsigned int i = 0; i < m_vStack.size(); i++) { if(m_vStack[i][0]=='/') { uri = m_vStack[i]; continue; } uri += m_vStack[i]; if(i+1 < m_vStack.size()) { uri += "/"; } } pCont = pService->GetSection(uri); CreateMenu(); return osContinue; } eOSState cPlexBrowser::ProcessSelected() { int current = Current(); // get current menu item index cPlexOsdItem *item = static_cast(Get(current)); if(item->IsVideo()) { plexclient::Video* pVid = item->GetAttachedVideo(); PlayFile(pVid); return osEnd; } if(item->IsDir()) { plexclient::Directory* pDir = item->GetAttachedDirectory(); m_vStack.push_back(pDir->m_sKey); std::string uri; for(unsigned int i = 0; i < m_vStack.size(); i++) { if(m_vStack[i][0]=='/') { uri = m_vStack[i]; continue; } uri += m_vStack[i]; if(i+1 < m_vStack.size()) { uri += "/"; } } std::cout << "m_sSection: " << uri << std::endl; pCont = pService->GetSection(uri); CreateMenu(); return osContinue; } //return osEnd; return osContinue; } ////////////////////////////////////////////////////////////////////////////// // cOsdMenu ////////////////////////////////////////////////////////////////////////////// /** ** Play menu constructor. */ cPlayMenu::cPlayMenu(const char *title, int c0, int c1, int c2, int c3, int c4) :cOsdMenu(title, c0, c1, c2, c3, c4) { SetHasHotkeys(); for(std::vector::iterator it = plexclient::plexgdm::GetInstance().GetPlexservers().begin(); it != plexclient::plexgdm::GetInstance().GetPlexservers().end(); ++it) { plexclient::PlexServer *pServer = &(*it); Add(new cPlexOsdItem(pServer->GetServerName().c_str(), pServer)); } if(Count() < 1) { Add(new cPlexOsdItem("No Plex Media Server found."), false); } } /** ** Play menu destructor. */ cPlayMenu::~cPlayMenu() { } /** ** Handle play plugin menu key event. ** ** @param key key event */ eOSState cPlayMenu::ProcessKey(eKeys key) { eOSState state; if (key != kNone) { dsyslog("[plex]%s: key=%d\n", __FUNCTION__, key); } // call standard function state = cOsdMenu::ProcessKey(key); int current = Current(); // get current menu item index cPlexOsdItem *item = static_cast(Get(current)); switch (state) { case osUnknown: switch (key) { case kOk: pPlexServer = item->GetAttachedServer(); ShowBrowser = 1; return osPlugin; // restart with OSD browser default: break; } default: break; } return state; } ////////////////////////////////////////////////////////////////////////////// // cPlugin ////////////////////////////////////////////////////////////////////////////// /** ** Initialize any member variables here. ** ** @note DON'T DO ANYTHING ELSE THAT MAY HAVE SIDE EFFECTS, REQUIRE GLOBAL ** VDR OBJECTS TO EXIST OR PRODUCE ANY OUTPUT! */ cMyPlugin::cMyPlugin(void) { dsyslog("[plex]%s:\n", __FUNCTION__); } /** ** Clean up after yourself! */ cMyPlugin::~cMyPlugin(void) { dsyslog("[plex]%s:\n", __FUNCTION__); plexclient::plexgdm::GetInstance().stopRegistration(); plexclient::ControlServer::GetInstance().Stop(); } /** ** Return plugin version number. ** ** @returns version number as constant string. */ const char *cMyPlugin::Version(void) { return VERSION; } /** ** Return plugin short description. ** ** @returns short description as constant string. */ const char *cMyPlugin::Description(void) { return DESCRIPTION; } /** ** Start any background activities the plugin shall perform. */ bool cMyPlugin::Initialize(void) { // First Startup? Save UUID SetupStore("UUID", Config::GetInstance().GetUUID().c_str()); plexclient::plexgdm::GetInstance().discover(); if (plexclient::plexgdm::GetInstance().GetPlexservers().size() > 0) { plexclient::plexgdm::GetInstance().clientDetails(Config::GetInstance().GetUUID(), DESCRIPTION, "3200", "VDR", VERSION); plexclient::plexgdm::GetInstance().Start(); plexclient::ControlServer::GetInstance().Start(); } else { esyslog("[plex]No Plexmediaserver found"); } return true; } /** ** Create main menu entry. */ const char *cMyPlugin::MainMenuEntry(void) { return Config::GetInstance().HideMainMenuEntry ? NULL : MAINMENUENTRY; } /** ** Perform the action when selected from the main VDR menu. */ cOsdObject *cMyPlugin::MainMenuAction(void) { //dsyslog("[plex]%s:\n", __FUNCTION__); if (ShowBrowser) { return new cPlexBrowser("Browse Plex", pPlexServer); } return new cPlayMenu("Plex"); } /** ** Called for every plugin once during every cycle of VDR's main program ** loop. */ void cMyPlugin::MainThreadHook(void) { // dsyslog("[plex]%s:\n", __FUNCTION__); // Start Tasks, e.g. Play Video if(plexclient::ActionManager::GetInstance().IsAction()) { std::string file = plexclient::ActionManager::GetInstance().GetAction(); //PlayFile(file, NULL); } } /** ** Return our setup menu. */ cMenuSetupPage *cMyPlugin::SetupMenu(void) { //dsyslog("[plex]%s:\n", __FUNCTION__); return new cMyMenuSetupPage; } /** ** Parse setup parameters ** ** @param name paramter name (case sensetive) ** @param value value as string ** ** @returns true if the parameter is supported. */ bool cMyPlugin::SetupParse(const char *name, const char *value) { //dsyslog("[plex]%s: '%s' = '%s'\n", __FUNCTION__, name, value); if (strcasecmp(name, "HideMainMenuEntry") == 0) Config::GetInstance().HideMainMenuEntry = atoi(value) ? true : false; else if (strcasecmp(name, "Username") == 0) Config::GetInstance().s_username = std::string(value); else if (strcasecmp(name, "Password") == 0) Config::GetInstance().s_password = std::string(value); else if (strcasecmp(name, "UUID") == 0) Config::GetInstance().SetUUID(value); else return false; return true; } VDRPLUGINCREATOR(cMyPlugin); // Don't touch this!