summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormethodus <methodus@web.de>2012-10-12 20:46:25 +0200
committermethodus <methodus@web.de>2012-10-12 20:46:25 +0200
commitb450015b9a6c0d35c264e93fbc9bcdf92538f47a (patch)
tree8959f8d24f8a14285e8623af078beacd860d4c58
parent9b199c2d95141de43fac33412ec3e9fc1f543e71 (diff)
downloadvdr-plugin-upnp-b450015b9a6c0d35c264e93fbc9bcdf92538f47a.tar.gz
vdr-plugin-upnp-b450015b9a6c0d35c264e93fbc9bcdf92538f47a.tar.bz2
Fixed some minor issues. Added current event from schedule to channel details.
-rw-r--r--include/media/profile.h16
-rw-r--r--include/plugin.h2
-rw-r--r--include/webserver.h2
-rw-r--r--media/mediaManager.cpp44
-rw-r--r--media/pluginManager.cpp6
-rw-r--r--media/profile.cpp51
-rw-r--r--plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp115
-rw-r--r--plugins/provider/vdrProvider/vdrProvider.cpp12
-rw-r--r--server/webserver.cpp13
9 files changed, 195 insertions, 66 deletions
diff --git a/include/media/profile.h b/include/media/profile.h
index e8b2bda..efac36d 100644
--- a/include/media/profile.h
+++ b/include/media/profile.h
@@ -58,6 +58,22 @@ struct DLNA4thField {
string ToString();
};
+struct ProtocolInfo {
+ enum StreamType {
+ DLNA_STREAM_HTTP,
+ DLNA_STREAM_RTP
+ };
+
+ ProtocolInfo();
+ ProtocolInfo(string contentType, DLNA4thField fourthField, StreamType type = DLNA_STREAM_HTTP);
+
+ StreamType streamType;
+ string contentType;
+ DLNA4thField fourthField;
+
+ string ToString();
+};
+
namespace video {
}
diff --git a/include/plugin.h b/include/plugin.h
index 6749336..d267bcd 100644
--- a/include/plugin.h
+++ b/include/plugin.h
@@ -374,7 +374,7 @@ public:
* The implementor of a resource provider MUST either implement
* this function or the file access methods below.
*/
- virtual string GetHTTPUri(const string& uri, const string& currentIP);
+ virtual string GetHTTPUri(const string& uri, const string& currentIP, const string& protocolInfo);
virtual bool Seekable() const;
diff --git a/include/webserver.h b/include/webserver.h
index 39ca8df..02377d7 100644
--- a/include/webserver.h
+++ b/include/webserver.h
@@ -38,6 +38,8 @@ namespace upnp {
const std::string GetStaticContentUrl() const;
const std::string GetPresentationUrl() const;
+ const std::string GetThumbnailDir() const;
+
std::string GetListenerAddress() const { return mListenerAddress; }
uint16_t GetListenerPort() const { return mListenerPort; }
diff --git a/media/mediaManager.cpp b/media/mediaManager.cpp
index 3df218a..377ed19 100644
--- a/media/mediaManager.cpp
+++ b/media/mediaManager.cpp
@@ -5,6 +5,7 @@
* Author: savop
*/
+#include "../include/webserver.h"
#include "../include/media/mediaManager.h"
#include "../include/pluginManager.h"
#include "../include/server.h"
@@ -326,27 +327,40 @@ int cMediaManager::CreateResponse(MediaRequest& request, const string& select, c
select2.setString("objectID", objectID);
+ int i=0;
+ string resourceFile;
+ string resourceURI;
+ stringstream tntnet;
for(tntdb::Statement::const_iterator it2 = select2.begin(); it2 != select2.end(); ++it2){
row2 = (*it2);
- boost::shared_ptr<cUPnPResourceProvider> provider(CreateResourceProvider(row2.getString(property::resource::KEY_RESOURCE)));
+ string resourceFile = row2.getString(property::resource::KEY_RESOURCE);
+ boost::shared_ptr<cUPnPResourceProvider> provider(CreateResourceProvider(resourceFile));
+ tntnet.str(string());
if(provider.get()){
- string resourceURI = provider->GetHTTPUri(row2.getString(property::resource::KEY_RESOURCE), cMediaServer::GetInstance()->GetServerIPAddress());
-
- IXML_Element* resource = ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_RESOURCE, resourceURI);
-
- if(resource){
- ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_PROTOCOL_INFO, row2.getString(property::resource::KEY_PROTOCOL_INFO));
- ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_BITRATE, row2.getString(property::resource::KEY_BITRATE));
- ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_BITS_PER_SAMPLE, row2.getString(property::resource::KEY_BITS_PER_SAMPLE));
- ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_COLOR_DEPTH, row2.getString(property::resource::KEY_COLOR_DEPTH));
- ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_DURATION, row2.getString(property::resource::KEY_DURATION));
- ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_NR_AUDIO_CHANNELS, row2.getString(property::resource::KEY_NR_AUDIO_CHANNELS));
- ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_RESOLUTION, row2.getString(property::resource::KEY_RESOLUTION));
- ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_SAMPLE_FREQUENCY, row2.getString(property::resource::KEY_SAMPLE_FREQUENCY));
- ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_SIZE, tools::ToString(row2.getInt64(property::resource::KEY_SIZE)));
+ resourceURI = provider->GetHTTPUri(resourceFile, cMediaServer::GetInstance()->GetServerIPAddress(), row2.getString(property::resource::KEY_PROTOCOL_INFO));
+ if(resourceURI.empty()){
+ tntnet << cMediaServer::GetInstance()->GetWebserver().GetBaseUrl() << "getStream?objectID=" << objectID << "&resourceID=" << i++;
+ resourceURI = tntnet.str();
}
+ } else if(resourceFile.find("thumb://",0) == 0 && !resourceFile.substr(8).empty()) {
+ tntnet << cMediaServer::GetInstance()->GetWebserver().GetBaseUrl() << "thumbs/" << resourceFile.substr(8);
+ resourceURI = tntnet.str();
+ }
+
+ IXML_Element* resource = ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_RESOURCE, resourceURI);
+
+ if(resource){
+ ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, resource, property::resource::KEY_PROTOCOL_INFO, row2.getString(property::resource::KEY_PROTOCOL_INFO));
+ ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, resource, property::resource::KEY_BITRATE, row2.getString(property::resource::KEY_BITRATE));
+ ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, resource, property::resource::KEY_BITS_PER_SAMPLE, row2.getString(property::resource::KEY_BITS_PER_SAMPLE));
+ ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, resource, property::resource::KEY_COLOR_DEPTH, row2.getString(property::resource::KEY_COLOR_DEPTH));
+ ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, resource, property::resource::KEY_DURATION, row2.getString(property::resource::KEY_DURATION));
+ ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, resource, property::resource::KEY_NR_AUDIO_CHANNELS, row2.getString(property::resource::KEY_NR_AUDIO_CHANNELS));
+ ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, resource, property::resource::KEY_RESOLUTION, row2.getString(property::resource::KEY_RESOLUTION));
+ ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, resource, property::resource::KEY_SAMPLE_FREQUENCY, row2.getString(property::resource::KEY_SAMPLE_FREQUENCY));
+ ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, resource, property::resource::KEY_SIZE, tools::ToString(row2.getInt64(property::resource::KEY_SIZE)));
}
}
diff --git a/media/pluginManager.cpp b/media/pluginManager.cpp
index ea7f82a..66cf69d 100644
--- a/media/pluginManager.cpp
+++ b/media/pluginManager.cpp
@@ -278,7 +278,7 @@ bool cUPnPResourceProvider::GetMetadata(const string& uri, cMetadata& metadata){
}
-string cUPnPResourceProvider::GetHTTPUri(const string&, const string&){
+string cUPnPResourceProvider::GetHTTPUri(const string&, const string&, const string&){
return string();
}
@@ -393,16 +393,12 @@ bool upnp::cPluginManager::DLL::Load(){
if (!(error = dlerror())){
isProvider = true;
return true;
- } else {
- cerr << error << endl;
}
function = (FuncPtr)dlsym(handle, "UPnPCreateMediaProfiler");
if (!(error = dlerror())){
isProvider = false;
return true;
- } else {
- cerr << error << endl;
}
} else {
cerr << "Error while opening plugin: " << error << endl;
diff --git a/media/profile.cpp b/media/profile.cpp
index 0cff566..8c9df6f 100644
--- a/media/profile.cpp
+++ b/media/profile.cpp
@@ -11,6 +11,42 @@
using namespace upnp;
+ProtocolInfo::ProtocolInfo()
+: streamType(DLNA_STREAM_HTTP)
+, contentType(string())
+, fourthField(DLNA4thField())
+{
+}
+
+ProtocolInfo::ProtocolInfo(string ct, DLNA4thField ffld, StreamType t)
+: streamType(t)
+, contentType(ct)
+, fourthField(ffld)
+{
+}
+
+string ProtocolInfo::ToString(){
+ if(contentType.empty()) return string();
+
+ stringstream ss;
+ switch(streamType){
+ case DLNA_STREAM_HTTP:
+ ss << "http-get:";
+ break;
+ case DLNA_STREAM_RTP:
+ ss << "rtsp-rtp-udp:";
+ break;
+ }
+
+ ss << "*:";
+
+ ss << contentType << ":";
+
+ ss << fourthField.ToString();
+
+ return ss.str();
+}
+
DLNA4thField::DLNA4thField()
: profile(string())
, operations(DLNA_OPERATION_NONE)
@@ -30,17 +66,20 @@ DLNA4thField::DLNA4thField(string pn, uint8_t op, string ps, bool ci, uint32_t f
}
string DLNA4thField::ToString(){
- stringstream ss;
-
if(profile.empty()) return "*";
- ss << "DLNA.ORG_PN=" << profile << ";";
+ stringstream ss;
+ ss << "DLNA.ORG_PN=" << profile;
+
+ if(primaryFlags){
+ ss << ";";
- ss << "DLNA.ORG_OP=" << bitset<2>(operations) << ";";
+ ss << "DLNA.ORG_OP=" << bitset<2>(operations) << ";";
- ss << "DLNA.ORG_CI=" << bitset<1>(conversionIndicator) << ";";
+ ss << "DLNA.ORG_CI=" << bitset<1>(conversionIndicator) << ";";
- ss << "DLNA.ORG_FLAGS=" << hex << primaryFlags << "000000000000000000000000" << ";";
+ ss << "DLNA.ORG_FLAGS=" << hex << primaryFlags << "000000000000000000000000";
+ }
return ss.str();
}
diff --git a/plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp b/plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp
index 4bb14c6..06948ac 100644
--- a/plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp
+++ b/plugins/profiler/vdrDVBProfiler/dvbProfiler.cpp
@@ -5,6 +5,8 @@
* Author: savop
*/
+#include <server.h>
+#include <webserver.h>
#include <vdr/channels.h>
#include <vdr/epg.h>
#include <vdr/tools.h>
@@ -13,6 +15,8 @@
#include <string>
#include <sstream>
#include <media/profile.h>
+#include <boost/date_time/gregorian/gregorian.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
using namespace std;
@@ -65,42 +69,85 @@ private:
metadata.SetProperty(cMetadata::Property(property::object::KEY_CHANNEL_NR, (long int)channel->Number()));
// Now, we try to get the present event of the schedule
- metadata.SetProperty(cMetadata::Property(property::object::KEY_TITLE, string(channel->Name())));
-
- cMetadata::Resource resource;
-
- stringstream protocolInfo;
-
- protocolInfo << "http-get:*:video/mpeg:";
-
- DLNA4thField fourthfield;
-
- switch (channel->Vtype()) {
- case 0x02:
- fourthfield = DLNA4thField("MPEG_TS_SD_EU_ISO", DLNA_OPERATION_NONE,
- DLNA_PLAYSPEEDS_NONE, DLNA_CONVERSION_NONE,
- DLNA_FLAG_STREAMING_TRANSFER |
- DLNA_FLAG_SN_INCREASE |
- DLNA_FLAG_VERSION_1_5 );
- break;
- case 0x1B:
- fourthfield = DLNA4thField("AVC_TS_HD_EU_ISO", DLNA_OPERATION_NONE,
- DLNA_PLAYSPEEDS_NONE, DLNA_CONVERSION_NONE,
- DLNA_FLAG_STREAMING_TRANSFER |
- DLNA_FLAG_SN_INCREASE |
- DLNA_FLAG_VERSION_1_5 );
- break;
- default:
- return false;
- break;
- }
-
- protocolInfo << fourthfield.ToString();
+ {
+ cSchedulesLock lock;
+ const cSchedules* schedules = cSchedules::Schedules(lock);
+ const cSchedule* schedule = (schedules) ? schedules->GetSchedule(channelID) : NULL;
+ const cEvent* event = (schedule) ? schedule->GetPresentEvent() : NULL;
+
+ if(event){
+ stringstream title;
+ title << channel->Name() << ": " << event->Title();
+ metadata.SetProperty(cMetadata::Property(property::object::KEY_TITLE, title.str()));
+
+ boost::posix_time::ptime startTime, endTime;
+ startTime = boost::posix_time::from_time_t(event->StartTime());
+ endTime = boost::posix_time::from_time_t(event->EndTime());
+
+ metadata.SetProperty(cMetadata::Property(property::object::KEY_DATE, boost::gregorian::to_iso_extended_string(startTime.date())));
+ metadata.SetProperty(cMetadata::Property(property::object::KEY_SCHEDULED_START, boost::posix_time::to_iso_extended_string(startTime)));
+ metadata.SetProperty(cMetadata::Property(property::object::KEY_SCHEDULED_END, boost::posix_time::to_iso_extended_string(endTime)));
+ metadata.SetProperty(cMetadata::Property(property::object::KEY_DESCRIPTION, string(event->ShortText())));
+ metadata.SetProperty(cMetadata::Property(property::object::KEY_LONG_DESCRIPTION, string(event->Description())));
+ } else {
+ metadata.SetProperty(cMetadata::Property(property::object::KEY_TITLE, string(channel->Name())));
+ }
+
+ cMetadata::Resource resource;
+
+ DLNA4thField fourthfield;
+ switch (channel->Vtype()) {
+ case 0x02:
+ fourthfield = DLNA4thField("MPEG_TS_SD_EU_ISO", DLNA_OPERATION_NONE,
+ DLNA_PLAYSPEEDS_NONE, DLNA_CONVERSION_NONE,
+ DLNA_FLAG_STREAMING_TRANSFER |
+ DLNA_FLAG_SN_INCREASE |
+ DLNA_FLAG_VERSION_1_5 );
+ break;
+ case 0x1B:
+ fourthfield = DLNA4thField("AVC_TS_HD_EU_ISO", DLNA_OPERATION_NONE,
+ DLNA_PLAYSPEEDS_NONE, DLNA_CONVERSION_NONE,
+ DLNA_FLAG_STREAMING_TRANSFER |
+ DLNA_FLAG_SN_INCREASE |
+ DLNA_FLAG_VERSION_1_5 );
+ break;
+ default:
+ return false;
+ break;
+ }
+
+ resource.SetResourceUri(uri);
+ resource.SetProtocolInfo(ProtocolInfo("video/mpeg", fourthfield).ToString());
+
+ if(event){
+ boost::posix_time::time_duration duration = boost::posix_time::seconds(event->Duration());
+ resource.SetDuration(boost::posix_time::to_simple_string(duration));
+ }
+
+ metadata.AddResource(resource);
- resource.SetResourceUri(uri);
- resource.SetProtocolInfo(protocolInfo.str());
+ }
- metadata.AddResource(resource);
+ stringstream ss;
+ cMetadata::Resource thumbnail;
+ ss.str(string());
+ ss << "channelIcons/" << channel->Name() << ".jpg";
+
+ stringstream filename, uriStrm;
+ filename << cMediaServer::GetInstance()->GetWebserver().GetThumbnailDir() << ss.str();
+ uriStrm << "thumb://" << ss.str();
+
+ struct stat fileStat;
+
+ dsyslog("DVBProvider\tTry to get thumbnail for %s in %s", channel->Name(), filename.str().c_str());
+ if(stat(filename.str().c_str(), &fileStat) == 0){
+ thumbnail.SetResourceUri(uriStrm.str());
+ thumbnail.SetProtocolInfo(ProtocolInfo("image/jpeg", DLNA4thField("JPEG_TN")).ToString());
+ thumbnail.SetSize(fileStat.st_size);
+ metadata.AddResource(thumbnail);
+ } else {
+ dsyslog("DVBProvider\tFailed to stat %s", filename.str().c_str());
+ }
return true;
}
diff --git a/plugins/provider/vdrProvider/vdrProvider.cpp b/plugins/provider/vdrProvider/vdrProvider.cpp
index b98568f..4e765bf 100644
--- a/plugins/provider/vdrProvider/vdrProvider.cpp
+++ b/plugins/provider/vdrProvider/vdrProvider.cpp
@@ -9,12 +9,10 @@
#include <vdr/epg.h>
#include <vdr/channels.h>
#include <vdr/tools.h>
-#include <vdr/config.h>
#include <string>
#include <sstream>
+#include <algorithm>
#include <tools.h>
-#include <vdr/thread.h>
-#include <iostream>
#include <pwd.h>
#include <unistd.h>
@@ -108,18 +106,22 @@ public:
return true;
}
- virtual string GetHTTPUri(const string& uri, const string& currentIP){
+ virtual string GetHTTPUri(const string& uri, const string& currentIP, const string& pInfo){
if(!IsRootContainer(uri)) return string();
int port = 3000;
stringstream ss;
+ string protocolInfo = pInfo.substr(pInfo.find_last_of(':'));
+
+ std::replace(protocolInfo.begin(), protocolInfo.end(), ';','+');
+
ss << "http://" << currentIP << ":" << port
<< "/"
<< "EXT;"
<< "PROG=cat;"
- << "DLNA_contentFeatures=DLNA.ORG_PN=MPEG_TS_SD_EU_ISO+DLNA.ORG_OP=00+DLNA.ORG_CI=0+DLNA.ORG_FLAGS=ED100000000000000000000000000000"
+ << "DLNA_contentFeatures=" << protocolInfo
<< "/"
<< uri.substr(6);
diff --git a/server/webserver.cpp b/server/webserver.cpp
index f1b589b..2066c7f 100644
--- a/server/webserver.cpp
+++ b/server/webserver.cpp
@@ -66,6 +66,15 @@ bool cWebserver::Initialise(){
mApplication.mapUrl(ss1.str(), ss2.str(), "static@tntnet");
+ // Map static contents
+ ss1.clear(); ss1.str(string());
+ ss1 << "^/thumbs/([^.]+.jpg)$";
+
+ ss2.clear(); ss2.str(string());
+ ss2 << mWebserverRootDir << "/images/thumbs/$1";
+
+ mApplication.mapUrl(ss1.str(), ss2.str(), "static@tntnet");
+
mApplication.mapUrl("^/getStream", "resourceStreamer");
isyslog("UPnP\tUsing %s for static content delivery.", mWebserverRootDir.c_str());
@@ -127,6 +136,10 @@ const std::string cWebserver::GetStaticContentUrl() const {
return GetBaseUrl() + mStaticContentUrl;
}
+const std::string cWebserver::GetThumbnailDir() const {
+ return mWebserverRootDir + "images/thumbs/";
+}
+
cWebserver::cWSThread::cWSThread(cWebserver& webServer)
: mWebserver(webServer)
{