diff options
-rw-r--r-- | common/tools.cpp | 76 | ||||
-rw-r--r-- | include/media/mediaManager.h | 2 | ||||
-rw-r--r-- | include/plugin.h | 26 | ||||
-rw-r--r-- | include/tools.h | 6 | ||||
-rw-r--r-- | media/mediaManager.cpp | 85 | ||||
-rw-r--r-- | media/pluginManager.cpp | 50 |
6 files changed, 131 insertions, 114 deletions
diff --git a/common/tools.cpp b/common/tools.cpp index f519276..015f998 100644 --- a/common/tools.cpp +++ b/common/tools.cpp @@ -328,32 +328,26 @@ int IxmlGetFirstDocumentItem( IN IXML_Document * doc, IN std::string item, std:: return error; } -//TODO const char* mit std::string ersetzen -IXML_Element* IxmlAddProperty(IXML_Document* document, IXML_Element* node, const char* upnpproperty, const char* value){ +IXML_Element* IxmlAddProperty(IXML_Document* document, IXML_Element* node, const string& upnpproperty, const string& value){ if(!node) return NULL; IXML_Element* PropertyNode = NULL; - //TODO Bug #887 - char tvalue[MAX_METADATA_LENGTH]; - // trim the value to max metadata size - if(value){ - strncpy(tvalue, value, MAX_METADATA_LENGTH); - } + string tvalue = value.substr(MAX_METADATA_LENGTH); + string attribute = upnpproperty.substr(upnpproperty.find('@')+1); + string property = upnpproperty.substr(0, upnpproperty.find('@')); - const char* attribute = att(upnpproperty); - const char* property = prop(upnpproperty); - if(attribute){ - if(!strcmp(property,"")){ - if(ixmlElement_setAttribute(node, attribute, tvalue)!=IXML_SUCCESS){ + 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); + 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, tvalue)!=IXML_SUCCESS){ + if(ixmlElement_setAttribute(PropertyNode, attribute.c_str(), tvalue.c_str())!=IXML_SUCCESS){ return NULL; } } @@ -368,64 +362,58 @@ IXML_Element* IxmlAddProperty(IXML_Document* document, IXML_Element* node, const } } else { - PropertyNode = ixmlDocument_createElement(document, property); - IXML_Node* PropertyText = ixmlDocument_createTextNode(document, tvalue); + 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; } -//TODO const char* mit std::string ersetzen -IXML_Element* IxmlAddFilteredProperty(cStringList* Filter, IXML_Document* document, IXML_Element* node, const char* upnpproperty, const char* value){ +IXML_Element* IxmlAddFilteredProperty(const StringList& Filter, IXML_Document* document, IXML_Element* node, const string& upnpproperty, const string& value){ // leave out empty values. - if(!value || !strcmp(value, "") || !strcmp(value, "0")){ + if(value.empty() || !value.compare("0")){ return NULL; } - if(!Filter || Filter->Find(upnpproperty)) - return IxmlAddProperty(document, node, upnpproperty, value); - else - return NULL; + for(StringList::const_iterator it = Filter.begin(); it != Filter.end(); ++it){ + if((*it).compare(upnpproperty) == 0) return IxmlAddProperty(document, node, upnpproperty, value); + } + + return NULL; } -//TODO const char* mit std::string ersetzen -IXML_Element* IxmlReplaceProperty(IXML_Document* document, IXML_Element* node, const char* upnpproperty, const char* newValue){ +IXML_Element* IxmlReplaceProperty(IXML_Document* document, IXML_Element* node, const string& upnpproperty, const string& newValue){ if(!node) return NULL; IXML_Element* PropertyNode = NULL; - //TODO Bug #887 - char tvalue[MAX_METADATA_LENGTH]; - // trim the value to max metadata size - if(newValue){ - strncpy(tvalue, newValue, MAX_METADATA_LENGTH); - } + string tvalue = newValue.substr(0, MAX_METADATA_LENGTH); + string attribute = upnpproperty.substr(upnpproperty.find('@')+1); + string property = upnpproperty.substr(0, upnpproperty.find('@')); - const char* attribute = att(upnpproperty); - const char* property = prop(upnpproperty); - if(attribute){ - if(!strcmp(property,"")){ - if(newValue){ - if(ixmlElement_setAttribute(node, attribute, tvalue)!=IXML_SUCCESS){ + 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); + ixmlElement_removeAttribute(node, attribute.c_str()); } } else { - IXML_NodeList* NodeList = ixmlElement_getElementsByTagName(node, property); + IXML_NodeList* NodeList = ixmlElement_getElementsByTagName(node, property.c_str()); if(NodeList!=NULL){ PropertyNode = (IXML_Element*) ixmlNodeList_item(NodeList, 0); if(PropertyNode){ if(newValue){ - if(ixmlElement_setAttribute(PropertyNode, attribute, tvalue)!=IXML_SUCCESS){ + if(ixmlElement_setAttribute(PropertyNode, attribute.c_str(), tvalue.c_str())!=IXML_SUCCESS){ return NULL; } } else { - ixmlElement_removeAttribute(PropertyNode, attribute); + ixmlElement_removeAttribute(PropertyNode, attribute.c_str()); } } else { @@ -439,7 +427,7 @@ IXML_Element* IxmlReplaceProperty(IXML_Document* document, IXML_Element* node, c } } else { - IXML_NodeList* NodeList = ixmlElement_getElementsByTagName(node, property); + 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); @@ -448,7 +436,7 @@ IXML_Element* IxmlReplaceProperty(IXML_Document* document, IXML_Element* node, c return NULL; } if(newValue){ - PropertyText = ixmlDocument_createTextNode(document, tvalue); + PropertyText = ixmlDocument_createTextNode(document, tvalue.c_str()); } ixmlNode_appendChild((IXML_Node*) PropertyNode, PropertyText); } diff --git a/include/media/mediaManager.h b/include/media/mediaManager.h index 8a8473f..929181f 100644 --- a/include/media/mediaManager.h +++ b/include/media/mediaManager.h @@ -72,6 +72,8 @@ private: void Action(); bool CheckIntegrity(); + void CreateResponse(MediaRequest&, const string&); + void OnContainerUpdate(string uri, long updateID); uint32_t mSystemUpdateID; diff --git a/include/plugin.h b/include/plugin.h index 3da08ef..fe2c5f6 100644 --- a/include/plugin.h +++ b/include/plugin.h @@ -27,6 +27,7 @@ namespace object { static const char* KEY_CREATOR = "dc:creator"; static const char* KEY_CLASS = "upnp:class"; static const char* KEY_RESTRICTED = "@restricted"; + static const char* KEY_CHILD_COUNT = "@childCount"; static const char* KEY_DESCRIPTION = "dc:description"; static const char* KEY_LONG_DESCRIPTION = "upnp:longDescription"; static const char* KEY_DATE = "dc:date"; @@ -35,6 +36,8 @@ namespace object { static const char* KEY_CHANNEL_NAME = "upnp:channelName"; static const char* KEY_SCHEDULED_START = "upnp:scheduledStartTime"; static const char* KEY_SCHEDULED_END = "upnp:scheduledEndTime"; + static const char* KEY_OBJECT_UPDATE_ID = "upnp:objectUpdateID"; + static const char* KEY_CONTAINER_UPDATE_ID= "upnp:containerUpdateID"; } @@ -87,6 +90,7 @@ class PropertyValidator; * */ class cMetadata { + friend class cMediaManager; public: /** @@ -170,19 +174,15 @@ public: typedef list<Resource> ResourceList; typedef map<string, PropertyValidator*> ValidatorMap; - bool AddProperty(Property property); - bool SetProperty(Property property, int index = 0); + bool AddProperty(const Property& property); + bool SetProperty(const Property& property, int index = 0); - Property& GetPropertyByKey(string property); - PropertyRange GetPropertiesByKey(string property); + Property& GetPropertyByKey(const string& property); + PropertyRange GetPropertiesByKey(const string& property); PropertyRange GetAllProperties(); - bool SetObjectID(string objectID); - bool SetObjectIDByUri(string uri); - string GetObjectID(); - bool SetParentID(string parentID); - bool SetParentIDByUri(string uri); - string GetParentID(); + bool SetObjectIDByUri(const string& uri); + bool SetParentIDByUri(const string& uri); private: @@ -309,7 +309,7 @@ public: /** * Returns the meta data of a specific container. * - * This function is used to retrieve meta informatio about a + * This function is used to retrieve meta information about a * container. It is NOT used to get information about files or * resources, as this is done by the media plugins. * @@ -329,7 +329,7 @@ public: * - Restricted: true * */ - virtual cMetadata* GetMetadata(string uri); + virtual cMetadata GetMetadata(string uri); /** * Get the HTTP Uri. @@ -502,7 +502,7 @@ public: * @param uri the absolute path to the resource. * @return the media resource information. */ - virtual cMetadata* GetMetadata(string uri) = 0; + virtual cMetadata GetMetadata(string uri) = 0; protected: }; diff --git a/include/tools.h b/include/tools.h index b12f6be..3c2fcd3 100644 --- a/include/tools.h +++ b/include/tools.h @@ -150,11 +150,11 @@ namespace ixml { * @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 char* upnpproperty, IN const char* value ); + IXML_Element* IxmlAddProperty(IN IXML_Document* document, IN IXML_Element* node, IN const string& upnpproperty, IN const string& value ); - IXML_Element* IxmlAddFilteredProperty(IN cStringList* Filter, IN IXML_Document* document, IN IXML_Element* node, IN const char* upnpproperty, IN const char* 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 char* upnpproperty, IN const char* newValue ); + IXML_Element* IxmlReplaceProperty(IN IXML_Document* document, IN IXML_Element* node, IN const string& upnpproperty, IN const string& newValue ); } } diff --git a/media/mediaManager.cpp b/media/mediaManager.cpp index 530dbe3..56c206a 100644 --- a/media/mediaManager.cpp +++ b/media/mediaManager.cpp @@ -98,55 +98,97 @@ StringList cMediaManager::GetSupportedProtocolInfos() const { return list; } -int cMediaManager::Browse(BrowseRequest& request){ +void cMediaManager::CreateResponse(MediaRequest& request, const string& select){ + stringstream resources, details; + + resources << "SELECT * FROM resources WHERE " + << "`" << property::object::KEY_OBJECTID << "` = " + << "':objectID'"; + + tntdb::Statement select1 = mConnection.prepare(select); + tntdb::Statement select2 = mConnection.prepare(resources.str()); + + StringList filterList = cFilterCriteria::parse(request.filter); + request.numberReturned = 0; - request.totalMatches = 0; request.updateID = 0; - stringstream sql; + // Using cursors, cannot calculate totalMatches as this would require another SQL request. + request.totalMatches = 0; + + string didl = "<DIDL-Lite " + "xmlns=\"urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/\" " + "xmlns:dc=\"http://purl.org/dc/elements/1.1/\" " + "xmlns:upnp=\"urn:schemas-upnp-org:metadata-1-0/upnp/\" " + "xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\"></DIDL-Lite>"; + + + + for(tntdb::Statement::const_iterator it = select1.begin(); it != select1.end(); ++it){ + tntdb::Row row = (*it); + + + select2.setString("objectID", row.getString(property::object::KEY_OBJECTID)); + + for(tntdb::Statement::const_iterator it2 = select.begin(); it2 != select.end(); ++it2){ + tntdb::Row row2 = (*it2); - sql << "SELECT * FROM metadata LEFT JOIN resources USING " - << "(`" << property::object::KEY_OBJECTID << "`)" - << " WHERE "; + cMetadata::Resource resource; + + resource.SetBitrate(row2.getInt(property::resource::KEY_BITRATE)); + resource.SetBitsPerSample(row2.getInt(property::resource::KEY_BITS_PER_SAMPLE)); + + } + + ++request.numberReturned; + } + + request.result; +} + +int cMediaManager::Browse(BrowseRequest& request){ + stringstream metadata; + + metadata << "SELECT *,(SELECT COUNT(1) FROM metadata m WHERE " + << "m.`" << property::object::KEY_PARENTID << "` = " + << "p.`" << property::object::KEY_OBJECTID << "`) as " + << "`" << property::object::KEY_CHILD_COUNT << "` FROM metadata p WHERE "; switch (request.browseMetadata){ case CD_BROWSE_METADATA: - sql << "`" << property::object::KEY_OBJECTID << "`"; + metadata << "`" << property::object::KEY_OBJECTID << "`"; + + // Set the offset and count to 0,1 as this is the only allowed option here. + request.requestCount = 1; + request.startIndex = 0; break; case CD_BROWSE_DIRECT_CHILDREN: - sql << "`" << property::object::KEY_PARENTID << "`"; + metadata << "`" << property::object::KEY_PARENTID << "`"; break; default: esyslog("UPnP\tInvalid arguments. Browse flag invalid"); return UPNP_SOAP_E_INVALID_ARGS; } - sql << " = '" << request.objectID << "'"; + metadata << " = '" << request.objectID << "'"; cSortCriteria::SortCriteriaList list = cSortCriteria::parse(request.sortCriteria); if(!list.empty()){ - sql << " ORDER BY "; + metadata << " ORDER BY "; upnp::cSortCriteria::SortCriteriaList::iterator it = list.begin(); - sql << (*it).property << " " << ((*it).sortDescending ? "DESC" : "ASC"); + metadata << (*it).property << " " << ((*it).sortDescending ? "DESC" : "ASC"); for(++it; it != list.end(); ++it){ - sql << ", " << (*it).property << " " << ((*it).sortDescending ? "DESC" : "ASC"); + metadata << ", " << (*it).property << " " << ((*it).sortDescending ? "DESC" : "ASC"); } } if(request.requestCount){ - sql << " LIMIT " << request.startIndex << ", " << request.requestCount; + metadata << " LIMIT " << request.startIndex << ", " << request.requestCount; } - cout << sql.str() << endl; - tntdb::Statement select = mConnection.prepare(sql.str()); - for(tntdb::Statement::const_iterator it = select.begin(); it != select.end(); ++it){ - tntdb::Row row = (*it); - cout << row.getString(property::object::KEY_TITLE) << endl; - } - - return UPNP_E_SUCCESS; + return (request.totalMatches == 0 && request.numberReturned == 0) ? UPNP_CDS_E_CANT_PROCESS_REQUEST : UPNP_E_SUCCESS; } int cMediaManager::Search(SearchRequest& request){ @@ -197,6 +239,7 @@ bool cMediaManager::Initialise(){ << "`" << property::object::KEY_CHANNEL_NAME << "` TEXT," << "`" << property::object::KEY_SCHEDULED_START << "` TEXT," << "`" << property::object::KEY_SCHEDULED_END << "` TEXT" + << "`" << property::object::KEY_OBJECT_UPDATE_ID << "` INTEGER" << ")"; tntdb::Statement objectTable = mConnection.prepare(ss.str()); diff --git a/media/pluginManager.cpp b/media/pluginManager.cpp index 5b397b7..a9bfd73 100644 --- a/media/pluginManager.cpp +++ b/media/pluginManager.cpp @@ -24,7 +24,7 @@ public: } virtual ~PropertyValidator(){} virtual string GetPropertyKey() const { return key; }; - virtual bool Validate(cMetadata::Property property) = 0; + virtual bool Validate(const cMetadata::Property& property) = 0; }; void cMetadata::RegisterPropertyValidator(PropertyValidator* validator){ @@ -33,31 +33,15 @@ void cMetadata::RegisterPropertyValidator(PropertyValidator* validator){ validators[key] = validator; } -bool cMetadata::SetObjectIDByUri(string uri){ - return SetObjectID(tools::GenerateUUIDFromURL(uri)); +bool cMetadata::SetObjectIDByUri(const string& uri){ + return SetProperty(Property(property::object::KEY_OBJECTID, tools::GenerateUUIDFromURL(uri))); } -bool cMetadata::SetParentIDByUri(string uri){ - return SetParentID(tools::GenerateUUIDFromURL(uri)); +bool cMetadata::SetParentIDByUri(const string& uri){ + return SetProperty(Property(property::object::KEY_PARENTID, tools::GenerateUUIDFromURL(uri))); } -bool cMetadata::SetObjectID(string objectID){ - if(objectID.empty() || objectID.compare("0") == 0) return false; - - SetProperty(Property(property::object::KEY_OBJECTID, objectID)); - - return true; -}; - -bool cMetadata::SetParentID(string parentID){ - if(parentID.compare("-1") == 0) return false; - - SetProperty(Property(property::object::KEY_PARENTID, parentID)); - - return true; -}; - -bool cMetadata::AddProperty(Property property){ +bool cMetadata::AddProperty(const Property& property){ string key = property.GetKey(); // Try to find a validator @@ -91,7 +75,7 @@ bool cMetadata::AddProperty(Property property){ return true; } -bool cMetadata::SetProperty(Property property, int index){ +bool cMetadata::SetProperty(const Property& property, int index){ // Try to find a validator PropertyValidator* validator = validators[property.GetKey()]; // If there is one and it fails to validate the property, return false. @@ -116,7 +100,7 @@ bool cMetadata::SetProperty(Property property, int index){ } -cMetadata::PropertyRange cMetadata::GetPropertiesByKey(string property) { +cMetadata::PropertyRange cMetadata::GetPropertiesByKey(const string& property) { return properties.equal_range(property); } @@ -125,7 +109,7 @@ cMetadata::PropertyRange cMetadata::GetAllProperties() { return range; } -cMetadata::Property& cMetadata::GetPropertyByKey(string property) { +cMetadata::Property& cMetadata::GetPropertyByKey(const string& property) { return (*properties.find(property)).second; } @@ -216,7 +200,7 @@ bool cMetadata::Resource::SetColorDepth(uint32_t colorDepth){ class ClassValidator : public PropertyValidator { public: ClassValidator() : PropertyValidator(property::object::KEY_CLASS) {} - virtual bool Validate(cMetadata::Property property){ + virtual bool Validate(const cMetadata::Property& property){ string value = property.GetString(); if(value.find("object.container", 0) == 0 || @@ -231,15 +215,15 @@ public: } } ClassValidatorInst; -cMetadata* cUPnPResourceProvider::GetMetadata(string uri){ +cMetadata cUPnPResourceProvider::GetMetadata(string uri){ - cMetadata* metadata = new cMetadata; + cMetadata metadata; - metadata->SetObjectIDByUri(uri); - metadata->SetParentIDByUri(uri.substr(0,uri.find_last_of("/"))); - metadata->SetProperty(cMetadata::Property(property::object::KEY_TITLE, uri.substr(uri.find_last_of("/")+1))); - metadata->SetProperty(cMetadata::Property(property::object::KEY_CLASS, "object.container")); - metadata->SetProperty(cMetadata::Property(property::object::KEY_RESTRICTED, true)); + metadata.SetObjectIDByUri(uri); + metadata.SetParentIDByUri(uri.substr(0,uri.find_last_of("/"))); + metadata.SetProperty(cMetadata::Property(property::object::KEY_TITLE, uri.substr(uri.find_last_of("/")+1))); + metadata.SetProperty(cMetadata::Property(property::object::KEY_CLASS, "object.container")); + metadata.SetProperty(cMetadata::Property(property::object::KEY_RESTRICTED, true)); return metadata; |