From: Andreas Ă–man Date: Sat, 18 Jul 2009 20:07:47 +0000 (+0000) Subject: * Try to detect duplicate EPG entries from the DVB feed and adjust X-Git-Tag: 2.12~572 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=be1a42d9092550ffa892e39ef91026e1405192d2;p=thirdparty%2Ftvheadend.git * Try to detect duplicate EPG entries from the DVB feed and adjust EPG accordingly. The EPG code will search for events with the same DVB event ID +- 2 events from the current one. If the event id is equal, the prvious (old) entry will be removed in favor of the new one. Reason for not blindingly trusting the event id is that some networks seem to (incorrectly) reuse IDs. Ticket #65 --- diff --git a/debian/changelog b/debian/changelog index c801cb35d..616931dbc 100644 --- a/debian/changelog +++ b/debian/changelog @@ -69,6 +69,13 @@ hts-tvheadend (2.3) hts; urgency=low * Add exponential backoff for reconnect attempt in code word client. Ticket #80 + * Try to detect duplicate EPG entries from the DVB feed and adjust + EPG accordingly. The EPG code will search for events with the same + DVB event ID +- 2 events from the current one. If the event id is + equal, the prvious (old) entry will be removed in favor of the new one. + Reason for not blindingly trusting the event id is that some networks + seem to (incorrectly) reuse IDs. + hts-tvheadend (2.2) hts; urgency=low * Set $HOME so forked processes (XMLTV) will have correct environment diff --git a/src/dvb/dvb_tables.c b/src/dvb/dvb_tables.c index 34addda2f..2364b7c65 100644 --- a/src/dvb/dvb_tables.c +++ b/src/dvb/dvb_tables.c @@ -522,7 +522,8 @@ dvb_eit_callback(th_dvb_mux_instance_t *tdmi, uint8_t *ptr, int len, continue; } - if((e = epg_event_create(ch, start_time, start_time + duration)) == NULL) { + if((e = epg_event_create(ch, start_time, start_time + duration, + event_id)) == NULL) { len -= dllen; ptr += dllen; continue; diff --git a/src/epg.c b/src/epg.c index 938a1c3c1..ce2a5630c 100644 --- a/src/epg.c +++ b/src/epg.c @@ -165,14 +165,74 @@ epg_event_set_content_type(event_t *e, epg_content_type_t *ect) } + +/** + * + */ +static void +epg_event_destroy(event_t *e) +{ + if(e->e_content_type != NULL) + LIST_REMOVE(e, e_content_type_link); + + free((void *)e->e_title); + free((void *)e->e_desc); + LIST_REMOVE(e, e_global_link); + free(e); +} + +/** + * + */ +static void +epg_event_unref(event_t *e) +{ + if(e->e_refcount > 1) { + e->e_refcount--; + return; + } + assert(e->e_refcount == 1); + epg_event_destroy(e); +} + +/** + * + */ +static void +epg_remove_event_from_channel(channel_t *ch, event_t *e) +{ + int wasfirst = e == RB_FIRST(&ch->ch_epg_events); + event_t *n = RB_NEXT(e, e_channel_link); + + assert(e->e_channel == ch); + + RB_REMOVE(&ch->ch_epg_events, e, e_channel_link); + e->e_channel = NULL; + epg_event_unref(e); + + if(ch->ch_epg_current == e) { + epg_set_current(ch, NULL); + + if(n != NULL) + gtimer_arm_abs(&ch->ch_epg_timer_current, epg_ch_check_current_event, + ch, n->e_start); + } + + if(wasfirst && (e = RB_FIRST(&ch->ch_epg_events)) != NULL) { + gtimer_arm_abs(&ch->ch_epg_timer_head, epg_expire_event_from_channel, + ch, e->e_stop); + } +} + + /** * */ event_t * -epg_event_create(channel_t *ch, time_t start, time_t stop) +epg_event_create(channel_t *ch, time_t start, time_t stop, int dvb_id) { static event_t *skel; - event_t *e; + event_t *e, *p, *n; static int tally; if((stop - start) > 11 * 3600) @@ -196,6 +256,7 @@ epg_event_create(channel_t *ch, time_t start, time_t stop) e->e_id = ++tally; e->e_stop = stop; + e->e_dvb_id = dvb_id; LIST_INSERT_HEAD(&epg_hash[e->e_id & EPG_GLOBAL_HASH_MASK], e, e_global_link); @@ -228,7 +289,7 @@ epg_event_create(channel_t *ch, time_t start, time_t stop) printf("Event %s on %s extended stop time\n", e->e_title, e->e_channel->ch_name); printf("Previous %s", ctime(&e->e_stop)); - printf(" New %s", ctime(&stop)); + printf(" New %s", ctime(&stop)); #endif e->e_stop = stop; epg_event_changed(e); @@ -239,6 +300,29 @@ epg_event_create(channel_t *ch, time_t start, time_t stop) } } } + + + if(dvb_id != -1) { + /* Erase any close events with the same DVB event id */ + + if((p = RB_PREV(e, e_channel_link)) != NULL) { + if(p->e_dvb_id == dvb_id) { + epg_remove_event_from_channel(ch, p); + } else if((p = RB_PREV(p, e_channel_link)) != NULL) { + if(p->e_dvb_id == dvb_id) + epg_remove_event_from_channel(ch, p); + } + } + + if((n = RB_NEXT(e, e_channel_link)) != NULL) { + if(n->e_dvb_id == dvb_id) { + epg_remove_event_from_channel(ch, n); + } else if((n = RB_NEXT(n, e_channel_link)) != NULL) { + if(n->e_dvb_id == dvb_id) + epg_remove_event_from_channel(ch, n); + } + } + } return e; } @@ -274,64 +358,6 @@ epg_event_find_by_id(int eventid) } -/** - * - */ -static void -epg_event_destroy(event_t *e) -{ - if(e->e_content_type != NULL) - LIST_REMOVE(e, e_content_type_link); - - free((void *)e->e_title); - free((void *)e->e_desc); - LIST_REMOVE(e, e_global_link); - free(e); -} - -/** - * - */ -static void -epg_event_unref(event_t *e) -{ - if(e->e_refcount > 1) { - e->e_refcount--; - return; - } - assert(e->e_refcount == 1); - epg_event_destroy(e); -} - -/** - * - */ -static void -epg_remove_event_from_channel(channel_t *ch, event_t *e) -{ - int wasfirst = e == RB_FIRST(&ch->ch_epg_events); - event_t *n = RB_NEXT(e, e_channel_link); - - assert(e->e_channel == ch); - - RB_REMOVE(&ch->ch_epg_events, e, e_channel_link); - e->e_channel = NULL; - epg_event_unref(e); - - if(ch->ch_epg_current == e) { - epg_set_current(ch, NULL); - - if(n != NULL) - gtimer_arm_abs(&ch->ch_epg_timer_current, epg_ch_check_current_event, - ch, n->e_start); - } - - if(wasfirst && (e = RB_FIRST(&ch->ch_epg_events)) != NULL) { - gtimer_arm_abs(&ch->ch_epg_timer_head, epg_expire_event_from_channel, - ch, e->e_stop); - } -} - /** * diff --git a/src/epg.h b/src/epg.h index 3a3952b16..9c922e2d2 100644 --- a/src/epg.h +++ b/src/epg.h @@ -61,10 +61,7 @@ typedef struct event { const char *e_title; /* UTF-8 encoded */ const char *e_desc; /* UTF-8 encoded */ - int e_source; /* higer is better, and we never downgrade */ - -#define EVENT_SRC_XMLTV 1 -#define EVENT_SRC_DVB 2 + int e_dvb_id; } event_t; @@ -80,7 +77,8 @@ void epg_event_set_desc(event_t *e, const char *desc); void epg_event_set_content_type(event_t *e, epg_content_type_t *ect); -event_t *epg_event_create(channel_t *ch, time_t start, time_t stop); +event_t *epg_event_create(channel_t *ch, time_t start, time_t stop, + int dvb_id); event_t *epg_event_find_by_time(channel_t *ch, time_t t); diff --git a/src/xmltv.c b/src/xmltv.c index 247d7db57..db03b1eaa 100644 --- a/src/xmltv.c +++ b/src/xmltv.c @@ -334,7 +334,7 @@ xmltv_parse_programme_tags(xmltv_channel_t *xc, htsmsg_t *tags, const char *desc = xmltv_get_cdata_by_tag(tags, "desc"); LIST_FOREACH(ch, &xc->xc_channels, ch_xc_link) { - if((e = epg_event_create(ch, start, stop)) == NULL) + if((e = epg_event_create(ch, start, stop, -1)) == NULL) continue; if(title != NULL) epg_event_set_title(e, title);