diff options
author | crvi <crvisqr@gmail.com> | 2021-04-11 19:16:27 +0530 |
---|---|---|
committer | crvi <crvisqr@gmail.com> | 2021-09-15 16:07:16 +0530 |
commit | fb6eaaee686a4071532ec9cb62110819c38f170e (patch) | |
tree | b75ca0bdd3fe874015db53417c288bc060b13693 | |
parent | 87fc47f6d992b65d2baaa987bb985bc388457a9b (diff) | |
download | totem-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.c | 87 | ||||
-rw-r--r-- | plparse/totem-pl-parser.c | 6 | ||||
-rw-r--r-- | plparse/totem-pl-parser.h | 10 |
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. |