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 */
} 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;
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;
{ "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 },
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:
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);
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 )
{
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:
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;
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;
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,
}
};
+/*
+ * 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
*/
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
} 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;
}
};
+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,
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))
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 *
&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,
&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,
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)
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)