diff options
-rw-r--r-- | HISTORY | 5 | ||||
-rw-r--r-- | common.h | 10 | ||||
-rw-r--r-- | database/object.cpp | 148 | ||||
-rw-r--r-- | database/resources.cpp | 2 | ||||
-rw-r--r-- | inc/object.h | 8 | ||||
-rw-r--r-- | inc/util.h | 9 | ||||
-rw-r--r-- | misc/util.cpp | 76 |
7 files changed, 173 insertions, 85 deletions
@@ -1,6 +1,11 @@ VDR Plugin 'upnp' Revision History ---------------------------------- +2009-01-25: Version 0.0.2-alpha1 + + - Bug: A minor bug prevented the plugin from detecting the resources + correnctly + 2009-01-24: Version 0.0.2-alpha0 - New: Added record streaming support for SDTV @@ -376,10 +376,13 @@ enum UPNP_WEB_METHODS { #define UPNP_PROP_WRITESTATUS "upnp:writeStatus" #define UPNP_PROP_CLASS "upnp:class" #define UPNP_PROP_CLASSNAME UPNP_PROP_CLASS "@name" +#define UPNP_PROP_CREATECLASS "upnp:createClass" #define UPNP_PROP_SEARCHCLASS "upnp:searchClass" #define UPNP_PROP_SCLASSDERIVED UPNP_PROP_SEARCHCLASS "@includeDerived" -#define UPNP_PROP_REFERENCEID UPNP_OBJECT_ITEM "@refID" #define UPNP_PROP_SCLASSNAME UPNP_PROP_SEARCHCLASS "@name" +#define UPNP_PROP_CCLASSDERIVED UPNP_PROP_CREATECLASS "@includeDerived" +#define UPNP_PROP_CCLASSNAME UPNP_PROP_CREATECLASS "@name" +#define UPNP_PROP_REFERENCEID UPNP_OBJECT_ITEM "@refID" #define UPNP_PROP_SEARCHABLE UPNP_OBJECT_CONTAINER "@searchable" #define UPNP_PROP_CHILDCOUNT UPNP_OBJECT_CONTAINER "@childcount" #define UPNP_PROP_RESOURCE "res" @@ -481,8 +484,9 @@ enum UPNP_WEB_METHODS { UPNP_PROP_LONGDESCRIPTION ","\ UPNP_PROP_PUBLISHER -#define UPNP_DURATION_FORMAT_STRING "%5d:%02d:%02d" -#define UPNP_DURATION_FRAME_FORMAT ".%03d" +#define UPNP_DURATION_FORMAT "%5d:%02d:%02d" +#define UPNP_DURATION_FRAME_FORMAT "%5d:%02d:%02d.%03d" +#define UPNP_MAX_METADATA_LENGTH 1024 #define AVDETECTOR_TIME_BASE 1000 /**************************************************** diff --git a/database/object.cpp b/database/object.cpp index 71dfe63..b193567 100644 --- a/database/object.cpp +++ b/database/object.cpp @@ -334,30 +334,22 @@ IXML_Node* cUPnPClassItem::createDIDLFragment(IXML_Document* Document, cStringLi MESSAGE(VERBOSE_DIDL, "ParentID: %s", *this->getParentID()); MESSAGE(VERBOSE_DIDL, "Restricted: %s", this->isRestricted()?"1":"0"); MESSAGE(VERBOSE_DIDL, "Class: %s", this->getClass()); + MESSAGE(VERBOSE_DIDL, "Filter: %d", Filter?Filter->Size():-1); IXML_Node* Didl = ixmlNode_getFirstChild((IXML_Node*) this->mDIDLFragment); IXML_Element* eItem = ixmlDocument_createElement(this->mDIDLFragment, "item"); - ixmlElement_setAttribute(eItem, att(UPNP_PROP_OBJECTID), *this->getID()); - ixmlElement_setAttribute(eItem, att(UPNP_PROP_PARENTID), *this->getParentID()); - ixmlElement_setAttribute(eItem, att(UPNP_PROP_RESTRICTED), this->isRestricted()?"1":"0"); - ixmlNode_appendChild(Didl, (IXML_Node*) eItem); - IXML_Element* eTitle = ixmlDocument_createElement(this->mDIDLFragment, UPNP_PROP_TITLE); - IXML_Node* Title = ixmlDocument_createTextNode(this->mDIDLFragment, this->getTitle()); - - IXML_Element* eClass = ixmlDocument_createElement(this->mDIDLFragment, UPNP_PROP_CLASS); - IXML_Node* Class = ixmlDocument_createTextNode(this->mDIDLFragment, this->getClass()); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_OBJECTID, *this->getID()); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_PARENTID, *this->getParentID()); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_RESTRICTED, this->isRestricted()?"1":"0"); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_TITLE, this->getTitle()); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_CLASS, this->getClass()); - ixmlNode_appendChild((IXML_Node*) eTitle, Title); - ixmlNode_appendChild((IXML_Node*) eClass, Class); - ixmlNode_appendChild((IXML_Node*) eItem, (IXML_Node*) eTitle); - ixmlNode_appendChild((IXML_Node*) eItem, (IXML_Node*) eClass); - -// if(Filter==NULL || Filter->Find(UPNP_PROP_CREATOR)) ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_CREATOR, this->getCreator()); -// if(Filter==NULL || Filter->Find(UPNP_PROP_WRITESTATUS)) ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_WRITESTATUS, itoa(this->getWriteStatus())); -// if(Filter==NULL || Filter->Find(UPNP_PROP_REFERENCEID)) ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_REFERENCEID, *this->getReferenceID()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_CREATOR, this->getCreator()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_WRITESTATUS, itoa(this->getWriteStatus())); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_REFERENCEID, ((int)(this->getReferenceID())<0)?"":*this->getReferenceID()); for(cUPnPResource* Resource = this->getResources()->First(); Resource; Resource = this->getResources()->Next(Resource)){ MESSAGE(VERBOSE_DIDL, "Resource: %s", Resource->getResource()); @@ -367,18 +359,17 @@ IXML_Node* cUPnPClassItem::createDIDLFragment(IXML_Document* Document, cStringLi cString ResourceURL = cString::sprintf("%s%s/get?resId=%d", *URLBase, UPNP_DIR_SHARES, Resource->getID()); MESSAGE(VERBOSE_DIDL, "Resource-URI: %s", *ResourceURL); + + IXML_Element* eRes = ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_RESOURCE, *ResourceURL); + if(eRes){ + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eRes, UPNP_PROP_BITRATE, itoa(Resource->getBitrate())); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eRes, UPNP_PROP_BITSPERSAMPLE, itoa(Resource->getBitsPerSample())); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eRes, UPNP_PROP_COLORDEPTH, itoa(Resource->getColorDepth())); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eRes, UPNP_PROP_DURATION, Resource->getDuration()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eRes, UPNP_PROP_PROTOCOLINFO, Resource->getProtocolInfo()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eRes, UPNP_PROP_SIZE, cString::sprintf("%lld", Resource->getFileSize())); + } - IXML_Element* eRes = ixmlDocument_createElement(this->mDIDLFragment, UPNP_PROP_RESOURCE); - IXML_Node* Res = ixmlDocument_createTextNode(this->mDIDLFragment, *ResourceURL); - ixmlNode_appendChild((IXML_Node*) eRes, Res); - - if(Resource->getBitrate()) ixmlElement_setAttribute(eRes, att(UPNP_PROP_BITRATE), itoa(Resource->getBitrate())); - if(Resource->getBitsPerSample()) ixmlElement_setAttribute(eRes, att(UPNP_PROP_BITSPERSAMPLE), itoa(Resource->getBitsPerSample())); - if(Resource->getColorDepth()) ixmlElement_setAttribute(eRes, att(UPNP_PROP_COLORDEPTH), itoa(Resource->getColorDepth())); - if(Resource->getDuration()) ixmlElement_setAttribute(eRes, att(UPNP_PROP_DURATION), Resource->getDuration()); - if(Resource->getProtocolInfo()) ixmlElement_setAttribute(eRes, att(UPNP_PROP_PROTOCOLINFO), Resource->getProtocolInfo()); - - ixmlNode_appendChild((IXML_Node*) eItem, (IXML_Node*) eRes); } return (IXML_Node*)eItem; @@ -411,25 +402,38 @@ IXML_Node* cUPnPClassContainer::createDIDLFragment(IXML_Document* Document, cStr MESSAGE(VERBOSE_DIDL, "ParentID: %s", *this->getParentID()); MESSAGE(VERBOSE_DIDL, "Restricted: %s", this->isRestricted()?"1":"0"); MESSAGE(VERBOSE_DIDL, "Class: %s", this->getClass()); + MESSAGE(VERBOSE_DIDL, "Filter: %d", Filter?Filter->Size():-1); IXML_Node* Didl = ixmlNode_getFirstChild((IXML_Node*) this->mDIDLFragment); IXML_Element* eItem = ixmlDocument_createElement(this->mDIDLFragment, "container"); - ixmlElement_setAttribute(eItem, att(UPNP_PROP_OBJECTID), *this->getID()); - ixmlElement_setAttribute(eItem, att(UPNP_PROP_PARENTID), *this->getParentID()); - ixmlElement_setAttribute(eItem, att(UPNP_PROP_RESTRICTED), this->isRestricted()?"1":"0"); ixmlNode_appendChild(Didl, (IXML_Node*) eItem); - IXML_Element* eTitle = ixmlDocument_createElement(this->mDIDLFragment, UPNP_PROP_TITLE); - IXML_Node* Title = ixmlDocument_createTextNode(this->mDIDLFragment, this->getTitle()); - - IXML_Element* eClass = ixmlDocument_createElement(this->mDIDLFragment, UPNP_PROP_CLASS); - IXML_Node* Class = ixmlDocument_createTextNode(this->mDIDLFragment, this->getClass()); - - ixmlNode_appendChild((IXML_Node*) eTitle, Title); - ixmlNode_appendChild((IXML_Node*) eClass, Class); - ixmlNode_appendChild((IXML_Node*) eItem, (IXML_Node*) eTitle); - ixmlNode_appendChild((IXML_Node*) eItem, (IXML_Node*) eClass); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_OBJECTID, *this->getID()); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_PARENTID, *this->getParentID()); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_RESTRICTED, this->isRestricted()?"1":"0"); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_TITLE, this->getTitle()); + ixmlAddProperty(this->mDIDLFragment, eItem, UPNP_PROP_CLASS, this->getClass()); + + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_DLNA_CONTAINERTYPE, this->getContainerType()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_CHILDCOUNT, itoa(this->getChildCount())); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_SEARCHABLE, this->isSearchable()?"1":"0"); + + const tClassVector* CreateClasses = this->getCreateClasses(); + for(unsigned int i = 0; i < CreateClasses->size(); i++){ + cClass CreateClass = CreateClasses->at(i); + IXML_Element* eCreateClasses = ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_CREATECLASS, CreateClass.ID); + if(eCreateClasses) + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_CCLASSDERIVED, CreateClass.includeDerived?"1":"0"); + } + const tClassVector* SearchClasses = this->getSearchClasses(); + for(unsigned int i = 0; i < SearchClasses->size(); i++){ + cClass SearchClass = SearchClasses->at(i); + IXML_Element* eSearchClasses = ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_SEARCHCLASS, SearchClass.ID); + if(eSearchClasses) + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_SCLASSDERIVED, SearchClass.includeDerived?"1":"0"); + } + return (IXML_Node*)eItem; } @@ -596,9 +600,52 @@ cUPnPClassVideoItem::cUPnPClassVideoItem(){ cUPnPClassVideoItem::~cUPnPClassVideoItem(){ } -//cString cUPnPClassVideoItem::createDIDLFragment(cStringList* Filter){ -// return NULL; -//} +IXML_Node* cUPnPClassVideoItem::createDIDLFragment(IXML_Document* Document, cStringList* Filter){ + IXML_Element* eItem = (IXML_Element*) cUPnPClassItem::createDIDLFragment(Document, Filter); + + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_LONGDESCRIPTION, this->getLongDescription()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_DESCRIPTION, this->getDescription()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_LANGUAGE, this->getLanguage()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_RATING, this->getRating()); + + char* genre = strtok(strdup0(this->getGenre()), ","); + while(genre){ + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_GENRE, genre); + genre = strtok(NULL, ","); + } + + char* producer = strtok(strdup0(this->getProducers()), ","); + while(producer){ + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_PRODUCER, producer); + producer = strtok(NULL, ","); + } + + char* actor = strtok(strdup0(this->getActors()), ","); + while(actor){ + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_ACTOR, actor); + actor = strtok(NULL, ","); + } + + char* director = strtok(strdup0(this->getDirectors()), ","); + while(director){ + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_DIRECTOR, director); + director = strtok(NULL, ","); + } + + char* publisher = strtok(strdup0(this->getPublishers()), ","); + while(publisher){ + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_PUBLISHER, publisher); + publisher = strtok(NULL, ","); + } + + char* relation = strtok(strdup0(this->getRelations()), ","); + while(relation){ + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_RELATION, relation); + relation = strtok(NULL, ","); + } + + return (IXML_Node*) eItem; +} cStringList* cUPnPClassVideoItem::getPropertyList(){ cStringList* Properties = cUPnPClassItem::getPropertyList(); @@ -754,9 +801,16 @@ cUPnPClassVideoBroadcast::cUPnPClassVideoBroadcast(){ cUPnPClassVideoBroadcast::~cUPnPClassVideoBroadcast(){ } -//cString cUPnPClassVideoBroadcast::createDIDLFragment(cStringList* Filter){ -// return NULL; -//} +IXML_Node* cUPnPClassVideoBroadcast::createDIDLFragment(IXML_Document* Document, cStringList* Filter){ + IXML_Element* eItem = (IXML_Element*) cUPnPClassItem::createDIDLFragment(Document, Filter); + + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_CHANNELNAME, this->getChannelName()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_CHANNELNR, itoa(this->getChannelNr())); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_ICON, this->getIcon()); + ixmlAddFilteredProperty(Filter, this->mDIDLFragment, eItem, UPNP_PROP_REGION, this->getRegion()); + + return (IXML_Node*) eItem; +} cStringList* cUPnPClassVideoBroadcast::getPropertyList(){ cStringList* Properties = cUPnPClassVideoItem::getPropertyList(); diff --git a/database/resources.cpp b/database/resources.cpp index 8ff478f..23403d5 100644 --- a/database/resources.cpp +++ b/database/resources.cpp @@ -156,7 +156,7 @@ int cUPnPResources::createFromRecording(cUPnPClassVideoItem* Object, cRecording* cUPnPResource* Resource = this->mMediator->newResource(Object, UPNP_RESOURCE_RECORDING,ResourceFile, Detector->getDLNAProfile()->mime, ProtocolInfo); Resource->mBitrate = Detector->getBitrate(); Resource->mBitsPerSample = Detector->getBitsPerSample(); - Resource->mDuration = duration(Detector->getDuration()); + Resource->mDuration = duration(Detector->getDuration(), AVDETECTOR_TIME_BASE); Resource->mResolution = (Detector->getWidth() && Detector->getHeight()) ? *cString::sprintf("%dx%d",Detector->getWidth(), Detector->getHeight()) : NULL; Resource->mSampleFrequency = Detector->getSampleFrequency(); Resource->mSize = Detector->getFileSize(); diff --git a/inc/object.h b/inc/object.h index bceb3f1..1031589 100644 --- a/inc/object.h +++ b/inc/object.h @@ -752,7 +752,7 @@ public: * * @return a vector with all search classes */ - const std::vector<cClass>* getSearchClasses() const { return &(this->mSearchClasses); } + const tClassVector* getSearchClasses() const { return &(this->mSearchClasses); } /** * Get the create classes * @@ -763,7 +763,7 @@ public: * * @return a vector with create classes */ - const std::vector<cClass>* getCreateClasses() const { return &(this->mCreateClasses); } + const tClassVector* getCreateClasses() const { return &(this->mCreateClasses); } /** * Is this container searchable * @@ -832,7 +832,7 @@ protected: cUPnPClassVideoItem(); public: virtual ~cUPnPClassVideoItem(); - //virtual cString createDIDLFragment(cStringList* Filter); + virtual IXML_Node* createDIDLFragment(IXML_Document* Document, cStringList* Filter); virtual cStringList* getPropertyList(); virtual bool setProperty(const char* Property, const char* Value); virtual bool getProperty(const char* Property, char** Value) const; @@ -1141,7 +1141,7 @@ protected: cUPnPClassVideoBroadcast(); public: virtual ~cUPnPClassVideoBroadcast(); - //virtual cString createDIDLFragment(cStringList* Filter); + virtual IXML_Node* createDIDLFragment(IXML_Document* Document, cStringList* Filter); virtual cStringList* getPropertyList(); virtual bool setProperty(const char* Property, const char* Value); virtual bool getProperty(const char* Property, char** Value) const; @@ -88,14 +88,17 @@ char* ixmlGetFirstDocumentItem( IN IXML_Document * doc, IN const char *item, int * The property must have the pattern "namespace:property@attribute". * * @return returns - * - \bc <0, in case of an error - * - \bc 0, otherwise + * - \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 */ -int ixmlAddProperty(IN IXML_Document* document, IN IXML_Element* node, const char* upnpproperty, const char* value ); +IXML_Element* ixmlAddProperty(IN IXML_Document* document, IN IXML_Element* node, IN const char* upnpproperty, IN const char* value ); + +IXML_Element* ixmlAddFilteredProperty(IN cStringList* Filter, IN IXML_Document* document, IN IXML_Element* node, IN const char* upnpproperty, IN const char* value ); /** * creates a part of a string * diff --git a/misc/util.cpp b/misc/util.cpp index d93d027..0781307 100644 --- a/misc/util.cpp +++ b/misc/util.cpp @@ -18,13 +18,15 @@ #include <iosfwd> #include <time.h> -#define DURATION_MAX_STRING_LENGTH 13 // DLNA: 1-5 DIGIT hours : +#define DURATION_MAX_STRING_LENGTH 16 // DLNA: 1-5 DIGIT hours : // 2 DIGIT minutes : // 2 DIGIT seconds . // 3 DIGIT fraction char* duration(off64_t duration, unsigned int timeBase){ - if (timeBase == 0) timeBase = 1; + if(!timeBase){ + timeBase = 1; + } int seconds, minutes, hours, fraction; @@ -37,28 +39,29 @@ char* duration(off64_t duration, unsigned int timeBase){ char* output = new char[DURATION_MAX_STRING_LENGTH]; - if(!snprintf( - output, - DURATION_MAX_STRING_LENGTH, - UPNP_DURATION_FORMAT_STRING, - hours, minutes, seconds) - ){ - delete output; - return NULL; + if(timeBase > 1){ + if(!snprintf( + output, + DURATION_MAX_STRING_LENGTH, + UPNP_DURATION_FRAME_FORMAT, + hours, minutes, seconds, fraction) < 0 + ){ + delete [] output; + return NULL; + } } else { - if(timeBase > 1 && - !snprintf( + if(snprintf( output, DURATION_MAX_STRING_LENGTH, - "%s" UPNP_DURATION_FRAME_FORMAT, - output, fraction) + UPNP_DURATION_FORMAT, + hours, minutes, seconds) < 0 ){ - delete output; + delete [] output; return NULL; } - else return output; } + return output; } char* substr(const char* str, unsigned int offset, unsigned int length){ @@ -475,39 +478,58 @@ char* ixmlGetFirstDocumentItem( IN IXML_Document * doc, IN const char *item, int return ret; } -int ixmlAddProperty(IXML_Document* document, IXML_Element* node, const char* upnpproperty, const char* value){ - if(!node) return -1; +IXML_Element* ixmlAddProperty(IXML_Document* document, IXML_Element* node, const char* upnpproperty, const char* value){ + if(!node) return NULL; IXML_Element* PropertyNode = NULL; + char tvalue[UPNP_MAX_METADATA_LENGTH]; + // trim the value to max metadata size + if(value){ + strncpy(tvalue, value, UPNP_MAX_METADATA_LENGTH); + } + const char* attribute = att(upnpproperty); const char* property = prop(upnpproperty); if(attribute){ - if(strcasecmp(property,"")){ - ixmlElement_setAttribute(node, attribute, value); + if(!strcmp(property,"")){ + ixmlElement_setAttribute(node, attribute, tvalue); } else { IXML_NodeList* NodeList = ixmlElement_getElementsByTagName(node, property); if(NodeList!=NULL){ - IXML_Node* Node = ixmlNodeList_item(NodeList, 0); - PropertyNode = (IXML_Element*) ixmlNode_getFirstChild(Node); + PropertyNode = (IXML_Element*) ixmlNodeList_item(NodeList, 0); if(PropertyNode){ - ixmlElement_setAttribute(PropertyNode, attribute, value); + if(ixmlElement_setAttribute(PropertyNode, attribute, tvalue)!=IXML_SUCCESS){ + return NULL; + } } else { ixmlNodeList_free(NodeList); - return -1; + return NULL; } } else { - return -1; + return NULL; } } } else { PropertyNode = ixmlDocument_createElement(document, property); - IXML_Node* PropertyText = ixmlDocument_createTextNode(document, value); + IXML_Node* PropertyText = ixmlDocument_createTextNode(document, tvalue); ixmlNode_appendChild((IXML_Node*) PropertyNode, PropertyText); ixmlNode_appendChild((IXML_Node*) node, (IXML_Node*) PropertyNode); } - return 0; + return PropertyNode; } + +IXML_Element* ixmlAddFilteredProperty(cStringList* Filter, IXML_Document* document, IXML_Element* node, const char* upnpproperty, const char* value){ + // leave out empty values. + if(!value || !strcmp(value, "") || !strcmp(value, "0")){ + return NULL; + } + + if(!Filter || Filter->Find(upnpproperty)) + return ixmlAddProperty(document, node, upnpproperty, value); + else + return NULL; +}
\ No newline at end of file |