aboutsummaryrefslogtreecommitdiff
path: root/multimedia/vdr-plugin-upnp
diff options
context:
space:
mode:
authorJuergen Lock <nox@FreeBSD.org>2011-03-26 19:21:08 +0000
committerJuergen Lock <nox@FreeBSD.org>2011-03-26 19:21:08 +0000
commitccc7f468f6ba0dfb0dbcb8fea824e25c20eaaf2f (patch)
treed2e005286d99c83639a47a2bbd83da7d3c8610f1 /multimedia/vdr-plugin-upnp
parent32777e78a4d6211eb29c25c27c96fbdd6bc11c54 (diff)
downloadports-ccc7f468f6ba0dfb0dbcb8fea824e25c20eaaf2f.tar.gz
ports-ccc7f468f6ba0dfb0dbcb8fea824e25c20eaaf2f.zip
Notes
Diffstat (limited to 'multimedia/vdr-plugin-upnp')
-rw-r--r--multimedia/vdr-plugin-upnp/Makefile46
-rw-r--r--multimedia/vdr-plugin-upnp/distinfo2
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-Makefile31
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-badvideo23
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-freebsd83
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-fromgit23
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-iconv44
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-libupnp1.6.9183
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-livetv-channelname14
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-recplayer-seek33
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-size_t51
-rw-r--r--multimedia/vdr-plugin-upnp/files/patch-strncpy12
-rw-r--r--multimedia/vdr-plugin-upnp/pkg-descr11
-rw-r--r--multimedia/vdr-plugin-upnp/pkg-plist15
14 files changed, 571 insertions, 0 deletions
diff --git a/multimedia/vdr-plugin-upnp/Makefile b/multimedia/vdr-plugin-upnp/Makefile
new file mode 100644
index 000000000000..eb51ede35018
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/Makefile
@@ -0,0 +1,46 @@
+# New ports collection makefile for: vdr-plugin-upnp
+# Date created: Tue Nov 16 18:34:10 CET 2010
+# Whom: Juergen Lock <nox@freebsd.org>
+#
+# $FreeBSD$
+#
+
+PORTNAME= vdr-plugin-upnp
+PORTVERSION= 0.0.2a2
+PORTREVISION= 8
+CATEGORIES= multimedia
+MASTER_SITES= http://projects.vdr-developer.org/attachments/download/177/
+DISTNAME= ${PORTNAME:S/-plugin-/-/}-${DISTVERSIONPREFIX}${DISTVERSION:S/a/-alpha/}${DISTVERSIONSUFFIX}
+EXTRACT_SUFX= .tgz
+
+MAINTAINER= nox@FreeBSD.org
+COMMENT= Video Disk Recorder - UPnP/DLNA plugin (alpha!)
+
+LIB_DEPENDS+= avcodec.1:${PORTSDIR}/multimedia/ffmpeg \
+ boost_system:${PORTSDIR}/devel/boost-libs \
+ upnp.7:${PORTSDIR}/devel/upnp \
+ sqlite3.8:${PORTSDIR}/databases/sqlite3
+
+DIST_SUBDIR= vdr
+PATCH_STRIP= -p1
+HAVE_CONFIGURE= yes
+PORTDOCS= COPYING README
+MAKE_JOBS_SAFE= yes
+WRKSRC= ${WRKDIR}/${PLUGIN}-${DISTVERSION:S/a2//}
+
+.include "${.CURDIR}/../vdr/Makefile.plugins"
+
+post-patch: post-patch-plugin
+
+post-install: post-install-pluginlocales
+ @${MKDIR} ${PREFIX}/etc/vdr/plugins/${PLUGIN}/http/icons
+ @${INSTALL_DATA} ${WRKSRC}/http/icons/* ${PREFIX}/etc/vdr/plugins/${PLUGIN}/http/icons
+ @${MKDIR} ${PREFIX}/etc/vdr/plugins/${PLUGIN}/http/xml
+ @${INSTALL_DATA} ${WRKSRC}/http/xml/* ${PREFIX}/etc/vdr/plugins/${PLUGIN}/http/xml
+ @${INSTALL} -o ${VDR_USER} -g ${VDR_GROUP} -d /var/cache/vdr/${PLUGIN}
+.if !defined(NOPORTDOCS)
+ ${MKDIR} ${DOCSDIR}
+ (cd ${WRKSRC} && ${INSTALL_DATA} ${PORTDOCS} ${DOCSDIR})
+.endif
+
+.include <bsd.port.mk>
diff --git a/multimedia/vdr-plugin-upnp/distinfo b/multimedia/vdr-plugin-upnp/distinfo
new file mode 100644
index 000000000000..c764cbbf3319
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/distinfo
@@ -0,0 +1,2 @@
+SHA256 (vdr/vdr-upnp-0.0.2-alpha2.tgz) = 5c5acff28e287b6ac59bd14c93cee1ce932bb8e2d0f9191cbb5a1314e6976ab3
+SIZE (vdr/vdr-upnp-0.0.2-alpha2.tgz) = 152762
diff --git a/multimedia/vdr-plugin-upnp/files/patch-Makefile b/multimedia/vdr-plugin-upnp/files/patch-Makefile
new file mode 100644
index 000000000000..3576ae999cc7
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-Makefile
@@ -0,0 +1,31 @@
+--- a/Makefile
++++ b/Makefile
+@@ -42,6 +42,9 @@ PACKAGE = vdr-$(ARCHIVE)
+
+ ### Includes and Defines (add further entries here):
+
++ifdef FREEBSD
++LIBS += -L${LOCALBASE}/lib
++endif
+ LIBS += -lupnp -lixml -lsqlite3 -lavformat -lavcodec
+
+ INCLUDES += -I$(VDRDIR)/include -I/usr/include -Iinc \
+@@ -150,7 +153,11 @@ i18n: $(I18Nmsgs) $(I18Npot)
+
+ libvdr-$(PLUGIN).so: $(OBJS)
+ $(CXX) $(CXXFLAGS) $(LIBS) -shared $(OBJS) -o $@ -lc
++ifdef FREEBSD
++ @cp -f $@ $(LIBDIR)/$@.$(APIVERSION)
++else
+ @cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
++endif
+
+ dist: clean
+ @-rm -rf $(TMPDIR)/$(ARCHIVE)
+@@ -162,3 +169,6 @@ dist: clean
+
+ clean:
+ @-rm -f $(OBJS) $(DEPFILE) *.so *.tgz core* *~ $(PODIR)/*.mo $(PODIR)/*.pot
++
++install:
++ ${INSTALL_PROGRAM} $(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION) $(PREFIX)/lib/vdr/libvdr-$(PLUGIN).so.$(APIVERSION)
diff --git a/multimedia/vdr-plugin-upnp/files/patch-badvideo b/multimedia/vdr-plugin-upnp/files/patch-badvideo
new file mode 100644
index 000000000000..7d45379f8812
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-badvideo
@@ -0,0 +1,23 @@
+--- a/dlna/avdetector.cpp
++++ b/dlna/avdetector.cpp
+@@ -262,7 +262,8 @@ int cAudioVideoDetector::detectDLNAProfi
+ }
+
+ AVCodecContext* cCodecToolKit::getFirstCodecContext(AVFormatContext* FormatCtx, CodecType Type){
+- return cCodecToolKit::getFirstStream(FormatCtx, Type)->codec;
++ AVStream* ret = cCodecToolKit::getFirstStream(FormatCtx, Type);
++ return ret ? ret->codec : NULL;
+ }
+
+ AVStream* cCodecToolKit::getFirstStream(AVFormatContext* FormatCtx, CodecType Type){
+--- a/dlna/profiles/mpeg2.cpp
++++ b/dlna/profiles/mpeg2.cpp
+@@ -159,6 +159,8 @@ VideoPortionProfile cMPEG2Profiler::prob
+ AVCodecContext* VideoCodec = cCodecToolKit::getFirstCodecContext(FormatCtx, CODEC_TYPE_VIDEO);
+ AVStream* VideoStream = cCodecToolKit::getFirstStream(FormatCtx, CODEC_TYPE_VIDEO);
+
++ if (VideoCodec == NULL || VideoStream == NULL)
++ return DLNA_VPP_UNKNOWN;
+ MESSAGE(VERBOSE_METADATA, "Codec-ID: %d", VideoCodec->codec_id);
+ MESSAGE(VERBOSE_METADATA, "Codec-Name: %s", VideoCodec->codec_name);
+ MESSAGE(VERBOSE_METADATA, "Codec Bitrate: %d", VideoCodec->bit_rate);
diff --git a/multimedia/vdr-plugin-upnp/files/patch-freebsd b/multimedia/vdr-plugin-upnp/files/patch-freebsd
new file mode 100644
index 000000000000..24665180e79b
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-freebsd
@@ -0,0 +1,83 @@
+--- a/misc/util.cpp
++++ b/misc/util.cpp
+@@ -12,6 +12,14 @@
+ #include <string.h>
+ #include <string>
+ #include <sys/ioctl.h>
++#ifdef __FreeBSD__
++#include <sys/socket.h>
++#include <ifaddrs.h>
++#include <net/if.h>
++#include <net/if_dl.h>
++#include <net/if_types.h>
++#include <net/ethernet.h>
++#endif
+ #include <net/if.h>
+ #include <upnp/ixml.h>
+ #include <arpa/inet.h>
+@@ -74,6 +82,7 @@ char* substr(const char* str, unsigned i
+ }
+
+ const char* getMACFromInterface(const char* Interface) {
++#ifndef __FreeBSD__
+ int fd;
+ struct ifreq ifr;
+
+@@ -95,6 +104,31 @@ const char* getMACFromInterface(const ch
+ (unsigned char)ifr.ifr_hwaddr.sa_data[3],
+ (unsigned char)ifr.ifr_hwaddr.sa_data[4],
+ (unsigned char)ifr.ifr_hwaddr.sa_data[5]);
++#else
++ struct ifaddrs *ifa, *ifp = NULL;
++ char *ret = new char[18];
++ strcpy(ret, "00:00:00:00:00:00");
++
++ if (!Interface || getifaddrs(&ifp) < 0)
++ return ret;
++
++ for (ifa = ifp; ifa != NULL; ifa = ifa->ifa_next) {
++ if (strcmp(ifa->ifa_name, Interface))
++ continue;
++
++ if (ifa->ifa_addr->sa_family == AF_LINK) {
++ struct sockaddr_dl *sdl =
++ (struct sockaddr_dl *)ifa->ifa_addr;
++
++ if (sdl->sdl_type == IFT_ETHER &&
++ sdl->sdl_alen == ETHER_ADDR_LEN)
++ snprintf(ret, 18, "%s",
++ ether_ntoa((struct ether_addr *)LLADDR(sdl)));
++ break;
++ }
++ }
++ freeifaddrs(ifp);
++#endif
+
+ return ret;
+ }
+--- a/server/server.cpp
++++ b/server/server.cpp
+@@ -8,6 +8,9 @@
+ #include <vdr/plugin.h>
+ #include <stdlib.h>
+ #include <string.h>
++#ifdef __FreeBSD__
++#include <sys/socket.h>
++#endif
+ #include <arpa/inet.h>
+ #include <upnp/upnp.h>
+ #include "server.h"
+--- a/database/database.cpp
++++ b/database/database.cpp
+@@ -161,7 +161,11 @@ bool cRow::fetchColumn(char** Column, ch
+
+ int cSQLiteDatabase::initialize(){
+ int ret;
++#ifdef __FreeBSD__
++ const char* dbdir = (cUPnPConfig::get()->mDatabaseFolder) ? cUPnPConfig::get()->mDatabaseFolder : "/var/cache/vdr/upnp";
++#else
+ const char* dbdir = (cUPnPConfig::get()->mDatabaseFolder) ? cUPnPConfig::get()->mDatabaseFolder : cPluginUpnp::getConfigDirectory();
++#endif
+ cString File = cString::sprintf("%s/%s", dbdir, SQLITE_DB_FILE);
+ if((ret = sqlite3_open(File, &this->mDatabase))){
+ ERROR("Unable to open database file %s (Error code: %d)!", *File, ret);
diff --git a/multimedia/vdr-plugin-upnp/files/patch-fromgit b/multimedia/vdr-plugin-upnp/files/patch-fromgit
new file mode 100644
index 000000000000..5d6a61e3fc7e
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-fromgit
@@ -0,0 +1,23 @@
+--- a/database/metadata.cpp
++++ b/database/metadata.cpp
+@@ -461,11 +471,20 @@ void cMediaDatabase::Action(){
+ time_t LastEPGUpdate = 0;
+ while(this->Running()){
+
++#ifndef WITHOUT_TV
+ if(cSchedules::Modified() >= LastEPGUpdate){
+ MESSAGE(VERBOSE_EPG_UPDATES, "Schedule changed. Updating...");
+ updateChannelEPG();
+ LastEPGUpdate = cSchedules::Modified();
+ }
++#endif
++#ifndef WITHOUT_RECORDS
++ int NotUsed;
++ if(Recordings.StateChanged(NotUsed)){
++ MESSAGE(VERBOSE_EPG_UPDATES, "Recordings changed. Updating...");
++ loadRecordings();
++ }
++#endif
+
+ cCondWait::SleepMs(60 * 1000); // sleep a minute
+ }
diff --git a/multimedia/vdr-plugin-upnp/files/patch-iconv b/multimedia/vdr-plugin-upnp/files/patch-iconv
new file mode 100644
index 000000000000..1a13d0b75ede
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-iconv
@@ -0,0 +1,44 @@
+--- a/inc/upnp/contentdirectory.h
++++ b/inc/upnp/contentdirectory.h
+@@ -39,6 +39,7 @@ public:
+ virtual void setError(Upnp_Action_Request* Request, int Error);
+ private:
+ cMediaDatabase* mMediaDatabase;
++ cCharSetConv* mconv;
+ void Action();
+ int getSearchCapabilities(Upnp_Action_Request* Request);
+ int getSortCapabilities(Upnp_Action_Request* Request);
+--- a/upnp/contentdirectory.cpp
++++ b/upnp/contentdirectory.cpp
+@@ -14,9 +14,13 @@
+ cContentDirectory::cContentDirectory(UpnpDevice_Handle DeviceHandle, cMediaDatabase* MediaDatabase)
+ : cUpnpService(DeviceHandle) {
+ this->mMediaDatabase = MediaDatabase;
++ this->mconv = new cCharSetConv((cCharSetConv::SystemCharacterTable() ?
++ cCharSetConv::SystemCharacterTable() : "UTF-8"), "UTF-8");
+ }
+
+-cContentDirectory::~cContentDirectory() {}
++cContentDirectory::~cContentDirectory() {
++ delete this->mconv;
++}
+
+ int cContentDirectory::subscribe(Upnp_Subscription_Request* Request){
+ IXML_Document* PropertySet = NULL;
+@@ -149,8 +153,15 @@ int cContentDirectory::browse(Upnp_Actio
+ return Request->ErrCode;
+ }
+
++ const char *utf8Result = this->mconv->Convert(ResultSet->mResult);
++ if(!utf8Result){
++ ERROR("Converting XML data failed");
++ this->setError(Request, UPNP_SOAP_E_ACTION_FAILED);
++ return Request->ErrCode;
++ }
++
+ char* escapedResult = NULL;
+- escapeXMLCharacters(ResultSet->mResult, &escapedResult);
++ escapeXMLCharacters(utf8Result, &escapedResult);
+
+ if(!escapedResult){
+ ERROR("Escaping XML data failed");
diff --git a/multimedia/vdr-plugin-upnp/files/patch-libupnp1.6.9 b/multimedia/vdr-plugin-upnp/files/patch-libupnp1.6.9
new file mode 100644
index 000000000000..1508e075b713
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-libupnp1.6.9
@@ -0,0 +1,183 @@
+--- a/database/object.cpp
++++ b/database/object.cpp
+@@ -7,6 +7,7 @@
+
+ #include <string.h>
+ #include <stdio.h>
++#include <upnp/upnp.h>
+ #include <upnp/upnptools.h>
+ #include <vdr/recording.h>
+ #include <vector>
+--- a/inc/util.h
++++ b/inc/util.h
+@@ -20,6 +20,12 @@ extern "C" {
+
+ #include <libavformat/avformat.h>
+ #include <libavcodec/avcodec.h>
++
++#ifdef __FreeBSD__
++#define off64_t off_t
++#endif
++#include <netinet/in.h>
++
+ /**
+ * Compares two strings
+ *
+@@ -147,5 +153,7 @@ public:
+ virtual eOSState ProcessKey(eKeys Key);
+ };
+
++const char *IPAddrP(struct sockaddr_storage &IPAddr, char *buf, size_t buflen);
++
+ #endif /* _UTIL_H */
+
+--- a/inc/webserver.h
++++ b/inc/webserver.h
+@@ -22,7 +22,9 @@ class cUPnPWebServer {
+ friend class cUPnPServer;
+ private:
+ static cUPnPWebServer *mInstance;
++#ifdef OLDUPNPAPI
+ static UpnpVirtualDirCallbacks mVirtualDirCallbacks;
++#endif
+ const char* mRootdir;
+ cUPnPWebServer(const char* root = "/");
+ protected:
+--- a/misc/util.cpp
++++ b/misc/util.cpp
+@@ -532,4 +567,16 @@ IXML_Element* ixmlAddFilteredProperty(cS
+ return ixmlAddProperty(document, node, upnpproperty, value);
+ else
+ return NULL;
+-}
+\ No newline at end of file
++}
++
++const char *IPAddrP(struct sockaddr_storage &IPAddr, char *buf, size_t buflen){
++ *buf = '\0';
++ if (IPAddr.ss_family == AF_INET) {
++ inet_ntop(AF_INET, (void *)&((struct sockaddr_in *)&IPAddr)->sin_addr, buf, buflen);
++ return buf;
++ } else if (IPAddr.ss_family == AF_INET6) {
++ inet_ntop(AF_INET6, (void *)&((struct sockaddr_in6 *)&IPAddr)->sin6_addr, buf, buflen);
++ return buf;
++ }
++ return "??";
++}
+--- a/server/webserver.cpp
++++ b/server/webserver.cpp
+@@ -100,6 +100,7 @@ cUPnPWebServer::~cUPnPWebServer(){}
+
+ cUPnPWebServer* cUPnPWebServer::mInstance = NULL;
+
++#ifdef OLDUPNPAPI
+ UpnpVirtualDirCallbacks cUPnPWebServer::mVirtualDirCallbacks = {
+ cUPnPWebServer::getInfo,
+ cUPnPWebServer::open,
+@@ -108,6 +109,7 @@ UpnpVirtualDirCallbacks cUPnPWebServer::
+ cUPnPWebServer::seek,
+ cUPnPWebServer::close
+ };
++#endif
+
+ bool cUPnPWebServer::init(){
+ MESSAGE(VERBOSE_WEBSERVER, "Initialize callbacks for virtual directories.");
+@@ -118,7 +120,16 @@ bool cUPnPWebServer::init(){
+ }
+ MESSAGE(VERBOSE_WEBSERVER, "Setting up callbacks");
+
++#ifdef OLDUPNPAPI
+ if(UpnpSetVirtualDirCallbacks(&cUPnPWebServer::mVirtualDirCallbacks) == UPNP_E_INVALID_ARGUMENT){
++#else
++ if(UpnpVirtualDir_set_GetInfoCallback(&cUPnPWebServer::getInfo) != UPNP_E_SUCCESS ||
++ UpnpVirtualDir_set_OpenCallback(&cUPnPWebServer::open) != UPNP_E_SUCCESS ||
++ UpnpVirtualDir_set_ReadCallback(&cUPnPWebServer::read) != UPNP_E_SUCCESS ||
++ UpnpVirtualDir_set_WriteCallback(&cUPnPWebServer::write) != UPNP_E_SUCCESS ||
++ UpnpVirtualDir_set_SeekCallback(&cUPnPWebServer::seek) != UPNP_E_SUCCESS ||
++ UpnpVirtualDir_set_CloseCallback(&cUPnPWebServer::close) != UPNP_E_SUCCESS){
++#endif
+ ERROR("The virtual directory callbacks are invalid.");
+ return false;
+ }
+--- a/upnp/connectionmanager.cpp
++++ b/upnp/connectionmanager.cpp
+@@ -7,6 +7,8 @@
+
+ #include <string.h>
+ #include <upnp/ixml.h>
++/* XXX */
++#define UPNP_HAVE_TOOLS 1
+ #include <upnp/upnptools.h>
+ #include <vdr/tools.h>
+ #include "upnp/connectionmanager.h"
+@@ -70,7 +72,8 @@ int cConnectionManager::execute(Upnp_Act
+ }
+
+ int cConnectionManager::getProtocolInfo(Upnp_Action_Request* Request){
+- MESSAGE(VERBOSE_CMS, "Protocol info requested by %s.", inet_ntoa(Request->CtrlPtIPAddr));
++ char buf[64];
++ MESSAGE(VERBOSE_CMS, "Protocol info requested by %s.", IPAddrP(Request->CtrlPtIPAddr, buf, sizeof buf));
+ cString Result = cString::sprintf(
+ "<u:%sResponse xmlns:u=\"%s\"> \
+ <Source>%s</Source> \
+@@ -87,7 +90,8 @@ int cConnectionManager::getProtocolInfo(
+ }
+
+ int cConnectionManager::getCurrentConnectionIDs(Upnp_Action_Request* Request){
+- MESSAGE(VERBOSE_CMS, "Current connection IDs requested by %s.", inet_ntoa(Request->CtrlPtIPAddr));
++ char buf[64];
++ MESSAGE(VERBOSE_CMS, "Current connection IDs requested by %s.", IPAddrP(Request->CtrlPtIPAddr, buf, sizeof buf));
+ cString Result;
+ const char* IDs = this->getConnectionIDsCVS();
+ if(!IDs){
+@@ -109,7 +113,8 @@ int cConnectionManager::getCurrentConnec
+ }
+
+ int cConnectionManager::getCurrentConnectionInfo(Upnp_Action_Request* Request){
+- MESSAGE(VERBOSE_CMS, "Current connection info requested by %s.", inet_ntoa(Request->CtrlPtIPAddr));
++ char buf[64];
++ MESSAGE(VERBOSE_CMS, "Current connection info requested by %s.", IPAddrP(Request->CtrlPtIPAddr, buf, sizeof buf));
+ int ConnectionID;
+
+ if(this->parseIntegerValue(Request->ActionRequest, "ConnectionID", &ConnectionID) != 0){
+@@ -156,7 +161,8 @@ int cConnectionManager::getCurrentConnec
+ }
+
+ int cConnectionManager::prepareForConnection(Upnp_Action_Request* Request){
+- MESSAGE(VERBOSE_CMS, "Request for a new connection by %s.", inet_ntoa(Request->CtrlPtIPAddr));
++ char buf[64];
++ MESSAGE(VERBOSE_CMS, "Request for a new connection by %s.", IPAddrP(Request->CtrlPtIPAddr, buf, sizeof buf));
+ //char* Result = NULL;
+ char* RemoteProtocolInfo = NULL;
+ char* PeerConnectionManager = NULL;
+@@ -198,7 +204,8 @@ int cConnectionManager::prepareForConnec
+ }
+
+ int cConnectionManager::connectionComplete(Upnp_Action_Request* Request){
+- MESSAGE(VERBOSE_CMS, "Request for closing an open connection by %s.", inet_ntoa(Request->CtrlPtIPAddr));
++ char buf[64];
++ MESSAGE(VERBOSE_CMS, "Request for closing an open connection by %s.", IPAddrP(Request->CtrlPtIPAddr, buf, sizeof buf));
+ //char* Result = NULL;
+ int ConnectionID;
+
+--- a/upnp/contentdirectory.cpp
++++ b/upnp/contentdirectory.cpp
+@@ -6,6 +6,8 @@
+ */
+
+ #include <upnp/ixml.h>
++/* XXX */
++#define UPNP_HAVE_TOOLS 1
+ #include <upnp/upnptools.h>
+ #include "upnp/contentdirectory.h"
+ #include "../common.h"
+@@ -84,7 +90,8 @@ int cContentDirectory::execute(Upnp_Acti
+
+
+ int cContentDirectory::browse(Upnp_Action_Request* Request){
+- MESSAGE(VERBOSE_CDS, "Browse requested by %s.", inet_ntoa(Request->CtrlPtIPAddr));
++ char buf[64];
++ MESSAGE(VERBOSE_CDS, "Browse requested by %s.", IPAddrP(Request->CtrlPtIPAddr, buf, sizeof buf));
+
+ char* ObjectID = NULL;
+ if(this->parseStringValue(Request->ActionRequest, "ObjectID", &ObjectID)){
diff --git a/multimedia/vdr-plugin-upnp/files/patch-livetv-channelname b/multimedia/vdr-plugin-upnp/files/patch-livetv-channelname
new file mode 100644
index 000000000000..983b480bd0c1
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-livetv-channelname
@@ -0,0 +1,14 @@
+--- a/database/metadata.cpp
++++ b/database/metadata.cpp
+@@ -364,7 +364,11 @@ void cMediaDatabase::updateChannelEPG(){
+ MESSAGE(VERBOSE_EPG_UPDATES, "Updating details");
+
+ if(Event){
++#if 1 // XXX easier to find the channels at least on xbmc
++ ChannelItem->setTitle(Channel->Name());
++#else
+ ChannelItem->setTitle(Event->Title()?Event->Title():Channel->Name());
++#endif
+ ChannelItem->setLongDescription(Event->Description());
+ ChannelItem->setDescription(Event->ShortText());
+ }
diff --git a/multimedia/vdr-plugin-upnp/files/patch-recplayer-seek b/multimedia/vdr-plugin-upnp/files/patch-recplayer-seek
new file mode 100644
index 000000000000..39fa165775a0
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-recplayer-seek
@@ -0,0 +1,33 @@
+--- a/receiver/recplayer.cpp
++++ b/receiver/recplayer.cpp
+@@ -97,13 +97,14 @@ int cRecordingPlayer::seek(off_t offset,
+ }
+ // finally, we can seek
+ // TODO: binary search
+- for(index = 1; this->mLastOffsets[index]; index++){
++ for(index = 1; index <= this->mLastFileNumber; index++){
+ if(this->mLastOffsets[index-1] <= offset && offset <= this->mLastOffsets[index]){
+ relativeOffset = offset - this->mLastOffsets[index-1];
+ break;
+ }
+ }
+- if(!(this->mCurrentFile = this->mRecordingFile->SetOffset(index, relativeOffset))){
++ if(index > this->mLastFileNumber ||
++ !(this->mCurrentFile = this->mRecordingFile->SetOffset(index, relativeOffset))){
+ // seeking failed!!! should never happen.
+ this->mCurrentFile = this->mRecordingFile->SetOffset(1);
+ return -1;
+@@ -115,9 +116,12 @@ int cRecordingPlayer::seek(off_t offset,
+ void cRecordingPlayer::scanLastOffsets(){
+ // rewind
+ this->mCurrentFile = this->mRecordingFile->SetOffset(1);
+- for(int i = 1; (this->mCurrentFile = this->mRecordingFile->NextFile()); i++){
++ this->mLastOffsets[0] = 0;
++ this->mLastFileNumber = 1;
++ for(int i = 1; this->mCurrentFile; i++){
+ this->mLastOffsets[i] = this->mLastOffsets[i-1] + this->mCurrentFile->Seek(0, SEEK_END);
+ this->mLastFileNumber = this->mRecordingFile->Number();
++ this->mCurrentFile = this->mRecordingFile->NextFile();
+ }
+ }
+
diff --git a/multimedia/vdr-plugin-upnp/files/patch-size_t b/multimedia/vdr-plugin-upnp/files/patch-size_t
new file mode 100644
index 000000000000..91985d102118
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-size_t
@@ -0,0 +1,51 @@
+--- a/database/object.cpp
++++ b/database/object.cpp
+@@ -1023,7 +1024,7 @@ void cUPnPObjectFactory::registerMediato
+ }
+ MESSAGE(VERBOSE_SDK, "Registering mediator for class '%s'", UPnPClass);
+ this->mMediators[UPnPClass] = Mediator;
+- MESSAGE(VERBOSE_SDK, "Now %d mediators registered", this->mMediators.size());
++ MESSAGE(VERBOSE_SDK, "Now %ld mediators registered", (long)this->mMediators.size());
+ return;
+ }
+
+@@ -1040,7 +1041,7 @@ void cUPnPObjectFactory::unregisterMedia
+ MESSAGE(VERBOSE_SDK, "Unregistering mediator for class '%s'", UPnPClass);
+ this->mMediators.erase(MediatorIterator);
+ if(freeMediator) delete MediatorIterator->second;
+- MESSAGE(VERBOSE_SDK, "Now %d mediators registered", this->mMediators.size());
++ MESSAGE(VERBOSE_SDK, "Now %ld mediators registered", (long)this->mMediators.size());
+ return;
+ }
+
+@@ -1067,7 +1068,7 @@ cMediatorInterface* cUPnPObjectFactory::
+
+ cMediatorInterface* cUPnPObjectFactory::findMediatorByClass(const char* Class){
+ if(!Class){ ERROR("No class specified"); return NULL; }
+- MESSAGE(VERBOSE_SQL, "Searching for mediator '%s' in %d mediators", Class, this->mMediators.size());
++ MESSAGE(VERBOSE_SQL, "Searching for mediator '%s' in %ld mediators", Class, (long)this->mMediators.size());
+ tMediatorMap::iterator MediatorIterator = this->mMediators.find(Class);
+ if(MediatorIterator==this->mMediators.end()){
+ ERROR("No matching mediator for class '%s'",Class);
+--- a/receiver/recplayer.cpp
++++ b/receiver/recplayer.cpp
+@@ -58,7 +58,7 @@ int cRecordingPlayer::read(char* buf, si
+ ERROR("Current part of record is not open");
+ return -1;
+ }
+- MESSAGE(VERBOSE_RECORDS, "Reading %d from record", buflen);
++ MESSAGE(VERBOSE_RECORDS, "Reading %ld from record", (long)buflen);
+ int bytesread = 0;
+ while((bytesread = this->mCurrentFile->Read(buf, buflen)) == 0){ // EOF, try next file
+ if(!(this->mCurrentFile = this->mRecordingFile->NextFile())){
+--- a/server/server.cpp
++++ b/server/server.cpp
+@@ -278,7 +281,7 @@ bool cUPnPServer::autoDetectSettings(voi
+ char** Ifaces = getNetworkInterfaces(&count);
+ int i=0;
+ bool ret = false;
+- MESSAGE(VERBOSE_CUSTOM_OUTPUT, "AUTODETECT: Found %d possible interfaces.", sizeof(Ifaces));
++ MESSAGE(VERBOSE_CUSTOM_OUTPUT, "AUTODETECT: Found %ld possible interfaces.", (long)sizeof(Ifaces));
+ while(Ifaces[i]){
+ if(strcmp(Ifaces[i],"lo")!=0){
+ // true || false == true
diff --git a/multimedia/vdr-plugin-upnp/files/patch-strncpy b/multimedia/vdr-plugin-upnp/files/patch-strncpy
new file mode 100644
index 000000000000..9a7ff1e55833
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/files/patch-strncpy
@@ -0,0 +1,12 @@
+--- a/misc/util.cpp
++++ b/misc/util.cpp
+@@ -485,7 +519,8 @@ IXML_Element* ixmlAddProperty(IXML_Docum
+ char tvalue[UPNP_MAX_METADATA_LENGTH];
+ // trim the value to max metadata size
+ if(value){
+- strncpy(tvalue, value, UPNP_MAX_METADATA_LENGTH);
++ strncpy(tvalue, value, UPNP_MAX_METADATA_LENGTH - 1);
++ tvalue[UPNP_MAX_METADATA_LENGTH - 1] = '\0';
+ }
+
+ const char* attribute = att(upnpproperty);
diff --git a/multimedia/vdr-plugin-upnp/pkg-descr b/multimedia/vdr-plugin-upnp/pkg-descr
new file mode 100644
index 000000000000..2903dccfcbf6
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/pkg-descr
@@ -0,0 +1,11 @@
+http://www.vdr-wiki.de/wiki/index.php/Upnp-plugin
+
+UPnP/DLNA Plugin for Video Disk Recorder
+
+This Plugins extends the VDR with the possibility to act as an UPnP/DLNA Media
+Server (DMS). It will serve VDR's contents in the network to any UPnP-AV and
+DLNA capable devices.
+
+This still is an alpha version!
+
+WWW: http://upnp.vdr-developer.org/
diff --git a/multimedia/vdr-plugin-upnp/pkg-plist b/multimedia/vdr-plugin-upnp/pkg-plist
new file mode 100644
index 000000000000..4fd0c3c812f3
--- /dev/null
+++ b/multimedia/vdr-plugin-upnp/pkg-plist
@@ -0,0 +1,15 @@
+lib/vdr/libvdr-upnp.so.1.7.17
+etc/vdr/plugins/upnp/http/icons/upnpIconLrg.jpeg
+etc/vdr/plugins/upnp/http/icons/upnpIconLrg.png
+etc/vdr/plugins/upnp/http/icons/upnpIconSm.jpeg
+etc/vdr/plugins/upnp/http/icons/upnpIconSm.png
+etc/vdr/plugins/upnp/http/xml/cds_scpd.xml
+etc/vdr/plugins/upnp/http/xml/cms_scpd.xml
+@exec /usr/bin/install -o %%VDR_USER%% -g %%VDR_GROUP%% -d /var/cache/vdr/upnp
+@dirrm etc/vdr/plugins/upnp/http/xml
+@dirrm etc/vdr/plugins/upnp/http/icons
+@dirrm etc/vdr/plugins/upnp/http
+@dirrmtry etc/vdr/plugins/upnp
+%%NLS%%share/locale/de-DE/LC_MESSAGES/vdr-upnp.mo
+%%NLS%%@dirrmtry share/locale/de-DE/LC_MESSAGES
+%%NLS%%@dirrmtry share/locale/de-DE