diff --git a/README b/README index 34b7659..3961a4f 100644 --- a/README +++ b/README @@ -34,15 +34,14 @@ Terminology: |## Channel Name ################### [SVDRP][AR][VF][A/DD][D]| |[=====Signal Strength ===================|=================]| |[=====Signal Quality ================|=====================]| -| STR: #0000 (0%) BER: #00000000 Video: 0 Mbit/s | -| SNR: #0000 (0%) UNC: #00000000 Audio: 0 kbit/s | +| STR: 0 CNR: 0 BER: 0 PER: 0 Video: 0 Audio: 0 | | [LOCK] [SIGNAL] [CARRIER] [VITERBI] [SYNC] | -------------------------------------------------------------- -STR - Signal strength from driver -SNR - Signal-to-noise ratio from driver -BER - Bit error rate -UNC - Uncorrected blocks +STR - Signal strength in dBm +CNR - Signal-to-noise ratio of the main carrier in dB +BER - Bit error rate after the forward error correction (FEC) done by inner code block +PER - Block error rate after the outer forward error correction coding Video - Calculated video bitrate in Mbit/s Audio - Calculated audio / AC-3 bitrate in kbit/s diff --git a/femon.c b/femon.c index fb000df..144135f 100644 --- a/femon.c +++ b/femon.c @@ -17,8 +17,8 @@ #include "tools.h" #include "setup.h" -#if defined(APIVERSNUM) && APIVERSNUM < 20302 -#error "VDR-2.3.2 API version or greater is required!" +#if defined(APIVERSNUM) && APIVERSNUM < 20305 +#error "VDR-2.3.5 API version or greater is required!" #endif #ifndef GITVERSION @@ -173,18 +173,18 @@ bool cPluginFemon::SetupParse(const char *nameP, const char *valueP) bool cPluginFemon::Service(const char *idP, void *dataP) { - if (strcmp(idP, "FemonService-v1.0") == 0) { + if (strcmp(idP, "FemonService-v1.1") == 0) { if (dataP) { - FemonService_v1_0 *data = reinterpret_cast(dataP); - if (!cDevice::ActualDevice()) + FemonService_v1_1 *data = reinterpret_cast(dataP); + cDevice *dev = cDevice::ActualDevice(); + if (!dev) return false; - cDvbDevice *dev = getDvbDevice(cDevice::ActualDevice()); data->fe_name = getFrontendName(dev); data->fe_status = getFrontendStatus(dev); - data->fe_snr = getSNR(dev); + data->fe_cnr = getCNR(dev); data->fe_signal = getSignal(dev); data->fe_ber = getBER(dev); - data->fe_unc = getUNC(dev); + data->fe_per = getPER(dev); data->video_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetVideoBitrate() : 0.0; data->audio_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetAudioBitrate() : 0.0; data->dolby_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetDolbyBitrate() : 0.0; @@ -218,12 +218,12 @@ const char **cPluginFemon::SVDRPHelpPages(void) " Print the signal quality.", "SGNL \n" " Print the signal strength from driver.", - "SNRA \n" - " Print the signal-to-noise ratio from driver.", + "CNRA \n" + " Print the carrier-to-noise ratio from driver.", "BERA \n" - " Print the bit error rate.", - "UNCB \n" - " Print the uncorrected blocks rate.", + " Print the bit error rate from driver.", + "PERA \n" + " Print the packet error rate from driver.", "VIBR\n" " Print the current video bitrate [Mbit/s].", "AUBR\n" @@ -239,14 +239,14 @@ const char **cPluginFemon::SVDRPHelpPages(void) cString cPluginFemon::SVDRPCommand(const char *commandP, const char *optionP, int &replyCodeP) { - cDvbDevice *dev = getDvbDevice(cDevice::ActualDevice()); + cDevice *dev = cDevice::ActualDevice(); if (strcasecmp(commandP, "TRAC") == 0) { if (optionP && *optionP) FemonConfig.SetTraceMode(strtol(optionP, NULL, 0)); return cString::sprintf("Tracing mode: 0x%04X\n", FemonConfig.GetTraceMode()); } if (*optionP && isnumber(optionP)) { - cDvbDevice *dev2 = dynamic_cast(cDevice::GetDevice(int(strtol(optionP, NULL, 10)))); + cDevice *dev2 = cDevice::GetDevice(int(strtol(optionP, NULL, 10))); if (dev2) dev = dev2; } @@ -292,18 +292,16 @@ cString cPluginFemon::SVDRPCommand(const char *commandP, const char *optionP, in return cString::sprintf("%d on device #%d", dev->SignalQuality(), dev->CardIndex()); } else if (strcasecmp(commandP, "SGNL") == 0) { - int value = getSignal(dev); - return cString::sprintf("%04X (%02d%%) on device #%d", value, value / 655, dev->CardIndex()); + return cString::sprintf("%.2f dBm on device #%d", getSignal(dev), dev->CardIndex()); } - else if (strcasecmp(commandP, "SNRA") == 0) { - int value = getSNR(dev); - return cString::sprintf("%04X (%02d%%) on device #%d", value, value / 655, dev->CardIndex()); + else if (strcasecmp(commandP, "CNRA") == 0) { + return cString::sprintf("%.2f dB on device #%d", getCNR(dev), dev->CardIndex()); } else if (strcasecmp(commandP, "BERA") == 0) { - return cString::sprintf("%08X on device #%d", getBER(dev), dev->CardIndex()); + return cString::sprintf("%.0f on device #%d", getBER(dev), dev->CardIndex()); } - else if (strcasecmp(commandP, "UNCB") == 0) { - return cString::sprintf("%08X on device #%d", getUNC(dev), dev->CardIndex()); + else if (strcasecmp(commandP, "PERA") == 0) { + return cString::sprintf("%.0f on device #%d", getPER(dev), dev->CardIndex()); } else if (strcasecmp(commandP, "VIBR") == 0) { if (cFemonOsd::Instance()) diff --git a/femonservice.h b/femonservice.h index a960b0a..dd4c8f0 100644 --- a/femonservice.h +++ b/femonservice.h @@ -8,15 +8,13 @@ #ifndef __FEMONSERVICE_H #define __FEMONSERVICE_H -#include - -struct FemonService_v1_0 { +struct FemonService_v1_1 { cString fe_name; cString fe_status; - uint16_t fe_snr; - uint16_t fe_signal; - uint32_t fe_ber; - uint32_t fe_unc; + double fe_cnr; + double fe_signal; + double fe_ber; + double fe_per; double video_bitrate; double audio_bitrate; double dolby_bitrate; diff --git a/osd.c b/osd.c index e7eddaa..a4890bf 100644 --- a/osd.c +++ b/osd.c @@ -27,7 +27,7 @@ #define OSDHEIGHT osdHeightM // in pixels #define OSDROWHEIGHT fontM->Height() // in pixels #define OSDINFOHEIGHT (OSDROWHEIGHT * 14) // in pixels (14 rows) -#define OSDSTATUSHEIGHT (OSDROWHEIGHT * 6) // in pixels (6 rows) +#define OSDSTATUSHEIGHT (OSDROWHEIGHT * 5) // in pixels (5 rows) #define OSDSYMBOL(id) femonSymbols.Get(id) #define OSDSPACING femonSymbols.GetSpacing() #define OSDROUNDING femonSymbols.GetRounding() @@ -39,12 +39,11 @@ (col == 2) ? int(round(OSDWIDTH * 0.26)) : \ int(round(OSDWIDTH * 0.025))) #define OSDSTATUSWIN_Y(offset) (FemonConfig.GetPosition() ? offset : (OSDHEIGHT - OSDSTATUSHEIGHT + offset)) -#define OSDSTATUSWIN_X(col) ((col == 7) ? int(round(OSDWIDTH * 0.79)) : \ - (col == 6) ? int(round(OSDWIDTH * 0.68)) : \ - (col == 5) ? int(round(OSDWIDTH * 0.46)) : \ - (col == 4) ? int(round(OSDWIDTH * 0.37)) : \ - (col == 3) ? int(round(OSDWIDTH * 0.21)) : \ - (col == 2) ? int(round(OSDWIDTH * 0.12)) : \ +#define OSDSTATUSWIN_X(col) ((col == 6) ? int(round(OSDWIDTH * 0.84)) : \ + (col == 5) ? int(round(OSDWIDTH * 0.66)) : \ + (col == 4) ? int(round(OSDWIDTH * 0.50)) : \ + (col == 3) ? int(round(OSDWIDTH * 0.35)) : \ + (col == 2) ? int(round(OSDWIDTH * 0.19)) : \ int(round(OSDWIDTH * 0.025))) #define OSDSTATUSWIN_XSYMBOL(c,w) (c * ((OSDWIDTH - (5 * w)) / 6) + ((c - 1) * w)) #define OSDBARWIDTH(x) (OSDWIDTH * x / 100) @@ -60,14 +59,13 @@ #define OSDDRAWSTATUSFRONTEND(column, bitmap, status) \ osdM->DrawBitmap(OSDSTATUSWIN_XSYMBOL(column, x), OSDSTATUSWIN_Y(offset) + y, bitmap, (frontendStatusM & status) ? FemonTheme[FemonConfig.GetTheme()].clrActiveText : FemonTheme[FemonConfig.GetTheme()].clrRed, FemonTheme[FemonConfig.GetTheme()].clrBackground) -#define OSDDRAWSTATUSVALUES(label1, label2, label3, label4, label5, label6, label7) \ +#define OSDDRAWSTATUSVALUES(label1, label2, label3, label4, label5, label6) \ osdM->DrawText(OSDSTATUSWIN_X(1), OSDSTATUSWIN_Y(offset), label1, FemonTheme[FemonConfig.GetTheme()].clrInactiveText, FemonTheme[FemonConfig.GetTheme()].clrBackground, fontM); \ osdM->DrawText(OSDSTATUSWIN_X(2), OSDSTATUSWIN_Y(offset), label2, FemonTheme[FemonConfig.GetTheme()].clrInactiveText, FemonTheme[FemonConfig.GetTheme()].clrBackground, fontM); \ osdM->DrawText(OSDSTATUSWIN_X(3), OSDSTATUSWIN_Y(offset), label3, FemonTheme[FemonConfig.GetTheme()].clrInactiveText, FemonTheme[FemonConfig.GetTheme()].clrBackground, fontM); \ osdM->DrawText(OSDSTATUSWIN_X(4), OSDSTATUSWIN_Y(offset), label4, FemonTheme[FemonConfig.GetTheme()].clrInactiveText, FemonTheme[FemonConfig.GetTheme()].clrBackground, fontM); \ osdM->DrawText(OSDSTATUSWIN_X(5), OSDSTATUSWIN_Y(offset), label5, FemonTheme[FemonConfig.GetTheme()].clrInactiveText, FemonTheme[FemonConfig.GetTheme()].clrBackground, fontM); \ - osdM->DrawText(OSDSTATUSWIN_X(6), OSDSTATUSWIN_Y(offset), label6, FemonTheme[FemonConfig.GetTheme()].clrInactiveText, FemonTheme[FemonConfig.GetTheme()].clrBackground, fontM); \ - osdM->DrawText(OSDSTATUSWIN_X(7), OSDSTATUSWIN_Y(offset), label7, FemonTheme[FemonConfig.GetTheme()].clrInactiveText, FemonTheme[FemonConfig.GetTheme()].clrBackground, fontM) + osdM->DrawText(OSDSTATUSWIN_X(6), OSDSTATUSWIN_Y(offset), label6, FemonTheme[FemonConfig.GetTheme()].clrInactiveText, FemonTheme[FemonConfig.GetTheme()].clrBackground, fontM) #define OSDDRAWSTATUSBAR(value) \ if (value > 0) { \ @@ -168,7 +166,6 @@ cFemonOsd::cFemonOsd() : cOsdObject(true), cThread("femon osd"), osdM(NULL), receiverM(NULL), - frontendM(-1), svdrpFrontendM(-1), svdrpVideoBitRateM(-1), svdrpAudioBitRateM(-1), @@ -179,15 +176,17 @@ cFemonOsd::cFemonOsd() qualityValidM(false), strengthM(0), strengthValidM(false), - snrM(0), - snrValidM(false), + cnrM(0), + cnrValidM(false), signalM(0), signalValidM(false), berM(0), berValidM(false), - uncM(0), - uncValidM(false), + perM(0), + perValidM(false), frontendNameM(""), + frontendTypeM(""), + frontendStatusM(DTV_STAT_HAS_NONE), frontendStatusValidM(false), deviceSourceM(DEVICESOURCE_DVBAPI), displayModeM(FemonConfig.GetDisplayMode()), @@ -201,8 +200,6 @@ cFemonOsd::cFemonOsd() { int tmp; debug1("%s", __PRETTY_FUNCTION__); - memset(&frontendStatusM, 0, sizeof(frontendStatusM)); - memset(&frontendInfoM, 0, sizeof(frontendInfoM)); svdrpConnectionM.handle = -1; femonSymbols.Refresh(); fontM = cFont::CreateFont(Setup.FontSml, constrain(Setup.FontSmlSize, MINFONTSIZE, MAXFONTSIZE)); @@ -241,10 +238,6 @@ cFemonOsd::~cFemonOsd(void) DELETENULL(osdM); if (fontM) DELETENULL(fontM); - if (frontendM >= 0) { - close(frontendM); - frontendM = -1; - } pInstanceS = NULL; } @@ -378,23 +371,22 @@ void cFemonOsd::DrawStatusWindow(void) if (qualityValidM) OSDDRAWSTATUSBAR(qualityM); offset += OSDROWHEIGHT; - OSDDRAWSTATUSVALUES("STR:", signalValidM ? *cString::sprintf("%04x", signalM) : "", signalValidM ? *cString::sprintf("(%2d%%)", signalM / 655) : "", - "BER:", berValidM ? *cString::sprintf("%08x", berM) : "", *cString::sprintf("%s:", tr("Video")), - *getBitrateMbits(receiverM ? receiverM->VideoBitrate() : (svdrpFrontendM >= 0 ? svdrpVideoBitRateM : -1.0))); - offset += OSDROWHEIGHT; - OSDDRAWSTATUSVALUES("SNR:", snrValidM ? *cString::sprintf("%04x", snrM) : "", snrValidM ? *cString::sprintf("(%2d%%)", snrM / 655) : "", - "UNC:", uncValidM ? *cString::sprintf("%08x", uncM) : "", - *cString::sprintf("%s:", (receiverM && receiverM->AC3Valid() && IS_DOLBY_TRACK(track)) ? tr("AC-3") : tr("Audio")), - *getBitrateKbits(receiverM ? ((receiverM->AC3Valid() && IS_DOLBY_TRACK(track)) ? receiverM->AC3Bitrate() : receiverM->AudioBitrate()) : (svdrpFrontendM >= 0 ? svdrpAudioBitRateM : -1.0))); + OSDDRAWSTATUSVALUES(signalValidM ? *cString::sprintf("STR: %.2f dBm", signalM) : "STR: ---", + cnrValidM ? *cString::sprintf("CNR: %.2f dB", cnrM) : "CNR: ---", + berValidM ? *cString::sprintf("BER: %.0f", berM) : "BER: ---", + perValidM ? *cString::sprintf("PER: %.0f", perM) : "PER: ---", + *cString::sprintf("%s: %s", tr("Video"), *getBitrateMbits(receiverM ? receiverM->VideoBitrate() : (svdrpFrontendM >= 0 ? svdrpVideoBitRateM : -1.0))), + *cString::sprintf("%s: %s", (receiverM && receiverM->AC3Valid() && IS_DOLBY_TRACK(track)) ? tr("AC-3") : tr("Audio"), *getBitrateKbits(receiverM ? ((receiverM->AC3Valid() && IS_DOLBY_TRACK(track)) ? receiverM->AC3Bitrate() : receiverM->AudioBitrate()) : (svdrpFrontendM >= 0 ? svdrpAudioBitRateM : -1.0))) + ); offset += OSDROWHEIGHT; x = OSDSYMBOL(SYMBOL_LOCK).Width(); y = (OSDROWHEIGHT - OSDSYMBOL(SYMBOL_LOCK).Height()) / 2; if (frontendStatusValidM) { - OSDDRAWSTATUSFRONTEND(1, OSDSYMBOL(SYMBOL_LOCK), FE_HAS_LOCK); - OSDDRAWSTATUSFRONTEND(2, OSDSYMBOL(SYMBOL_SIGNAL), FE_HAS_SIGNAL); - OSDDRAWSTATUSFRONTEND(3, OSDSYMBOL(SYMBOL_CARRIER), FE_HAS_CARRIER); - OSDDRAWSTATUSFRONTEND(4, OSDSYMBOL(SYMBOL_VITERBI), FE_HAS_VITERBI); - OSDDRAWSTATUSFRONTEND(5, OSDSYMBOL(SYMBOL_SYNC), FE_HAS_SYNC); + OSDDRAWSTATUSFRONTEND(1, OSDSYMBOL(SYMBOL_LOCK), DTV_STAT_HAS_LOCK); + OSDDRAWSTATUSFRONTEND(2, OSDSYMBOL(SYMBOL_SIGNAL), DTV_STAT_HAS_SIGNAL); + OSDDRAWSTATUSFRONTEND(3, OSDSYMBOL(SYMBOL_CARRIER), DTV_STAT_HAS_CARRIER); + OSDDRAWSTATUSFRONTEND(4, OSDSYMBOL(SYMBOL_VITERBI), DTV_STAT_HAS_VITERBI); + OSDDRAWSTATUSFRONTEND(5, OSDSYMBOL(SYMBOL_SYNC), DTV_STAT_HAS_SYNC); } OSDDRAWSTATUSBOTTOMBAR(); osdM->Flush(); @@ -601,16 +593,16 @@ void cFemonOsd::Action(void) strengthM = cDevice::ActualDevice()->SignalStrength(); strengthValidM = (strengthM >= 0); frontendNameM = cDevice::ActualDevice()->DeviceName(); - frontendStatusM = (fe_status_t)(strengthValidM ? (FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC) : 0); + frontendStatusM = strengthValidM ? (DTV_STAT_HAS_SIGNAL | DTV_STAT_HAS_CARRIER | DTV_STAT_HAS_VITERBI | DTV_STAT_HAS_SYNC | DTV_STAT_HAS_LOCK) : DTV_STAT_HAS_NONE; frontendStatusValidM = strengthValidM; - signalM = uint16_t(strengthM * 0xFFFF / 100); + signalM = strengthM; signalValidM = strengthValidM; - snrM = 0; - snrValidM = false; + cnrM = 0; + cnrValidM = false; berM = 0; berValidM = false; - uncM = 0; - uncValidM = false; + perM = 0; + perValidM = false; break; case DEVICESOURCE_IPTV: qualityM = cDevice::ActualDevice()->SignalQuality(); @@ -618,49 +610,20 @@ void cFemonOsd::Action(void) strengthM = cDevice::ActualDevice()->SignalStrength(); strengthValidM = (strengthM >= 0); frontendNameM = cDevice::ActualDevice()->DeviceName(); - frontendStatusM = (fe_status_t)(strengthValidM ? (FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC) : 0); + frontendStatusM = strengthValidM ? (DTV_STAT_HAS_SIGNAL | DTV_STAT_HAS_CARRIER | DTV_STAT_HAS_VITERBI | DTV_STAT_HAS_SYNC | DTV_STAT_HAS_LOCK) : DTV_STAT_HAS_NONE; frontendStatusValidM = strengthValidM; - signalM = uint16_t(strengthM * 0xFFFF / 100); + signalM = strengthM; signalValidM = strengthValidM; - snrM = uint16_t(qualityM * 0xFFFF / 100); - snrValidM = qualityValidM; + cnrM = qualityM; + cnrValidM = qualityValidM; berM = 0; berValidM = false; - uncM = 0; - uncValidM = false; + perM = 0; + perValidM = false; break; default: case DEVICESOURCE_DVBAPI: - if (frontendM != -1) { - qualityM = cDevice::ActualDevice()->SignalQuality(); - qualityValidM = (qualityM >= 0); - strengthM = cDevice::ActualDevice()->SignalStrength(); - strengthValidM = (strengthM >= 0); - frontendNameM = cDevice::ActualDevice()->DeviceName(); - frontendStatusValidM = (ioctl(frontendM, FE_READ_STATUS, &frontendStatusM) >= 0); - signalValidM = (ioctl(frontendM, FE_READ_SIGNAL_STRENGTH, &signalM) >= 0); - snrValidM = (ioctl(frontendM, FE_READ_SNR, &snrM) >= 0); - berValidM = (ioctl(frontendM, FE_READ_BER, &berM) >= 0); - uncValidM = (ioctl(frontendM, FE_READ_UNCORRECTED_BLOCKS, &uncM) >= 0); - } - else if (strstr(*cDevice::ActualDevice()->DeviceType(), SATIP_DEVICE)) { - qualityM = cDevice::ActualDevice()->SignalQuality(); - qualityValidM = (qualityM >= 0); - strengthM = cDevice::ActualDevice()->SignalStrength(); - strengthValidM = (strengthM >= 0); - frontendNameM = cDevice::ActualDevice()->DeviceName(); - frontendStatusM = (fe_status_t)(cDevice::ActualDevice()->HasLock() ? (FE_HAS_LOCK | FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI | FE_HAS_SYNC) : 0); - frontendStatusValidM = strengthValidM; - signalM = uint16_t(strengthM * 0xFFFF / 100); - signalValidM = strengthValidM; - snrM = uint16_t(qualityM * 0xFFFF / 100); - snrValidM = qualityValidM; - berM = 0; - berValidM = false; - uncM = 0; - uncValidM = false; - } - else if (svdrpConnectionM.handle >= 0) { + if (svdrpConnectionM.handle >= 0) { cmd.handle = svdrpConnectionM.handle; svdrpPluginM->Service("SvdrpCommand-v1.0", &cmd); if (cmd.responseCode == 900) { @@ -668,9 +631,9 @@ void cFemonOsd::Action(void) qualityValidM = false; frontendStatusValidM = false; signalValidM = false; - snrValidM = false; + cnrValidM = false; berValidM = false; - uncValidM = false; + perValidM = false; for (cLine *line = cmd.reply.First(); line; line = cmd.reply.Next(line)) { const char *s = line->Text(); if (!strncasecmp(s, "CARD:", 5)) @@ -683,38 +646,61 @@ void cFemonOsd::Action(void) qualityM = (int)strtol(s + 5, NULL, 10); qualityValidM = (qualityM >= 0); } - else if (!strncasecmp(s, "TYPE:", 5)) - frontendInfoM.type = (fe_type_t)strtol(s + 5, NULL, 10); + else if (!strncasecmp(s, "TYPE:", 5)) { + frontendTypeM = s + 5; + } else if (!strncasecmp(s, "NAME:", 5)) { frontendNameM = s + 5; } else if (!strncasecmp(s, "STAT:", 5)) { - frontendStatusM = (fe_status_t)strtol(s + 5, NULL, 16); + frontendStatusM = strtol(s + 5, NULL, 16); frontendStatusValidM = true; } else if (!strncasecmp(s, "SGNL:", 5)) { - signalM = (uint16_t)strtol(s + 5, NULL, 16); + signalM = atod(s + 5); signalValidM = true; } - else if (!strncasecmp(s, "SNRA:", 5)) { - snrM = (uint16_t)strtol(s + 5, NULL, 16); - snrValidM = true; + else if (!strncasecmp(s, "CNRA:", 5)) { + cnrM = atod(s + 5); + cnrValidM = true; } else if (!strncasecmp(s, "BERA:", 5)) { - berM = (uint32_t)strtol(s + 5, NULL, 16); + berM = atod(s + 5); berValidM = true; } - else if (!strncasecmp(s, "UNCB:", 5)) { - uncM = (uint32_t)strtol(s + 5, NULL, 16); - uncValidM = true; + else if (!strncasecmp(s, "PERA:", 5)) { + perM = atod(s + 5); + perValidM = true; } else if (!strncasecmp(s, "VIBR:", 5)) - svdrpVideoBitRateM = (double)strtol(s + 5, NULL, 10); + svdrpVideoBitRateM = atod(s + 5); else if (!strncasecmp(s, "AUBR:", 5)) - svdrpAudioBitRateM = (double)strtol(s + 5, NULL, 10); + svdrpAudioBitRateM = atod(s + 5); } } } + else { + int valid; + qualityM = cDevice::ActualDevice()->SignalQuality(); + qualityValidM = (qualityM >= 0); + strengthM = cDevice::ActualDevice()->SignalStrength(); + strengthValidM = (strengthM >= 0); + frontendNameM = cDevice::ActualDevice()->DeviceName(); + if (cDevice::ActualDevice()->SignalStats(valid, &signalM, &cnrM, NULL, &berM, &perM, &frontendStatusM)) { + frontendStatusValidM = valid & DTV_STAT_VALID_STATUS; + signalValidM = valid & DTV_STAT_VALID_STRENGTH; + cnrValidM = valid & DTV_STAT_VALID_CNR; + berValidM = valid & DTV_STAT_VALID_BERPOST; + perValidM = valid & DTV_STAT_VALID_PER; + } + else { + frontendStatusValidM = false; + signalValidM = false; + cnrValidM = false; + berValidM = false; + perValidM = false; + } + } break; } DrawInfoWindow(); @@ -765,11 +751,6 @@ bool cFemonOsd::AttachFrontend(void) LOCK_CHANNELS_READ; const cChannel *channel = Channels->GetByNumber(cDevice::CurrentChannel()); - if (frontendM >= 0) { - close(frontendM); - frontendM = -1; - } - deviceSourceM = DEVICESOURCE_DVBAPI; if (channel) { if (channel->IsSourceType('I')) @@ -780,30 +761,12 @@ bool cFemonOsd::AttachFrontend(void) if (deviceSourceM == DEVICESOURCE_DVBAPI) { if (!strstr(*cDevice::ActualDevice()->DeviceType(), SATIP_DEVICE)) { - cDvbDevice *dev = getDvbDevice(cDevice::ActualDevice()); - frontendM = dev ? open(*cString::sprintf(FRONTEND_DEVICE, dev->Adapter(), dev->Frontend()), O_RDONLY | O_NONBLOCK) : -1; - if (frontendM >= 0) { - if (ioctl(frontendM, FE_GET_INFO, &frontendInfoM) < 0) { - if (!FemonConfig.GetUseSvdrp()) - error("%s Cannot read frontend info", __PRETTY_FUNCTION__); - close(frontendM); - frontendM = -1; - memset(&frontendInfoM, 0, sizeof(frontendInfoM)); - return false; - } - } - else if (FemonConfig.GetUseSvdrp()) { + if (FemonConfig.GetUseSvdrp()) { if (!SvdrpConnect() || !SvdrpTune()) return false; } - else { - error("%s Cannot open frontend device", __PRETTY_FUNCTION__); - return false; - } } } - else - frontendM = -1; return true; } diff --git a/osd.h b/osd.h index 88de8b0..154974d 100644 --- a/osd.h +++ b/osd.h @@ -8,9 +8,7 @@ #ifndef __FEMON_OSD_H #define __FEMON_OSD_H -#include #include -#include #include #include #include @@ -37,7 +35,6 @@ private: cOsd *osdM; cFemonReceiver *receiverM; - int frontendM; int svdrpFrontendM; double svdrpVideoBitRateM; double svdrpAudioBitRateM; @@ -49,16 +46,17 @@ private: bool qualityValidM; int strengthM; bool strengthValidM; - uint16_t snrM; - bool snrValidM; - uint16_t signalM; + double cnrM; + bool cnrValidM; + double signalM; bool signalValidM; - uint32_t berM; + double berM; bool berValidM; - uint32_t uncM; - bool uncValidM; + double perM; + bool perValidM; cString frontendNameM; - fe_status_t frontendStatusM; + cString frontendTypeM; + int frontendStatusM; bool frontendStatusValidM; dvb_frontend_info frontendInfoM; eDeviceSourceType deviceSourceM; diff --git a/tools.c b/tools.c index 26106ad..3f8ea4c 100644 --- a/tools.c +++ b/tools.c @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include "osd.h" #include "receiver.h" @@ -91,61 +89,42 @@ static const char *getUserString(int valueP, const tDvbParameterMap *mapP) return "---"; } -cDvbDevice *getDvbDevice(cDevice* deviceP) +cString getFrontendInfo(cDevice *deviceP) { - cDvbDevice *dev = dynamic_cast(deviceP); -#ifdef __DYNAMIC_DEVICE_PROBE - if (!dev && deviceP && deviceP->HasSubDevice()) - dev = dynamic_cast(deviceP->SubDevice()); -#endif - return dev; -} - -cString getFrontendInfo(cDvbDevice *deviceP) -{ - struct dvb_frontend_info value; - fe_status_t status; + const cChannel *channel; + int status, valid = DTV_STAT_VALID_NONE; cString info = ""; - uint16_t signal = 0; - uint16_t snr = 0; - uint32_t ber = 0; - uint32_t unc = 0; - LOCK_CHANNELS_READ; - const cChannel *channel = Channels->GetByNumber(cDevice::CurrentChannel()); + double signal = 0, cnr = 0, ber = 0, per = 0; if (!deviceP) return info; - int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); - if (fe < 0) - return info; - - info = cString::sprintf("CARD:%d\nSTRG:%d\nQUAL:%d", deviceP->CardIndex(), deviceP->SignalStrength(), deviceP->SignalQuality()); - - if (ioctl(fe, FE_GET_INFO, &value) >= 0) - info = cString::sprintf("%s\nTYPE:%d\nNAME:%s", *info, value.type, *deviceP->DeviceName()); - if (ioctl(fe, FE_READ_STATUS, &status) >= 0) - info = cString::sprintf("%s\nSTAT:%02X", *info, status); - if (ioctl(fe, FE_READ_SIGNAL_STRENGTH, &signal) >= 0) - info = cString::sprintf("%s\nSGNL:%04X", *info, signal); - if (ioctl(fe, FE_READ_SNR, &snr) >= 0) - info = cString::sprintf("%s\nSNRA:%04X", *info, snr); - if (ioctl(fe, FE_READ_BER, &ber) >= 0) - info = cString::sprintf("%s\nBERA:%08X", *info, ber); - if (ioctl(fe, FE_READ_UNCORRECTED_BLOCKS, &unc) >= 0) - info = cString::sprintf("%s\nUNCB:%08X", *info, unc); - close(fe); + info = cString::sprintf("CARD:%d\nSTRG:%d\nQUAL:%d\nTYPE:%s\nNAME:%s", deviceP->CardIndex(), deviceP->SignalStrength(), deviceP->SignalQuality(), *deviceP->DeviceType(), *deviceP->DeviceName()); + if (deviceP && deviceP->SignalStats(valid, &signal, &cnr, NULL, &ber, &per, &status)) { + if (valid & DTV_STAT_VALID_STATUS) + info = cString::sprintf("%s\nSTAT:%04X", *info, status); + if (valid & DTV_STAT_VALID_STRENGTH) + info = cString::sprintf("%s\nSGNL:%s", *info, *dtoa(signal, "%.2f")); + if (valid & DTV_STAT_VALID_CNR) + info = cString::sprintf("%s\nCNRA:%s", *info, *dtoa(cnr, "%.2f")); + if (valid & DTV_STAT_VALID_BERPOST) + info = cString::sprintf("%s\nBERA:%s", *info, *dtoa(ber, "%.0f")); + if (valid & DTV_STAT_VALID_PER) + info = cString::sprintf("%s\nPERA:%s", *info, *dtoa(per, "%.0f")); + } if (cFemonOsd::Instance()) - info = cString::sprintf("%s\nVIBR:%.0f\nAUBR:%.0f\nDDBR:%.0f", *info, cFemonOsd::Instance()->GetVideoBitrate(), cFemonOsd::Instance()->GetAudioBitrate(), cFemonOsd::Instance()->GetDolbyBitrate()); + info = cString::sprintf("%s\nVIBR:%s\nAUBR:%s\nDDBR:%s", *info, *dtoa(cFemonOsd::Instance()->GetVideoBitrate(), "%.0f"), *dtoa(cFemonOsd::Instance()->GetAudioBitrate(), "%.0f"), *dtoa(cFemonOsd::Instance()->GetDolbyBitrate(), "%.0f")); + LOCK_CHANNELS_READ; + channel = Channels->GetByNumber(cDevice::CurrentChannel()); if (channel) info = cString::sprintf("%s\nCHAN:%s", *info, *channel->ToText()); return info; } -cString getFrontendName(cDvbDevice *deviceP) +cString getFrontendName(cDevice *deviceP) { if (!deviceP) return NULL; @@ -153,85 +132,69 @@ cString getFrontendName(cDvbDevice *deviceP) return (cString::sprintf("%s on deviceP #%d", *deviceP->DeviceName(), deviceP->CardIndex())); } -cString getFrontendStatus(cDvbDevice *deviceP) +cString getFrontendStatus(cDevice *deviceP) { - fe_status_t value; + int status; + int valid = DTV_STAT_VALID_NONE; - if (!deviceP) - return NULL; + if (deviceP && deviceP->SignalStats(valid, NULL, NULL, NULL, NULL, NULL, &status)) { + if (valid & DTV_STAT_VALID_STATUS) + return (cString::sprintf("Status %s:%s:%s:%s:%s on deviceP #%d", (status & DTV_STAT_HAS_LOCK) ? "LOCKED" : "-", (status & DTV_STAT_HAS_SIGNAL) ? "SIGNAL" : "-", (status & DTV_STAT_HAS_CARRIER) ? "CARRIER" : "-", (status & DTV_STAT_HAS_VITERBI) ? "VITERBI" : "-", (status & DTV_STAT_HAS_SYNC) ? "SYNC" : "-", deviceP->CardIndex())); + } - int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); - if (fe < 0) - return NULL; - memset(&value, 0, sizeof(value)); - ioctl(fe, FE_READ_STATUS, &value); - close(fe); - - return (cString::sprintf("Status %s:%s:%s:%s:%s on deviceP #%d", (value & FE_HAS_LOCK) ? "LOCKED" : "-", (value & FE_HAS_SIGNAL) ? "SIGNAL" : "-", (value & FE_HAS_CARRIER) ? "CARRIER" : "-", (value & FE_HAS_VITERBI) ? "VITERBI" : "-", (value & FE_HAS_SYNC) ? "SYNC" : "-", deviceP->CardIndex())); + return NULL; } -uint16_t getSignal(cDvbDevice *deviceP) +double getSignal(cDevice *deviceP) { - uint16_t value = 0; + double strength; + int valid = DTV_STAT_VALID_NONE; - if (!deviceP) - return (value); + if (deviceP && deviceP->SignalStats(valid, &strength, NULL, NULL, NULL, NULL, NULL)) { + if (valid & DTV_STAT_VALID_STRENGTH) + return strength; + } - int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); - if (fe < 0) - return (value); - ioctl(fe, FE_READ_SIGNAL_STRENGTH, &value); - close(fe); - - return (value); + return 0; } -uint16_t getSNR(cDvbDevice *deviceP) +double getCNR(cDevice *deviceP) { - uint16_t value = 0; + double cnr; + int valid = DTV_STAT_VALID_NONE; - if (!deviceP) - return (value); + if (deviceP && deviceP->SignalStats(valid, NULL, &cnr, NULL, NULL, NULL, NULL)) { + if (valid & DTV_STAT_VALID_CNR) + return cnr; + } - int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); - if (fe < 0) - return (value); - ioctl(fe, FE_READ_SNR, &value); - close(fe); - - return (value); + return 0; } -uint32_t getBER(cDvbDevice *deviceP) +double getBER(cDevice *deviceP) { - uint32_t value = 0; + double ber; + int valid = DTV_STAT_VALID_NONE; - if (!deviceP) - return (value); + if (deviceP && deviceP->SignalStats(valid, NULL, NULL, NULL, &ber, NULL, NULL)) { + if (valid & DTV_STAT_VALID_BERPOST) + return ber; + } - int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); - if (fe < 0) - return (value); - ioctl(fe, FE_READ_BER, &value); - close(fe); - - return (value); + return 0; } -uint32_t getUNC(cDvbDevice *deviceP) +double getPER(cDevice *deviceP) { - uint32_t value = 0; + double per; + int valid = DTV_STAT_VALID_NONE; - if (!deviceP) - return (value); + if (deviceP && deviceP->SignalStats(valid, NULL, NULL, NULL, NULL, &per, NULL)) { + if (valid & DTV_STAT_VALID_PER) + return per; + } - int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); - if (fe < 0) - return (value); - ioctl(fe, FE_READ_UNCORRECTED_BLOCKS, &value); - close(fe); - - return (value); + return 0; } cString getApids(const cChannel *channelP) diff --git a/tools.h b/tools.h index d492e41..1d0793a 100644 --- a/tools.h +++ b/tools.h @@ -20,17 +20,14 @@ #define SATIP_DEVICE "SAT>IP" -cDvbDevice *getDvbDevice(cDevice* deviceP); +cString getFrontendInfo(cDevice *deviceP); +cString getFrontendName(cDevice *deviceP); +cString getFrontendStatus(cDevice *deviceP); -cString getFrontendInfo(cDvbDevice *deviceP); -cString getFrontendName(cDvbDevice *deviceP); -cString getFrontendStatus(cDvbDevice *deviceP); - -uint16_t getSNR(cDvbDevice *deviceP); -uint16_t getSignal(cDvbDevice *deviceP); - -uint32_t getBER(cDvbDevice *deviceP); -uint32_t getUNC(cDvbDevice *deviceP); +double getCNR(cDevice *deviceP); +double getSignal(cDevice *deviceP); +double getBER(cDevice *deviceP); +double getPER(cDevice *deviceP); cString getApids(const cChannel *channelP); cString getDpids(const cChannel *channelP);