summaryrefslogtreecommitdiff
path: root/SubscriptionManager.cpp
diff options
context:
space:
mode:
authorchriszero <zerov83@gmail.com>2015-02-05 21:32:55 +0100
committerchriszero <zerov83@gmail.com>2015-02-05 21:32:55 +0100
commit312c13f4f6b299a976787542869f96b1e66549cf (patch)
tree7ee2732eaec79d50e0c9718960fd58e2436f10f6 /SubscriptionManager.cpp
parent1ecdb2a5d9e05e0d30dae89e3d675218ca4c255e (diff)
downloadvdr-plugin-plex-312c13f4f6b299a976787542869f96b1e66549cf.tar.gz
vdr-plugin-plex-312c13f4f6b299a976787542869f96b1e66549cf.tar.bz2
Plex remote support.
Control via Plexapps (Android, IOS...)
Diffstat (limited to 'SubscriptionManager.cpp')
-rw-r--r--SubscriptionManager.cpp279
1 files changed, 222 insertions, 57 deletions
diff --git a/SubscriptionManager.cpp b/SubscriptionManager.cpp
index c4589ef..165018d 100644
--- a/SubscriptionManager.cpp
+++ b/SubscriptionManager.cpp
@@ -9,110 +9,275 @@
#include <Poco/Net/HTTPResponse.h>
#include <Poco/Net/MessageHeader.h>
+#include "Plexservice.h"
+
namespace plexclient
{
SubscriptionManager::SubscriptionManager()
{
-
+ m_pStatus = new cSubscriberStatus();
+ m_bStoppedSent = true;
}
-void SubscriptionManager::Notify() {
- //mutex.lock();
-
- //TODO: Implement
+void SubscriptionManager::Notify()
+{
+ //dsyslog("[plex]: '%s'", __FUNCTION__);
+ Cleanup();
+ m_myLock.Lock(&m_myMutex);
for(std::map<std::string, Subscriber>::iterator it = m_mSubcribers.begin() ; it != m_mSubcribers.end(); ++it) {
Subscriber subs = it->second;
- subs.SendUpdate(GetMsg(std::string(itoa(subs.m_iCommandId))), false);
+ subs.SendUpdate(GetMsg(subs.m_iCommandId), false);
}
-
- //mutex.unlock();
+ NotifyServer();
}
-void SubscriptionManager::AddSubscriber(Subscriber subs) {
- //mutex.lock();
+void SubscriptionManager::NotifyServer()
+{
+ if(m_bStoppedSent && m_pStatus->PlayerStopped) return;
+ try {
+ int current, total, speed;
+ bool play, forward;
+ Video *pVid = NULL;
+ if(!m_pStatus->PlayerStopped && m_pStatus->pControl) {
+ m_pStatus->pControl->GetIndex(current, total);
+ current = current / m_pStatus->pControl->FramesPerSecond() * 1000;
+ total = total / m_pStatus->pControl->FramesPerSecond() * 1000;
+ m_pStatus->pControl->GetReplayMode(play, forward, speed);
+ pVid = m_pStatus->pVideo;
+ }
+ else {
+ return;
+ }
+
+ std::stringstream uri;
+ uri << "/:/timeline";
+ uri << "?containerKey=" << Plexservice::encode(pVid ? pVid->m_sKey : "/library/metadata/900000");
+ uri << "&key=" << Plexservice::encode(pVid ? pVid->m_sKey : "/library/metadata/900000");
+ uri << "&ratingKey=" << (pVid ? pVid->m_iRatingKey : 900000);
+ uri << "&state=";
+ if (m_pStatus->PlayerStopped) uri << "stopped";
+ else if(!play) uri << "paused";
+ else uri << "playing";
+ uri << "&time=" << current;
+ uri << "&duration=" << total;
+
+ 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");
+
+ Poco::Net::HTTPClientSession session(pVid->m_pServer->GetIpAdress(), pVid->m_pServer->GetPort());
+
+ session.sendRequest(Request);
+ Poco::Net::HTTPResponse response;
+ session.receiveResponse(response);
+
+ if(m_pStatus->PlayerStopped) {
+ m_bStoppedSent = true;
+ }
+ else {
+ m_bStoppedSent = false;
+ }
+ } catch (Poco::Exception& e) {
+ std::cout << e.displayText() << std::endl;
+ }
+
+}
+
+void SubscriptionManager::AddSubscriber(Subscriber subs)
+{
+ m_myLock.Lock(&m_myMutex);
m_mSubcribers[subs.GetUuid()] = subs;
- std::cout << "AddSubscriber: " << subs.to_string() << std::endl;
- //mutex.unlock();
}
-void SubscriptionManager::RemoveSubscriber(std::string uuid) {
- //mutex.lock();
+void SubscriptionManager::RemoveSubscriber(std::string uuid)
+{
+ m_myLock.Lock(&m_myMutex);
if(m_mSubcribers.find(uuid) != m_mSubcribers.end()) {
m_mSubcribers.erase(uuid);
}
- //mutex.unlock();
}
-std::string SubscriptionManager::GetMsg(std::string commandId) {
- int time = 0;//PlayerGetCurrentPosition();
-
- //bool paused = PlayerPaused;
-
+void SubscriptionManager::UpdateSubscriber(std::string uuid, std::string commandId)
+{
+ m_myLock.Lock(&m_myMutex);
+ if(m_mSubcribers.find(uuid) != m_mSubcribers.end()) {
+ m_mSubcribers[uuid].m_iCommandId = commandId;
+ //dsyslog("[plex]: '%s'", __FUNCTION__);
+ }
+}
+
+std::string SubscriptionManager::GetMsg(std::string commandId)
+{
+ //dsyslog("[plex]: '%s'", __FUNCTION__);
std::stringstream msg;
msg << "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
- "<MediaContainer commandID=\"" << commandId << "\""
- " location=\"navigation\">";
-
- msg << "<Timeline location=\"navigation\" state=\"";
- //if(paused) msg << "paused";
- //else if (paused) msg << "paused";
- msg << "stopped";
- msg << "\" time=\"" << time << "\" type=\"video\" />";
+ "<MediaContainer commandID=\"" << commandId << "\" location=\"navigation\">";
+
msg << "<Timeline location=\"navigation\" state=\"stopped\" time=\"0\" type=\"photo\" />";
msg << "<Timeline location=\"navigation\" state=\"stopped\" time=\"0\" type=\"music\" />";
-
+
+ msg << GetTimelineXml();
+
msg << "</MediaContainer>";
return msg.str();
}
-Subscriber::Subscriber(std::string protocol, std::string host, int port, std::string uuid, int commandId) {
+std::string SubscriptionManager::GetTimelineXml()
+{
+ int current, total, speed;
+ bool play, forward;
+ Video *pVid = NULL;
+ if(!m_pStatus->PlayerStopped && m_pStatus->pControl) {
+ m_pStatus->pControl->GetIndex(current, total);
+ current = current / m_pStatus->pControl->FramesPerSecond() * 1000;
+ total = total / m_pStatus->pControl->FramesPerSecond() * 1000;
+ m_pStatus->pControl->GetReplayMode(play, forward, speed);
+ pVid = m_pStatus->pVideo;
+ }
+
+ std::stringstream msg;
+
+ msg << "<Timeline location=\"navigation\" state=\"";
+ if (m_pStatus->PlayerStopped) msg << "stopped";
+ else if(!play) msg << "paused";
+ else msg << "playing";
+
+ msg << "\" time=\"" << current << "\" type=\"video\"";
+
+ msg << " duration=\"" << total << "\"";
+ msg << " seekRange=\"0-" << total << "\"";
+ msg << " controllable=\"true\"";
+ msg << " machineIdentifier=\"" << (pVid ? pVid->m_pServer->GetUuid() : "") << "\"";
+ msg << " protocol=\"http\"";
+ msg << " address=\"" << (pVid ? pVid->m_pServer->GetIpAdress() : "") << "\"";
+ msg << " port=\"" << (pVid ? pVid->m_pServer->GetPort() : 0) << "\"";
+ msg << " guid=\"" << Config::GetInstance().GetUUID() << "\"";
+ msg << " containerKey=\"" << (pVid ? pVid->m_sKey : "/library/metadata/900000") << "\"";
+ msg << " key=\"" << (pVid ? pVid->m_sKey : "/library/metadata/900000") << "\"";
+ msg << " ratingKey=\"" << (pVid ? pVid->m_iRatingKey : 900000) << "\"";
+ msg << " volume=\"" << m_pStatus->Volume << "\"";
+ msg << " shuffle=\"false\"";
+
+ msg << "/>";
+ return msg.str();
+}
+
+void SubscriptionManager::Cleanup()
+{
+ m_myLock.Lock(&m_myMutex);
+ for(std::map<std::string, Subscriber>::iterator it = m_mSubcribers.begin() ; it != m_mSubcribers.end(); ++it) {
+ Subscriber subs = it->second;
+ if(subs.m_iAge > 30) {
+ m_mSubcribers.erase(it);
+ }
+ }
+}
+
+Subscriber::Subscriber(std::string protocol, std::string host, int port, std::string uuid, std::string commandId)
+{
m_sProtocol = protocol;
- m_sHost = host;
+ int pos = host.find(":");
+ m_sHost = host.substr(0,pos-1);
m_iPort = port;
m_sUuid = uuid;
m_iCommandId = commandId;
+ m_iAge = 0;
}
-void Subscriber::SendUpdate(std::string msg, bool isNav) {
+void Subscriber::SendUpdate(std::string msg, bool isNav)
+{
+ //dsyslog("[plex]: '%s'", __FUNCTION__);
++m_iAge;
-
- Poco::Net::HTTPRequest *pRequest = new Poco::Net::HTTPRequest(Poco::Net::HTTPRequest::HTTP_POST,
- "/:/timeline", Poco::Net::HTTPMessage::HTTP_1_1);
-
- pRequest->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");
- 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-vdr");
- pRequest->add("X-Plex-Provides", "player");
- pRequest->add("X-Plex-Version", "0.0.1a");
-
- Poco::Net::HTTPClientSession* session = new Poco::Net::HTTPClientSession(m_sHost, m_iPort);
- std::ostream& oustr = session->sendRequest(*pRequest);
- oustr << msg;
+ try {
+ 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");
+
+ Poco::Net::HTTPClientSession session(m_sHost, m_iPort);
+
+ Request.setContentLength(msg.length());
+ session.sendRequest(Request) << msg;
+
+ Poco::Net::HTTPResponse response;
+ session.receiveResponse(response);
+
+ } catch (Poco::Exception& e) {
+ std::cout << e.displayText() << std::endl;
+ }
}
ActionManager::ActionManager() {}
-void ActionManager::AddAction(std::string file) {
- m_sAction = file;
+void ActionManager::AddAction(Video* video)
+{
+ m_myLock.Lock(&m_myMutex);
+ m_Action = video;
m_isAction = true;
}
-std::string ActionManager::GetAction() {
+Video* ActionManager::GetAction()
+{
+ m_myLock.Lock(&m_myMutex);
m_isAction = false;
- return m_sAction;
+ return m_Action;
}
-bool ActionManager::IsAction() {
+bool ActionManager::IsAction()
+{
+ //m_myLock.Lock(&m_myMutex);
return m_isAction;
}
+cSubscriberStatus::cSubscriberStatus()
+{
+ PlayerStopped = true;
+ pControl = NULL;
+}
+
+void cSubscriberStatus::ChannelSwitch(const cDevice* Device, int ChannelNumber, bool LiveView)
+{
+ dsyslog("[plex]: '%s'", __FUNCTION__);
+}
+
+void cSubscriberStatus::Replaying(const cControl* DvbPlayerControl, const char* Name, const char* FileName, bool On)
+{
+ //dsyslog("[plex]: '%s'", __FUNCTION__);
+ PlayerStopped = !On;
+ pControl = const_cast<cControl*>(DvbPlayerControl);
+ cHlsPlayerControl* hlsControl = dynamic_cast<cHlsPlayerControl*>(pControl);
+ if(hlsControl) {
+ pVideo = hlsControl->m_pVideo;
+ } else {
+ pVideo = NULL;
+ }
+
+ SubscriptionManager::GetInstance().Notify();
+}
+
+void cSubscriberStatus::SetVolume(int Volume, bool Absolute)
+{
+ dsyslog("[plex]: '%s'", __FUNCTION__);
}
+} // Namespace