config.dscp = -1;
config.descrambler_buffer = 9000;
config.epg_compress = 1;
- config.epg_cutwindow = 5*60;
+ config.epg_cut_window = 5*60;
+ config.epg_update_window = 24*3600;
config_scanfile_ok = 0;
config.theme_ui = strdup("blue");
.id = "epg_cutwindow",
.name = N_("EPG overlap cut"),
.desc = N_("The time window to cut the stop time from the overlapped event in seconds."),
- .off = offsetof(config_t, epg_cutwindow),
+ .off = offsetof(config_t, epg_cut_window),
+ .opts = PO_EXPERT,
+ .group = 2
+ },
+ {
+ .type = PT_U32,
+ .id = "epg_window",
+ .name = N_("EPG update window"),
+ .desc = N_("Maximum allowed difference between event start time when "
+ "the EPG event is changed in seconds."),
+ .off = offsetof(config_t, epg_update_window),
.opts = PO_EXPERT,
.group = 2
},
int caclient_ui;
int parser_backlog;
int epg_compress;
- uint32_t epg_cutwindow;
+ uint32_t epg_cut_window;
+ uint32_t epg_update_window;
} config_t;
extern const idclass_t config_class;
.id = "epg-update-window",
.name = N_("EPG update window"),
.desc = N_("Maximum allowed difference between event start time when "
- "the EPG event is changed."),
+ "the EPG event is changed in seconds."),
.off = offsetof(dvr_config_t, dvr_update_window),
.list = dvr_config_entry_class_update_window_list,
.def.u32 = 24*3600,
return 0;
/* Title match (or contains?) */
- if (strcmp(title1, title2))
+ if (strcasecmp(title1, title2))
return 0;
/* episode check */
_epg_channel_rem_broadcast(ch, ret, NULL);
return NULL;
}
- if (config.epg_cutwindow && ebc->stop - ebc->start > config.epg_cutwindow * 2 &&
- ebc->stop - ret->start <= config.epg_cutwindow) {
+ if (config.epg_cut_window && ebc->stop - ebc->start > config.epg_cut_window * 2 &&
+ ebc->stop - ret->start <= config.epg_cut_window) {
tvhtrace(LS_EPG, "cut stop for overlap (b) event %u (%s) on %s @ %s to %s",
ebc->id, epg_broadcast_get_title(ebc, NULL),
channel_get_name(ch, channel_blank_name),
_epg_channel_rem_broadcast(ch, ret, NULL);
return NULL;
}
- if (config.epg_cutwindow && ret->stop - ret->start > config.epg_cutwindow * 2 &&
- ret->stop - ebc->start <= config.epg_cutwindow) {
+ if (config.epg_cut_window && ret->stop - ret->start > config.epg_cut_window * 2 &&
+ ret->stop - ebc->start <= config.epg_cut_window) {
tvhtrace(LS_EPG, "cut stop for overlap (a) event %u (%s) on %s @ %s to %s",
ebc->id, epg_broadcast_get_title(ebc, NULL),
channel_get_name(ch, channel_blank_name),
gtimer_disarm(&ch->ch_epg_timer);
}
+static int epg_match_event_fuzzy(epg_broadcast_t *a, epg_broadcast_t *b)
+{
+ time_t t1, t2;
+ const char *title1, *title2;
+ epg_episode_num_t num1, num2;
+
+ /* Matching ID */
+ if (a->dvb_eid) {
+ if (b->dvb_eid && a->dvb_eid == b->dvb_eid)
+ return 1;
+ return 0;
+ }
+
+ /* Wrong length (+/-20%) */
+ t1 = a->stop - a->start;
+ t2 = b->stop - b->start;
+ if (labs((long)(t2 - t1)) > (t1 / 5))
+ return 0;
+
+ /* No title */
+ if (!(title1 = epg_broadcast_get_title(a, NULL)))
+ return 0;
+ if (!(title2 = epg_broadcast_get_title(b, NULL)))
+ return 0;
+
+ /* Outside of window */
+ if ((int64_t)llabs(b->start - a->start) > config.epg_update_window)
+ return 0;
+
+ /* Title match (or contains?) */
+ if (strcasecmp(title1, title2))
+ return 0;
+
+ /* episode check */
+ if (a->episode && b->episode) {
+ epg_episode_get_epnum(a->episode, &num1);
+ epg_episode_get_epnum(b->episode, &num2);
+ if (epg_episode_number_cmp(&num1, &num2) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+epg_broadcast_t *epg_match_now_next ( channel_t *ch, epg_broadcast_t *ebc )
+{
+ epg_broadcast_t *ret;
+
+ if (epg_match_event_fuzzy(ch->ch_epg_now, ebc))
+ ret = ch->ch_epg_now;
+ else if (epg_match_event_fuzzy(ch->ch_epg_next, ebc))
+ ret = ch->ch_epg_next;
+ else
+ return NULL;
+ /* update eid for further lookups */
+ if (ret->dvb_eid != ebc->dvb_eid && ret->dvb_eid == 0 && ebc->dvb_eid)
+ ret->dvb_eid = ebc->dvb_eid;
+ return ret;
+}
+
/* **************************************************************************
* Broadcast
* *************************************************************************/
/* Unlink */
void epg_channel_unlink ( struct channel *ch );
+/* Match now / next events */
+epg_broadcast_t *epg_match_now_next ( struct channel *ch, epg_broadcast_t *ebc );
/* ************************************************************************
* Global config
const uint8_t *ptr, int len,
int local, int *resched, int *save )
{
- int dllen, save2 = 0;
+ int dllen, save2 = 0, rsonly = 0;
time_t start, stop;
uint16_t eid;
uint8_t dtag, dlen, running;
- epg_broadcast_t *ebc;
- epg_episode_t *ee = NULL;
+ epg_broadcast_t *ebc, _ebc;
+ epg_episode_t *ee = NULL, _ee;
epg_serieslink_t *es;
epg_running_t run;
eit_event_t ev;
eid, tableid, running,
gmtime2local(start, tm1, sizeof(tm1)),
gmtime2local(stop, tm2, sizeof(tm2)), ebc);
- if (!ebc) return 0;
+ if (!ebc) {
+ if (tableid == 0x4e)
+ rsonly = 1;
+ else
+ return 0;
+ }
/* Mark re-schedule detect (only now/next) */
- if (save2 && tableid < 0x50) *resched = 1;
- *save |= save2;
+ if (!rsonly) {
+ if (save2 && tableid < 0x50) *resched = 1;
+ *save |= save2;
+ }
/* Process tags */
memset(&ev, 0, sizeof(ev));
ptr += dlen;
}
+ if (rsonly) {
+ memset(&_ebc, 0, sizeof(_ebc));
+ if (*ev.suri)
+ if ((es = epg_serieslink_find_by_uri(ev.suri, mod, 0, 0, NULL)))
+ _ebc.serieslink = es;
+
+ if (*ev.uri && (ee = epg_episode_find_by_uri(ev.uri, mod, 0, 0, NULL))) {
+ _ee = *ee;
+ } else {
+ memset(&_ee, 0, sizeof(_ee));
+ }
+ _ebc.episode = &_ee;
+ _ebc.dvb_eid = eid;
+ _ebc.start = start;
+ _ebc.stop = stop;
+ _ee.title = ev.title;
+
+ ebc = epg_match_now_next(ch, &_ebc);
+ tvhtrace(mod->subsys, "%s: running state only ebc=%p", svc->s_dvb_svcname ?: "(null)", ebc);
+ goto tidy;
+ }
+
/*
* Broadcast
*/
*save |= epg_broadcast_change_finish(ebc, changes2, 0);
+
+tidy:
/* Tidy up */
#if TODO_ADD_EXTRA
if (ev.extra) htsmsg_destroy(ev.extra);
if (ev.desc) lang_str_destroy(ev.desc);
/* use running flag only for current broadcast */
- if (running && tableid == 0x4e) {
+ if (ebc && running && tableid == 0x4e) {
if (sect == 0) {
switch (running) {
case 2: run = EPG_RUNNING_WARM; break;
}
epg_broadcast_notify_running(ebc, EPG_SOURCE_EIT, run);
} else if (sect == 1 && running != 2 && running != 3 && running != 4) {
- epg_broadcast_notify_running(ebc, EPG_SOURCE_EIT, EPG_RUNNING_STOP);
}
}