#include "ControlServer.h" #include "SubscriptionManager.h" #include "plex.h" /** ** Play a file. ** ** @param filename path and file name */ static void PlayFile(plexclient::Video Vid) { isyslog("[plex]: play file '%s'\n", Vid.m_sKey.c_str()); cControl* control = cHlsPlayerControl::Create(Vid); if(control) { cControl::Launch(control); } } ////////////////////////////////////////////////////////////////////////////// // cOsdMenu ////////////////////////////////////////////////////////////////////////////// static char ShowBrowser; ///< flag show browser static std::shared_ptr pPlexService; cPlexBrowser::cPlexBrowser(const char *title, std::shared_ptr Service) :cOsdMenu(title) { dsyslog("[plex]%s:\n", __FUNCTION__); pService = Service; pService->Authenticate(); pCont = pService->GetSection(pService->StartUri); SetMenuCategory(mcRecording); CreateMenu(); } void cPlexBrowser::CreateMenu() { // Clear Menu Clear(); // Directory or Video? if(pCont && 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->GetTitle().c_str(), pDir) ); } } if(pCont && 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->GetTitle().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() { pCont = pService->GetLastSection(); if(!pCont) { ShowBrowser = 0; return osEnd; } CreateMenu(); return osContinue; } eOSState cPlexBrowser::ProcessSelected() { int current = Current(); // get current menu item index cPlexOsdItem *item = static_cast(Get(current)); if(item->IsVideo()) { PlayFile(*item->GetAttachedVideo()); return osEnd; } if(item->IsDir()) { plexclient::Directory* pDir = item->GetAttachedDirectory(); pCont = pService->GetSection(pDir->m_sKey); //SetTitle(pDir->m_sTitle); CreateMenu(); return osContinue; } //return osEnd; return osContinue; } 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 ////////////////////////////////////////////////////////////////////////////// /** ** 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) { //&(*it) auto s1 = std::make_shared( &(*it) ); s1->StartUri = "/library/sections"; Add(new cPlexOsdItem(Poco::format("%s - Library", it->GetServerName()).c_str(), s1)); auto s2 = std::make_shared( &(*it) ); s2->StartUri = "/video"; Add(new cPlexOsdItem(Poco::format("%s - Video Channels", it->GetServerName()).c_str(), s2 )); } 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: pPlexService = item->GetAttachedService(); 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().clientDetails(Config::GetInstance().GetUUID(), DESCRIPTION, "3200", "VDR", VERSION); plexclient::plexgdm::GetInstance().Start(); plexclient::ControlServer::GetInstance().Start(); 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", pPlexService); } 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()) { PlayFile(plexclient::ActionManager::GetInstance().GetAction()); } } /** ** 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, "UseCustomTranscodeProfile") == 0) Config::GetInstance().UseCustomTranscodeProfile = 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!