}
static int
-satip_frontend_match_satcfg ( satip_frontend_t *lfe2, mpegts_mux_t *mm2 )
+satip_frontend_get_max_weight ( satip_frontend_t *lfe, mpegts_mux_t *mm, int flags )
+{
+ satip_frontend_t *lfe2;
+ int w = 0, w2;
+
+ TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
+ if (!lfe2->sf_running) continue;
+ if (lfe2->sf_type != DVB_TYPE_S) continue;
+ if (lfe2 != lfe) continue;
+ if (lfe->sf_master != lfe2->sf_number &&
+ lfe2->sf_master != lfe->sf_number) continue;
+ w2 = lfe2->mi_get_weight((mpegts_input_t *)lfe2, mm, flags);
+ if (w2 > w)
+ w = w2;
+ }
+ return w;
+}
+
+int
+satip_frontend_match_satcfg
+ ( satip_frontend_t *lfe2, mpegts_mux_t *mm2, int flags, int weight )
{
satip_frontend_t *lfe_master;
mpegts_mux_t *mm1 = NULL;
dvb_mux_conf_t *mc1, *mc2;
- int position, high1, high2;
+ int position, weight2, high1, high2;
- if (lfe2->sf_req == NULL || lfe2->sf_req->sf_mmi == NULL)
+ if (!lfe2->sf_running)
return 0;
lfe_master = lfe2;
if (lfe2->sf_master)
lfe_master = satip_frontend_find_by_number(lfe2->sf_device, lfe2->sf_master) ?: lfe2;
+ if (weight > 0) {
+ weight2 = satip_frontend_get_max_weight(lfe2, mm2, flags);
+ if (weight2 > 0 && weight2 < weight)
+ return 1;
+ }
+
mm1 = lfe2->sf_req->sf_mmi->mmi_mux;
- position = satip_satconf_get_position(lfe2, mm2, NULL, 0);
+ position = satip_satconf_get_position(lfe2, mm2, NULL, 0, 0, -1);
if (position <= 0 || lfe_master->sf_position != position)
return 0;
mc1 = &((dvb_mux_t *)mm1)->lm_tuning;
high2 = mc2->dmc_fe_freq > 11700000;
if (high1 != high2)
return 0;
- return 1;
+
+ /* return unique hash for the active satcfg greater than zero */
+ return 1 | (high1 ? 2 : 0) | ((int)mc1->u.dmc_fe_qpsk.polarisation << 8) | (position << 16);
}
static int
if (lfe->sf_type != DVB_TYPE_S) return 1;
/* try to reuse any input for limited networks if allowed */
if (lfe->sf_device->sd_all_tuners) {
- position = satip_satconf_get_position(lfe, mm, &netlimit, 0);
+ position = satip_satconf_get_position(lfe, mm, &netlimit, 0, 0, -1);
if (position <= 0) return 0;
if (netlimit <= 0) goto cont;
/* try to reuse any tuner input as slave */
TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
if (lfe2 == lfe) continue;
- if (satip_frontend_match_satcfg(lfe2, mm))
+ if (satip_frontend_match_satcfg(lfe2, mm, flags, weight))
return 1;
}
}
/* check if the position is enabled */
- position = satip_satconf_get_position(lfe, mm, NULL, 1);
+ position = satip_satconf_get_position(lfe, mm, NULL, 1, flags, weight);
if (position <= 0)
return 0;
/* check if any "blocking" tuner is running */
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_req == NULL || lfe2->sf_req->sf_mmi == NULL)
- return 0;
- return satip_frontend_match_satcfg(lfe2, mm);
+ return satip_frontend_match_satcfg(lfe2, mm, flags, weight);
}
+ if (lfe2->sf_master == lfe->sf_number && lfe2->sf_running)
+ return satip_frontend_match_satcfg(lfe2, mm, flags, weight);
}
return 1;
}
}
static int
-satip_frontend_start_mux
- ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi, int weight )
+satip_frontend_warm_mux
+ ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi )
{
satip_frontend_t *lfe = (satip_frontend_t*)mi;
- dvb_mux_t *lm = (dvb_mux_t *)mmi->mmi_mux;
- satip_tune_req_t *tr;
- char buf1[256], buf2[256];
+ int r;
+
+ r = mpegts_input_warm_mux(mi, mmi);
+ if (r)
+ return r;
if (lfe->sf_positions > 0) {
- lfe->sf_position = satip_satconf_get_position(lfe, mmi->mmi_mux, NULL, 0);
+ lfe->sf_position = satip_satconf_get_position(lfe, mmi->mmi_mux, NULL, 2, 0, -1);
if (lfe->sf_position <= 0)
return SM_CODE_TUNING_FAILED;
}
+ return 0;
+}
+
+static int
+satip_frontend_start_mux
+ ( mpegts_input_t *mi, mpegts_mux_instance_t *mmi, int weight )
+{
+ satip_frontend_t *lfe = (satip_frontend_t*)mi;
+ dvb_mux_t *lm = (dvb_mux_t *)mmi->mmi_mux;
+ satip_tune_req_t *tr;
+ char buf1[256], buf2[256];
+
lfe->mi_display_name((mpegts_input_t*)lfe, buf1, sizeof(buf1));
mpegts_mux_nice_name(mmi->mmi_mux, buf2, sizeof(buf2));
tvhdebug("satip", "%s - starting %s", buf1, buf2);
lfe->ti_wizard_get = satip_frontend_wizard_get;
lfe->ti_wizard_set = satip_frontend_wizard_set;
lfe->mi_is_enabled = satip_frontend_is_enabled;
+ lfe->mi_warm_mux = satip_frontend_warm_mux;
lfe->mi_start_mux = satip_frontend_start_mux;
lfe->mi_stop_mux = satip_frontend_stop_mux;
lfe->mi_network_list = satip_frontend_network_list;
}
static int
-satip_satconf_check_network_limit
- ( satip_frontend_t *lfe, satip_satconf_t *sfc, idnode_t *mn )
+satip_satconf_master_or_slave
+ ( satip_frontend_t *lfe1, satip_frontend_t *lfe2 )
+{
+ return lfe1->sf_number == lfe2->sf_master ||
+ lfe2->sf_number == lfe1->sf_master;
+}
+
+static int
+satip_satconf_in_network_group
+ ( satip_frontend_t *lfe, int network_group, idnode_t *mn )
{
- satip_frontend_t *lfe2;
satip_satconf_t *sfc2;
- int count;
- count = 0;
+ TAILQ_FOREACH(sfc2, &lfe->sf_satconf, sfc_link) {
+ if (network_group > 0 &&
+ sfc2->sfc_network_group > 0 &&
+ sfc2->sfc_network_group == network_group)
+ break;
+ else if (idnode_set_exists(sfc2->sfc_networks, mn))
+ break;
+ }
+ return sfc2 != NULL;
+}
+
+static int
+satip_satconf_check_limits
+ ( satip_frontend_t *lfe, satip_satconf_t *sfc, mpegts_mux_t *mm,
+ int flags, int weight, int manage )
+{
+ satip_frontend_t *lfe2, *lowest_lfe;
+ mpegts_mux_t *mm2;
+ mpegts_input_t *mi2;
+ idnode_t *mn = &mm->mm_network->mn_id;
+ int count, size, lowest, w2, r, i, limit, *hashes;
+
+ size = 0;
TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link)
- TAILQ_FOREACH(sfc2, &lfe2->sf_satconf, sfc_link) {
- if (!lfe2->sf_running) continue;
- if (sfc->sfc_network_group > 0 &&
- sfc2->sfc_network_group > 0 &&
- sfc2->sfc_network_group == sfc->sfc_network_group)
- count++;
- else if (idnode_set_exists(sfc2->sfc_networks, mn))
+ size++;
+ hashes = alloca(size * sizeof(int));
+
+ limit = sfc->sfc_network_limit > 0 ? sfc->sfc_network_limit : 1;
+
+retry:
+ memset(hashes, 0, size * sizeof(int));
+ count = 1;
+ lowest = INT_MAX;
+ lowest_lfe = NULL;
+ TAILQ_FOREACH(lfe2, &lfe->sf_device->sd_frontends, sf_link) {
+ if (lfe == lfe2 || !lfe2->sf_running || lfe2->sf_type != DVB_TYPE_S)
+ continue;
+ if (sfc->sfc_network_limit) {
+ if (!satip_satconf_in_network_group(lfe2, sfc->sfc_network_group, mn))
+ continue;
+ } else {
+ if (!satip_satconf_master_or_slave(lfe, lfe2))
+ continue;
+ }
+ mi2 = (mpegts_input_t *)lfe2;
+ mm2 = lfe2->sf_req->sf_mmi->mmi_mux;
+ if (weight > 0) {
+ w2 = lfe2->mi_get_weight(mi2, mm2, flags);
+ if (w2 < weight)
+ continue;
+ } else {
+ w2 = -1;
+ }
+ r = satip_frontend_match_satcfg(lfe2, mm, 0, -1);
+ if (r && manage) {
+ w2 = lfe2->mi_get_weight(mi2, mm2, flags);;
+ if (w2 < lowest) {
+ lowest = w2;
+ lowest_lfe = lfe2;
+ }
+ }
+ for (i = 0; i < size; i++) {
+ if (hashes[i] == r)
+ break;
+ if (!hashes[i]) {
+ hashes[i] = r;
count++;
+ break;
+ }
}
-
- return count <= sfc->sfc_network_limit;
+ }
+ if (count <= limit)
+ return 1;
+ if (manage) {
+ /* free tuner with lowest weight */
+ mm2 = lowest_lfe->sf_req->sf_mmi->mmi_mux;
+ mm2->mm_stop(mm2, 1, SM_CODE_SUBSCRIPTION_OVERRIDDEN);
+ goto retry;
+ }
+ return 0;
}
int
satip_satconf_get_position
- ( satip_frontend_t *lfe, mpegts_mux_t *mm, int *netlimit, int check )
+ ( satip_frontend_t *lfe, mpegts_mux_t *mm, int *netlimit, int check, int flags, int weight )
{
satip_satconf_t *sfc;
sfc = satip_satconf_find_ele(lfe, mm);
if (sfc && sfc->sfc_enabled) {
if (netlimit)
*netlimit = sfc->sfc_network_limit;
- if (!check || sfc->sfc_network_limit <= 0)
+ if (!check)
return sfc->sfc_position;
- if (satip_satconf_check_network_limit(lfe, sfc, &mm->mm_network->mn_id))
+ if (check > 1) {
+ satip_satconf_check_limits(lfe, sfc, mm, flags, weight, 1);
return sfc->sfc_position;
+ } else {
+ if (sfc->sfc_network_limit <= 0)
+ return sfc->sfc_position;
+ if (satip_satconf_check_limits(lfe, sfc, mm, flags, weight, 0))
+ return sfc->sfc_position;
+ }
} else {
if (netlimit)
*netlimit = 0;