/* Reads a value of state variable @variable_name to an initialised GValue pair * from the InstanceID node of a LastChange xml doc */ static gboolean read_state_variable (const char *variable_name, GValue *value, xmlNode *instance_node) { xmlNode *variable_node; const char *val_str; variable_node = xml_util_get_element (instance_node, variable_name, NULL); if (!variable_node) return FALSE; val_str = xml_util_get_attribute_content (variable_node, "val"); if (!val_str) { g_warning ("No value provided for variable \"%s\" in " "LastChange event", variable_name); return FALSE; } gvalue_util_set_value_from_string (value, val_str); return TRUE; }
static void init_uuid (void) { xmlNode *uuid_node; char *udn; uuid = gupnp_get_uuid (); uuid_node = xml_util_get_element ((xmlNode *) doc->doc, "root", "device", "UDN", NULL); if (uuid_node == NULL) { g_critical ("Failed to find UDN element" "in device description"); return; } udn = g_strdup_printf ("uuid:%s", uuid); xmlNodeSetContent (uuid_node, (unsigned char *) udn); g_free (udn); }
/* * Called when the description document is loaded. */ static void description_loaded (GUPnPControlPoint *control_point, GUPnPXMLDoc *doc, const char *udn, const char *service_type, const char *description_url) { xmlNode *element; SoupURI *url_base; /* Save the URL base, if any */ element = xml_util_get_element ((xmlNode *) doc->doc, "root", NULL); if (element == NULL) { g_warning ("No 'root' element found in description document" " '%s'. Ignoring device '%s'\n", description_url, udn); return; } if (element == NULL) return; url_base = xml_util_get_child_element_content_uri (element, "URLBase", NULL); if (!url_base) url_base = soup_uri_new (description_url); /* Iterate matching devices */ process_device_list (element, control_point, doc, udn, service_type, description_url, url_base); /* Cleanup */ soup_uri_free (url_base); }
static void init_friendly_name (gchar *name) { xmlNode *fdn_node; fdn_node = xml_util_get_element ((xmlNode *) doc->doc, "root", "device", "friendlyName", NULL); if (fdn_node == NULL) { g_warning ("Failed to find friendly name element" "in device description, " "using default value"); return; } xmlNodeSetContent (fdn_node, (unsigned char *) name); }
/* Recursively search @element for matching devices */ static void process_device_list (xmlNode *element, GUPnPControlPoint *control_point, GUPnPXMLDoc *doc, const char *udn, const char *service_type, const char *description_url, SoupURI *url_base) { g_object_ref (control_point); for (element = element->children; element; element = element->next) { xmlNode *children; xmlChar *prop; gboolean match; if (strcmp ((char *) element->name, "device") != 0) continue; /* Recurse into children */ children = xml_util_get_element (element, "deviceList", NULL); if (children) { process_device_list (children, control_point, doc, udn, service_type, description_url, url_base); } /* See if this is a matching device */ prop = xml_util_get_child_element_content (element, "UDN"); if (!prop) continue; match = (strcmp ((char *) prop, udn) == 0); xmlFree (prop); if (!match) continue; /* Match */ if (service_type) { /* Dive into serviceList */ children = xml_util_get_element (element, "serviceList", NULL); if (children) { process_service_list (children, control_point, doc, udn, service_type, description_url, url_base); } } else create_and_report_device_proxy (control_point, doc, element, udn, description_url, url_base); } g_object_unref (control_point); }
/** * gupnp_device_info_get_icon_url: * @info: A #GUPnPDeviceInfo * @requested_mime_type: (allow-none) (transfer none): The requested file * format, or %NULL for any * @requested_depth: The requested color depth, or -1 for any * @requested_width: The requested width, or -1 for any * @requested_height: The requested height, or -1 for any * @prefer_bigger: %TRUE if a bigger, rather than a smaller icon should be * returned if no exact match could be found * @mime_type: (out) (allow-none): The location where to store the the format * of the returned icon, or %NULL. The returned string should be freed after * use * @depth: (out) (allow-none) : The location where to store the depth of the * returned icon, or %NULL * @width: (out) (allow-none) : The location where to store the width of the * returned icon, or %NULL * @height: (out) (allow-none) : The location where to store the height of the * returned icon, or %NULL * * Get a URL pointing to the icon most closely matching the * given criteria, or %NULL. If @requested_mime_type is set, only icons with * this mime type will be returned. If @requested_depth is set, only icons with * this or lower depth will be returned. If @requested_width and/or * @requested_height are set, only icons that are this size or smaller are * returned, unless @prefer_bigger is set, in which case the next biggest icon * will be returned. The returned strings should be freed. * * Return value: (transfer full): a string, or %NULL. g_free() after use. **/ char * gupnp_device_info_get_icon_url (GUPnPDeviceInfo *info, const char *requested_mime_type, int requested_depth, int requested_width, int requested_height, gboolean prefer_bigger, char **mime_type, int *depth, int *width, int *height) { GList *icons, *l; xmlNode *element; Icon *icon, *closest; char *ret; g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL); /* List available icons */ icons = NULL; element = xml_util_get_element (info->priv->element, "iconList", NULL); if (!element) return NULL; for (element = element->children; element; element = element->next) { if (!strcmp ("icon", (char *) element->name)) { gboolean mime_type_ok; icon = icon_parse (info, element); if (requested_mime_type) { mime_type_ok = !strcmp (requested_mime_type, (char *) icon->mime_type); } else mime_type_ok = TRUE; if (requested_depth >= 0) icon->weight = requested_depth - icon->depth; /* Filter out icons with incorrect mime type or * incorrect depth. */ if (mime_type_ok && icon->weight >= 0) { if (requested_width >= 0) { if (prefer_bigger) { icon->weight += icon->width - requested_width; } else { icon->weight += requested_width - icon->width; } } if (requested_height >= 0) { if (prefer_bigger) { icon->weight += icon->height - requested_height; } else { icon->weight += requested_height - icon->height; } } icons = g_list_prepend (icons, icon); } else icon_free (icon); } } if (icons == NULL) return NULL; /* Find closest match */ closest = NULL; for (l = icons; l; l = l->next) { icon = l->data; /* Look between icons with positive weight first */ if (icon->weight >= 0) { if (!closest || icon->weight < closest->weight) closest = icon; } } if (!closest) { for (l = icons; l; l = l->next) { icon = l->data; /* No icons with positive weight, look at ones with * negative weight */ if (!closest || icon->weight > closest->weight) closest = icon; } } /* Fill in return values */ if (closest) { icon = closest; if (mime_type) { if (icon->mime_type) { *mime_type = g_strdup ((char *) icon->mime_type); } else *mime_type = NULL; } if (depth) *depth = icon->depth; if (width) *width = icon->width; if (height) *height = icon->height; if (icon->url) { SoupURI *uri; uri = soup_uri_new_with_base (info->priv->url_base, (const char *) icon->url); ret = soup_uri_to_string (uri, FALSE); soup_uri_free (uri); } else ret = NULL; } else { if (mime_type) *mime_type = NULL; if (depth) *depth = -1; if (width) *width = -1; if (height) *height = -1; ret = NULL; } /* Cleanup */ while (icons) { icon_free (icons->data); icons = g_list_delete_link (icons, icons); } return ret; }
gupnp_device_info_list_devices (GUPnPDeviceInfo *info) { GUPnPDeviceInfoClass *class; GList *devices; xmlNode *element; g_return_val_if_fail (GUPNP_IS_DEVICE_INFO (info), NULL); class = GUPNP_DEVICE_INFO_GET_CLASS (info); g_return_val_if_fail (class->get_device, NULL); devices = NULL; element = xml_util_get_element (info->priv->element, "deviceList", NULL); if (!element) return NULL; for (element = element->children; element; element = element->next) { if (!strcmp ("device", (char *) element->name)) { GUPnPDeviceInfo *child; child = class->get_device (info, element); devices = g_list_prepend (devices, child); } } return devices; }
/** * gupnp_didl_lite_parser_parse_didl_recursive: * @parser: A #GUPnPDIDLLiteParser * @didl: The DIDL-Lite XML string to be parsed * @error: The location where to store any error, or %NULL * * Parses DIDL-Lite XML string @didl, emitting the ::object-available, * ::item-available and ::container-available signals appropriately during the * process. * * Return value: TRUE on success. **/ gboolean gupnp_didl_lite_parser_parse_didl_recursive (GUPnPDIDLLiteParser *parser, const char *didl, gboolean recursive, GError **error) { xmlDoc *doc; xmlNode *element; xmlNs *upnp_ns = NULL; xmlNs *dc_ns = NULL; xmlNs *dlna_ns = NULL; xmlNs *pv_ns = NULL; GUPnPAVXMLDoc *xml_doc = NULL; gboolean result; doc = xmlRecoverMemory (didl, strlen (didl)); if (doc == NULL) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "Could not parse DIDL-Lite XML:\n%s", didl); return FALSE; } /* Get a pointer to root element */ element = xml_util_get_element ((xmlNode *) doc, "DIDL-Lite", NULL); if (element == NULL) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "No 'DIDL-Lite' node in the DIDL-Lite XML:\n%s", didl); xmlFreeDoc (doc); return FALSE; } if (element->children == NULL) { g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_EMPTY, "Empty 'DIDL-Lite' node in the DIDL-Lite XML:\n%s", didl); xmlFreeDoc (doc); return FALSE; } /* Create namespaces if they don't exist */ upnp_ns = xml_util_lookup_namespace (doc, GUPNP_XML_NAMESPACE_UPNP); if (! upnp_ns) upnp_ns = xml_util_create_namespace (xmlDocGetRootElement (doc), GUPNP_XML_NAMESPACE_UPNP); dc_ns = xml_util_lookup_namespace (doc, GUPNP_XML_NAMESPACE_DC); if (! dc_ns) dc_ns = xml_util_create_namespace (xmlDocGetRootElement (doc), GUPNP_XML_NAMESPACE_DC); dlna_ns = xml_util_lookup_namespace (doc, GUPNP_XML_NAMESPACE_DLNA); if (! dlna_ns) dlna_ns = xml_util_create_namespace (xmlDocGetRootElement (doc), GUPNP_XML_NAMESPACE_DLNA); pv_ns = xml_util_lookup_namespace (doc, GUPNP_XML_NAMESPACE_PV); if (! pv_ns) pv_ns = xml_util_create_namespace (xmlDocGetRootElement (doc), GUPNP_XML_NAMESPACE_PV); xml_doc = xml_doc_new (doc); result = parse_elements (parser, element, xml_doc, upnp_ns, dc_ns, dlna_ns, pv_ns, recursive, error); xml_doc_unref (xml_doc); return result; }