SAT>IP: Add possibility to define master/slave tuners
The signal from the standard universal LNB can be split using a simple coaxial splitter (no multiswitch) to several outputs. In this case, the position, the polarization and low-high band settings must be equal. This code adds the master/slave configuration option in the tuner settings and does the tuner arbitration to preserve above settings. Ideally, this arbitration and configuration may be moved to the generic dvbs input class in future, because all dvb-s adapters can be wired in this way, but it's more complicated.
This commit is contained in:
parent
b8f2fa8461
commit
cfe878319e
10 changed files with 188 additions and 18 deletions
|
@ -505,7 +505,7 @@ struct mpegts_input
|
|||
/*
|
||||
* Functions
|
||||
*/
|
||||
int (*mi_is_enabled) (mpegts_input_t*);
|
||||
int (*mi_is_enabled) (mpegts_input_t*, mpegts_mux_t *mm);
|
||||
void (*mi_enabled_updated)(mpegts_input_t*);
|
||||
void (*mi_display_name) (mpegts_input_t*, char *buf, size_t len);
|
||||
int (*mi_is_free) (mpegts_input_t*);
|
||||
|
|
|
@ -119,7 +119,7 @@ linuxdvb_adapter_is_enabled ( linuxdvb_adapter_t *la )
|
|||
{
|
||||
linuxdvb_frontend_t *lfe;
|
||||
LIST_FOREACH(lfe, &la->la_frontends, lfe_link) {
|
||||
if (lfe->mi_is_enabled((mpegts_input_t*)lfe))
|
||||
if (lfe->mi_is_enabled((mpegts_input_t*)lfe, NULL))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -252,7 +252,7 @@ linuxdvb_frontend_get_grace ( mpegts_input_t *mi, mpegts_mux_t *mm )
|
|||
}
|
||||
|
||||
static int
|
||||
linuxdvb_frontend_is_enabled ( mpegts_input_t *mi )
|
||||
linuxdvb_frontend_is_enabled ( mpegts_input_t *mi, mpegts_mux_t *mm )
|
||||
{
|
||||
linuxdvb_frontend_t *lfe = (linuxdvb_frontend_t*)mi;
|
||||
if (lfe->lfe_fe_path == NULL) return 0;
|
||||
|
|
|
@ -162,7 +162,7 @@ const idclass_t mpegts_input_class =
|
|||
* *************************************************************************/
|
||||
|
||||
static int
|
||||
mpegts_input_is_enabled ( mpegts_input_t *mi )
|
||||
mpegts_input_is_enabled ( mpegts_input_t *mi, mpegts_mux_t *mm )
|
||||
{
|
||||
return mi->mi_enabled;
|
||||
}
|
||||
|
|
|
@ -440,7 +440,7 @@ mpegts_mux_start
|
|||
|
||||
/* First pass - free only */
|
||||
if (!pass) {
|
||||
int e = mmi->mmi_input->mi_is_enabled(mmi->mmi_input);
|
||||
int e = mmi->mmi_input->mi_is_enabled(mmi->mmi_input, mm);
|
||||
int f = mmi->mmi_input->mi_is_free(mmi->mmi_input);
|
||||
tvhtrace("mpegts", "%s - enabled %d free %d", buf, e, f);
|
||||
if (e) enabled = 1;
|
||||
|
@ -457,7 +457,7 @@ mpegts_mux_start
|
|||
} else {
|
||||
|
||||
/* Enabled, valid and lower weight */
|
||||
if (mmi->mmi_input->mi_is_enabled(mmi->mmi_input) &&
|
||||
if (mmi->mmi_input->mi_is_enabled(mmi->mmi_input, mm) &&
|
||||
!mmi->mmi_tune_failed &&
|
||||
(weight > mmi->mmi_input->mi_get_weight(mmi->mmi_input))) {
|
||||
tune = mmi;
|
||||
|
|
|
@ -592,7 +592,7 @@ dvb_mux_create_instances ( mpegts_mux_t *mm )
|
|||
mpegts_network_link_t *mnl;
|
||||
LIST_FOREACH(mnl, &mm->mm_network->mn_inputs, mnl_mn_link) {
|
||||
mpegts_input_t *mi = mnl->mnl_input;
|
||||
if (mi->mi_is_enabled(mi))
|
||||
if (mi->mi_is_enabled(mi, mm))
|
||||
mi->mi_create_mux_instance(mi, mm);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -189,7 +189,7 @@ mpegts_service_enlist(service_t *t, struct service_instance_list *sil)
|
|||
if (mmi->mmi_tune_failed)
|
||||
continue;
|
||||
|
||||
if (!mmi->mmi_input->mi_is_enabled(mmi->mmi_input)) continue;
|
||||
if (!mmi->mmi_input->mi_is_enabled(mmi->mmi_input, mmi->mmi_mux)) continue;
|
||||
|
||||
/* Set weight to -1 (forced) for already active mux */
|
||||
if (mmi->mmi_mux->mm_active == mmi) {
|
||||
|
|
|
@ -28,6 +28,20 @@ static int
|
|||
satip_frontend_tune1
|
||||
( satip_frontend_t *lfe, mpegts_mux_instance_t *mmi );
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
static satip_frontend_t *
|
||||
satip_frontend_find_by_number( satip_device_t *sd, int num )
|
||||
{
|
||||
satip_frontend_t *lfe;
|
||||
|
||||
TAILQ_FOREACH(lfe, &sd->sd_frontends, sf_link)
|
||||
if (lfe->sf_number == num)
|
||||
return lfe;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
* Class definition
|
||||
* *************************************************************************/
|
||||
|
@ -147,6 +161,46 @@ satip_frontend_dvbs_class_positions_set ( void *self, const void *val )
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
satip_frontend_dvbs_class_master_set ( void *self, const void *val )
|
||||
{
|
||||
satip_frontend_t *lfe = self;
|
||||
satip_frontend_t *lfe2 = NULL;
|
||||
int num = *(int *)val, pos = 0;
|
||||
|
||||
if (num) {
|
||||
TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link)
|
||||
if (lfe2 != lfe && lfe2->sf_type == lfe->sf_type)
|
||||
if (++pos == num) {
|
||||
num = lfe2->sf_number;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lfe2 == NULL)
|
||||
num = 0;
|
||||
else if (lfe2->sf_master)
|
||||
num = lfe2->sf_master;
|
||||
if (lfe->sf_master != num) {
|
||||
lfe->sf_master = num;
|
||||
satip_device_destroy_later(lfe->sf_device, 100);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static htsmsg_t *
|
||||
satip_frontend_dvbs_class_master_enum( void * self )
|
||||
{
|
||||
satip_frontend_t *lfe = self, *lfe2;
|
||||
satip_device_t *sd = lfe->sf_device;
|
||||
htsmsg_t *m = htsmsg_create_list();
|
||||
htsmsg_add_str(m, NULL, "This Tuner");
|
||||
TAILQ_FOREACH(lfe2, &sd->sd_frontends, sf_link)
|
||||
if (lfe2 != lfe && lfe2->sf_type == lfe->sf_type)
|
||||
htsmsg_add_str(m, NULL, lfe2->mi_name);
|
||||
return m;
|
||||
}
|
||||
|
||||
const idclass_t satip_frontend_dvbs_class =
|
||||
{
|
||||
.ic_super = &satip_frontend_class,
|
||||
|
@ -163,6 +217,36 @@ const idclass_t satip_frontend_dvbs_class =
|
|||
.off = offsetof(satip_frontend_t, sf_positions),
|
||||
.def.i = 4
|
||||
},
|
||||
{
|
||||
.type = PT_INT,
|
||||
.id = "fe_master",
|
||||
.name = "Master Tuner",
|
||||
.set = satip_frontend_dvbs_class_master_set,
|
||||
.list = satip_frontend_dvbs_class_master_enum,
|
||||
.off = offsetof(satip_frontend_t, sf_master),
|
||||
},
|
||||
{
|
||||
.id = "networks",
|
||||
.type = PT_NONE,
|
||||
},
|
||||
{}
|
||||
}
|
||||
};
|
||||
|
||||
const idclass_t satip_frontend_dvbs_slave_class =
|
||||
{
|
||||
.ic_super = &satip_frontend_class,
|
||||
.ic_class = "satip_frontend_dvbs",
|
||||
.ic_caption = "SAT>IP DVB-S Slave Frontend",
|
||||
.ic_properties = (const property_t[]){
|
||||
{
|
||||
.type = PT_INT,
|
||||
.id = "fe_master",
|
||||
.name = "Master Tuner",
|
||||
.set = satip_frontend_dvbs_class_master_set,
|
||||
.list = satip_frontend_dvbs_class_master_enum,
|
||||
.off = offsetof(satip_frontend_t, sf_master),
|
||||
},
|
||||
{
|
||||
.id = "networks",
|
||||
.type = PT_NONE,
|
||||
|
@ -227,10 +311,56 @@ satip_frontend_get_grace ( mpegts_input_t *mi, mpegts_mux_t *mm )
|
|||
}
|
||||
|
||||
static int
|
||||
satip_frontend_is_enabled ( mpegts_input_t *mi )
|
||||
satip_frontend_match_satcfg ( satip_frontend_t *lfe2, mpegts_mux_t *mm2 )
|
||||
{
|
||||
mpegts_mux_t *mm1;
|
||||
dvb_mux_conf_t *mc1, *mc2;
|
||||
int position, high1, high2;
|
||||
|
||||
if (lfe2->sf_mmi == NULL)
|
||||
return 0;
|
||||
mm1 = lfe2->sf_mmi->mmi_mux;
|
||||
position = satip_satconf_get_position(lfe2, mm2);
|
||||
if (lfe2->sf_position != position)
|
||||
return 0;
|
||||
mc1 = &((dvb_mux_t *)mm1)->lm_tuning;
|
||||
mc2 = &((dvb_mux_t *)mm2)->lm_tuning;
|
||||
if (mc1->dmc_fe_type != DVB_TYPE_S || mc2->dmc_fe_type != DVB_TYPE_S)
|
||||
return 0;
|
||||
if (mc1->u.dmc_fe_qpsk.polarisation != mc2->u.dmc_fe_qpsk.polarisation)
|
||||
return 0;
|
||||
high1 = mc1->dmc_fe_freq > 11700000;
|
||||
high2 = mc2->dmc_fe_freq > 11700000;
|
||||
if (high1 != high2)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
satip_frontend_is_enabled ( mpegts_input_t *mi, mpegts_mux_t *mm )
|
||||
{
|
||||
satip_frontend_t *lfe = (satip_frontend_t*)mi;
|
||||
satip_frontend_t *lfe2;
|
||||
|
||||
lock_assert(&global_lock);
|
||||
|
||||
if (!lfe->mi_enabled) return 0;
|
||||
if (lfe->sf_type != DVB_TYPE_S) return 1;
|
||||
/* check if any "blocking" tuner is running */
|
||||
TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
|
||||
if (lfe2 == lfe) continue;
|
||||
if (lfe2->sf_type != DVB_TYPE_S) continue;
|
||||
if (lfe->sf_master == lfe2->sf_number) {
|
||||
if (!lfe2->sf_running)
|
||||
return 0; /* master must be running */
|
||||
return satip_frontend_match_satcfg(lfe2, mm);
|
||||
}
|
||||
if (lfe2->sf_master == lfe->sf_number && lfe2->sf_running) {
|
||||
if (lfe2->sf_mmi == NULL)
|
||||
return 0;
|
||||
return satip_frontend_match_satcfg(lfe2, mm);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -727,7 +857,7 @@ satip_frontend_input_thread ( void *aux )
|
|||
#define RTP_PKTS 64
|
||||
#define RTP_PKT_SIZE 1472 /* this is maximum UDP payload (standard ethernet) */
|
||||
#define HTTP_CMD_NONE 9874
|
||||
satip_frontend_t *lfe = aux;
|
||||
satip_frontend_t *lfe = aux, *lfe2;
|
||||
mpegts_mux_instance_t *mmi = lfe->sf_mmi;
|
||||
http_client_t *rtsp;
|
||||
dvb_mux_t *lm;
|
||||
|
@ -775,8 +905,14 @@ satip_frontend_input_thread ( void *aux )
|
|||
tvhpoll_add(efd, ev, 4);
|
||||
rtsp->hc_efd = efd;
|
||||
|
||||
pos = lfe->sf_position;
|
||||
if (lfe->sf_master) {
|
||||
lfe2 = satip_frontend_find_by_number(lfe->sf_device, lfe->sf_master);
|
||||
if (lfe2)
|
||||
pos = lfe2->sf_position;
|
||||
}
|
||||
r = satip_rtsp_setup(rtsp,
|
||||
lfe->sf_position, lfe->sf_number,
|
||||
pos, lfe->sf_number,
|
||||
lfe->sf_rtp_port, &lm->lm_tuning,
|
||||
lfe->sf_device->sd_pids0);
|
||||
if (r < 0) {
|
||||
|
@ -1064,8 +1200,9 @@ satip_frontend_create
|
|||
{
|
||||
const idclass_t *idc;
|
||||
const char *uuid = NULL, *override = NULL;
|
||||
char id[12], lname[256];
|
||||
char id[16], lname[256];
|
||||
satip_frontend_t *lfe;
|
||||
uint32_t master = 0;
|
||||
int i;
|
||||
|
||||
/* Override type */
|
||||
|
@ -1080,6 +1217,14 @@ satip_frontend_create
|
|||
override = NULL;
|
||||
}
|
||||
}
|
||||
/* Tuner slave */
|
||||
snprintf(id, sizeof(id), "master for #%d", num);
|
||||
if (conf && type == DVB_TYPE_S) {
|
||||
if (htsmsg_get_u32(conf, id, &master))
|
||||
master = 0;
|
||||
if (master == num)
|
||||
master = 0;
|
||||
}
|
||||
/* Internal config ID */
|
||||
snprintf(id, sizeof(id), "%s #%d", dvb_type2str(type), num);
|
||||
if (conf)
|
||||
|
@ -1089,7 +1234,8 @@ satip_frontend_create
|
|||
|
||||
/* Class */
|
||||
if (type == DVB_TYPE_S)
|
||||
idc = &satip_frontend_dvbs_class;
|
||||
idc = master ? &satip_frontend_dvbs_slave_class :
|
||||
&satip_frontend_dvbs_class;
|
||||
else if (type == DVB_TYPE_T)
|
||||
idc = &satip_frontend_dvbt_class;
|
||||
else if (type == DVB_TYPE_C)
|
||||
|
@ -1107,6 +1253,7 @@ satip_frontend_create
|
|||
lfe->sf_number = num;
|
||||
lfe->sf_type = type;
|
||||
lfe->sf_type_t2 = t2;
|
||||
lfe->sf_master = master;
|
||||
lfe->sf_type_override = override ? strdup(override) : NULL;
|
||||
TAILQ_INIT(&lfe->sf_satconf);
|
||||
pthread_mutex_init(&lfe->sf_dvr_lock, NULL);
|
||||
|
@ -1146,16 +1293,28 @@ satip_frontend_create
|
|||
TAILQ_INSERT_TAIL(&sd->sd_frontends, lfe, sf_link);
|
||||
|
||||
/* Create satconf */
|
||||
if (lfe->sf_type == DVB_TYPE_S)
|
||||
if (lfe->sf_type == DVB_TYPE_S && master == 0)
|
||||
satip_satconf_create(lfe, conf);
|
||||
|
||||
/* Slave networks update */
|
||||
if (master) {
|
||||
satip_frontend_t *lfe2 = satip_frontend_find_by_number(sd, master);
|
||||
if (lfe2) {
|
||||
htsmsg_t *l = (htsmsg_t *)mpegts_input_class_network_get(lfe2);
|
||||
if (l) {
|
||||
mpegts_input_class_network_set(lfe, l);
|
||||
htsmsg_destroy(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lfe;
|
||||
}
|
||||
|
||||
void
|
||||
satip_frontend_save ( satip_frontend_t *lfe, htsmsg_t *fe )
|
||||
{
|
||||
char id[12];
|
||||
char id[16];
|
||||
htsmsg_t *m = htsmsg_create_map();
|
||||
|
||||
/* Save frontend */
|
||||
|
@ -1166,6 +1325,7 @@ satip_frontend_save ( satip_frontend_t *lfe, htsmsg_t *fe )
|
|||
htsmsg_delete_field(m, "networks");
|
||||
}
|
||||
htsmsg_delete_field(m, "fe_override");
|
||||
htsmsg_delete_field(m, "fe_master");
|
||||
|
||||
/* Add to list */
|
||||
snprintf(id, sizeof(id), "%s #%d", dvb_type2str(lfe->sf_type), lfe->sf_number);
|
||||
|
@ -1174,6 +1334,10 @@ satip_frontend_save ( satip_frontend_t *lfe, htsmsg_t *fe )
|
|||
snprintf(id, sizeof(id), "override #%d", lfe->sf_number);
|
||||
htsmsg_add_str(fe, id, lfe->sf_type_override);
|
||||
}
|
||||
if (lfe->sf_master) {
|
||||
snprintf(id, sizeof(id), "master for #%d", lfe->sf_number);
|
||||
htsmsg_add_u32(fe, id, lfe->sf_master);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -98,6 +98,7 @@ struct satip_frontend
|
|||
dvb_fe_type_t sf_type;
|
||||
int sf_type_t2;
|
||||
char *sf_type_override;
|
||||
int sf_master;
|
||||
int sf_udp_rtp_port;
|
||||
int sf_fullmux;
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ satip_satconf_get_priority
|
|||
( satip_frontend_t *lfe, mpegts_mux_t *mm )
|
||||
{
|
||||
satip_satconf_t *sfc = satip_satconf_find_ele(lfe, mm);
|
||||
return sfc->sfc_priority;
|
||||
return sfc ? sfc->sfc_priority : 0;
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -49,7 +49,7 @@ satip_satconf_get_position
|
|||
( satip_frontend_t *lfe, mpegts_mux_t *mm )
|
||||
{
|
||||
satip_satconf_t *sfc = satip_satconf_find_ele(lfe, mm);
|
||||
return sfc->sfc_position;
|
||||
return sfc ? sfc->sfc_position : 0;
|
||||
}
|
||||
|
||||
/* **************************************************************************
|
||||
|
@ -94,7 +94,7 @@ satip_satconf_class_network_set( void *o, const void *p )
|
|||
sfc->sfc_networks = n;
|
||||
/* update the input (frontend) network list */
|
||||
htsmsg_t *l = htsmsg_create_list();
|
||||
satip_frontend_t *lfe = sfc->sfc_lfe;
|
||||
satip_frontend_t *lfe = sfc->sfc_lfe, *lfe2;
|
||||
satip_satconf_t *sfc2;
|
||||
TAILQ_FOREACH(sfc2, &lfe->sf_satconf, sfc_link) {
|
||||
for (i = 0; i < sfc2->sfc_networks->is_count; i++)
|
||||
|
@ -102,6 +102,11 @@ satip_satconf_class_network_set( void *o, const void *p )
|
|||
idnode_uuid_as_str(sfc2->sfc_networks->is_array[i]));
|
||||
}
|
||||
mpegts_input_class_network_set(lfe, l);
|
||||
/* update the slave tuners, too */
|
||||
TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link)
|
||||
if (lfe2->sf_number != lfe->sf_number &&
|
||||
lfe2->sf_master == lfe->sf_number)
|
||||
mpegts_input_class_network_set(lfe2, l);
|
||||
htsmsg_destroy(l);
|
||||
} else {
|
||||
idnode_set_free(n);
|
||||
|
|
Loading…
Add table
Reference in a new issue