Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
scanfile: cleanups, allow runtime update, fixes #3612
The scanfiles are parsed in the tasklet thread now, so it might
also improve the start time.
  • Loading branch information
perexg committed Mar 8, 2016
1 parent 1210696 commit 95fcfc2
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 92 deletions.
19 changes: 4 additions & 15 deletions src/api/api_mpegts.c
Expand Up @@ -381,29 +381,18 @@ api_dvb_scanfile_list
if (!type)
return -EINVAL;

if (!strcasecmp(type, "dvbt"))
list = &scanfile_regions_DVBT;
else if (!strcasecmp(type, "dvbc"))
list = &scanfile_regions_DVBC;
else if (!strcasecmp(type, "dvbs"))
list = &scanfile_regions_DVBS;
else if (!strcasecmp(type, "atsc-t"))
list = &scanfile_regions_ATSC_T;
else if (!strcasecmp(type, "atsc-c"))
list = &scanfile_regions_ATSC_C;
else if (!strcasecmp(type, "isdb-t"))
list = &scanfile_regions_ISDB_T;
else
list = scanfile_find_region_list(type);
if (!list)
return -EINVAL;

l = htsmsg_create_list();
LIST_FOREACH(r, list, sfr_link) {
LIST_FOREACH(r, &list->srl_regions, sfr_link) {
LIST_FOREACH(n, &r->sfr_networks, sfn_link) {
if (satpos != INT_MAX && n->sfn_satpos != satpos) continue;
e = htsmsg_create_map();
sprintf(buf, "%s/%s/%s", type, r->sfr_id, n->sfn_id);
htsmsg_add_str(e, "key", buf);
if (list != &scanfile_regions_DVBS) {
if (strcmp(list->srl_type, "dvb-s")) {
sprintf(buf, "%s: %s", r->sfr_name, n->sfn_name);
htsmsg_add_str(e, "val", buf);
} else {
Expand Down
25 changes: 25 additions & 0 deletions src/config.c
Expand Up @@ -33,6 +33,7 @@
#include "url.h"
#include "satip/server.h"
#include "channels.h"
#include "input/mpegts/scanfile.h"

#include <netinet/ip.h>

Expand Down Expand Up @@ -1930,6 +1931,29 @@ config_class_piconscheme_list ( void *o, const char *lang )
return strtab2htsmsg(tab, 1, lang);
}

#if ENABLE_MPEGTS_DVB
static void
config_muxconfpath_notify_cb(void *opaque, int disarmed)
{
char *muxconf_path = opaque;
if (disarmed || muxconf_path == NULL || muxconf_path[0] == '\0') {
free(muxconf_path);
return;
}
tvhinfo("config", "scanfile re-initialization with path %s", muxconf_path);
scanfile_init(muxconf_path, 1);
free(muxconf_path);
}
#endif

static void
config_muxconfpath_notify ( void *o, const char *lang )
{
#if ENABLE_MPEGTS_DVB
tasklet_arm_alloc(config_muxconfpath_notify_cb, strdup(config.muxconf_path));
#endif
}

const idclass_t config_class = {
.ic_snode = &config.idnode,
.ic_class = "config",
Expand Down Expand Up @@ -2142,6 +2166,7 @@ const idclass_t config_class = {
"/usr/share/dvb/. Leave blank to use Tvheadend's "
"internal file set."),
.off = offsetof(config_t, muxconf_path),
.notify = config_muxconfpath_notify,
.opts = PO_ADVANCED,
.group = 4
},
Expand Down
4 changes: 1 addition & 3 deletions src/input/mpegts/mpegts_network_dvb.c
Expand Up @@ -24,6 +24,7 @@
#include "mpegts_dvb.h"
#include "linuxdvb/linuxdvb_private.h"
#include "dvb_charset.h"
#include "config.h"
#include "scanfile.h"

#include <sys/types.h>
Expand Down Expand Up @@ -843,9 +844,6 @@ void dvb_network_init ( void )
const char *s;
int i;

/* Load scan files */
scanfile_init();

/* Load list of mux charset global overrides */
dvb_charset_init();

Expand Down
183 changes: 117 additions & 66 deletions src/input/mpegts/scanfile.c
Expand Up @@ -34,12 +34,23 @@
#include <strings.h>
#include <ctype.h>

scanfile_region_list_t scanfile_regions_DVBC;
scanfile_region_list_t scanfile_regions_DVBT;
scanfile_region_list_t scanfile_regions_DVBS;
scanfile_region_list_t scanfile_regions_ATSC_T;
scanfile_region_list_t scanfile_regions_ATSC_C;
scanfile_region_list_t scanfile_regions_ISDB_T;
#define SCANFILE_LIMIT (4*1024*1024)

static const char *scanfile_region_types[][2] = {
{ "dvb-s", "dvbs" },
{ "dvb-t", "dvbt" },
{ "dvb-c", "dvbc" },
{ "atsc-t", NULL },
{ "atsc-c", NULL },
{ "isdb-t", NULL }
};

#define REGIONS ARRAY_SIZE(scanfile_region_types)

static scanfile_region_list_t *scanfile_regions;
static scanfile_region_list_t *scanfile_regions_load;
static int64_t scanfile_total_load;


/* **************************************************************************
* Country codes
Expand Down Expand Up @@ -281,15 +292,15 @@ scanfile_region_create
{
scanfile_region_t *reg;
scanfile_region_list_t *list = NULL;
if (!strcmp(type, "dvb-s")) list = &scanfile_regions_DVBS;
else if (!strcmp(type, "dvb-t")) list = &scanfile_regions_DVBT;
else if (!strcmp(type, "dvb-c")) list = &scanfile_regions_DVBC;
else if (!strcmp(type, "atsc-t")) list = &scanfile_regions_ATSC_T;
else if (!strcmp(type, "atsc-c")) list = &scanfile_regions_ATSC_C;
else if (!strcmp(type, "isdb-t")) list = &scanfile_regions_ISDB_T;
int i;
for (i = 0; i < REGIONS; i++)
if (strcmp(scanfile_regions_load[i].srl_type, type) == 0) {
list = &scanfile_regions_load[i];
break;
}
if (!list) return NULL;

LIST_FOREACH(reg, list, sfr_link) {
LIST_FOREACH(reg, &list->srl_regions, sfr_link) {
if (!strcmp(reg->sfr_id, id)) break;
}

Expand All @@ -298,7 +309,7 @@ scanfile_region_create
reg = calloc(1, sizeof(scanfile_region_t));
reg->sfr_id = strdup(id);
reg->sfr_name = strdup(desc);
LIST_INSERT_SORTED(list, reg, sfr_link, scanfile_region_cmp);
LIST_INSERT_SORTED(&list->srl_regions, reg, sfr_link, scanfile_region_cmp);
}

return reg;
Expand Down Expand Up @@ -700,8 +711,11 @@ scanfile_load_file

tvhtrace("scanfile", "load file %s", name);

if (scanfile_total_load > SCANFILE_LIMIT) return;
fp = fb_open2(dir, name, 1, 0);
if (!fp) return;
scanfile_total_load += fb_size(fp);
if (scanfile_total_load > SCANFILE_LIMIT) goto end;

/* Process file */
load = 1;
Expand Down Expand Up @@ -734,6 +748,7 @@ scanfile_load_file
break;
}
}
end:
fb_close(fp);
}

Expand Down Expand Up @@ -778,7 +793,7 @@ scanfile_stats(const char *what, scanfile_region_list_t *list)
scanfile_network_t *sfn;
int regions = 0, networks =0;

LIST_FOREACH(reg, list, sfr_link) {
LIST_FOREACH(reg, &list->srl_regions, sfr_link) {
regions++;
LIST_FOREACH(sfn, &reg->sfr_networks, sfn_link)
networks++;
Expand All @@ -790,14 +805,43 @@ scanfile_stats(const char *what, scanfile_region_list_t *list)
return 0;
}

/*
* Destroy the region
*/
static void
scanfile_done_region( scanfile_region_list_t *list )
{
scanfile_region_t *reg;
scanfile_network_t *net;
dvb_mux_conf_t *mux;

while ((reg = LIST_FIRST(&list->srl_regions)) != NULL) {
LIST_REMOVE(reg, sfr_link);
while ((net = LIST_FIRST(&reg->sfr_networks)) != NULL) {
LIST_REMOVE(net, sfn_link);
while ((mux = LIST_FIRST(&net->sfn_muxes)) != NULL) {
LIST_REMOVE(mux, dmc_link);
free(mux);
}
free((void *)net->sfn_id);
free((void *)net->sfn_name);
free(net);
}
free((void *)reg->sfr_id);
free((void *)reg->sfr_name);
free(reg);
}
}

/*
* Initialise the mux list
*/
void
scanfile_init ( void )
scanfile_init ( const char *muxconf_path, int lock )
{
const char *path = config.muxconf_path;
int r = 0;
const char *path = muxconf_path;
char buf[32], *p;
int r = 0, i;
if (!path || !*path)
#if ENABLE_DVBSCAN
path = "data/dvb-scan";
Expand All @@ -806,59 +850,77 @@ scanfile_init ( void )
#else
path = "/usr/share/dvb";
#endif

scanfile_total_load = 0;
scanfile_regions_load = calloc(REGIONS, sizeof(scanfile_region_list_t));
for (i = 0; i < REGIONS; i++) {
scanfile_regions_load[i].srl_type = scanfile_region_types[i][0];
scanfile_regions_load[i].srl_alt_type = scanfile_region_types[i][1];
}

scanfile_load_dir(path, NULL, 0);

r += scanfile_stats("DVB-T", &scanfile_regions_DVBT);
r += scanfile_stats("DVB-S", &scanfile_regions_DVBS);
r += scanfile_stats("DVB-C", &scanfile_regions_DVBC);
r += scanfile_stats("ATSC-T", &scanfile_regions_ATSC_T);
r += scanfile_stats("ATSC-C", &scanfile_regions_ATSC_C);
r += scanfile_stats("ISDB-T", &scanfile_regions_ISDB_T);
for (i = 0; i < REGIONS; i++) {
snprintf(buf, sizeof(buf)-1, "%s", scanfile_regions_load[i].srl_type);
buf[sizeof(buf)-1] = '\0';
for (p = buf; *p; p++) *p = toupper(*p);
r += scanfile_stats(buf, &scanfile_regions_load[i]);
}
if (!r) {
tvhwarn("scanfile", "no predefined muxes found, check path '%s%s'",
path[0] == '/' ? path : TVHEADEND_DATADIR "/",
path[0] == '/' ? "" : path);
tvhwarn("scanfile", "expected tree structure - http://git.linuxtv.org/cgit.cgi/dtv-scan-tables.git/tree/");
for (i = 0; i < REGIONS; i++)
scanfile_done_region(&scanfile_regions_load[i]);
free(scanfile_regions_load);
scanfile_regions_load = NULL;
} else {
if (lock)
pthread_mutex_lock(&global_lock);
scanfile_done();
scanfile_regions = scanfile_regions_load;
scanfile_regions_load = NULL;
if (lock)
pthread_mutex_unlock(&global_lock);
}
}

/*
* Destroy the mux list
*/
static void
scanfile_done_region( scanfile_region_list_t *list )
void
scanfile_done ( void )
{
scanfile_region_t *reg;
scanfile_network_t *net;
dvb_mux_conf_t *mux;
scanfile_region_list_t *l;
int i;

while ((reg = LIST_FIRST(list)) != NULL) {
LIST_REMOVE(reg, sfr_link);
while ((net = LIST_FIRST(&reg->sfr_networks)) != NULL) {
LIST_REMOVE(net, sfn_link);
while ((mux = LIST_FIRST(&net->sfn_muxes)) != NULL) {
LIST_REMOVE(mux, dmc_link);
free(mux);
}
free((void *)net->sfn_id);
free((void *)net->sfn_name);
free(net);
}
free((void *)reg->sfr_id);
free((void *)reg->sfr_name);
free(reg);
l = scanfile_regions;
scanfile_regions = NULL;
if (l) {
for (i = 0; i < REGIONS; i++)
scanfile_done_region(&l[i]);
free(l);
}
}

void
scanfile_done ( void )
/*
* Find region list by type
*/
scanfile_region_list_t *
scanfile_find_region_list ( const char *type )
{
scanfile_done_region(&scanfile_regions_DVBS);
scanfile_done_region(&scanfile_regions_DVBT);
scanfile_done_region(&scanfile_regions_DVBC);
scanfile_done_region(&scanfile_regions_ATSC_T);
scanfile_done_region(&scanfile_regions_ATSC_C);
scanfile_done_region(&scanfile_regions_ISDB_T);
scanfile_region_list_t *list = NULL;
int i;
if (scanfile_regions == NULL)
return NULL;
for (i = 0; i < REGIONS; i++)
if (strcasecmp(scanfile_regions[i].srl_type, type) == 0 ||
strcasecmp(scanfile_regions[i].srl_alt_type, type) == 0) {
list = &scanfile_regions[i];
break;
}
return list;
}

/*
Expand All @@ -876,25 +938,14 @@ scanfile_find ( const char *id )
/* Type */
if (!(tok = strtok_r(tmp, "/", &s)))
goto fail;
if (!strcasecmp(tok, "dvbt"))
l = &scanfile_regions_DVBT;
else if (!strcasecmp(tok, "dvbc"))
l = &scanfile_regions_DVBC;
else if (!strcasecmp(tok, "dvbs"))
l = &scanfile_regions_DVBS;
else if (!strcasecmp(tok, "atsc-t"))
l = &scanfile_regions_ATSC_T;
else if (!strcasecmp(tok, "atsc-c"))
l = &scanfile_regions_ATSC_C;
else if (!strcasecmp(tok, "isdb-t"))
l = &scanfile_regions_ISDB_T;
else
l = scanfile_find_region_list(tok);
if (!l)
goto fail;

/* Region */
if (!(tok = strtok_r(NULL, "/", &s)))
goto fail;
LIST_FOREACH(r, l, sfr_link)
LIST_FOREACH(r, &l->srl_regions, sfr_link)
if (!strcmp(r->sfr_id, tok))
break;
if (!r) goto fail;
Expand Down

0 comments on commit 95fcfc2

Please sign in to comment.