Mercurial > projects > hoofbaby
view deps/Platinum/Source/Devices/MediaServer/PltDidl.cpp @ 0:3425707ddbf6
Initial import (hopefully this mercurial stuff works...)
author | fraserofthenight |
---|---|
date | Mon, 06 Jul 2009 08:06:28 -0700 |
parents | |
children |
line wrap: on
line source
/***************************************************************** | | Platinum - DIDL | | Copyright (c) 2004-2008, Plutinosoft, LLC. | All rights reserved. | http://www.plutinosoft.com | | This program is free software; you can redistribute it and/or | modify it under the terms of the GNU General Public License | as published by the Free Software Foundation; either version 2 | of the License, or (at your option) any later version. | | OEMs, ISVs, VARs and other distributors that combine and | distribute commercially licensed software with Platinum software | and do not wish to distribute the source code for the commercially | licensed software under version 2, or (at your option) any later | version, of the GNU General Public License (the "GPL") must enter | into a commercial license agreement with Plutinosoft, LLC. | | This program is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU General Public License for more details. | | You should have received a copy of the GNU General Public License | along with this program; see the file LICENSE.txt. If not, write to | the Free Software Foundation, Inc., | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | http://www.gnu.org/licenses/gpl-2.0.html | ****************************************************************/ /*---------------------------------------------------------------------- | includes +---------------------------------------------------------------------*/ #include "PltDidl.h" #include "PltXmlHelper.h" #include "PltService.h" NPT_SET_LOCAL_LOGGER("platinum.media.server.didl") /*---------------------------------------------------------------------- | globals +---------------------------------------------------------------------*/ const char* didl_header = "<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/\">"; const char* didl_footer = "</DIDL-Lite>"; const char* didl_namespace_dc = "http://purl.org/dc/elements/1.1/"; const char* didl_namespace_upnp = "urn:schemas-upnp-org:metadata-1-0/upnp/"; const char* didl_namespace_dlna = "urn:schemas-dlna-org:metadata-1-0/"; /*---------------------------------------------------------------------- | PLT_Didl::ConvertFilterToMask +---------------------------------------------------------------------*/ NPT_UInt32 PLT_Didl::ConvertFilterToMask(NPT_String filter) { // easy out if (filter.GetLength() == 0) return PLT_FILTER_MASK_ALL; // a filter string is a comma delimited set of fields identifying // a given DIDL property (or set of properties). // These fields are or start with: upnp:, @, res@, res, dc:, container@ NPT_UInt32 mask = 0; const char* s = filter; int i = 0; while (s[i] != '\0') { int next_comma = filter.Find(',', i); int len = ((next_comma < 0)?filter.GetLength():next_comma)-i; if (NPT_String::CompareN(s+i, "*", 1) == 0) { // return now, there's no point in parsing the rest return PLT_FILTER_MASK_ALL; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CREATOR, len) == 0) { mask |= PLT_FILTER_MASK_CREATOR; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ARTIST, len) == 0) { mask |= PLT_FILTER_MASK_ARTIST; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ACTOR, len) == 0) { mask |= PLT_FILTER_MASK_ACTOR; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_AUTHOR, len) == 0) { mask |= PLT_FILTER_MASK_AUTHOR; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DATE, len) == 0) { mask |= PLT_FILTER_MASK_DATE; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUM, len) == 0) { mask |= PLT_FILTER_MASK_ALBUM; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_GENRE, len) == 0) { mask |= PLT_FILTER_MASK_GENRE; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ALBUMARTURI, len) == 0) { mask |= PLT_FILTER_MASK_ALBUMARTURI; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_DESCRIPTION, len) == 0) { mask |= PLT_FILTER_MASK_DESCRIPTION; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_ORIGINALTRACK, len) == 0) { mask |= PLT_FILTER_MASK_ORIGINALTRACK; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_SEARCHABLE, len) == 0) { mask |= PLT_FILTER_MASK_SEARCHABLE; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CONTAINER_SEARCHABLE, len) == 0) { mask |= PLT_FILTER_MASK_SEARCHABLE; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CHILDCOUNT, len) == 0) { mask |= PLT_FILTER_MASK_CHILDCOUNT; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_CONTAINER_CHILDCOUNT, len) == 0) { mask |= PLT_FILTER_MASK_CHILDCOUNT; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_DURATION, len) == 0) { mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_DURATION; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_SIZE, len) == 0) { mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_SIZE; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_PROTECTION, len) == 0) { mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_PROTECTION; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES_RESOLUTION, len) == 0) { mask |= PLT_FILTER_MASK_RES | PLT_FILTER_MASK_RES_RESOLUTION; } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_RES, len) == 0) { mask |= PLT_FILTER_MASK_RES; } if (next_comma < 0) { return mask; } i = next_comma + 1; } return mask; } /*---------------------------------------------------------------------- | PLT_Didl::AppendXmlUnEscape +---------------------------------------------------------------------*/ void PLT_Didl::AppendXmlUnEscape(NPT_String& out, NPT_String& in) { const char* input = (const char*) in; unsigned int i=0; while (i<in.GetLength()) { if (NPT_String::CompareN(input+i, "<", 4) == 0) { out += '<'; i +=4; } else if (NPT_String::CompareN(input+i, ">", 4) == 0) { out += '>'; i += 4; } else if (NPT_String::CompareN(input+i, "&", 5) == 0) { out += '&'; i += 5; } else if (NPT_String::CompareN(input+i, """, 6) == 0) { out += '"'; i += 6; } else if (NPT_String::CompareN(input+i, "'", 6) == 0) { out += '\''; i += 6; } else { out += *(input+i); i++; } } } /*---------------------------------------------------------------------- | PLT_Didl::AppendXmlEscape +---------------------------------------------------------------------*/ void PLT_Didl::AppendXmlEscape(NPT_String& out, NPT_String& in) { for (int i=0; i<(int)in.GetLength(); i++) { if (in[i] == '<') { out += "<"; } else if (in[i] == '>') { out += ">"; } else if (in[i] == '&') { out += "&"; } else if (in[i] == '"') { out += """; } else if (in[i] == '\'') { out += "'"; } else { out += in[i]; } } } /*---------------------------------------------------------------------- | PLT_Didl::FormatTimeStamp +---------------------------------------------------------------------*/ void PLT_Didl::FormatTimeStamp(NPT_String& out, NPT_UInt32 seconds) { int hours = seconds/3600; if (hours == 0) { out += "00:"; } else { if (hours < 10) { out += '0'; } out += NPT_String::FromInteger(hours) + ":"; } int minutes = (seconds/60)%60; if (minutes == 0) { out += "00:"; } else { if (minutes < 10) { out += '0'; } out += NPT_String::FromInteger(minutes) + ":"; } int secs = seconds%60; if (secs == 0) { out += "00"; } else { if (secs < 10) { out += '0'; } out += NPT_String::FromInteger(secs); } out += ".000"; } /*---------------------------------------------------------------------- | PLT_Didl::ParseTimeStamp +---------------------------------------------------------------------*/ NPT_Result PLT_Didl::ParseTimeStamp(NPT_String timestamp, NPT_UInt32& seconds) { // assume a timestamp in the format HH:MM:SS int colon; NPT_String str = timestamp; NPT_UInt32 num; // extract millisecondsfirst if ((colon = timestamp.ReverseFind('.')) != -1) { str = timestamp.SubString(colon + 1); timestamp = timestamp.Left(colon); } // extract seconds first str = timestamp; if ((colon = timestamp.ReverseFind(':')) != -1) { str = timestamp.SubString(colon + 1); timestamp = timestamp.Left(colon); } if (NPT_FAILED(str.ToInteger(num))) { return NPT_FAILURE; } seconds = num; // extract minutes str = timestamp; if (timestamp.GetLength()) { if ((colon = timestamp.ReverseFind(':')) != -1) { str = timestamp.SubString(colon + 1); timestamp = timestamp.Left(colon); } if (NPT_FAILED(str.ToInteger(num))) { return NPT_FAILURE; } seconds += 60*num; } // extract hours str = timestamp; if (timestamp.GetLength()) { if ((colon = timestamp.ReverseFind(':')) != -1) { str = timestamp.SubString(colon + 1); timestamp = timestamp.Left(colon); } if (NPT_FAILED(str.ToInteger(num))) { return NPT_FAILURE; } seconds += 3600*num; } return NPT_SUCCESS; } /*---------------------------------------------------------------------- | PLT_Didl::ToDidl +---------------------------------------------------------------------*/ NPT_Result PLT_Didl::ToDidl(PLT_MediaObject& object, NPT_String filter, NPT_String& didl) { NPT_UInt32 mask = ConvertFilterToMask(filter); // Allocate enough space for the didl didl.Reserve(2048); return object.ToDidl(mask, didl); } /*---------------------------------------------------------------------- | PLT_Didl::FromDidl +---------------------------------------------------------------------*/ NPT_Result PLT_Didl::FromDidl(const char* xml, PLT_MediaObjectListReference& objects) { NPT_String str; PLT_MediaObject* object = NULL; NPT_XmlNode* node = NULL; NPT_XmlElementNode* didl = NULL; NPT_LOG_FINE("Parsing Didl..."); NPT_XmlParser parser; if (NPT_FAILED(parser.Parse(xml, node)) || !node || !node->AsElementNode()) { goto cleanup; } didl = node->AsElementNode(); NPT_LOG_FINE("Processing Didl xml..."); if (didl->GetTag().Compare("DIDL-Lite", true)) { goto cleanup; } // create entry list objects = new PLT_MediaObjectList(); // for each child, find out if it's a container or not // and then invoke the FromDidl on it for (NPT_List<NPT_XmlNode*>::Iterator children = didl->GetChildren().GetFirstItem(); children; children++) { NPT_XmlElementNode* child = (*children)->AsElementNode(); if (!child) continue; if (child->GetTag().Compare("Container", true) == 0) { object = new PLT_MediaContainer(); } else if (child->GetTag().Compare("item", true) == 0) { object = new PLT_MediaItem(); } else { goto cleanup; } if (NPT_FAILED(object->FromDidl(child))) { goto cleanup; } objects->Add(object); } delete node; return NPT_SUCCESS; cleanup: objects = NULL; delete node; delete object; return NPT_FAILURE; }