From 13da924f918ef0c455638bb448ccb7f34c5a9ae5 Mon Sep 17 00:00:00 2001 From: Adam Sutton Date: Fri, 8 Jun 2012 17:05:30 +0100 Subject: [PATCH] Started work on adding back in genre support. --- src/epg.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/epg.h | 61 +++----------- 2 files changed, 249 insertions(+), 50 deletions(-) diff --git a/src/epg.c b/src/epg.c index 76d0d92a..0a3576e4 100644 --- a/src/epg.c +++ b/src/epg.c @@ -898,6 +898,49 @@ int epg_episode_set_season ( epg_episode_t *episode, epg_season_t *season ) return save; } +int epg_episode_set_genre ( epg_episode_t *ee, const uint8_t *genre, int cnt ) +{ + int i, save = 0; + if (!ee || !genre || !cnt) return 0; + if (cnt != ee->genre_cnt) + save = 1; + else { + for (i = 0; i < cnt; i++ ) { + if (genre[i] != ee->genre[i]) { + save = 1; + break; + } + } + } + if (save) { + if (cnt > ee->genre_cnt) + ee->genre = realloc(ee->genre, cnt * sizeof(uint8_t)); + memcpy(ee->genre, genre, cnt * sizeof(uint8_t)); + ee->genre_cnt = cnt; + } + return save; +} + +// Note: only works for the EN 300 468 defined names +int epg_episode_set_genre_str ( epg_episode_t *ee, const char **gstr ) +{ + static int gcnt = 0; + static uint8_t *genre; + int cnt = 0; + while (gstr[cnt]) cnt++; + if (!cnt) return 0; + if (cnt > gcnt) { + genre = realloc(genre, sizeof(uint8_t) * cnt); + gcnt = cnt; + } + cnt = 0; + while (gstr[cnt]) { + genre[cnt] = epg_genre_find_by_name(gstr[cnt]); + cnt++; + } + return epg_episode_set_genre(ee, genre, gcnt); +} + static void _epg_episode_add_broadcast ( epg_episode_t *episode, epg_broadcast_t *broadcast ) { @@ -1281,6 +1324,201 @@ epg_broadcast_t *epg_broadcast_deserialize return ret; } +/* ************************************************************************** + * Genre + * *************************************************************************/ + +// FULL(ish) list from EN 300 468, I've excluded the last category +// that relates more to broadcast content than what I call a "genre" +// these will be handled elsewhere as broadcast metadata +static const char *_epg_genre_names[16][16] = { + {}, + { + "Movie/Drama", + "detective/thriller", + "adventure/western/war", + "science fiction/fantasy/horror", + "comedy", + "soap/melodrama/folkloric", + "romance", + "serious/classical/religious/historical movie/drama", + "adult movie/drama", + "adult movie/drama", + "adult movie/drama", + "adult movie/drama", + "adult movie/drama", + "adult movie/drama", + }, + { + "News/Current affairs", + "news/weather report", + "news magazine", + "documentary", + "discussion/interview/debate", + "discussion/interview/debate", + "discussion/interview/debate", + "discussion/interview/debate", + "discussion/interview/debate", + "discussion/interview/debate", + "discussion/interview/debate", + "discussion/interview/debate", + "discussion/interview/debate", + "discussion/interview/debate", + }, + { + "Show/Game show", + "game show/quiz/contest", + "variety show", + "talk show", + "talk show", + "talk show", + "talk show", + "talk show", + "talk show", + "talk show", + "talk show", + "talk show", + "talk show", + "talk show", + }, + { + "Sports", + "special events (Olympic Games, World Cup, etc.)", + "sports magazines", + "football/soccer", + "tennis/squash", + "team sports (excluding football)", + "athletics", + "motor sport", + "water sport", + }, + { + "Children's/Youth programmes", + "pre-school children's programmes", + "entertainment programmes for 6 to14", + "entertainment programmes for 10 to 16", + "informational/educational/school programmes", + "cartoons/puppets", + "cartoons/puppets", + "cartoons/puppets", + "cartoons/puppets", + "cartoons/puppets", + "cartoons/puppets", + "cartoons/puppets", + "cartoons/puppets", + "cartoons/puppets", + }, + { + "Music/Ballet/Dance", + "rock/pop", + "serious music/classical music", + "folk/traditional music", + "jazz", + "musical/opera", + "musical/opera", + "musical/opera", + "musical/opera", + "musical/opera", + "musical/opera", + "musical/opera", + "musical/opera", + }, + { + "Arts/Culture (without music)", + "performing arts", + "fine arts", + "religion", + "popular culture/traditional arts", + "literature", + "film/cinema", + "experimental film/video", + "broadcasting/press", + }, + { + "Social/Political issues/Economics", + "magazines/reports/documentary", + "economics/social advisory", + "remarkable people", + "remarkable people", + "remarkable people", + "remarkable people", + "remarkable people", + "remarkable people", + "remarkable people", + "remarkable people", + "remarkable people", + "remarkable people", + "remarkable people", + }, + { + "Education/Science/Factual topics", + "nature/animals/environment", + "technology/natural sciences", + "medicine/physiology/psychology", + "foreign countries/expeditions", + "social/spiritual sciences", + "further education", + "languages", + "languages", + "languages", + "languages", + "languages", + "languages", + "languages", + }, + { + "Leisure hobbies", + "tourism/travel", + "handicraft", + "motoring", + "fitness and health", + "cooking", + "advertisement/shopping", + "gardening", + "gardening", + "gardening", + "gardening", + "gardening", + "gardening", + "gardening", + } +}; + +// match strings, ignoring case and whitespace +// Note: | 0x20 is a cheats (fast) way of lowering case +static int _genre_str_match ( const char *a, const char *b ) +{ + int i = 0, j = 0; + if (!a || !b) return 0; + while (a[i] != '\0' || b[j] != '\0') { + while (a[i] == ' ') i++; + while (b[j] == ' ') j++; + if ((a[i] | 0x20) != (b[j] | 0x20)) return 0; + i++; j++; + } + return (a[i] == '\0' && b[j] == '\0'); // end of string(both) +} + +uint8_t epg_genre_find_by_name ( const char *name ) +{ + uint8_t a, b; + for ( a = 1; a < 11; a++ ) { + for ( b = 0; b < 16; b++ ) { + if (_genre_str_match(name, _epg_genre_names[a][b])) + return (a | (b << 4)); + } + } + return 0; // undefined +} + +const char *epg_genre_get_name ( uint8_t genre, int full ) +{ + int a, b = 0; + a = genre & 0xF; + if (full) b = (genre >> 4) & 0xF; + return _epg_genre_names[a][b]; +} + /* ************************************************************************** * Querying * *************************************************************************/ diff --git a/src/epg.h b/src/epg.h index ad686063..dff7f268 100644 --- a/src/epg.h +++ b/src/epg.h @@ -94,7 +94,6 @@ struct epg_object void (*updated) ( epg_object_t* ); ///< Updated }; - /* ************************************************************************ * Brand - Represents a specific show * e.g. The Simpsons, 24, Eastenders, etc... @@ -184,7 +183,8 @@ struct epg_episode char *subtitle; ///< Sub-title char *summary; ///< Summary char *description; ///< An extended description - uint8_t genre; ///< Episode genre + uint8_t *genre; ///< Episode genre(s) + int genre_cnt; ///< Genre count uint16_t number; ///< The episode number uint16_t part_number; ///< For multipart episodes uint16_t part_count; ///< For multipart episodes @@ -222,9 +222,9 @@ int epg_episode_set_brand ( epg_episode_t *e, epg_brand_t *b ) __attribute__((warn_unused_result)); int epg_episode_set_season ( epg_episode_t *e, epg_season_t *s ) __attribute__((warn_unused_result)); -int epg_episode_set_genre ( epg_episode_t *e, uint8_t g ) +int epg_episode_set_genre ( epg_episode_t *e, const uint8_t *g, int c ) __attribute__((warn_unused_result)); -int epg_episode_set_genre_str ( epg_episode_t *e, const char *s ) +int epg_episode_set_genre_str ( epg_episode_t *e, const char **s ) __attribute__((warn_unused_result)); /* EpNum format helper */ @@ -313,6 +313,13 @@ epg_broadcast_t *epg_channel_get_broadcast /* Unlink */ void epg_channel_unlink ( struct channel *ch ); +/* ************************************************************************ + * Genre + * ***********************************************************************/ + +uint8_t epg_genre_find_by_name ( const char *name ); +const char *epg_genre_get_name ( uint8_t genre, int full ); + /* ************************************************************************ * Querying * ***********************************************************************/ @@ -347,50 +354,4 @@ void epg_init (void); void epg_save (void); void epg_updated (void); -/* ************************************************************************ - * Compatibility code - * ***********************************************************************/ - -//#define TODO_EPG_COMPAT -#ifdef TODO_EPG_COMPAT - -typedef struct _epg_episode { - - uint16_t ee_season; - uint16_t ee_episode; - uint16_t ee_part; - - char *ee_onscreen; -} _epg_episode_t; - - -/* - * EPG event - */ -typedef struct event { - LIST_ENTRY(event) e_global_link; - - struct channel *e_channel; - RB_ENTRY(event) e_channel_link; - - int e_refcount; - uint32_t e_id; - - uint8_t e_content_type; - - time_t e_start; /* UTC time */ - time_t e_stop; /* UTC time */ - - char *e_title; /* UTF-8 encoded */ - char *e_desc; /* UTF-8 encoded */ - char *e_ext_desc;/* UTF-8 encoded (from extended descriptor) */ - char *e_ext_item;/* UTF-8 encoded (from extended descriptor) */ - char *e_ext_text;/* UTF-8 encoded (from extended descriptor) */ - - int e_dvb_id; - - _epg_episode_t e_episode; - -} event_t; -#endif #endif /* EPG_H */