static int print_frontend_stats(FILE *fd, struct dvb_v5_fe_parms *parms) { char buf[512], *p; int rc, i, len, show, n_status_lines = 0; rc = dvb_fe_get_stats(parms); if (rc) { ERROR(_("dvb_fe_get_stats failed")); return -1; } p = buf; len = sizeof(buf); dvb_fe_snprintf_stat(parms, DTV_STATUS, NULL, 0, &p, &len, &show); for (i = 0; i < MAX_DTV_STATS; i++) { show = 1; dvb_fe_snprintf_stat(parms, DTV_QUALITY, _("Quality"), i, &p, &len, &show); dvb_fe_snprintf_stat(parms, DTV_STAT_SIGNAL_STRENGTH, _("Signal"), i, &p, &len, &show); dvb_fe_snprintf_stat(parms, DTV_STAT_CNR, _("C/N"), i, &p, &len, &show); dvb_fe_snprintf_stat(parms, DTV_STAT_ERROR_BLOCK_COUNT, _("UCB"), i, &p, &len, &show); dvb_fe_snprintf_stat(parms, DTV_BER, _("postBER"), i, &p, &len, &show); dvb_fe_snprintf_stat(parms, DTV_PRE_BER, _("preBER"), i, &p, &len, &show); dvb_fe_snprintf_stat(parms, DTV_PER, _("PER"), i, &p, &len, &show); if (p != buf) { if (isatty(fileno(fd))) { enum dvb_quality qual; int color; qual = dvb_fe_retrieve_quality(parms, 0); switch (qual) { case DVB_QUAL_POOR: color = 31; break; case DVB_QUAL_OK: color = 36; break; case DVB_QUAL_GOOD: color = 32; break; case DVB_QUAL_UNKNOWN: default: color = 0; break; } fprintf(fd, "\033[%dm", color); /* * It would be great to change the BELL * tone depending on the quality. The legacy * femon used to to that, but this doesn't * work anymore with modern Linux distros. * * So, just print a bell if quality is good. * * The console audio should be enabled * at the window manater for this to * work. */ if (acoustical) { if (qual == DVB_QUAL_GOOD) fprintf(fd, "\a"); } } if (n_status_lines) fprintf(fd, "\t%s\n", buf); else fprintf(fd, "%s\n", buf); n_status_lines++; p = buf; len = sizeof(buf); } } fflush(fd); return 0; }
int dvb_fe_snprintf_stat(struct dvb_v5_fe_parms *p, uint32_t cmd, char *display_name, int layer, char **buf, int *len, int *show_layer_name) { struct dvb_v5_fe_parms_priv *parms = (void *)p; struct dtv_stats *stat = NULL; enum dvb_quality qual = DVB_QUAL_UNKNOWN; enum fecap_scale_params scale; float val = -1; int initial_len = *len; int size, i; /* Print status, if layer == 0, as there is only global status */ if (cmd == DTV_STATUS) { fe_status_t status; if (layer) return 0; if (dvb_fe_retrieve_stats(&parms->p, DTV_STATUS, &status)) { dvb_logerr (_("Error: no adapter status")); return -1; } if (display_name) { size = snprintf(*buf, *len, " %s=", display_name); *buf += size; *len -= size; } /* Get the name of the highest status bit */ for (i = ARRAY_SIZE(sig_bits) - 1; i >= 0 ; i--) { if ((1 << i) & status) { size = snprintf(*buf, *len, _("%-7s"), _(sig_bits[i])); *buf += size; *len -= size; break; } } if (i < 0) { size = snprintf(*buf, *len, _("%7s"), ""); *buf += size; *len -= size; } /* Add the status bits */ size = snprintf(*buf, *len, "(0x%02x)", status); *buf += size; *len -= size; return initial_len - *len; } /* Retrieve the statistics */ switch (cmd) { case DTV_PRE_BER: val = calculate_preBER(parms, layer); if (val < 0) return 0; scale = FE_SCALE_COUNTER; break; case DTV_BER: val = dvb_fe_retrieve_ber(&parms->p, layer, &scale); if (scale == FE_SCALE_NOT_AVAILABLE) return 0; break; case DTV_PER: val = dvb_fe_retrieve_per(&parms->p, layer); if (val < 0) return 0; scale = FE_SCALE_COUNTER; break; case DTV_QUALITY: qual = dvb_fe_retrieve_quality(&parms->p, layer); if (qual == DVB_QUAL_UNKNOWN) return 0; break; default: stat = dvb_fe_retrieve_stats_layer(&parms->p, cmd, layer); if (!stat || stat->scale == FE_SCALE_NOT_AVAILABLE) return 0; } /* If requested, prints the layer name */ if (*show_layer_name && layer) { size = snprintf(*buf, *len, _(" Layer %c:"), 'A' + layer - 1); *buf += size; *len -= size; *show_layer_name = 0; } if (display_name) { size = snprintf(*buf, *len, " %s=", display_name); *buf += size; *len -= size; } /* Quality measure */ if (qual != DVB_QUAL_UNKNOWN) { size = snprintf(*buf, *len, " %-4s", _(qual_name[qual])); *buf += size; *len -= size; return initial_len - *len; } /* Special case: float point measures like BER/PER */ if (!stat) { switch (scale) { case FE_SCALE_RELATIVE: size = snprintf(*buf, *len, " %u", (unsigned int)val); break; case FE_SCALE_COUNTER: size = dvb_fe_snprintf_eng(*buf, *len, val); break; default: size = 0; } *buf += size; *len -= size; return initial_len - *len; } /* Prints the scale */ switch (stat->scale) { case FE_SCALE_DECIBEL: if (cmd == DTV_STAT_SIGNAL_STRENGTH) size = snprintf(*buf, *len, " %.2fdBm", stat->svalue / 1000.); else size = snprintf(*buf, *len, " %.2fdB", stat->svalue / 1000.); break; case FE_SCALE_RELATIVE: size = snprintf(*buf, *len, " %3.2f%%", (100 * stat->uvalue) / 65535.); break; case FE_SCALE_COUNTER: size = snprintf(*buf, *len, " %" PRIu64, (uint64_t)stat->uvalue); break; default: size = 0; } *buf += size; *len -= size; return initial_len - *len; }