Blame libgupnp-av/gupnp-last-change-parser.c

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, &copy_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