|
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 |
}
|