Fix #1444 - dvr: ensure that DVR entries are not removed when EPG is updated
previously an overlapping (replacement) event could result in the DVR
entry being completely removed. This will now ensure that the original
entry is left in place (with just info and times).
It will also try and re-match with an EPG entry as and when it can.
(cherry picked from commit a0a7539a73
)
This commit is contained in:
parent
ed6adeb464
commit
3e4389b564
2 changed files with 83 additions and 32 deletions
|
@ -137,6 +137,8 @@ typedef struct dvr_entry {
|
|||
lang_str_t *de_desc; /* Description in UTF-8 (from EPG) */
|
||||
epg_genre_t de_content_type; /* Content type (from EPG) */
|
||||
|
||||
uint16_t de_dvb_eid;
|
||||
|
||||
dvr_prio_t de_pri;
|
||||
|
||||
uint32_t de_dont_reschedule;
|
||||
|
|
113
src/dvr/dvr_db.c
113
src/dvr/dvr_db.c
|
@ -250,6 +250,39 @@ dvr_entry_link(dvr_entry_t *de)
|
|||
htsp_dvr_entry_add(de);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find dvr entry using 'fuzzy' search
|
||||
*/
|
||||
static int
|
||||
dvr_entry_fuzzy_match(dvr_entry_t *de, epg_broadcast_t *e)
|
||||
{
|
||||
time_t t1, t2;
|
||||
const char *title1, *title2;
|
||||
|
||||
/* Matching ID */
|
||||
if (de->de_dvb_eid && de->de_dvb_eid == e->dvb_eid)
|
||||
return 1;
|
||||
|
||||
/* No title */
|
||||
if (!(title1 = epg_broadcast_get_title(e, NULL)))
|
||||
return 0;
|
||||
if (!(title2 = lang_str_get(de->de_title, NULL)))
|
||||
return 0;
|
||||
|
||||
/* Wrong length (+/-20%) */
|
||||
t1 = de->de_stop - de->de_start;
|
||||
t2 = e->stop - e->start;
|
||||
if ( abs(t2 - t1) > (t1 / 5) )
|
||||
return 0;
|
||||
|
||||
/* Outside of window (should it be configurable)? */
|
||||
if ( abs(e->start - de->de_start) > 86400 )
|
||||
return 0;
|
||||
|
||||
/* Title match (or contains?) */
|
||||
return strcmp(title1, title2) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the event
|
||||
*/
|
||||
|
@ -301,6 +334,7 @@ static dvr_entry_t *_dvr_entry_create (
|
|||
de->de_desc = NULL;
|
||||
// TODO: this really needs updating
|
||||
if (e) {
|
||||
de->de_dvb_eid = e->dvb_eid;
|
||||
if (e->episode && e->episode->title)
|
||||
de->de_title = lang_str_copy(e->episode->title);
|
||||
if (e->description)
|
||||
|
@ -478,7 +512,7 @@ dvr_db_load_one(htsmsg_t *c, int id)
|
|||
dvr_entry_t *de;
|
||||
const char *chname, *s, *creator;
|
||||
channel_t *ch;
|
||||
uint32_t start, stop, bcid;
|
||||
uint32_t start, stop, bcid, u32;
|
||||
int d;
|
||||
dvr_config_t *cfg;
|
||||
lang_str_t *title, *ls;
|
||||
|
@ -519,6 +553,8 @@ dvr_db_load_one(htsmsg_t *c, int id)
|
|||
de->de_creator = strdup(creator);
|
||||
de->de_title = title;
|
||||
de->de_pri = dvr_pri2val(htsmsg_get_str(c, "pri"));
|
||||
if (!htsmsg_get_u32(c, "dvb_eid", &u32))
|
||||
de->de_dvb_eid = (uint16_t)u32;
|
||||
|
||||
if(htsmsg_get_s32(c, "start_extra", &d))
|
||||
if (ch && ch->ch_dvr_extra_time_pre)
|
||||
|
@ -619,6 +655,9 @@ dvr_entry_save(dvr_entry_t *de)
|
|||
|
||||
lang_str_serialize(de->de_title, m, "title");
|
||||
|
||||
if(de->de_dvb_eid)
|
||||
htsmsg_add_u32(m, "dvb_eid", de->de_dvb_eid);
|
||||
|
||||
if(de->de_desc != NULL)
|
||||
lang_str_serialize(de->de_desc, m, "description");
|
||||
|
||||
|
@ -696,6 +735,12 @@ static dvr_entry_t *_dvr_entry_update
|
|||
if (!de->de_title) de->de_title = lang_str_create();
|
||||
save = lang_str_add(de->de_title, title, lang, 1);
|
||||
}
|
||||
|
||||
/* EID */
|
||||
if (e && e->dvb_eid != de->de_dvb_eid) {
|
||||
de->de_dvb_eid = e->dvb_eid;
|
||||
save = 1;
|
||||
}
|
||||
|
||||
// TODO: description
|
||||
|
||||
|
@ -710,7 +755,8 @@ static dvr_entry_t *_dvr_entry_update
|
|||
|
||||
/* Broadcast */
|
||||
if (e && (de->de_bcast != e)) {
|
||||
de->de_bcast->putref(de->de_bcast);
|
||||
if (de->de_bcast)
|
||||
de->de_bcast->putref(de->de_bcast);
|
||||
de->de_bcast = e;
|
||||
e->getref(e);
|
||||
save = 1;
|
||||
|
@ -744,23 +790,33 @@ dvr_entry_update
|
|||
|
||||
/**
|
||||
* Used to notify the DVR that an event has been replaced in the EPG
|
||||
*
|
||||
* TODO: I think this will record the title slot event if its now a
|
||||
* completely different episode etc...
|
||||
*/
|
||||
void
|
||||
dvr_event_replaced(epg_broadcast_t *e, epg_broadcast_t *new_e)
|
||||
{
|
||||
dvr_entry_t *de, *ude;
|
||||
dvr_entry_t *de;
|
||||
assert(e != NULL);
|
||||
assert(new_e != NULL);
|
||||
|
||||
/* Ignore */
|
||||
if ( e == new_e ) return;
|
||||
|
||||
de = dvr_entry_find_by_event(e);
|
||||
if (de != NULL) {
|
||||
ude = dvr_entry_find_by_event_fuzzy(new_e);
|
||||
if (ude == NULL && de->de_sched_state == DVR_SCHEDULED)
|
||||
dvr_entry_cancel(de);
|
||||
else if(new_e->episode && new_e->episode->title)
|
||||
_dvr_entry_update(de, new_e, NULL, NULL, NULL, 0, 0, 0, 0);
|
||||
/* Existing entry */
|
||||
if ((de = dvr_entry_find_by_event(e))) {
|
||||
|
||||
/* Unlink the broadcast */
|
||||
e->putref(e);
|
||||
de->de_bcast = NULL;
|
||||
|
||||
/* Find match */
|
||||
RB_FOREACH(e, &e->channel->ch_epg_schedule, sched_link) {
|
||||
if (dvr_entry_fuzzy_match(de, e)) {
|
||||
e->getref(e);
|
||||
de->de_bcast = e;
|
||||
_dvr_entry_update(de, e, NULL, NULL, NULL, 0, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -768,7 +824,18 @@ void dvr_event_updated ( epg_broadcast_t *e )
|
|||
{
|
||||
dvr_entry_t *de;
|
||||
de = dvr_entry_find_by_event(e);
|
||||
if (de) _dvr_entry_update(de, e, NULL, NULL, NULL, 0, 0, 0, 0);
|
||||
if (de)
|
||||
_dvr_entry_update(de, e, NULL, NULL, NULL, 0, 0, 0, 0);
|
||||
else {
|
||||
LIST_FOREACH(de, &dvrentries, de_global_link) {
|
||||
if (dvr_entry_fuzzy_match(de, e)) {
|
||||
e->getref(e);
|
||||
de->de_bcast = e;
|
||||
_dvr_entry_update(de, e, NULL, NULL, NULL, 0, 0, 0, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -863,24 +930,6 @@ dvr_entry_find_by_event(epg_broadcast_t *e)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find dvr entry using 'fuzzy' search
|
||||
*/
|
||||
dvr_entry_t *
|
||||
dvr_entry_find_by_event_fuzzy(epg_broadcast_t *e)
|
||||
{
|
||||
dvr_entry_t *de;
|
||||
|
||||
if (!e->episode || !e->episode->title)
|
||||
return NULL;
|
||||
|
||||
LIST_FOREACH(de, &e->channel->ch_dvrs, de_channel_link)
|
||||
if ((abs(de->de_start - e->start) < 600) && (abs(de->de_stop - e->stop) < 600)) {
|
||||
return de;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find DVR entry based on an episode
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue