diff --git a/src/epg.c b/src/epg.c index 6fb320a8..2b3c8470 100644 --- a/src/epg.c +++ b/src/epg.c @@ -45,12 +45,16 @@ #include "htsmsg_binary.h" #include "epggrab.h" +/* Broadcast hashing */ +#define EPG_HASH_WIDTH 1024 +#define EPG_HASH_MASK (EPG_HASH_WIDTH - 1) + /* Element lists */ -struct epg_object_tree epg_brands; -struct epg_object_tree epg_seasons; -struct epg_object_tree epg_episodes; -struct epg_object_tree epg_channels; -struct epg_object_tree epg_broadcasts; +epg_object_list_t epg_objects[EPG_HASH_WIDTH]; +epg_object_tree_t epg_brands; +epg_object_tree_t epg_seasons; +epg_object_tree_t epg_episodes; +epg_object_tree_t epg_channels; /* Unmapped */ LIST_HEAD(epg_channel_unmapped_list, epg_channel); @@ -59,10 +63,9 @@ struct epg_channel_unmapped_list epg_channel_unmapped; struct channel_unmapped_list channel_unmapped; /* Unreferenced */ -LIST_HEAD(epg_object_unref_list, epg_object); -struct epg_object_unref_list epg_object_unref; +epg_object_list_t epg_object_unref; -/* Global counters */ +/* Global counter */ static uint64_t _epg_object_idx = 0; /* ************************************************************************** @@ -332,6 +335,7 @@ static epg_object_t *_epg_object_find if (!eo->putref) eo->putref = _epg_object_putref; _epg_object_idx++; LIST_INSERT_HEAD(&epg_object_unref, eo, ulink); + LIST_INSERT_HEAD(&epg_objects[eo->id & EPG_HASH_WIDTH], eo, hlink); } } @@ -359,11 +363,20 @@ static epg_object_t *_epg_object_find_by_uri return eo; } -static epg_object_t *_epg_object_find_by_id +static epg_object_t *_epg_object_find_by_id2 ( uint64_t id ) +{ + epg_object_t *eo; + LIST_FOREACH(eo, &epg_objects[id & EPG_HASH_WIDTH], hlink) { + if (eo->id == id) return eo; + } + return NULL; +} + +static epg_object_t *_epg_object_find_by_id ( uint64_t id, epg_object_tree_t *tree ) { epg_object_t *eo; - if (!tree) return NULL; + if (!tree) return _epg_object_find_by_id2(id); RB_FOREACH(eo, tree, glink) { if ( eo->id == id ) return eo; } @@ -755,13 +768,12 @@ int epg_episode_set_number ( epg_episode_t *episode, uint16_t number ) int epg_episode_set_part ( epg_episode_t *episode, uint16_t part, uint16_t count ) { int save = 0; - // TODO: could treat part/count independently - if ( !episode || !part || !count ) return 0; + if ( !episode || !part ) return 0; if ( episode->part_number != part ) { episode->part_number = part; save |= 1; } - if ( episode->part_count != count ) { + if ( count && episode->part_count != count ) { episode->part_count = count; save |= 1; } @@ -925,14 +937,11 @@ epg_broadcast_t* epg_broadcast_find_by_time // TODO: allow optional channel parameter? epg_broadcast_t *epg_broadcast_find_by_id ( uint64_t id, epg_channel_t *ec ) { - epg_object_t *eo = NULL, *eoc; + epg_object_t *eo = NULL; if ( ec ) { eo = _epg_object_find_by_id(id, &((epg_channel_t*)ec)->schedule); } else { - RB_FOREACH(eoc, &epg_channels, glink) { - eo = _epg_object_find_by_id(id, &((epg_channel_t*)eoc)->schedule); - if (eo) break; - } + eo = _epg_object_find_by_id2(id); } return (epg_broadcast_t*)eo; } diff --git a/src/epg.h b/src/epg.h index 0137852d..87e208c3 100644 --- a/src/epg.h +++ b/src/epg.h @@ -32,6 +32,7 @@ /* * Map types */ +LIST_HEAD(epg_object_list, epg_object); RB_HEAD(epg_object_tree, epg_object); RB_HEAD(epg_brand_tree, epg_brand); RB_HEAD(epg_season_tree, epg_season); @@ -48,6 +49,7 @@ typedef struct epg_season epg_season_t; typedef struct epg_episode epg_episode_t; typedef struct epg_broadcast epg_broadcast_t; typedef struct epg_channel epg_channel_t; +typedef struct epg_object_list epg_object_list_t; typedef struct epg_object_tree epg_object_tree_t; typedef struct epg_brand_tree epg_brand_tree_t; typedef struct epg_season_tree epg_season_tree_t; @@ -62,7 +64,8 @@ typedef struct epg_broadcast_tree epg_broadcast_tree_t; /* Object */ typedef struct epg_object { - RB_ENTRY(epg_object) glink; ///< Global list link + RB_ENTRY(epg_object) glink; ///< Global (URI) list link + LIST_ENTRY(epg_object) hlink; ///< Global (ID) hash link LIST_ENTRY(epg_object) ulink; ///< Global unref'd link char *uri; ///< Unique ID (from grabber) @@ -150,8 +153,6 @@ epg_season_t *epg_season_deserialize ( htsmsg_t *m, int create, int *save ); /* ************************************************************************ * Episode - * - * TODO: ee_genre needs to be a list * ***********************************************************************/ /* Object */ @@ -192,6 +193,8 @@ int epg_episode_set_description ( epg_episode_t *e, const char *description ) __attribute__((warn_unused_result)); int epg_episode_set_number ( epg_episode_t *e, uint16_t number ) __attribute__((warn_unused_result)); +int epg_episode_set_onscreen ( epg_episode_t *e, const char *onscreen ) + __attribute__((warn_unused_result)); int epg_episode_set_part ( epg_episode_t *e, uint16_t number, uint16_t count ) __attribute__((warn_unused_result)); @@ -199,6 +202,10 @@ 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 ) + __attribute__((warn_unused_result)); +int epg_episode_set_genre_str ( epg_episode_t *e, const char *s ) + __attribute__((warn_unused_result)); /* EpNum format helper */ // output string will be: @@ -248,9 +255,9 @@ typedef struct epg_broadcast uint8_t is_new; ///< New series / file premiere uint8_t is_repeat; ///< Repeat screening - RB_ENTRY(epg_broadcast) elink; ///< Episode link - epg_episode_t *episode; ///< Episode shown - epg_channel_t *channel; ///< Channel being broadcast on + RB_ENTRY(epg_broadcast) elink; ///< Episode link + epg_episode_t *episode; ///< Episode shown + epg_channel_t *channel; ///< Channel being broadcast on } epg_broadcast_t; @@ -281,6 +288,7 @@ typedef struct epg_channel epg_object_t _; ///< Parent object char *name; ///< Channel name + char *icon; ///< Channel icon char **sname; ///< DVB svc names (to map) int **sid; ///< DVB svc ids (to map) @@ -302,6 +310,8 @@ epg_channel_t *epg_channel_find_by_id ( uint64_t id ); /* Mutators */ int epg_channel_set_name ( epg_channel_t *c, const char *n ) __attribute__((warn_unused_result)); +int epg_channel_set_icon ( epg_channel_t *c, const char *i ) + __attribute__((warn_unused_result)); int epg_channel_set_channel ( epg_channel_t *c, channel_t *ch ); /* Accessors */