/* * Copyright (C) 2009 Nokia Corporation. * Copyright (C) 2012 Intel Corporation * * Authors: Zeeshan Ali (Khattak) * * Krzesimir Nowak * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** * SECTION:gupnp-didl-lite-object * @short_description: DIDL-Lite Object * * #GUPnPDIDLLiteObject respresent a DIDL-Lite object element. */ #include #include "gupnp-didl-lite-object.h" #include "gupnp-didl-lite-object-private.h" #include "gupnp-didl-lite-resource-private.h" #include "gupnp-didl-lite-descriptor-private.h" #include "gupnp-didl-lite-container.h" #include "gupnp-didl-lite-item.h" #include "gupnp-didl-lite-contributor-private.h" #include "xml-util.h" #include "fragment-util.h" #include "xsd-data.h" G_DEFINE_ABSTRACT_TYPE (GUPnPDIDLLiteObject, gupnp_didl_lite_object, G_TYPE_OBJECT); struct _GUPnPDIDLLiteObjectPrivate { xmlNode *xml_node; GUPnPAVXMLDoc *xml_doc; xmlNs *upnp_ns; xmlNs *dc_ns; xmlNs *dlna_ns; xmlNs *pv_ns; }; static XSDData *didl_lite_xsd; enum { PROP_0, PROP_XML_NODE, PROP_XML_DOC, PROP_UPNP_NAMESPACE, PROP_DC_NAMESPACE, PROP_DLNA_NAMESPACE, PROP_PV_NAMESPACE, PROP_ID, PROP_PARENT_ID, PROP_RESTRICTED, PROP_TITLE, PROP_UPNP_CLASS, PROP_CREATOR, PROP_ARTIST, PROP_AUTHOR, PROP_GENRE, PROP_WRITE_STATUS, PROP_ALBUM, PROP_ALBUM_ART, PROP_DESCRIPTION, PROP_DATE, PROP_TRACK_NUMBER, PROP_DLNA_MANAGED, PROP_UPDATE_ID }; static int is_non_transcoded_resource (GUPnPDIDLLiteResource *resource) { GUPnPProtocolInfo *info; info = gupnp_didl_lite_resource_get_protocol_info (resource); if (G_UNLIKELY (info == NULL)) return -1; return gupnp_protocol_info_get_dlna_conversion (info) & GUPNP_DLNA_CONVERSION_TRANSCODED; } static void gupnp_didl_lite_object_init (GUPnPDIDLLiteObject *object) { object->priv = G_TYPE_INSTANCE_GET_PRIVATE (object, GUPNP_TYPE_DIDL_LITE_OBJECT, GUPnPDIDLLiteObjectPrivate); } static void gupnp_didl_lite_object_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec) { GUPnPDIDLLiteObject *didl_object; didl_object = GUPNP_DIDL_LITE_OBJECT (object); switch (property_id) { case PROP_XML_NODE: didl_object->priv->xml_node = g_value_get_pointer (value); break; case PROP_XML_DOC: didl_object->priv->xml_doc = g_value_dup_boxed (value); break; case PROP_UPNP_NAMESPACE: didl_object->priv->upnp_ns = g_value_get_pointer (value); break; case PROP_DC_NAMESPACE: didl_object->priv->dc_ns = g_value_get_pointer (value); break; case PROP_DLNA_NAMESPACE: didl_object->priv->dlna_ns = g_value_get_pointer (value); break; case PROP_PV_NAMESPACE: didl_object->priv->pv_ns = g_value_get_pointer (value); break; case PROP_ID: gupnp_didl_lite_object_set_id (didl_object, g_value_get_string (value)); break; case PROP_PARENT_ID: gupnp_didl_lite_object_set_parent_id (didl_object, g_value_get_string (value)); break; case PROP_RESTRICTED: gupnp_didl_lite_object_set_restricted (didl_object, g_value_get_boolean (value)); break; case PROP_TITLE: gupnp_didl_lite_object_set_title (didl_object, g_value_get_string (value)); break; case PROP_UPNP_CLASS: gupnp_didl_lite_object_set_upnp_class (didl_object, g_value_get_string (value)); break; case PROP_CREATOR: gupnp_didl_lite_object_set_creator (didl_object, g_value_get_string (value)); break; case PROP_ARTIST: gupnp_didl_lite_object_set_artist (didl_object, g_value_get_string (value)); break; case PROP_AUTHOR: gupnp_didl_lite_object_set_author (didl_object, g_value_get_string (value)); break; case PROP_GENRE: gupnp_didl_lite_object_set_genre (didl_object, g_value_get_string (value)); break; case PROP_WRITE_STATUS: gupnp_didl_lite_object_set_write_status (didl_object, g_value_get_string (value)); break; case PROP_ALBUM: gupnp_didl_lite_object_set_album (didl_object, g_value_get_string (value)); break; case PROP_ALBUM_ART: gupnp_didl_lite_object_set_album_art (didl_object, g_value_get_string (value)); break; case PROP_DESCRIPTION: gupnp_didl_lite_object_set_description (didl_object, g_value_get_string (value)); break; case PROP_DATE: gupnp_didl_lite_object_set_date (didl_object, g_value_get_string (value)); break; case PROP_TRACK_NUMBER: gupnp_didl_lite_object_set_track_number (didl_object, g_value_get_int (value)); break; case PROP_DLNA_MANAGED: gupnp_didl_lite_object_set_dlna_managed (didl_object, g_value_get_flags (value)); break; case PROP_UPDATE_ID: gupnp_didl_lite_object_set_update_id (didl_object, g_value_get_uint (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gupnp_didl_lite_object_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec) { GUPnPDIDLLiteObject *didl_object; didl_object = GUPNP_DIDL_LITE_OBJECT (object); switch (property_id) { case PROP_XML_NODE: g_value_set_pointer (value, gupnp_didl_lite_object_get_xml_node (didl_object)); break; case PROP_UPNP_NAMESPACE: g_value_set_pointer (value, gupnp_didl_lite_object_get_upnp_namespace (didl_object)); break; case PROP_DC_NAMESPACE: g_value_set_pointer (value, gupnp_didl_lite_object_get_dc_namespace (didl_object)); break; case PROP_DLNA_NAMESPACE: g_value_set_pointer (value, gupnp_didl_lite_object_get_dlna_namespace (didl_object)); break; case PROP_PV_NAMESPACE: g_value_set_pointer (value, gupnp_didl_lite_object_get_pv_namespace (didl_object)); break; case PROP_ID: g_value_set_string (value, gupnp_didl_lite_object_get_id (didl_object)); break; case PROP_PARENT_ID: g_value_set_string (value, gupnp_didl_lite_object_get_parent_id (didl_object)); break; case PROP_RESTRICTED: g_value_set_boolean (value, gupnp_didl_lite_object_get_restricted (didl_object)); break; case PROP_TITLE: g_value_set_string (value, gupnp_didl_lite_object_get_title (didl_object)); break; case PROP_UPNP_CLASS: g_value_set_string (value, gupnp_didl_lite_object_get_upnp_class (didl_object)); break; case PROP_CREATOR: g_value_set_string (value, gupnp_didl_lite_object_get_creator (didl_object)); break; case PROP_ARTIST: g_value_set_string (value, gupnp_didl_lite_object_get_artist (didl_object)); break; case PROP_AUTHOR: g_value_set_string (value, gupnp_didl_lite_object_get_author (didl_object)); break; case PROP_GENRE: g_value_set_string (value, gupnp_didl_lite_object_get_genre (didl_object)); break; case PROP_WRITE_STATUS: g_value_set_string (value, gupnp_didl_lite_object_get_write_status (didl_object)); break; case PROP_ALBUM: g_value_set_string (value, gupnp_didl_lite_object_get_album (didl_object)); break; case PROP_ALBUM_ART: g_value_set_string (value, gupnp_didl_lite_object_get_album_art (didl_object)); break; case PROP_DESCRIPTION: g_value_set_string (value, gupnp_didl_lite_object_get_description (didl_object)); break; case PROP_DATE: g_value_set_string (value, gupnp_didl_lite_object_get_date (didl_object)); break; case PROP_TRACK_NUMBER: g_value_set_int (value, gupnp_didl_lite_object_get_track_number (didl_object)); break; case PROP_DLNA_MANAGED: g_value_set_flags (value, gupnp_didl_lite_object_get_dlna_managed (didl_object)); break; case PROP_UPDATE_ID: g_value_set_uint (value, gupnp_didl_lite_object_get_update_id (didl_object)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } } static void gupnp_didl_lite_object_dispose (GObject *object) { GObjectClass *object_class; GUPnPDIDLLiteObjectPrivate *priv; priv = GUPNP_DIDL_LITE_OBJECT (object)->priv; g_clear_pointer (&priv->xml_doc, xml_doc_unref); object_class = G_OBJECT_CLASS (gupnp_didl_lite_object_parent_class); object_class->dispose (object); } static void gupnp_didl_lite_object_class_init (GUPnPDIDLLiteObjectClass *klass) { GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->set_property = gupnp_didl_lite_object_set_property; object_class->get_property = gupnp_didl_lite_object_get_property; object_class->dispose = gupnp_didl_lite_object_dispose; g_type_class_add_private (klass, sizeof (GUPnPDIDLLiteObjectPrivate)); /** * GUPnPDIDLLiteObject:xml-node: * * The pointer to object node in XML document. **/ g_object_class_install_property (object_class, PROP_XML_NODE, g_param_spec_pointer ("xml-node", "XMLNode", "The pointer to object node in XML" " document.", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:xml-doc: * * The reference to XML document containing this object. * * Internal property. * * Stability: Private **/ g_object_class_install_property (object_class, PROP_XML_DOC, g_param_spec_boxed ("xml-doc", "XMLDoc", "The reference to XML document" " containing this object.", xml_doc_get_type (), G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:upnp-namespace: * * Pointer to the UPnP namespace registered with the XML document * containing this object. * **/ g_object_class_install_property (object_class, PROP_UPNP_NAMESPACE, g_param_spec_pointer ("upnp-namespace", "XML namespace", "Pointer to the UPnP XML namespace " "registered with the XML document " "containing this object.", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:dc-namespace: * * Pointer to the DublinCore namespace registered with the XML document * containing this object. * **/ g_object_class_install_property (object_class, PROP_DC_NAMESPACE, g_param_spec_pointer ("dc-namespace", "XML namespace", "Pointer to the Dublin Core XML " "namespace registered with the XML " "document containing this object.", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:dlna-namespace: * * Pointer to the DLNA metadata namespace registered with the XML * document containing this object. * **/ g_object_class_install_property (object_class, PROP_DLNA_NAMESPACE, g_param_spec_pointer ("dlna-namespace", "XML namespace", "Pointer to the DLNA metadata namespace " "registered with the XML document " "containing this object.", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:pv-namespace: * * Pointer to the PV metadata namespace registered with the XML * document containing this object. * **/ g_object_class_install_property (object_class, PROP_PV_NAMESPACE, g_param_spec_pointer ("pv-namespace", "XML namespace", "Pointer to the PV metadata namespace " "registered with the XML document " "containing this object.", G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); /** * GUPnPDIDLLiteObject:id: * * The ID of this object. **/ g_object_class_install_property (object_class, PROP_ID, g_param_spec_string ("id", "ID", "The ID of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:parent-id: * * The ID of the parent container of this object. **/ g_object_class_install_property (object_class, PROP_PARENT_ID, g_param_spec_string ("parent-id", "ParentID", "The ID of the parent container of" " this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:restricted: * * Whether this object is restricted. **/ g_object_class_install_property (object_class, PROP_RESTRICTED, g_param_spec_boolean ("restricted", "Restricted", "Whether this object is restricted.", FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:title: * * The title of this object. **/ g_object_class_install_property (object_class, PROP_TITLE, g_param_spec_string ("title", "Title", "The title of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:upnp-class: * * The UPnP class of this object. **/ g_object_class_install_property (object_class, PROP_UPNP_CLASS, g_param_spec_string ("upnp-class", "UPnPClassName", "The UPnP class of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:creator: * * The creator of this object. * **/ g_object_class_install_property (object_class, PROP_CREATOR, g_param_spec_string ("creator", "Creator", "The creator of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:artist: * * The artist of this object. * * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_artists and * #gupnp_didl_lite_object_add_artist instead since unlike this * property, they are capable of dealing with multiple artist nodes. **/ g_object_class_install_property (object_class, PROP_ARTIST, g_param_spec_string ("artist", "Artist", "The artist of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:author: * * The author of this object. * * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_authors and * #gupnp_didl_lite_object_add_author instead since unlike this * property, they are capable of dealing with multiple author nodes. **/ g_object_class_install_property (object_class, PROP_AUTHOR, g_param_spec_string ("author", "Author", "The author of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:genre: * * The genre of this object. **/ g_object_class_install_property (object_class, PROP_GENRE, g_param_spec_string ("genre", "Genre", "The genre of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:write-status: * * The write status of this object. **/ g_object_class_install_property (object_class, PROP_WRITE_STATUS, g_param_spec_string ("write-status", "WriteStatus", "The write status of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:album: * * The album of this object. **/ g_object_class_install_property (object_class, PROP_ALBUM, g_param_spec_string ("album", "Album", "The album of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:album-art: * * The URI to album art of this object. **/ g_object_class_install_property (object_class, PROP_ALBUM_ART, g_param_spec_string ("album-art", "AlbumArt", "The URI to album art of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:description: * * The description of this object. **/ g_object_class_install_property (object_class, PROP_DESCRIPTION, g_param_spec_string ("description", "Description", "The description of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:date: * * The date of this object. **/ g_object_class_install_property (object_class, PROP_DATE, g_param_spec_string ("date", "Date", "The date of this object.", NULL, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:track-number: * * The original track number of this object. **/ g_object_class_install_property (object_class, PROP_TRACK_NUMBER, g_param_spec_int ("track-number", "TrackNumber", "The original track number of this object.", -1, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:dlna-managed: * * The 'dlna:dlnaManaged' attribute. **/ g_object_class_install_property (object_class, PROP_DLNA_MANAGED, g_param_spec_flags ("dlna-managed", "DLNAManaged", "The 'dlna:dlnaManaged' attribute", GUPNP_TYPE_OCM_FLAGS, GUPNP_OCM_FLAGS_NONE, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); /** * GUPnPDIDLLiteObject:update-id: * * Update ID of this object. **/ g_object_class_install_property (object_class, PROP_UPDATE_ID, g_param_spec_uint ("update-id", "UpdateID", "Update ID of this object.", 0, G_MAXUINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); if (didl_lite_xsd == NULL) didl_lite_xsd = fragment_util_get_didl_lite_xsd_data (); } static gboolean is_resource_compatible (GUPnPDIDLLiteResource *resource, char **protocols) { gboolean ret = FALSE; char **it; for (it = protocols; *it != NULL && !ret; it++) { GUPnPProtocolInfo *info; GUPnPProtocolInfo *res_info; info = gupnp_protocol_info_new_from_string (*it, NULL); if (info == NULL) continue; res_info = gupnp_didl_lite_resource_get_protocol_info (resource); if (res_info == NULL) continue; ret = gupnp_protocol_info_is_compatible (info, res_info); g_object_unref (info); } return ret; } static GList * get_contributor_list_by_name (GUPnPDIDLLiteObject *object, const char *name) { GList *contributors = NULL; GList *ret = NULL; GList *l; contributors = gupnp_didl_lite_object_get_properties (object, name); for (l = contributors; l; l = l->next) { GUPnPDIDLLiteContributor *contributor; xmlNode *contributor_node; contributor_node = (xmlNode *) l->data; if (!contributor_node->children) continue; contributor = gupnp_didl_lite_contributor_new_from_xml (contributor_node, object->priv->xml_doc); ret = g_list_append (ret, contributor); } g_list_free (contributors); return ret; } static char * get_contributors_xml_string_by_name (GUPnPDIDLLiteObject *object, const char *name) { GList *contributors = NULL; char *ret = NULL; GList *l; xmlBuffer *buffer; contributors = gupnp_didl_lite_object_get_properties (object, name); if (contributors == NULL) return NULL; buffer = xmlBufferCreate (); for (l = contributors; l; l = l->next) { xmlNode *node; node = (xmlNode *) l->data; if (!node->children) continue; xmlNodeDump (buffer, object->priv->xml_doc->doc, node, 0, 0); } ret = g_strndup ((char *) xmlBufferContent (buffer), xmlBufferLength (buffer)); xmlBufferFree (buffer); g_list_free (contributors); return ret; } static void unset_contributors_by_name (GUPnPDIDLLiteObject *object, const char *name) { GList *contributors = NULL; GList *l; contributors = gupnp_didl_lite_object_get_properties (object, name); if (contributors == NULL) return; for (l = contributors; l; l = l->next) { xmlNode *node; node = (xmlNode *) l->data; if (!node->children) continue; xmlUnlinkNode (node); xmlFreeNode (node); } g_list_free (contributors); return; } /** * gupnp_didl_lite_object_new_from_xml: * @xml_node: The pointer to 'res' node in XML document * @xml_doc: The reference to XML document containing this object * @upnp_ns: The pointer to 'upnp' namespace in XML document * @dc_ns: The pointer to 'dc' namespace in XML document * @dlna_ns: The pointer to 'dlna' namespace in XML document * @pv_ns: The pointer to 'pv' namespace in XML document * * Creates a new #GUPnPDIDLLiteObject for the @xml_node. * * Return value: A new #GUPnPDIDLLiteObject object. Unref after usage. **/ GUPnPDIDLLiteObject * gupnp_didl_lite_object_new_from_xml (xmlNode *xml_node, GUPnPAVXMLDoc *xml_doc, xmlNs *upnp_ns, xmlNs *dc_ns, xmlNs *dlna_ns, xmlNs *pv_ns) { g_return_val_if_fail (xml_node != NULL, NULL); g_return_val_if_fail (xml_node->name != NULL, NULL); if (g_ascii_strcasecmp ((char *) xml_node->name, "container") == 0) return g_object_new (GUPNP_TYPE_DIDL_LITE_CONTAINER, "xml-node", xml_node, "xml-doc", xml_doc, "upnp-namespace", upnp_ns, "dc-namespace", dc_ns, "dlna-namespace", dlna_ns, "pv-namespace", pv_ns, NULL); else if (g_ascii_strcasecmp ((char *) xml_node->name, "item") == 0) return g_object_new (GUPNP_TYPE_DIDL_LITE_ITEM, "xml-node", xml_node, "xml-doc", xml_doc, "upnp-namespace", upnp_ns, "dc-namespace", dc_ns, "dlna-namespace", dlna_ns, "pv-namespace", pv_ns, NULL); else return NULL; } /** * gupnp_didl_lite_object_get_gupnp_xml_doc: * @object: The #GUPnPDIDLLiteObject * * Get the pointer to the XML document containing this object. * * Returns: (transfer none): The pointer to the XML document containing this * object. **/ GUPnPAVXMLDoc * gupnp_didl_lite_object_get_gupnp_xml_doc (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return object->priv->xml_doc; } /** * gupnp_didl_lite_object_get_xml_node: * @object: The #GUPnPDIDLLiteObject * * Get the pointer to object node in XML document. * * Returns: (transfer none): The pointer to object node in XML document. **/ xmlNode * gupnp_didl_lite_object_get_xml_node (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return object->priv->xml_node; } /** * gupnp_didl_lite_object_get_upnp_namespace: * @object: The #GUPnPDIDLLiteObject * * Get the pointer to the UPnP namespace registered with the XML document. * * Returns: (transfer none): The pointer to UPnP namespace in XML document. **/ xmlNsPtr gupnp_didl_lite_object_get_upnp_namespace (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_ns (object->priv->xml_doc->doc, GUPNP_XML_NAMESPACE_UPNP, &(object->priv->upnp_ns)); } /** * gupnp_didl_lite_object_get_dc_namespace: * @object: The #GUPnPDIDLLiteObject * * Get the pointer to the DublinCore namespace registered with the XML document * containing this object. * * Returns: (transfer none): The pointer to DublinCore namespace in XML document. **/ xmlNsPtr gupnp_didl_lite_object_get_dc_namespace (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_ns (object->priv->xml_doc->doc, GUPNP_XML_NAMESPACE_DC, &(object->priv->dc_ns)); } /** * gupnp_didl_lite_object_get_upnp_class: * @object: The #GUPnPDIDLLiteObject * * Get the UPnP class of the @object. * * Return value: The class of @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_upnp_class (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "class"); } /** * gupnp_didl_lite_object_get_dlna_namespace: * @object: The #GUPnPDIDLLiteObject * * Get the pointer to the DLNA metadata namespace registered with the XML * document containing this object. * * Returns: (transfer none): The pointer to DLNA namespace in XML document. **/ xmlNsPtr gupnp_didl_lite_object_get_dlna_namespace (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_ns (object->priv->xml_doc->doc, GUPNP_XML_NAMESPACE_DLNA, &(object->priv->dlna_ns)); } /** * gupnp_didl_lite_object_get_pv_namespace: * @object: The #GUPnPDIDLLiteObject * * Get the pointer to the PV metadata namespace registered with the XML * document containing this object. * * Returns: (transfer none): The pointer to PV namespace in XML document. **/ xmlNsPtr gupnp_didl_lite_object_get_pv_namespace (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_ns (object->priv->xml_doc->doc, GUPNP_XML_NAMESPACE_PV, &(object->priv->pv_ns)); } /** * gupnp_didl_lite_object_get_id: * @object: #GUPnPDIDLLiteObject * * Get the ID of the @object. * * Return value: The ID of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_id (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_attribute_content (object->priv->xml_node, "id"); } /** * gupnp_didl_lite_object_get_parent_id: * @object: #GUPnPDIDLLiteObject * * Get the ID of the parent of the @object. * * Return value: The ID of parent of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_parent_id (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_attribute_content (object->priv->xml_node, "parentID"); } /** * gupnp_didl_lite_object_get_properties: * @object: #GUPnPDIDLLiteObject * @name: name of the properties * * Use this function to retreive property nodes by name. * * Return value: (element-type xmlNode*) (transfer container): The list of * property nodes by the name @property_name belonging to @object, or %NULL. * #g_list_free the returned list after usage but do not modify the contents. **/ GList * gupnp_didl_lite_object_get_properties (GUPnPDIDLLiteObject *object, const char *name) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); g_return_val_if_fail (name != NULL, NULL); return xml_util_get_child_elements_by_name (object->priv->xml_node, name); } /** * gupnp_didl_lite_object_is_restricted_set: * @object: #GUPnPDIDLLiteObject * * Whehter the restricted attribute exists on @object * * Return value: #TRUE if restricted exists, #FALSE otherwise. **/ gboolean gupnp_didl_lite_object_is_restricted_set (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (object != NULL, FALSE); g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), FALSE); return xml_util_get_attribute_content (object->priv->xml_node, "restricted") != NULL; } /** * gupnp_didl_lite_object_get_restricted: * @object: #GUPnPDIDLLiteObject * * Whether the @object is restricted or not. * * Return value: #TRUE if @object is restricted. **/ gboolean gupnp_didl_lite_object_get_restricted (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), FALSE); return xml_util_get_boolean_attribute (object->priv->xml_node, "restricted"); } /** * gupnp_didl_lite_object_get_title: * @object: #GUPnPDIDLLiteObject * * Get the title of the @object. * * Return value: The title of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_title (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "title"); } /** * gupnp_didl_lite_object_get_creator: * @object: #GUPnPDIDLLiteObject * * Get the creator of the @object. * * Return value: The creator of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_creator (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "creator"); } /** * gupnp_didl_lite_object_get_creators: * @object: #GUPnPDIDLLiteObject * * Get the creators of the @object. * * Returns: (element-type GUPnPDIDLLiteContributor*) (transfer full): The list * of creators belonging to @object, or %NULL. * #g_list_free the returned list after usage and unref each object in it. **/ GList * gupnp_didl_lite_object_get_creators (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return get_contributor_list_by_name (object, "creator"); } /** * gupnp_didl_lite_object_get_artist: * @object: #GUPnPDIDLLiteObject * * Get the artist of the @object. If role is not %NULL, it is set to the role * of the artist if available. * * Return value: The artist of the @object, or %NULL. * * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_artists instead. **/ const char * gupnp_didl_lite_object_get_artist (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "artist"); } /** * gupnp_didl_lite_object_get_artists: * @object: #GUPnPDIDLLiteObject * * Get the artists of the @object. * * Returns: (element-type GUPnPDIDLLiteContributor*) (transfer full): The list * of artists belonging to @object, or %NULL. * #g_list_free the returned list after usage and unref each object in it. **/ GList * gupnp_didl_lite_object_get_artists (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return get_contributor_list_by_name (object, "artist"); } /** * gupnp_didl_lite_object_get_author: * @object: #GUPnPDIDLLiteObject * * Get the author of the @object. * * Return value: The author of the @object, or %NULL. * * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_get_authors instead. **/ const char * gupnp_didl_lite_object_get_author (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "author"); } /** * gupnp_didl_lite_object_get_authors: * @object: #GUPnPDIDLLiteObject * * Get the authors of the @object. * * Returns: (element-type GUPnPDIDLLiteContributor*) (transfer full): The list * of authors belonging to @object, or %NULL. * #g_list_free the returned list after usage and unref each object in it. **/ GList * gupnp_didl_lite_object_get_authors (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return get_contributor_list_by_name (object, "author"); } /** * gupnp_didl_lite_object_get_descriptors: * @object: #GUPnPDIDLLiteObject * * Get the descriptors of the @object. * * Returns: (element-type GUPnPDIDLLiteDescriptor*) (transfer full): The list of * descriptors belonging to @object, or %NULL. * #g_list_free the returned list after usage and unref each object in it. **/ GList * gupnp_didl_lite_object_get_descriptors (GUPnPDIDLLiteObject *object) { GList *descriptors = NULL; GList *ret = NULL; GList *l; g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); descriptors = gupnp_didl_lite_object_get_properties (object, "desc"); for (l = descriptors; l; l = l->next) { GUPnPDIDLLiteDescriptor *descriptor; xmlNode *descriptor_node; descriptor_node = (xmlNode *) l->data; descriptor = gupnp_didl_lite_descriptor_new_from_xml (descriptor_node, object->priv->xml_doc); ret = g_list_append (ret, descriptor); } g_list_free (descriptors); return ret; } /** * gupnp_didl_lite_object_get_genre: * @object: #GUPnPDIDLLiteObject * * Get the genre of the @object. * * Return value: The genre of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_genre (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "genre"); } /** * gupnp_didl_lite_object_get_write_status: * @object: #GUPnPDIDLLiteObject * * Get the write status of the @object. * * Return value: The write status of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_write_status (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "writeStatus"); } /** * gupnp_didl_lite_object_get_album: * @object: #GUPnPDIDLLiteObject * * Get the album of the @object. * * Return value: The album of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_album (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "album"); } /** * gupnp_didl_lite_object_get_album_art: * @object: #GUPnPDIDLLiteObject * * Get the URI to album art of the @object. * * Return value: The URI to album art of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_album_art (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "albumArtURI"); } /** * gupnp_didl_lite_object_get_description: * @object: #GUPnPDIDLLiteObject * * Get the description of the @object. * * Return value: The description of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_description (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "description"); } /** * gupnp_didl_lite_object_get_date: * @object: #GUPnPDIDLLiteObject * * Get the date of the @object. * * Return value: The date of the @object, or %NULL. **/ const char * gupnp_didl_lite_object_get_date (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_element_content (object->priv->xml_node, "date"); } /** * gupnp_didl_lite_object_get_track_number: * @object: #GUPnPDIDLLiteObject * * Get the original track number of the @object. * * Return value: The original track number of the @object, or -1. **/ int gupnp_didl_lite_object_get_track_number (GUPnPDIDLLiteObject *object) { const char *str; g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), -1); str = xml_util_get_child_element_content (object->priv->xml_node, "originalTrackNumber"); if (str == NULL) return -1; return atoi (str); } /** * gupnp_didl_lite_object_get_dlna_managed: * @object: #GUPnPDIDLLiteObject * * Get the 'dlna:dlnaManaged' attribute of the @object. * * Return value: The 'dlna:dlnaManaged' attribute of the @object. **/ GUPnPOCMFlags gupnp_didl_lite_object_get_dlna_managed (GUPnPDIDLLiteObject *object) { const char *str; GUPnPOCMFlags dlna_managed; g_return_val_if_fail (object != NULL, GUPNP_OCM_FLAGS_NONE); g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), GUPNP_OCM_FLAGS_NONE); str = xml_util_get_attribute_content (object->priv->xml_node, "dlnaManaged"); if (str == NULL) return GUPNP_OCM_FLAGS_NONE; sscanf (str, "%08x", &dlna_managed); return dlna_managed; } /** * gupnp_didl_lite_object_get_update_id: * @object: #GUPnPDIDLLiteObject * * Get the update ID of the @object. * * Return value: The update ID of the @object. **/ guint gupnp_didl_lite_object_get_update_id (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (object != NULL, 0); g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), 0); return xml_util_get_uint_child_element (object->priv->xml_node, "objectUpdateID", 0); } /** * gupnp_didl_lite_object_update_id_is_set: * @object: #GUPnPDIDLLiteObject * * Get whether the update ID of the @object is set. * * Return value: %TRUE if update ID is set, otherwise %FALSE **/ gboolean gupnp_didl_lite_object_update_id_is_set (GUPnPDIDLLiteObject *object) { const char *content; g_return_val_if_fail (object != NULL, FALSE); g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), FALSE); content = xml_util_get_child_element_content (object->priv->xml_node, "objectUpdateID"); return content != NULL; } /** * gupnp_didl_lite_object_get_resources: * @object: #GUPnPDIDLLiteObject * * Use this function to retreive resources from the @object. * * Return value: (element-type GUPnPDIDLLiteResource*) (transfer full): The list * of resources belonging to @object, or %NULL. #g_list_free the * returned list after usage and unref each resource in it. **/ GList * gupnp_didl_lite_object_get_resources (GUPnPDIDLLiteObject *object) { GList *resources = NULL; GList *res = NULL; GList *ret = NULL; g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); resources = gupnp_didl_lite_object_get_properties (object, "res"); for (res = resources; res; res = res->next) { GUPnPDIDLLiteResource *resource; xmlNode *res_node; res_node = (xmlNode *) res->data; /* Create a resource struct out of DIDLLite XML */ resource = gupnp_didl_lite_resource_new_from_xml (res_node, object->priv->xml_doc, object->priv->dlna_ns, object->priv->pv_ns); ret = g_list_append (ret, resource); } g_list_free (resources); return ret; } /** * gupnp_didl_lite_object_get_compat_resource: * @object: #GUPnPDIDLLiteObject * @sink_protocol_info: The SinkProtocolInfo string from MediaRenderer * @lenient: Enable lenient mode * * Use this function to get a resource from the @object that is compatible with * any of the protocols specified in the @sink_protocol_info. The value of * @sink_protocol_info will typically be acquired from 'Sink' argument of * 'GetProtocolInfo' action or 'SinkProtocolInfo' state-variable of a * ConnectionManager service. * * If @lenient is #TRUE, the first resource in the list is returned instead of * %NULL if none of resources and protocols are found to be compatible. * * Returns: (transfer full): The resource belonging to @object that is comaptible with * any of the protocols specified in @sink_protocol_info, or %NULL. Unref after * usage. **/ GUPnPDIDLLiteResource * gupnp_didl_lite_object_get_compat_resource (GUPnPDIDLLiteObject *object, const char *sink_protocol_info, gboolean lenient) { GUPnPDIDLLiteResource *resource = NULL; GList *resources = NULL; GList *compat_resources = NULL; GList *res; char **protocols = NULL; g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); g_return_val_if_fail (sink_protocol_info != NULL, NULL); resources = gupnp_didl_lite_object_get_resources (object); if (resources == NULL) return NULL; protocols = g_strsplit (sink_protocol_info, ",", -1); for (res = resources; res != NULL; res = res->next) { resource = (GUPnPDIDLLiteResource *) res->data; if (is_resource_compatible (resource, protocols)) compat_resources = g_list_append (compat_resources, resource); } g_strfreev (protocols); protocols = NULL; resource = NULL; if (compat_resources != NULL) { /* Try to find non-transcoded resource */ res = g_list_find_custom (compat_resources, NULL, (GCompareFunc) is_non_transcoded_resource); if (res != NULL) resource = (GUPnPDIDLLiteResource *) res->data; else /* Just use the first compatible resource */ resource = (GUPnPDIDLLiteResource *) compat_resources->data; } else if (lenient) /* Just use the first resource */ resource = (GUPnPDIDLLiteResource *) resources->data; /* Unref all resources except for the one we just took */ for (res = resources; res; res = res->next) if (res->data != resource) g_object_unref (res->data); g_list_free (resources); g_list_free (compat_resources); return resource; } /** * gupnp_didl_lite_object_set_upnp_class: * @object: The #GUPnPDIDLLiteObject * @upnp_class: The UPnP class as string. * * Set the UPnP class of the @object to @upnp_class. **/ void gupnp_didl_lite_object_set_upnp_class (GUPnPDIDLLiteObject *object, const char *upnp_class) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_UPNP, &(object->priv->upnp_ns), object->priv->xml_doc->doc, "class", upnp_class); g_object_notify (G_OBJECT (object), "upnp-class"); } /** * gupnp_didl_lite_object_set_id: * @object: #GUPnPDIDLLiteObject * @id: The ID * * Set the ID of the @object to @id. **/ void gupnp_didl_lite_object_set_id (GUPnPDIDLLiteObject *object, const char *id) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xmlSetProp (object->priv->xml_node, (unsigned char *) "id", (unsigned char *) id); g_object_notify (G_OBJECT (object), "id"); } /** * gupnp_didl_lite_object_set_parent_id: * @object: #GUPnPDIDLLiteObject * @parent_id: The parent ID * * Set the ID of the parent of the @object to @parent_id. **/ void gupnp_didl_lite_object_set_parent_id (GUPnPDIDLLiteObject *object, const char *parent_id) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xmlSetProp (object->priv->xml_node, (unsigned char *) "parentID", (unsigned char *) parent_id); g_object_notify (G_OBJECT (object), "parent-id"); } /** * gupnp_didl_lite_object_set_restricted: * @object: #GUPnPDIDLLiteObject * @restricted: The restricted status * * Set the restricted status of @object to @restricted. **/ void gupnp_didl_lite_object_set_restricted (GUPnPDIDLLiteObject *object, gboolean restricted) { const char *str; g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); if (restricted) str = "1"; else str = "0"; xmlSetProp (object->priv->xml_node, (unsigned char *) "restricted", (unsigned char *) str); g_object_notify (G_OBJECT (object), "restricted"); } /** * gupnp_didl_lite_object_set_title: * @object: #GUPnPDIDLLiteObject * @title: The title * * Set the title of the @object to @title. **/ void gupnp_didl_lite_object_set_title (GUPnPDIDLLiteObject *object, const char *title) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_DC, &(object->priv->dc_ns), object->priv->xml_doc->doc, "title", title); g_object_notify (G_OBJECT (object), "title"); } /** * gupnp_didl_lite_object_set_creator: * @object: #GUPnPDIDLLiteObject * @creator: The creator * * Set the creator of the @object to @creator. **/ void gupnp_didl_lite_object_set_creator (GUPnPDIDLLiteObject *object, const char *creator) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_DC, &(object->priv->dc_ns), object->priv->xml_doc->doc, "creator", creator); g_object_notify (G_OBJECT (object), "creator"); } /** * gupnp_didl_lite_object_add_creator: * @object: The #GUPnPDIDLLiteObject * * Add a new creator node to the @object and return the associated * #GUPnPDIDLLiteContributor object. * * Returns: (transfer full): A new #GUPnPDIDLLiteContributor object. Unref after usage. **/ GUPnPDIDLLiteContributor * gupnp_didl_lite_object_add_creator (GUPnPDIDLLiteObject *object) { xmlNode *res_node; g_return_val_if_fail (object != NULL, NULL); g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); res_node = xmlNewChild (object->priv->xml_node, object->priv->dc_ns, (unsigned char *) "creator", NULL); return gupnp_didl_lite_contributor_new_from_xml (res_node, object->priv->xml_doc); } /** * gupnp_didl_lite_object_set_artist: * @object: The #GUPnPDIDLLiteObject * @artist: The Artist * * Set the Artist of the @object to @artist. * * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_add_artist instead. **/ void gupnp_didl_lite_object_set_artist (GUPnPDIDLLiteObject *object, const char *artist) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_UPNP, &(object->priv->upnp_ns), object->priv->xml_doc->doc, "artist", artist); g_object_notify (G_OBJECT (object), "artist"); } /** * gupnp_didl_lite_object_add_artist: * @object: The #GUPnPDIDLLiteObject * * Add a new Artist node to the @object and return the associated * #GUPnPDIDLLiteContributor object. * * Returns: (transfer full): A new #GUPnPDIDLLiteContributor object. Unref after usage. **/ GUPnPDIDLLiteContributor * gupnp_didl_lite_object_add_artist (GUPnPDIDLLiteObject *object) { xmlNode *res_node; g_return_val_if_fail (object != NULL, NULL); g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); res_node = xmlNewChild (object->priv->xml_node, object->priv->upnp_ns, (unsigned char *) "artist", NULL); return gupnp_didl_lite_contributor_new_from_xml (res_node, object->priv->xml_doc); } /** * gupnp_didl_lite_object_set_author: * @object: The #GUPnPDIDLLiteObject * @author: The Author * * Set the Author of the @object to @author. * * Deprecated: 0.5.3: Use #gupnp_didl_lite_object_add_author instead. **/ void gupnp_didl_lite_object_set_author (GUPnPDIDLLiteObject *object, const char *author) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_DC, &(object->priv->upnp_ns), object->priv->xml_doc->doc, "author", author); g_object_notify (G_OBJECT (object), "author"); } /** * gupnp_didl_lite_object_add_author: * @object: The #GUPnPDIDLLiteObject * * Add a new author node to the @object and return the associated * #GUPnPDIDLLiteContributor object. * * Returns: (transfer full): A new #GUPnPDIDLLiteContributor object. Unref after usage. **/ GUPnPDIDLLiteContributor * gupnp_didl_lite_object_add_author (GUPnPDIDLLiteObject *object) { xmlNode *res_node; g_return_val_if_fail (object != NULL, NULL); g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); res_node = xmlNewChild (object->priv->xml_node, object->priv->upnp_ns, (unsigned char *) "author", NULL); return gupnp_didl_lite_contributor_new_from_xml (res_node, object->priv->xml_doc); } /** * gupnp_didl_lite_object_set_genre: * @object: The #GUPnPDIDLLiteObject * @genre: The Genre * * Set the genre of the @object to @genre. **/ void gupnp_didl_lite_object_set_genre (GUPnPDIDLLiteObject *object, const char *genre) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_UPNP, &(object->priv->upnp_ns), object->priv->xml_doc->doc, "genre", genre); g_object_notify (G_OBJECT (object), "genre"); } /** * gupnp_didl_lite_object_set_write_status: * @object: #GUPnPDIDLLiteObject * @write_status: The write status string * * Set the write status of the @object to @write_status. **/ void gupnp_didl_lite_object_set_write_status (GUPnPDIDLLiteObject *object, const char *write_status) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_DC, &(object->priv->dc_ns), object->priv->xml_doc->doc, "writeStatus", write_status); g_object_notify (G_OBJECT (object), "write-status"); } /** * gupnp_didl_lite_object_set_album: * @object: #GUPnPDIDLLiteObject * @album: The album string * * Set the album of the @object to @album. **/ void gupnp_didl_lite_object_set_album (GUPnPDIDLLiteObject *object, const char *album) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_UPNP, &(object->priv->upnp_ns), object->priv->xml_doc->doc, "album", album); g_object_notify (G_OBJECT (object), "album"); } /** * gupnp_didl_lite_object_set_album_art: * @object: #GUPnPDIDLLiteObject * @album_art: The URI of album art * * Set the URI to album art of the @object to @album_art. **/ void gupnp_didl_lite_object_set_album_art (GUPnPDIDLLiteObject *object, const char *album_art) { xmlNode *node; g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); node = xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_UPNP, &(object->priv->upnp_ns), object->priv->xml_doc->doc, "albumArtURI", album_art); xml_util_get_ns (object->priv->xml_doc->doc, GUPNP_XML_NAMESPACE_DLNA, &(object->priv->dlna_ns)); xmlSetNsProp (node, object->priv->dlna_ns, (const unsigned char *) "profileID", (const unsigned char *) "JPEG_TN"); g_object_notify (G_OBJECT (object), "album-art"); } /** * gupnp_didl_lite_object_set_description: * @object: #GUPnPDIDLLiteObject * @description: The description string * * Set the description of the @object to @description. **/ void gupnp_didl_lite_object_set_description (GUPnPDIDLLiteObject *object, const char *description) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_DC, &(object->priv->dc_ns), object->priv->xml_doc->doc, "description", description); g_object_notify (G_OBJECT (object), "description"); } /** * gupnp_didl_lite_object_set_date: * @object: #GUPnPDIDLLiteObject * @date: The date string * * Set the date of the @object to @date. **/ void gupnp_didl_lite_object_set_date (GUPnPDIDLLiteObject *object, const char *date) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_DC, &(object->priv->dc_ns), object->priv->xml_doc->doc, "date", date); g_object_notify (G_OBJECT (object), "date"); } /** * gupnp_didl_lite_object_set_track_number: * @object: #GUPnPDIDLLiteObject * @track_number: The original track number * * Set the original track number of the @object to @track_number. **/ void gupnp_didl_lite_object_set_track_number (GUPnPDIDLLiteObject *object, int track_number) { char *str; g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); str = g_strdup_printf ("%d", track_number); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_UPNP, &(object->priv->upnp_ns), object->priv->xml_doc->doc, "originalTrackNumber", str); g_free (str); g_object_notify (G_OBJECT (object), "track-number"); } /** * gupnp_didl_lite_object_set_dlna_managed: * @object: #GUPnPDIDLLiteObject * @dlna_managed: The #GUPnPOCMFlags. * * Set the 'dlna:dlnaManaged' attribute of the @object to @dlna_managed. **/ void gupnp_didl_lite_object_set_dlna_managed (GUPnPDIDLLiteObject *object, GUPnPOCMFlags dlna_managed) { char *str; g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_get_ns (object->priv->xml_doc->doc, GUPNP_XML_NAMESPACE_DLNA, &(object->priv->dlna_ns)); str = g_strdup_printf ("%08x", dlna_managed); xmlSetNsProp (object->priv->xml_node, object->priv->dlna_ns, (const unsigned char *) "dlnaManaged", (const unsigned char *) str); g_free (str); g_object_notify (G_OBJECT (object), "dlna-managed"); } /** * gupnp_didl_lite_object_set_update_id: * @object: #GUPnPDIDLLiteObject * @update_id: Update ID * * Set the update ID of the @object. **/ void gupnp_didl_lite_object_set_update_id (GUPnPDIDLLiteObject *object, guint update_id) { char *str; g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); str = g_strdup_printf ("%u", update_id); xml_util_set_child (object->priv->xml_node, GUPNP_XML_NAMESPACE_UPNP, &(object->priv->upnp_ns), object->priv->xml_doc->doc, "objectUpdateID", str); g_free (str); g_object_notify (G_OBJECT (object), "update-id"); } /** * gupnp_didl_lite_object_unset_update_id: * @object: #GUPnPDIDLLiteObject * * Unset the update ID property of the @object. **/ void gupnp_didl_lite_object_unset_update_id (GUPnPDIDLLiteObject *object) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); xml_util_unset_child (object->priv->xml_node, "objectUpdateID"); g_object_notify (G_OBJECT (object), "update-id"); } /** * gupnp_didl_lite_object_add_resource: * @object: A #GUPnPDIDLLiteObject * * Creates a new resource, attaches it to @object and returns it. * * Returns: (transfer full): A new #GUPnPDIDLLiteResource object. Unref after usage. **/ GUPnPDIDLLiteResource * gupnp_didl_lite_object_add_resource (GUPnPDIDLLiteObject *object) { xmlNode *res_node; g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); res_node = xmlNewChild (object->priv->xml_node, NULL, (unsigned char *) "res", NULL); return gupnp_didl_lite_resource_new_from_xml (res_node, object->priv->xml_doc, object->priv->dlna_ns, object->priv->pv_ns); } /** * gupnp_didl_lite_object_add_descriptor: * @object: A #GUPnPDIDLLiteObject * * Creates a new descriptor, attaches it to @object and returns it. * * Returns: (transfer full): A new #GUPnPDIDLLiteDescriptor object. Unref after usage. **/ GUPnPDIDLLiteDescriptor * gupnp_didl_lite_object_add_descriptor (GUPnPDIDLLiteObject *object) { xmlNode *desc_node; g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); desc_node = xmlNewChild (object->priv->xml_node, NULL, (unsigned char *) "desc", NULL); return gupnp_didl_lite_descriptor_new_from_xml (desc_node, object->priv->xml_doc); } /** * gupnp_didl_lite_object_get_title_xml_string: * @object: A #GUPnPDIDLLiteObject * * Creates a string representation of the DIDL-Lite XML fragment related to the * object title. * * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage. **/ char * gupnp_didl_lite_object_get_title_xml_string (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_string (object->priv->xml_node, object->priv->xml_doc->doc, "title"); } /** * gupnp_didl_lite_object_get_date_xml_string: * @object: A #GUPnPDIDLLiteObject * * Creates a string representation of the DIDL-Lite XML fragment related to the * object date. * * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage. **/ char * gupnp_didl_lite_object_get_date_xml_string (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_string (object->priv->xml_node, object->priv->xml_doc->doc, "date"); } /** * gupnp_didl_lite_object_get_upnp_class_xml_string: * @object: A #GUPnPDIDLLiteObject * * Creates a string representation of the DIDL-Lite XML fragment related to the * object UPnP class. * * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage. **/ char * gupnp_didl_lite_object_get_upnp_class_xml_string (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_string (object->priv->xml_node, object->priv->xml_doc->doc, "class"); } /** * gupnp_didl_lite_object_get_album_xml_string: * @object: A #GUPnPDIDLLiteObject * * Creates a string representation of the DIDL-Lite XML fragment related to the * object album. * * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage. **/ char * gupnp_didl_lite_object_get_album_xml_string (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_string (object->priv->xml_node, object->priv->xml_doc->doc, "album"); } /** * gupnp_didl_lite_object_get_track_number_xml_string: * @object: A #GUPnPDIDLLiteObject * * Creates a string representation of the DIDL-Lite XML fragment related to the * object track number. * * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage. **/ char * gupnp_didl_lite_object_get_track_number_xml_string (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return xml_util_get_child_string (object->priv->xml_node, object->priv->xml_doc->doc, "originalTrackNumber"); } /** * gupnp_didl_lite_object_get_artists_xml_string: * @object: A #GUPnPDIDLLiteObject * * Creates a string representation of the DIDL-Lite XML fragments related to the * object artists. * * Return value: A DIDL-Lite XML fragment string, or %NULL. #g_free after usage. **/ char * gupnp_didl_lite_object_get_artists_xml_string (GUPnPDIDLLiteObject *object) { g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), NULL); return get_contributors_xml_string_by_name (object, "artist"); } /** * gupnp_didl_lite_object_unset_artists: * @object: #GUPnPDIDLLiteObject * * Unset the artists properties of the @object. **/ void gupnp_didl_lite_object_unset_artists (GUPnPDIDLLiteObject *object) { g_return_if_fail (object != NULL); g_return_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object)); unset_contributors_by_name (object, "artist"); g_object_notify (G_OBJECT (object), "artist"); } /* GENERAL DOCS ABOUT FRAGMENT APPLYING. * * The function applying fragments takes two arrays of fragments. One * array contains current fragments and another one contains new * fragments. Both arrays have to be of equal length and have more * then zero elements. Each of fragments in both arrays make a pair * (i.e. first/second/third/... fragment in current array and * first/second/third/... fragment in new array form a pair). Each * fragment can have zero, one or more XML elements. * * For each fragment pair first we check if current fragment is indeed * a part of this object's document. If it is then we check validity * of new fragment for applying. If it is then we replace the current * fragment with new fragment in object's document copy and validate * the modified document against didl-lite schema. After all fragment * pairs are processed we replace a part describing this object in * original document with respective one in modified document. * * Checking if current fragment is a part of object's document is in * essence checking for deep equality of document's node and this * fragment (i.e. element name and properties have to be equal, same * for children). * * Checking if new fragment is valid for applying is about checking * whether element in new fragment is either a context (i.e. both * current element and new element are deep equal) or element * modification (i.e. changes attributes but element name is still the * same). There may be a case when there are more elements in current * fragment than in new fragment then those excessive elements are * checked whether they can be really removed. The other case is when * there are more elements in new fragments than in current fragment - * in such situation we check if additions are valid. * * By checking validity of modification, removals or additions we mean * that no read-only properties are changed. Additionaly, for * removals, we check if required properties are not removed. * * This approach may fail in some more twisted cases. */ /** * gupnp_didl_lite_object_apply_fragments: * @object: The #GUPnPDIDLLiteObject * @current_fragments: (array length=current_size) (transfer none): XML * fragments of @object. * @current_size: Size of @current_fragments or -1. * @new_fragments: (array length=new_size) (transfer none): Substitutes * for @current_fragments. * @new_size: Size of @new_fragments or -1. * * Updates object by applying @new_fragments in places of * @current_fragments. For @current_size and @new_size -1 can be * passed when respectively @current_fragments and @new_fragments are * NULL terminated. * * Returns: Result of operation. */ GUPnPDIDLLiteFragmentResult gupnp_didl_lite_object_apply_fragments (GUPnPDIDLLiteObject *object, gchar **current_fragments, gint current_size, gchar **new_fragments, gint new_size) { DocNode modified; DocNode original; GUPnPDIDLLiteFragmentResult result; gint iter; g_return_val_if_fail (GUPNP_IS_DIDL_LITE_OBJECT (object), GUPNP_DIDL_LITE_FRAGMENT_RESULT_UNKNOWN_ERROR); g_return_val_if_fail (current_fragments != NULL, GUPNP_DIDL_LITE_FRAGMENT_RESULT_CURRENT_INVALID); g_return_val_if_fail (new_fragments != NULL, GUPNP_DIDL_LITE_FRAGMENT_RESULT_NEW_INVALID); result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_OK; modified.doc = NULL; if (current_size < 0) current_size = g_strv_length (current_fragments); if (new_size < 0) new_size = g_strv_length (new_fragments); if (current_size != new_size) { result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_MISMATCH; goto out; } if (!current_size) { result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_CURRENT_INVALID; goto out; } original.doc = object->priv->xml_doc->doc; original.node = object->priv->xml_node; modified.doc = xmlCopyDoc (original.doc, 1); if (modified.doc == NULL) { result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_UNKNOWN_ERROR; goto out; } modified.node = xml_util_find_node (modified.doc->children, original.node); if (modified.node == NULL) { result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_UNKNOWN_ERROR; goto out; } for (iter = 0; iter < new_size; ++iter) { const gchar *current_fragment = current_fragments[iter]; const gchar *new_fragment = new_fragments[iter]; result = fragment_util_check_fragments (&original, &modified, current_fragment, new_fragment, didl_lite_xsd); if (result != GUPNP_DIDL_LITE_FRAGMENT_RESULT_OK) goto out; } if (!fragment_util_apply_modification (&object->priv->xml_node, &modified)) result = GUPNP_DIDL_LITE_FRAGMENT_RESULT_UNKNOWN_ERROR; out: if (modified.doc != NULL) xmlFreeDoc (modified.doc); return result; } /** * gupnp_didl_lite_object_get_xml_string: * @object: #GUPnPDIDLLiteObject * * Get the representation of this object as an XML string. * Returns: (transfer full): XML representation of this object as string. **/ char * gupnp_didl_lite_object_get_xml_string (GUPnPDIDLLiteObject *object) { xmlBuffer *buffer = NULL; char *ret = NULL; buffer = xmlBufferCreate (); xmlNodeDump (buffer, object->priv->xml_doc->doc, object->priv->xml_node, 0, 0); ret = g_strndup ((char *) xmlBufferContent (buffer), xmlBufferLength (buffer)); xmlBufferFree (buffer); return ret; }