diff options
author | chriszero <zerov83@gmail.com> | 2015-02-14 18:53:11 +0100 |
---|---|---|
committer | chriszero <zerov83@gmail.com> | 2015-02-14 18:53:11 +0100 |
commit | e412257abf8de4576a180351d24ff07589fa630c (patch) | |
tree | ed020de5c8257545eca66e96997984731ac60379 | |
parent | 20fefdd3f341d6e7f6b15e4926bf5569aa1943d5 (diff) | |
download | vdr-plugin-plex-e412257abf8de4576a180351d24ff07589fa630c.tar.gz vdr-plugin-plex-e412257abf8de4576a180351d24ff07589fa630c.tar.bz2 |
Various Fixes0.1.0
Bump Version to frist beta.
-rw-r--r-- | Config.h | 11 | ||||
-rw-r--r-- | Directory.cpp | 19 | ||||
-rw-r--r-- | Directory.h | 17 | ||||
-rw-r--r-- | Makefile | 38 | ||||
-rw-r--r-- | MediaContainer.cpp | 12 | ||||
-rw-r--r-- | MediaContainer.h | 8 | ||||
-rw-r--r-- | PVideo.cpp | 24 | ||||
-rw-r--r-- | PVideo.h | 8 | ||||
-rw-r--r-- | PlexHTTPRequestHandler.cpp | 2 | ||||
-rw-r--r-- | PlexHelper.cpp | 21 | ||||
-rw-r--r-- | PlexHelper.h | 7 | ||||
-rw-r--r-- | PlexReqHandlerFactory.cpp | 4 | ||||
-rw-r--r-- | Plexservice.cpp | 129 | ||||
-rw-r--r-- | Plexservice.h | 17 | ||||
-rw-r--r-- | SubscriptionManager.cpp | 30 | ||||
-rw-r--r-- | XmlObject.cpp | 10 | ||||
-rw-r--r-- | XmlObject.h | 4 | ||||
-rw-r--r-- | hlsPlayerControl.cpp | 42 | ||||
-rw-r--r-- | misc.h | 157 | ||||
-rw-r--r-- | plex.cpp | 59 | ||||
-rw-r--r-- | plex.h | 143 | ||||
-rw-r--r-- | plexgdm.cpp | 4 |
22 files changed, 187 insertions, 579 deletions
@@ -13,17 +13,6 @@ #include <vdr/osd.h> #include <vdr/menuitems.h> - - -/// vdr-plugin version number. -/// Makefile extracts the version number for generating the file name -/// for the distribution archive. -static const char *const VERSION = "0.0.1" -#ifdef GIT_REV - "-GIT" GIT_REV -#endif - ; - #define STRING_SIZE 256 class Config diff --git a/Directory.cpp b/Directory.cpp index c54580f..46f2d54 100644 --- a/Directory.cpp +++ b/Directory.cpp @@ -1,19 +1,24 @@ #include "Directory.h" +#include <Poco/Format.h> namespace plexclient { -Directory::Directory(Poco::XML::Node* pNode) +Directory::Directory(Poco::XML::Node* pNode, MediaContainer* parent) { if(Poco::icompare(pNode->nodeName(), "Directory") == 0) { - + m_pParent = parent; Poco::XML::AutoPtr<Poco::XML::NamedNodeMap> pAttribs = pNode->attributes(); m_bAllowSync = GetNodeValueAsBool(pAttribs->getNamedItem("allowSync")); + m_iIndex = GetNodeValueAsInt(pAttribs->getNamedItem("index")); + m_iYear = GetNodeValueAsInt(pAttribs->getNamedItem("year")); m_sArt = GetNodeValue(pAttribs->getNamedItem("art")); m_sThumb = GetNodeValue(pAttribs->getNamedItem("thumb")); m_sKey = GetNodeValue(pAttribs->getNamedItem("key")); m_sTitle = GetNodeValue(pAttribs->getNamedItem("title")); + m_sTitle1 = GetNodeValue(pAttribs->getNamedItem("title1")); + m_sTitle2 = GetNodeValue(pAttribs->getNamedItem("title2")); m_sComposite = GetNodeValue(pAttribs->getNamedItem("composite")); m_sLanguage = GetNodeValue(pAttribs->getNamedItem("language")); m_sUuid = GetNodeValue(pAttribs->getNamedItem("uuid")); @@ -25,10 +30,14 @@ Directory::Directory(Poco::XML::Node* pNode) } } -Directory::~Directory() +std::string Directory::GetTitle() { + switch(m_eType) { + case SEASON: + return Poco::format("%s - Staffel %d", m_pParent->m_sTitle2, m_iIndex); + default: + return m_sTitle; + } } - } - diff --git a/Directory.h b/Directory.h index fb54bc5..8638565 100644 --- a/Directory.h +++ b/Directory.h @@ -12,6 +12,7 @@ #include <Poco/String.h> #include "XmlObject.h" +#include "MediaContainer.h" using Poco::XML::DOMParser; using Poco::XML::Document; @@ -23,16 +24,20 @@ using Poco::Exception; namespace plexclient { - +class MediaContainer; + class Directory: XmlObject -{ +{ public: - Directory(Poco::XML::Node* pNode); - ~Directory(); + Directory(Poco::XML::Node* pNode, MediaContainer* parent); public: bool m_bAllowSync; + int m_iIndex; + int m_iYear; std::string m_sTitle; + std::string m_sTitle1; + std::string m_sTitle2; std::string m_sComposite; std::string m_sLanguage; std::string m_sUuid; @@ -42,7 +47,9 @@ public: Poco::Timestamp m_tCreatedAt; std::string m_sKey; MediaType m_eType; - + MediaContainer* m_pParent; + + std::string GetTitle(); }; } @@ -8,52 +8,20 @@ # By default the main source file also carries this name. PLUGIN = plex +VERSION := $(shell git describe --tags master) LIBS += -lPocoUtil -lPocoNet -lPocoNetSSL -lPocoXML -lPocoFoundation -lpcrecpp ### Configuration (edit this for your needs) - # support avfs a virtual file system -# FIXME: AVFS isn't working, corrupts memory -#AVFS ?= $(shell test -x /usr/bin/avfs-config && echo 1) - # use ffmpeg libswscale -#SWSCALE ?= $(shell pkg-config --exists libswscale && echo 1) - # support png images -#PNG ?= $(shell pkg-config --exists libpng && echo 1) - # support jpg images -#JPG ?= $(shell test -r /usr/include/jpeglib.h && echo 1) - CONFIG := #-DDEBUG # uncomment to build DEBUG -ifeq ($(AVFS),1) -CONFIG += -DUSE_AVFS -_CFLAGS += $(shell /usr/bin/avfs-config --cflags) -LIBS += $(shell /usr/bin/avfs-config --libs) -endif -ifeq ($(SWSCALE),1) -CONFIG += -DUSE_SWSCALE -_CFLAGS += $(shell pkg-config --cflags libswscale) -LIBS += $(shell pkg-config --libs libswscale) -endif -ifeq ($(PNG),1) -CONFIG += -DUSE_PNG -_CFLAGS += $(shell pkg-config --cflags libpng) -LIBS += $(shell pkg-config --libs libpng) -endif -ifeq ($(JPG),1) -CONFIG += -DUSE_JPG -_CFLAGS += -I/usr/include -LIBS += -Ljpeg - -endif - -_CFLAGS += $(shell pkg-config --cflags xcb xcb-image xcb-keysyms xcb-icccm) -#LIBS += -lrt $(shell pkg-config --libs xcb xcb-image xcb-keysyms xcb-icccm) +_CFLAGS += $(shell pkg-config --cflags libpcrecpp) ### The version number of this plugin (taken from the main source file): -VERSION = $(shell grep 'static const char \*const VERSION *=' $(PLUGIN).cpp | awk '{ print $$7 }' | sed -e 's/[";]//g') +VERSION = $(shell grep 'static const char \*const VERSION *=' $(PLUGIN).h | awk '{ print $$7 }' | sed -e 's/[";]//g') GIT_REV = $(shell git describe --always 2>/dev/null) ### The directory environment: diff --git a/MediaContainer.cpp b/MediaContainer.cpp index fa3c24a..6fa92f6 100644 --- a/MediaContainer.cpp +++ b/MediaContainer.cpp @@ -11,13 +11,14 @@ MediaContainer::MediaContainer(std::istream* response, PlexServer Server) NodeIterator it(pDoc, Poco::XML::NodeFilter::SHOW_ALL); Poco::XML::Node* pNode = it.nextNode(); - while(pNode) { if(Poco::icompare(pNode->nodeName(), "MediaContainer") == 0) { Poco::XML::NamedNodeMap* pAttribs = pNode->attributes(); - - m_sTitle = GetNodeValue(pAttribs->getNamedItem("title1")); + + m_sTitle = GetNodeValue(pAttribs->getNamedItem("title")); + m_sTitle1 = GetNodeValue(pAttribs->getNamedItem("title1")); m_sTitle2 = GetNodeValue(pAttribs->getNamedItem("title2")); + m_iParentIndex = GetNodeValueAsInt(pAttribs->getNamedItem("parentIndex")); m_sThumb = GetNodeValue(pAttribs->getNamedItem("thumb")); m_sViewGroup = GetNodeValue(pAttribs->getNamedItem("viewGroup")); m_sLibrarySectionTitle = GetNodeValue(pAttribs->getNamedItem("librarySectionTitle")); @@ -27,12 +28,13 @@ MediaContainer::MediaContainer(std::istream* response, PlexServer Server) m_iSize = GetNodeValueAsInt(pAttribs->getNamedItem("size")); m_bAllowSync = GetNodeValueAsBool(pAttribs->getNamedItem("allowSync")); m_sArt = GetNodeValue(pAttribs->getNamedItem("art")); + m_sSummary = GetNodeValue(pAttribs->getNamedItem("summary")); pAttribs->release(); } else if(Poco::icompare(pNode->nodeName(), "Directory") == 0) { - m_vDirectories.push_back(Directory(pNode)); + m_vDirectories.push_back(Directory(pNode, this)); } else if(Poco::icompare(pNode->nodeName(), "Video") == 0) { - m_vVideos.push_back(Video(pNode, Server)); + m_vVideos.push_back(Video(pNode, Server, this)); } pNode = it.nextNode(); diff --git a/MediaContainer.h b/MediaContainer.h index e3ad6b7..967700f 100644 --- a/MediaContainer.h +++ b/MediaContainer.h @@ -30,7 +30,9 @@ using Poco::Exception; namespace plexclient { - +class Video; +class Directory; + class MediaContainer: XmlObject { public: @@ -47,6 +49,7 @@ public: std::string m_sArt; std::string m_sThumb; std::string m_sTitle; + std::string m_sTitle1; std::string m_sTitle2; std::string m_sViewGroup; int m_iLibrarySectionID; @@ -54,7 +57,8 @@ public: std::string m_sLibrarySectionUUID; std::string m_sMediaTagPrefix; int m_iSize; - + std::string m_sSummary; + int m_iParentIndex; }; } @@ -1,9 +1,10 @@ #include "PVideo.h" +#include <Poco/Format.h> namespace plexclient { -Video::Video(Poco::XML::Node* pNode, PlexServer Server) +Video::Video(Poco::XML::Node* pNode, PlexServer Server, MediaContainer* parent) { m_iMyPlayOffset = 0; m_Server = Server; @@ -16,6 +17,8 @@ Video::Video(Poco::XML::Node* pNode, PlexServer Server) Poco::XML::AutoPtr<Poco::XML::NamedNodeMap> pAttribs = pNode->attributes(); m_iRatingKey = GetNodeValueAsInt(pAttribs->getNamedItem("ratingKey")); + m_iIndex = GetNodeValueAsInt(pAttribs->getNamedItem("index")); + m_iParentIndex = GetNodeValueAsInt(pAttribs->getNamedItem("parentIndex")); m_sKey = GetNodeValue(pAttribs->getNamedItem("key")); m_sStudio = GetNodeValue(pAttribs->getNamedItem("studio")); m_tType = GetNodeValueAsMediaType(pAttribs->getNamedItem("type")); @@ -51,6 +54,25 @@ Video::Video(Poco::XML::Node* pNode, PlexServer Server) } pChildNode = it.nextNode(); } + if (m_iParentIndex < 0) { + m_iParentIndex = parent->m_iParentIndex; + } } +std::string Video::GetTitle() +{ + std::string res = m_sTitle; + switch(m_tType) { + case MOVIE: + res = Poco::format("%s (%d)", m_sTitle, m_iYear); + break; + case EPISODE: + res = Poco::format("%02dx%02d - %s", m_iParentIndex, m_iIndex, m_sTitle); + break; + default: + break; + } + return res; } + +} // Namespace @@ -16,6 +16,7 @@ #include <iostream> #include "XmlObject.h" +#include "MediaContainer.h" #include "Media.h" #include "PlexServer.h" @@ -29,11 +30,12 @@ using Poco::Exception; namespace plexclient { +class MediaContainer; class Video: XmlObject { public: - Video(Poco::XML::Node* pNode, PlexServer Server); + Video(Poco::XML::Node* pNode, PlexServer Server, MediaContainer* parent); Video() {}; public: @@ -63,6 +65,10 @@ public: Media m_Media; PlexServer m_Server; int m_iMyPlayOffset; + int m_iIndex; + int m_iParentIndex; + + std::string GetTitle(); }; } diff --git a/PlexHTTPRequestHandler.cpp b/PlexHTTPRequestHandler.cpp index 86ac3cd..552239a 100644 --- a/PlexHTTPRequestHandler.cpp +++ b/PlexHTTPRequestHandler.cpp @@ -235,7 +235,7 @@ void PlayerRequestHandler::handleRequest(Poco::Net::HTTPServerRequest& request, if(query.find("offset") != query.end()) { Cont.m_vVideos[0].m_iMyPlayOffset = atoi(query["offset"].c_str()) / 1000; } - //Poco:: + ActionManager::GetInstance().AddAction(Cont.m_vVideos[0]); } else if(request.getURI().find("/playback/play") != std::string::npos) { cRemote::Put(kPlay); diff --git a/PlexHelper.cpp b/PlexHelper.cpp index b1421c5..61643d7 100644 --- a/PlexHelper.cpp +++ b/PlexHelper.cpp @@ -1,16 +1,25 @@ #include "PlexHelper.h" +#include "Config.h" +#include "plex.h" namespace plexclient { -PlexHelper::PlexHelper() +void PlexHelper::AddHttpHeader(Poco::Net::HTTPRequest& request) { -} + request.add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17"); -PlexHelper::~PlexHelper() -{ + //request.add("X-Plex-Client-Capabilities", "protocols=shoutcast,http-video;videoDecoders=h264{profile:high&resolution:1080&level:51};audioDecoders=mp3,aac"); + request.add("X-Plex-Client-Identifier", Config::GetInstance().GetUUID()); + request.add("X-Plex-Device", "PC"); + request.add("X-Plex-Device-Name", Config::GetInstance().GetHostname()); + request.add("X-Plex-Language", Config::GetInstance().GetLanguage()); + request.add("X-Plex-Model", "Linux"); + request.add("X-Plex-Platform", "VDR"); + request.add("X-Plex-Product", "plex for vdr"); + request.add("X-Plex-Provides", "player"); + request.add("X-Plex-Version", VERSION); } -} - +} // namespace diff --git a/PlexHelper.h b/PlexHelper.h index e42fc1d..0df6eaf 100644 --- a/PlexHelper.h +++ b/PlexHelper.h @@ -1,14 +1,17 @@ #ifndef PLEXHELPER_H #define PLEXHELPER_H +#include <Poco/Net/HTTPRequest.h> + namespace plexclient { class PlexHelper { public: - PlexHelper(); - ~PlexHelper(); + static void AddHttpHeader(Poco::Net::HTTPRequest& request); +private: + PlexHelper() {}; }; diff --git a/PlexReqHandlerFactory.cpp b/PlexReqHandlerFactory.cpp index ec33a12..dacdff7 100644 --- a/PlexReqHandlerFactory.cpp +++ b/PlexReqHandlerFactory.cpp @@ -12,7 +12,7 @@ PlexReqHandlerFactory::~PlexReqHandlerFactory() } Poco::Net::HTTPRequestHandler* PlexReqHandlerFactory::createRequestHandler(const Poco::Net::HTTPServerRequest& request) -{ +{ /* if(request.getMethod() == Poco::Net::HTTPRequest::HTTP_GET) { std::cout << "GET Request: " << request.getURI() << " from: " << request.clientAddress().toString() << std::endl; } else if(request.getMethod() == Poco::Net::HTTPRequest::HTTP_OPTIONS) { @@ -23,7 +23,7 @@ Poco::Net::HTTPRequestHandler* PlexReqHandlerFactory::createRequestHandler(const else { std::cout << "??? Request: " << request.getURI() << " from: " << request.clientAddress().toString() << std::endl; } - + */ if(request.getURI().find("/player/timeline")!= std::string::npos) return new SubscribeRequestHandler(); else if(request.getURI().find("/resources")!= std::string::npos) return new ResourceRequestHandler(); else if(request.getURI().find("/player")!= std::string::npos) return new PlayerRequestHandler(); diff --git a/Plexservice.cpp b/Plexservice.cpp index 776f9fc..7a1633e 100644 --- a/Plexservice.cpp +++ b/Plexservice.cpp @@ -1,12 +1,13 @@ #include "Plexservice.h" +#include "PlexHelper.h" + namespace plexclient { Plexservice::Plexservice(PlexServer *server) { pServer = server; - USERAGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17"; } Plexservice::~Plexservice() @@ -56,13 +57,7 @@ std::string Plexservice::GetMyPlexToken() Poco::Net::HTTPSClientSession plexSession("plex.tv", 443, context); Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_POST, "/users/sign_in.xml", Poco::Net::HTTPMessage::HTTP_1_1); - request.add("X-Plex-Platform", "VDR"); - request.add("X-Plex-Platform-Version", "2.0.4"); - request.add("X-Plex-Provides", "player"); - request.add("X-Plex-Product", "plex for vdr"); - request.add("X-Plex-Version", "0.0.1a"); - request.add("X-Plex-Device", "Linux"); - request.add("X-Plex-Client-Identifier", "plex for vdr"); + PlexHelper::AddHttpHeader(request); request.add("Authorization", Poco::format("Basic %s", m_sToken)); plexSession.sendRequest(request); @@ -103,18 +98,6 @@ void Plexservice::Authenticate() esyslog("[plex]Exception in %s s%", __func__, exc.displayText().c_str() ); } } -/* -void Plexservice::DiscoverAllServers() -{ - // try automatic discovery via multicast - plexgdm gdmClient = plexgdm(); - gdmClient.discover(); - pServer = gdmClient.GetPServer(); - if (pServer == 0) { - perror("No Plexserver found"); - } -} - */ PlexServer* Plexservice::GetServer() { @@ -129,7 +112,7 @@ MediaContainer* Plexservice::GetAllSections() MediaContainer* Plexservice::GetSection(std::string section) { std::string token = GetMyPlexToken(); - if(GetHttpSession(true)) { + if(GetHttpSession()) { Poco::Net::HTTPRequest *pRequest; if(section[0]=='/') { // Full URI? @@ -162,41 +145,16 @@ Poco::Net::HTTPRequest* Plexservice::CreateRequest(std::string path) Poco::Net::HTTPRequest *pRequest = new Poco::Net::HTTPRequest(Poco::Net::HTTPRequest::HTTP_GET, path, Poco::Net::HTTPMessage::HTTP_1_1); - pRequest->add("User-Agent", USERAGENT); - - //pRequest->add("X-Plex-Client-Capabilities", "protocols=shoutcast,http-video;videoDecoders=h264{profile:high&resolution:1080&level:51};audioDecoders=mp3,aac"); - pRequest->add("X-Plex-Client-Identifier", Config::GetInstance().GetUUID()); - pRequest->add("X-Plex-Device", "PC"); - pRequest->add("X-Plex-Device-Name", Config::GetInstance().GetHostname()); - pRequest->add("X-Plex-Language", Config::GetInstance().GetLanguage()); - pRequest->add("X-Plex-Model", "Linux"); - pRequest->add("X-Plex-Platform", "VDR"); - pRequest->add("X-Plex-Product", "plex for vdr"); - pRequest->add("X-Plex-Provides", "player"); - pRequest->add("X-Plex-Version", "0.0.1a"); + PlexHelper::AddHttpHeader(*pRequest); return pRequest; } MediaContainer Plexservice::GetMediaContainer(std::string fullUrl) { - Poco::URI fileuri(fullUrl); - Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET, fileuri.getPathAndQuery(), Poco::Net::HTTPMessage::HTTP_1_1); - - request.add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17"); - - //pRequest->add("X-Plex-Client-Capabilities", "protocols=shoutcast,http-video;videoDecoders=h264{profile:high&resolution:1080&level:51};audioDecoders=mp3,aac"); - request.add("X-Plex-Client-Identifier", Config::GetInstance().GetUUID()); - request.add("X-Plex-Device", "PC"); - request.add("X-Plex-Device-Name", Config::GetInstance().GetHostname()); - request.add("X-Plex-Language", Config::GetInstance().GetLanguage()); - request.add("X-Plex-Model", "Linux"); - request.add("X-Plex-Platform", "VDR"); - request.add("X-Plex-Product", "plex for vdr"); - request.add("X-Plex-Provides", "player"); - request.add("X-Plex-Version", "0.0.1a"); + PlexHelper::AddHttpHeader(request); Poco::Net::HTTPClientSession session(fileuri.getHost(), fileuri.getPort()); @@ -209,81 +167,6 @@ MediaContainer Plexservice::GetMediaContainer(std::string fullUrl) return allsections; } -#ifdef CRYPTOPP -std::string Plexservice::computeHMAC(std::string message) -{ - using CryptoPP::Exception; - using CryptoPP::HMAC; - using CryptoPP::SHA256; - using CryptoPP::Base64Encoder; - using CryptoPP::Base64Decoder; - using CryptoPP::StringSink; - using CryptoPP::ArraySink; - using CryptoPP::StringSource; - using CryptoPP::HashFilter; - - const std::string transcode_private = "k3U6GLkZOoNIoSgjDshPErvqMIFdE0xMTx8kgsrhnC0="; - - std::string encoded; - byte key[32]; - - StringSource(transcode_private, true, - new Base64Decoder( - new ArraySink(key, 32) - ) // Base64Encoder - ); // StringSource - - try { - HMAC<SHA256> hmac((byte*)key, sizeof(key)); - - StringSource(message, true, - new HashFilter(hmac, - new Base64Encoder( - new StringSink(encoded), - false - ) // Base64Encoder - ) // HashFilter - ); // StringSource - } catch(const CryptoPP::Exception& e) { - std::cerr << e.what() << std::endl; - } - return encoded; -} - -std::string Plexservice::GetTranscodeUrl(Video* video) -{ - const std::string transcodeURL = "/video/:/transcode/segmented/start.m3u8?"; - const std::string transcode_public = "KQMIY6GATPC63AIMC4R2"; - - std::stringstream params; - params << "identifier=com.plexapp.plugins.library"; - params << "&url=" << encode(pServer->GetUri() + video->m_pMedia->m_sPartKey); - params << "&quality=8"; - params << "&ratingKey=" << video->m_iRatingKey; - params << "&3g=0"; - params << "&offset=0"; - params << "&directStream=1"; - params << "&maxVideoBitrate=30000"; - - int time = std::time(0); - std::string message = Poco::format("%s@%d", transcodeURL + params.str(), time); - - std::string b64hmacMessage = computeHMAC(message); - - std::stringstream plexAccess; - plexAccess << "&X-Plex-Access-Key=" << encode(transcode_public); - plexAccess << "&X-Plex-Access-Time=" << Poco::format("%d", time); - plexAccess << "&X-Plex-Access-Code=" << encode(b64hmacMessage); - plexAccess << "&X-Plex-Client-Capabilities="; - plexAccess << encode("protocols=http-live-streaming,http-streaming-video-720p,http-streaming-video-1080p;"); - plexAccess << encode("videoDecoders=h264{profile:high&resolution:1080&level:51};"); - plexAccess << encode("audioDecoders=aac,ac3{channels:6}"); - - std::string fullQuery = params.str() + plexAccess.str(); - return pServer->GetUri() + transcodeURL + fullQuery; -} -#endif - std::string Plexservice::encode(std::string message) { std::string temp; diff --git a/Plexservice.h b/Plexservice.h index 02961d3..cccf17b 100644 --- a/Plexservice.h +++ b/Plexservice.h @@ -33,15 +33,6 @@ #include "user.h" #include "MediaContainer.h" -#ifdef CRYPTOPP -#include <cryptopp/cryptlib.h> -#include <cryptopp/hmac.h> -#include <cryptopp/sha.h> -#include <cryptopp/base64.h> -#include <cryptopp/filters.h> -#include <cryptopp/hex.h> -#endif - namespace plexclient { @@ -76,14 +67,6 @@ private: Poco::Net::HTTPClientSession* GetHttpSession(bool createNew = false); Poco::Net::HTTPRequest* CreateRequest(std::string path); - -#ifdef CRYPTOPP -protected: - std::string computeHMAC(std::string message); -public: - std::string GetTranscodeUrl(Video* video); -#endif - }; } diff --git a/SubscriptionManager.cpp b/SubscriptionManager.cpp index d312803..47bd6f2 100644 --- a/SubscriptionManager.cpp +++ b/SubscriptionManager.cpp @@ -11,6 +11,7 @@ #include "Plexservice.h" #include "plexgdm.h" +#include "PlexHelper.h" namespace plexclient { @@ -77,17 +78,8 @@ void SubscriptionManager::NotifyServer() Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_GET, uri.str(), Poco::Net::HTTPMessage::HTTP_1_1); - Request.add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17"); - Request.add("X-Plex-Client-Identifier", Config::GetInstance().GetUUID()); - Request.add("X-Plex-Device", "PC"); - Request.add("X-Plex-Device-Name", Config::GetInstance().GetHostname()); - Request.add("X-Plex-Language", Config::GetInstance().GetLanguage()); - Request.add("X-Plex-Model", "Linux"); - Request.add("X-Plex-Platform", "VDR"); - Request.add("X-Plex-Product", "plex-vdr"); - Request.add("X-Plex-Provides", "player"); - Request.add("X-Plex-Version", "0.0.1a"); - + PlexHelper::AddHttpHeader(Request); + Poco::Net::HTTPClientSession session(server, port); session.sendRequest(Request); @@ -99,9 +91,7 @@ void SubscriptionManager::NotifyServer() } else { m_bStoppedSent = false; } - } catch (Poco::Exception& e) { - std::cout << e.displayText() << std::endl; - } + } catch (Poco::Exception& e) {} } @@ -214,17 +204,7 @@ void Subscriber::SendUpdate(std::string msg, bool isNav) Poco::Net::HTTPRequest Request(Poco::Net::HTTPRequest::HTTP_POST, "/:/timeline", Poco::Net::HTTPMessage::HTTP_1_1); - Request.add("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.52 Safari/537.17"); - - Request.add("X-Plex-Client-Identifier", Config::GetInstance().GetUUID()); - Request.add("X-Plex-Device", "PC"); - Request.add("X-Plex-Device-Name", Config::GetInstance().GetHostname()); - Request.add("X-Plex-Language", Config::GetInstance().GetLanguage()); - Request.add("X-Plex-Model", "Linux"); - Request.add("X-Plex-Platform", "VDR"); - Request.add("X-Plex-Product", "plex-vdr"); - Request.add("X-Plex-Provides", "player"); - Request.add("X-Plex-Version", "0.0.1a"); + PlexHelper::AddHttpHeader(Request); Poco::Net::HTTPClientSession session(m_sHost, m_iPort); diff --git a/XmlObject.cpp b/XmlObject.cpp index 09db02d..d588c5f 100644 --- a/XmlObject.cpp +++ b/XmlObject.cpp @@ -14,7 +14,7 @@ std::string XmlObject::GetNodeValue(Poco::XML::Node* pNode) int XmlObject::GetNodeValueAsInt(Poco::XML::Node* pNode) { - int value = 0; + int value = -1; if(pNode != 0) { try { value = atoi(pNode->getNodeValue().c_str()); @@ -25,7 +25,7 @@ int XmlObject::GetNodeValueAsInt(Poco::XML::Node* pNode) long XmlObject::GetNodeValueAsLong(Poco::XML::Node* pNode) { - long value = 0; + long value = -1; if(pNode != 0) { try { value = atol(pNode->getNodeValue().c_str()); @@ -36,7 +36,7 @@ long XmlObject::GetNodeValueAsLong(Poco::XML::Node* pNode) double XmlObject::GetNodeValueAsDouble(Poco::XML::Node* pNode) { - double value = 0; + double value = -1; if(pNode != 0) { try { value = atod(pNode->getNodeValue().c_str()); @@ -81,7 +81,9 @@ MediaType XmlObject::GetNodeValueAsMediaType(Poco::XML::Node* pNode) } else if (Poco::icompare(sType, "show") == 0) { type = SHOW; } else if (Poco::icompare(sType, "season") == 0) { - type = SHOW; + type = SEASON; + } else if (Poco::icompare(sType, "episode") == 0) { + type = EPISODE; } } return type; diff --git a/XmlObject.h b/XmlObject.h index 16b63b7..5b8b2ca 100644 --- a/XmlObject.h +++ b/XmlObject.h @@ -11,13 +11,13 @@ namespace plexclient { -enum MediaType {UNDEF = 0, PHOTO, MOVIE, MUSIC, SHOW, SEASON}; +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/hlsPlayerControl.cpp b/hlsPlayerControl.cpp index b9e15d3..1f19336 100644 --- a/hlsPlayerControl.cpp +++ b/hlsPlayerControl.cpp @@ -46,10 +46,10 @@ cHlsPlayerControl::cHlsPlayerControl(cHlsPlayer* Player, plexclient::Video Video cHlsPlayerControl::~cHlsPlayerControl() { dsyslog("[plex]: '%s'", __FUNCTION__); + cStatus::MsgReplaying(this, NULL, NULL, false); Hide(); delete player; player = NULL; - cStatus::MsgReplaying(this, NULL, NULL, false); } cString cHlsPlayerControl::GetHeader(void) @@ -74,7 +74,7 @@ void cHlsPlayerControl::Hide(void) void cHlsPlayerControl::Show(void) { - ShowTimed(); + ShowTimed(3); } eOSState cHlsPlayerControl::ProcessKey(eKeys Key) @@ -111,32 +111,15 @@ eOSState cHlsPlayerControl::ProcessKey(eKeys Key) case kDown: Pause(); break; - case kFastRew|k_Release: - case kLeft|k_Release: - //if (Setup.MultiSpeedMode) break; - case kFastRew: - case kLeft: - //Backward(); - break; - case kFastFwd|k_Release: - case kRight|k_Release: - //if (Setup.MultiSpeedMode) break; - case kFastFwd: - case kRight: - //Forward(); - break; - case kRed: - //TimeSearch(); - break; case kGreen|k_Repeat: case kGreen: - Hide(); - player->JumpRelative(-600); + //Hide(); + player->JumpRelative(-300); break; case kYellow|k_Repeat: case kYellow: - Hide(); - player->JumpRelative(600); + //Hide(); + player->JumpRelative(300); break; case kStop: case kBlue: @@ -241,7 +224,7 @@ bool cHlsPlayerControl::ShowProgress(bool Initial) if (GetIndex(Current, Total)) { if (!visible) { displayReplay = Skins.Current()->DisplayReplay(modeOnly); - //displayReplay->SetMarks(player->Marks()); + displayReplay->SetButtons(NULL,"-10m","+10m",tr("Stop")); SetNeedsFastResponse(true); visible = true; } @@ -265,16 +248,7 @@ bool cHlsPlayerControl::ShowProgress(bool Initial) if (!Initial) displayReplay->Flush(); displayReplay->SetCurrent(IndexToHMSF(Current, false, FramesPerSecond())); - - cString Title; - //cString Pos = player ? player->PosStr() : cString(NULL); - //if (*Pos && strlen(Pos) > 1) { - // Title = cString::sprintf("%s (%s)", m_title.c_str(), *Pos); - //} else { - Title = m_title.c_str(); - //} - displayReplay->SetTitle(Title); - + displayReplay->SetTitle(m_title.c_str()); displayReplay->Flush(); lastCurrent = Current; } @@ -1,157 +0,0 @@ -/// -/// @file misc.h @brief Misc function header file -/// -/// Copyright (c) 2009 - 2012 by Lutz Sammer. All Rights Reserved. -/// -/// Contributor(s): -/// Copied from vdr-softhddevice. -/// -/// License: AGPLv3 -/// -/// This program is free software: you can redistribute it and/or modify -/// it under the terms of the GNU Affero General Public License as -/// published by the Free Software Foundation, either version 3 of the -/// License. -/// -/// This program is distributed in the hope that it will be useful, -/// but WITHOUT ANY WARRANTY; without even the implied warranty of -/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -/// GNU Affero General Public License for more details. -/// -/// $Id: 3ced30cd6fa89227270c2f769654c65c62d3ef85 $ -////////////////////////////////////////////////////////////////////////////// - -/// @addtogroup misc -/// @{ - -#include <syslog.h> -#include <stdarg.h> -#include <time.h> // clock_gettime - -////////////////////////////////////////////////////////////////////////////// -// Defines -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -// Declares -////////////////////////////////////////////////////////////////////////////// - -////////////////////////////////////////////////////////////////////////////// -// Variables -////////////////////////////////////////////////////////////////////////////// - -extern int SysLogLevel; ///< how much information wanted - -////////////////////////////////////////////////////////////////////////////// -// Prototypes -////////////////////////////////////////////////////////////////////////////// - -static inline void Syslog(const int, const char *format, ...) - __attribute__ ((format(printf, 2, 3))); - -////////////////////////////////////////////////////////////////////////////// -// Inlines -////////////////////////////////////////////////////////////////////////////// - -#ifdef DEBUG -#define DebugLevel 4 /// private debug level -#else -#define DebugLevel 0 /// private debug level -#endif - -/** -** Syslog output function. -** -** - 0 fatal errors and errors -** - 1 warnings -** - 2 info -** - 3 important debug and fixme's -*/ -static inline void Syslog(const int level, const char *format, ...) -{ - if (SysLogLevel > level || DebugLevel > level) { - va_list ap; - - va_start(ap, format); - vsyslog(LOG_ERR, format, ap); - va_end(ap); - } -} - -/** -** Show error. -*/ -#define Error(fmt...) Syslog(0, fmt) - -/** -** Show fatal error. -*/ -#define Fatal(fmt...) do { Error(fmt); abort(); } while (0) - -/** -** Show warning. -*/ -#define Warning(fmt...) Syslog(1, fmt) - -/** -** Show info. -*/ -#define Info(fmt...) Syslog(2, fmt) - -/** -** Show debug. -*/ -#ifdef DEBUG -#define Debug(level, fmt...) Syslog(level, fmt) -#else -#define Debug(level, fmt...) /* disabled */ -#endif - -#ifndef AV_NOPTS_VALUE -#define AV_NOPTS_VALUE INT64_C(0x8000000000000000) -#endif - -/** -** Nice time-stamp string. -** -** @param ts dvb time stamp -*/ -static inline const char *Timestamp2String(int64_t ts) -{ - static char buf[4][16]; - static int idx; - - if (ts == (int64_t) AV_NOPTS_VALUE) { - return "--:--:--.---"; - } - idx = (idx + 1) % 3; - snprintf(buf[idx], sizeof(buf[idx]), "%2d:%02d:%02d.%03d", - (int)(ts / (90 * 3600000)), (int)((ts / (90 * 60000)) % 60), - (int)((ts / (90 * 1000)) % 60), (int)((ts / 90) % 1000)); - - return buf[idx]; -} - -/** -** Get ticks in ms. -** -** @returns ticks in ms, -*/ -static inline uint32_t GetMsTicks(void) -{ -#ifdef CLOCK_MONOTONIC - struct timespec tspec; - - clock_gettime(CLOCK_MONOTONIC, &tspec); - return (tspec.tv_sec * 1000) + (tspec.tv_nsec / (1000 * 1000)); -#else - struct timeval tval; - - if (gettimeofday(&tval, NULL) < 0) { - return 0; - } - return (tval.tv_sec * 1000) + (tval.tv_usec / 1000); -#endif -} - -/// @} @@ -2,14 +2,6 @@ #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. ** @@ -34,11 +26,11 @@ 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(); + SetMenuCategory(mcRecording); CreateMenu(); } @@ -56,21 +48,20 @@ void cPlexBrowser::CreateMenu() for(std::vector<plexclient::Directory>::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) ); + Add(new cPlexOsdItem( pDir->GetTitle().c_str(), pDir) ); } } if(pCont && pCont->m_vVideos.size() > 0) { for(std::vector<plexclient::Video>::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) ); + Add(new cPlexOsdItem( vid->GetTitle().c_str(), vid) ); } } if(Count() < 1) { Add(new cPlexOsdItem("Empty")); } - Display(); } @@ -175,6 +166,48 @@ 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 ////////////////////////////////////////////////////////////////////////////// @@ -290,7 +323,7 @@ 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(); @@ -23,88 +23,17 @@ #include <iterator> #include <algorithm> -/** -** Device plugin remote class. -*/ -class cMyRemote:public cRemote -{ -public: - - /** - ** Soft device remote class constructor. - ** - ** @param name remote name - */ - cMyRemote(const char *name):cRemote(name) { - } - - /** - ** Put keycode into vdr event queue. - ** - ** @param code key code - ** @param repeat flag key repeated - ** @param release flag key released - */ - bool Put(const char *code, bool repeat = false, bool release = false) { - return cRemote::Put(code, repeat, release); - } -}; - -/** -** Player class. -*/ -class cMyPlayer:public cPlayer -{ -private: - char *FileName; ///< file to play - -public: - cMyPlayer(const char *); ///< player constructor - virtual ~ cMyPlayer(); ///< player destructor - void Activate(bool); ///< player attached/detached - /// get current replay mode - virtual bool GetReplayMode(bool &, bool &, int &); -}; - -/** -** Status class. -** -** To get volume changes. -*/ -class cMyStatus:public cStatus -{ -private: - int Volume; ///< current volume - -public: - cMyStatus(void); ///< my status constructor - -protected: - virtual void SetVolume(int, bool); ///< volume changed -}; - -/** -** Our player control class. -*/ -class cMyControl:public cControl -{ -private: - cMyPlayer * Player; ///< our player - cSkinDisplayReplay *Display; ///< our osd display - void ShowReplayMode(void); ///< display replay mode - void ShowProgress(void); ///< display progress bar - virtual void Show(void); ///< show replay control - virtual void Hide(void); ///< hide replay control - bool infoVisible; ///< RecordingInfo visible - time_t timeoutShow; ///< timeout shown control - -public: - cMyControl(const char *); ///< player control constructor - virtual ~ cMyControl(); ///< player control destructor - - virtual eOSState ProcessKey(eKeys); ///< handle keyboard input -}; +/// vdr-plugin version number. +/// Makefile extracts the version number for generating the file name +/// for the distribution archive. +static const char *const VERSION = "0.1.0" +#ifdef GIT_REV + "-GIT" GIT_REV +#endif +; +static const char *const DESCRIPTION = "Plex for VDR Plugin"; +static const char *const MAINMENUENTRY = "Plex for VDR"; /* * Plex Browser @@ -137,60 +66,24 @@ public: }; -/** -** Play plugin menu class. -*/ -class cPlayMenu:public cOsdMenu +class cPlexInfo : public cOsdMenu { -private: -public: - cPlayMenu(const char *, int = 0, int = 0, int = 0, int = 0, int = 0); - virtual ~ cPlayMenu(); - virtual eOSState ProcessKey(eKeys); -}; -/** -** My device plugin OSD class. -*/ -class cMyOsd:public cOsd -{ public: - static volatile char Dirty; ///< flag force redraw everything - int OsdLevel; ///< current osd level - - cMyOsd(int, int, uint); ///< osd constructor - virtual ~ cMyOsd(void); ///< osd destructor - virtual void Flush(void); ///< commits all data to the hardware - virtual void SetActive(bool); ///< sets OSD to be the active one + cPlexInfo(plexclient::Video* video); + virtual eOSState ProcessKey(eKeys Keys); }; /** -** My device plugin OSD provider class. +** Play plugin menu class. */ -class cMyOsdProvider:public cOsdProvider +class cPlayMenu:public cOsdMenu { private: - static cOsd *Osd; - public: - virtual cOsd * CreateOsd(int, int, uint); - virtual bool ProvidesTrueColor(void); - cMyOsdProvider(void); -}; - -/** -** Dummy device class. -*/ -class cMyDevice:public cDevice -{ -public: - cMyDevice(void); - virtual ~ cMyDevice(void); - - virtual void GetOsdSize(int &, int &, double &); - -protected: - virtual void MakePrimaryDevice(bool); + cPlayMenu(const char *, int = 0, int = 0, int = 0, int = 0, int = 0); + virtual ~ cPlayMenu(); + virtual eOSState ProcessKey(eKeys); }; class cMyPlugin:public cPlugin diff --git a/plexgdm.cpp b/plexgdm.cpp index 9eb152f..083e00d 100644 --- a/plexgdm.cpp +++ b/plexgdm.cpp @@ -142,9 +142,7 @@ void plexgdm::discover() vBuffer[sender.host().toString()] = buf; } } - } catch(Poco::TimeoutException& exc) { - dsyslog("[plex]TimeoutException in %s s%", __func__, exc.displayText().c_str()); - } + } catch(Poco::TimeoutException) {} socket.close(); m_discoveryComplete = true; |