Blame libgupnp-av/gupnp-didl-lite-writer.c

Packit 712bc5
/*
Packit 712bc5
 * Copyright (C) 2007, 2008 OpenedHand Ltd.
Packit 712bc5
 * Copyright (C) 2012 Intel Corporation.
Packit 712bc5
 *
Packit 712bc5
 * Authors: Jorn Baayen <jorn@openedhand.com>
Packit 712bc5
 *          Jens Georg <jensg@openismus.com>
Packit 712bc5
 *
Packit 712bc5
 * This library is free software; you can redistribute it and/or
Packit 712bc5
 * modify it under the terms of the GNU Library General Public
Packit 712bc5
 * License as published by the Free Software Foundation; either
Packit 712bc5
 * version 2 of the License, or (at your option) any later version.
Packit 712bc5
 *
Packit 712bc5
 * This library is distributed in the hope that it will be useful,
Packit 712bc5
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 712bc5
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 712bc5
 * Library General Public License for more details.
Packit 712bc5
 *
Packit 712bc5
 * You should have received a copy of the GNU Library General Public
Packit 712bc5
 * License along with this library; if not, write to the
Packit 712bc5
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit 712bc5
 * Boston, MA 02110-1301, USA.
Packit 712bc5
 */
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * SECTION:gupnp-didl-lite-writer
Packit 712bc5
 * @short_description: DIDL-Lite fragment writer
Packit 712bc5
 *
Packit 712bc5
 * #GUPnPDIDLLiteWriter is a helper class for writing DIDL-Lite fragments.
Packit 712bc5
 */
Packit 712bc5
Packit 712bc5
#include <string.h>
Packit 712bc5
Packit 712bc5
#include "gupnp-didl-lite-writer.h"
Packit 712bc5
#include "gupnp-didl-lite-object.h"
Packit 712bc5
#include "gupnp-didl-lite-object-private.h"
Packit 712bc5
#include "gupnp-didl-lite-descriptor-private.h"
Packit 712bc5
#include "gupnp-didl-lite-writer-private.h"
Packit 712bc5
Packit 712bc5
#include "xml-util.h"
Packit 712bc5
Packit 712bc5
G_DEFINE_TYPE (GUPnPDIDLLiteWriter,
Packit 712bc5
               gupnp_didl_lite_writer,
Packit 712bc5
               G_TYPE_OBJECT);
