From f924187bfc38277ea945aad648c000bc162e73e1 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 9 Sep 2011 20:24:49 +1000 Subject: [PATCH 1/2] * Cancel DVR entries for events that are removed from EPG * Handle networks that change DVB event ID when updating event details --- src/dvr/dvr.h | 2 ++ src/dvr/dvr_db.c | 26 +++++++++++++++++----- src/epg.c | 57 ++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index d2d6d476..169886dd 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -254,6 +254,8 @@ void dvr_rec_subscribe(dvr_entry_t *de); void dvr_rec_unsubscribe(dvr_entry_t *de, int stopcode); +void dvr_event_cancelled(event_t *e); + dvr_entry_t *dvr_entry_find_by_id(int id); dvr_entry_t *dvr_entry_find_by_event(event_t *e); diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 6a31b2d4..84462f5f 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -630,6 +630,23 @@ dvr_entry_update(dvr_entry_t *de, const char* de_title, int de_start, int de_sto return de; } +/** + * Used to notify the DVR that an event has been removed from the EPG + */ +void +dvr_event_cancelled(event_t *e) +{ + dvr_entry_t *de; + + de = dvr_entry_find_by_event(e); + if (de != NULL) { + if (de->de_sched_state == DVR_SCHEDULED) + dvr_entry_cancel(de); + } + + +} + /** * */ @@ -721,8 +738,7 @@ dvr_entry_find_by_event(event_t *e) } /** - * Find event with same title starting and ending around same time - * on same channel + * Find dvr entry using 'fuzzy' search */ dvr_entry_t * dvr_entry_find_by_event_fuzzy(event_t *e) @@ -730,10 +746,8 @@ dvr_entry_find_by_event_fuzzy(event_t *e) dvr_entry_t *de; LIST_FOREACH(de, &e->e_channel->ch_dvrs, de_channel_link) - if(strcmp(de->de_title, e->e_title) == 0) { - if ((abs(de->de_start - e->e_start) < 600) && (abs(de->de_stop - e->e_stop) < 600)) - return de; - } + if (abs(de->de_start - e->e_start) < 600 && abs(de->de_stop - e->e_stop) < 600) + return de; return NULL; } diff --git a/src/epg.c b/src/epg.c index 49d00740..40be0001 100644 --- a/src/epg.c +++ b/src/epg.c @@ -41,6 +41,9 @@ static struct event_list epg_hash[EPG_GLOBAL_HASH_WIDTH]; static void epg_expire_event_from_channel(void *opauqe); static void epg_ch_check_current_event(void *aux); +/* helper function to fuzzy compare two events */ +static int epg_event_cmp_overlap(event_t *e1, event_t *e2); +static void epg_erase_duplicates(event_t *e, channel_t *ch); static int @@ -330,7 +333,7 @@ epg_event_create(channel_t *ch, time_t start, time_t stop, int dvb_id, int *created) { static event_t *skel; - event_t *e, *p, *n; + event_t *e; static int tally; if(created != NULL) @@ -404,31 +407,71 @@ epg_event_create(channel_t *ch, time_t start, time_t stop, int dvb_id, } } + epg_erase_duplicates(e, ch); + return e; +} + +static void +epg_erase_duplicates(event_t *e, channel_t *ch) { + + event_t *p, *n; + int dvb_id = e->e_dvb_id; if(dvb_id != -1) { - /* Erase any close events with the same DVB event id */ + /* Erase any close events with the same DVB event id or are very similar*/ if((p = RB_PREV(e, e_channel_link)) != NULL) { - if(p->e_dvb_id == dvb_id) { + if(p->e_dvb_id == dvb_id || epg_event_cmp_overlap(p, e)) { + tvhlog(LOG_DEBUG, "epg", + "Removing overlapping event instance %s from EPG", p->e_title); + dvr_event_cancelled(p); epg_remove_event_from_channel(ch, p); } else if((p = RB_PREV(p, e_channel_link)) != NULL) { - if(p->e_dvb_id == dvb_id) + if(p->e_dvb_id == dvb_id || epg_event_cmp_overlap(p, e)) { + tvhlog(LOG_DEBUG, "epg", + "Removing overlapping event instance %s from EPG", p->e_title); + dvr_event_cancelled(p); epg_remove_event_from_channel(ch, p); + } } } if((n = RB_NEXT(e, e_channel_link)) != NULL) { - if(n->e_dvb_id == dvb_id) { + if(n->e_dvb_id == dvb_id || epg_event_cmp_overlap(n, e)) { + tvhlog(LOG_DEBUG, "epg", + "Removing overlapping event instance %s from EPG", n->e_title); + dvr_event_cancelled(n); epg_remove_event_from_channel(ch, n); } else if((n = RB_NEXT(n, e_channel_link)) != NULL) { - if(n->e_dvb_id == dvb_id) + if(n->e_dvb_id == dvb_id || epg_event_cmp_overlap(n, e)) { + tvhlog(LOG_DEBUG, "epg", + "Removing overlapping event instance %s from EPG", n->e_title); + dvr_event_cancelled(n); epg_remove_event_from_channel(ch, n); + } } } } - return e; + } +static int +epg_event_cmp_overlap(event_t *e1, event_t *e2) +{ + if ((e1->e_title == NULL) || (e2->e_title == NULL)) + return 0; + + if ((e1->e_stop < e2->e_start) || (e2->e_stop < e1->e_start)) { + return 0; + } else { + if ((e1->e_start < e2->e_stop) && (e2->e_start < e1->e_stop)) { + if ((e1->e_stop - e2->e_start) > 60 || (e2->e_stop - e1->e_start) > 60) + return 1; + } + } + + return 0; +} /** * From e6159c437323bb0a68f67f593d9f9cd5b86dc01a Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 11 Sep 2011 15:30:24 +1000 Subject: [PATCH 2/2] Improved logic when an event is replaced in EPG This is needed to avoid removing DVR entries that are not based on an AutoRec --- src/dvr/dvr.h | 2 +- src/dvr/dvr_db.c | 11 +++++++---- src/epg.c | 8 ++++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/dvr/dvr.h b/src/dvr/dvr.h index 169886dd..b91a1b90 100644 --- a/src/dvr/dvr.h +++ b/src/dvr/dvr.h @@ -254,7 +254,7 @@ void dvr_rec_subscribe(dvr_entry_t *de); void dvr_rec_unsubscribe(dvr_entry_t *de, int stopcode); -void dvr_event_cancelled(event_t *e); +void dvr_event_replaced(event_t *e, event_t *new_e); dvr_entry_t *dvr_entry_find_by_id(int id); diff --git a/src/dvr/dvr_db.c b/src/dvr/dvr_db.c index 84462f5f..5e5f4373 100644 --- a/src/dvr/dvr_db.c +++ b/src/dvr/dvr_db.c @@ -631,17 +631,20 @@ dvr_entry_update(dvr_entry_t *de, const char* de_title, int de_start, int de_sto } /** - * Used to notify the DVR that an event has been removed from the EPG + * Used to notify the DVR that an event has been replaced in the EPG */ void -dvr_event_cancelled(event_t *e) +dvr_event_replaced(event_t *e, event_t *new_e) { - dvr_entry_t *de; + dvr_entry_t *de, *ude; de = dvr_entry_find_by_event(e); if (de != NULL) { - if (de->de_sched_state == DVR_SCHEDULED) + ude = dvr_entry_find_by_event_fuzzy(new_e); + if (ude == NULL && de->de_sched_state == DVR_SCHEDULED) dvr_entry_cancel(de); + else + dvr_entry_update(de, new_e->e_title, new_e->e_start, new_e->e_stop); } diff --git a/src/epg.c b/src/epg.c index 40be0001..e15d7003 100644 --- a/src/epg.c +++ b/src/epg.c @@ -424,13 +424,13 @@ epg_erase_duplicates(event_t *e, channel_t *ch) { if(p->e_dvb_id == dvb_id || epg_event_cmp_overlap(p, e)) { tvhlog(LOG_DEBUG, "epg", "Removing overlapping event instance %s from EPG", p->e_title); - dvr_event_cancelled(p); + dvr_event_replaced(p, e); 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_event_cmp_overlap(p, e)) { tvhlog(LOG_DEBUG, "epg", "Removing overlapping event instance %s from EPG", p->e_title); - dvr_event_cancelled(p); + dvr_event_replaced(p, e); epg_remove_event_from_channel(ch, p); } } @@ -440,13 +440,13 @@ epg_erase_duplicates(event_t *e, channel_t *ch) { if(n->e_dvb_id == dvb_id || epg_event_cmp_overlap(n, e)) { tvhlog(LOG_DEBUG, "epg", "Removing overlapping event instance %s from EPG", n->e_title); - dvr_event_cancelled(n); + dvr_event_replaced(n, e); 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_event_cmp_overlap(n, e)) { tvhlog(LOG_DEBUG, "epg", "Removing overlapping event instance %s from EPG", n->e_title); - dvr_event_cancelled(n); + dvr_event_replaced(n, e); epg_remove_event_from_channel(ch, n); } }