diff options
| author | chriszero <zerov83@gmail.com> | 2015-01-28 21:17:18 +0100 | 
|---|---|---|
| committer | chriszero <zerov83@gmail.com> | 2015-01-28 21:17:18 +0100 | 
| commit | 87eb8a9e931606da4197391b6e3a09376b1383c2 (patch) | |
| tree | 9427c28a2d7e9e44d4d77dc7fe53ff91f5152e23 | |
| parent | 1da4dbe662e75be47e046472137c6bd72daa7b4d (diff) | |
| download | vdr-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.cpp | 2 | ||||
| -rw-r--r-- | Config.h | 1 | ||||
| -rw-r--r-- | Media.cpp | 10 | ||||
| -rw-r--r-- | Media.h | 8 | ||||
| -rw-r--r-- | MediaContainer.h | 2 | ||||
| -rw-r--r-- | PVideo.cpp | 7 | ||||
| -rw-r--r-- | PVideo.h | 3 | ||||
| -rw-r--r-- | PlexHTTPRequestHandler.cpp | 2 | ||||
| -rw-r--r-- | Plexservice.cpp | 8 | ||||
| -rw-r--r-- | Stream.cpp | 26 | ||||
| -rw-r--r-- | Stream.h | 51 | ||||
| -rw-r--r-- | SubscriptionManager.h | 1 | ||||
| -rw-r--r-- | XmlObject.cpp | 16 | ||||
| -rw-r--r-- | XmlObject.h | 2 | ||||
| -rw-r--r-- | hlsPlayer.cpp | 134 | ||||
| -rw-r--r-- | hlsPlayer.h | 12 | ||||
| -rw-r--r-- | hlsPlayerControl.cpp | 20 | ||||
| -rw-r--r-- | hlsPlayerControl.h | 4 | ||||
| -rw-r--r-- | plex.cpp | 18 | ||||
| -rw-r--r-- | plex.h | 203 | 
20 files changed, 357 insertions, 173 deletions
| @@ -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()); @@ -39,7 +39,6 @@ public:  	std::string s_password;  	bool HideMainMenuEntry; -	bool DisableRemote;  	std::string GetUUID();  	void SetUUID(const char* uuid); @@ -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() -{  } - - -} - @@ -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: @@ -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() -{ -} - -  } @@ -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); @@ -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); @@ -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 | 
