summaryrefslogtreecommitdiffstats
path: root/lib/libUPnP/patches/0027-platinum-add-support-for-xbmc-specific-fields-datead.patch
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libUPnP/patches/0027-platinum-add-support-for-xbmc-specific-fields-datead.patch')
-rw-r--r--lib/libUPnP/patches/0027-platinum-add-support-for-xbmc-specific-fields-datead.patch284
1 files changed, 284 insertions, 0 deletions
diff --git a/lib/libUPnP/patches/0027-platinum-add-support-for-xbmc-specific-fields-datead.patch b/lib/libUPnP/patches/0027-platinum-add-support-for-xbmc-specific-fields-datead.patch
new file mode 100644
index 0000000..ba7593f
--- /dev/null
+++ b/lib/libUPnP/patches/0027-platinum-add-support-for-xbmc-specific-fields-datead.patch
@@ -0,0 +1,284 @@
+From ac80794eedc6e240671ce3b60ecb4a24c58f84ab Mon Sep 17 00:00:00 2001
+From: montellese <montellese@xbmc.org>
+Date: Mon, 19 May 2014 20:56:25 +0200
+Subject: [PATCH 04/11] platinum: add support for xbmc specific fields
+ dateadded, rating, votes and artwork
+
+xbmc:dateadded to pass dateadded with items and not need to stat upnp resources for that
+xbmc:rating for number-based rating
+xbmc:votes for string-based votes number
+xbmc:artwork for a type-url-based mapping of artwork
+---
+ .../Source/Devices/MediaServer/PltDidl.cpp | 12 ++-
+ .../Platinum/Source/Devices/MediaServer/PltDidl.h | 11 +++
+ .../Source/Devices/MediaServer/PltMediaItem.cpp | 109 +++++++++++++++++++++
+ .../Source/Devices/MediaServer/PltMediaItem.h | 23 +++++
+ .../Devices/MediaServer/PltSyncMediaBrowser.h | 2 +-
+ 5 files changed, 155 insertions(+), 2 deletions(-)
+
+diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.cpp
+index 0758ad5..2bb6a04 100644
+--- a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.cpp
++++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.cpp
+@@ -47,11 +47,13 @@ NPT_SET_LOCAL_LOGGER("platinum.media.server.didl")
+ 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/\">";
++ " xmlns:dlna=\"urn:schemas-dlna-org:metadata-1-0/\""
++ " xmlns:xbmc=\"urn:schemas-xbmc-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/";
++const char* didl_namespace_xbmc = "urn:schemas-xbmc-org:metadata-1-0/";
+
+ /*----------------------------------------------------------------------
+ | PLT_Didl::ConvertFilterToMask
+@@ -160,6 +162,14 @@ PLT_Didl::ConvertFilterToMask(const NPT_String& filter)
+ mask |= PLT_FILTER_MASK_EPISODE_COUNT;
+ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_EPISODE_SEASON, len, true) == 0) {
+ mask |= PLT_FILTER_MASK_EPISODE_SEASON;
++ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_DATEADDED, len, true) == 0) {
++ mask |= PLT_FILTER_MASK_XBMC_DATEADDED;
++ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_RATING, len, true) == 0) {
++ mask |= PLT_FILTER_MASK_XBMC_RATING;
++ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_VOTES, len, true) == 0) {
++ mask |= PLT_FILTER_MASK_XBMC_VOTES;
++ } else if (NPT_String::CompareN(s+i, PLT_FILTER_FIELD_XBMC_ARTWORK, len, true) == 0) {
++ mask |= PLT_FILTER_MASK_XBMC_ARTWORK;
+ }
+
+ if (next_comma < 0) {
+diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.h
+index 2271162..0f7c892 100644
+--- a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.h
++++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltDidl.h
+@@ -95,6 +95,11 @@
+ #define PLT_FILTER_MASK_EPISODE_COUNT NPT_UINT64_C(0x0000001000000000)
+ #define PLT_FILTER_MASK_EPISODE_SEASON NPT_UINT64_C(0x0000002000000000)
+
++#define PLT_FILTER_MASK_XBMC_DATEADDED NPT_UINT64_C(0x0000100000000000)
++#define PLT_FILTER_MASK_XBMC_RATING NPT_UINT64_C(0x0000200000000000)
++#define PLT_FILTER_MASK_XBMC_VOTES NPT_UINT64_C(0x0000300000000000)
++#define PLT_FILTER_MASK_XBMC_ARTWORK NPT_UINT64_C(0x0000400000000000)
++
+ #define PLT_FILTER_FIELD_TITLE "dc:title"
+ #define PLT_FILTER_FIELD_CREATOR "dc:creator"
+ #define PLT_FILTER_FIELD_DATE "dc:date"
+@@ -139,11 +144,17 @@
+ #define PLT_FILTER_FIELD_EPISODE_COUNT "upnp:episodeCount"
+ #define PLT_FILTER_FIELD_EPISODE_SEASON "upnp:episodeSeason"
+
++#define PLT_FILTER_FIELD_XBMC_DATEADDED "xbmc:dateadded"
++#define PLT_FILTER_FIELD_XBMC_RATING "xbmc:rating"
++#define PLT_FILTER_FIELD_XBMC_VOTES "xbmc:votes"
++#define PLT_FILTER_FIELD_XBMC_ARTWORK "xbmc:artwork"
++
+ extern const char* didl_header;
+ extern const char* didl_footer;
+ extern const char* didl_namespace_dc;
+ extern const char* didl_namespace_upnp;
+ extern const char* didl_namespace_dlna;
++extern const char* didl_namespace_xbmc;
+
+ /*----------------------------------------------------------------------
+ | PLT_Didl
+diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp
+index a8855cc..5c2ec84 100644
+--- a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp
++++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.cpp
+@@ -110,6 +110,62 @@ PLT_PersonRoles::FromDidl(const NPT_Array<NPT_XmlElementNode*>& nodes)
+ }
+
+ /*----------------------------------------------------------------------
++| PLT_Artworks::Add
+++---------------------------------------------------------------------*/
++NPT_Result
++PLT_Artworks::Add(const NPT_String& type, const NPT_String& url)
++{
++ PLT_Artwork artwork;
++ artwork.type = type;
++ artwork.url = url;
++
++ return NPT_List<PLT_Artwork>::Add(artwork);
++}
++
++/*----------------------------------------------------------------------
++| PLT_Artworks::ToDidl
+++---------------------------------------------------------------------*/
++NPT_Result
++PLT_Artworks::ToDidl(NPT_String& didl, const NPT_String& tag)
++{
++ NPT_String tmp;
++ for (NPT_List<PLT_Artwork>::Iterator it =
++ NPT_List<PLT_Artwork>::GetFirstItem(); it; it++) {
++ if (it->type.IsEmpty()) continue;
++
++ tmp += "<xbmc:" + tag;
++ if (!it->type.IsEmpty()) {
++ tmp += " type=\"";
++ PLT_Didl::AppendXmlEscape(tmp, it->type);
++ tmp += "\"";
++ }
++ tmp += ">";
++ PLT_Didl::AppendXmlEscape(tmp, it->url);
++ tmp += "</xbmc:" + tag + ">";
++ }
++
++ didl += tmp;
++ return NPT_SUCCESS;
++}
++
++/*----------------------------------------------------------------------
++| PLT_Artworks::ToDidl
+++---------------------------------------------------------------------*/
++NPT_Result
++PLT_Artworks::FromDidl(const NPT_Array<NPT_XmlElementNode*>& nodes)
++{
++ for (NPT_Cardinal i=0; i<nodes.GetItemCount(); i++) {
++ PLT_Artwork artwork;
++ const NPT_String* url = nodes[i]->GetText();
++ const NPT_String* type = nodes[i]->GetAttribute("type");
++ if (type) artwork.type = *type;
++ if (url) artwork.url = *url;
++ NPT_CHECK(NPT_List<PLT_Artwork>::Add(artwork));
++ }
++ return NPT_SUCCESS;
++}
++
++/*----------------------------------------------------------------------
+ | PLT_MediaItemResource::PLT_MediaItemResource
+ +---------------------------------------------------------------------*/
+ PLT_MediaItemResource::PLT_MediaItemResource()
+@@ -200,6 +256,11 @@ PLT_MediaObject::Reset()
+
+ m_Resources.Clear();
+
++ m_XbmcInfo.date_added = "";
++ m_XbmcInfo.rating = 0.0f;
++ m_XbmcInfo.votes = "";
++ m_XbmcInfo.artwork.Clear();
++
+ m_Didl = "";
+
+ return NPT_SUCCESS;
+@@ -472,6 +533,32 @@ PLT_MediaObject::ToDidl(NPT_UInt64 mask, NPT_String& didl)
+ }
+ }
+
++ // xbmc dateadded
++ if ((mask & PLT_FILTER_MASK_XBMC_DATEADDED) && !m_XbmcInfo.date_added.IsEmpty()) {
++ didl += "<xbmc:dateadded>";
++ PLT_Didl::AppendXmlEscape(didl, m_XbmcInfo.date_added);
++ didl += "</xbmc:dateadded>";
++ }
++
++ // xbmc rating
++ if (mask & PLT_FILTER_MASK_XBMC_RATING) {
++ didl += "<xbmc:rating>";
++ didl += NPT_String::Format("%.1f", m_XbmcInfo.rating);
++ didl += "</xbmc:rating>";
++ }
++
++ // xbmc votes
++ if (mask & PLT_FILTER_MASK_XBMC_VOTES && !m_XbmcInfo.votes.IsEmpty()) {
++ didl += "<xbmc:votes>";
++ PLT_Didl::AppendXmlEscape(didl, m_XbmcInfo.votes);
++ didl += "</xbmc:votes>";
++ }
++
++ // xbmc artwork
++ if (mask & PLT_FILTER_MASK_XBMC_ARTWORK) {
++ m_XbmcInfo.artwork.ToDidl(didl, "artwork");
++ }
++
+ // class is required
+ didl += "<upnp:class";
+ if (!m_ObjectClass.friendly_name.IsEmpty()) {
+@@ -672,6 +759,28 @@ PLT_MediaObject::FromDidl(NPT_XmlElementNode* entry)
+ m_Resources.Add(resource);
+ }
+
++ PLT_XmlHelper::GetChildText(entry, "dateadded", m_XbmcInfo.date_added, didl_namespace_xbmc, 256);
++ // parse date and make sure it's valid
++ for (int format=0; format<=NPT_DateTime::FORMAT_RFC_1036; format++) {
++ NPT_DateTime date;
++ if (NPT_SUCCEEDED(date.FromString(m_XbmcInfo.date_added, (NPT_DateTime::Format)format))) {
++ parsed_date = date.ToString((NPT_DateTime::Format)format);
++ break;
++ }
++ }
++ m_XbmcInfo.date_added = parsed_date;
++
++ PLT_XmlHelper::GetChildText(entry, "rating", str, didl_namespace_xbmc);
++ NPT_Float floatValue;
++ if (NPT_FAILED(str.ToFloat(floatValue))) floatValue = 0.0;
++ m_XbmcInfo.rating = floatValue;
++
++ PLT_XmlHelper::GetChildText(entry, "votes", m_XbmcInfo.votes, didl_namespace_xbmc, 256);
++
++ children.Clear();
++ PLT_XmlHelper::GetChildren(entry, children, "artwork", didl_namespace_xbmc);
++ m_XbmcInfo.artwork.FromDidl(children);
++
+ // re serialize the entry didl as a we might need to pass it to a renderer
+ // we may have modified the tree to "fix" issues, so as not to break a renderer
+ // (don't write xml prefix as this didl could be part of a larger document)
+diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.h
+index 34a69b7..56291a7 100644
+--- a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.h
++++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltMediaItem.h
+@@ -151,6 +151,26 @@ typedef struct {
+ NPT_UInt32 episode_season;
+ } PLT_RecordedInfo;
+
++typedef struct {
++ NPT_String type;
++ NPT_String url;
++} PLT_Artwork;
++
++class PLT_Artworks : public NPT_List<PLT_Artwork>
++{
++public:
++ NPT_Result Add(const NPT_String& type, const NPT_String& url);
++ NPT_Result ToDidl(NPT_String& didl, const NPT_String& tag);
++ NPT_Result FromDidl(const NPT_Array<NPT_XmlElementNode*>& nodes);
++};
++
++typedef struct {
++ NPT_String date_added;
++ NPT_Float rating;
++ NPT_String votes;
++ PLT_Artworks artwork;
++} PLT_XbmcInfo;
++
+ /*----------------------------------------------------------------------
+ | PLT_MediaItemResource
+ +---------------------------------------------------------------------*/
+@@ -229,6 +249,9 @@ public:
+ /* resources related */
+ NPT_Array<PLT_MediaItemResource> m_Resources;
+
++ /* XBMC specific */
++ PLT_XbmcInfo m_XbmcInfo;
++
+ /* original DIDL for Control Points to pass to a renderer when invoking SetAVTransportURI */
+ NPT_String m_Didl;
+ };
+diff --git a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h
+index 3c14dff..ffdddda 100644
+--- a/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h
++++ b/lib/libUPnP/Platinum/Source/Devices/MediaServer/PltSyncMediaBrowser.h
+@@ -118,7 +118,7 @@ protected:
+ NPT_Int32 index,
+ NPT_Int32 count,
+ bool browse_metadata = false,
+- const char* filter = "dc:date,dc:description,upnp:longDescription,upnp:genre,res,res@duration,res@size,upnp:albumArtURI,upnp:rating,upnp:lastPlaybackPosition,upnp:lastPlaybackTime,upnp:playbackCount,upnp:originalTrackNumber,upnp:episodeNumber,upnp:programTitle,upnp:seriesTitle,upnp:album,upnp:artist,upnp:author,upnp:director,dc:publisher,searchable,childCount,dc:title,dc:creator,upnp:actor,res@resolution,upnp:episodeCount,upnp:episodeSeason", // explicitely specify res otherwise WMP won't return a URL!
++ const char* filter = "dc:date,dc:description,upnp:longDescription,upnp:genre,res,res@duration,res@size,upnp:albumArtURI,upnp:rating,upnp:lastPlaybackPosition,upnp:lastPlaybackTime,upnp:playbackCount,upnp:originalTrackNumber,upnp:episodeNumber,upnp:programTitle,upnp:seriesTitle,upnp:album,upnp:artist,upnp:author,upnp:director,dc:publisher,searchable,childCount,dc:title,dc:creator,upnp:actor,res@resolution,upnp:episodeCount,upnp:episodeSeason,xbmc:dateadded,xbmc:rating,xbmc:votes,xbmc:artwork", // explicitely specify res otherwise WMP won't return a URL!
+ const char* sort = "");
+ private:
+ NPT_Result Find(const char* ip, PLT_DeviceDataReference& device);
+--
+1.7.11.msysgit.0
+