diff --git a/Makefile b/Makefile index 07473355..75f50843 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ SRCS += pvr.c pvr_rec.c SRCS += epg.c epg_xmltv.c -SRCS += dvb.c dvb_support.c dvb_pmt.c dvb_dvr.c +SRCS += dvb.c dvb_support.c dvb_pmt.c dvb_dvr.c dvb_muxconfig.c SRCS += iptv_input.c iptv_output.c diff --git a/dvb.c b/dvb.c index 428e7df5..cd4febe9 100644 --- a/dvb.c +++ b/dvb.c @@ -44,6 +44,7 @@ #include "dvb_support.h" #include "dvb_pmt.h" #include "dvb_dvr.h" +#include "dvb_muxconfig.h" struct th_dvb_mux_list dvb_muxes; struct th_dvb_adapter_list dvb_adapters_probing; @@ -57,8 +58,6 @@ static int dvb_tune_tdmi(th_dvb_mux_instance_t *tdmi, int maylog); static void *dvb_monitor_thread(void *aux); -static void dvb_add_muxes(void); - static void tdmi_check_scan_status(th_dvb_mux_instance_t *tdmi); static void dvb_start_initial_scan(th_dvb_mux_instance_t *tdmi); @@ -129,11 +128,17 @@ dvb_init(void) dvb_add_adapter(path); } - dvb_add_muxes(); + dvb_mux_setup(); LIST_FOREACH(tda, &dvb_adapters_probing, tda_link) { tdmi = LIST_FIRST(&tda->tda_muxes_configured); - dvb_start_initial_scan(tdmi); + if(tdmi == NULL) { + syslog(LOG_WARNING, + "No muxes configured on \"%s\" DVB adapter unused", + tda->tda_name); + } else { + dvb_start_initial_scan(tdmi); + } } } @@ -288,72 +293,6 @@ dvb_tune(th_dvb_adapter_t *tda, th_dvb_mux_t *tdm, int maylog) -static void -dvb_add_mux_instance(th_dvb_adapter_t *tda, th_dvb_mux_t *tdm) -{ - th_dvb_mux_instance_t *tdmi; - - tdmi = calloc(1, sizeof(th_dvb_mux_instance_t)); - - tdmi->tdmi_status = TDMI_CONFIGURED; - - tdmi->tdmi_mux = tdm; - tdmi->tdmi_adapter = tda; - - LIST_INSERT_HEAD(&tda->tda_muxes_configured, tdmi, tdmi_adapter_link); - LIST_INSERT_HEAD(&tdm->tdm_instances, tdmi, tdmi_mux_link); -} - - - -static void -dvb_add_muxes(void) -{ - th_dvb_mux_t *tdm; - th_dvb_adapter_t *tda; - config_entry_t *ce; - const char *s; - struct dvb_frontend_parameters *fe_param; - char buf[100]; - - TAILQ_FOREACH(ce, &config_list, ce_link) { - if(ce->ce_type == CFG_SUB && !strcasecmp("dvbmux", ce->ce_key)) { - - if((s = config_get_str_sub(&ce->ce_sub, "name", NULL)) == NULL) - continue; - - tdm = calloc(1, sizeof(th_dvb_mux_t)); - fe_param = &tdm->tdm_fe_params; - - fe_param->inversion = INVERSION_AUTO; - fe_param->u.ofdm.bandwidth = BANDWIDTH_8_MHZ; - fe_param->u.ofdm.code_rate_HP = FEC_2_3; - fe_param->u.ofdm.code_rate_LP = FEC_1_2; - fe_param->u.ofdm.constellation = QAM_64; - fe_param->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; - fe_param->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; - fe_param->u.ofdm.hierarchy_information = HIERARCHY_NONE; - - fe_param->frequency = - atoi(config_get_str_sub(&ce->ce_sub, "frequency", "0")); - - tdm->tdm_name = strdup(s); - - snprintf(buf, sizeof(buf), "DVB-T: %s (%.1f MHz)", s, - (float)fe_param->frequency / 1000000.0f); - tdm->tdm_title = strdup(buf); - - LIST_INSERT_HEAD(&dvb_muxes, tdm, tdm_global_link); - - LIST_FOREACH(tda, &dvb_adapters_probing, tda_link) { - dvb_add_mux_instance(tda, tdm); - } - } - } -} - - - static void dvb_monitor_current_mux(th_dvb_adapter_t *tda) diff --git a/dvb_muxconfig.c b/dvb_muxconfig.c new file mode 100644 index 00000000..75fd7659 --- /dev/null +++ b/dvb_muxconfig.c @@ -0,0 +1,277 @@ +/* + * TV headend - Code for configuring DVB muxes + * This code is based on code from linux dvb-apps + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#include + +#include "tvhead.h" +#include "dvb.h" +#include "dvb_muxconfig.h" + + +static void +dvb_add_mux_instance(th_dvb_adapter_t *tda, th_dvb_mux_t *tdm) +{ + th_dvb_mux_instance_t *tdmi; + + tdmi = calloc(1, sizeof(th_dvb_mux_instance_t)); + + tdmi->tdmi_status = TDMI_CONFIGURED; + + tdmi->tdmi_mux = tdm; + tdmi->tdmi_adapter = tda; + + LIST_INSERT_HEAD(&tda->tda_muxes_configured, tdmi, tdmi_adapter_link); + LIST_INSERT_HEAD(&tdm->tdm_instances, tdmi, tdmi_mux_link); +} + + +static void +dvb_add_mux(struct dvb_frontend_parameters *fe_param, const char *name) +{ + th_dvb_mux_t *tdm; + th_dvb_adapter_t *tda; + char buf[100]; + + tdm = calloc(1, sizeof(th_dvb_mux_t)); + + memcpy(&tdm->tdm_fe_params, fe_param, + sizeof(struct dvb_frontend_parameters)); + + if(name == NULL) { + snprintf(buf, sizeof(buf), "DVB-%d", fe_param->frequency); + + tdm->tdm_name = strdup(buf); + + snprintf(buf, sizeof(buf), "DVB-T: %.1f MHz", + (float)fe_param->frequency / 1000000.0f); + } else { + tdm->tdm_name = strdup(name); + snprintf(buf, sizeof(buf), "DVB-T: %.1f MHz (%s)", + (float)fe_param->frequency / 1000000.0f, name); + } + + tdm->tdm_title = strdup(buf); + + LIST_INSERT_HEAD(&dvb_muxes, tdm, tdm_global_link); + + LIST_FOREACH(tda, &dvb_adapters_probing, tda_link) { + dvb_add_mux_instance(tda, tdm); + } +} + + + +struct strtab { + const char *str; + int val; +}; + + +static struct strtab fectab[] = { + { "NONE", FEC_NONE }, + { "1/2", FEC_1_2 }, + { "2/3", FEC_2_3 }, + { "3/4", FEC_3_4 }, + { "4/5", FEC_4_5 }, + { "5/6", FEC_5_6 }, + { "6/7", FEC_6_7 }, + { "7/8", FEC_7_8 }, + { "8/9", FEC_8_9 }, + { "AUTO", FEC_AUTO } +}; + +static struct strtab qamtab[] = { + { "QPSK", QPSK }, + { "QAM16", QAM_16 }, + { "QAM32", QAM_32 }, + { "QAM64", QAM_64 }, + { "QAM128", QAM_128 }, + { "QAM256", QAM_256 }, + { "AUTO", QAM_AUTO }, + { "8VSB", VSB_8 }, + { "16VSB", VSB_16 } +}; + +static struct strtab bwtab[] = { + { "8MHz", BANDWIDTH_8_MHZ }, + { "7MHz", BANDWIDTH_7_MHZ }, + { "6MHz", BANDWIDTH_6_MHZ }, + { "AUTO", BANDWIDTH_AUTO } +}; + +static struct strtab modetab[] = { + { "2k", TRANSMISSION_MODE_2K }, + { "8k", TRANSMISSION_MODE_8K }, + { "AUTO", TRANSMISSION_MODE_AUTO } +}; + + +static struct strtab guardtab[] = { + { "1/32", GUARD_INTERVAL_1_32 }, + { "1/16", GUARD_INTERVAL_1_16 }, + { "1/8", GUARD_INTERVAL_1_8 }, + { "1/4", GUARD_INTERVAL_1_4 }, + { "AUTO", GUARD_INTERVAL_AUTO }, +}; + +static struct strtab hiertab[] = { + { "NONE", HIERARCHY_NONE }, + { "1", HIERARCHY_1 }, + { "2", HIERARCHY_2 }, + { "4", HIERARCHY_4 }, + { "AUTO", HIERARCHY_AUTO } +}; + + + +static int +str2val0(const char *str, struct strtab tab[], int l) +{ + int i; + for(i = 0; i < l; i++) + if(!strcasecmp(str, tab[i].str)) + return tab[i].val; + + return -1; +} + +#define str2val(str, tab) str2val0(str, tab, sizeof(tab) / sizeof(tab[0])) + + + +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]; + struct dvb_frontend_parameters f; + 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; + + memset(&f, 0, sizeof(f)); + + f.inversion = INVERSION_AUTO; + f.frequency = freq; + f.u.ofdm.bandwidth = str2val(bw, bwtab); + f.u.ofdm.constellation = str2val(qam, qamtab); + f.u.ofdm.transmission_mode = str2val(mode, modetab); + f.u.ofdm.guard_interval = str2val(guard, guardtab); + f.u.ofdm.hierarchy_information = str2val(hier, hiertab); + + r = str2val(fec, fectab); + f.u.ofdm.code_rate_HP = r == FEC_NONE ? FEC_AUTO : r; + + r = str2val(fec2, fectab); + f.u.ofdm.code_rate_LP = r == FEC_NONE ? FEC_AUTO : r; + + dvb_add_mux(&f, NULL); +} + + + + + +static void +dvb_muxfile_add(const char *fname) +{ + FILE *fp; + char line[200]; + + fp = fopen(fname, "r"); + if(fp == NULL) { + syslog(LOG_ERR, "dvb: Unable to open file %s -- %s", + fname, strerror(errno)); + } + + while(!feof(fp)) { + memset(line, 0, sizeof(line)); + + if(fgets(line, sizeof(line) - 1, fp) == NULL) + break; + + switch(line[0]) { + case '#': + break; + + case 'T': + dvb_t_config(line + 1); + break; + + default: + break; + } + } +} + + + + +static void +dvb_add_configured_muxes(void) +{ + config_entry_t *ce; + const char *s; + struct dvb_frontend_parameters fe_param; + + TAILQ_FOREACH(ce, &config_list, ce_link) { + if(ce->ce_type == CFG_SUB && !strcasecmp("dvbmux", ce->ce_key)) { + + if((s = config_get_str_sub(&ce->ce_sub, "name", NULL)) == NULL) + continue; + + + fe_param.inversion = INVERSION_AUTO; + fe_param.u.ofdm.bandwidth = BANDWIDTH_8_MHZ; + fe_param.u.ofdm.code_rate_HP = FEC_2_3; + fe_param.u.ofdm.code_rate_LP = FEC_1_2; + fe_param.u.ofdm.constellation = QAM_64; + fe_param.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; + fe_param.u.ofdm.guard_interval = GUARD_INTERVAL_1_8; + fe_param.u.ofdm.hierarchy_information = HIERARCHY_NONE; + + fe_param.frequency = + atoi(config_get_str_sub(&ce->ce_sub, "frequency", "0")); + + dvb_add_mux(&fe_param, s); + } + } +} + + +void +dvb_mux_setup(void) +{ + const char *s; + + s = config_get_str("muxfile", NULL); + if(s != NULL) + dvb_muxfile_add(s); + + dvb_add_configured_muxes(); +} diff --git a/dvb_muxconfig.h b/dvb_muxconfig.h new file mode 100644 index 00000000..64684dc7 --- /dev/null +++ b/dvb_muxconfig.h @@ -0,0 +1,24 @@ +/* + * TV headend - Code for configuring DVB muxes + * Copyright (C) 2007 Andreas Öman + * + * 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 . + */ + +#ifndef DVB_MUXCONFIG_H_ +#define DVB_MUXCONFIG_H_ + +void dvb_mux_setup(void); + +#endif /* DVB_MUXCONFIG_H */