diff options
author | Jens Georg <mail@jensge.org> | 2022-10-20 00:38:05 +0200 |
---|---|---|
committer | Jens Georg <mail@jensge.org> | 2022-10-20 21:50:40 +0200 |
commit | 03d996353cf6eca52ce28e37b5dc560605d110e2 (patch) | |
tree | 78a27cd161b77d83d408b0c2bf276cee68795899 | |
parent | e9fb08b74971b87d59f50cd8d11e6ce0422f24da (diff) | |
download | gupnp-av-wip/phako/clocksync.tar.gz |
wip: Implement BOOKMARKS featurewip/phako/clocksync
-rw-r--r-- | libgupnp-av/gupnp-didl-lite-createclass.h | 1 | ||||
-rw-r--r-- | libgupnp-av/gupnp-feature-clocksync.c | 0 | ||||
-rw-r--r-- | libgupnp-av/gupnp-feature-clocksync.h | 0 | ||||
-rw-r--r-- | libgupnp-av/gupnp-feature-container-shortcuts.c | 124 | ||||
-rw-r--r-- | libgupnp-av/gupnp-feature-container-shortcuts.h | 52 | ||||
-rw-r--r-- | libgupnp-av/gupnp-feature-list-parser.c | 18 | ||||
-rw-r--r-- | libgupnp-av/gupnp-feature-private.h | 19 | ||||
-rw-r--r-- | libgupnp-av/gupnp-feature.c | 82 | ||||
-rw-r--r-- | libgupnp-av/meson.build | 1 | ||||
-rw-r--r-- | libgupnp-av/xml-util.c | 6 | ||||
-rw-r--r-- | tests/check-feature-list-parser.c | 41 |
11 files changed, 334 insertions, 10 deletions
diff --git a/libgupnp-av/gupnp-didl-lite-createclass.h b/libgupnp-av/gupnp-didl-lite-createclass.h index 3d33f9e..3f734ea 100644 --- a/libgupnp-av/gupnp-didl-lite-createclass.h +++ b/libgupnp-av/gupnp-didl-lite-createclass.h @@ -15,7 +15,6 @@ #include <glib-object.h> #include <libxml/tree.h> -#include "gupnp-didl-lite-container.h" G_BEGIN_DECLS diff --git a/libgupnp-av/gupnp-feature-clocksync.c b/libgupnp-av/gupnp-feature-clocksync.c new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/libgupnp-av/gupnp-feature-clocksync.c diff --git a/libgupnp-av/gupnp-feature-clocksync.h b/libgupnp-av/gupnp-feature-clocksync.h new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/libgupnp-av/gupnp-feature-clocksync.h diff --git a/libgupnp-av/gupnp-feature-container-shortcuts.c b/libgupnp-av/gupnp-feature-container-shortcuts.c new file mode 100644 index 0000000..8dffd6d --- /dev/null +++ b/libgupnp-av/gupnp-feature-container-shortcuts.c @@ -0,0 +1,124 @@ +#include "gupnp-feature-container-shortcuts.h" +#include "gupnp-feature-private.h" +#include "xml-util.h" + +#include <libxml/tree.h> + +struct _GUPnPContainerShortcut { + GUPnPAVXMLDoc *doc; + xmlNodePtr node; +}; + + +struct _GUPnPFeatureContainerShortcuts { + GUPnPFeature parent; +}; + +G_DEFINE_TYPE (GUPnPFeatureContainerShortcuts, + gupnp_feature_container_shortcuts, + GUPNP_TYPE_FEATURE) + +static void +gupnp_feature_container_shortcuts_init (GUPnPFeatureContainerShortcuts *self) +{ +} + +static void +gupnp_feature_container_shortcuts_class_init ( + GUPnPFeatureContainerShortcutsClass *klass) +{ +} + +/** + * gupnp_feature_container_shortcuts_get_list: + * + * Get the supported shortcuts on that feature. + * + * Returns: (element-type: GUPnPContainerShortcut): List + * of shortcuts included in this feature. + */ +GSList * +gupnp_feature_container_shortcuts_get_list ( + GUPnPFeatureContainerShortcuts *self) +{ + xmlNode *node = gupnp_feature_get_node (GUPNP_FEATURE (self)); + xmlNode *shortcuts_node = + av_xml_util_get_element (node, "shortcutlist", NULL); + + if (shortcuts_node == NULL) { + return NULL; + } + + GList *shortcuts = + av_xml_util_get_child_elements_by_name (shortcuts_node, + "shortcut"); + GList *it = shortcuts; + GSList *retval = NULL; + + while (it != NULL) { + GUPnPContainerShortcut *shortcut = + g_rc_box_new0 (GUPnPContainerShortcut); + + shortcut->doc = gupnp_feature_get_doc (GUPNP_FEATURE (self)); + shortcut->node = it->data; + + retval = g_slist_prepend (retval, shortcut); + it = it->next; + } + + return g_slist_reverse(retval); +} + +/** + * gupnp_container_shortcut_type: + * + * Get the gtype for GUPnPServiceActon + * + * Return value: The gtype of GUPnPServiceAction + **/ +GType +gupnp_container_shortcut_get_type (void) +{ + static GType our_type = 0; + + if (our_type == 0) + our_type = g_boxed_type_register_static ( + "GUPnPServiceAction", + (GBoxedCopyFunc) gupnp_container_shortcut_ref, + (GBoxedFreeFunc) gupnp_container_shortcut_unref); + + return our_type; +} + +GUPnPContainerShortcut * +gupnp_container_shortcut_ref (GUPnPContainerShortcut *shortcut) +{ + return g_rc_box_acquire (shortcut); +} + +static void +gupnp_container_shortcut_free (GUPnPContainerShortcut *shortcut) +{ + g_clear_pointer (&shortcut->doc, av_xml_doc_unref); +} + +void +gupnp_container_shortcut_unref (GUPnPContainerShortcut *shortcut) +{ + g_rc_box_release_full (shortcut, + (GDestroyNotify) gupnp_container_shortcut_free); +} + + +const char * +gupnp_container_shortcut_get_name (GUPnPContainerShortcut *shortcut) +{ + return av_xml_util_get_child_element_content (shortcut->node, "name"); +} + +const char * +gupnp_container_shortcut_get_object_id (GUPnPContainerShortcut *shortcut) +{ + return av_xml_util_get_child_element_content (shortcut->node, + "objectID"); +} diff --git a/libgupnp-av/gupnp-feature-container-shortcuts.h b/libgupnp-av/gupnp-feature-container-shortcuts.h new file mode 100644 index 0000000..5fb475d --- /dev/null +++ b/libgupnp-av/gupnp-feature-container-shortcuts.h @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// SPDX-FileCopyrightText: 2022 Jens Georg <mail@jensge.org> + +#pragma once + +#include <config.h> + +#include "gupnp-feature.h" + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define GUPNP_TYPE_FEATURE_CONTAINER_SHORTCUTS \ + (gupnp_feature_container_shortcuts_get_type ()) + +G_DECLARE_FINAL_TYPE (GUPnPFeatureContainerShortcuts, + gupnp_feature_container_shortcuts, + GUPNP, + FEATURE_CONTAINER_SHORTCUTS, + GUPnPFeature) + +typedef struct _GUPnPContainerShortcut GUPnPContainerShortcut; + +#define GUPNP_TYPE_CONTAINER_SHORTCUT (gupnp_container_shortcut_get_type ()) + +struct _GUPnPFeatureContainerShortcutsClass { + GUPnPFeature parent_class; +}; + +GSList *gupnp_feature_container_shortcuts_get_list( + GUPnPFeatureContainerShortcuts *self); + +GType +gupnp_container_shortcut_get_type (void); + +GUPnPContainerShortcut * +gupnp_container_shortcut_ref (GUPnPContainerShortcut *); + +void +gupnp_container_shortcut_unref (GUPnPContainerShortcut *); + +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GUPnPContainerShortcut, + gupnp_container_shortcut_unref) + +const char * +gupnp_container_shortcut_get_name (GUPnPContainerShortcut *); + +const char * +gupnp_container_shortcut_get_object_id (GUPnPContainerShortcut *); + +G_END_DECLS diff --git a/libgupnp-av/gupnp-feature-list-parser.c b/libgupnp-av/gupnp-feature-list-parser.c index 16208b5..f4fe357 100644 --- a/libgupnp-av/gupnp-feature-list-parser.c +++ b/libgupnp-av/gupnp-feature-list-parser.c @@ -113,6 +113,7 @@ gupnp_feature_list_parser_parse_text xmlDoc *doc; xmlNode *element; GList *feature_list = NULL; + GUPnPAVXMLDoc *xml_doc = NULL; doc = xmlRecoverMemory (text, strlen (text)); if (doc == NULL) { @@ -124,6 +125,8 @@ gupnp_feature_list_parser_parse_text return NULL; } + xml_doc = av_xml_doc_new (doc); + /* Get a pointer to root element */ element = av_xml_util_get_element ((xmlNode *) doc, "Features", NULL); if (element == NULL) { @@ -168,9 +171,16 @@ gupnp_feature_list_parser_parse_text object_ids = get_feature_object_ids (element); feature = g_object_new (GUPNP_TYPE_FEATURE, - "name", name, - "version", version, - "object-ids", object_ids, + "doc", + xml_doc, + "node", + element, + "name", + name, + "version", + version, + "object-ids", + object_ids, NULL); feature_list = g_list_append (feature_list, feature); @@ -179,7 +189,7 @@ gupnp_feature_list_parser_parse_text } } - xmlFreeDoc (doc); + av_xml_doc_unref (xml_doc); return feature_list; } diff --git a/libgupnp-av/gupnp-feature-private.h b/libgupnp-av/gupnp-feature-private.h new file mode 100644 index 0000000..908ac5d --- /dev/null +++ b/libgupnp-av/gupnp-feature-private.h @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later +// SPDX-FileCopyrightText: 2022 Jens Georg <mail@jensge.org> + +#pragma once + +#include "gupnp-feature.h" +#include "xml-util.h" + +G_BEGIN_DECLS + +G_GNUC_INTERNAL +GUPnPAVXMLDoc * +gupnp_feature_get_doc (GUPnPFeature *feature); + +G_GNUC_INTERNAL +xmlNode * +gupnp_feature_get_node (GUPnPFeature *feature); + +G_END_DECLS diff --git a/libgupnp-av/gupnp-feature.c b/libgupnp-av/gupnp-feature.c index ee12015..0f3f566 100644 --- a/libgupnp-av/gupnp-feature.c +++ b/libgupnp-av/gupnp-feature.c @@ -17,11 +17,18 @@ #include <config.h> #include "gupnp-feature.h" +#include "gupnp-feature-private.h" + +#include "xml-util.h" + +#include <libxml/tree.h> struct _GUPnPFeaturePrivate { char *name; char *version; char *object_ids; + GUPnPAVXMLDoc *doc; + xmlNode *node; }; typedef struct _GUPnPFeaturePrivate GUPnPFeaturePrivate; @@ -33,7 +40,9 @@ enum { PROP_0, PROP_NAME, PROP_VERSION, - PROP_OBJECT_IDS + PROP_OBJECT_IDS, + PROP_DOC, + PROP_NODE }; static void @@ -78,6 +87,12 @@ gupnp_feature_get_property (GObject *object, g_value_set_string (value, gupnp_feature_get_object_ids (feature)); break; + case PROP_DOC: + g_value_set_boxed (value, gupnp_feature_get_doc (feature)); + break; + case PROP_NODE: + g_value_set_pointer (value, gupnp_feature_get_node (feature)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -101,7 +116,16 @@ gupnp_feature_set_property (GObject *object, priv->version = g_value_dup_string (value); break; case PROP_OBJECT_IDS: - priv->object_ids = g_value_dup_string (value); + if (G_VALUE_HOLDS(value, G_TYPE_STRING)) + priv->object_ids = g_value_dup_string (value); + else + priv->object_ids = NULL; + break; + case PROP_DOC: + priv->doc = g_value_dup_boxed (value); + break; + case PROP_NODE: + priv->node = g_value_get_pointer (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -173,6 +197,37 @@ gupnp_feature_class_init (GUPnPFeatureClass *klass) G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB)); + + /** + * GUPnPFeature:doc: + * + * The XML Doc of the feature list that contains this feature. + **/ + g_object_class_install_property ( + object_class, + PROP_DOC, + g_param_spec_boxed ("doc", + "XML document", + "XML document for the feature list that " + "contains this feature", + av_xml_doc_get_type (), + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + + /** + * GUPnPFeature:node: + * + * The XML node for this feature + **/ + g_object_class_install_property ( + object_class, + PROP_OBJECT_IDS, + g_param_spec_pointer ("node", + "XML node", + "XML node of this feature", + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); } /** @@ -209,6 +264,24 @@ gupnp_feature_get_version (GUPnPFeature *feature) return priv->version; } +GUPnPAVXMLDoc * +gupnp_feature_get_doc (GUPnPFeature *feature) +{ + GUPnPFeaturePrivate *priv = + gupnp_feature_get_instance_private (GUPNP_FEATURE (feature)); + + return av_xml_doc_ref (priv->doc); +} + +xmlNode * +gupnp_feature_get_node (GUPnPFeature *feature) +{ + GUPnPFeaturePrivate *priv = + gupnp_feature_get_instance_private (GUPNP_FEATURE (feature)); + + return priv->node; +} + /** * gupnp_feature_get_object_ids: * @feature: #GUPnPFeature @@ -216,8 +289,11 @@ gupnp_feature_get_version (GUPnPFeature *feature) * Get the object IDs related to the @feature. * * Return value: The object IDs related to the @feature. + * + * Deprecated. Use gupnp_feature_bookmarks_get_object_ids() or + * gupnp_feature_epg_get_object_ids() instead **/ -const char * +G_GNUC_DEPRECATED const char * gupnp_feature_get_object_ids (GUPnPFeature *feature) { GUPnPFeaturePrivate *priv = diff --git a/libgupnp-av/meson.build b/libgupnp-av/meson.build index 89cc927..769c886 100644 --- a/libgupnp-av/meson.build +++ b/libgupnp-av/meson.build @@ -16,6 +16,7 @@ introspection_sources = [ 'gupnp-didl-lite-writer.c', 'gupnp-dlna.c', 'gupnp-feature.c', + 'gupnp-feature-container-shortcuts.c', 'gupnp-feature-list-parser.c', 'gupnp-last-change-parser.c', 'gupnp-media-collection.c', diff --git a/libgupnp-av/xml-util.c b/libgupnp-av/xml-util.c index 0d1661b..a72ad00 100644 --- a/libgupnp-av/xml-util.c +++ b/libgupnp-av/xml-util.c @@ -54,6 +54,12 @@ av_xml_doc_free (GUPnPAVXMLDoc *doc) g_clear_pointer (&doc->doc, xmlFreeDoc); } +GUPnPAVXMLDoc * +av_xml_doc_ref (GUPnPAVXMLDoc *doc) +{ + return g_rc_box_acquire (doc); +} + void av_xml_doc_unref (GUPnPAVXMLDoc *doc) { diff --git a/tests/check-feature-list-parser.c b/tests/check-feature-list-parser.c index 94e968a..7011a67 100644 --- a/tests/check-feature-list-parser.c +++ b/tests/check-feature-list-parser.c @@ -10,17 +10,21 @@ #include <config.h> #include <libgupnp-av/gupnp-feature-list-parser.h> +#include <libgupnp-av/gupnp-feature-container-shortcuts.h> + #include <stdlib.h> #include <string.h> static const char * const names[] = { "BOOKMARK", "EPG", + "CONTAINER_SHORTCUTS", }; static const char * const versions[] = { "1", "2", + "1", }; static const char * const ids[] = { @@ -28,6 +32,17 @@ static const char * const ids[] = { "epg1,epg2", }; +static const char *const container_names[] = { + "MUSIC_GENRES", + "IMAGES_ALL", +}; + +static const char *const container_ids[] = { + "container:genre", + "container:images_all", +}; + +//clang-format off static const char *text = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" "<Features " @@ -43,7 +58,20 @@ static const char *text = "<Feature name=\"EPG\" version=\"2\">" "<objectIDs>epg1,epg2</objectIDs>" "</Feature>" + "<Feature name=\"CONTAINER_SHORTCUTS\" version=\"1\">" + "<shortcutlist>" + "<shortcut>" + "<name>MUSIC_GENRES</name>" + "<objectID>container:genre</objectID>" + "</shortcut>" + "<shortcut>" + "<name>IMAGES_ALL</name>" + "<objectID>container:images_all</objectID>" + "</shortcut>" + "</shortcutlist>" + "</Feature>" "</Features>"; +// clang-format on static gboolean check_feature (GUPnPFeature *feature) @@ -54,11 +82,20 @@ check_feature (GUPnPFeature *feature) return FALSE; if (strcmp (versions[index], gupnp_feature_get_version (feature))) - return FALSE; + return FALSE; - if (strcmp (ids[index], gupnp_feature_get_object_ids (feature))) + if (index < 2) { + if (strcmp (ids[index], gupnp_feature_get_object_ids (feature))) + return FALSE; + } else { + if (!GUPNP_IS_FEATURE_CONTAINER_SHORTCUTS (feature)) return FALSE; + GUPnPFeatureContainerShortcuts *f = + GUPNP_FEATURE_CONTAINER_SHORTCUTS (feature); + + GSList *s = gupnp_feature_container_shortcuts_get_list (f); + } index++; return TRUE; |