diff options
-rw-r--r-- | common/tools.cpp | 22 | ||||
-rw-r--r-- | include/media/mediaManager.h | 2 | ||||
-rw-r--r-- | include/tools.h | 3 | ||||
-rw-r--r-- | media/mediaManager.cpp | 101 |
4 files changed, 102 insertions, 26 deletions
diff --git a/common/tools.cpp b/common/tools.cpp index 015f998..1b725e6 100644 --- a/common/tools.cpp +++ b/common/tools.cpp @@ -332,9 +332,11 @@ IXML_Element* IxmlAddProperty(IXML_Document* document, IXML_Element* node, const if(!node) return NULL; IXML_Element* PropertyNode = NULL; - string tvalue = value.substr(MAX_METADATA_LENGTH); - string attribute = upnpproperty.substr(upnpproperty.find('@')+1); - string property = upnpproperty.substr(0, upnpproperty.find('@')); + 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()){ @@ -376,6 +378,8 @@ IXML_Element* IxmlAddFilteredProperty(const StringList& Filter, IXML_Document* d 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); } @@ -387,9 +391,11 @@ IXML_Element* IxmlReplaceProperty(IXML_Document* document, IXML_Element* node, c if(!node) return NULL; IXML_Element* PropertyNode = NULL; - string tvalue = newValue.substr(0, MAX_METADATA_LENGTH); - string attribute = upnpproperty.substr(upnpproperty.find('@')+1); - string property = upnpproperty.substr(0, upnpproperty.find('@')); + 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()){ @@ -407,7 +413,7 @@ IXML_Element* IxmlReplaceProperty(IXML_Document* document, IXML_Element* node, c if(NodeList!=NULL){ PropertyNode = (IXML_Element*) ixmlNodeList_item(NodeList, 0); if(PropertyNode){ - if(newValue){ + if(!tvalue.empty()){ if(ixmlElement_setAttribute(PropertyNode, attribute.c_str(), tvalue.c_str())!=IXML_SUCCESS){ return NULL; } @@ -435,7 +441,7 @@ IXML_Element* IxmlReplaceProperty(IXML_Document* document, IXML_Element* node, c if(ixmlNode_removeChild((IXML_Node*) PropertyNode, PropertyText, NULL)!=IXML_SUCCESS){ return NULL; } - if(newValue){ + if(!tvalue.empty()){ 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 929181f..1ffa329 100644 --- a/include/media/mediaManager.h +++ b/include/media/mediaManager.h @@ -72,7 +72,7 @@ private: void Action(); bool CheckIntegrity(); - void CreateResponse(MediaRequest&, const string&); + int CreateResponse(MediaRequest&, const string&); void OnContainerUpdate(string uri, long updateID); diff --git a/include/tools.h b/include/tools.h index 3c2fcd3..bd82cd4 100644 --- a/include/tools.h +++ b/include/tools.h @@ -31,7 +31,8 @@ using namespace std; #define att(s) strchr(s,'@')!=NULL?strchr(s,'@')+1:NULL #define prop(s) substr(s, 0, strchr(s,'@')-s) -#define MAX_METADATA_LENGTH 1024 +#define MAX_METADATA_LENGTH_L 1024 +#define MAX_METADATA_LENGTH_S 256 /** * creates a part of a string diff --git a/media/mediaManager.cpp b/media/mediaManager.cpp index 56c206a..2f2e968 100644 --- a/media/mediaManager.cpp +++ b/media/mediaManager.cpp @@ -9,13 +9,21 @@ #include "../include/media/mediaManager.h" #include "../include/server.h" #include "../include/parser.h" +#include "../include/tools.h" #include <upnp/upnp.h> #include <sstream> #include <tntdb/statement.h> #include <tntdb/result.h> +#include <upnp/ixml.h> namespace upnp { +static const char* DIDLFragment = "<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>"; + cMediaManager::cMediaManager() : mSystemUpdateID(0) , mDatabaseFile("metadata.db") @@ -98,7 +106,7 @@ StringList cMediaManager::GetSupportedProtocolInfos() const { return list; } -void cMediaManager::CreateResponse(MediaRequest& request, const string& select){ +int cMediaManager::CreateResponse(MediaRequest& request, const string& select){ stringstream resources, details; resources << "SELECT * FROM resources WHERE " @@ -116,34 +124,92 @@ void cMediaManager::CreateResponse(MediaRequest& request, const string& select){ // 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>"; + IXML_Document* DIDLDoc = NULL; + if(ixmlParseBufferEx(DIDLFragment, &DIDLDoc)==IXML_SUCCESS){ + IXML_Node* root = ixmlNode_getFirstChild((IXML_Node*) DIDLDoc); + for(tntdb::Statement::const_iterator it = select1.begin(); it != select1.end(); ++it){ - for(tntdb::Statement::const_iterator it = select1.begin(); it != select1.end(); ++it){ - tntdb::Row row = (*it); + tntdb::Row row = (*it); + + IXML_Element* object; + string upnpClass = row.getString(property::object::KEY_CLASS); + + bool isContainer; + + if(upnpClass.find("object.item",0) == 0){ + object = ixmlDocument_createElement(DIDLDoc, "item"); + isContainer = false; + } else if(upnpClass.find("object.container",0) == 0) { + object = ixmlDocument_createElement(DIDLDoc, "container"); + isContainer = true; + } else { + goto error; + } + ixmlNode_appendChild(root, (IXML_Node*)object); + + ixml::IxmlAddProperty(DIDLDoc, object, property::object::KEY_OBJECTID, row.getString(property::object::KEY_OBJECTID)); + ixml::IxmlAddProperty(DIDLDoc, object, property::object::KEY_PARENTID, row.getString(property::object::KEY_PARENTID)); + ixml::IxmlAddProperty(DIDLDoc, object, property::object::KEY_RESTRICTED, row.getString(property::object::KEY_RESTRICTED)); + ixml::IxmlAddProperty(DIDLDoc, object, property::object::KEY_TITLE, row.getString(property::object::KEY_TITLE).substr(0, MAX_METADATA_LENGTH_S)); + ixml::IxmlAddProperty(DIDLDoc, object, property::object::KEY_CLASS, row.getString(property::object::KEY_CLASS).substr(0, MAX_METADATA_LENGTH_S)); + if(isContainer){ + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_CHILD_COUNT, row.getString(property::object::KEY_CHILD_COUNT)); + } + else { + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_CHANNEL_NR, row.getString(property::object::KEY_CHANNEL_NR)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_CHANNEL_NAME, row.getString(property::object::KEY_CHANNEL_NAME)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_SCHEDULED_START, row.getString(property::object::KEY_SCHEDULED_START)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_SCHEDULED_END, row.getString(property::object::KEY_SCHEDULED_END)); + } - select2.setString("objectID", row.getString(property::object::KEY_OBJECTID)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_CREATOR, row.getString(property::object::KEY_CREATOR)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_DESCRIPTION, row.getString(property::object::KEY_DESCRIPTION)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_LONG_DESCRIPTION, row.getString(property::object::KEY_LONG_DESCRIPTION)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_DATE, row.getDatetime(property::object::KEY_DATE).getIso()); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::object::KEY_LANGUAGE, row.getString(property::object::KEY_LANGUAGE)); - for(tntdb::Statement::const_iterator it2 = select.begin(); it2 != select.end(); ++it2){ - tntdb::Row row2 = (*it2); - cMetadata::Resource resource; + select2.setString("objectID", row.getString(property::object::KEY_OBJECTID)); - resource.SetBitrate(row2.getInt(property::resource::KEY_BITRATE)); - resource.SetBitsPerSample(row2.getInt(property::resource::KEY_BITS_PER_SAMPLE)); + for(tntdb::Statement::const_iterator it2 = select2.begin(); it2 != select2.end(); ++it2){ + tntdb::Row row2 = (*it2); + string resourceURI; + + IXML_Element* resource = ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_RESOURCE, resourceURI); + + if(resource){ + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_PROTOCOL_INFO, row.getString(property::resource::KEY_PROTOCOL_INFO)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_BITRATE, row.getString(property::resource::KEY_BITRATE)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_BITS_PER_SAMPLE, row.getString(property::resource::KEY_BITS_PER_SAMPLE)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_COLOR_DEPTH, row.getString(property::resource::KEY_COLOR_DEPTH)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_DURATION, row.getTime(property::resource::KEY_DURATION).getIso()); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_NR_AUDIO_CHANNELS, row.getString(property::resource::KEY_NR_AUDIO_CHANNELS)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_RESOLUTION, row.getString(property::resource::KEY_RESOLUTION)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_SAMPLE_FREQUENCY, row.getString(property::resource::KEY_SAMPLE_FREQUENCY)); + ixml::IxmlAddFilteredProperty(filterList, DIDLDoc, object, property::resource::KEY_SIZE, row.getString(property::resource::KEY_SIZE)); + } + + } + + ++request.numberReturned; } - ++request.numberReturned; + request.result = ixmlDocumenttoString(DIDLDoc); + + cout << request.result << endl; + + ixmlDocument_free(DIDLDoc); + return UPNP_E_SUCCESS; } - request.result; + error: + esyslog("UPnP\tFailed to process the request"); + ixmlDocument_free(DIDLDoc); + return UPNP_CDS_E_CANT_PROCESS_REQUEST; } int cMediaManager::Browse(BrowseRequest& request){ @@ -186,7 +252,10 @@ int cMediaManager::Browse(BrowseRequest& request){ metadata << " LIMIT " << request.startIndex << ", " << request.requestCount; } + metadata << ";"; + int ret = 0; + if((ret = CreateResponse(request, metadata.str())) == UPNP_E_SUCCESS) return ret; return (request.totalMatches == 0 && request.numberReturned == 0) ? UPNP_CDS_E_CANT_PROCESS_REQUEST : UPNP_E_SUCCESS; } |