summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--common/tools.cpp326
-rw-r--r--include/media/mediaManager.h58
-rw-r--r--include/plugin.h20
-rw-r--r--include/pluginManager.h35
-rw-r--r--include/tools.h129
-rw-r--r--media/mediaManager.cpp11
-rw-r--r--media/pluginManager.cpp66
-rw-r--r--plugins/provider/vdrProvider/Makefile6
-rw-r--r--plugins/provider/vdrProvider/vdrProvider.cpp35
-rw-r--r--tests/Makefile7
11 files changed, 148 insertions, 550 deletions
diff --git a/Makefile b/Makefile
index d77e982..cbae582 100644
--- a/Makefile
+++ b/Makefile
@@ -72,12 +72,13 @@ OBJS = $(PLUGIN).o \
common/tools.o \
common/parser.o \
common/setup.o \
+ common/ixml.o \
media/profile.o \
media/mediaManager.o \
media/pluginManager.o \
$(TNTOBJ)
-LIBS += -lupnp -lcxxtools -ltntnet -ltntdb
+LIBS += -lupnp -lcxxtools -ltntnet -ltntdb -ldl
### The main target:
@@ -128,7 +129,7 @@ i18n: $(I18Nmsgs) $(I18Npot)
### Targets:
libvdr-$(PLUGIN).so: $(OBJS)
- $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -rdynamic -shared $(OBJS) $(LIBS) -o $@
@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
dist: $(I18Npo) clean
diff --git a/common/tools.cpp b/common/tools.cpp
index 61220c6..6f02d2a 100644
--- a/common/tools.cpp
+++ b/common/tools.cpp
@@ -17,15 +17,6 @@
using namespace std;
-char* substr(const char* str, unsigned int offset, unsigned int length){
- if(offset > strlen(str)) return NULL;
- if(length > strlen(str+offset)) length = strlen(str+offset);
- char* substring = (char*)malloc(sizeof(substring)*length+1);
- strncpy(substring, str+offset, length);
- substring[length] = '\0';
- return substring;
-}
-
namespace upnp {
namespace tools {
@@ -154,322 +145,5 @@ void StringExplode(string str, string separator, StringVector& results) {
} // namespace tools
-namespace ixml {
-
-void XmlEscapeSpecialChars(string& doc){
- std::string buffer;
-
- buffer.reserve(doc.size()*1.1);
- for(unsigned int i = 0; i < doc.size(); i++){
- switch((long)doc[i]){
- case L'€': buffer.append("&euro;"); break;
- case L'"': buffer.append("&quot;"); break;
- case L'&': buffer.append("&amp;"); break;
- case L'<': buffer.append("&lt;"); break;
- case L'>': buffer.append("&gt;"); break;
- case L'¡': buffer.append("&iexcl;"); break;
- case L'¢': buffer.append("&cent;"); break;
- case L'£': buffer.append("&pound;"); break;
- case L'¤': buffer.append("&curren;"); break;
- case L'¥': buffer.append("&yen;"); break;
- case L'¦': buffer.append("&brvbar;"); break;
- case L'§': buffer.append("&sect;"); break;
- case L'¨': buffer.append("&uml;"); break;
- case L'©': buffer.append("&copy;"); break;
- case L'ª': buffer.append("&ordf;"); break;
- case L'¬': buffer.append("&not;"); break;
- case L'­': buffer.append("&shy;"); break;
- case L'®': buffer.append("&reg;"); break;
- case L'¯': buffer.append("&macr;"); break;
- case L'°': buffer.append("&deg;"); break;
- case L'±': buffer.append("&plusmn;"); break;
- case L'²': buffer.append("&sup2;"); break;
- case L'³': buffer.append("&sup3;"); break;
- case L'´': buffer.append("&acute;"); break;
- case L'µ': buffer.append("&micro;"); break;
- case L'¶': buffer.append("&para;"); break;
- case L'·': buffer.append("&middot;"); break;
- case L'¸': buffer.append("&cedil;"); break;
- case L'¹': buffer.append("&sup1;"); break;
- case L'º': buffer.append("&ordm;"); break;
- case L'»': buffer.append("&raquo;"); break;
- case L'«': buffer.append("&laquo;"); break;
- case L'¼': buffer.append("&frac14;"); break;
- case L'½': buffer.append("&frac12;"); break;
- case L'¾': buffer.append("&frac34;"); break;
- case L'¿': buffer.append("&iquest;"); break;
- case L'À': buffer.append("&Agrave;"); break;
- case L'Á': buffer.append("&Aacute;"); break;
- case L'Â': buffer.append("&Acirc;"); break;
- case L'Ã': buffer.append("&Atilde;"); break;
- case L'Ä': buffer.append("&Auml;"); break;
- case L'Å': buffer.append("&Aring;"); break;
- case L'Æ': buffer.append("&AElig;"); break;
- case L'Ç': buffer.append("&Ccedil;"); break;
- case L'È': buffer.append("&Egrave;"); break;
- case L'É': buffer.append("&Eacute;"); break;
- case L'Ê': buffer.append("&Ecirc;"); break;
- case L'Ë': buffer.append("&Euml;"); break;
- case L'Ì': buffer.append("&Igrave;"); break;
- case L'Í': buffer.append("&Iacute;"); break;
- case L'Î': buffer.append("&Icirc;"); break;
- case L'Ï': buffer.append("&Iuml;"); break;
- case L'Ð': buffer.append("&ETH;"); break;
- case L'Ñ': buffer.append("&Ntilde;"); break;
- case L'Ò': buffer.append("&Ograve;"); break;
- case L'Ó': buffer.append("&Oacute;"); break;
- case L'Ô': buffer.append("&Ocirc;"); break;
- case L'Õ': buffer.append("&Otilde;"); break;
- case L'Ö': buffer.append("&Ouml;"); break;
- case L'×': buffer.append("&times;"); break;
- case L'Ø': buffer.append("&Oslash;"); break;
- case L'Ù': buffer.append("&Ugrave;"); break;
- case L'Ú': buffer.append("&Uacute;"); break;
- case L'Û': buffer.append("&Ucirc;"); break;
- case L'Ü': buffer.append("&Uuml;"); break;
- case L'Ý': buffer.append("&Yacute;"); break;
- case L'Þ': buffer.append("&THORN;"); break;
- case L'ß': buffer.append("&szlig;"); break;
- case L'à': buffer.append("&agrave;"); break;
- case L'á': buffer.append("&aacute;"); break;
- case L'â': buffer.append("&acirc;"); break;
- case L'ã': buffer.append("&atilde;"); break;
- case L'ä': buffer.append("&auml;"); break;
- case L'å': buffer.append("&aring;"); break;
- case L'æ': buffer.append("&aelig;"); break;
- case L'ç': buffer.append("&ccedil;"); break;
- case L'è': buffer.append("&egrave;"); break;
- case L'é': buffer.append("&eacute;"); break;
- case L'ê': buffer.append("&ecirc;"); break;
- case L'ë': buffer.append("&euml;"); break;
- case L'ì': buffer.append("&igrave;"); break;
- case L'í': buffer.append("&iacute;"); break;
- case L'î': buffer.append("&icirc;"); break;
- case L'ï': buffer.append("&iuml;"); break;
- case L'ð': buffer.append("&eth;"); break;
- case L'ñ': buffer.append("&ntilde;"); break;
- case L'ò': buffer.append("&ograve;"); break;
- case L'ó': buffer.append("&oacute;"); break;
- case L'ô': buffer.append("&ocirc;"); break;
- case L'õ': buffer.append("&otilde;"); break;
- case L'ö': buffer.append("&ouml;"); break;
- case L'÷': buffer.append("&divide;"); break;
- case L'ø': buffer.append("&oslash;"); break;
- case L'ù': buffer.append("&ugrave;"); break;
- case L'ú': buffer.append("&uacute;"); break;
- case L'û': buffer.append("&ucirc;"); break;
- case L'ü': buffer.append("&uuml;"); break;
- case L'ý': buffer.append("&yacute;"); break;
- case L'þ': buffer.append("&thorn;"); break;
- default: buffer.append(1, doc[i]); break;
- }
- }
-
- doc.swap(buffer);
-}
-
-//Function copied from Intel SDK
-///////////////////////////////////////////////////////////////////////////
-//
-// Copyright (c) 2000-2003 Intel Corporation
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are met:
-//
-// * Redistributions of source code must retain the above copyright notice,
-// this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above copyright notice,
-// this list of conditions and the following disclaimer in the documentation
-// and/or other materials provided with the distribution.
-// * Neither name of Intel Corporation nor the names of its contributors
-// may be used to endorse or promote products derived from this software
-// without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR
-// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-///////////////////////////////////////////////////////////////////////////
-/********************************************************************************
- * SampleUtil_GetFirstDocumentItem
- *
- * Description:
- * Given a document node, this routine searches for the first element
- * named by the input string item, and returns its value as a string.
- * String must be freed by caller using free.
- * Parameters:
- * doc -- The DOM document from which to extract the value
- * item -- The item to search for
- *
- *
- ********************************************************************************/
-
-int IxmlGetFirstDocumentItem( IN IXML_Document * doc, IN std::string item, std::string& value ) {
- IXML_NodeList *nodeList = NULL;
- IXML_Node *textNode = NULL;
- IXML_Node *tmpNode = NULL;
-
- int error = 0;
-
- nodeList = ixmlDocument_getElementsByTagName( doc, item.c_str() );
-
- if( nodeList != NULL ) {
- if( ( tmpNode = ixmlNodeList_item( nodeList, 0 ) ) ) {
-
- textNode = ixmlNode_getFirstChild( tmpNode );
-
- if(textNode != NULL){
- value = ixmlNode_getNodeValue( textNode );
- }
- }
- } else {
- error = -1;
- }
-
- if( nodeList != NULL) {
- ixmlNodeList_free( nodeList );
- }
-
-
- return error;
-}
-
-IXML_Element* IxmlAddProperty(IXML_Document* document, IXML_Element* node, const string& upnpproperty, const string& value){
- if(!node) return NULL;
- IXML_Element* PropertyNode = NULL;
-
- string tvalue = value.substr(0,MAX_METADATA_LENGTH_L);
-
- string::size_type pos = upnpproperty.find('@');
- string attribute = pos!=string::npos ? upnpproperty.substr(pos+1) : string();
- string property = pos!=string::npos ? upnpproperty.substr(0, pos) : upnpproperty;
-
- if(!attribute.empty()){
- if(property.empty()){
- if(ixmlElement_setAttribute(node, attribute.c_str(), tvalue.c_str())!=IXML_SUCCESS){
- return NULL;
- }
- }
- else {
- IXML_NodeList* NodeList = ixmlElement_getElementsByTagName(node, property.c_str());
- if(NodeList!=NULL){
- PropertyNode = (IXML_Element*) ixmlNodeList_item(NodeList, 0);
- if(PropertyNode){
- if(ixmlElement_setAttribute(PropertyNode, attribute.c_str(), tvalue.c_str())!=IXML_SUCCESS){
- return NULL;
- }
- }
- else {
- ixmlNodeList_free(NodeList);
- return NULL;
- }
- }
- else {
- return NULL;
- }
- }
- }
- else {
- PropertyNode = ixmlDocument_createElement(document, property.c_str());
- IXML_Node* PropertyText = ixmlDocument_createTextNode(document, tvalue.c_str());
- ixmlNode_appendChild((IXML_Node*) PropertyNode, PropertyText);
- ixmlNode_appendChild((IXML_Node*) node, (IXML_Node*) PropertyNode);
- }
- return PropertyNode;
-}
-
-IXML_Element* IxmlAddFilteredProperty(const StringList& Filter, IXML_Document* document, IXML_Element* node, const string& upnpproperty, const string& value){
- // leave out empty values.
- if(value.empty() || !value.compare("0")){
- return NULL;
- }
-
- if((*Filter.begin()).compare("*") == 0) return IxmlAddProperty(document, node, upnpproperty, value);
-
- for(StringList::const_iterator it = Filter.begin(); it != Filter.end(); ++it){
- if((*it).compare(upnpproperty) == 0) return IxmlAddProperty(document, node, upnpproperty, value);
- }
-
- return NULL;
-}
-
-IXML_Element* IxmlReplaceProperty(IXML_Document* document, IXML_Element* node, const string& upnpproperty, const string& newValue){
- if(!node) return NULL;
- IXML_Element* PropertyNode = NULL;
-
- string tvalue = newValue.substr(0, MAX_METADATA_LENGTH_L);
-
- string::size_type pos = upnpproperty.find('@');
- string attribute = pos!=string::npos ? upnpproperty.substr(pos+1) : string();
- string property = pos!=string::npos ? upnpproperty.substr(0, pos) : upnpproperty;
-
- if(!attribute.empty()){
- if(property.empty()){
- if(tvalue.empty()){
- if(ixmlElement_setAttribute(node, attribute.c_str(), tvalue.c_str())!=IXML_SUCCESS){
- return NULL;
- }
- }
- else {
- ixmlElement_removeAttribute(node, attribute.c_str());
- }
- }
- else {
- IXML_NodeList* NodeList = ixmlElement_getElementsByTagName(node, property.c_str());
- if(NodeList!=NULL){
- PropertyNode = (IXML_Element*) ixmlNodeList_item(NodeList, 0);
- if(PropertyNode){
- if(!tvalue.empty()){
- if(ixmlElement_setAttribute(PropertyNode, attribute.c_str(), tvalue.c_str())!=IXML_SUCCESS){
- return NULL;
- }
- }
- else {
- ixmlElement_removeAttribute(PropertyNode, attribute.c_str());
- }
- }
- else {
- ixmlNodeList_free(NodeList);
- return NULL;
- }
- }
- else {
- return NULL;
- }
- }
- }
- else {
- IXML_NodeList* NodeList = ixmlElement_getElementsByTagName(node, property.c_str());
- if(NodeList!=NULL){
- PropertyNode = (IXML_Element*) ixmlNodeList_item(NodeList, 0);
- IXML_Node* PropertyText = ixmlNode_getFirstChild((IXML_Node*) PropertyNode);
-
- if(ixmlNode_removeChild((IXML_Node*) PropertyNode, PropertyText, NULL)!=IXML_SUCCESS){
- return NULL;
- }
- if(!tvalue.empty()){
- PropertyText = ixmlDocument_createTextNode(document, tvalue.c_str());
- }
- ixmlNode_appendChild((IXML_Node*) PropertyNode, PropertyText);
- }
- else {
- ixmlNodeList_free(NodeList);
- return NULL;
- }
- }
- return PropertyNode;
-}
-
-} // namespace ixml
-
} // namespace upnp
diff --git a/include/media/mediaManager.h b/include/media/mediaManager.h
index 16dbb4d..c9e042d 100644
--- a/include/media/mediaManager.h
+++ b/include/media/mediaManager.h
@@ -20,35 +20,9 @@
namespace upnp {
-class cMediaManager;
-
-class cResourceStreamer {
- friend class cMediaManager;
-private:
- cUPnPResourceProvider* provider;
- cMetadata::Resource* resource;
-
- cMediaManager* manager;
-
- StringVector protocolInfo;
-
- cResourceStreamer(cMediaManager* manager, cUPnPResourceProvider* provider, cMetadata::Resource* resource);
-public:
- virtual ~cResourceStreamer();
- std::string GetContentFeatures() const;
- size_t GetContentLength() const;
- std::string GetContentType() const;
- std::string GetTransferMode(const std::string& requestedMode ) const;
- bool Seekable() const;
-
- bool Open();
- size_t Read(char* buf, size_t bufLen);
- bool Seek(size_t offset, int origin);
- void Close();
-};
+class cResourceStreamer;
class cMediaManager : public cThread {
- friend class upnp::cPluginManager;
private:
struct MediaRequest {
@@ -111,9 +85,6 @@ private:
cUPnPResourceProvider* CreateResourceProvider(const std::string& uri);
- void AddProviderFunctor(upnp::cPluginManager::FunctionPtr providerFunctor);
- void AddProfiler(cMediaProfiler* profiler);
-
uint32_t systemUpdateID;
IdList eventedContainerUpdateIDs;
StringList scanDirectories;
@@ -123,12 +94,31 @@ private:
upnp::cPluginManager* pluginManager;
- typedef std::map<std::string, upnp::cPluginManager::FunctionPtr> ProviderMap;
- typedef std::list<boost::shared_ptr<cMediaProfiler> > ProfilerList;
+};
+
+class cResourceStreamer {
+ friend class cMediaManager;
+private:
+ cUPnPResourceProvider* provider;
+ cMetadata::Resource* resource;
+
+ cMediaManager* manager;
+
+ StringVector protocolInfo;
- ProviderMap providers;
- ProfilerList profilers;
+ cResourceStreamer(cMediaManager* manager, cUPnPResourceProvider* provider, cMetadata::Resource* resource);
+public:
+ virtual ~cResourceStreamer();
+ std::string GetContentFeatures() const;
+ size_t GetContentLength() const;
+ std::string GetContentType() const;
+ std::string GetTransferMode(const std::string& requestedMode ) const;
+ bool Seekable() const;
+ bool Open();
+ size_t Read(char* buf, size_t bufLen);
+ bool Seek(size_t offset, int origin);
+ void Close();
};
} // namespace upnp
diff --git a/include/plugin.h b/include/plugin.h
index 6896ebf..c30ce2b 100644
--- a/include/plugin.h
+++ b/include/plugin.h
@@ -257,7 +257,7 @@ public:
*
* The given URI is an absolute URI.
*/
- virtual EntryList GetContainerEntries(string uri) = 0;
+ virtual EntryList GetContainerEntries(const string& uri) = 0;
/**
* Checks if the given URI is a container.
@@ -268,7 +268,7 @@ public:
* If it is a container, the plugin manager will try to recurse
* into that directory and get the elements of it.
*/
- virtual bool IsContainer(string uri) = 0;
+ virtual bool IsContainer(const string& uri) = 0;
/**
* Checks if the given URI is a link to another element.
@@ -283,7 +283,7 @@ public:
* registered as a reference to the original element. Otherwise
* the element is skipped.
*/
- virtual bool IsLink(string uri, string& target) = 0;
+ virtual bool IsLink(const string& uri, string& target) = 0;
/**
* Returns the containerUpdateId of the given container
@@ -306,7 +306,7 @@ public:
* confused, if the elements differ though the updateId remains
* the same.
*/
- virtual long GetContainerUpdateId(string uri) = 0;
+ virtual long GetContainerUpdateId(const string& uri) = 0;
/**
* Returns the meta data of a specific container.
@@ -331,7 +331,7 @@ public:
* - Restricted: true
*
*/
- virtual cMetadata GetMetadata(string uri);
+ virtual bool GetMetadata(const string& uri, cMetadata& metadata);
/**
* Get the HTTP Uri.
@@ -348,7 +348,7 @@ public:
* The implementor of a resource provider MUST either implement
* this function or the file access methods below.
*/
- virtual string GetHTTPUri(string uri);
+ virtual string GetHTTPUri(const string& uri, const string& currentIP = string());
virtual bool Seekable() const;
@@ -365,7 +365,7 @@ public:
*
* The default implementation return false.
*/
- virtual bool Open(string uri);
+ virtual bool Open(const string& uri);
/**
* Reads data from the stream
@@ -446,7 +446,7 @@ protected:
* - change of the parent container, where the file or container
* was moved to
*/
- void OnContainerUpdate(string uri, long containerUpdateId, string changesUri = string());
+ void OnContainerUpdate(const string& uri, long containerUpdateId, const string& changesUri = string());
};
@@ -474,7 +474,7 @@ public:
*
* @return \b true if the plugin can handle the uri schema, \b false if not.
*/
- virtual bool CanHandleSchema(string schema) = 0;
+ virtual bool CanHandleSchema(const string& schema) = 0;
/**
* Get the metadata from a specific resource.
@@ -504,7 +504,7 @@ public:
* @return true, if this profiler was able to get the specific metadata,
* false, if not.
*/
- virtual bool GetMetadata(string uri, cMetadata& metadata) = 0;
+ virtual bool GetMetadata(const string& uri, cMetadata& metadata) = 0;
protected:
};
diff --git a/include/pluginManager.h b/include/pluginManager.h
index a40308f..8520b01 100644
--- a/include/pluginManager.h
+++ b/include/pluginManager.h
@@ -16,36 +16,51 @@
namespace upnp {
-class cMediaManager;
-
class cPluginManager {
public:
- typedef void*(*FunctionPtr)(void);
- cPluginManager(cMediaManager* manager);
+ typedef std::list< boost::shared_ptr<cMediaProfiler> > ProfilerList;
+
+ cPluginManager();
virtual ~cPluginManager();
bool LoadPlugins(const std::string& directory);
+
+ int Count() const;
+
+ const ProfilerList& GetProfilers() const;
+ cUPnPResourceProvider* CreateProvider(const string& schema);
+
private:
+
+ typedef cUPnPResourceProvider*(*ResourceProviderFuncPtr)(void);
+ typedef cMediaProfiler*(*MediaProfilerFuncPtr)(void);
+
class DLL {
public:
DLL(const std::string& file);
virtual ~DLL();
bool Load();
- FunctionPtr GetProvider() const { return provider; };
- FunctionPtr GetProfiler() const { return profiler; };
+
+ bool IsProvider() const { return isProvider; }
+
+ typedef void*(*FuncPtr)(void);
+
+ FuncPtr GetFunc() const { return function; };
private:
std::string file;
void* handle;
- FunctionPtr provider;
- FunctionPtr profiler;
+ bool isProvider;
+ FuncPtr function;
};
typedef std::list< boost::shared_ptr<DLL> > DLLList;
+ typedef std::map<string, ResourceProviderFuncPtr > ProviderMap;
- DLLList dlls;
- cMediaManager* manager;
+ DLLList dlls;
+ ProviderMap providers;
+ ProfilerList profilers;
};
diff --git a/include/tools.h b/include/tools.h
index cf34b42..a92b8a2 100644
--- a/include/tools.h
+++ b/include/tools.h
@@ -11,7 +11,6 @@
#include <vector>
#include <string>
#include <iostream>
-#include <upnp/upnp.h>
#include <string.h>
#include <vdr/tools.h>
#include <map>
@@ -28,139 +27,21 @@ using namespace std;
#define NL "\n"
-#define att(s) strchr(s,'@')!=NULL?strchr(s,'@')+1:NULL
-#define prop(s) substr(s, 0, strchr(s,'@')-s)
-
#define MAX_METADATA_LENGTH_L 1024
#define MAX_METADATA_LENGTH_S 256
-/**
- * creates a part of a string
- *
- * This creates a substring of a string which begins at the given offset and has the
- * specified lenght.
- *
- * @return the new string
- * @param str the full string
- * @param offset the starting index
- * @param length the length of the new string
- */
-char* substr(const char* str, unsigned int offset, unsigned int length);
-
-/****************************************************
- *
- * Known Errors
- *
- ****************************************************/
-
-/* Errors 401-404, 501 are already defined in
- * Intel SDK, however 403 MUST NOT USED.
- */
-
-/****** 600 Common Action Errors ******/
-
-#define UPNP_SOAP_E_ARGUMENT_INVALID 600
-#define UPNP_SOAP_E_ARGUMENT_OUT_OF_RANGE 601
-#define UPNP_SOAP_E_ACTION_NOT_IMPLEMENTED 602
-#define UPNP_SOAP_E_OUT_OF_MEMORY 603
-#define UPNP_SOAP_E_HUMAN_INTERVENTION 604
-#define UPNP_SOAP_E_STRING_TO_LONG 605
-#define UPNP_SOAP_E_NOT_AUTHORIZED 606
-#define UPNP_SOAP_E_SIGNATURE_FAILURE 607
-#define UPNP_SOAP_E_SIGNATURE_MISSING 608
-#define UPNP_SOAP_E_NOT_ENCRYPTED 609
-#define UPNP_SOAP_E_INVALID_SEQUENCE 610
-#define UPNP_SOAP_E_INVALID_CONTROL_URL 611
-#define UPNP_SOAP_E_NO_SUCH_SESSION 612
-
-/****** 700 Action specific Errors ******/
-
-#define UPNP_CDS_E_NO_SUCH_OBJECT 701
-#define UPNP_CDS_E_INVALID_CURRENT_TAG 702
-#define UPNP_CDS_E_INVALID_NEW_TAG 703
-#define UPNP_CDS_E_REQUIRED_TAG 704
-#define UPNP_CDS_E_READ_ONLY_TAG 705
-#define UPNP_CDS_E_PARAMETER_MISMATCH 706
-#define UPNP_CDS_E_INVALID_SEARCH_CRITERIA 708
-#define UPNP_CDS_E_INVALID_SORT_CRITERIA 709
-#define UPNP_CDS_E_NO_SUCH_CONTAINER 710
-#define UPNP_CDS_E_RESTRICTED_OBJECT 711
-#define UPNP_CDS_E_BAD_METADATA 712
-#define UPNP_CDS_E_RESTRICTED_PARENT 713
-#define UPNP_CDS_E_NO_SUCH_SOURCE_RESOURCE 714
-#define UPNP_CDS_E_RESOURCE_ACCESS_DENIED 715
-#define UPNP_CDS_E_TRANSFER_BUSY 716
-#define UPNP_CDS_E_NO_SUCH_FILE_TRANSFER 717
-#define UPNP_CDS_E_NO_SUCH_DESTINATION_RESOURCE 718
-#define UPNP_CDS_E_DEST_RESOURCE_ACCESS_DENIED 719
-#define UPNP_CDS_E_CANT_PROCESS_REQUEST 720
-
-#define UPNP_CMS_E_INCOMPATIBLE_PROTOCOL_INFO 701
-#define UPNP_CMS_E_INCOMPATIBLE_DIRECTIONS 702
-#define UPNP_CMS_E_INSUFFICIENT_RESOURCES 703
-#define UPNP_CMS_E_LOCAL_RESTRICTIONS 704
-#define UPNP_CMS_E_ACCESS_DENIED 705
-#define UPNP_CMS_E_INVALID_CONNECTION_REFERENCE 706
-#define UPNP_CMS_E_NOT_IN_NETWORK 707
-
namespace upnp {
typedef std::list<std::string> StringList;
typedef std::vector<std::string> StringVector;
typedef std::map<std::string, uint32_t> IdList;
-namespace tools {
- string GetAddressByInterface(string Interface);
- string GetNetworkInterfaceByIndex(int Index, bool skipLoop);
- StringVector GetNetworkInterfaces(bool skipLoop);
-
- string ToString(long number);
-
- string StringListToCSV(StringList list);
- string IdListToCSV(IdList list);
-
- string GenerateUUIDFromURL(string url);
- string GenerateUUIDRandomly();
-
- void StringExplode(string str, string separator, StringVector& results);
-}
-
-namespace ixml {
- void XmlEscapeSpecialChars(string& doc);
- /**
- * First occurance of item
- *
- * Finds the first occurance of a specified item in a given \bc IXML document and returns its value.
- * If an error occures, its code is stored in the last parameter \c 'error'.
- *
- * @return error the error code in case of an error
- * @param doc the \c IXML document to be parsed
- * @param item the item which shall be found
- * @param the value of the item
- */
- int IxmlGetFirstDocumentItem( IN IXML_Document * doc, IN const string item, string& value );
- /**
- * Adds a property
- *
- * This adds a UPnP property to an \bc IXML document.
- * The property must have the pattern "namespace:property@attribute".
- *
- * @return returns
- * - \bc NULL, in case of an error
- * - \bc the newly created property node or the node at which the attribute was
- * appended to
- * @param document the \c IXML document to put the parameter in
- * @param node the specific node where to put the parameter
- * @param upnpproperty the upnp property
- * @param value the value of the upnp property
- */
- IXML_Element* IxmlAddProperty(IN IXML_Document* document, IN IXML_Element* node, IN const string& upnpproperty, IN const string& value );
-
- IXML_Element* IxmlAddFilteredProperty(IN const StringList& Filter, IN IXML_Document* document, IN IXML_Element* node, IN const string& upnpproperty, IN const string& value );
-
- IXML_Element* IxmlReplaceProperty(IN IXML_Document* document, IN IXML_Element* node, IN const string& upnpproperty, IN const string& newValue );
}
-}
+#include "tools/error.h"
+#include "tools/ixml.h"
+#include "tools/net.h"
+#include "tools/string.h"
+#include "tools/uuid.h"
#endif /* TOOLS_H_ */
diff --git a/media/mediaManager.cpp b/media/mediaManager.cpp
index a94b563..c869bb0 100644
--- a/media/mediaManager.cpp
+++ b/media/mediaManager.cpp
@@ -6,17 +6,14 @@
*/
#include "../include/media/mediaManager.h"
-#include "../include/plugin.h"
#include "../include/server.h"
#include "../include/parser.h"
-#include "../include/tools.h"
#include <upnp/upnp.h>
#include <sstream>
-#include <tntdb/connection.h>
-#include <tntdb/statement.h>
#include <tntdb/result.h>
#include <upnp/ixml.h>
#include <memory>
+#include <tntdb/statement.h>
namespace upnp {
@@ -394,11 +391,13 @@ cMediaManager::BrowseFlag cMediaManager::ToBrowseFlag(const std::string& browseF
bool cMediaManager::Initialise(){
- pluginManager = new upnp::cPluginManager(this);
+ pluginManager = new upnp::cPluginManager();
if(!pluginManager->LoadPlugins(pluginDirectory)){
esyslog("UPnP\tError while loading upnp plugin directory '%s'", pluginDirectory.c_str());
return false;
+ } else {
+ dsyslog("UPnP\tFound %d plugins", pluginManager->Count());
}
try {
@@ -508,7 +507,7 @@ bool cMediaManager::Initialise(){
return true;
} catch (const std::exception& e) {
- esyslog("UPnP\tException occurred while initializing database: %s", e.what());
+ esyslog("UPnP\tException occurred while initializing database '%s': %s", databaseFile.c_str(), e.what());
connection.rollbackTransaction();
diff --git a/media/pluginManager.cpp b/media/pluginManager.cpp
index 40a0b9f..9c4cafd 100644
--- a/media/pluginManager.cpp
+++ b/media/pluginManager.cpp
@@ -5,9 +5,9 @@
* Author: savop
*/
-#include "../include/plugin.h"
-#include "../include/tools.h"
#include "../include/pluginManager.h"
+#include "../include/tools/string.h"
+#include "../include/tools/uuid.h"
#include <string>
#include <dlfcn.h>
#include <dirent.h>
@@ -69,7 +69,6 @@ bool cMetadata::AddProperty(const Property& property){
key.compare(property::object::KEY_SCHEDULED_START) == 0 ||
key.compare(property::object::KEY_TITLE) == 0)
{
- esyslog("UPnP\tProperty '%s' already exist!", key.c_str());
return false;
}
}
@@ -218,9 +217,7 @@ public:
}
} ClassValidatorInst;
-cMetadata cUPnPResourceProvider::GetMetadata(string uri){
-
- cMetadata metadata;
+bool cUPnPResourceProvider::GetMetadata(const string& uri, cMetadata& metadata){
metadata.SetObjectIDByUri(uri);
metadata.SetParentIDByUri(uri.substr(0,uri.find_last_of("/")));
@@ -228,11 +225,11 @@ cMetadata cUPnPResourceProvider::GetMetadata(string uri){
metadata.SetProperty(cMetadata::Property(property::object::KEY_CLASS, "object.container"));
metadata.SetProperty(cMetadata::Property(property::object::KEY_RESTRICTED, true));
- return metadata;
+ return true;
}
-string cUPnPResourceProvider::GetHTTPUri(string uri){
+string cUPnPResourceProvider::GetHTTPUri(const string& uri, const string& currentIP){
return string();
}
@@ -240,7 +237,7 @@ bool cUPnPResourceProvider::Seekable() const {
return false;
}
-bool cUPnPResourceProvider::Open(string uri){
+bool cUPnPResourceProvider::Open(const string& uri){
return false;
}
@@ -255,11 +252,24 @@ bool cUPnPResourceProvider::Seek(size_t offset, int origin){
void cUPnPResourceProvider::Close(){
}
-upnp::cPluginManager::cPluginManager(cMediaManager* manager)
-: manager(manager)
+
+
+upnp::cPluginManager::cPluginManager()
{}
-cPluginManager::~cPluginManager(){}
+upnp::cPluginManager::~cPluginManager(){}
+
+const cPluginManager::ProfilerList& upnp::cPluginManager::GetProfilers() const {
+ return profilers;
+}
+
+int upnp::cPluginManager::Count() const {
+ return dlls.size();
+}
+
+cUPnPResourceProvider* upnp::cPluginManager::CreateProvider(const string& schema) {
+ return providers[schema]();
+}
#define UPNPPLUGIN_PREFIX "libupnp-"
#define SO_INDICATOR ".so."
@@ -270,7 +280,6 @@ bool upnp::cPluginManager::LoadPlugins(const string& directory){
struct dirent* dirEntry;
if((dirHandle = opendir(directory.c_str())) == NULL){
- esyslog("UPnP\tLoading directory '%s' failed. Errno: %d", directory.c_str(), errno);
return false;
}
@@ -283,8 +292,17 @@ bool upnp::cPluginManager::LoadPlugins(const string& directory){
filename.find(SO_INDICATOR) != string::npos)
{
boost::shared_ptr<DLL> dll(new DLL(directory + "/" + filename));
- if(dll->Load())
+ if(dll->Load()){
dlls.push_back(dll);
+
+ if(dll->IsProvider()){
+ boost::shared_ptr<cUPnPResourceProvider> provider((cUPnPResourceProvider*)(dll->GetFunc()()));
+ providers[provider->ProvidesSchema()] = (ResourceProviderFuncPtr)dll->GetFunc();
+ } else {
+ boost::shared_ptr<cMediaProfiler> profiler((cMediaProfiler*)(dll->GetFunc()()));
+ profilers.push_back( profiler );
+ }
+ }
}
}
}
@@ -296,8 +314,8 @@ bool upnp::cPluginManager::LoadPlugins(const string& directory){
upnp::cPluginManager::DLL::DLL(const string& f)
: file(f)
, handle(NULL)
-, provider(NULL)
-, profiler(NULL)
+, isProvider(false)
+, function(NULL)
{
}
@@ -309,27 +327,25 @@ bool upnp::cPluginManager::DLL::Load(){
const char* error = dlerror();
if(!error){
- provider = (FunctionPtr)dlsym(handle, "UPnPCreateResourceProvider");
+ function = (FuncPtr)dlsym(handle, "UPnPCreateResourceProvider");
if (!(error = dlerror())){
- isyslog("UPnP\tFound provider in %s", file.c_str());
+ isProvider = true;
return true;
} else {
- dsyslog("UPnP\tError: %s", error);
+ cerr << error << endl;
}
- profiler = (FunctionPtr)dlsym(handle, "UPnPCreateMediaProfiler");
+ function = (FuncPtr)dlsym(handle, "UPnPCreateMediaProfiler");
if (!(error = dlerror())){
- isyslog("UPnP\tFound profiler in %s", file.c_str());
+ isProvider = false;
return true;
} else {
- dsyslog("UPnP\tError: %s", error);
+ cerr << error << endl;
}
} else {
- dsyslog("UPnP\tError: %s", error);
+ cerr << error << endl;
}
- isyslog("UPnP\tInvalid library '%s', no valid symbols found.", file.c_str());
-
return false;
}
diff --git a/plugins/provider/vdrProvider/Makefile b/plugins/provider/vdrProvider/Makefile
index dfbf54f..1220a55 100644
--- a/plugins/provider/vdrProvider/Makefile
+++ b/plugins/provider/vdrProvider/Makefile
@@ -21,6 +21,8 @@ CXXFLAGS ?= -g -O3 -Wall -Werror=overloaded-virtual -Wno-parentheses -fPIC
UPNPDIR ?= ../../..
+APIVERSION = $(shell sed -ne '/define UPNPPLUGIN_VERSION/s/^.*"\(.*\)".*$$/\1/p' $(UPNPDIR)/include/plugin.h)
+
INCLUDES += -I$(UPNPDIR)/include
DEFINES += -D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE
@@ -45,3 +47,7 @@ $(DEPFILE): Makefile
libupnp-$(SCHEMA)-provider.so: $(OBJS)
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@
+ @cp --remove-destination $@ $@.$(APIVERSION)
+
+clean:
+ @-rm -f $(OBJS) $(DEPFILE) *.so *.so.$(APIVERSION) core* *~
diff --git a/plugins/provider/vdrProvider/vdrProvider.cpp b/plugins/provider/vdrProvider/vdrProvider.cpp
index f593cba..7d1ef22 100644
--- a/plugins/provider/vdrProvider/vdrProvider.cpp
+++ b/plugins/provider/vdrProvider/vdrProvider.cpp
@@ -8,13 +8,15 @@
#include <plugin.h>
#include <vdr/channels.h>
#include <vdr/tools.h>
+#include <vdr/config.h>
#include <string>
+#include <tools.h>
-namespace upnp {
+using namespace std;
-#define GROUP_CHANNELS
+namespace upnp {
-class VdrProvider : cUPnPResourceProvider {
+class VdrProvider : public cUPnPResourceProvider {
virtual string ProvidesSchema(){ return "vdr"; }
@@ -22,10 +24,10 @@ class VdrProvider : cUPnPResourceProvider {
return ProvidesSchema() + "://";
}
- virtual EntryList GetContainerEntries(string uri){
+ virtual cUPnPResourceProvider::EntryList GetContainerEntries(const string& uri){
if(uri.find(GetRootContainer(), 0) != 0){
isyslog("VdrProvider\tUri does not contain the root.");
- return EntryList;
+ return cUPnPResourceProvider::EntryList();
}
EntryList list;
@@ -43,24 +45,35 @@ class VdrProvider : cUPnPResourceProvider {
return list;
}
- virtual bool IsContainer(string uri){
+ virtual bool IsContainer(const string& uri){
return uri.compare(GetRootContainer()) == 0;
}
- virtual bool IsLink(string uri, string& target){
+ virtual bool IsLink(const string& uri, string& target){
// TODO: what are Channel::RefChannel or LinkChannels ?
return false;
}
- virtual long GetContainerUpdateId(string uri){
+ virtual long GetContainerUpdateId(const string& uri){
// TODO: provide a container update id
return 0;
}
- virtual cMetadata GetMetadata(string uri);
+ virtual bool GetMetadata(const string& uri, cMetadata& metadata){
+ if(uri.find(GetRootContainer(), 0) != 0){
+ isyslog("VdrProvider\tUri does not contain the root.");
+ return false;
+ }
+
+ return false;
+ }
+
+ virtual string GetHTTPUri(const string& uri, const string& currentIP){
+ if(uri.find(GetRootContainer(), 0) != 0){
+ isyslog("VdrProvider\tUri does not contain the root.");
+ return string();
+ }
- virtual string GetHTTPUri(string uri){
- // TODO: get streamdev settings from configuration
return string();
}
diff --git a/tests/Makefile b/tests/Makefile
index 41b056a..c8e6192 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,3 +1,6 @@
-tests: test_parser.cpp ../common/parser.cpp
- g++ -o test_parser test_parser.cpp ../common/parser.cpp -I../include -I/usr/include -I/usr/local/include \ No newline at end of file
+parser: test_parser.cpp ../common/parser.cpp
+ g++ -o test_parser test_parser.cpp ../common/parser.cpp -g -I../include -I/usr/include -I/usr/local/include
+
+dllloader: dll_loader.cpp ../media/pluginManager.cpp ../common/tools.cpp
+ g++ -o test_dllloader dll_loader.cpp ../media/pluginManager.cpp ../common/tools.cpp -g -ldl -Wl,--export-dynamic -I../include -I/usr/include -I/usr/local/include \ No newline at end of file