Packit 712bc5
Packit 712bc5
struct _GUPnPDIDLLiteWriterPrivate {
Packit 712bc5
        xmlNode       *xml_node;
Packit 712bc5
        GUPnPAVXMLDoc *xml_doc;
Packit 712bc5
Packit 712bc5
        xmlNs       *upnp_ns;
Packit 712bc5
        xmlNs       *dc_ns;
Packit 712bc5
        xmlNs       *dlna_ns;
Packit 712bc5
        xmlNs       *pv_ns;
Packit 712bc5
Packit 712bc5
        char        *language;
Packit 712bc5
};
Packit 712bc5
Packit 712bc5
enum {
Packit 712bc5
        PROP_0,
Packit 712bc5
        PROP_XML_NODE,
Packit 712bc5
        PROP_LANGUAGE,
Packit 712bc5
};
Packit 712bc5
Packit 712bc5
static int
Packit 712bc5
compare_prop (const char *a, xmlAttr *attr)
Packit 712bc5
{
Packit 712bc5
        const char *p;
Packit 712bc5
        char *parent_name;
Packit 712bc5
        char *attr_name;
Packit 712bc5
        int ret = -1;
Packit 712bc5
Packit 712bc5
        if (attr->ns != NULL)
Packit 712bc5
                attr_name = g_strjoin (":", attr->ns->prefix, attr->name, NULL);
Packit 712bc5
        else
Packit 712bc5
                attr_name = g_strdup ((const char *) attr->name);
Packit 712bc5
Packit 712bc5
        if (attr->parent->ns != NULL)
Packit 712bc5
                parent_name = g_strjoin (":",
Packit 712bc5
                                         attr->parent->ns->prefix,
Packit 712bc5
                                         attr->parent->name,
Packit 712bc5
                                         NULL);
Packit 712bc5
        else
Packit 712bc5
                parent_name = g_strdup ((const char *) attr->parent->name);
Packit 712bc5
Packit 712bc5
        p = strstr (a, "@");
Packit 712bc5
        if (p)
Packit 712bc5
                if (p == a)
Packit 712bc5
                        /* Top-level property */
Packit 712bc5
                        ret = strcmp (a + 1, attr_name);
Packit 712bc5
                else
Packit 712bc5
                        ret = strncmp (a, parent_name, p - a) ||
Packit 712bc5
                              strcmp (p + 1, attr_name);
Packit 712bc5
        else
Packit 712bc5
                ret = strcmp (a, attr_name);
Packit 712bc5
Packit 712bc5
        g_free (attr_name);
Packit 712bc5
        g_free (parent_name);
Packit 712bc5
Packit 712bc5
        return ret;
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static gboolean
Packit 712bc5
is_attribute_forbidden (xmlAttr *attr,
Packit 712bc5
                        GList   *allowed)
Packit 712bc5
{
Packit 712bc5
        return g_list_find_custom (allowed,
Packit 712bc5
                                   attr,
Packit 712bc5
                                   (GCompareFunc) compare_prop) == NULL;
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static int
Packit 712bc5
compare_node_name (const char *a, const char *b)
Packit 712bc5
{
Packit 712bc5
        const char *p;
Packit 712bc5
        int len, result;
Packit 712bc5
Packit 712bc5
        if (a[0] == '@')
Packit 712bc5
                /* Filter is for top-level property */
Packit 712bc5
                return -1;
Packit 712bc5
Packit 712bc5
        p = strstr (a, "@");
Packit 712bc5
        if (p != NULL)
Packit 712bc5
                /* Compare only the string before '@' */
Packit 712bc5
                len = p - a;
Packit 712bc5
        else
Packit 712bc5
                len = strlen (a);
Packit 712bc5
Packit 712bc5
        result = strncmp (a, b, len);
Packit 712bc5
Packit 712bc5
        if (result == 0) {
Packit 712bc5
            /* Avoid that we return a match although only prefixes match like
Packit 712bc5
             * in upnp:album and upnp:albumArtUri, cf. bgo#687462 */
Packit 712bc5
            return strlen (b) - len;
Packit 712bc5
        }
Packit 712bc5
Packit 712bc5
        return result;
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static gboolean
Packit 712bc5
is_node_forbidden (xmlNode     *node,
Packit 712bc5
                    GList      *allowed,
Packit 712bc5
                    const char *ns)
Packit 712bc5
{
Packit 712bc5
        char *name;
Packit 712bc5
        gboolean ret;
Packit 712bc5
Packit 712bc5
        if (ns != NULL)
Packit 712bc5
                name = g_strjoin (":", ns, node->name, NULL);
Packit 712bc5
        else
Packit 712bc5
                name = g_strdup ((const char *) node->name);
Packit 712bc5
Packit 712bc5
        ret = g_list_find_custom (allowed,
Packit 712bc5
                                  name,
Packit 712bc5
                                  (GCompareFunc) compare_node_name) == NULL;
Packit 712bc5
Packit 712bc5
        g_free (name);
Packit 712bc5
Packit 712bc5
        return ret;
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static gboolean
Packit 712bc5
is_container_standard_prop (const char *name,
Packit 712bc5
                            const char *namespace,
Packit 712bc5
                            const char *upnp_class)
Packit 712bc5
{
Packit 712bc5
        return g_strcmp0 (upnp_class, "object.container.storageFolder") == 0 &&
Packit 712bc5
               g_strcmp0 (namespace, "upnp") == 0 &&
Packit 712bc5
               strcmp (name, "storageUsed") == 0;
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static gboolean
Packit 712bc5
is_standard_prop (const char *name,
Packit 712bc5
                  const char *namespace,
Packit 712bc5
                  const char *parent_name)
Packit 712bc5
{
Packit 712bc5
        return strcmp (name, "id") == 0 ||
Packit 712bc5
               strcmp (name, "parentID") == 0 ||
Packit 712bc5
               strcmp (name, "restricted") == 0 ||
Packit 712bc5
               (g_strcmp0 (namespace, "dc") == 0 &&
Packit 712bc5
                strcmp (name, "title") == 0) ||
Packit 712bc5
               (g_strcmp0 (namespace, "upnp") == 0 &&
Packit 712bc5
                strcmp (name, "class") == 0) ||
Packit 712bc5
               (g_strcmp0 (parent_name, "res") == 0 &&
Packit 712bc5
                strcmp (name, "protocolInfo") == 0);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
filter_attributes (xmlNode             *node,
Packit 712bc5
                   GList               *allowed)
Packit 712bc5
{
Packit 712bc5
        xmlAttr *attr;
Packit 712bc5
        GList   *forbidden = NULL;
Packit 712bc5
        GList   *l;
Packit 712bc5
Packit 712bc5
        /* Find forbidden properties */
Packit 712bc5
        for (attr = node->properties; attr != NULL; attr = attr->next)
Packit 712bc5
                if (!is_standard_prop ((const char *) attr->name,
Packit 712bc5
                                        NULL,
Packit 712bc5
                                        (const char *) attr->parent->name) &&
Packit 712bc5
                    is_attribute_forbidden (attr, allowed))
Packit 712bc5
                        forbidden = g_list_append (forbidden, attr);
Packit 712bc5
Packit 712bc5
        /* Now unset forbidden properties */
Packit 712bc5
        for (l = forbidden; l != NULL; l = l->next)
Packit 712bc5
                xmlRemoveProp ((xmlAttr *) l->data);
Packit 712bc5
Packit 712bc5
        g_list_free (forbidden);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
filter_node (xmlNode             *node,
Packit 712bc5
             GList               *allowed,
Packit 712bc5
             GUPnPDIDLLiteWriter *writer,
Packit 712bc5
             gboolean             tags_only)
Packit 712bc5
{
Packit 712bc5
        xmlNode *child;
Packit 712bc5
        GList   *forbidden = NULL;
Packit 712bc5
        GList   *l;
Packit 712bc5
        gboolean is_container = FALSE;
Packit 712bc5
        const char *container_class = NULL;
Packit 712bc5
Packit 712bc5
        if (!tags_only)
Packit 712bc5
                filter_attributes (node, allowed);
Packit 712bc5
Packit 712bc5
        if (strcmp ((const char *) node->name, "container") == 0) {
Packit 712bc5
                is_container = TRUE;
Packit 712bc5
                container_class = xml_util_get_child_element_content (node,
Packit 712bc5
                                                                      "class");
Packit 712bc5
        }
Packit 712bc5
Packit 712bc5
        forbidden = NULL;
Packit 712bc5
        for (child = node->children; child != NULL; child = child->next) {
Packit 712bc5
                const char *ns = NULL;
Packit 712bc5
Packit 712bc5
                if (xmlNodeIsText (child))
Packit 712bc5
                        continue;
Packit 712bc5
Packit 712bc5
                if (child->ns != NULL)
Packit 712bc5
                        ns = (const char *) child->ns->prefix;
Packit 712bc5
Packit 712bc5
                if (!(is_container && is_container_standard_prop
Packit 712bc5
                                            ((const char *) child->name,
Packit 712bc5
                                             ns,
Packit 712bc5
                                             container_class)) &&
Packit 712bc5
                    !is_standard_prop ((const char *) child->name,
Packit 712bc5
                                       ns,
Packit 712bc5
                                       (const char *)  node->name) &&
Packit 712bc5
                    is_node_forbidden (child, allowed, ns))
Packit 712bc5
                        forbidden = g_list_append (forbidden, child);
Packit 712bc5
        }
Packit 712bc5
Packit 712bc5
        /* Now remove the forbidden nodes */
Packit 712bc5
        for (l = forbidden; l != NULL; l = l->next) {
Packit 712bc5
                xmlNode *n;
Packit 712bc5
Packit 712bc5
                n = (xmlNode *) l->data;
Packit 712bc5
Packit 712bc5
                xmlUnlinkNode (n);
Packit 712bc5
                xmlFreeNode (n);
Packit 712bc5
        }
Packit 712bc5
Packit 712bc5
        g_list_free (forbidden);
Packit 712bc5
Packit 712bc5
        /* Recurse */
Packit 712bc5
        for (child = node->children; child != NULL; child = child->next)
Packit 712bc5
                if (!xmlNodeIsText (child))
Packit 712bc5
                        filter_node (child, allowed, writer, tags_only);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
apply_filter (GUPnPDIDLLiteWriter *writer,
Packit 712bc5
              const char          *filter,
Packit 712bc5
              gboolean             tags_only)
Packit 712bc5
{
Packit 712bc5
        char **tokens;
Packit 712bc5
        GList *allowed = NULL;
Packit 712bc5
        unsigned short i;
Packit 712bc5
        xmlNode *node;
Packit 712bc5
Packit 712bc5
        g_return_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer));
Packit 712bc5
        g_return_if_fail (filter != NULL);
Packit 712bc5
Packit 712bc5
        if (filter[0] == '*')
Packit 712bc5
                return;         /* Wildcard */
Packit 712bc5
Packit 712bc5
        tokens = g_strsplit (filter, ",", -1);
Packit 712bc5
        g_return_if_fail (tokens != NULL);
Packit 712bc5
Packit 712bc5
        for (i = 0; tokens[i] != NULL; i++)
Packit 712bc5
                allowed = g_list_append (allowed, tokens[i]);
Packit 712bc5
Packit 712bc5
        for (node = writer->priv->xml_node->children;
Packit 712bc5
             node != NULL;
Packit 712bc5
             node = node->next)
Packit 712bc5
                filter_node (node, allowed, writer, tags_only);
Packit 712bc5
Packit 712bc5
        g_list_free (allowed);
Packit 712bc5
        g_strfreev (tokens);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
gupnp_didl_lite_writer_init (GUPnPDIDLLiteWriter *writer)
Packit 712bc5
{
Packit 712bc5
        writer->priv = G_TYPE_INSTANCE_GET_PRIVATE (writer,
Packit 712bc5
                                                    GUPNP_TYPE_DIDL_LITE_WRITER,
Packit 712bc5
                                                    GUPnPDIDLLiteWriterPrivate);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
gupnp_didl_lite_writer_set_property (GObject      *object,
Packit 712bc5
                                     guint         property_id,
Packit 712bc5
                                     const GValue *value,
Packit 712bc5
                                     GParamSpec   *pspec)
Packit 712bc5
Packit 712bc5
{
Packit 712bc5
        GUPnPDIDLLiteWriter *writer;
Packit 712bc5
Packit 712bc5
        writer = GUPNP_DIDL_LITE_WRITER (object);
Packit 712bc5
Packit 712bc5
        switch (property_id) {
Packit 712bc5
        case PROP_LANGUAGE:
Packit 712bc5
                writer->priv->language = g_value_dup_string (value);
Packit 712bc5
                break;
Packit 712bc5
        default:
Packit 712bc5
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 712bc5
                break;
Packit 712bc5
        }
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
gupnp_didl_lite_writer_get_property (GObject    *object,
Packit 712bc5
                                     guint       property_id,
Packit 712bc5
                                     GValue     *value,
Packit 712bc5
                                     GParamSpec *pspec)
Packit 712bc5
{
Packit 712bc5
        GUPnPDIDLLiteWriter *writer;
Packit 712bc5
Packit 712bc5
        writer = GUPNP_DIDL_LITE_WRITER (object);
Packit 712bc5
Packit 712bc5
        switch (property_id) {
Packit 712bc5
        case PROP_XML_NODE:
Packit 712bc5
                g_value_set_pointer
Packit 712bc5
                        (value, gupnp_didl_lite_writer_get_xml_node (writer));
Packit 712bc5
                break;
Packit 712bc5
        case PROP_LANGUAGE:
Packit 712bc5
                g_value_set_string
Packit 712bc5
                        (value, gupnp_didl_lite_writer_get_language (writer));
Packit 712bc5
                break;
Packit 712bc5
        default:
Packit 712bc5
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
Packit 712bc5
                break;
Packit 712bc5
        }
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
gupnp_didl_lite_writer_constructed (GObject *object)
Packit 712bc5
{
Packit 712bc5
        GObjectClass               *object_class;
Packit 712bc5
        GUPnPDIDLLiteWriterPrivate *priv;
Packit 712bc5
        xmlDoc                     *doc;
Packit 712bc5
Packit 712bc5
        priv = GUPNP_DIDL_LITE_WRITER (object)->priv;
Packit 712bc5
Packit 712bc5
        doc = xmlNewDoc ((unsigned char *) "1.0");
Packit 712bc5
        priv->xml_doc = xml_doc_new (doc);
Packit 712bc5
Packit 712bc5
        priv->xml_node = xmlNewDocNode (priv->xml_doc->doc,
Packit 712bc5
                                        NULL,
Packit 712bc5
                                        (unsigned char *) "DIDL-Lite",
Packit 712bc5
                                        NULL);
Packit 712bc5
        xmlDocSetRootElement (priv->xml_doc->doc, priv->xml_node);
Packit 712bc5
Packit 712bc5
        xml_util_create_namespace (priv->xml_node,
Packit 712bc5
                                   GUPNP_XML_NAMESPACE_DIDL_LITE);
Packit 712bc5
Packit 712bc5
        if (priv->language)
Packit 712bc5
                xmlSetProp (priv->xml_node,
Packit 712bc5
                            (unsigned char *) "lang",
Packit 712bc5
                            (unsigned char *) priv->language);
Packit 712bc5
Packit 712bc5
        object_class = G_OBJECT_CLASS (gupnp_didl_lite_writer_parent_class);
Packit 712bc5
        if (object_class->constructed != NULL)
Packit 712bc5
                object_class->constructed (object);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
gupnp_didl_lite_writer_dispose (GObject *object)
Packit 712bc5
{
Packit 712bc5
        GObjectClass               *object_class;
Packit 712bc5
        GUPnPDIDLLiteWriterPrivate *priv;
Packit 712bc5
Packit 712bc5
        priv = GUPNP_DIDL_LITE_WRITER (object)->priv;
Packit 712bc5
Packit 712bc5
        g_clear_pointer (&priv->xml_doc, xml_doc_unref);
Packit 712bc5
Packit 712bc5
        object_class = G_OBJECT_CLASS (gupnp_didl_lite_writer_parent_class);
Packit 712bc5
        object_class->dispose (object);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
gupnp_didl_lite_writer_finalize (GObject *object)
Packit 712bc5
{
Packit 712bc5
        GObjectClass               *object_class;
Packit 712bc5
        GUPnPDIDLLiteWriterPrivate *priv;
Packit 712bc5
Packit 712bc5
        priv = GUPNP_DIDL_LITE_WRITER (object)->priv;
Packit 712bc5
Packit 712bc5
        if (priv->language)
Packit 712bc5
                g_free (priv->language);
Packit 712bc5
Packit 712bc5
        object_class = G_OBJECT_CLASS (gupnp_didl_lite_writer_parent_class);
Packit 712bc5
        object_class->finalize (object);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
static void
Packit 712bc5
gupnp_didl_lite_writer_class_init (GUPnPDIDLLiteWriterClass *klass)
Packit 712bc5
{
Packit 712bc5
        GObjectClass *object_class;
Packit 712bc5
Packit 712bc5
        object_class = G_OBJECT_CLASS (klass);
Packit 712bc5
Packit 712bc5
        object_class->set_property = gupnp_didl_lite_writer_set_property;
Packit 712bc5
        object_class->get_property = gupnp_didl_lite_writer_get_property;
Packit 712bc5
        object_class->constructed = gupnp_didl_lite_writer_constructed;
Packit 712bc5
        object_class->dispose = gupnp_didl_lite_writer_dispose;
Packit 712bc5
        object_class->finalize = gupnp_didl_lite_writer_finalize;
Packit 712bc5
Packit 712bc5
        g_type_class_add_private (klass, sizeof (GUPnPDIDLLiteWriterPrivate));
Packit 712bc5
Packit 712bc5
        /**
Packit 712bc5
         * GUPnPDIDLLiteWriter:xml-node:
Packit 712bc5
         *
Packit 712bc5
         * The pointer to root node in XML document.
Packit 712bc5
         **/
Packit 712bc5
        g_object_class_install_property
Packit 712bc5
                (object_class,
Packit 712bc5
                 PROP_XML_NODE,
Packit 712bc5
                 g_param_spec_pointer ("xml-node",
Packit 712bc5
                                       "XMLNode",
Packit 712bc5
                                       "The pointer to root node in XML"
Packit 712bc5
                                       " document.",
Packit 712bc5
                                       G_PARAM_READABLE |
Packit 712bc5
                                       G_PARAM_STATIC_NAME |
Packit 712bc5
                                       G_PARAM_STATIC_NICK |
Packit 712bc5
                                       G_PARAM_STATIC_BLURB));
Packit 712bc5
Packit 712bc5
        /**
Packit 712bc5
         * GUPnPDIDLLiteWriter:language:
Packit 712bc5
         *
Packit 712bc5
         * The language the DIDL-Lite fragment is in.
Packit 712bc5
         *
Packit 712bc5
         **/
Packit 712bc5
        g_object_class_install_property
Packit 712bc5
                (object_class,
Packit 712bc5
                 PROP_LANGUAGE,
Packit 712bc5
                 g_param_spec_string ("language",
Packit 712bc5
                                      "Language",
Packit 712bc5
                                      "The language the DIDL-Lite fragment"
Packit 712bc5
                                      " is in.",
Packit 712bc5
                                      NULL,
Packit 712bc5
                                      G_PARAM_CONSTRUCT_ONLY |
Packit 712bc5
                                      G_PARAM_READWRITE |
Packit 712bc5
                                      G_PARAM_STATIC_NAME |
Packit 712bc5
                                      G_PARAM_STATIC_NICK |
Packit 712bc5
                                      G_PARAM_STATIC_BLURB));
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_new:
Packit 712bc5
 * @language: (allow-none):The language the DIDL-Lite fragment is in, or %NULL
Packit 712bc5
 *
Packit 712bc5
 * Note: @language should always be set to %NULL, DLNA does not support the
Packit 712bc5
 * language parameter.
Packit 712bc5
 *
Packit 712bc5
 * Return value: A new #GUPnPDIDLLiteWriter object.
Packit 712bc5
 **/
Packit 712bc5
GUPnPDIDLLiteWriter *
Packit 712bc5
gupnp_didl_lite_writer_new (const char *language)
Packit 712bc5
{
Packit 712bc5
        return g_object_new (GUPNP_TYPE_DIDL_LITE_WRITER,
Packit 712bc5
                             "language", language,
Packit 712bc5
                             NULL);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_add_item:
Packit 712bc5
 * @writer: A #GUPnPDIDLLiteWriter
Packit 712bc5
 *
Packit 712bc5
 * Creates a new item, attaches it to @writer and returns it.
Packit 712bc5
 *
Packit 712bc5
 * Returns: (transfer full): A new #GUPnPDIDLLiteItem object. Unref after usage.
Packit 712bc5
 **/
Packit 712bc5
GUPnPDIDLLiteItem *
Packit 712bc5
gupnp_didl_lite_writer_add_item (GUPnPDIDLLiteWriter *writer)
Packit 712bc5
{
Packit 712bc5
        xmlNode *item_node;
Packit 712bc5
        GUPnPDIDLLiteObject *object;
Packit 712bc5
Packit 712bc5
        g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
Packit 712bc5
Packit 712bc5
        item_node = xmlNewChild (writer->priv->xml_node,
Packit 712bc5
                                NULL,
Packit 712bc5
                                (unsigned char *) "item",
Packit 712bc5
                                NULL);
Packit 712bc5
Packit 712bc5
        object = gupnp_didl_lite_object_new_from_xml (item_node,
Packit 712bc5
                                                      writer->priv->xml_doc,
Packit 712bc5
                                                      writer->priv->upnp_ns,
Packit 712bc5
                                                      writer->priv->dc_ns,
Packit 712bc5
                                                      writer->priv->dlna_ns,
Packit 712bc5
                                                      writer->priv->pv_ns);
Packit 712bc5
        return GUPNP_DIDL_LITE_ITEM (object);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_add_container_child_item:
Packit 712bc5
 * @writer: #GUPnPDIDLLiteWriter
Packit 712bc5
 * @container: #GUPnPDIDLLiteContainer
Packit 712bc5
 *
Packit 712bc5
 * Add a child item to a container. This is only useful in DIDL_S playlist
Packit 712bc5
 * creation.
Packit 712bc5
 *
Packit 712bc5
 * Returns: (transfer full): A new #GUPnPDIDLLiteItem object. Unref after
Packit 712bc5
 * usage.
Packit 712bc5
 **/
Packit 712bc5
GUPnPDIDLLiteItem *
Packit 712bc5
gupnp_didl_lite_writer_add_container_child_item
Packit 712bc5
                                        (GUPnPDIDLLiteWriter    *writer,
Packit 712bc5
                                         GUPnPDIDLLiteContainer *container)
Packit 712bc5
{
Packit 712bc5
        xmlNode *item_node, *container_node;
Packit 712bc5
        GUPnPDIDLLiteObject *object;
Packit 712bc5
Packit 712bc5
        g_return_val_if_fail (GUPNP_IS_DIDL_LITE_CONTAINER (container), NULL);
Packit 712bc5
Packit 712bc5
        object = GUPNP_DIDL_LITE_OBJECT (container);
Packit 712bc5
        container_node = gupnp_didl_lite_object_get_xml_node (object);
Packit 712bc5
Packit 712bc5
        item_node = xmlNewChild (container_node,
Packit 712bc5
                                 NULL,
Packit 712bc5
                                 (xmlChar *) "item",
Packit 712bc5
                                 NULL);
Packit 712bc5
Packit 712bc5
        object = gupnp_didl_lite_object_new_from_xml (item_node,
Packit 712bc5
                                                      writer->priv->xml_doc,
Packit 712bc5
                                                      writer->priv->upnp_ns,
Packit 712bc5
                                                      writer->priv->dc_ns,
Packit 712bc5
                                                      writer->priv->dlna_ns,
Packit 712bc5
                                                      writer->priv->pv_ns);
Packit 712bc5
        return GUPNP_DIDL_LITE_ITEM (object);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_add_container:
Packit 712bc5
 * @writer: A #GUPnPDIDLLiteWriter
Packit 712bc5
 *
Packit 712bc5
 * Creates a new container, attaches it to @writer and returns it.
Packit 712bc5
 *
Packit 712bc5
 * Returns: (transfer full): A new #GUPnPDIDLLiteContainer object. Unref after usage.
Packit 712bc5
 **/
Packit 712bc5
GUPnPDIDLLiteContainer *
Packit 712bc5
gupnp_didl_lite_writer_add_container (GUPnPDIDLLiteWriter *writer)
Packit 712bc5
{
Packit 712bc5
        xmlNode *container_node;
Packit 712bc5
        GUPnPDIDLLiteObject *object;
Packit 712bc5
Packit 712bc5
        g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
Packit 712bc5
Packit 712bc5
        container_node = xmlNewChild (writer->priv->xml_node,
Packit 712bc5
                                      NULL,
Packit 712bc5
                                      (unsigned char *) "container",
Packit 712bc5
                                      NULL);
Packit 712bc5
Packit 712bc5
        object = gupnp_didl_lite_object_new_from_xml (container_node,
Packit 712bc5
                                                      writer->priv->xml_doc,
Packit 712bc5
                                                      writer->priv->upnp_ns,
Packit 712bc5
                                                      writer->priv->dc_ns,
Packit 712bc5
                                                      writer->priv->dlna_ns,
Packit 712bc5
                                                      writer->priv->pv_ns);
Packit 712bc5
        return GUPNP_DIDL_LITE_CONTAINER (object);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_add_descriptor:
Packit 712bc5
 * @writer: A #GUPnPDIDLLiteWriter
Packit 712bc5
 *
Packit 712bc5
 * Creates a new descriptor, attaches it to @object and returns it.
Packit 712bc5
 *
Packit 712bc5
 * Returns: (transfer full): A new #GUPnPDIDLLiteDescriptor object. Unref after usage.
Packit 712bc5
 **/
Packit 712bc5
GUPnPDIDLLiteDescriptor *
Packit 712bc5
gupnp_didl_lite_writer_add_descriptor (GUPnPDIDLLiteWriter *writer)
Packit 712bc5
{
Packit 712bc5
        xmlNode *desc_node;
Packit 712bc5
Packit 712bc5
        g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
Packit 712bc5
Packit 712bc5
        desc_node = xmlNewChild (writer->priv->xml_node,
Packit 712bc5
                                 NULL,
Packit 712bc5
                                 (unsigned char *) "desc",
Packit 712bc5
                                 NULL);
Packit 712bc5
Packit 712bc5
        return gupnp_didl_lite_descriptor_new_from_xml (desc_node,
Packit 712bc5
                                                        writer->priv->xml_doc);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_get_string:
Packit 712bc5
 * @writer: A #GUPnPDIDLLiteWriter
Packit 712bc5
 *
Packit 712bc5
 * Creates a string representation of the DIDL-Lite XML document.
Packit 712bc5
 *
Packit 712bc5
 * Return value: The DIDL-Lite XML string, or %NULL. #g_free after usage.
Packit 712bc5
 **/
Packit 712bc5
char *
Packit 712bc5
gupnp_didl_lite_writer_get_string (GUPnPDIDLLiteWriter *writer)
Packit 712bc5
{
Packit 712bc5
        xmlBuffer *buffer;
Packit 712bc5
        char      *ret;
Packit 712bc5
Packit 712bc5
        g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
Packit 712bc5
Packit 712bc5
        buffer = xmlBufferCreate ();
Packit 712bc5
        xmlNodeDump (buffer,
Packit 712bc5
                     writer->priv->xml_doc->doc,
Packit 712bc5
                     writer->priv->xml_node,
Packit 712bc5
                     0,
Packit 712bc5
                     0);
Packit 712bc5
        ret = g_strndup ((char *) xmlBufferContent (buffer),
Packit 712bc5
                         xmlBufferLength (buffer));
Packit 712bc5
        xmlBufferFree (buffer);
Packit 712bc5
Packit 712bc5
        return ret;
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_get_xml_node:
Packit 712bc5
 * @writer: The #GUPnPDIDLLiteWriter
Packit 712bc5
 *
Packit 712bc5
 * Get the pointer to root node in XML document.
Packit 712bc5
 *
Packit 712bc5
 * Returns: (transfer none): The pointer to root node in XML document.
Packit 712bc5
 **/
Packit 712bc5
xmlNode *
Packit 712bc5
gupnp_didl_lite_writer_get_xml_node (GUPnPDIDLLiteWriter *writer)
Packit 712bc5
{
Packit 712bc5
        g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
Packit 712bc5
Packit 712bc5
        return writer->priv->xml_node;
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_get_language:
Packit 712bc5
 * @writer: #GUPnPDIDLLiteWriter
Packit 712bc5
 *
Packit 712bc5
 * Get the language the DIDL-Lite fragment is in.
Packit 712bc5
 *
Packit 712bc5
 * Returns: (transfer none): The language of the @writer, or %NULL.
Packit 712bc5
 **/
Packit 712bc5
const char *
Packit 712bc5
gupnp_didl_lite_writer_get_language (GUPnPDIDLLiteWriter *writer)
Packit 712bc5
{
Packit 712bc5
        g_return_val_if_fail (GUPNP_IS_DIDL_LITE_WRITER (writer), NULL);
Packit 712bc5
Packit 712bc5
        return writer->priv->language;
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_filter:
Packit 712bc5
 * @writer: A #GUPnPDIDLLiteWriter
Packit 712bc5
 * @filter: A filter string
Packit 712bc5
 *
Packit 712bc5
 * Clears the DIDL-Lite XML document of the properties not specified in the
Packit 712bc5
 * @filter. The passed filter string would typically come from the 'Filter'
Packit 712bc5
 * argument of Browse or Search actions from a ContentDirectory control point.
Packit 712bc5
 * Please refer to Section 2.3.15 of UPnP AV ContentDirectory version 3
Packit 712bc5
 * specification for details on this string.
Packit 712bc5
 **/
Packit 712bc5
void
Packit 712bc5
gupnp_didl_lite_writer_filter (GUPnPDIDLLiteWriter *writer,
Packit 712bc5
                               const char          *filter)
Packit 712bc5
{
Packit 712bc5
        apply_filter (writer, filter, FALSE);
Packit 712bc5
}
Packit 712bc5
Packit 712bc5
/**
Packit 712bc5
 * gupnp_didl_lite_writer_filter_tags:
Packit 712bc5
 * @writer: A #GUPnPDIDLLiteWriter
Packit 712bc5
 * @filter: A filter string
Packit 712bc5
 *
Packit 712bc5
 * Clears the DIDL-Lite XML document of the properties not specified in the
Packit 712bc5
 * @filter. The passed filter string would typically come from the 'Filter'
Packit 712bc5
 * argument of Browse or Search actions from a ContentDirectory control point.
Packit 712bc5
 * Please refer to Section 2.3.15 of UPnP AV ContentDirectory version 3
Packit 712bc5
 * specification for details on this string.
Packit 712bc5
 *
Packit 712bc5
 * In contrast to gupnp_didl_lite_writer_filter(), this function only removes
Packit 712bc5
 * unwanted tags but leaves all attributes in-place.
Packit 712bc5
 *
Packit 712bc5
 * Return value: None.
Packit 712bc5
 **/
Packit 712bc5
void
Packit 712bc5
gupnp_didl_lite_writer_filter_tags (GUPnPDIDLLiteWriter *writer,
Packit 712bc5
                                    const char          *filter)
Packit 712bc5
{
Packit 712bc5
        apply_filter (writer, filter, TRUE);
Packit 712bc5
}