summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchriszero <zerov83@gmail.com>2015-01-28 21:17:18 +0100
committerchriszero <zerov83@gmail.com>2015-01-28 21:17:18 +0100
commit87eb8a9e931606da4197391b6e3a09376b1383c2 (patch)
tree9427c28a2d7e9e44d4d77dc7fe53ff91f5152e23
parent1da4dbe662e75be47e046472137c6bd72daa7b4d (diff)
downloadvdr-plugin-plex-87eb8a9e931606da4197391b6e3a09376b1383c2.tar.gz
vdr-plugin-plex-87eb8a9e931606da4197391b6e3a09376b1383c2.tar.bz2
- Counting played time correctly
- Implemented switching audiostreams - Removed some compile warnings
-rw-r--r--Config.cpp2
-rw-r--r--Config.h1
-rw-r--r--Media.cpp10
-rw-r--r--Media.h8
-rw-r--r--MediaContainer.h2
-rw-r--r--PVideo.cpp7
-rw-r--r--PVideo.h3
-rw-r--r--PlexHTTPRequestHandler.cpp2
-rw-r--r--Plexservice.cpp8
-rw-r--r--Stream.cpp26
-rw-r--r--Stream.h51
-rw-r--r--SubscriptionManager.h1
-rw-r--r--XmlObject.cpp16
-rw-r--r--XmlObject.h2
-rw-r--r--hlsPlayer.cpp134
-rw-r--r--hlsPlayer.h12
-rw-r--r--hlsPlayerControl.cpp20
-rw-r--r--hlsPlayerControl.h4
-rw-r--r--plex.cpp18
-rw-r--r--plex.h203
20 files changed, 357 insertions, 173 deletions
diff --git a/Config.cpp b/Config.cpp
index f8a706a..0ce98d6 100644
--- a/Config.cpp
+++ b/Config.cpp
@@ -67,7 +67,6 @@ cMyMenuSetupPage::cMyMenuSetupPage(void)
strn0cpy(Uuid, Config::GetInstance().GetUUID().c_str(), STRING_SIZE);
Add(new cMenuEditBoolItem(tr("Hide main menu entry"), (int*)&Config::GetInstance().HideMainMenuEntry, trVDR("no"), trVDR("yes")));
- Add(new cMenuEditBoolItem(tr("Disable remote"), (int*)&Config::GetInstance().DisableRemote, trVDR("no"), trVDR("yes")));
Add(new cMenuEditStrItem(tr("Plex Username"), Username, STRING_SIZE));
Add(new cMenuEditStrItem(tr("Plex Password"), Password, STRING_SIZE));
cMenuEditStrItem* devUUID = new cMenuEditStrItem(tr("Current UUID"), Uuid, STRING_SIZE);
@@ -84,7 +83,6 @@ void cMyMenuSetupPage::Store(void)
Config::GetInstance().s_password = std::string(Password);
SetupStore("HideMainMenuEntry", Config::GetInstance().HideMainMenuEntry);
- SetupStore("DisableRemote", Config::GetInstance().DisableRemote);
SetupStore("Username", Config::GetInstance().s_username.c_str());
SetupStore("Password", Config::GetInstance().s_password.c_str());
SetupStore("UUID", Config::GetInstance().GetUUID().c_str());
diff --git a/Config.h b/Config.h
index c089b4e..0a43600 100644
--- a/Config.h
+++ b/Config.h
@@ -39,7 +39,6 @@ public:
std::string s_password;
bool HideMainMenuEntry;
- bool DisableRemote;
std::string GetUUID();
void SetUUID(const char* uuid);
diff --git a/Media.cpp b/Media.cpp
index 4837bc7..8147e5c 100644
--- a/Media.cpp
+++ b/Media.cpp
@@ -30,7 +30,6 @@ Media::Media(Poco::XML::Node* pNode)
}
if(Poco::icompare(pChildNode->nodeName(), "Part") == 0) {
-
Poco::XML::AutoPtr<Poco::XML::NamedNodeMap> pAttribs = pChildNode->attributes();
m_sPartKey = GetNodeValue(pAttribs->getNamedItem("key"));
m_iPartId = GetNodeValueAsInt(pAttribs->getNamedItem("id"));
@@ -41,14 +40,11 @@ Media::Media(Poco::XML::Node* pNode)
pAttribs->release();
}
+ if(Poco::icompare(pChildNode->nodeName(), "Stream") == 0) {
+ m_vStreams.push_back(Stream(pChildNode));
+ }
pChildNode = it.nextNode();
}
}
-Media::~Media()
-{
}
-
-
-}
-
diff --git a/Media.h b/Media.h
index 5441bde..4d9b89e 100644
--- a/Media.h
+++ b/Media.h
@@ -16,6 +16,7 @@
#include <iostream>
#include "XmlObject.h" // Base class: model::XmlObject
+#include "Stream.h"
using Poco::XML::DOMParser;
using Poco::XML::Document;
@@ -30,9 +31,9 @@ namespace plexclient
class Media: XmlObject
{
-public:
+ public:
+ Media() {};
Media(Poco::XML::Node* pNode);
- ~Media();
public:
std::string m_sVideoResolution;
@@ -54,7 +55,8 @@ public:
std::string m_sPartFile;
long m_lPartSize;
std::string m_sPartContainer;
-
+
+ std::vector<Stream> m_vStreams;
};
}
diff --git a/MediaContainer.h b/MediaContainer.h
index 5d5c722..aaf0d9a 100644
--- a/MediaContainer.h
+++ b/MediaContainer.h
@@ -36,8 +36,6 @@ class MediaContainer: XmlObject
public:
MediaContainer(std::istream *response, PlexServer* Server);
- ~MediaContainer();
-
protected:
diff --git a/PVideo.cpp b/PVideo.cpp
index 770c15b..f893859 100644
--- a/PVideo.cpp
+++ b/PVideo.cpp
@@ -34,7 +34,7 @@ Video::Video(Poco::XML::Node* pNode, PlexServer* Server)
pAttribs->release();
} else if(Poco::icompare(pChildNode->nodeName(), "Media") == 0) {
- m_pMedia = new Media(pChildNode);
+ m_Media = Media(pChildNode);
} else if(Poco::icompare(pChildNode->nodeName(), "Genre") == 0) {
m_vGenre.push_back(GetNodeValue(pChildNode));
} else if(Poco::icompare(pChildNode->nodeName(), "Writer") == 0) {
@@ -52,9 +52,4 @@ Video::Video(Poco::XML::Node* pNode, PlexServer* Server)
}
}
-Video::~Video()
-{
-}
-
-
}
diff --git a/PVideo.h b/PVideo.h
index 0d5829a..fb4b5a5 100644
--- a/PVideo.h
+++ b/PVideo.h
@@ -34,7 +34,6 @@ class Video: XmlObject
{
public:
Video(Poco::XML::Node* pNode, PlexServer* Server);
- ~Video();
public:
int m_iRatingKey;
@@ -60,7 +59,7 @@ public:
std::vector<std::string> m_vCountry;
std::vector<std::string> m_vRole;
std::string m_sCollection;
- Media *m_pMedia;
+ Media m_Media;
PlexServer* m_pServer;
};
diff --git a/PlexHTTPRequestHandler.cpp b/PlexHTTPRequestHandler.cpp
index 7fc3415..d6c8ad3 100644
--- a/PlexHTTPRequestHandler.cpp
+++ b/PlexHTTPRequestHandler.cpp
@@ -141,7 +141,7 @@ void PlayerRequestHandler::handleRequest(Poco::Net::HTTPServerRequest& request,
std::cout << "FullUrl: " << fullUrl << std::endl;
MediaContainer *pCont = Plexservice::GetMediaContainer(fullUrl);
- std::string filePath = pCont->m_vVideos[0].m_pMedia->m_sPartKey;
+ std::string filePath = pCont->m_vVideos[0].m_Media.m_sPartKey;
Poco::URI fileuri(fullUrl);
fileuri.setPath(filePath);
diff --git a/Plexservice.cpp b/Plexservice.cpp
index ce803c3..f156550 100644
--- a/Plexservice.cpp
+++ b/Plexservice.cpp
@@ -207,11 +207,11 @@ MediaContainer* Plexservice::GetMediaContainer(std::string fullUrl)
//std::cout << "URI: " << session->getHost() << "[" << pRequest->getURI() << "]" << std::endl;
+ MediaContainer* pAllsections = new MediaContainer(&rs, new PlexServer(fileuri.getHost(), fileuri.getPort()));
+
delete pRequest;
delete session;
-
- MediaContainer* pAllsections = new MediaContainer(&rs, new PlexServer(fileuri.getHost(), fileuri.getPort()));
- //Poco::StreamCopier::copyStream(rs, std::cout);
+
return pAllsections;
}
@@ -319,7 +319,7 @@ std::string Plexservice::GetUniversalTranscodeUrl(Video* video, int offset, Plex
params << "&videoQuality=100";
params << "&session=" << encode(Config::GetInstance().GetUUID()); // TODO: generate Random SessionID
-
+
return pSrv->GetUri() + params.str();
}
diff --git a/Stream.cpp b/Stream.cpp
new file mode 100644
index 0000000..1611f72
--- /dev/null
+++ b/Stream.cpp
@@ -0,0 +1,26 @@
+#include "Stream.h"
+
+namespace plexclient
+{
+
+Stream::Stream(Poco::XML::Node* pNode)
+{
+ if(Poco::icompare(pNode->nodeName(), "Stream") == 0) {
+
+ Poco::XML::AutoPtr<Poco::XML::NamedNodeMap> pAttribs = pNode->attributes();
+
+ m_iID = GetNodeValueAsInt(pAttribs->getNamedItem("id"));
+ m_iStreamType = GetNodeValueAsInt(pAttribs->getNamedItem("streamType"));
+ m_iIndex = GetNodeValueAsInt(pAttribs->getNamedItem("index"));
+ m_iChannels = GetNodeValueAsInt(pAttribs->getNamedItem("channels"));
+ m_sCodec = GetNodeValue(pAttribs->getNamedItem("codec"));
+ m_sCodecId = GetNodeValue(pAttribs->getNamedItem("codecID"));
+ m_sLanguage = GetNodeValue(pAttribs->getNamedItem("language"));
+ m_sLanguageCode = GetNodeValue(pAttribs->getNamedItem("languageCode"));
+ m_eStreamType = GetNodeValueAsStreamType(pAttribs->getNamedItem("streamType"));
+
+ pAttribs->release();
+ }
+}
+
+} // namespace
diff --git a/Stream.h b/Stream.h
new file mode 100644
index 0000000..f8a392c
--- /dev/null
+++ b/Stream.h
@@ -0,0 +1,51 @@
+#ifndef STREAM_H
+#define STREAM_H
+
+
+#include <Poco/DOM/DOMParser.h>
+#include <Poco/DOM/Document.h>
+#include <Poco/DOM/NamedNodeMap.h>
+#include <Poco/DOM/NodeIterator.h>
+#include <Poco/DOM/NodeFilter.h>
+#include <Poco/DOM/NodeList.h>
+#include <Poco/DOM/AutoPtr.h>
+#include <Poco/Exception.h>
+#include <Poco/Timestamp.h>
+#include <Poco/String.h>
+
+#include <vector>
+#include <iostream>
+
+#include "XmlObject.h" // Base class: model::XmlObject
+
+using Poco::XML::DOMParser;
+using Poco::XML::Document;
+using Poco::XML::NodeIterator;
+using Poco::XML::NodeFilter;
+using Poco::XML::Node;
+using Poco::XML::AutoPtr;
+using Poco::Exception;
+
+namespace plexclient
+{
+
+class Stream: XmlObject
+{
+public:
+ Stream(Poco::XML::Node* pNode);
+
+public:
+ int m_iID;
+ int m_iStreamType;
+ int m_iIndex;
+ int m_iChannels;
+ std::string m_sCodec;
+ std::string m_sCodecId;
+ std::string m_sLanguage;
+ std::string m_sLanguageCode;
+ StreamType m_eStreamType;
+};
+
+}
+
+#endif // STREAM_H
diff --git a/SubscriptionManager.h b/SubscriptionManager.h
index b3f7f33..9d68e3c 100644
--- a/SubscriptionManager.h
+++ b/SubscriptionManager.h
@@ -26,7 +26,6 @@ class Subscriber
virtual std::string to_string() {
return "Subscriber-> Host: " + m_sHost + "; Port: " + std::string(itoa(m_iPort)) + "; Uuid:" + m_sUuid + "; CmdID:" + std::string(itoa(m_iCommandId));
- return "";
}
private:
diff --git a/XmlObject.cpp b/XmlObject.cpp
index a9c0bb4..09db02d 100644
--- a/XmlObject.cpp
+++ b/XmlObject.cpp
@@ -87,4 +87,20 @@ MediaType XmlObject::GetNodeValueAsMediaType(Poco::XML::Node* pNode)
return type;
}
+StreamType XmlObject::GetNodeValueAsStreamType(Poco::XML::Node* pNode)
+{
+ StreamType type = sUNDEF;
+
+ if(pNode != 0) {
+ int iType = GetNodeValueAsInt(pNode);
+ switch(iType) {
+ case 1: type = sVIDEO; break;
+ case 2: type = sAUDIO; break;
+ case 3: type = sSUBTITLE; break;
+ default: type = sUNDEF; break;
+ }
+ }
+ return type;
+}
+
}
diff --git a/XmlObject.h b/XmlObject.h
index db9969a..16b63b7 100644
--- a/XmlObject.h
+++ b/XmlObject.h
@@ -12,6 +12,7 @@ namespace plexclient
{
enum MediaType {UNDEF = 0, PHOTO, MOVIE, MUSIC, SHOW, SEASON};
+enum StreamType {sUNDEF = 0, sVIDEO = 1, sAUDIO = 2, sSUBTITLE = 3};
class XmlObject
{
@@ -25,6 +26,7 @@ protected:
static bool GetNodeValueAsBool(Poco::XML::Node* pNode);
static Poco::Timestamp GetNodeValueAsTimeStamp(Poco::XML::Node* pNode);
static MediaType GetNodeValueAsMediaType(Poco::XML::Node* pNode);
+ static StreamType GetNodeValueAsStreamType(Poco::XML::Node* pNode);
private:
};
diff --git a/hlsPlayer.cpp b/hlsPlayer.cpp
index 3f90750..9245efb 100644
--- a/hlsPlayer.cpp
+++ b/hlsPlayer.cpp
@@ -1,5 +1,6 @@
#include "hlsPlayer.h"
+#include <sys/time.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/Exception.h>
@@ -8,6 +9,9 @@
#include <pcrecpp.h>
#include "Plexservice.h"
+#include "XmlObject.h"
+#include "Media.h"
+#include "Stream.h"
static cMutex hlsMutex;
@@ -18,7 +22,7 @@ cHlsSegmentLoader::cHlsSegmentLoader(std::string startm3u8)
m_newList = false;
m_bufferFilled = false;
m_lastLoadedSegment = 0;
- m_segmentsToBuffer = 3;
+ m_segmentsToBuffer = 2;
m_pBuffer = new uchar[8192];
// Initialize members
@@ -54,9 +58,9 @@ void cHlsSegmentLoader::Action(void)
if(!LoadLists()) return;
int estSize = EstimateSegmentSize();
- m_ringBufferSize = MEGABYTE(estSize*3);
+ m_ringBufferSize = MEGABYTE(estSize*m_segmentsToBuffer);
- isyslog("[plex]%s Create Ringbuffer %d MB", __FUNCTION__, estSize*3);
+ isyslog("[plex]%s Create Ringbuffer %d MB", __FUNCTION__, estSize*m_segmentsToBuffer);
m_pRingbuffer = new cRingBufferLinear(m_ringBufferSize, 2*TS_SIZE);
@@ -128,9 +132,9 @@ bool cHlsSegmentLoader::LoadIndexList(void)
m_segmentUriPart = path.substr(0, path.find_last_of("/")+1);
}
if(m_indexParser.TargetDuration > 3) {
- m_segmentsToBuffer = 1;
- } else {
m_segmentsToBuffer = 2;
+ } else {
+ m_segmentsToBuffer = 3;
}
}
return res;
@@ -174,7 +178,11 @@ int cHlsSegmentLoader::EstimateSegmentSize()
int len = m_indexParser.TargetDuration;
double estSize = (bandw) * len;
- estSize = max(estSize, 1.0); // default
+ estSize = max(estSize, 1.0);
+ // default
+ if(estSize <= 1) {
+ estSize = 32;
+ }
return ceil(estSize);
}
@@ -322,8 +330,11 @@ cHlsPlayer::cHlsPlayer(std::string startm3u8, plexclient::Video* Video)
m_pSegmentLoader = new cHlsSegmentLoader(startm3u8);
m_pVideo = Video;
m_timeOffset = 0;
+ m_jumpOffset = 0;
+ m_tTimeSum = 0;
m_doJump = false;
m_isBuffering = false;
+ AudioIndexOffset = 1000; // Just a magic number
}
cHlsPlayer::~cHlsPlayer()
@@ -332,6 +343,21 @@ cHlsPlayer::~cHlsPlayer()
m_pSegmentLoader = NULL;
}
+void cHlsPlayer::SetAudioAndSubtitleTracks(void)
+{
+ //DeviceClrAvailableTracks();
+ DeviceSetAvailableTrack(ttDolby, 0, 0, "Current");
+ if(m_pVideo->m_Media.m_vStreams.size() > 0) {
+ std::vector<plexclient::Stream> streams = m_pVideo->m_Media.m_vStreams;
+ for(std::vector<plexclient::Stream>::iterator it = streams.begin(); it != streams.end(); ++it) {
+ plexclient::Stream *pStream = &(*it);
+ if(pStream->m_eStreamType == plexclient::sAUDIO) {
+ DeviceSetAvailableTrack(ttDolby, pStream->m_iIndex, pStream->m_iIndex + AudioIndexOffset, pStream->m_sLanguage.c_str(), pStream->m_sCodec.c_str());
+ }
+ }
+ }
+}
+
void cHlsPlayer::Action(void)
{
@@ -344,12 +370,21 @@ void cHlsPlayer::Action(void)
DeviceFreeze();
m_doJump = false;
+ m_bFirstPlay = true;
std::string uri = plexclient::Plexservice::GetUniversalTranscodeUrl(m_pVideo, m_jumpOffset);
m_pSegmentLoader->LoadM3u8(uri);
+ m_timeOffset = m_jumpOffset;
DeviceClear();
DevicePlay();
+ playMode = pmPlay;
} else if(m_pSegmentLoader && m_pSegmentLoader->BufferFilled()) {
DoPlay();
+ if(m_bFirstPlay) {
+ SetAudioAndSubtitleTracks();
+ ResetPlayedSeconds();
+ m_bFirstPlay = false;
+ }
+ CountPlayedSeconds();
} else {
// Pause
cCondWait::SleepMs(3);
@@ -359,6 +394,7 @@ void cHlsPlayer::Action(void)
bool cHlsPlayer::DoPlay(void)
{
+ bool res = false;
cPoller Poller;
if(DevicePoll(Poller, 10)) {
hlsMutex.Lock();
@@ -372,6 +408,7 @@ bool cHlsPlayer::DoPlay(void)
if(bytesAvaliable >= TS_SIZE) {
int playedBytes = PlayTs(toPlay, TS_SIZE, false);
m_pSegmentLoader->m_pRingbuffer->Del(playedBytes);
+ res = true;
} else {
// Pause & Buffer
break;
@@ -379,7 +416,7 @@ bool cHlsPlayer::DoPlay(void)
}
hlsMutex.Unlock();
}
- return true;
+ return res;
}
void cHlsPlayer::Activate(bool On)
@@ -391,12 +428,10 @@ void cHlsPlayer::Activate(bool On)
}
}
-bool cHlsPlayer::GetIndex(int& Current, int& Total, bool SnapToIFrame)
+bool cHlsPlayer::GetIndex(int& Current, int& Total, bool SnapToIFrame __attribute__((unused)))
{
- long stc = DeviceGetSTC();
- Total = m_pVideo->m_pMedia->m_lDuration / 1000 * 25;//FramesPerSecond(); // milliseconds
- Current = stc / (100 * 1000) * FramesPerSecond(); // 100ns per Tick
- Current += m_timeOffset; // apply offset
+ Total = m_pVideo->m_Media.m_lDuration / 1000 * FramesPerSecond(); // milliseconds
+ Current = GetPlayedSeconds() * FramesPerSecond();
return true;
}
@@ -446,18 +481,12 @@ void cHlsPlayer::Stop(void)
double cHlsPlayer::FramesPerSecond(void)
{
- return m_pVideo->m_pMedia->m_VideoFrameRate ? m_pVideo->m_pMedia->m_VideoFrameRate : DEFAULTFRAMESPERSECOND;
+ return m_pVideo->m_Media.m_VideoFrameRate ? m_pVideo->m_Media.m_VideoFrameRate : DEFAULTFRAMESPERSECOND;
}
void cHlsPlayer::JumpRelative(int seconds)
{
- long stc = DeviceGetSTC();
- if(stc > 0) {
- int current = stc / (100 * 1000);
- JumpTo(current + seconds);
- } else {
- JumpTo(m_jumpOffset + seconds);
- }
+ JumpTo(GetPlayedSeconds() + seconds);
}
void cHlsPlayer::JumpTo(int seconds)
@@ -468,3 +497,68 @@ void cHlsPlayer::JumpTo(int seconds)
m_jumpOffset = seconds;
m_doJump = true;
}
+
+void cHlsPlayer::SetAudioTrack(eTrackType Type __attribute__((unused)), const tTrackId* TrackId)
+{
+ dsyslog("[plex]%s %d %s", __FUNCTION__, TrackId->id, TrackId->language);
+ // Check if stream availiable
+ int streamId = 0;
+ if(m_pVideo->m_Media.m_vStreams.size() > 0) {
+ std::vector<plexclient::Stream> streams = m_pVideo->m_Media.m_vStreams;
+ for(std::vector<plexclient::Stream>::iterator it = streams.begin(); it != streams.end(); ++it) {
+ plexclient::Stream *pStream = &(*it);
+ if(pStream->m_eStreamType == plexclient::sAUDIO && pStream->m_iIndex + AudioIndexOffset == TrackId->id) {
+ streamId = pStream->m_iID;
+ break;
+ }
+ }
+ }
+ // Then do the request
+ if(streamId > 0) {
+ Poco::Net::HTTPClientSession session(m_pVideo->m_pServer->GetIpAdress(), m_pVideo->m_pServer->GetPort());
+
+ std::string uri = "/library/parts/" + std::string(itoa(m_pVideo->m_Media.m_iPartId)) + "?audioStreamID=" + std::string(itoa(streamId));
+ Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_PUT, uri);
+ session.sendRequest(req);
+
+ Poco::Net::HTTPResponse resp;
+ session.receiveResponse(resp);
+
+ if(resp.getStatus() == 200) {
+ DeviceSetCurrentAudioTrack(eTrackType(ttDolby + 0)); // hacky
+ DeviceSetAvailableTrack(ttDolby, 0, 0, TrackId->language);
+ JumpRelative(0); // Reload Stream to get new Audio
+ dsyslog("[plex]: Set AudioStream: %d\n", TrackId->id);
+ }
+ }
+}
+
+unsigned long long cHlsPlayer::MsNow(void)
+{
+ static timeval tv;
+ gettimeofday(&tv, 0);
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+int cHlsPlayer::GetPlayedSeconds(void)
+{
+ return m_timeOffset + (m_tTimeSum / 1000);
+}
+
+void cHlsPlayer::CountPlayedSeconds(void)
+{
+ if (playMode == pmPlay) {
+ unsigned long long tTmp = MsNow();
+ m_tTimeSum += (tTmp - m_tLastTime);
+ m_tLastTime = tTmp;
+ }
+ else {
+ m_tLastTime = MsNow();
+ }
+}
+
+void cHlsPlayer::ResetPlayedSeconds(void)
+{
+ m_tTimeSum = 0;
+ m_tLastTime = MsNow();
+}
diff --git a/hlsPlayer.h b/hlsPlayer.h
index a7663f5..49561d8 100644
--- a/hlsPlayer.h
+++ b/hlsPlayer.h
@@ -68,6 +68,7 @@ public:
class cHlsPlayer : public cPlayer, cThread
{
private:
+ int AudioIndexOffset;
cHlsSegmentLoader* m_pSegmentLoader;
plexclient::Video* m_pVideo;
@@ -80,12 +81,19 @@ private:
int m_actualSegment;
int m_actualTime;
long m_lastValidSTC;
+
+ unsigned long long m_tLastTime;
+ unsigned long long m_tTimeSum;
+ bool m_bFirstPlay;
enum ePlayModes { pmPlay, pmPause };
ePlayModes playMode;
virtual void Activate(bool On);
-
+ unsigned long long MsNow(void);
+ int GetPlayedSeconds(void);
+ void CountPlayedSeconds(void);
+ void ResetPlayedSeconds(void);
protected:
void Action(void);
@@ -100,12 +108,14 @@ public:
virtual bool GetIndex(int &Current, int &Total, bool SnapToIFrame = false);
virtual bool GetReplayMode(bool &Play, bool &Forward, int &Speed);
virtual double FramesPerSecond(void);
+ virtual void SetAudioTrack(eTrackType Type, const tTrackId *TrackId);
void Pause(void);
void Play(void);
void Stop(void);
bool Active(void);
void JumpTo(int seconds);
void JumpRelative(int seconds);
+ void SetAudioAndSubtitleTracks(void);
};
diff --git a/hlsPlayerControl.cpp b/hlsPlayerControl.cpp
index b4b93df..f4e1330 100644
--- a/hlsPlayerControl.cpp
+++ b/hlsPlayerControl.cpp
@@ -4,6 +4,8 @@
#include "PlexServer.h"
#include "Plexservice.h"
+#include "MediaContainer.h"
+#include "PVideo.h"
// static
cControl* cHlsPlayerControl::Create(plexclient::Video* Video)
@@ -11,17 +13,22 @@ cControl* cHlsPlayerControl::Create(plexclient::Video* Video)
if(!Video->m_pServer)
return NULL;
- std::string transcodeUri = plexclient::Plexservice::GetUniversalTranscodeUrl(Video);
+ // get Metadata
+ std::string uri = Video->m_pServer->GetUri() + Video->m_sKey;
+ plexclient::MediaContainer *pmcontainer = plexclient::Plexservice::GetMediaContainer(uri);
+
+ std::cout << "Video Size" << pmcontainer->m_vVideos.size() << " Video: " << pmcontainer->m_vVideos[0].m_sKey << std::endl;
+ std::string transcodeUri = plexclient::Plexservice::GetUniversalTranscodeUrl(&pmcontainer->m_vVideos[0]);
- cHlsPlayerControl* playerControl = new cHlsPlayerControl(new cHlsPlayer(transcodeUri, Video), Video);
- playerControl->m_title = Video->m_sTitle;
+ cHlsPlayerControl* playerControl = new cHlsPlayerControl(new cHlsPlayer(transcodeUri, &pmcontainer->m_vVideos[0]), pmcontainer);
+ playerControl->m_title = pmcontainer->m_vVideos[0].m_sTitle;
return playerControl;
}
-cHlsPlayerControl::cHlsPlayerControl(cHlsPlayer* Player, plexclient::Video* Video) :cControl(Player)
+cHlsPlayerControl::cHlsPlayerControl(cHlsPlayer* Player, plexclient::MediaContainer* Container) :cControl(Player)
{
player = Player;
- m_pVideo = Video;
+ m_pVideo = &Container->m_vVideos[0];
//m_title = title;
displayReplay = NULL;
@@ -31,11 +38,12 @@ cHlsPlayerControl::cHlsPlayerControl(cHlsPlayer* Player, plexclient::Video* Vide
lastSpeed = -2; // an invalid value
timeoutShow = 0;
- cStatus::MsgReplaying(this, m_title.c_str(), Video->m_pMedia->m_sPartFile.c_str(), true);
+ cStatus::MsgReplaying(this, m_title.c_str(), m_pVideo->m_Media.m_sPartFile.c_str(), true);
}
cHlsPlayerControl::~cHlsPlayerControl()
{
+ //delete m_pMediaContainer;
}
cString cHlsPlayerControl::GetHeader(void)
diff --git a/hlsPlayerControl.h b/hlsPlayerControl.h
index 8eb8bc6..2f7347b 100644
--- a/hlsPlayerControl.h
+++ b/hlsPlayerControl.h
@@ -5,12 +5,14 @@
#include <vdr/tools.h>
#include "hlsPlayer.h"
+#include "MediaContainer.h"
#include "PVideo.h"
class cHlsPlayerControl : public cControl
{
private:
static volatile int active;
+ plexclient::MediaContainer* m_pMediaContainer;
plexclient::Video* m_pVideo;
cHlsPlayer* player;
std::string m_title;
@@ -31,7 +33,7 @@ protected:
public:
static cControl* Create(plexclient::Video* Video);
- cHlsPlayerControl(cHlsPlayer* Player, plexclient::Video* Video);
+ cHlsPlayerControl(cHlsPlayer* Player, plexclient::MediaContainer* Container);
virtual ~cHlsPlayerControl();
virtual void Show(void);
diff --git a/plex.cpp b/plex.cpp
index 2626d75..9ae6acf 100644
--- a/plex.cpp
+++ b/plex.cpp
@@ -2,10 +2,13 @@
#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
+//static char ConfigHideMainMenuEntry; ///< hide main menu entry
+//char ConfigDisableRemote; ///< disable remote during external play
/**
** Play a file.
@@ -273,14 +276,6 @@ const char *cMyPlugin::Description(void)
}
/**
-** Process the command line arguments.
-*/
-bool cMyPlugin::ProcessArgs(int argc, char *argv[])
-{
- return true;
-}
-
-/**
** Start any background activities the plugin shall perform.
*/
bool cMyPlugin::Initialize(void)
@@ -308,7 +303,7 @@ bool cMyPlugin::Initialize(void)
*/
const char *cMyPlugin::MainMenuEntry(void)
{
- return ConfigHideMainMenuEntry ? NULL : MAINMENUENTRY;
+ return Config::GetInstance().HideMainMenuEntry ? NULL : MAINMENUENTRY;
}
/**
@@ -361,7 +356,6 @@ 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, "DisableRemote") == 0) Config::GetInstance().DisableRemote = 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);
diff --git a/plex.h b/plex.h
index 4090888..e37e39e 100644
--- a/plex.h
+++ b/plex.h
@@ -23,35 +23,31 @@
#include <iterator>
#include <algorithm>
-static const char *DESCRIPTION = "Plex for VDR Plugin";
-static const char *MAINMENUENTRY = "Plex for VDR";
-
/**
** 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);
- }
+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);
+ }
};
/**
@@ -59,15 +55,15 @@ class cMyRemote:public cRemote
*/
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 &);
+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 &);
};
/**
@@ -77,14 +73,14 @@ class cMyPlayer:public cPlayer
*/
class cMyStatus:public cStatus
{
- private:
- int Volume; ///< current volume
+private:
+ int Volume; ///< current volume
- public:
- cMyStatus(void); ///< my status constructor
+public:
+ cMyStatus(void); ///< my status constructor
- protected:
- virtual void SetVolume(int, bool); ///< volume changed
+protected:
+ virtual void SetVolume(int, bool); ///< volume changed
};
/**
@@ -92,26 +88,26 @@ class cMyStatus:public cStatus
*/
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
+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
};
/*
- * Plex Browser
+ * Plex Browser
*/
class cPlexBrowser :public cOsdMenu
@@ -124,21 +120,21 @@ private:
std::vector<std::string> m_vStack;
std::string m_sSection;
std::string m_sActualPos;
- /// Create a browser menu for current directory
- void CreateMenu();
- /// Handle menu level up
- eOSState LevelUp(void);
- /// Handle menu item selection
- eOSState ProcessSelected();
-
+ /// Create a browser menu for current directory
+ void CreateMenu();
+ /// Handle menu level up
+ eOSState LevelUp(void);
+ /// Handle menu item selection
+ eOSState ProcessSelected();
+
public:
cPlexBrowser(const char *title, plexclient::PlexServer* pServ);
~cPlexBrowser();
/// File browser destructor
- //virtual ~ cPlexBrowser();
- /// Process keyboard input
- virtual eOSState ProcessKey(eKeys);
-
+ //virtual ~ cPlexBrowser();
+ /// Process keyboard input
+ virtual eOSState ProcessKey(eKeys);
+
};
/**
@@ -146,11 +142,11 @@ public:
*/
class cPlayMenu:public cOsdMenu
{
- private:
- public:
- cPlayMenu(const char *, int = 0, int = 0, int = 0, int = 0, int = 0);
- virtual ~ cPlayMenu();
- virtual eOSState ProcessKey(eKeys);
+private:
+public:
+ cPlayMenu(const char *, int = 0, int = 0, int = 0, int = 0, int = 0);
+ virtual ~ cPlayMenu();
+ virtual eOSState ProcessKey(eKeys);
};
/**
@@ -158,14 +154,14 @@ class cPlayMenu:public cOsdMenu
*/
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
+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
};
/**
@@ -173,13 +169,13 @@ class cMyOsd:public cOsd
*/
class cMyOsdProvider:public cOsdProvider
{
- private:
- static cOsd *Osd;
+private:
+ static cOsd *Osd;
- public:
- virtual cOsd * CreateOsd(int, int, uint);
- virtual bool ProvidesTrueColor(void);
- cMyOsdProvider(void);
+public:
+ virtual cOsd * CreateOsd(int, int, uint);
+ virtual bool ProvidesTrueColor(void);
+ cMyOsdProvider(void);
};
/**
@@ -187,31 +183,30 @@ class cMyOsdProvider:public cOsdProvider
*/
class cMyDevice:public cDevice
{
- public:
- cMyDevice(void);
- virtual ~ cMyDevice(void);
+public:
+ cMyDevice(void);
+ virtual ~ cMyDevice(void);
- virtual void GetOsdSize(int &, int &, double &);
+ virtual void GetOsdSize(int &, int &, double &);
- protected:
- virtual void MakePrimaryDevice(bool);
+protected:
+ virtual void MakePrimaryDevice(bool);
};
class cMyPlugin:public cPlugin
{
- public:
- cMyPlugin(void);
- virtual ~ cMyPlugin(void);
- virtual const char *Version(void);
- virtual const char *Description(void);
- virtual bool ProcessArgs(int, char *[]);
- virtual bool Initialize(void);
- virtual void MainThreadHook(void);
- virtual const char *MainMenuEntry(void);
- virtual cOsdObject *MainMenuAction(void);
- virtual cMenuSetupPage *SetupMenu(void);
- virtual bool SetupParse(const char *, const char *);
+public:
+ cMyPlugin(void);
+ virtual ~ cMyPlugin(void);
+ virtual const char *Version(void);
+ virtual const char *Description(void);
+ virtual bool Initialize(void);
+ virtual void MainThreadHook(void);
+ virtual const char *MainMenuEntry(void);
+ virtual cOsdObject *MainMenuAction(void);
+ virtual cMenuSetupPage *SetupMenu(void);
+ virtual bool SetupParse(const char *, const char *);
};
-#endif \ No newline at end of file
+#endif