summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--common/tools.cpp22
-rw-r--r--include/media/mediaManager.h2
-rw-r--r--include/tools.h3
-rw-r--r--media/mediaManager.cpp101
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;
}