|
Packit |
712bc5 |
/*
|
|
Packit |
712bc5 |
* Copyright (C) 2007 Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
|
|
Packit |
712bc5 |
* Copyright (C) 2007 OpenedHand Ltd
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Authors: Zeeshan Ali (Khattak) <zeeshanak@gnome.org>
|
|
Packit |
712bc5 |
* Jorn Baayen <jorn@openedhand.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-last-change-parser
|
|
Packit |
712bc5 |
* @short_description: A/V LastChange event XML parser
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* #GUPnPLastChangeParser parses XML strings from LastChange events that are
|
|
Packit |
712bc5 |
* generated by AVTransport and RenderingControl services.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
*/
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
#include <gobject/gvaluecollector.h>
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
#include "gupnp-last-change-parser.h"
|
|
Packit |
712bc5 |
#include "gvalue-util.h"
|
|
Packit |
712bc5 |
#include "xml-util.h"
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
G_DEFINE_TYPE (GUPnPLastChangeParser,
|
|
Packit |
712bc5 |
gupnp_last_change_parser,
|
|
Packit |
712bc5 |
G_TYPE_OBJECT);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static void
|
|
Packit |
712bc5 |
gupnp_last_change_parser_init (G_GNUC_UNUSED GUPnPLastChangeParser *parser)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static void
|
|
Packit |
712bc5 |
gupnp_last_change_parser_dispose (GObject *object)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
GObjectClass *gobject_class;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
gobject_class = G_OBJECT_CLASS (gupnp_last_change_parser_parent_class);
|
|
Packit |
712bc5 |
gobject_class->dispose (object);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static void
|
|
Packit |
712bc5 |
gupnp_last_change_parser_class_init (GUPnPLastChangeParserClass *klass)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
GObjectClass *object_class;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
object_class = G_OBJECT_CLASS (klass);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
object_class->dispose = gupnp_last_change_parser_dispose;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Reads a value of state variable @variable_name to an initialised GValue pair
|
|
Packit |
712bc5 |
* from the InstanceID node of a LastChange xml doc */
|
|
Packit |
712bc5 |
static gboolean
|
|
Packit |
712bc5 |
read_state_variable (const char *variable_name,
|
|
Packit |
712bc5 |
GValue *value,
|
|
Packit |
712bc5 |
xmlNode *instance_node)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlNode *variable_node;
|
|
Packit |
712bc5 |
const char *val_str;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
variable_node = xml_util_get_element (instance_node,
|
|
Packit |
712bc5 |
variable_name,
|
|
Packit |
712bc5 |
NULL);
|
|
Packit |
712bc5 |
if (!variable_node)
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
val_str = xml_util_get_attribute_content (variable_node, "val");
|
|
Packit |
712bc5 |
if (!val_str) {
|
|
Packit |
712bc5 |
g_warning ("No value provided for variable \"%s\" in "
|
|
Packit |
712bc5 |
"LastChange event",
|
|
Packit |
712bc5 |
variable_name);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
gvalue_util_set_value_from_string (value, val_str);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return TRUE;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
static xmlNode *
|
|
Packit |
712bc5 |
get_instance_node (xmlDoc *doc,
|
|
Packit |
712bc5 |
guint instance_id)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
xmlNode *node;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (doc->children == NULL)
|
|
Packit |
712bc5 |
return NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
for (node = doc->children->children;
|
|
Packit |
712bc5 |
node;
|
|
Packit |
712bc5 |
node = node->next) {
|
|
Packit |
712bc5 |
if (node->type != XML_ELEMENT_NODE)
|
|
Packit |
712bc5 |
continue;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (!xmlStrcmp (node->name, BAD_CAST ("InstanceID")) &&
|
|
Packit |
712bc5 |
xml_util_get_uint_attribute (node, "val", 0) == instance_id)
|
|
Packit |
712bc5 |
break;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return node;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* gupnp_last_change_parser_new:
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Return value: A new #GUPnPLastChangeParser
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
GUPnPLastChangeParser *
|
|
Packit |
712bc5 |
gupnp_last_change_parser_new (void)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
return g_object_new (GUPNP_TYPE_LAST_CHANGE_PARSER,
|
|
Packit |
712bc5 |
NULL);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* gupnp_last_change_parser_parse_last_change_valist:
|
|
Packit |
712bc5 |
* @parser: A #GUPnPLastChangeParser
|
|
Packit |
712bc5 |
* @instance_id: The ID of the AV instance caller is interested in
|
|
Packit |
712bc5 |
* @last_change_xml: The xml from the "LastChange" event to parse
|
|
Packit |
712bc5 |
* @error: The location where to store any error, or NULL
|
|
Packit |
712bc5 |
* @var_args: A va_list of tuples of state variable name, state variable type,
|
|
Packit |
712bc5 |
* and state variable value location, terminated with NULL. The state variable
|
|
Packit |
712bc5 |
* values should be freed after use
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* See gupnp_last_change_parser_parse_last_change(); this version takes a
|
|
Packit |
712bc5 |
* va_list for use by language bindings.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Return value: TRUE on success.
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
gboolean
|
|
Packit |
712bc5 |
gupnp_last_change_parser_parse_last_change_valist
|
|
Packit |
712bc5 |
(G_GNUC_UNUSED GUPnPLastChangeParser *parser,
|
|
Packit |
712bc5 |
guint instance_id,
|
|
Packit |
712bc5 |
const char *last_change_xml,
|
|
Packit |
712bc5 |
GError **error,
|
|
Packit |
712bc5 |
va_list var_args)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
const char *variable_name;
|
|
Packit |
712bc5 |
xmlDoc *doc;
|
|
Packit |
712bc5 |
xmlNode *instance_node;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_return_val_if_fail (last_change_xml, FALSE);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
doc = xmlParseDoc ((const xmlChar *) last_change_xml);
|
|
Packit |
712bc5 |
if (doc == NULL) {
|
|
Packit |
712bc5 |
g_set_error (error,
|
|
Packit |
712bc5 |
G_MARKUP_ERROR,
|
|
Packit |
712bc5 |
G_MARKUP_ERROR_PARSE,
|
|
Packit |
712bc5 |
"Could not parse LastChange xml");
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
instance_node = get_instance_node (doc, instance_id);
|
|
Packit |
712bc5 |
if (instance_node == NULL) {
|
|
Packit |
712bc5 |
/* This is not an error since the caller of this function
|
|
Packit |
712bc5 |
* doesn't (need to) know if the instance of his interest is
|
|
Packit |
712bc5 |
* part of the LastChange event received.
|
|
Packit |
712bc5 |
*/
|
|
Packit |
712bc5 |
xmlFreeDoc (doc);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return FALSE;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Variables */
|
|
Packit |
712bc5 |
variable_name = va_arg (var_args, const char *);
|
|
Packit |
712bc5 |
while (variable_name) {
|
|
Packit |
712bc5 |
GType variable_type;
|
|
Packit |
712bc5 |
GValue value = { 0, };
|
|
Packit |
712bc5 |
char *copy_error = NULL;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
variable_type = va_arg (var_args, GType);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_value_init (&value, variable_type);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (read_state_variable (variable_name,
|
|
Packit |
712bc5 |
&value,
|
|
Packit |
712bc5 |
instance_node)) {
|
|
Packit |
712bc5 |
G_VALUE_LCOPY (&value, var_args, 0, ©_error);
|
|
Packit |
712bc5 |
} else {
|
|
Packit |
712bc5 |
va_arg (var_args, gpointer);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_value_unset (&value);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
if (copy_error) {
|
|
Packit |
712bc5 |
g_warning ("Error copying value: %s", copy_error);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
g_free (copy_error);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
variable_name = va_arg (var_args, const char *);
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/* Cleanup */
|
|
Packit |
712bc5 |
xmlFreeDoc (doc);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return TRUE;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
/**
|
|
Packit |
712bc5 |
* gupnp_last_change_parser_parse_last_change:
|
|
Packit |
712bc5 |
* @parser: A #GUPnPLastChangeParser
|
|
Packit |
712bc5 |
* @instance_id: The ID of the AV instance caller is interested in
|
|
Packit |
712bc5 |
* @last_change_xml: The xml from the "LastChange" event to parse
|
|
Packit |
712bc5 |
* @error: The location where to store any error, or NULL
|
|
Packit |
712bc5 |
* @...: tuples of state variable name, state variable type, and state
|
|
Packit |
712bc5 |
* variable value location, terminated with NULL. The state variable values
|
|
Packit |
712bc5 |
* should be freed after use.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Parses the xml fragment from a LastChange event.
|
|
Packit |
712bc5 |
*
|
|
Packit |
712bc5 |
* Return value: TRUE on success.
|
|
Packit |
712bc5 |
**/
|
|
Packit |
712bc5 |
gboolean
|
|
Packit |
712bc5 |
gupnp_last_change_parser_parse_last_change
|
|
Packit |
712bc5 |
(GUPnPLastChangeParser *parser,
|
|
Packit |
712bc5 |
guint instance_id,
|
|
Packit |
712bc5 |
const char *last_change_xml,
|
|
Packit |
712bc5 |
GError **error,
|
|
Packit |
712bc5 |
...)
|
|
Packit |
712bc5 |
{
|
|
Packit |
712bc5 |
va_list var_args;
|
|
Packit |
712bc5 |
gboolean ret;
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
va_start (var_args, error);
|
|
Packit |
712bc5 |
ret = gupnp_last_change_parser_parse_last_change_valist
|
|
Packit |
712bc5 |
(parser,
|
|
Packit |
712bc5 |
instance_id,
|
|
Packit |
712bc5 |
last_change_xml,
|
|
Packit |
712bc5 |
error,
|
|
Packit |
712bc5 |
var_args);
|
|
Packit |
712bc5 |
va_end (var_args);
|
|
Packit |
712bc5 |
|
|
Packit |
712bc5 |
return ret;
|
|
Packit |
712bc5 |
}
|
|
Packit |
712bc5 |
|