diff --git a/src/input/mpegts.h b/src/input/mpegts.h index 7563d389..c9676e17 100644 --- a/src/input/mpegts.h +++ b/src/input/mpegts.h @@ -447,6 +447,7 @@ struct mpegts_service uint16_t s_dvb_forcecaid; time_t s_dvb_created; time_t s_dvb_last_seen; + time_t s_dvb_check_seen; /* * EIT/EPG control diff --git a/src/input/mpegts/dvb_psi.c b/src/input/mpegts/dvb_psi.c index 337be732..0b4e8a0d 100644 --- a/src/input/mpegts/dvb_psi.c +++ b/src/input/mpegts/dvb_psi.c @@ -1012,13 +1012,36 @@ dvb_pat_callback uint16_t nit_pid = 0; mpegts_mux_t *mm = mt->mt_mux; mpegts_table_state_t *st = NULL; - mpegts_service_t *s; + mpegts_service_t *s, *snext; + time_t last_seen; /* Begin */ if (tableid != 0) return -1; tsid = (ptr[0] << 8) | ptr[1]; r = dvb_table_begin(mt, ptr, len, tableid, tsid, 5, &st, §, &last, &ver); + if (r == 0 && mt->mt_opaque == NULL) { + /* + * Disable "not seen" services. It's quite easy algorithm which + * compares the time for the most recent services with others. + * If there is a big gap (24 hours) the service will be removed. + * + * Note that this code is run only when the PAT table scan is + * fully completed (all live services are known at this point). + */ + last_seen = 0; + LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link) + if (last_seen < s->s_dvb_check_seen) + last_seen = s->s_dvb_check_seen; + for (s = LIST_FIRST(&mm->mm_services); s; s = snext) { + snext = LIST_NEXT(s, s_dvb_mux_link); + if (s->s_enabled && s->s_dvb_check_seen + 24 * 3600 < last_seen) { + tvhinfo("mpegts", "disabling service %s (missing in PAT)", s->s_nicename ?: ""); + service_set_enabled((service_t *)s, 0); + } + } + mt->mt_opaque = mm; + } if (r != 1) return r; /* Multiplex */ @@ -1044,6 +1067,7 @@ dvb_pat_callback tvhdebug("pat", " sid %04X (%d) on pid %04X (%d)", sid, sid, pid, pid); int save = 0; if ((s = mpegts_service_find(mm, sid, pid, 1, &save))) { + s->s_dvb_check_seen = dispatch_clock; mpegts_table_add(mm, DVB_PMT_BASE, DVB_PMT_MASK, dvb_pmt_callback, NULL, "pmt", MT_CRC | MT_QUICKREQ | MT_SCANSUBS, pid); @@ -2397,6 +2421,10 @@ psi_parse_pmt void psi_tables_default ( mpegts_mux_t *mm ) { + mpegts_service_t *s; + + LIST_FOREACH(s, &mm->mm_services, s_dvb_mux_link) + s->s_dvb_check_seen = s->s_dvb_last_seen; mpegts_table_add(mm, DVB_PAT_BASE, DVB_PAT_MASK, dvb_pat_callback, NULL, "pat", MT_QUICKREQ | MT_CRC | MT_RECORD, DVB_PAT_PID); diff --git a/src/service.c b/src/service.c index 12e57815..40a2d32a 100644 --- a/src/service.c +++ b/src/service.c @@ -820,6 +820,17 @@ service_destroy(service_t *t, int delconf) service_unref(t); } +void +service_set_enabled(service_t *t, int enabled) +{ + if (t->s_enabled != !!enabled) { + t->s_enabled = !!enabled; + service_class_notify_enabled(t); + service_request_save(t, 0); + idnode_notify_simple(&t->s_id); + } +} + static int64_t service_channel_number ( service_t *s ) { diff --git a/src/service.h b/src/service.h index ce44900f..36f8fe60 100644 --- a/src/service.h +++ b/src/service.h @@ -521,6 +521,8 @@ int service_is_other(service_t *t); int service_is_encrypted ( service_t *t ); +void service_set_enabled ( service_t *t, int enabled ); + void service_destroy(service_t *t, int delconf); void service_remove_subscriber(service_t *t, struct th_subscription *s,