Cleanup, fixes and improvements of linuxdvb frontend statistics code,
including webui improvements and fixes.
This commit is contained in:
parent
bcb8373f8b
commit
1858323412
8 changed files with 389 additions and 113 deletions
|
@ -2798,9 +2798,9 @@ htsp_subscription_signal_status(htsp_subscription_t *hs, signal_status_t *sig)
|
|||
htsmsg_add_str(m, "method", "signalStatus");
|
||||
htsmsg_add_u32(m, "subscriptionId", hs->hs_sid);
|
||||
htsmsg_add_str(m, "feStatus", sig->status_text);
|
||||
if(sig->snr != -2)
|
||||
if((sig->snr != -2) && (sig->snr_scale == SIGNAL_STATUS_SCALE_RELATIVE))
|
||||
htsmsg_add_u32(m, "feSNR", sig->snr);
|
||||
if(sig->signal != -2)
|
||||
if((sig->signal != -2) && (sig->signal_scale == SIGNAL_STATUS_SCALE_RELATIVE))
|
||||
htsmsg_add_u32(m, "feSignal", sig->signal);
|
||||
if(sig->ber != -2)
|
||||
htsmsg_add_u32(m, "feBER", sig->ber);
|
||||
|
|
|
@ -80,12 +80,18 @@ tvh_input_stream_create_msg
|
|||
htsmsg_add_u32(m, "subs", st->subs_count);
|
||||
htsmsg_add_u32(m, "weight", st->max_weight);
|
||||
htsmsg_add_u32(m, "signal", st->stats.signal);
|
||||
htsmsg_add_u32(m, "signal_scale", st->stats.signal_scale);
|
||||
htsmsg_add_u32(m, "ber", st->stats.ber);
|
||||
htsmsg_add_u32(m, "snr", st->stats.snr);
|
||||
htsmsg_add_u32(m, "snr_scale", st->stats.snr_scale);
|
||||
htsmsg_add_u32(m, "unc", st->stats.unc);
|
||||
htsmsg_add_u32(m, "bps", st->stats.bps);
|
||||
htsmsg_add_u32(m, "te", st->stats.te);
|
||||
htsmsg_add_u32(m, "cc", st->stats.cc);
|
||||
htsmsg_add_u32(m, "ec_bit", st->stats.ec_bit);
|
||||
htsmsg_add_u32(m, "tc_bit", st->stats.tc_bit);
|
||||
htsmsg_add_u32(m, "ec_block", st->stats.ec_block);
|
||||
htsmsg_add_u32(m, "tc_block", st->stats.tc_block);
|
||||
return m;
|
||||
}
|
||||
|
||||
|
|
38
src/input.h
38
src/input.h
|
@ -34,18 +34,42 @@ typedef LIST_HEAD(,tvh_hardware) tvh_hardware_list_t;
|
|||
typedef LIST_HEAD(,tvh_input) tvh_input_list_t;
|
||||
typedef LIST_HEAD(,tvh_input_stream) tvh_input_stream_list_t;
|
||||
|
||||
/*
|
||||
* Scales for input stream statistics values
|
||||
*/
|
||||
typedef enum {
|
||||
INPUT_STREAM_STATS_SCALE_UNKNOWN = 0,
|
||||
INPUT_STREAM_STATS_SCALE_RELATIVE, // value is unsigned, where 0 means 0% and 65535 means 100%
|
||||
INPUT_STREAM_STATS_SCALE_DECIBEL // value is measured in dB
|
||||
} tvh_input_stream_stats_scale_t;
|
||||
|
||||
/*
|
||||
* Input stream structure - used for getting statistics about active streams
|
||||
*/
|
||||
struct tvh_input_stream_stats
|
||||
{
|
||||
int signal; ///< Signal level (0-100)
|
||||
int ber; ///< Bit error rate (0-100?)
|
||||
int unc; ///< Uncorrectable errors
|
||||
int snr; ///< Signal 2 Noise (dB)
|
||||
int bps; ///< Bandwidth (bps)
|
||||
int cc; ///< Continuity errors
|
||||
int te; ///< Transport errors
|
||||
int signal; ///< signal strength, value depending on signal_scale value:
|
||||
///< - SCALE_RELATIVE : 0...65535 (which means 0%...100%)
|
||||
///< - SCALE DECIBEL : 0.0001 dBm units. This value is generally negative.
|
||||
int snr; ///< signal to noise ratio, value depending on snr_scale value:
|
||||
///< - SCALE_RELATIVE : 0...65535 (which means 0%...100%)
|
||||
///< - SCALE DECIBEL : 0.0001 dB units.
|
||||
int ber; ///< bit error rate (driver/vendor specific value!)
|
||||
int unc; ///< number of uncorrected blocks
|
||||
int bps; ///< bandwidth (bps)
|
||||
int cc; ///< number of continuity errors
|
||||
int te; ///< number of transport errors
|
||||
|
||||
tvh_input_stream_stats_scale_t signal_scale;
|
||||
tvh_input_stream_stats_scale_t snr_scale;
|
||||
|
||||
/* Note: if tc_bit > 0, BER = ec_bit / tc_bit (0...1) else BER = ber (driver specific value) */
|
||||
int ec_bit; ///< ERROR_BIT_COUNT (same as unc?)
|
||||
int tc_bit; ///< TOTAL_BIT_COUNT
|
||||
|
||||
/* Note: PER = ec_block / tc_block (0...1) */
|
||||
int ec_block; ///< ERROR_BLOCK_COUNT
|
||||
int tc_block; ///< TOTAL_BLOCK_COUNT
|
||||
};
|
||||
|
||||
struct tvh_input_stream {
|
||||
|
|
|
@ -432,6 +432,7 @@ linuxdvb_frontend_monitor ( void *aux )
|
|||
#if DVB_VER_ATLEAST(5,10)
|
||||
struct dtv_property fe_properties[6];
|
||||
struct dtv_properties dtv_prop;
|
||||
int gotprop;
|
||||
#endif
|
||||
|
||||
lfe->mi_display_name((mpegts_input_t*)lfe, buf, sizeof(buf));
|
||||
|
@ -536,82 +537,194 @@ linuxdvb_frontend_monitor ( void *aux )
|
|||
/* Statistics - New API */
|
||||
#if DVB_VER_ATLEAST(5,10)
|
||||
memset(&fe_properties, 0, sizeof(fe_properties));
|
||||
|
||||
/* Signal strength */
|
||||
fe_properties[0].cmd = DTV_STAT_SIGNAL_STRENGTH;
|
||||
|
||||
/* BER */
|
||||
fe_properties[1].cmd = DTV_STAT_PRE_ERROR_BIT_COUNT;
|
||||
fe_properties[2].cmd = DTV_STAT_PRE_TOTAL_BIT_COUNT;
|
||||
|
||||
/* SNR */
|
||||
fe_properties[3].cmd = DTV_STAT_CNR;
|
||||
|
||||
/* PER */
|
||||
/* PER / UNC */
|
||||
fe_properties[4].cmd = DTV_STAT_ERROR_BLOCK_COUNT;
|
||||
fe_properties[5].cmd = DTV_STAT_TOTAL_BLOCK_COUNT;
|
||||
dtv_prop.num = 6;
|
||||
dtv_prop.props = fe_properties;
|
||||
|
||||
if(!ioctl(lfe->lfe_fe_fd, FE_GET_PROPERTY, &dtv_prop)) {
|
||||
/* Signal strength */
|
||||
gotprop = 0;
|
||||
if(fe_properties[0].u.st.len > 0) {
|
||||
if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_RELATIVE)
|
||||
mmi->mmi_stats.signal = (fe_properties[0].u.st.stat[0].uvalue * 100) / 0xffff;
|
||||
/* TODO: handle other scales */
|
||||
if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_RELATIVE) {
|
||||
mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
mmi->mmi_stats.signal = fe_properties[0].u.st.stat[0].uvalue;
|
||||
gotprop = 1;
|
||||
}
|
||||
else if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_DECIBEL) {
|
||||
mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_DECIBEL;
|
||||
mmi->mmi_stats.signal = fe_properties[0].u.st.stat[0].svalue;
|
||||
gotprop = 1;
|
||||
}
|
||||
else {
|
||||
mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN;
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled signal scale: %d",
|
||||
fe_properties[0].u.st.stat[0].scale);
|
||||
}
|
||||
}
|
||||
if(!gotprop) {
|
||||
/* try old API */
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) {
|
||||
mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
mmi->mmi_stats.signal = u16;
|
||||
}
|
||||
else {
|
||||
mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN;
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide signal strength value.");
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate BER from PRE_ERROR and TOTAL_BIT_COUNT */
|
||||
/* ERROR_BIT_COUNT */
|
||||
gotprop = 0;
|
||||
if(fe_properties[1].u.st.len > 0) {
|
||||
if(fe_properties[1].u.st.stat[0].scale == FE_SCALE_COUNTER)
|
||||
u16 = fe_properties[1].u.st.stat[0].uvalue;
|
||||
}
|
||||
if(fe_properties[2].u.st.len > 0) {
|
||||
if(fe_properties[2].u.st.stat[0].scale == FE_SCALE_COUNTER) {
|
||||
if(fe_properties[2].u.st.stat[0].uvalue > 0 )
|
||||
mmi->mmi_stats.ber = u16 / fe_properties[2].u.st.stat[0].uvalue;
|
||||
else
|
||||
mmi->mmi_stats.ber = 0;
|
||||
if(fe_properties[1].u.st.stat[0].scale == FE_SCALE_COUNTER) {
|
||||
mmi->mmi_stats.ec_bit = fe_properties[1].u.st.stat[0].uvalue;
|
||||
gotprop = 1;
|
||||
}
|
||||
else
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled ERROR_BIT_COUNT scale: %d",
|
||||
fe_properties[1].u.st.stat[0].scale);
|
||||
}
|
||||
/* TOTAL_BIT_COUNT */
|
||||
if(gotprop && (fe_properties[2].u.st.len > 0)) {
|
||||
gotprop = 0;
|
||||
if(fe_properties[2].u.st.stat[0].scale == FE_SCALE_COUNTER) {
|
||||
mmi->mmi_stats.tc_bit = fe_properties[2].u.st.stat[0].uvalue;
|
||||
gotprop = 1;
|
||||
}
|
||||
else {
|
||||
mmi->mmi_stats.ec_bit = 0; /* both values or none */
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled TOTAL_BIT_COUNT scale: %d",
|
||||
fe_properties[2].u.st.stat[0].scale);
|
||||
}
|
||||
}
|
||||
if(!gotprop) {
|
||||
/* try old API */
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32))
|
||||
mmi->mmi_stats.ber = u32;
|
||||
else
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide BER value.");
|
||||
}
|
||||
|
||||
/* SNR */
|
||||
gotprop = 0;
|
||||
if(fe_properties[3].u.st.len > 0) {
|
||||
/* note that decibel scale means 1 = 0.0001 dB units here */
|
||||
if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_DECIBEL)
|
||||
mmi->mmi_stats.snr = fe_properties[3].u.st.stat[0].svalue * 0.0001;
|
||||
/* TODO: handle other scales */
|
||||
}
|
||||
|
||||
/* Calculate PER from PRE_ERROR and TOTAL_BIT_COUNT */
|
||||
if(fe_properties[4].u.st.len > 0) {
|
||||
if(fe_properties[4].u.st.stat[0].scale == FE_SCALE_COUNTER)
|
||||
u16 = fe_properties[4].u.st.stat[0].uvalue;
|
||||
}
|
||||
if(fe_properties[5].u.st.len > 0) {
|
||||
if(fe_properties[5].u.st.stat[0].scale == FE_SCALE_COUNTER) {
|
||||
if(fe_properties[5].u.st.stat[0].uvalue > 0 )
|
||||
mmi->mmi_stats.unc = u16 / fe_properties[5].u.st.stat[0].uvalue;
|
||||
else
|
||||
mmi->mmi_stats.unc = 0;
|
||||
if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_RELATIVE) {
|
||||
mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
mmi->mmi_stats.snr = fe_properties[3].u.st.stat[0].uvalue;
|
||||
gotprop = 1;
|
||||
}
|
||||
else if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_DECIBEL) {
|
||||
mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_DECIBEL;
|
||||
mmi->mmi_stats.snr = fe_properties[3].u.st.stat[0].svalue;
|
||||
gotprop = 1;
|
||||
}
|
||||
else {
|
||||
mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN;
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled SNR scale: %d",
|
||||
fe_properties[3].u.st.stat[0].scale);
|
||||
}
|
||||
}
|
||||
|
||||
if(!gotprop) {
|
||||
/* try old API */
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) {
|
||||
mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
mmi->mmi_stats.snr = u16;
|
||||
}
|
||||
else {
|
||||
mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN;
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide SNR value.");
|
||||
}
|
||||
}
|
||||
|
||||
/* ERROR_BLOCK_COUNT == Uncorrected blocks (UNC) */
|
||||
gotprop = 0;
|
||||
if(fe_properties[4].u.st.len > 0) {
|
||||
if(fe_properties[4].u.st.stat[0].scale == FE_SCALE_COUNTER) {
|
||||
mmi->mmi_stats.unc = mmi->mmi_stats.ec_block = fe_properties[4].u.st.stat[0].uvalue;
|
||||
gotprop = 1;
|
||||
}
|
||||
else
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled ERROR_BLOCK_COUNT scale: %d",
|
||||
fe_properties[4].u.st.stat[0].scale);
|
||||
}
|
||||
|
||||
/* TOTAL_BLOCK_COUNT */
|
||||
if(gotprop && (fe_properties[5].u.st.len > 0)) {
|
||||
gotprop = 0;
|
||||
if(fe_properties[5].u.st.stat[0].scale == FE_SCALE_COUNTER) {
|
||||
mmi->mmi_stats.tc_block = fe_properties[5].u.st.stat[0].uvalue;
|
||||
gotprop = 1;
|
||||
}
|
||||
else {
|
||||
mmi->mmi_stats.ec_block = mmi->mmi_stats.unc = 0; /* both values or none */
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unhandled TOTAL_BLOCK_COUNT scale: %d",
|
||||
fe_properties[5].u.st.stat[0].scale);
|
||||
}
|
||||
}
|
||||
if(!gotprop) {
|
||||
/* try old API */
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32)) {
|
||||
mmi->mmi_stats.unc = u32;
|
||||
gotprop = 1;
|
||||
}
|
||||
else
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide UNC value.");
|
||||
}
|
||||
/* Older API */
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16))
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) {
|
||||
mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
mmi->mmi_stats.signal = u16;
|
||||
}
|
||||
else {
|
||||
mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN;
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide signal strength value.");
|
||||
}
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32))
|
||||
mmi->mmi_stats.ber = u32;
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16))
|
||||
else
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide BER value.");
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) {
|
||||
mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
mmi->mmi_stats.snr = u16;
|
||||
}
|
||||
else {
|
||||
mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN;
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide SNR value.");
|
||||
}
|
||||
if (!ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32))
|
||||
mmi->mmi_stats.unc = u32;
|
||||
else
|
||||
tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide UNC value.");
|
||||
}
|
||||
|
||||
/* Send message */
|
||||
sigstat.status_text = signal2str(status);
|
||||
sigstat.snr = mmi->mmi_stats.snr;
|
||||
sigstat.signal = mmi->mmi_stats.signal;
|
||||
sigstat.ber = mmi->mmi_stats.ber;
|
||||
sigstat.unc = mmi->mmi_stats.unc;
|
||||
sigstat.status_text = signal2str(status);
|
||||
sigstat.snr = mmi->mmi_stats.snr;
|
||||
sigstat.signal = mmi->mmi_stats.signal;
|
||||
sigstat.ber = mmi->mmi_stats.ber;
|
||||
sigstat.unc = mmi->mmi_stats.unc;
|
||||
sigstat.signal_scale = mmi->mmi_stats.signal_scale;
|
||||
sigstat.snr_scale = mmi->mmi_stats.snr_scale;
|
||||
sigstat.ec_bit = mmi->mmi_stats.ec_bit;
|
||||
sigstat.tc_bit = mmi->mmi_stats.tc_bit;
|
||||
sigstat.ec_block = mmi->mmi_stats.ec_block;
|
||||
sigstat.tc_block = mmi->mmi_stats.tc_block;
|
||||
sm.sm_type = SMT_SIGNAL_STATUS;
|
||||
sm.sm_data = &sigstat;
|
||||
LIST_FOREACH(s, &lfe->mi_transports, s_active_link) {
|
||||
|
|
|
@ -712,15 +712,19 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
|
|||
if (atoi(argv[0]) != lfe->sf_number)
|
||||
return;
|
||||
mmi->mmi_stats.signal =
|
||||
(atoi(argv[1]) * 100) / lfe->sf_device->sd_sig_scale;
|
||||
((atoi(argv[1]) * 100) / lfe->sf_device->sd_sig_scale) * 65535 / 100;
|
||||
mmi->mmi_stats.signal_scale =
|
||||
INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
if (atoi(argv[2]) > 0)
|
||||
status = SIGNAL_GOOD;
|
||||
mmi->mmi_stats.snr = atoi(argv[3]);
|
||||
mmi->mmi_stats.snr = atoi(argv[3]) * 65535 / 100;
|
||||
mmi->mmi_stats.snr_scale =
|
||||
INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
if (status == SIGNAL_GOOD &&
|
||||
mmi->mmi_stats.signal == 0 && mmi->mmi_stats.snr == 0) {
|
||||
/* some values that we're tuned */
|
||||
mmi->mmi_stats.signal = 50;
|
||||
mmi->mmi_stats.snr = 12;
|
||||
mmi->mmi_stats.signal = 50 * 65535 / 100;
|
||||
mmi->mmi_stats.snr = 12 * 65535 / 100;
|
||||
}
|
||||
goto ok;
|
||||
} else if (strncmp(s, "ver=1.0;", 8) == 0) {
|
||||
|
@ -733,10 +737,14 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
|
|||
if (atoi(argv[0]) != lfe->sf_number)
|
||||
return;
|
||||
mmi->mmi_stats.signal =
|
||||
(atoi(argv[1]) * 100) / lfe->sf_device->sd_sig_scale;
|
||||
((atoi(argv[1]) * 100) / lfe->sf_device->sd_sig_scale) * 65535 / 100;
|
||||
mmi->mmi_stats.signal_scale =
|
||||
INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
if (atoi(argv[2]) > 0)
|
||||
status = SIGNAL_GOOD;
|
||||
mmi->mmi_stats.snr = atoi(argv[3]);
|
||||
mmi->mmi_stats.snr = atoi(argv[3]) * 65535 / 100;
|
||||
mmi->mmi_stats.snr_scale =
|
||||
INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
goto ok;
|
||||
} else if (strncmp(s, "ver=1.1;tuner=", 14) == 0) {
|
||||
n = http_tokenize(s + 14, argv, 4, ',');
|
||||
|
@ -745,10 +753,14 @@ satip_frontend_decode_rtcp( satip_frontend_t *lfe, const char *name,
|
|||
if (atoi(argv[0]) != lfe->sf_number)
|
||||
return;
|
||||
mmi->mmi_stats.signal =
|
||||
(atoi(argv[1]) * 100) / lfe->sf_device->sd_sig_scale;
|
||||
((atoi(argv[1]) * 100) / lfe->sf_device->sd_sig_scale) * 65535 / 100;
|
||||
mmi->mmi_stats.signal_scale =
|
||||
INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
if (atoi(argv[2]) > 0)
|
||||
status = SIGNAL_GOOD;
|
||||
mmi->mmi_stats.snr = atoi(argv[3]);
|
||||
mmi->mmi_stats.snr = atoi(argv[3]) * 65535 / 100;
|
||||
mmi->mmi_stats.snr_scale =
|
||||
INPUT_STREAM_STATS_SCALE_RELATIVE;
|
||||
goto ok;
|
||||
}
|
||||
}
|
||||
|
@ -1260,6 +1272,12 @@ satip_frontend_signal_cb( void *aux )
|
|||
sigstat.signal = mmi->mmi_stats.signal;
|
||||
sigstat.ber = mmi->mmi_stats.ber;
|
||||
sigstat.unc = mmi->mmi_stats.unc;
|
||||
sigstat.signal_scale = mmi->mmi_stats.signal_scale;
|
||||
sigstat.snr_scale = mmi->mmi_stats.snr_scale;
|
||||
sigstat.ec_bit = mmi->mmi_stats.ec_bit;
|
||||
sigstat.tc_bit = mmi->mmi_stats.tc_bit;
|
||||
sigstat.ec_block = mmi->mmi_stats.ec_block;
|
||||
sigstat.tc_block = mmi->mmi_stats.tc_block;
|
||||
sm.sm_type = SMT_SIGNAL_STATUS;
|
||||
sm.sm_data = &sigstat;
|
||||
LIST_FOREACH(svc, &lfe->mi_transports, s_active_link) {
|
||||
|
|
|
@ -237,15 +237,30 @@ typedef enum {
|
|||
|
||||
#define SCT_ISSUBTITLE(t) ((t) == SCT_TEXTSUB || (t) == SCT_DVBSUB)
|
||||
|
||||
/*
|
||||
* Scales for signal status values
|
||||
*/
|
||||
typedef enum {
|
||||
SIGNAL_STATUS_SCALE_UNKNOWN = 0,
|
||||
SIGNAL_STATUS_SCALE_RELATIVE, // value is unsigned, where 0 means 0% and 65535 means 100%
|
||||
SIGNAL_STATUS_SCALE_DECIBEL // value is measured in dB
|
||||
} signal_status_scale_t;
|
||||
|
||||
/**
|
||||
* The signal status of a tuner
|
||||
*/
|
||||
typedef struct signal_status {
|
||||
const char *status_text; /* adapter status text */
|
||||
int snr; /* signal/noise ratio */
|
||||
signal_status_scale_t snr_scale;
|
||||
int signal; /* signal strength */
|
||||
signal_status_scale_t signal_scale;
|
||||
int ber; /* bit error rate */
|
||||
int unc; /* uncorrected blocks */
|
||||
int ec_bit; /* error bit count */
|
||||
int tc_bit; /* total bit count */
|
||||
int ec_block; /* error block count */
|
||||
int tc_block; /* total block count */
|
||||
} signal_status_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -345,6 +345,9 @@ Ext.reg("multiselect", Ext.ux.Multiselect);
|
|||
* License details: http://www.gnu.org/licenses/lgpl.html
|
||||
*/
|
||||
|
||||
/**
|
||||
* 22/07/2014: ceiling support backported from version 1.2, by Kai Sommerfeld
|
||||
*/
|
||||
Ext.namespace('Ext.ux.grid');
|
||||
|
||||
Ext.ux.grid.ProgressColumn = function(config) {
|
||||
|
@ -355,6 +358,10 @@ Ext.ux.grid.ProgressColumn = function(config) {
|
|||
};
|
||||
|
||||
Ext.extend(Ext.ux.grid.ProgressColumn, Ext.util.Observable, {
|
||||
/**
|
||||
* @cfg {Integer} upper limit for full progress indicator (defaults to 100)
|
||||
*/
|
||||
ceiling : 100,
|
||||
/**
|
||||
* @cfg {String} colored determines whether use special progression coloring
|
||||
* or the standard Ext.ProgressBar coloring for the bar (defaults to
|
||||
|
@ -397,27 +404,30 @@ Ext.extend(Ext.ux.grid.ProgressColumn, Ext.util.Observable, {
|
|||
},
|
||||
renderer: function(v, p, record) {
|
||||
var style = '';
|
||||
var textClass = (v < 55) ? 'x-progress-text-back' : 'x-progress-text-front' + (Ext.isIE6 ? '-ie6' : '');
|
||||
var textClass = (v < (this.ceiling / 1.818)) ? 'x-progress-text-back' : 'x-progress-text-front' + (Ext.isIE6 ? '-ie6' : '');
|
||||
|
||||
var value = v / this.ceiling * 100;
|
||||
value = value.toFixed(0);
|
||||
|
||||
//ugly hack to deal with IE6 issue
|
||||
var text = String.format('</div><div class="x-progress-text {0}" style="width:100%;" id="{1}">{2}</div></div>',
|
||||
textClass, Ext.id(), v + this.textPst
|
||||
textClass, Ext.id(), value + this.textPst
|
||||
);
|
||||
text = (v < 96) ? text.substring(0, text.length - 6) : text.substr(6);
|
||||
text = (v < (this.ceiling / 1.031)) ? text.substring(0, text.length - 6) : text.substr(6);
|
||||
|
||||
if (this.colored == true) {
|
||||
if (v <= 100 && v > 66)
|
||||
if (v <= this.ceiling && v > (this.ceiling * 0.66))
|
||||
style = '-green';
|
||||
if (v < 67 && v > 33)
|
||||
if (v < (this.ceiling * 0.67) && v > (this.ceiling * 0.33))
|
||||
style = '-orange';
|
||||
if (v < 34)
|
||||
if (v < (this.ceiling * 0.34))
|
||||
style = '-red';
|
||||
}
|
||||
|
||||
p.css += ' x-grid3-progresscol';
|
||||
return String.format(
|
||||
'<div class="x-progress-wrap"><div class="x-progress-inner"><div class="x-progress-bar{0}" style="width:{1}%;">{2}</div>' +
|
||||
'</div>', style, v, text
|
||||
'</div>', style, value, text
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -181,6 +181,18 @@ tvheadend.status_streams = function() {
|
|||
name: 'cc'
|
||||
}, {
|
||||
name: 'te'
|
||||
}, {
|
||||
name: 'signal_scale'
|
||||
}, {
|
||||
name: 'snr_scale'
|
||||
}, {
|
||||
name: 'ec_bit'
|
||||
}, {
|
||||
name: 'tc_bit'
|
||||
}, {
|
||||
name: 'ec_block'
|
||||
}, {
|
||||
name: 'tc_block'
|
||||
}
|
||||
],
|
||||
url: 'api/status/inputs',
|
||||
|
@ -188,49 +200,32 @@ tvheadend.status_streams = function() {
|
|||
id: 'uuid'
|
||||
});
|
||||
|
||||
tvheadend.comet.on('input_status', function(m) {
|
||||
if (m.reload != null)
|
||||
tvheadend.streamStatusStore.reload();
|
||||
if (m.update != null) {
|
||||
var r = tvheadend.streamStatusStore.getById(m.uuid);
|
||||
if (r) {
|
||||
r.data.subs = m.subs;
|
||||
r.data.weight = m.weight;
|
||||
r.data.signal = m.signal;
|
||||
r.data.ber = m.ber;
|
||||
r.data.unc = m.unc;
|
||||
r.data.snr = m.snr;
|
||||
r.data.bps = m.bps;
|
||||
r.data.cc = m.cc;
|
||||
r.data.te = m.te;
|
||||
|
||||
tvheadend.streamStatusStore.afterEdit(r);
|
||||
tvheadend.streamStatusStore.fireEvent('updated',
|
||||
tvheadend.streamStatusStore,
|
||||
r,
|
||||
Ext.data.Record.COMMIT);
|
||||
} else {
|
||||
tvheadend.streamStatusStore.reload();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var signal = new Ext.ux.grid.ProgressColumn({
|
||||
header: "Signal Strength",
|
||||
dataIndex: 'signal',
|
||||
width: 85,
|
||||
textPst: '%',
|
||||
colored: true
|
||||
});
|
||||
|
||||
function renderBw(value, item, store) {
|
||||
var txt = parseInt(value / 1024);
|
||||
var href = "javascript:tvheadend.stream_bw_monitor('" + store.id + "');";
|
||||
return '<a href="' + href + '">' + txt + '</a>';
|
||||
}
|
||||
|
||||
function renderBer(value, item, store) {
|
||||
if (store.data.tc_bit == 0)
|
||||
return value; // fallback (driver/vendor dependent ber)
|
||||
|
||||
// ber = error_bit_count / total_bit_count
|
||||
var ber = store.data.ec_bit / store.data.tc_bit;
|
||||
return ber;
|
||||
}
|
||||
|
||||
function renderPer(value, item, store) {
|
||||
if (value == 0) // value: total_block_count
|
||||
return '<span class="tvh-grid-unset">Unknown</span>';
|
||||
|
||||
// per = error_block_count / total_block_count
|
||||
var per = store.data.ec_block / value;
|
||||
return per;
|
||||
}
|
||||
|
||||
var cm = new Ext.grid.ColumnModel([{
|
||||
width: 100,
|
||||
width: 120,
|
||||
header: "Input",
|
||||
dataIndex: 'input'
|
||||
}, {
|
||||
|
@ -253,31 +248,126 @@ tvheadend.status_streams = function() {
|
|||
}, {
|
||||
width: 50,
|
||||
header: "BER",
|
||||
dataIndex: 'ber'
|
||||
dataIndex: 'ber',
|
||||
renderer: renderBer
|
||||
}, {
|
||||
width: 50,
|
||||
header: "Uncorrected BER",
|
||||
header: "PER",
|
||||
dataIndex: 'tc_block',
|
||||
renderer: renderPer
|
||||
}, {
|
||||
width: 50,
|
||||
header: "Uncorrected Blocks",
|
||||
dataIndex: 'unc'
|
||||
}, {
|
||||
width: 50,
|
||||
header: "Transport Error",
|
||||
header: "Transport Errors",
|
||||
dataIndex: 'te'
|
||||
}, {
|
||||
width: 50,
|
||||
header: "Continuity Error",
|
||||
header: "Continuity Errors",
|
||||
dataIndex: 'cc'
|
||||
}, {
|
||||
width: 50,
|
||||
header: "SNR",
|
||||
dataIndex: 'snr',
|
||||
renderer: function(value) {
|
||||
if (value > 0) {
|
||||
return value.toFixed(1) + " dB";
|
||||
} else {
|
||||
return '<span class="tvh-grid-unset">Unknown</span>';
|
||||
}]);
|
||||
|
||||
var has_signal_rel = false;
|
||||
var has_signal_dbm = false;
|
||||
var has_snr_rel = false;
|
||||
var has_snr_db = false;
|
||||
|
||||
tvheadend.comet.on('input_status', function(m) {
|
||||
if (m.reload != null)
|
||||
tvheadend.streamStatusStore.reload();
|
||||
if (m.update != null) {
|
||||
var r = tvheadend.streamStatusStore.getById(m.uuid);
|
||||
if (r) {
|
||||
r.data.subs = m.subs;
|
||||
r.data.weight = m.weight;
|
||||
r.data.signal = m.signal;
|
||||
r.data.ber = m.ber;
|
||||
r.data.unc = m.unc;
|
||||
r.data.snr = m.snr;
|
||||
r.data.bps = m.bps;
|
||||
r.data.cc = m.cc;
|
||||
r.data.te = m.te;
|
||||
r.data.signal_scale = m.signal_scale;
|
||||
r.data.snr_scale = m.snr_scale;
|
||||
r.data.ec_bit = m.ec_bit;
|
||||
r.data.tc_bit = m.tc_bit;
|
||||
r.data.ec_block = m.ec_block;
|
||||
r.data.tc_block = m.tc_block;
|
||||
|
||||
if (r.data.snr_scale == 1 /* scale_relative */) {
|
||||
if (!has_snr_rel) {
|
||||
cm.config.push(new Ext.ux.grid.ProgressColumn({
|
||||
header: "SNR (%)",
|
||||
dataIndex: 'snr',
|
||||
width: 85,
|
||||
colored: true,
|
||||
ceiling: 65535
|
||||
}));
|
||||
has_snr_rel = true;
|
||||
}
|
||||
}
|
||||
else if (r.data.snr_scale == 2 /* scale_decibel */) {
|
||||
if (!has_snr_db) {
|
||||
cm.config.push(new Ext.grid.Column({
|
||||
width: 50,
|
||||
header: "SNR (dB)",
|
||||
dataIndex: 'snr',
|
||||
renderer: function(value) {
|
||||
if (value > 0) {
|
||||
var snr = value * 0.0001;
|
||||
return snr.toFixed(1) + " dB";
|
||||
} else {
|
||||
return '<span class="tvh-grid-unset">Unknown</span>';
|
||||
}
|
||||
}
|
||||
}));
|
||||
has_snr_db = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (r.data.signal_scale == 1 /* scale_relative */) {
|
||||
if (!has_signal_rel) {
|
||||
cm.config.push(new Ext.ux.grid.ProgressColumn({
|
||||
header: "Signal Strength (%)",
|
||||
dataIndex: 'signal',
|
||||
width: 85,
|
||||
colored: true,
|
||||
ceiling: 65535
|
||||
}));
|
||||
has_signal_rel = true;
|
||||
}
|
||||
}
|
||||
else if (r.data.signal_scale == 2 /* scale_decibel */) {
|
||||
if (!has_signal_dbm) {
|
||||
cm.config.push(new Ext.grid.Column({
|
||||
width: 50,
|
||||
header: "Signal Strength (dBm)",
|
||||
dataIndex: 'signal',
|
||||
renderer: function(value) {
|
||||
if (value > 0) {
|
||||
var snr = value * 0.0001;
|
||||
return snr.toFixed(1) + " dBm";
|
||||
} else {
|
||||
return '<span class="tvh-grid-unset">Unknown</span>';
|
||||
}
|
||||
}
|
||||
}));
|
||||
has_signal_dbm = true;
|
||||
}
|
||||
}
|
||||
|
||||
tvheadend.streamStatusStore.afterEdit(r);
|
||||
tvheadend.streamStatusStore.fireEvent('updated',
|
||||
tvheadend.streamStatusStore,
|
||||
r,
|
||||
Ext.data.Record.COMMIT);
|
||||
} else {
|
||||
tvheadend.streamStatusStore.reload();
|
||||
}
|
||||
}, signal]);
|
||||
}
|
||||
});
|
||||
|
||||
var panel = new Ext.grid.GridPanel({
|
||||
border: false,
|
||||
|
|
Loading…
Add table
Reference in a new issue