diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | common/tools.cpp | 326 | ||||
-rw-r--r-- | include/media/mediaManager.h | 58 | ||||
-rw-r--r-- | include/plugin.h | 20 | ||||
-rw-r--r-- | include/pluginManager.h | 35 | ||||
-rw-r--r-- | include/tools.h | 129 | ||||
-rw-r--r-- | media/mediaManager.cpp | 11 | ||||
-rw-r--r-- | media/pluginManager.cpp | 66 | ||||
-rw-r--r-- | plugins/provider/vdrProvider/Makefile | 6 | ||||
-rw-r--r-- | plugins/provider/vdrProvider/vdrProvider.cpp | 35 | ||||
-rw-r--r-- | tests/Makefile | 7 |
11 files changed, 148 insertions, 550 deletions
@@ -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("€"); break; - case L'"': buffer.append("""); break; - case L'&': buffer.append("&"); break; - case L'<': buffer.append("<"); break; - case L'>': buffer.append(">"); break; - case L'¡': buffer.append("¡"); break; - case L'¢': buffer.append("¢"); break; - case L'£': buffer.append("£"); break; - case L'¤': buffer.append("¤"); break; - case L'¥': buffer.append("¥"); break; - case L'¦': buffer.append("¦"); break; - case L'§': buffer.append("§"); break; - case L'¨': buffer.append("¨"); break; - case L'©': buffer.append("©"); break; - case L'ª': buffer.append("ª"); break; - case L'¬': buffer.append("¬"); break; - case L'': buffer.append("­"); break; - case L'®': buffer.append("®"); break; - case L'¯': buffer.append("¯"); break; - case L'°': buffer.append("°"); break; - case L'±': buffer.append("±"); break; - case L'²': buffer.append("²"); break; - case L'³': buffer.append("³"); break; - case L'´': buffer.append("´"); break; - case L'µ': buffer.append("µ"); break; - case L'¶': buffer.append("¶"); break; - case L'·': buffer.append("·"); break; - case L'¸': buffer.append("¸"); break; - case L'¹': buffer.append("¹"); break; - case L'º': buffer.append("º"); break; - case L'»': buffer.append("»"); break; - case L'«': buffer.append("«"); break; - case L'¼': buffer.append("¼"); break; - case L'½': buffer.append("½"); break; - case L'¾': buffer.append("¾"); break; - case L'¿': buffer.append("¿"); break; - case L'À': buffer.append("À"); break; - case L'Á': buffer.append("Á"); break; - case L'Â': buffer.append("Â"); break; - case L'Ã': buffer.append("Ã"); break; - case L'Ä': buffer.append("Ä"); break; - case L'Å': buffer.append("Å"); break; - case L'Æ': buffer.append("Æ"); break; - case L'Ç': buffer.append("Ç"); break; - case L'È': buffer.append("È"); break; - case L'É': buffer.append("É"); break; - case L'Ê': buffer.append("Ê"); break; - case L'Ë': buffer.append("Ë"); break; - case L'Ì': buffer.append("Ì"); break; - case L'Í': buffer.append("Í"); break; - case L'Î': buffer.append("Î"); break; - case L'Ï': buffer.append("Ï"); break; - case L'Ð': buffer.append("Ð"); break; - case L'Ñ': buffer.append("Ñ"); break; - case L'Ò': buffer.append("Ò"); break; - case L'Ó': buffer.append("Ó"); break; - case L'Ô': buffer.append("Ô"); break; - case L'Õ': buffer.append("Õ"); break; - case L'Ö': buffer.append("Ö"); break; - case L'×': buffer.append("×"); break; - case L'Ø': buffer.append("Ø"); break; - case L'Ù': buffer.append("Ù"); break; - case L'Ú': buffer.append("Ú"); break; - case L'Û': buffer.append("Û"); break; - case L'Ü': buffer.append("Ü"); break; - case L'Ý': buffer.append("Ý"); break; - case L'Þ': buffer.append("Þ"); break; - case L'ß': buffer.append("ß"); break; - case L'à': buffer.append("à"); break; - case L'á': buffer.append("á"); break; - case L'â': buffer.append("â"); break; - case L'ã': buffer.append("ã"); break; - case L'ä': buffer.append("ä"); break; - case L'å': buffer.append("å"); break; - case L'æ': buffer.append("æ"); break; - case L'ç': buffer.append("ç"); break; - case L'è': buffer.append("è"); break; - case L'é': buffer.append("é"); break; - case L'ê': buffer.append("ê"); break; - case L'ë': buffer.append("ë"); break; - case L'ì': buffer.append("ì"); break; - case L'í': buffer.append("í"); break; - case L'î': buffer.append("î"); break; - case L'ï': buffer.append("ï"); break; - case L'ð': buffer.append("ð"); break; - case L'ñ': buffer.append("ñ"); break; - case L'ò': buffer.append("ò"); break; - case L'ó': buffer.append("ó"); break; - case L'ô': buffer.append("ô"); break; - case L'õ': buffer.append("õ"); break; - case L'ö': buffer.append("ö"); break; - case L'÷': buffer.append("÷"); break; - case L'ø': buffer.append("ø"); break; - case L'ù': buffer.append("ù"); break; - case L'ú': buffer.append("ú"); break; - case L'û': buffer.append("û"); break; - case L'ü': buffer.append("ü"); break; - case L'ý': buffer.append("ý"); break; - case L'þ': buffer.append("þ"); 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 |