From: Robert Cameron Date: Thu, 10 May 2018 17:41:31 +0000 (-0700) Subject: Add logical network support for CableCARD networks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fb340ae8bea0c69910f27038de9a9179dd5fe392;p=thirdparty%2Ftvheadend.git Add logical network support for CableCARD networks --- diff --git a/src/input/mpegts/dvb.h b/src/input/mpegts/dvb.h index 317dff8df..db87594d4 100644 --- a/src/input/mpegts/dvb.h +++ b/src/input/mpegts/dvb.h @@ -421,6 +421,7 @@ typedef enum dvb_fe_type { DVB_TYPE_S, /* satellite */ DVB_TYPE_ATSC_T, /* terrestrial - north america */ DVB_TYPE_ATSC_C, /* cable - north america */ + DVB_TYPE_CABLECARD, /* CableCARD - North America */ DVB_TYPE_ISDB_T, /* terrestrial - japan, brazil */ DVB_TYPE_ISDB_C, /* cable - japan, brazil */ DVB_TYPE_ISDB_S, /* satellite - japan, brazil */ @@ -615,6 +616,12 @@ typedef struct dvb_isdbt_config { } layers[3]; } dvb_isdbt_config_t; +typedef struct dvb_fe_vchan { + uint32_t num; + uint16_t minor; + char *name; +} dvb_fe_vchan_t; + typedef struct dvb_mux_conf { dvb_fe_type_t dmc_fe_type; @@ -633,6 +640,7 @@ typedef struct dvb_mux_conf dvb_ofdm_config_t dmc_fe_ofdm; dvb_isdbt_config_t dmc_fe_isdbt; } u; + dvb_fe_vchan_t dmc_fe_vchan; // For scan file configurations LIST_ENTRY(dvb_mux_conf) dmc_link; diff --git a/src/input/mpegts/dvb_support.c b/src/input/mpegts/dvb_support.c index ab646a375..7a90ae677 100644 --- a/src/input/mpegts/dvb_support.c +++ b/src/input/mpegts/dvb_support.c @@ -683,6 +683,7 @@ const static struct strtab delsystab[] = { { "DVBC/ANNEX_A", DVB_SYS_DVBC_ANNEX_A }, { "DVBC_ANNEX_A", DVB_SYS_DVBC_ANNEX_A }, { "ATSC-C", DVB_SYS_DVBC_ANNEX_B }, + { "CableCARD", DVB_SYS_DVBC_ANNEX_B }, { "DVBC/ANNEX_B", DVB_SYS_DVBC_ANNEX_B }, { "DVBC_ANNEX_B", DVB_SYS_DVBC_ANNEX_B }, { "DVB-C/ANNEX-C",DVB_SYS_DVBC_ANNEX_C }, @@ -738,6 +739,8 @@ dvb_delsys2type ( mpegts_network_t *ln, dvb_fe_delivery_system_t delsys ) case DVB_SYS_DVBC_ANNEX_B: if (ln && idnode_is_instance(&ln->mn_id, &dvb_network_dvbc_class)) return DVB_TYPE_C; + if (ln && idnode_is_instance(&ln->mn_id, &dvb_network_cablecard_class)) + return DVB_TYPE_CABLECARD; else return DVB_TYPE_ATSC_C; case DVB_SYS_ISDBT: @@ -946,24 +949,25 @@ const static struct strtab poltab[] = { dvb_str2val(pol); const static struct strtab typetab[] = { - {"DVB-T", DVB_TYPE_T}, - {"DVB-C", DVB_TYPE_C}, - {"DVB-S", DVB_TYPE_S}, - {"ATSC-T", DVB_TYPE_ATSC_T}, - {"ATSC-C", DVB_TYPE_ATSC_C}, - {"ISDB-T", DVB_TYPE_ISDB_T}, - {"ISDB-C", DVB_TYPE_ISDB_C}, - {"ISDB-S", DVB_TYPE_ISDB_S}, - {"DAB", DVB_TYPE_DAB}, - {"DVBT", DVB_TYPE_T}, - {"DVBC", DVB_TYPE_C}, - {"DVBS", DVB_TYPE_S}, - {"ATSC", DVB_TYPE_ATSC_T}, - {"ATSCT", DVB_TYPE_ATSC_T}, - {"ATSCC", DVB_TYPE_ATSC_C}, - {"ISDBT", DVB_TYPE_ISDB_T}, - {"ISDBC", DVB_TYPE_ISDB_C}, - {"ISDBS", DVB_TYPE_ISDB_S} + {"DVB-T", DVB_TYPE_T}, + {"DVB-C", DVB_TYPE_C}, + {"DVB-S", DVB_TYPE_S}, + {"ATSC-T", DVB_TYPE_ATSC_T}, + {"ATSC-C", DVB_TYPE_ATSC_C}, + {"CableCARD", DVB_TYPE_CABLECARD}, + {"ISDB-T", DVB_TYPE_ISDB_T}, + {"ISDB-C", DVB_TYPE_ISDB_C}, + {"ISDB-S", DVB_TYPE_ISDB_S}, + {"DAB", DVB_TYPE_DAB}, + {"DVBT", DVB_TYPE_T}, + {"DVBC", DVB_TYPE_C}, + {"DVBS", DVB_TYPE_S}, + {"ATSC", DVB_TYPE_ATSC_T}, + {"ATSCT", DVB_TYPE_ATSC_T}, + {"ATSCC", DVB_TYPE_ATSC_C}, + {"ISDBT", DVB_TYPE_ISDB_T}, + {"ISDBC", DVB_TYPE_ISDB_C}, + {"ISDBS", DVB_TYPE_ISDB_S} }; dvb_str2val(type); @@ -1081,6 +1085,20 @@ dvb_mux_conf_str_atsc_t ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize ) dvb_qam2str(dmc->dmc_fe_modulation)); } +static int +dvb_mux_conf_str_cablecard(dvb_mux_conf_t *dmc, char *buf, size_t bufsize) +{ + if (!dmc->dmc_fe_vchan.minor) + return snprintf(buf, bufsize, "%s channel %u", + dvb_type2str(dmc->dmc_fe_type), + dmc->dmc_fe_vchan.num); + else + return snprintf(buf, bufsize, "%s channel %u.%u", + dvb_type2str(dmc->dmc_fe_type), + dmc->dmc_fe_vchan.num, + dmc->dmc_fe_vchan.minor); +} + static int dvb_mux_conf_str_isdb_t ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize ) { @@ -1124,6 +1142,8 @@ dvb_mux_conf_str ( dvb_mux_conf_t *dmc, char *buf, size_t bufsize ) return dvb_mux_conf_str_dvbs(dmc, buf, bufsize); case DVB_TYPE_ATSC_T: return dvb_mux_conf_str_atsc_t(dmc, buf, bufsize); + case DVB_TYPE_CABLECARD: + return dvb_mux_conf_str_cablecard(dmc, buf, bufsize); case DVB_TYPE_ISDB_T: return dvb_mux_conf_str_isdb_t(dmc, buf, bufsize); default: diff --git a/src/input/mpegts/mpegts_dvb.h b/src/input/mpegts/mpegts_dvb.h index 43e163453..87f5faf71 100644 --- a/src/input/mpegts/mpegts_dvb.h +++ b/src/input/mpegts/mpegts_dvb.h @@ -50,6 +50,7 @@ extern const idclass_t dvb_network_dvbc_class; extern const idclass_t dvb_network_dvbs_class; extern const idclass_t dvb_network_atsc_t_class; extern const idclass_t dvb_network_atsc_c_class; +extern const idclass_t dvb_network_cablecard_class; extern const idclass_t dvb_network_isdb_t_class; extern const idclass_t dvb_network_isdb_c_class; extern const idclass_t dvb_network_isdb_s_class; @@ -88,6 +89,7 @@ extern const idclass_t dvb_mux_dvbc_class; extern const idclass_t dvb_mux_dvbs_class; extern const idclass_t dvb_mux_atsc_t_class; extern const idclass_t dvb_mux_atsc_c_class; +extern const idclass_t dvb_mux_cablecard_class; extern const idclass_t dvb_mux_isdb_t_class; extern const idclass_t dvb_mux_isdb_c_class; extern const idclass_t dvb_mux_isdb_s_class; diff --git a/src/input/mpegts/mpegts_mux_dvb.c b/src/input/mpegts/mpegts_mux_dvb.c index 7228dcd1e..a09725a68 100644 --- a/src/input/mpegts/mpegts_mux_dvb.c +++ b/src/input/mpegts/mpegts_mux_dvb.c @@ -129,6 +129,39 @@ dvb_mux_class_delsys_set (void *o, const void *v) return 0; } +static const void * +dvb_mux_class_vchan_get(void *o) +{ + dvb_mux_t *lm = (dvb_mux_t *)o; + + if (!lm->lm_tuning.dmc_fe_vchan.minor) + snprintf(prop_sbuf, PROP_SBUF_LEN, "%u", + lm->lm_tuning.dmc_fe_vchan.num); + else + snprintf(prop_sbuf, PROP_SBUF_LEN, "%u.%u", + lm->lm_tuning.dmc_fe_vchan.num, + lm->lm_tuning.dmc_fe_vchan.minor); + return &prop_sbuf_ptr; +} + +static int +dvb_mux_class_vchan_set(void *o, const void *v) +{ + dvb_mux_t *lm = (dvb_mux_t *)o; + int r; + + r = sscanf(v, "%u%*[.-]%hu", + &lm->lm_tuning.dmc_fe_vchan.num, + &lm->lm_tuning.dmc_fe_vchan.minor); + switch (r) { + case 0: + return 1; + case 1: + lm->lm_tuning.dmc_fe_vchan.minor = 0; + } + return 0; +} + const idclass_t dvb_mux_class = { .ic_super = &mpegts_mux_class, @@ -614,6 +647,43 @@ const idclass_t dvb_mux_atsc_c_class = } }; +/* + * CableCARD + */ +const idclass_t dvb_mux_cablecard_class = +{ + .ic_super = &dvb_mux_class, + .ic_class = "dvb_mux_cablecard", + .ic_caption = N_("CableCARD multiplex"), + .ic_properties = (const property_t[]){ + { + .type = PT_STR, + .id = "vchan", + .name = N_("Channel"), + .desc = N_("The channel on the cable provider's network."), + .get = dvb_mux_class_vchan_get, + .set = dvb_mux_class_vchan_set, + }, + { + .type = PT_U32, + .id = "frequency", + .name = N_("Frequency (Hz)"), + .desc = N_("The frequency of the mux (in Hertz)."), + .off = offsetof(dvb_mux_t, lm_tuning.dmc_fe_freq), + .opts = PO_RDONLY | PO_NOSAVE, + }, + { + .type = PT_STR, + .id = "vchan_name", + .name = N_("Callsign"), + .desc = N_("The channel's name or callsign as set by the cable provider."), + .off = offsetof(dvb_mux_t, lm_tuning.dmc_fe_vchan.name), + .opts = PO_RDONLY | PO_NOSAVE, + }, + {} + } +}; + /* * ISDB-T */ @@ -1049,26 +1119,36 @@ dvb_mux_display_name ( mpegts_mux_t *mm, char *buf, size_t len ) dvb_network_t *ln = (dvb_network_t*)mm->mm_network; uint32_t freq = lm->lm_tuning.dmc_fe_freq, freq2; char extra[8], buf2[5], *p; - if (ln->ln_type == DVB_TYPE_S) { - const char *s = dvb_pol2str(lm->lm_tuning.u.dmc_fe_qpsk.polarisation); - if (s) extra[0] = *s; - extra[1] = '\0'; + + if (lm->lm_tuning.dmc_fe_type == DVB_TYPE_CABLECARD) { + if (!lm->lm_tuning.dmc_fe_vchan.minor) + snprintf(buf, len, "%u", lm->lm_tuning.dmc_fe_vchan.num); + else + snprintf(buf, len, "%u.%u", + lm->lm_tuning.dmc_fe_vchan.num, + lm->lm_tuning.dmc_fe_vchan.minor); } else { + if (ln->ln_type == DVB_TYPE_S) { + const char *s = dvb_pol2str(lm->lm_tuning.u.dmc_fe_qpsk.polarisation); + if (s) extra[0] = *s; + extra[1] = '\0'; + } else { + freq /= 1000; + strcpy(extra, "MHz"); + } + freq2 = freq % 1000; freq /= 1000; - strcpy(extra, "MHz"); - } - freq2 = freq % 1000; - freq /= 1000; - snprintf(buf2, sizeof(buf2), "%03d", freq2); - p = buf2 + 2; - while (freq2 && (freq2 % 10) == 0) { - freq2 /= 10; - *(p--) = '\0'; + snprintf(buf2, sizeof(buf2), "%03d", freq2); + p = buf2 + 2; + while (freq2 && (freq2 % 10) == 0) { + freq2 /= 10; + *(p--) = '\0'; + } + if (freq2) + snprintf(buf, len, "%d.%s%s", freq, buf2, extra); + else + snprintf(buf, len, "%d%s", freq, extra); } - if (freq2) - snprintf(buf, len, "%d.%s%s", freq, buf2, extra); - else - snprintf(buf, len, "%d%s", freq, extra); } static void @@ -1122,6 +1202,9 @@ dvb_mux_create0 } else if (ln->ln_type == DVB_TYPE_ATSC_C) { idc = &dvb_mux_atsc_c_class; delsys = DVB_SYS_DVBC_ANNEX_B; + } else if (ln->ln_type == DVB_TYPE_CABLECARD) { + idc = &dvb_mux_cablecard_class; + delsys = DVB_SYS_DVBC_ANNEX_B; } else if (ln->ln_type == DVB_TYPE_ISDB_T) { idc = &dvb_mux_isdb_t_class; delsys = DVB_SYS_ISDBT; diff --git a/src/input/mpegts/mpegts_network_dvb.c b/src/input/mpegts/mpegts_network_dvb.c index a4904f209..e673d86b6 100644 --- a/src/input/mpegts/mpegts_network_dvb.c +++ b/src/input/mpegts/mpegts_network_dvb.c @@ -360,6 +360,16 @@ const idclass_t dvb_network_atsc_c_class = } }; +const idclass_t dvb_network_cablecard_class = +{ + .ic_super = &dvb_network_class, + .ic_class = "dvb_network_cablecard", + .ic_caption = N_("CableCARD Network"), + .ic_properties = (const property_t[]){ + {} + } +}; + const idclass_t dvb_network_isdb_t_class = { .ic_super = &dvb_network_class, @@ -632,6 +642,8 @@ dvb_network_mux_class return &dvb_mux_atsc_c_class; if (idnode_is_instance(&mn->mn_id, &dvb_network_isdb_t_class)) return &dvb_mux_isdb_t_class; + if (idnode_is_instance(&mn->mn_id, &dvb_network_cablecard_class)) + return &dvb_mux_cablecard_class; if (idnode_is_instance(&mn->mn_id, &dvb_network_isdb_c_class)) return &dvb_mux_isdb_c_class; if (idnode_is_instance(&mn->mn_id, &dvb_network_isdb_s_class)) @@ -830,7 +842,25 @@ static mpegts_service_t * dvb_network_create_service ( mpegts_mux_t *mm, uint16_t sid, uint16_t pmt_pid ) { - return mpegts_service_create1(NULL, mm, sid, pmt_pid, NULL); + dvb_mux_t *lm = (dvb_mux_t *)mm; + mpegts_service_t *s; + + s = mpegts_service_create1(NULL, mm, sid, pmt_pid, NULL); + + /* Set service values from mux if CableCARD */ + if (lm->lm_tuning.dmc_fe_type == DVB_TYPE_CABLECARD) { + mpegts_network_t *ln = mm->mm_network; + if (!s->s_dvb_provider && ln->mn_provider_network_name) + s->s_dvb_provider = strdup(ln->mn_provider_network_name); + if (!s->s_dvb_channel_num) + s->s_dvb_channel_num = lm->lm_tuning.dmc_fe_vchan.num; + if (!s->s_dvb_channel_minor && lm->lm_tuning.dmc_fe_vchan.minor) + s->s_dvb_channel_minor = lm->lm_tuning.dmc_fe_vchan.minor; + if (!s->s_dvb_svcname && lm->lm_tuning.dmc_fe_vchan.name) + s->s_dvb_svcname = strdup(lm->lm_tuning.dmc_fe_vchan.name); + } + + return s; } static mpegts_mux_t * @@ -910,6 +940,7 @@ static const idclass_t * dvb_network_classes[] = { &dvb_network_dvbs_class, &dvb_network_atsc_t_class, &dvb_network_atsc_c_class, + &dvb_network_cablecard_class, &dvb_network_isdb_t_class, &dvb_network_isdb_c_class, &dvb_network_isdb_s_class, @@ -924,6 +955,7 @@ static const idclass_t * dvb_mux_classes[] = { &dvb_mux_dvbs_class, &dvb_mux_atsc_t_class, &dvb_mux_atsc_c_class, + &dvb_mux_cablecard_class, &dvb_mux_isdb_t_class, &dvb_mux_isdb_c_class, &dvb_mux_isdb_s_class, @@ -1003,6 +1035,8 @@ const idclass_t *dvb_network_class_by_fe_type(dvb_fe_type_t type) return &dvb_network_atsc_t_class; else if (type == DVB_TYPE_ATSC_C) return &dvb_network_atsc_c_class; + else if (type == DVB_TYPE_CABLECARD) + return &dvb_network_cablecard_class; else if (type == DVB_TYPE_ISDB_T) return &dvb_network_isdb_t_class; else if (type == DVB_TYPE_ISDB_C) @@ -1029,6 +1063,8 @@ dvb_fe_type_t dvb_fe_type_by_network_class(const idclass_t *idc) return DVB_TYPE_ATSC_T; else if (idc == &dvb_network_atsc_c_class) return DVB_TYPE_ATSC_C; + else if (idc == &dvb_network_cablecard_class) + return DVB_TYPE_CABLECARD; else if (idc == &dvb_network_isdb_t_class) return DVB_TYPE_ISDB_T; else if (idc == &dvb_network_isdb_c_class)