First stab at moving mux initial config system to using dvb-apps mux config files directly.
This commit is contained in:
parent
0b38ca1287
commit
629a07009f
10 changed files with 516 additions and 14835 deletions
1
Makefile
1
Makefile
|
@ -75,6 +75,7 @@ SRCS = src/main.c \
|
|||
src/avc.c \
|
||||
src/huffman.c \
|
||||
src/filebundle.c \
|
||||
src/muxes.c \
|
||||
|
||||
SRCS += src/epggrab/module.c\
|
||||
src/epggrab/channel.c\
|
||||
|
|
|
@ -314,6 +314,13 @@ const char* dvb_mux_delsys2str(int delsys);
|
|||
const char* dvb_mux_qam2str(int qam);
|
||||
const char* dvb_mux_rolloff2str(int rolloff);
|
||||
|
||||
int dvb_mux_str2bw(const char *str);
|
||||
int dvb_mux_str2qam(const char *str);
|
||||
int dvb_mux_str2fec(const char *str);
|
||||
int dvb_mux_str2mode(const char *str);
|
||||
int dvb_mux_str2guard(const char *str);
|
||||
int dvb_mux_str2hier(const char *str);
|
||||
|
||||
void dvb_mux_save(th_dvb_mux_instance_t *tdmi);
|
||||
|
||||
void dvb_mux_load(th_dvb_adapter_t *tda);
|
||||
|
|
|
@ -505,6 +505,39 @@ const char* dvb_mux_rolloff2str(int rolloff) {
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* for external use
|
||||
*/
|
||||
int dvb_mux_str2bw(const char *str)
|
||||
{
|
||||
return str2val(str, bwtab);
|
||||
}
|
||||
|
||||
int dvb_mux_str2qam(const char *str)
|
||||
{
|
||||
return str2val(str, qamtab);
|
||||
}
|
||||
|
||||
int dvb_mux_str2fec(const char *str)
|
||||
{
|
||||
return str2val(str, fectab);
|
||||
}
|
||||
|
||||
int dvb_mux_str2mode(const char *str)
|
||||
{
|
||||
return str2val(str, modetab);
|
||||
}
|
||||
|
||||
int dvb_mux_str2guard(const char *str)
|
||||
{
|
||||
return str2val(str, guardtab);
|
||||
}
|
||||
|
||||
int dvb_mux_str2hier(const char *str)
|
||||
{
|
||||
return str2val(str, hiertab);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
@ -29,23 +29,19 @@
|
|||
#include "tvheadend.h"
|
||||
#include "dvb.h"
|
||||
#include "dvb_preconf.h"
|
||||
|
||||
/**
|
||||
* A big list of all known DVB networks (from linuxtv.org)
|
||||
*/
|
||||
#include "linuxtv_muxes.h"
|
||||
#include "muxes.h"
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
static void
|
||||
dvb_mux_preconf_add(th_dvb_adapter_t *tda, const struct mux *m, int num,
|
||||
dvb_mux_preconf_add(th_dvb_adapter_t *tda, const network_t *net,
|
||||
const char *source, const char *satconf)
|
||||
{
|
||||
const mux_t *m;
|
||||
struct dvb_mux_conf dmc;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < num; i++) {
|
||||
LIST_FOREACH(m, &net->muxes, link) {
|
||||
|
||||
memset(&dmc, 0, sizeof(dmc));
|
||||
|
||||
|
@ -103,7 +99,6 @@ dvb_mux_preconf_add(th_dvb_adapter_t *tda, const struct mux *m, int num,
|
|||
dmc.dmc_satconf = dvb_satconf_entry_find(tda, satconf, 0);
|
||||
|
||||
dvb_mux_create(tda, &dmc, 0xffff, NULL, source, 1, 1, NULL, NULL);
|
||||
m++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,42 +110,35 @@ int
|
|||
dvb_mux_preconf_add_network(th_dvb_adapter_t *tda, const char *id,
|
||||
const char *satconf)
|
||||
{
|
||||
const struct region *r;
|
||||
const struct network *n;
|
||||
int nr, nn, i, j;
|
||||
region_list_t *list;
|
||||
const region_t *r;
|
||||
const network_t *n;
|
||||
char source[100];
|
||||
|
||||
snprintf(source, sizeof(source), "built-in configuration from \"%s\"", id);
|
||||
|
||||
switch(tda->tda_type) {
|
||||
case FE_QAM:
|
||||
r = regions_DVBC;
|
||||
nr = sizeof(regions_DVBC) / sizeof(regions_DVBC[0]);
|
||||
break;
|
||||
case FE_QPSK:
|
||||
r = regions_DVBS;
|
||||
nr = sizeof(regions_DVBS) / sizeof(regions_DVBS[0]);
|
||||
break;
|
||||
case FE_OFDM:
|
||||
r = regions_DVBT;
|
||||
nr = sizeof(regions_DVBT) / sizeof(regions_DVBT[0]);
|
||||
break;
|
||||
case FE_ATSC:
|
||||
r = regions_ATSC;
|
||||
nr = sizeof(regions_ATSC) / sizeof(regions_ATSC[0]);
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
case FE_QAM:
|
||||
list = ®ions_DVBC;
|
||||
break;
|
||||
case FE_QPSK:
|
||||
list = ®ions_DVBS;
|
||||
break;
|
||||
case FE_OFDM:
|
||||
list = ®ions_DVBT;
|
||||
break;
|
||||
case FE_ATSC:
|
||||
list = ®ions_ATSC;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
||||
for(i = 0; i < nr; i++) {
|
||||
n = r[i].networks;
|
||||
nn = r[i].nnetworks;
|
||||
|
||||
for(j = 0; j < nn; j++) {
|
||||
if(!strcmp(n[j].name, id)) {
|
||||
dvb_mux_preconf_add(tda, n[j].muxes, n[j].nmuxes, source, satconf);
|
||||
break;
|
||||
LIST_FOREACH(r, list, link) {
|
||||
LIST_FOREACH(n, &r->networks, link) {
|
||||
if(!strcmp(n->id, id)) {
|
||||
dvb_mux_preconf_add(tda, n, source, satconf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -163,61 +151,52 @@ dvb_mux_preconf_add_network(th_dvb_adapter_t *tda, const char *id,
|
|||
htsmsg_t *
|
||||
dvb_mux_preconf_get_node(int fetype, const char *node)
|
||||
{
|
||||
const struct region *r;
|
||||
const struct network *n;
|
||||
int nr, nn, i;
|
||||
region_list_t *list = NULL;
|
||||
const region_t *r;
|
||||
const network_t *n;
|
||||
htsmsg_t *out, *e;
|
||||
|
||||
switch(fetype) {
|
||||
case FE_QAM:
|
||||
r = regions_DVBC;
|
||||
nr = sizeof(regions_DVBC) / sizeof(regions_DVBC[0]);
|
||||
break;
|
||||
case FE_QPSK:
|
||||
r = regions_DVBS;
|
||||
nr = sizeof(regions_DVBS) / sizeof(regions_DVBS[0]);
|
||||
break;
|
||||
case FE_OFDM:
|
||||
r = regions_DVBT;
|
||||
nr = sizeof(regions_DVBT) / sizeof(regions_DVBT[0]);
|
||||
break;
|
||||
case FE_ATSC:
|
||||
r = regions_ATSC;
|
||||
nr = sizeof(regions_ATSC) / sizeof(regions_ATSC[0]);
|
||||
break;
|
||||
default:
|
||||
tvhlog(LOG_ERR, "DVB", "No built-in config for fetype %d", fetype);
|
||||
return NULL;
|
||||
case FE_QAM:
|
||||
list = ®ions_DVBC;
|
||||
break;
|
||||
case FE_QPSK:
|
||||
list = ®ions_DVBS;
|
||||
break;
|
||||
case FE_OFDM:
|
||||
list = ®ions_DVBT;
|
||||
break;
|
||||
case FE_ATSC:
|
||||
list = ®ions_ATSC;
|
||||
break;
|
||||
default:
|
||||
tvhlog(LOG_ERR, "DVB", "No built-in config for fetype %d", fetype);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
out = htsmsg_create_list();
|
||||
|
||||
if(!strcmp(node, "root")) {
|
||||
|
||||
for(i = 0; i < nr; i++) {
|
||||
LIST_FOREACH(r, list, link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_u32(e, "leaf", 0);
|
||||
htsmsg_add_str(e, "text", r[i].name);
|
||||
htsmsg_add_str(e, "id", r[i].name);
|
||||
htsmsg_add_str(e, "text", r->name);
|
||||
htsmsg_add_str(e, "id", r->id);
|
||||
htsmsg_add_msg(out, NULL, e);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
for(i = 0; i < nr; i++)
|
||||
if(!strcmp(node, r[i].name))
|
||||
LIST_FOREACH(r, list, link)
|
||||
if (!strcmp(node, r->id))
|
||||
break;
|
||||
if (!r) return out;
|
||||
|
||||
if(i == nr)
|
||||
return out;
|
||||
n = r[i].networks;
|
||||
nn = r[i].nnetworks;
|
||||
|
||||
for(i = 0; i < nn; i++) {
|
||||
LIST_FOREACH(n, &r->networks, link) {
|
||||
e = htsmsg_create_map();
|
||||
htsmsg_add_u32(e, "leaf", 1);
|
||||
htsmsg_add_str(e, "text", n[i].name);
|
||||
htsmsg_add_str(e, "id", n[i].name);
|
||||
htsmsg_add_str(e, "text", n->name);
|
||||
htsmsg_add_str(e, "id", n->id);
|
||||
htsmsg_add_msg(out, NULL, e);
|
||||
}
|
||||
|
||||
|
|
14173
src/linuxtv_muxes.h
14173
src/linuxtv_muxes.h
File diff suppressed because it is too large
Load diff
10
src/main.c
10
src/main.c
|
@ -57,6 +57,7 @@
|
|||
#include "trap.h"
|
||||
#include "settings.h"
|
||||
#include "ffdecsa/FFdecsa.h"
|
||||
#include "muxes.h"
|
||||
|
||||
int running;
|
||||
time_t dispatch_clock;
|
||||
|
@ -168,6 +169,7 @@ usage(const char *argv0)
|
|||
printf(" -a <adapters> Use only DVB adapters specified (csv)\n");
|
||||
printf(" -c <directory> Alternate configuration path.\n"
|
||||
" Defaults to [$HOME/.hts/tvheadend]\n");
|
||||
printf(" -m <directory> Alternate mux configuration directory\n");
|
||||
printf(" -f Fork and daemonize\n");
|
||||
printf(" -p <pidfile> Write pid to <pidfile> instead of /var/run/tvheadend.pid,\n"
|
||||
" only works with -f\n");
|
||||
|
@ -257,11 +259,12 @@ main(int argc, char **argv)
|
|||
char *p, *endp;
|
||||
uint32_t adapter_mask = 0xffffffff;
|
||||
int crash = 0;
|
||||
const char *muxpath = NULL;
|
||||
|
||||
// make sure the timezone is set
|
||||
tzset();
|
||||
|
||||
while((c = getopt(argc, argv, "Aa:fp:u:g:c:Chdr:j:s")) != -1) {
|
||||
while((c = getopt(argc, argv, "Aa:fp:u:g:c:m:Chdr:j:s")) != -1) {
|
||||
switch(c) {
|
||||
case 'a':
|
||||
adapter_mask = 0x0;
|
||||
|
@ -301,6 +304,9 @@ main(int argc, char **argv)
|
|||
case 'c':
|
||||
confpath = optarg;
|
||||
break;
|
||||
case 'm':
|
||||
muxpath = optarg;
|
||||
break;
|
||||
case 'd':
|
||||
log_debug_to_console = 1;
|
||||
break;
|
||||
|
@ -380,6 +386,8 @@ main(int argc, char **argv)
|
|||
* Initialize subsystems
|
||||
*/
|
||||
|
||||
muxes_init(muxpath);
|
||||
|
||||
service_init();
|
||||
|
||||
channels_init();
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
gcc -O2 -Wall main.c -o muxbuilder
|
||||
|
||||
cat <<EOF
|
||||
|
||||
struct mux {
|
||||
unsigned int freq;
|
||||
unsigned int symrate;
|
||||
char fec;
|
||||
char constellation;
|
||||
char bw;
|
||||
char fechp;
|
||||
char feclp;
|
||||
char tmode;
|
||||
char guard;
|
||||
char hierarchy;
|
||||
char polarisation;
|
||||
};
|
||||
|
||||
struct network {
|
||||
const char *name;
|
||||
const struct mux *muxes;
|
||||
const int nmuxes;
|
||||
};
|
||||
|
||||
struct region {
|
||||
const char *name;
|
||||
const struct network *networks;
|
||||
const int nnetworks;
|
||||
};
|
||||
|
||||
EOF
|
||||
|
||||
|
||||
find $1/dvb-s -type f | sort | xargs ./muxbuilder DVBS
|
||||
find $1/dvb-t -type f | sort | xargs ./muxbuilder DVBT
|
||||
find $1/dvb-c -type f | sort | xargs ./muxbuilder DVBC
|
||||
find $1/atsc -type f | sort | xargs ./muxbuilder ATSC
|
|
@ -1,548 +0,0 @@
|
|||
#include <stdlib.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
|
||||
char *type;
|
||||
|
||||
struct strtab {
|
||||
const char *v1;
|
||||
const char *v2;
|
||||
};
|
||||
|
||||
static struct strtab fectab[] = {
|
||||
{ "NONE", "0" },
|
||||
{ "1/2", "1" },
|
||||
{ "2/3", "2" },
|
||||
{ "3/4", "3" },
|
||||
{ "4/5", "4" },
|
||||
{ "5/6", "5" },
|
||||
{ "6/7", "6" },
|
||||
{ "7/8", "7" },
|
||||
{ "8/9", "8" },
|
||||
{ "AUTO", "9" },
|
||||
{ "1/1", "9" },
|
||||
{ "3/5", "10" },
|
||||
{ "9/10", "11" },
|
||||
};
|
||||
|
||||
static struct strtab qamtab[] = {
|
||||
{ "QPSK", "0" },
|
||||
{ "QAM16", "1" },
|
||||
{ "QAM32", "2" },
|
||||
{ "QAM64", "3" },
|
||||
{ "QAM128", "4" },
|
||||
{ "QAM256", "5" },
|
||||
{ "AUTO", "6" },
|
||||
{ "8VSB", "7" },
|
||||
{ "16VSB", "8" },
|
||||
{ "8PSK", "9" }
|
||||
};
|
||||
|
||||
static struct strtab bwtab[] = {
|
||||
{ "8MHz", "0" },
|
||||
{ "7MHz", "1" },
|
||||
{ "6MHz", "2" },
|
||||
{ "AUTO", "3" }
|
||||
};
|
||||
|
||||
static struct strtab modetab[] = {
|
||||
{ "2k", "0" },
|
||||
{ "8k", "1" },
|
||||
{ "AUTO", "2" }
|
||||
};
|
||||
|
||||
static struct strtab guardtab[] = {
|
||||
{ "1/32", "0" },
|
||||
{ "1/16", "1" },
|
||||
{ "1/8", "2" },
|
||||
{ "1/4", "3" },
|
||||
{ "AUTO", "4" },
|
||||
};
|
||||
|
||||
static struct strtab hiertab[] = {
|
||||
{ "NONE", "0" },
|
||||
{ "1", "1" },
|
||||
{ "2", "2" },
|
||||
{ "4", "3" },
|
||||
{ "AUTO", "4" }
|
||||
};
|
||||
|
||||
|
||||
static const char *
|
||||
str2str0(const char *str, struct strtab tab[], int l, const char *what)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < l; i++)
|
||||
if(!strcasecmp(str, tab[i].v1))
|
||||
return tab[i].v2;
|
||||
fprintf(stderr, "Warning, cannot translate %s (%s)\n", str, what);
|
||||
return "#error";
|
||||
}
|
||||
|
||||
#define str2str(str, tab,what) str2str0(str, tab, sizeof(tab) / sizeof(tab[0]),what)
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
dvb_t_config(const char *l)
|
||||
{
|
||||
unsigned long freq;
|
||||
char bw[20], fec[20], fec2[20], qam[20], mode[20], guard[20], hier[20];
|
||||
int r;
|
||||
|
||||
r = sscanf(l, "%lu %10s %10s %10s %10s %10s %10s %10s",
|
||||
&freq, bw, fec, fec2, qam, mode, guard, hier);
|
||||
|
||||
if(r != 8)
|
||||
return;
|
||||
|
||||
printf("\t{.freq = %lu, "
|
||||
".bw = %s, "
|
||||
".constellation = %s, "
|
||||
".fechp = %s, "
|
||||
".feclp = %s, "
|
||||
".tmode = %s, "
|
||||
".guard = %s, "
|
||||
".hierarchy = %s},\n "
|
||||
,
|
||||
freq,
|
||||
str2str(bw, bwtab, "bandwidth"),
|
||||
str2str(qam, qamtab, "constellation"),
|
||||
str2str(fec, fectab, "fec"),
|
||||
str2str(fec2, fectab, "fec2"),
|
||||
str2str(mode, modetab, "mode"),
|
||||
str2str(guard, guardtab, "guard"),
|
||||
str2str(hier, hiertab, "hierarchy"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
dvb_s_config(const char *l)
|
||||
{
|
||||
unsigned long freq, symrate;
|
||||
char fec[20], polarisation;
|
||||
int r;
|
||||
|
||||
r = sscanf(l, "%lu %c %lu %s",
|
||||
&freq, &polarisation, &symrate, fec);
|
||||
|
||||
if(r != 4)
|
||||
return;
|
||||
|
||||
printf("\t{"
|
||||
".freq = %lu, "
|
||||
".symrate = %lu, "
|
||||
".fec = %s, "
|
||||
".polarisation = '%c'"
|
||||
"},\n",
|
||||
freq,
|
||||
symrate,
|
||||
str2str(fec, fectab, "fec"),
|
||||
polarisation);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dvb_s2_config(const char *l)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
dvb_c_config(const char *l)
|
||||
{
|
||||
unsigned long freq, symrate;
|
||||
char fec[20], qam[20];
|
||||
int r;
|
||||
|
||||
r = sscanf(l, "%lu %lu %s %s",
|
||||
&freq, &symrate, fec, qam);
|
||||
|
||||
if(r != 4)
|
||||
return;
|
||||
|
||||
printf("\t{ "
|
||||
".freq = %lu, .symrate = %lu, .fec = %s, .constellation = %s},\n",
|
||||
freq, symrate, str2str(fec, fectab, "fec"), str2str(qam, qamtab, "constellations"));
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
atsc_config(const char *l)
|
||||
{
|
||||
unsigned long freq;
|
||||
char modulation[20];
|
||||
int r;
|
||||
|
||||
r = sscanf(l, "%lu %s",
|
||||
&freq, modulation);
|
||||
|
||||
if(r != 2)
|
||||
return;
|
||||
|
||||
printf("\t{ "
|
||||
".freq = %lu, .constellation = %s},\n",
|
||||
freq, str2str(modulation, qamtab, "constellations"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
typedef struct network {
|
||||
char *structname;
|
||||
char *displayname;
|
||||
char *comment;
|
||||
struct network *next;
|
||||
} network_t;
|
||||
|
||||
|
||||
typedef struct region {
|
||||
char *shortname;
|
||||
char *longname;
|
||||
struct network *networks;
|
||||
struct region *next;
|
||||
} region_t;
|
||||
|
||||
region_t *regions;
|
||||
|
||||
|
||||
static region_t *
|
||||
find_region(const char *name, const char *longname)
|
||||
{
|
||||
region_t *c, *n, **p;
|
||||
|
||||
for(c = regions; c != NULL; c = c->next)
|
||||
if(!strcmp(name, c->shortname))
|
||||
return c;
|
||||
|
||||
n = malloc(sizeof(region_t));
|
||||
n->shortname = strdup(name);
|
||||
n->longname = strdup(longname);
|
||||
n->networks = NULL;
|
||||
|
||||
if(regions == NULL)
|
||||
regions = n;
|
||||
else {
|
||||
p = ®ions;
|
||||
while((c = *p) != NULL) {
|
||||
if(strcmp(c->longname, longname) > 0)
|
||||
break;
|
||||
p = &c->next;
|
||||
}
|
||||
n->next = *p;
|
||||
*p = n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static network_t *
|
||||
add_network(region_t *x, const char *name)
|
||||
{
|
||||
network_t *m, *n, **p;
|
||||
|
||||
n = calloc(1, sizeof(network_t));
|
||||
n->structname = strdup(name);
|
||||
|
||||
if(x->networks == NULL)
|
||||
x->networks = n;
|
||||
else {
|
||||
p = &x->networks;
|
||||
while((m = *p) != NULL) {
|
||||
if(strcmp(m->structname, name) > 0)
|
||||
break;
|
||||
p = &m->next;
|
||||
}
|
||||
n->next = *p;
|
||||
*p = n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
static const struct {
|
||||
const char *code;
|
||||
const char *name;
|
||||
|
||||
} tldlist[] = {
|
||||
{"auto", "--Generic--"},
|
||||
{"ad", "Andorra"},
|
||||
{"at", "Austria"},
|
||||
{"au", "Australia"},
|
||||
{"ax", "Aland Islands"},
|
||||
{"be", "Belgium"},
|
||||
{"br", "Brazil"},
|
||||
{"ca", "Canada"},
|
||||
{"ch", "Switzerland"},
|
||||
{"cz", "Czech Republic"},
|
||||
{"de", "Germany"},
|
||||
{"dk", "Denmark"},
|
||||
{"es", "Spain"},
|
||||
{"fi", "Finland"},
|
||||
{"fr", "France"},
|
||||
{"gr", "Greece"},
|
||||
{"hk", "Hong Kong"},
|
||||
{"hr", "Croatia"},
|
||||
{"hu", "Hungary"},
|
||||
{"il", "Israel"},
|
||||
{"ir", "Iran"},
|
||||
{"is", "Iceland"},
|
||||
{"it", "Italy"},
|
||||
{"lt", "Lithuania"},
|
||||
{"lu", "Luxembourg"},
|
||||
{"lv", "Latvia"},
|
||||
{"nl", "Netherlands"},
|
||||
{"no", "Norway"},
|
||||
{"nz", "New Zealand"},
|
||||
{"pl", "Poland"},
|
||||
{"ro", "Romania"},
|
||||
{"se", "Sweden"},
|
||||
{"si", "Slovenia"},
|
||||
{"sk", "Slovakia"},
|
||||
{"tw", "Taiwan"},
|
||||
{"uk", "United Kingdom"},
|
||||
{"us", "United States"},
|
||||
{"vn", "Vietnam"},
|
||||
};
|
||||
|
||||
static const char *
|
||||
tldcode2longname(const char *tld)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < sizeof(tldlist) / sizeof(tldlist[0]); i++)
|
||||
if(!strcmp(tld, tldlist[i].code))
|
||||
return tldlist[i].name;
|
||||
|
||||
fprintf(stderr, "Unable to translate tld %s\n", tld);
|
||||
fprintf(stderr, "Exiting. Output is incomplete\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static void
|
||||
scan_file(char *fname)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[200];
|
||||
int l;
|
||||
char c, *s;
|
||||
char smartname[200];
|
||||
char *bn;
|
||||
int gotcomment = 0;
|
||||
region_t *co;
|
||||
network_t *ne;
|
||||
char *name, *displayname;
|
||||
|
||||
char buf[100];
|
||||
|
||||
fp = fopen(fname, "r");
|
||||
if(fp == NULL) {
|
||||
fprintf(stderr, "Unable to open file %s -- %s", fname, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
l = 0;
|
||||
bn = basename(fname);
|
||||
while(*bn) {
|
||||
c = *bn++;
|
||||
smartname[l++] = isalnum(c) ? c : '_';
|
||||
}
|
||||
smartname[l] = 0;
|
||||
|
||||
name = basename(fname);
|
||||
|
||||
if(!strcmp(type, "DVBS")) {
|
||||
displayname = name;
|
||||
co = find_region("geo", "Geosynchronous Orbit");
|
||||
|
||||
} else {
|
||||
l = 0;
|
||||
c = 0;
|
||||
while(*name && c != '-') {
|
||||
c = *name++;
|
||||
if (c != '-') {
|
||||
buf[l++] = c;
|
||||
}
|
||||
}
|
||||
buf[l] = 0;
|
||||
displayname = name;
|
||||
co = find_region(buf, tldcode2longname(buf));
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s_%s", type, smartname);
|
||||
|
||||
printf("static const struct mux muxes_%s[] = {\n", buf);
|
||||
|
||||
ne = add_network(co, buf);
|
||||
bn = ne->displayname = strdup(displayname);
|
||||
|
||||
while(*bn) {
|
||||
if(*bn == '_') *bn = ' ';
|
||||
bn++;
|
||||
}
|
||||
|
||||
// ne->muxlistname = strdup(buf);
|
||||
|
||||
#if 0
|
||||
if(pass == 2) {
|
||||
printf("{\n");
|
||||
printf("\t.type = %s,\n", type);
|
||||
printf("\t.name = \"%s\",\n", basename(fname));
|
||||
printf("\t.muxes = muxlist_%s_%s,\n", type, smartname);
|
||||
printf("\t.nmuxes = sizeof(muxlist_%s_%s) / sizeof(struct mux),\n",
|
||||
type, smartname);
|
||||
printf("\t.comment = ");
|
||||
}
|
||||
#endif
|
||||
|
||||
while(!feof(fp)) {
|
||||
memset(line, 0, sizeof(line));
|
||||
|
||||
if(fgets(line, sizeof(line) - 1, fp) == NULL)
|
||||
break;
|
||||
|
||||
l = strlen(line);
|
||||
while(l > 0 && line[l - 1] < 32)
|
||||
line[--l] = 0;
|
||||
|
||||
switch(line[0]) {
|
||||
case '#':
|
||||
if(gotcomment)
|
||||
break;
|
||||
|
||||
s = line + 2;
|
||||
if(strstr(s, " freq "))
|
||||
break;
|
||||
|
||||
// ne->comment = strdup(s);
|
||||
gotcomment = 1;
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
atsc_config(line + 1);
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
dvb_c_config(line + 1);
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
dvb_t_config(line + 1);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
if(line[1] == '2')
|
||||
dvb_s2_config(line + 2);
|
||||
else
|
||||
dvb_s_config(line + 1);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
dump_networks(region_t *c)
|
||||
{
|
||||
network_t *n;
|
||||
|
||||
printf("static const struct network networks_%s_%s[] = {\n",
|
||||
type, c->shortname);
|
||||
|
||||
for(n = c->networks; n != NULL; n = n->next) {
|
||||
|
||||
printf("\t{\n");
|
||||
printf("\t\t.name = \"%s\",\n", n->displayname);
|
||||
printf("\t\t.muxes = muxes_%s,\n", n->structname);
|
||||
printf("\t\t.nmuxes = sizeof(muxes_%s) / sizeof(struct mux),\n",
|
||||
n->structname);
|
||||
if(n->comment)
|
||||
printf("\t\t.comment = \"%s\",\n", n->comment);
|
||||
printf("\t},\n");
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void
|
||||
dump_regions(void)
|
||||
{
|
||||
region_t *r;
|
||||
|
||||
printf("static const struct region regions_%s[] = {\n", type);
|
||||
|
||||
for(r = regions; r != NULL; r = r->next) {
|
||||
|
||||
printf("\t{\n");
|
||||
printf("\t\t.name = \"%s\",\n", r->longname);
|
||||
printf("\t\t.networks = networks_%s_%s,\n", type, r->shortname);
|
||||
printf("\t\t.nnetworks = sizeof(networks_%s_%s) / sizeof(struct network),\n",
|
||||
type, r->shortname);
|
||||
printf("\t},\n");
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
region_t *c;
|
||||
|
||||
if(argc < 2)
|
||||
return 1;
|
||||
|
||||
type = argv[1];
|
||||
#if 0
|
||||
printf("struct mux {\n"
|
||||
"unsigned int freq;\n"
|
||||
"unsigned int symrate;\n"
|
||||
"char fec;\n"
|
||||
"char constellation;\n"
|
||||
"char bw;\n"
|
||||
"char fechp;\n"
|
||||
"char feclp;\n"
|
||||
"char tmode;\n"
|
||||
"char guard;\n"
|
||||
"char hierarchy;\n"
|
||||
"char polarisation;\n"
|
||||
"}\n");
|
||||
#endif
|
||||
|
||||
for(i = 2; i < argc; i++)
|
||||
scan_file(argv[i]);
|
||||
|
||||
for(c = regions; c != NULL; c = c->next) {
|
||||
dump_networks(c);
|
||||
}
|
||||
dump_regions();
|
||||
|
||||
return 0;
|
||||
}
|
354
src/muxes.c
Normal file
354
src/muxes.c
Normal file
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* tvheadend, intial mux list
|
||||
* Copyright (C) 2012 Adam Sutton
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <stdlib.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "tvheadend.h"
|
||||
#include "dvb/dvb.h"
|
||||
#include "muxes.h"
|
||||
|
||||
region_list_t regions_DVBC;
|
||||
region_list_t regions_DVBT;
|
||||
region_list_t regions_DVBS;
|
||||
region_list_t regions_ATSC;
|
||||
|
||||
/* **************************************************************************
|
||||
* Country codes
|
||||
* *************************************************************************/
|
||||
|
||||
static const struct {
|
||||
const char *code;
|
||||
const char *name;
|
||||
|
||||
} tldlist[] = {
|
||||
{"auto", "--Generic--"},
|
||||
{"ad", "Andorra"},
|
||||
{"at", "Austria"},
|
||||
{"au", "Australia"},
|
||||
{"ax", "Aland Islands"},
|
||||
{"be", "Belgium"},
|
||||
{"br", "Brazil"},
|
||||
{"ca", "Canada"},
|
||||
{"ch", "Switzerland"},
|
||||
{"cz", "Czech Republic"},
|
||||
{"de", "Germany"},
|
||||
{"dk", "Denmark"},
|
||||
{"es", "Spain"},
|
||||
{"fi", "Finland"},
|
||||
{"fr", "France"},
|
||||
{"gr", "Greece"},
|
||||
{"hk", "Hong Kong"},
|
||||
{"hr", "Croatia"},
|
||||
{"hu", "Hungary"},
|
||||
{"il", "Israel"},
|
||||
{"ir", "Iran"},
|
||||
{"is", "Iceland"},
|
||||
{"it", "Italy"},
|
||||
{"lt", "Lithuania"},
|
||||
{"lu", "Luxembourg"},
|
||||
{"lv", "Latvia"},
|
||||
{"nl", "Netherlands"},
|
||||
{"no", "Norway"},
|
||||
{"nz", "New Zealand"},
|
||||
{"pl", "Poland"},
|
||||
{"ro", "Romania"},
|
||||
{"se", "Sweden"},
|
||||
{"si", "Slovenia"},
|
||||
{"sk", "Slovakia"},
|
||||
{"tw", "Taiwan"},
|
||||
{"uk", "United Kingdom"},
|
||||
{"us", "United States"},
|
||||
{"vn", "Vietnam"},
|
||||
};
|
||||
|
||||
static const char *
|
||||
tldcode2longname(const char *tld)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < sizeof(tldlist) / sizeof(tldlist[0]); i++)
|
||||
if(!strcmp(tld, tldlist[i].code))
|
||||
return tldlist[i].name;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Type specific parsers
|
||||
* *************************************************************************/
|
||||
|
||||
static int _muxes_load_atsc ( mux_t *mux, const char *line )
|
||||
{
|
||||
char qam[20];
|
||||
int r;
|
||||
|
||||
r = sscanf(line, "%u %s", &mux->freq, qam);
|
||||
if (r != 2) return 1;
|
||||
if ((mux->constellation = dvb_mux_str2qam(qam)) == -1) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _muxes_load_dvbt ( mux_t *mux, const char *line )
|
||||
{
|
||||
char bw[20], fec[20], fec2[20], qam[20], mode[20], guard[20], hier[20];
|
||||
int r;
|
||||
|
||||
r = sscanf(line, "%u %10s %10s %10s %10s %10s %10s %10s",
|
||||
&mux->freq, bw, fec, fec2, qam, mode, guard, hier);
|
||||
if(r != 8) return 1;
|
||||
|
||||
if ((mux->bw = dvb_mux_str2bw(bw)) == -1) return 1;
|
||||
if ((mux->constellation = dvb_mux_str2qam(qam)) == -1) return 1;
|
||||
if ((mux->fechp = dvb_mux_str2fec(fec)) == -1) return 1;
|
||||
if ((mux->feclp = dvb_mux_str2fec(fec2)) == -1) return 1;
|
||||
if ((mux->tmode = dvb_mux_str2mode(mode)) == -1) return 1;
|
||||
if ((mux->guard = dvb_mux_str2guard(guard)) == -1) return 1;
|
||||
if ((mux->hierarchy = dvb_mux_str2hier(hier)) == -1) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _muxes_load_dvbs ( mux_t *mux, const char *line )
|
||||
{
|
||||
char fec[20], qam[20], hier[20];
|
||||
int r, v2 = 0;
|
||||
|
||||
if (*line == '2') {
|
||||
v2 = 2;
|
||||
line++;
|
||||
}
|
||||
|
||||
r = sscanf(line, "%u %c %u %s %s %s",
|
||||
&mux->freq, &mux->polarisation, &mux->symrate,
|
||||
fec, hier, qam);
|
||||
if (r != (4+v2)) return 1;
|
||||
|
||||
if ((mux->fec = dvb_mux_str2fec(fec)) == -1) return 1;
|
||||
if (v2) {
|
||||
if ((mux->hierarchy = dvb_mux_str2hier(hier)) == -1) return 1;
|
||||
if ((mux->constellation = dvb_mux_str2qam(qam)) == -1) return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _muxes_load_dvbc ( mux_t *mux, const char *line )
|
||||
{
|
||||
char fec[20], qam[20];
|
||||
int r;
|
||||
|
||||
r = sscanf(line, "%u %u %s %s",
|
||||
&mux->freq, &mux->symrate, fec, qam);
|
||||
if(r != 4) return 1;
|
||||
|
||||
if ((mux->fec = dvb_mux_str2fec(fec)) == -1) return 1;
|
||||
if ((mux->constellation = dvb_mux_str2qam(qam)) == -1) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* **************************************************************************
|
||||
* File processing
|
||||
* *************************************************************************/
|
||||
|
||||
/*
|
||||
* Sorting
|
||||
*/
|
||||
static int _net_cmp ( void *a, void *b )
|
||||
{
|
||||
return strcmp(((network_t*)a)->name, ((network_t*)b)->name);
|
||||
}
|
||||
static int _reg_cmp ( void *a, void *b )
|
||||
{
|
||||
return strcmp(((region_t*)a)->name, ((region_t*)b)->name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create/Find region entry
|
||||
*/
|
||||
static region_t *_muxes_region_create
|
||||
( const char *type, const char *id, const char *desc )
|
||||
{
|
||||
region_t *reg;
|
||||
region_list_t *list = NULL;
|
||||
if (!strcmp(type, "dvb-s")) list = ®ions_DVBS;
|
||||
else if (!strcmp(type, "dvb-t")) list = ®ions_DVBT;
|
||||
else if (!strcmp(type, "dvb-c")) list = ®ions_DVBC;
|
||||
else if (!strcmp(type, "atsc")) list = ®ions_ATSC;
|
||||
if (!list) return NULL;
|
||||
|
||||
LIST_FOREACH(reg, list, link) {
|
||||
if (!strcmp(reg->id, id)) break;
|
||||
}
|
||||
|
||||
if (!reg) {
|
||||
reg = calloc(1, sizeof(region_t));
|
||||
reg->id = strdup(id);
|
||||
reg->name = strdup(desc);
|
||||
LIST_INSERT_SORTED(list, reg, link, _reg_cmp);
|
||||
}
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
/*
|
||||
* Process mux entry
|
||||
*/
|
||||
static void _muxes_load_one ( network_t *net, const char *line )
|
||||
{
|
||||
int r = 1;
|
||||
mux_t *mux = calloc(1, sizeof(mux_t));
|
||||
|
||||
switch (line[0]) {
|
||||
case 'A':
|
||||
r = _muxes_load_atsc(mux, line+1);
|
||||
break;
|
||||
case 'T':
|
||||
r = _muxes_load_dvbt(mux, line+1);
|
||||
break;
|
||||
case 'S':
|
||||
r = _muxes_load_dvbs(mux, line+1);
|
||||
break;
|
||||
case 'C':
|
||||
r = _muxes_load_dvbc(mux, line+1);
|
||||
break;
|
||||
}
|
||||
|
||||
if (r) {
|
||||
free(mux);
|
||||
} else {
|
||||
LIST_INSERT_HEAD(&net->muxes, mux, link);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process a file
|
||||
*/
|
||||
static void _muxes_load_file ( const char *type, const char *path )
|
||||
{
|
||||
FILE *fp;
|
||||
int i;
|
||||
region_t *reg;
|
||||
network_t *net;
|
||||
char *name, *co;
|
||||
char buf[256], buf2[256];
|
||||
|
||||
fp = fopen(path, "r");
|
||||
if (!fp) return;
|
||||
|
||||
/* Region */
|
||||
strcpy(buf, path);
|
||||
if (!(name = basename(buf))) return;
|
||||
if (!strcmp(type, "dvb-s")) {
|
||||
reg = _muxes_region_create(type, "geo", "Geo-synchronous Orbit");
|
||||
} else {
|
||||
if (!(co = strtok(name, "-"))) return;
|
||||
reg = _muxes_region_create(type, co, tldcode2longname(co));
|
||||
}
|
||||
if (!reg) return;
|
||||
|
||||
/* Network */
|
||||
i = 0;
|
||||
name = basename((char*)path);
|
||||
while (*name) {
|
||||
buf[i++] = isalnum(*name) ? *name : '_';
|
||||
name++;
|
||||
}
|
||||
buf[i] = '\0';
|
||||
snprintf(buf2, sizeof(buf2), "%s_%s", type, buf);
|
||||
net = calloc(1, sizeof(network_t));
|
||||
net->id = strdup(buf2);
|
||||
net->name = strdup(buf);
|
||||
LIST_INSERT_SORTED(®->networks, net, link, _net_cmp);
|
||||
|
||||
/* Process file */
|
||||
while (!feof(fp)) {
|
||||
|
||||
/* Get line */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
if (!fgets(buf, sizeof(buf) - 1, fp)) break;
|
||||
i = 0;
|
||||
while (buf[i]) {
|
||||
if (buf[i] == '#')
|
||||
buf[i] = '\0';
|
||||
else
|
||||
i++;
|
||||
}
|
||||
while (i > 0 && buf[i-1] < 32) buf[--i] = 0;
|
||||
|
||||
/* Process mux */
|
||||
switch (*buf) {
|
||||
case 'A':
|
||||
case 'C':
|
||||
case 'T':
|
||||
case 'S':
|
||||
_muxes_load_one(net, buf);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Process directory
|
||||
*
|
||||
* Note: should we follow symlinks?
|
||||
*/
|
||||
static void _muxes_load_dir ( const char *path, const char *type )
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *dent;
|
||||
struct stat st;
|
||||
|
||||
if (!(dir = opendir(path))) return;
|
||||
|
||||
while ((dent = readdir(dir))) {
|
||||
if (*dent->d_name == '.') continue;
|
||||
char p[256];
|
||||
sprintf(p, "%s/%s", path, dent->d_name);
|
||||
if (stat(p, &st)) continue;
|
||||
if (S_ISDIR(st.st_mode))
|
||||
_muxes_load_dir(p, dent->d_name);
|
||||
else
|
||||
_muxes_load_file(type, p);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the mux list
|
||||
*/
|
||||
void muxes_init ( const char *path )
|
||||
{
|
||||
/* TODO: Default */
|
||||
if (!path) return;
|
||||
|
||||
/* Process */
|
||||
_muxes_load_dir(path, NULL);
|
||||
}
|
59
src/muxes.h
Normal file
59
src/muxes.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* tvheadend, intial mux list
|
||||
* Copyright (C) 2012 Adam Sutton
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __TVH_MUXES_H__
|
||||
#define __TVH_MUXES_H__
|
||||
|
||||
typedef struct mux {
|
||||
LIST_ENTRY(mux) link;
|
||||
unsigned int freq;
|
||||
unsigned int symrate;
|
||||
char fec;
|
||||
char constellation;
|
||||
char bw;
|
||||
char fechp;
|
||||
char feclp;
|
||||
char tmode;
|
||||
char guard;
|
||||
char hierarchy;
|
||||
char polarisation;
|
||||
} mux_t;
|
||||
|
||||
typedef struct network {
|
||||
const char *id;
|
||||
const char *name;
|
||||
LIST_ENTRY(network) link;
|
||||
LIST_HEAD(,mux) muxes;
|
||||
} network_t;
|
||||
|
||||
typedef struct region {
|
||||
const char *id;
|
||||
const char *name;
|
||||
LIST_ENTRY(region) link;
|
||||
LIST_HEAD(,network) networks;
|
||||
} region_t;
|
||||
|
||||
typedef LIST_HEAD(,region) region_list_t;
|
||||
extern region_list_t regions_DVBC;
|
||||
extern region_list_t regions_DVBT;
|
||||
extern region_list_t regions_DVBS;
|
||||
extern region_list_t regions_ATSC;
|
||||
|
||||
void muxes_init ( const char *path );
|
||||
|
||||
#endif /* __TVH_MUXES_H__ */
|
Loading…
Add table
Reference in a new issue