bouquet: do not keep services for not enabled bouquets, fix bouquet delete

This commit is contained in:
Jaroslav Kysela 2014-11-06 14:29:51 +01:00
parent bdaab51c30
commit 7e99756d3c
9 changed files with 221 additions and 23 deletions

View file

@ -251,6 +251,9 @@ bouquet_add_service(bouquet_t *bq, service_t *s, uint64_t lcn)
lock_assert(&global_lock);
if (!bq->bq_enabled)
return;
if (!idnode_set_exists(bq->bq_services, &s->s_id)) {
tvhtrace("bouquet", "add service %s to %s", s->s_nicename, bq->bq_name ?: "<unknown>");
idnode_set_add(bq->bq_services, &s->s_id, NULL);
@ -317,7 +320,7 @@ bouquet_remove_service(bouquet_t *bq, service_t *s)
*
*/
void
bouquet_completed(bouquet_t *bq)
bouquet_completed(bouquet_t *bq, uint32_t seen)
{
idnode_set_t *remove;
service_t *s;
@ -327,9 +330,17 @@ bouquet_completed(bouquet_t *bq)
if (!bq)
return;
tvhtrace("bouquet", "%s: completed: active=%zi old=%zi",
bq->bq_name ?: "", bq->bq_active_services->is_count,
bq->bq_services->is_count);
if (seen != bq->bq_services_seen) {
bq->bq_services_seen = seen;
bq->bq_saveflag = 1;
}
tvhtrace("bouquet", "%s: completed: enabled=%d active=%zi old=%zi seen=%u",
bq->bq_name ?: "", bq->bq_enabled, bq->bq_active_services->is_count,
bq->bq_services->is_count, seen);
if (!bq->bq_enabled)
goto save;
/* Add/Remove services */
remove = idnode_set_create(0);
@ -359,6 +370,7 @@ bouquet_completed(bouquet_t *bq)
idnode_set_free(bq->bq_active_services);
bq->bq_active_services = idnode_set_create(1);
save:
if (bq->bq_saveflag)
bouquet_save(bq, 1);
}
@ -380,6 +392,18 @@ bouquet_map_to_channels(bouquet_t *bq)
bouquet_unmap_channel(bq, t);
}
}
if (!bq->bq_enabled) {
if (bq->bq_services->is_count) {
idnode_set_free(bq->bq_services);
bq->bq_services = idnode_set_create(1);
bq->bq_saveflag = 1;
}
if (bq->bq_active_services->is_count) {
idnode_set_free(bq->bq_active_services);
bq->bq_active_services = idnode_set_create(1);
}
}
}
/*
@ -446,6 +470,8 @@ bouquet_class_delete(idnode_t *self)
{
bouquet_t *bq = (bouquet_t *)self;
bq->bq_enabled = 0;
bouquet_map_to_channels(bq);
if (!bq->bq_shield) {
hts_settings_remove("bouquet/%s", idnode_uuid_as_str(&bq->bq_id));
bouquet_destroy(bq);
@ -477,10 +503,25 @@ bouquet_class_get_list(void *o)
return m;
}
static void
bouquet_class_rescan_notify ( void *obj )
{
void mpegts_mux_bouquet_rescan ( const char *src, const char *extra );
bouquet_t *bq = obj;
if (bq->bq_rescan)
mpegts_mux_bouquet_rescan(bq->bq_src, bq->bq_comment);
bq->bq_rescan = 0;
}
static void
bouquet_class_enabled_notify ( void *obj )
{
bouquet_map_to_channels((bouquet_t *)obj);
bouquet_t *bq = obj;
if (bq->bq_enabled)
bouquet_class_rescan_notify(obj);
bouquet_map_to_channels(bq);
}
static void
@ -687,6 +728,14 @@ const idclass_t bouquet_class = {
.off = offsetof(bouquet_t, bq_enabled),
.notify = bouquet_class_enabled_notify,
},
{
.type = PT_BOOL,
.id = "rescan",
.name = "Rescan",
.off = offsetof(bouquet_t, bq_rescan),
.notify = bouquet_class_rescan_notify,
.opts = PO_NOSAVE,
},
{
.type = PT_BOOL,
.id = "maptoch",
@ -754,6 +803,13 @@ const idclass_t bouquet_class = {
.rend = bouquet_class_services_rend,
.opts = PO_RDONLY | PO_HIDDEN,
},
{
.type = PT_U32,
.id = "services_seen",
.name = "# Seen Services",
.off = offsetof(bouquet_t, bq_services_seen),
.opts = PO_RDONLY,
},
{
.type = PT_U32,
.id = "services_count",
@ -816,11 +872,13 @@ bouquet_service_resolve(void)
if (!bq->bq_services_waiting)
continue;
saveflag = bq->bq_saveflag;
HTSMSG_FOREACH(f, bq->bq_services_waiting) {
if (htsmsg_field_get_u32(f, &lcn)) continue;
s = service_find_by_identifier(f->hmf_name);
if (s)
bouquet_add_service(bq, s, lcn);
if (bq->bq_enabled) {
HTSMSG_FOREACH(f, bq->bq_services_waiting) {
if (htsmsg_field_get_u32(f, &lcn)) continue;
s = service_find_by_identifier(f->hmf_name);
if (s)
bouquet_add_service(bq, s, lcn);
}
}
htsmsg_destroy(bq->bq_services_waiting);
bq->bq_services_waiting = NULL;

View file

@ -34,6 +34,7 @@ typedef struct bouquet {
int bq_shield;
int bq_enabled;
int bq_rescan;
int bq_maptoch;
int bq_mapnolcn;
int bq_mapnoname;
@ -47,6 +48,8 @@ typedef struct bouquet {
idnode_set_t *bq_services;
idnode_set_t *bq_active_services;
htsmsg_t *bq_services_waiting;
uint32_t bq_services_seen;
uint32_t bq_services_tmp; /* for fastscan tables */
uint32_t bq_lcn_offset;
} bouquet_t;
@ -78,7 +81,7 @@ bouquet_t * bouquet_find_by_source(const char *name, const char *src, int create
void bouquet_map_to_channels(bouquet_t *bq);
void bouquet_notify_channels(bouquet_t *bq);
void bouquet_add_service(bouquet_t *bq, service_t *s, uint64_t lcn);
void bouquet_completed(bouquet_t *bq);
void bouquet_completed(bouquet_t *bq, uint32_t seen);
uint64_t bouquet_get_channel_number(bouquet_t *bq, service_t *t);

View file

@ -752,8 +752,15 @@ void mpegts_mux_unsubscribe_by_name(mpegts_mux_t *mm, const char *name);
void mpegts_mux_scan_done ( mpegts_mux_t *mm, const char *buf, int res );
void mpegts_mux_bouquet_rescan ( const char *src, const char *extra );
void mpegts_mux_nice_name( mpegts_mux_t *mm, char *buf, size_t len );
int mpegts_mux_class_scan_state_set ( void *, const void * );
static inline int mpegts_mux_scan_state_set ( mpegts_mux_t *m, int state )
{ return mpegts_mux_class_scan_state_set ( m, &state ); }
mpegts_pid_t *mpegts_mux_find_pid_(mpegts_mux_t *mm, int pid, int create);
static inline mpegts_pid_t *

View file

@ -505,6 +505,8 @@ int dvb_sat_position( const dvb_mux_conf_t *mc );
const char *dvb_sat_position_to_str( int position, char *buf, size_t buflen );
const int dvb_sat_position_from_str( const char *buf );
#endif /* ENABLE_MPEGTS_DVB */
void dvb_done ( void );

View file

@ -63,6 +63,7 @@ typedef struct dvb_bat_id {
uint32_t freesat:1;
uint32_t bskyb:1;
uint16_t nbid;
uint32_t services_count;
char name[32];
mpegts_mux_t *mm;
TAILQ_HEAD(,dvb_bat_svc) services;
@ -389,6 +390,8 @@ dvb_desc_service_list
sid = (ptr[i] << 8) | ptr[i+1];
stype = ptr[i+2];
tvhdebug(dstr, " service %04X (%d) type %d", sid, sid, stype);
if (bi)
bi->services_count++;
if (mm) {
int save = 0;
s = mpegts_service_find(mm, sid, 0, 1, &save);
@ -524,7 +527,7 @@ dvb_freesat_add_service
snprintf(name, sizeof(name), "%s: %s", bi->name, fr->name);
fr->bouquet = bouquet_find_by_source(name, src, 1);
}
bouquet_add_service(fr->bouquet, (service_t *)s, lcn * CHANNEL_SPLIT);
bouquet_add_service(fr->bouquet, (service_t *)s, (int64_t)lcn * CHANNEL_SPLIT);
}
static void
@ -590,7 +593,7 @@ dvb_freesat_completed
TAILQ_REMOVE(&fr->services, fs, region_link);
if (fr->bouquet) {
dvb_bouquet_comment(fr->bouquet, bi->mm);
bouquet_completed(fr->bouquet);
bouquet_completed(fr->bouquet, total);
fr->bouquet = NULL;
}
}
@ -653,9 +656,9 @@ dvb_bskyb_local_channels
if (len < 2)
return;
regionid = ptr[1];
regionid = (ptr[1] != 0xff) ? ptr[1] : 0xffff;
if (regionid != 0xff && regionid != 0 && regionid != 1) {
if (regionid != 0xffff && regionid != 0 && regionid != 1) {
if ((str = getenv("TVHEADEND_BSKYB_REGIONID")) != NULL) {
if (regionid != atoi(str))
return;
@ -667,7 +670,7 @@ dvb_bskyb_local_channels
len -= 2;
ptr += 2;
tvhtrace(dstr, " region id %02X (%d) unknown %02X (%d)",
tvhtrace(dstr, " region id %04X (%d) unknown %02X (%d)",
regionid, regionid, ptr[0], ptr[0]);
while (len > 8) {
@ -687,7 +690,7 @@ dvb_bskyb_local_channels
if (!fs) {
fs = calloc(1, sizeof(*fs));
fs->sid = sid;
fs->regionid = regionid != 0xff ? regionid : 0xffff;
fs->regionid = regionid;
fs->lcn = lcn != 0xffff ? lcn : 0;
TAILQ_INSERT_TAIL(&b->fservices, fs, link);
}
@ -704,7 +707,7 @@ dvb_bskyb_local_channels
}
}
if (regionid && regionid != 0xff) {
if (regionid && regionid != 0xffff) {
LIST_FOREACH(fr, &b->fregions, link)
if (fr->regionid == regionid)
break;
@ -1153,7 +1156,7 @@ dvb_bat_completed
TAILQ_FOREACH(bs, &bi->services, link)
bouquet_add_service(bq, (service_t *)bs->svc, 0);
bouquet_completed(bq);
bouquet_completed(bq, bi->services_count);
complete:
bi->complete = 1;
@ -1678,7 +1681,7 @@ dvb_fs_sdt_callback
if (r == 0) {
mt->mt_working -= st->working;
st->working = 0;
bouquet_completed(bq);
bouquet_completed(bq, bq->bq_services_tmp);
}
if (r != 1) return r;
if (len < 5) return -1;
@ -1730,6 +1733,7 @@ dvb_fs_sdt_callback
tvhtrace(mt->mt_name, " dtag %02X dlen %d", dtag, dlen);
switch (dtag) {
case DVB_DESC_SERVICE:
bq->bq_services_tmp++;
if (dvb_desc_service(dptr, dlen, &stype, sprov,
sizeof(sprov), sname, sizeof(sname), charset))
return -1;
@ -2301,6 +2305,7 @@ static void
psi_tables_dvb_fastscan( void *aux, bouquet_t *bq, const char *name, int pid )
{
tvhtrace("fastscan", "adding table %04X (%i) for '%s'", pid, pid, name);
bq->bq_services_tmp = 0;
mpegts_table_add(aux, DVB_FASTSCAN_NIT_BASE, DVB_FASTSCAN_MASK,
dvb_nit_callback, bq, "fs_nit", MT_CRC, pid);
mpegts_table_add(aux, DVB_FASTSCAN_SDT_BASE, DVB_FASTSCAN_MASK,

View file

@ -868,6 +868,31 @@ dvb_sat_position_to_str(int position, char *buf, size_t buflen)
return buf;
}
const int
dvb_sat_position_from_str( const char *buf )
{
const char *s = buf;
int min, maj;
char c;
if (!buf)
return INT_MAX;
maj = atoi(s);
while (*s && *s != '.')
s++;
min = *s == '.' ? atoi(s + 1) : 0;
do {
c = *s++;
} while (c && c != 'W' && c != 'E');
if (!c)
return INT_MAX;
if (maj > 180 || maj < 0)
return INT_MAX;
if (min > 9 || min < 0)
return INT_MAX;
return (maj * 10 + min) * (c == 'W' ? -1 : 1);
}
#endif /* ENABLE_MPEGTS_DVB */
/**

View file

@ -257,7 +257,7 @@ scan_result_tab[] = {
{ "FAIL", MM_SCAN_FAIL },
};
static int
int
mpegts_mux_class_scan_state_set ( void *o, const void *p )
{
mpegts_mux_t *mm = o;

View file

@ -213,6 +213,102 @@ mpegts_network_scan_queue_add ( mpegts_mux_t *mm, int weight )
mpegts_network_scan_notify(mm);
}
/******************************************************************************
* Bouquet helper
*****************************************************************************/
static ssize_t
startswith( const char *str, const char *start )
{
size_t len = strlen(start);
if (!strncmp(str, start, len))
return len;
return -1;
}
void
mpegts_mux_bouquet_rescan ( const char *src, const char *extra )
{
mpegts_network_t *mn;
mpegts_mux_t *mm;
ssize_t l;
#if ENABLE_MPEGTS_DVB
const idclass_t *ic;
uint32_t freq;
int satpos;
#endif
if (!src)
return;
#if ENABLE_MPEGTS_DVB
if ((l = startswith(src, "dvb-bouquet://dvbs,")) > 0) {
uint32_t tsid, nbid;
src += l;
if ((satpos = dvb_sat_position_from_str(src)) == INT_MAX)
return;
while (*src && *src != ',')
src++;
if (sscanf(src, ",%x,%x", &tsid, &nbid) != 2)
return;
LIST_FOREACH(mn, &mpegts_network_all, mn_global_link)
LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link)
if (idnode_is_instance(&mm->mm_id, &dvb_mux_dvbs_class) &&
mm->mm_tsid == tsid &&
dvb_sat_position(&((dvb_mux_t *)mm)->lm_tuning) == satpos)
mpegts_mux_scan_state_set(mm, MM_SCAN_STATE_PEND);
return;
}
if ((l = startswith(src, "dvb-bouquet://dvbt,")) > 0) {
uint32_t tsid, nbid;
if (sscanf(src, "%x,%x", &tsid, &nbid) != 2)
return;
ic = &dvb_mux_dvbt_class;
goto tsid_lookup;
}
if ((l = startswith(src, "dvb-bouquet://dvbc,")) > 0) {
uint32_t tsid, nbid;
if (sscanf(src, "%x,%x", &tsid, &nbid) != 2)
return;
ic = &dvb_mux_dvbc_class;
tsid_lookup:
LIST_FOREACH(mn, &mpegts_network_all, mn_global_link)
LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link)
if (idnode_is_instance(&mm->mm_id, ic) &&
mm->mm_tsid == tsid)
mpegts_mux_scan_state_set(mm, MM_SCAN_STATE_PEND);
return;
}
if ((l = startswith(src, "dvb-bskyb://dvbs,")) > 0 ||
(l = startswith(src, "dvb-freesat://dvbs,")) > 0) {
if ((satpos = dvb_sat_position_from_str(src + l)) == INT_MAX)
return;
/* a bit tricky, but we don't have other info */
if (!extra)
return;
freq = strtod(extra, NULL) * 1000;
goto freq;
}
if ((l = startswith(src, "dvb-fastscan://dvbs,")) > 0) {
uint32_t pid;
src += l;
if ((satpos = dvb_sat_position_from_str(src)) == INT_MAX)
return;
while (*src && *src != ',')
src++;
if (sscanf(src, ",%u,%u", &freq, &pid) != 2)
return;
freq:
LIST_FOREACH(mn, &mpegts_network_all, mn_global_link)
LIST_FOREACH(mm, &mn->mn_muxes, mm_network_link)
if (idnode_is_instance(&mm->mm_id, &dvb_mux_dvbs_class) &&
((dvb_mux_t *)mm)->lm_tuning.dmc_fe_freq == freq &&
dvb_sat_position(&((dvb_mux_t *)mm)->lm_tuning) == satpos)
mpegts_mux_scan_state_set(mm, MM_SCAN_STATE_PEND);
return;
}
#endif
}
/******************************************************************************
* Subsystem setup / tear down
*****************************************************************************/

View file

@ -32,8 +32,8 @@ tvheadend.cteditor = function(panel, index)
*/
tvheadend.bouquet = function(panel, index)
{
var list = 'enabled,name,maptoch,mapnolcn,lcn_off,mapnoname,mapradio,' +
'chtag,source,services_count,comment';
var list = 'enabled,rescan,name,maptoch,mapnolcn,lcn_off,mapnoname,mapradio,' +
'chtag,source,services_count,services_seen,comment';
tvheadend.idnode_grid(panel, {
url: 'api/bouquet',
@ -43,6 +43,7 @@ tvheadend.bouquet = function(panel, index)
tabIndex: index,
columns: {
enabled: { width: 50 },
rescan: { width: 50 },
name: { width: 200 },
maptoch: { width: 100 },
mapnolcn: { width: 100 },
@ -52,6 +53,7 @@ tvheadend.bouquet = function(panel, index)
chtag: { width: 100 },
source: { width: 200 },
services_count: { width: 100 },
services_seen: { width: 100 },
comment: { width: 200 },
},
list: list,