summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcrvi <crvisqr@gmail.com>2021-04-11 19:16:27 +0530
committercrvi <crvisqr@gmail.com>2021-09-15 16:07:16 +0530
commitfb6eaaee686a4071532ec9cb62110819c38f170e (patch)
treeb75ca0bdd3fe874015db53417c288bc060b13693
parent87fc47f6d992b65d2baaa987bb985bc388457a9b (diff)
downloadtotem-pl-parser-fb6eaaee686a4071532ec9cb62110819c38f170e.tar.gz
podcast: Add itunes genre ( <itunes:category> ) support for podcast rss feeds
Refer: https://podcasts.apple.com/us/genre/podcasts/id26 for full list of genres supported by <itunes:category> tag. Considering "MG = Main Genre" and "SG = Sub Genre", iTunes genre can be of the following 2 basic forms: 1. MG ( E.g. Business ) 2. MG/SG ( E.g. Science/Astronomy ) The first such genre value is assigned to TOTEM_PL_PARSER_FIELD_GENRE metadata field Combinations of the above 2 forms are valid too: 1. MG,MG/SG etc ( E.g. Music,Leisure/Hobbies ) 2. MG1/SG1,MG2/SG2 etc ( E.g. Business/Investing,Education/Self Improvement ) The full genre value is assigned to TOTEM_PL_PARSER_FIELD_GENRES metadata field
-rw-r--r--plparse/totem-pl-parser-podcast.c87
-rw-r--r--plparse/totem-pl-parser.c6
-rw-r--r--plparse/totem-pl-parser.h10
3 files changed, 101 insertions, 2 deletions
diff --git a/plparse/totem-pl-parser-podcast.c b/plparse/totem-pl-parser-podcast.c
index 16a31d6..458fbb7 100644
--- a/plparse/totem-pl-parser-podcast.c
+++ b/plparse/totem-pl-parser-podcast.c
@@ -39,6 +39,9 @@
#define ATOM_NEEDLE "<feed"
#define OPML_NEEDLE "<opml"
+#define GENRE_SEPARATOR ','
+#define SUB_GENRE_SEPARATOR '/'
+
static const char *
totem_pl_parser_is_xml_type (const char *data,
gsize len,
@@ -111,6 +114,69 @@ xml_parser_get_node_value (xml_node_t *parent, const char *node_name)
return NULL;
}
+/*
+ * <itunes:category text="Health & Fitness"> <-- xml_node
+ * <itunes:category text="Alternative Health"/>
+ * </itunes:category>
+ *
+ * get_itunes_subgenre (xml_node)
+ *
+ * returns "Alternative Health"
+ *
+ */
+static const char *
+get_itunes_subgenre (xml_node_t *parent)
+{
+ xml_node_t *child;
+ const char *sub_genre = NULL;
+
+ for (child = parent->child; child != NULL; child = child->next) {
+ if (child->name == NULL)
+ continue;
+
+ if (g_ascii_strcasecmp (child->name, "itunes:category") == 0) {
+ sub_genre = xml_parser_get_property (child, "text");
+
+ /* we expect atmost one itunes subgenre */
+ break;
+ }
+ }
+
+ return sub_genre;
+}
+
+/*
+ * <itunes:category text="Technology"> <-- xml_node
+ * <itunes:category text="Tech News"/>
+ * </itunes:category>
+ *
+ * get_itunes_genre (xml_node)
+ *
+ * returns "Technology/Tech News"
+ *
+ */
+static char *
+get_itunes_genre (xml_node_t *node)
+{
+ char *genre = NULL;
+ const char *main_genre = NULL;
+
+ main_genre = xml_parser_get_property (node, "text");
+
+ /* if main genre exists, check and append sub-genres */
+ if (main_genre != NULL) {
+ const char *sub_genre;
+ sub_genre = get_itunes_subgenre (node);
+
+ if (sub_genre != NULL)
+ genre = g_strdup_printf ("%s%c%s", main_genre, SUB_GENRE_SEPARATOR, sub_genre);
+ else
+ genre = g_strdup (main_genre);
+ }
+
+ return genre;
+}
+
static gboolean
is_image (const char *url)
{
@@ -323,8 +389,12 @@ parse_rss_items (TotemPlParser *parser, const char *uri, xml_node_t *parent)
{
const char *title, *language, *description, *author;
const char *contact, *img, *pub_date, *copyright, *generator, *explicit;
+ g_autofree char *genre = NULL;
+ g_autofree char *genres = NULL;
+ GString *genres_str;
xml_node_t *node;
+ genres_str = NULL;
title = language = description = author = NULL;
contact = img = pub_date = copyright = generator = explicit = NULL;
@@ -378,9 +448,24 @@ parse_rss_items (TotemPlParser *parser, const char *uri, xml_node_t *parent)
copyright = node->data;
} else if (g_ascii_strcasecmp (node->name, "itunes:explicit") == 0) {
explicit = node->data;
+ } else if (g_ascii_strcasecmp (node->name, "itunes:category") == 0) {
+ /* only one primary genre */
+ if (genre == NULL) {
+ genre = get_itunes_genre (node);
+ genres_str = g_string_new (genre);
+ } else {
+ char *tmp;
+
+ tmp = get_itunes_genre (node);
+ g_string_append_printf (genres_str, "%c%s", GENRE_SEPARATOR, tmp);
+ g_free (tmp);
+ }
}
}
+ if (genres_str)
+ genres = g_string_free (genres_str, FALSE);
+
/* update generator as author, only as last resort */
if (!author && generator)
author = generator;
@@ -390,6 +475,8 @@ parse_rss_items (TotemPlParser *parser, const char *uri, xml_node_t *parent)
TOTEM_PL_PARSER_FIELD_IS_PLAYLIST, TRUE,
TOTEM_PL_PARSER_FIELD_URI, uri,
TOTEM_PL_PARSER_FIELD_TITLE, title,
+ TOTEM_PL_PARSER_FIELD_GENRE, genre,
+ TOTEM_PL_PARSER_FIELD_GENRES, genres,
TOTEM_PL_PARSER_FIELD_LANGUAGE, language,
TOTEM_PL_PARSER_FIELD_DESCRIPTION, description,
TOTEM_PL_PARSER_FIELD_AUTHOR, author,
diff --git a/plparse/totem-pl-parser.c b/plparse/totem-pl-parser.c
index 32fd435..b16ccdb 100644
--- a/plparse/totem-pl-parser.c
+++ b/plparse/totem-pl-parser.c
@@ -462,7 +462,11 @@ totem_pl_parser_class_init (TotemPlParserClass *klass)
G_PARAM_READABLE & G_PARAM_WRITABLE);
g_param_spec_pool_insert (totem_pl_parser_pspec_pool, pspec, TOTEM_TYPE_PL_PARSER);
pspec = g_param_spec_string ("genre", "genre",
- "Genre of the item to be added", NULL,
+ "Primary genre of the item to be added", NULL,
+ G_PARAM_READABLE & G_PARAM_WRITABLE);
+ g_param_spec_pool_insert (totem_pl_parser_pspec_pool, pspec, TOTEM_TYPE_PL_PARSER);
+ pspec = g_param_spec_string ("genres", "genres",
+ "Full genre of the item to be added", NULL,
G_PARAM_READABLE & G_PARAM_WRITABLE);
g_param_spec_pool_insert (totem_pl_parser_pspec_pool, pspec, TOTEM_TYPE_PL_PARSER);
pspec = g_param_spec_string ("album", "album",
diff --git a/plparse/totem-pl-parser.h b/plparse/totem-pl-parser.h
index 1b10d4f..7cee4d1 100644
--- a/plparse/totem-pl-parser.h
+++ b/plparse/totem-pl-parser.h
@@ -84,10 +84,18 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(TotemPlParser, g_object_unref)
/**
* TOTEM_PL_PARSER_FIELD_GENRE:
*
- * Metadata field for an entry's genre.
+ * Metadata field for an entry's primary genre. This is a string of
+ * the form 'Genre1' or 'Genre1/SubGenre1".
**/
#define TOTEM_PL_PARSER_FIELD_GENRE "genre"
/**
+ * TOTEM_PL_PARSER_FIELD_GENRES:
+ *
+ * Metadata field for an entry's full genre. This is a concatenated
+ * string of the form 'Genre1/SubGenre1,Genre2/SubGenre2" etc.
+ **/
+#define TOTEM_PL_PARSER_FIELD_GENRES "genres"
+/**
* TOTEM_PL_PARSER_FIELD_TITLE:
*
* Metadata field for an entry's displayable title.