📄 gupnp-service-introspection.c
字号:
/* * Copyright (C) 2007 Zeeshan Ali <zeenix@gstreamer.net> * Copyright (C) 2006, 2007 OpenedHand Ltd. * * Author: Zeeshan Ali <zeenix@gstreamer.net> * Jorn Baayen <jorn@openedhand.com> * * 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., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. *//** * SECTION:gupnp-service-introspection * @short_description: Service introspection class. * * The #GUPnPServiceIntrospection class provides methods for service * introspection based on information contained in its service description * document (SCPD). There is no constructor provided for this class, please use * #gupnp_service_info_get_introspection or * #gupnp_service_info_get_introspection_async to create an * #GUPnPServiceIntrospection object for a specific service. * * Note that all the introspection information is retreived from the service * description document (SCPD) provided by the service and hence can not be * guaranteed to be complete. A UPnP service is required to provide an SCPD but * unfortunately, many services either do not provide this document or the * document does not provide any or all of the introspection information. * * This class exposes internals of the UPnP protocol and should not need * to be used for regular device or control point development. * **/#include <libsoup/soup.h>#include <string.h>#include "gupnp-service-introspection.h"#include "gupnp-service-introspection-private.h"#include "xml-util.h"#include "gvalue-util.h"#include "gupnp-types.h"#include "gupnp-types-private.h"#define MAX_FIXED_14_4 99999999999999.9999G_DEFINE_TYPE (GUPnPServiceIntrospection, gupnp_service_introspection, G_TYPE_OBJECT);struct _GUPnPServiceIntrospectionPrivate { GList *variables; GList *actions; /* For caching purposes */ GList *action_names; GList *variable_names;};enum { PROP_0, PROP_SCPD};static voidconstruct_introspection_info (GUPnPServiceIntrospection *introspection, xmlDoc *scpd);/** * gupnp_service_state_variable_info_free * @argument: A #GUPnPServiceStateVariableInfo * * Frees a #GUPnPServiceStateVariableInfo. * **/static voidgupnp_service_state_variable_info_free (GUPnPServiceStateVariableInfo *variable){ g_free (variable->name); g_value_unset (&variable->default_value); if (variable->is_numeric) { g_value_unset (&variable->minimum); g_value_unset (&variable->maximum); g_value_unset (&variable->step); } g_list_foreach (variable->allowed_values, (GFunc) g_free, NULL); g_list_free (variable->allowed_values); g_slice_free (GUPnPServiceStateVariableInfo, variable);}static voidgupnp_service_introspection_init (GUPnPServiceIntrospection *introspection){ introspection->priv = G_TYPE_INSTANCE_GET_PRIVATE (introspection, GUPNP_TYPE_SERVICE_INTROSPECTION, GUPnPServiceIntrospectionPrivate);}static voidgupnp_service_introspection_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec){ GUPnPServiceIntrospection *introspection; introspection = GUPNP_SERVICE_INTROSPECTION (object); switch (property_id) { case PROP_SCPD: /* Construct introspection data */ construct_introspection_info (introspection, g_value_get_pointer (value)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; }}/** * gupnp_service_action_arg_info_free * @argument: A #GUPnPServiceActionArgInfo * * Frees a #GUPnPServiceActionArgInfo. * **/static voidgupnp_service_action_arg_info_free (GUPnPServiceActionArgInfo *argument){ g_free (argument->name); g_free (argument->related_state_variable); g_slice_free (GUPnPServiceActionArgInfo, argument);}/** * gupnp_service_action_info_free * @argument: A #GUPnPServiceActionInfo * * Frees a #GUPnPServiceActionInfo. * **/static voidgupnp_service_action_info_free (GUPnPServiceActionInfo *action_info){ GList *iter; g_free (action_info->name); for (iter = action_info->arguments; iter; iter = iter->next) { gupnp_service_action_arg_info_free ( (GUPnPServiceActionArgInfo *) iter->data); } g_list_free (action_info->arguments); g_slice_free (GUPnPServiceActionInfo, action_info);}static voidgupnp_service_introspection_finalize (GObject *object){ GUPnPServiceIntrospection *introspection; introspection = GUPNP_SERVICE_INTROSPECTION (object); if (introspection->priv->variables) { g_list_foreach (introspection->priv->variables, (GFunc) gupnp_service_state_variable_info_free, NULL); g_list_free (introspection->priv->variables); } if (introspection->priv->actions) { g_list_foreach (introspection->priv->actions, (GFunc) gupnp_service_action_info_free, NULL); g_list_free (introspection->priv->actions); } if (introspection->priv->variable_names) g_list_free (introspection->priv->variable_names); if (introspection->priv->action_names) g_list_free (introspection->priv->action_names);}static voidgupnp_service_introspection_class_init (GUPnPServiceIntrospectionClass *klass){ GObjectClass *object_class; object_class = G_OBJECT_CLASS (klass); object_class->set_property = gupnp_service_introspection_set_property; object_class->finalize = gupnp_service_introspection_finalize; g_type_class_add_private (klass, sizeof (GUPnPServiceIntrospectionPrivate)); /** * GUPnPServiceIntrospection:scpd * * The scpd of the device description file. **/ g_object_class_install_property (object_class, PROP_SCPD, g_param_spec_pointer ("scpd", "SCPD", "Pointer to SCPD", G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));}static voidset_default_value (xmlNodePtr variable_node, GUPnPServiceStateVariableInfo *variable){ xmlChar *default_str; default_str = xml_util_get_child_element_content (variable_node, "defaultValue"); if (default_str) { gvalue_util_set_value_from_string (&variable->default_value, (char *) default_str); xmlFree (default_str); }}static voidset_string_value_limits (xmlNodePtr limit_node, GList **limits){ xmlNodePtr value_node; for (value_node = limit_node->children; value_node; value_node = value_node->next) { xmlChar *allowed_value; if (strcmp ("allowedValue", (char *) value_node->name) != 0) continue; allowed_value = xmlNodeGetContent (value_node); if (!allowed_value) continue; *limits = g_list_append (*limits, g_strdup ((char *) allowed_value)); xmlFree (allowed_value); }}static voidset_value_limit_by_name (xmlNodePtr limit_node, GValue *limit, char *limit_name){ xmlChar *limit_str; limit_str = xml_util_get_child_element_content (limit_node, limit_name); if (limit_str) { gvalue_util_set_value_from_string (limit, (char *) limit_str); xmlFree (limit_str); }}static voidset_variable_limits (xmlNodePtr variable_node, GUPnPServiceStateVariableInfo *variable){ xmlNodePtr limit_node; if (variable->is_numeric) { limit_node = xml_util_get_element (variable_node, "allowedValueRange", NULL); if (limit_node == NULL) return; set_value_limit_by_name (limit_node, &(variable->minimum), "minimum"); set_value_limit_by_name (limit_node, &(variable->maximum), "maximum"); set_value_limit_by_name (limit_node, &(variable->step), "step"); } else if (variable->type == G_TYPE_STRING) { limit_node = xml_util_get_element (variable_node, "allowedValueList", NULL); if (limit_node == NULL) return; set_string_value_limits (limit_node, &(variable->allowed_values)); }}static gbooleanset_variable_type (GUPnPServiceStateVariableInfo *variable, char *data_type){ GType type; if (strcmp ("string", data_type) == 0) { type = G_TYPE_STRING; } else if (strcmp ("char", data_type) == 0) { type = G_TYPE_CHAR; } else if (strcmp ("boolean", data_type) == 0) { type = G_TYPE_BOOLEAN; } else if (strcmp ("i1", data_type) == 0) { type = G_TYPE_INT; g_value_init (&variable->minimum, type); g_value_set_int (&variable->minimum, G_MININT8); g_value_init (&variable->maximum, type); g_value_set_int (&variable->maximum, G_MAXINT8); g_value_init (&variable->step, type); g_value_set_int (&variable->step, 1); variable->is_numeric = TRUE; } else if (strcmp ("i2", data_type) == 0) { type = G_TYPE_INT; g_value_init (&variable->minimum, type); g_value_set_int (&variable->minimum, G_MININT16); g_value_init (&variable->maximum, type); g_value_set_int (&variable->maximum, G_MAXINT16); g_value_init (&variable->step, type); g_value_set_int (&variable->step, 1); variable->is_numeric = TRUE; } else if (strcmp ("i4", data_type) == 0 || strcmp ("int", data_type) == 0) { type = G_TYPE_INT; g_value_init (&variable->minimum, type); g_value_set_int (&variable->minimum, G_MININT32); g_value_init (&variable->maximum, type); g_value_set_int (&variable->maximum, G_MAXINT32); g_value_init (&variable->step, type); g_value_set_int (&variable->step, 1); variable->is_numeric = TRUE; } else if (strcmp ("ui1", data_type) == 0) { type = G_TYPE_UINT; g_value_init (&variable->minimum, type); g_value_set_uint (&variable->minimum, 0); g_value_init (&variable->maximum, type); g_value_set_uint (&variable->maximum, G_MAXUINT8); g_value_init (&variable->step, type); g_value_set_uint (&variable->step, 1); variable->is_numeric = TRUE; } else if (strcmp ("ui2", data_type) == 0) { type = G_TYPE_UINT; g_value_init (&variable->minimum, type); g_value_set_uint (&variable->minimum, 0); g_value_init (&variable->maximum, type); g_value_set_uint (&variable->maximum, G_MAXUINT16); g_value_init (&variable->step, type); g_value_set_uint (&variable->step, 1); variable->is_numeric = TRUE; } else if (strcmp ("ui4", data_type) == 0) { type = G_TYPE_UINT; g_value_init (&variable->minimum, type); g_value_set_uint (&variable->minimum, 0); g_value_init (&variable->maximum, type); g_value_set_uint (&variable->maximum, G_MAXUINT32); g_value_init (&variable->step, type); g_value_set_uint (&variable->step, 1); variable->is_numeric = TRUE; } else if (strcmp ("r4", data_type) == 0) { type = G_TYPE_FLOAT; g_value_init (&variable->minimum, type); g_value_set_float (&variable->minimum, -G_MAXFLOAT); g_value_init (&variable->maximum, type); g_value_set_float (&variable->maximum, G_MAXFLOAT); g_value_init (&variable->step, type); g_value_set_float (&variable->step, 1.0); variable->is_numeric = TRUE; } else if (strcmp ("r8", data_type) == 0 || strcmp ("number", data_type) == 0) { type = G_TYPE_DOUBLE; g_value_init (&variable->minimum, type); g_value_set_double (&variable->minimum, -G_MAXDOUBLE); g_value_init (&variable->maximum, type); g_value_set_double (&variable->maximum, G_MAXDOUBLE); g_value_init (&variable->step, type); g_value_set_double (&variable->step, 1.0); variable->is_numeric = TRUE; } else if (strcmp ("fixed.14.4", data_type) == 0) { /* Just how did this get into the UPnP specs? */ type = G_TYPE_DOUBLE; g_value_init (&variable->minimum, type); g_value_set_double (&variable->minimum, -MAX_FIXED_14_4); g_value_init (&variable->maximum, type); g_value_set_double (&variable->maximum, MAX_FIXED_14_4); g_value_init (&variable->step, type); g_value_set_double (&variable->step, 1.0); variable->is_numeric = TRUE; } /* TODO: "float", "int" */ else { type = gupnp_data_type_to_gtype (data_type); } if (type == G_TYPE_INVALID) { g_warning ("Unkown type '%s' in the SCPD", data_type); return FALSE; } g_value_init (&variable->default_value, type); variable->type = type; return TRUE;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -