Get rid of ioctls.

This commit is contained in:
Rolf Ahrenberg 2017-05-04 22:47:49 +03:00
parent c6546524cc
commit 6764e356e9
7 changed files with 185 additions and 269 deletions

11
README
View File

@ -34,15 +34,14 @@ Terminology:
|## Channel Name ################### [SVDRP][AR][VF][A/DD][D]| |## Channel Name ################### [SVDRP][AR][VF][A/DD][D]|
|[=====Signal Strength ===================|=================]| |[=====Signal Strength ===================|=================]|
|[=====Signal Quality ================|=====================]| |[=====Signal Quality ================|=====================]|
| STR: #0000 (0%) BER: #00000000 Video: 0 Mbit/s | | STR: 0 CNR: 0 BER: 0 PER: 0 Video: 0 Audio: 0 |
| SNR: #0000 (0%) UNC: #00000000 Audio: 0 kbit/s |
| [LOCK] [SIGNAL] [CARRIER] [VITERBI] [SYNC] | | [LOCK] [SIGNAL] [CARRIER] [VITERBI] [SYNC] |
-------------------------------------------------------------- --------------------------------------------------------------
STR - Signal strength from driver STR - Signal strength in dBm
SNR - Signal-to-noise ratio from driver CNR - Signal-to-noise ratio of the main carrier in dB
BER - Bit error rate BER - Bit error rate after the forward error correction (FEC) done by inner code block
UNC - Uncorrected blocks PER - Block error rate after the outer forward error correction coding
Video - Calculated video bitrate in Mbit/s Video - Calculated video bitrate in Mbit/s
Audio - Calculated audio / AC-3 bitrate in kbit/s Audio - Calculated audio / AC-3 bitrate in kbit/s

44
femon.c
View File

@ -17,8 +17,8 @@
#include "tools.h" #include "tools.h"
#include "setup.h" #include "setup.h"
#if defined(APIVERSNUM) && APIVERSNUM < 20302 #if defined(APIVERSNUM) && APIVERSNUM < 20305
#error "VDR-2.3.2 API version or greater is required!" #error "VDR-2.3.5 API version or greater is required!"
#endif #endif
#ifndef GITVERSION #ifndef GITVERSION
@ -173,18 +173,18 @@ bool cPluginFemon::SetupParse(const char *nameP, const char *valueP)
bool cPluginFemon::Service(const char *idP, void *dataP) bool cPluginFemon::Service(const char *idP, void *dataP)
{ {
if (strcmp(idP, "FemonService-v1.0") == 0) { if (strcmp(idP, "FemonService-v1.1") == 0) {
if (dataP) { if (dataP) {
FemonService_v1_0 *data = reinterpret_cast<FemonService_v1_0*>(dataP); FemonService_v1_1 *data = reinterpret_cast<FemonService_v1_1*>(dataP);
if (!cDevice::ActualDevice()) cDevice *dev = cDevice::ActualDevice();
if (!dev)
return false; return false;
cDvbDevice *dev = getDvbDevice(cDevice::ActualDevice());
data->fe_name = getFrontendName(dev); data->fe_name = getFrontendName(dev);
data->fe_status = getFrontendStatus(dev); data->fe_status = getFrontendStatus(dev);
data->fe_snr = getSNR(dev); data->fe_cnr = getCNR(dev);
data->fe_signal = getSignal(dev); data->fe_signal = getSignal(dev);
data->fe_ber = getBER(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->video_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetVideoBitrate() : 0.0;
data->audio_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetAudioBitrate() : 0.0; data->audio_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetAudioBitrate() : 0.0;
data->dolby_bitrate = cFemonOsd::Instance() ? cFemonOsd::Instance()->GetDolbyBitrate() : 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.", " Print the signal quality.",
"SGNL <card index>\n" "SGNL <card index>\n"
" Print the signal strength from driver.", " Print the signal strength from driver.",
"SNRA <card index>\n" "CNRA <card index>\n"
" Print the signal-to-noise ratio from driver.", " Print the carrier-to-noise ratio from driver.",
"BERA <card index>\n" "BERA <card index>\n"
" Print the bit error rate.", " Print the bit error rate from driver.",
"UNCB <card index>\n" "PERA <card index>\n"
" Print the uncorrected blocks rate.", " Print the packet error rate from driver.",
"VIBR\n" "VIBR\n"
" Print the current video bitrate [Mbit/s].", " Print the current video bitrate [Mbit/s].",
"AUBR\n" "AUBR\n"
@ -239,14 +239,14 @@ const char **cPluginFemon::SVDRPHelpPages(void)
cString cPluginFemon::SVDRPCommand(const char *commandP, const char *optionP, int &replyCodeP) 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 (strcasecmp(commandP, "TRAC") == 0) {
if (optionP && *optionP) if (optionP && *optionP)
FemonConfig.SetTraceMode(strtol(optionP, NULL, 0)); FemonConfig.SetTraceMode(strtol(optionP, NULL, 0));
return cString::sprintf("Tracing mode: 0x%04X\n", FemonConfig.GetTraceMode()); return cString::sprintf("Tracing mode: 0x%04X\n", FemonConfig.GetTraceMode());
} }
if (*optionP && isnumber(optionP)) { if (*optionP && isnumber(optionP)) {
cDvbDevice *dev2 = dynamic_cast<cDvbDevice*>(cDevice::GetDevice(int(strtol(optionP, NULL, 10)))); cDevice *dev2 = cDevice::GetDevice(int(strtol(optionP, NULL, 10)));
if (dev2) if (dev2)
dev = 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()); return cString::sprintf("%d on device #%d", dev->SignalQuality(), dev->CardIndex());
} }
else if (strcasecmp(commandP, "SGNL") == 0) { else if (strcasecmp(commandP, "SGNL") == 0) {
int value = getSignal(dev); return cString::sprintf("%.2f dBm on device #%d", getSignal(dev), dev->CardIndex());
return cString::sprintf("%04X (%02d%%) on device #%d", value, value / 655, dev->CardIndex());
} }
else if (strcasecmp(commandP, "SNRA") == 0) { else if (strcasecmp(commandP, "CNRA") == 0) {
int value = getSNR(dev); return cString::sprintf("%.2f dB on device #%d", getCNR(dev), dev->CardIndex());
return cString::sprintf("%04X (%02d%%) on device #%d", value, value / 655, dev->CardIndex());
} }
else if (strcasecmp(commandP, "BERA") == 0) { 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) { else if (strcasecmp(commandP, "PERA") == 0) {
return cString::sprintf("%08X on device #%d", getUNC(dev), dev->CardIndex()); return cString::sprintf("%.0f on device #%d", getPER(dev), dev->CardIndex());
} }
else if (strcasecmp(commandP, "VIBR") == 0) { else if (strcasecmp(commandP, "VIBR") == 0) {
if (cFemonOsd::Instance()) if (cFemonOsd::Instance())

View File

@ -8,15 +8,13 @@
#ifndef __FEMONSERVICE_H #ifndef __FEMONSERVICE_H
#define __FEMONSERVICE_H #define __FEMONSERVICE_H
#include <linux/dvb/frontend.h> struct FemonService_v1_1 {
struct FemonService_v1_0 {
cString fe_name; cString fe_name;
cString fe_status; cString fe_status;
uint16_t fe_snr; double fe_cnr;
uint16_t fe_signal; double fe_signal;
uint32_t fe_ber; double fe_ber;
uint32_t fe_unc; double fe_per;
double video_bitrate; double video_bitrate;
double audio_bitrate; double audio_bitrate;
double dolby_bitrate; double dolby_bitrate;

193
osd.c
View File

@ -27,7 +27,7 @@
#define OSDHEIGHT osdHeightM // in pixels #define OSDHEIGHT osdHeightM // in pixels
#define OSDROWHEIGHT fontM->Height() // in pixels #define OSDROWHEIGHT fontM->Height() // in pixels
#define OSDINFOHEIGHT (OSDROWHEIGHT * 14) // in pixels (14 rows) #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 OSDSYMBOL(id) femonSymbols.Get(id)
#define OSDSPACING femonSymbols.GetSpacing() #define OSDSPACING femonSymbols.GetSpacing()
#define OSDROUNDING femonSymbols.GetRounding() #define OSDROUNDING femonSymbols.GetRounding()
@ -39,12 +39,11 @@
(col == 2) ? int(round(OSDWIDTH * 0.26)) : \ (col == 2) ? int(round(OSDWIDTH * 0.26)) : \
int(round(OSDWIDTH * 0.025))) int(round(OSDWIDTH * 0.025)))
#define OSDSTATUSWIN_Y(offset) (FemonConfig.GetPosition() ? offset : (OSDHEIGHT - OSDSTATUSHEIGHT + offset)) #define OSDSTATUSWIN_Y(offset) (FemonConfig.GetPosition() ? offset : (OSDHEIGHT - OSDSTATUSHEIGHT + offset))
#define OSDSTATUSWIN_X(col) ((col == 7) ? int(round(OSDWIDTH * 0.79)) : \ #define OSDSTATUSWIN_X(col) ((col == 6) ? int(round(OSDWIDTH * 0.84)) : \
(col == 6) ? int(round(OSDWIDTH * 0.68)) : \ (col == 5) ? int(round(OSDWIDTH * 0.66)) : \
(col == 5) ? int(round(OSDWIDTH * 0.46)) : \ (col == 4) ? int(round(OSDWIDTH * 0.50)) : \
(col == 4) ? int(round(OSDWIDTH * 0.37)) : \ (col == 3) ? int(round(OSDWIDTH * 0.35)) : \
(col == 3) ? int(round(OSDWIDTH * 0.21)) : \ (col == 2) ? int(round(OSDWIDTH * 0.19)) : \
(col == 2) ? int(round(OSDWIDTH * 0.12)) : \
int(round(OSDWIDTH * 0.025))) int(round(OSDWIDTH * 0.025)))
#define OSDSTATUSWIN_XSYMBOL(c,w) (c * ((OSDWIDTH - (5 * w)) / 6) + ((c - 1) * w)) #define OSDSTATUSWIN_XSYMBOL(c,w) (c * ((OSDWIDTH - (5 * w)) / 6) + ((c - 1) * w))
#define OSDBARWIDTH(x) (OSDWIDTH * x / 100) #define OSDBARWIDTH(x) (OSDWIDTH * x / 100)
@ -60,14 +59,13 @@
#define OSDDRAWSTATUSFRONTEND(column, bitmap, status) \ #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) 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(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(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(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(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(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(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)
#define OSDDRAWSTATUSBAR(value) \ #define OSDDRAWSTATUSBAR(value) \
if (value > 0) { \ if (value > 0) { \
@ -168,7 +166,6 @@ cFemonOsd::cFemonOsd()
: cOsdObject(true), cThread("femon osd"), : cOsdObject(true), cThread("femon osd"),
osdM(NULL), osdM(NULL),
receiverM(NULL), receiverM(NULL),
frontendM(-1),
svdrpFrontendM(-1), svdrpFrontendM(-1),
svdrpVideoBitRateM(-1), svdrpVideoBitRateM(-1),
svdrpAudioBitRateM(-1), svdrpAudioBitRateM(-1),
@ -179,15 +176,17 @@ cFemonOsd::cFemonOsd()
qualityValidM(false), qualityValidM(false),
strengthM(0), strengthM(0),
strengthValidM(false), strengthValidM(false),
snrM(0), cnrM(0),
snrValidM(false), cnrValidM(false),
signalM(0), signalM(0),
signalValidM(false), signalValidM(false),
berM(0), berM(0),
berValidM(false), berValidM(false),
uncM(0), perM(0),
uncValidM(false), perValidM(false),
frontendNameM(""), frontendNameM(""),
frontendTypeM(""),
frontendStatusM(DTV_STAT_HAS_NONE),
frontendStatusValidM(false), frontendStatusValidM(false),
deviceSourceM(DEVICESOURCE_DVBAPI), deviceSourceM(DEVICESOURCE_DVBAPI),
displayModeM(FemonConfig.GetDisplayMode()), displayModeM(FemonConfig.GetDisplayMode()),
@ -201,8 +200,6 @@ cFemonOsd::cFemonOsd()
{ {
int tmp; int tmp;
debug1("%s", __PRETTY_FUNCTION__); debug1("%s", __PRETTY_FUNCTION__);
memset(&frontendStatusM, 0, sizeof(frontendStatusM));
memset(&frontendInfoM, 0, sizeof(frontendInfoM));
svdrpConnectionM.handle = -1; svdrpConnectionM.handle = -1;
femonSymbols.Refresh(); femonSymbols.Refresh();
fontM = cFont::CreateFont(Setup.FontSml, constrain(Setup.FontSmlSize, MINFONTSIZE, MAXFONTSIZE)); fontM = cFont::CreateFont(Setup.FontSml, constrain(Setup.FontSmlSize, MINFONTSIZE, MAXFONTSIZE));
@ -241,10 +238,6 @@ cFemonOsd::~cFemonOsd(void)
DELETENULL(osdM); DELETENULL(osdM);
if (fontM) if (fontM)
DELETENULL(fontM); DELETENULL(fontM);
if (frontendM >= 0) {
close(frontendM);
frontendM = -1;
}
pInstanceS = NULL; pInstanceS = NULL;
} }
@ -378,23 +371,22 @@ void cFemonOsd::DrawStatusWindow(void)
if (qualityValidM) if (qualityValidM)
OSDDRAWSTATUSBAR(qualityM); OSDDRAWSTATUSBAR(qualityM);
offset += OSDROWHEIGHT; offset += OSDROWHEIGHT;
OSDDRAWSTATUSVALUES("STR:", signalValidM ? *cString::sprintf("%04x", signalM) : "", signalValidM ? *cString::sprintf("(%2d%%)", signalM / 655) : "", OSDDRAWSTATUSVALUES(signalValidM ? *cString::sprintf("STR: %.2f dBm", signalM) : "STR: ---",
"BER:", berValidM ? *cString::sprintf("%08x", berM) : "", *cString::sprintf("%s:", tr("Video")), cnrValidM ? *cString::sprintf("CNR: %.2f dB", cnrM) : "CNR: ---",
*getBitrateMbits(receiverM ? receiverM->VideoBitrate() : (svdrpFrontendM >= 0 ? svdrpVideoBitRateM : -1.0))); berValidM ? *cString::sprintf("BER: %.0f", berM) : "BER: ---",
offset += OSDROWHEIGHT; perValidM ? *cString::sprintf("PER: %.0f", perM) : "PER: ---",
OSDDRAWSTATUSVALUES("SNR:", snrValidM ? *cString::sprintf("%04x", snrM) : "", snrValidM ? *cString::sprintf("(%2d%%)", snrM / 655) : "", *cString::sprintf("%s: %s", tr("Video"), *getBitrateMbits(receiverM ? receiverM->VideoBitrate() : (svdrpFrontendM >= 0 ? svdrpVideoBitRateM : -1.0))),
"UNC:", uncValidM ? *cString::sprintf("%08x", uncM) : "", *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)))
*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)));
offset += OSDROWHEIGHT; offset += OSDROWHEIGHT;
x = OSDSYMBOL(SYMBOL_LOCK).Width(); x = OSDSYMBOL(SYMBOL_LOCK).Width();
y = (OSDROWHEIGHT - OSDSYMBOL(SYMBOL_LOCK).Height()) / 2; y = (OSDROWHEIGHT - OSDSYMBOL(SYMBOL_LOCK).Height()) / 2;
if (frontendStatusValidM) { if (frontendStatusValidM) {
OSDDRAWSTATUSFRONTEND(1, OSDSYMBOL(SYMBOL_LOCK), FE_HAS_LOCK); OSDDRAWSTATUSFRONTEND(1, OSDSYMBOL(SYMBOL_LOCK), DTV_STAT_HAS_LOCK);
OSDDRAWSTATUSFRONTEND(2, OSDSYMBOL(SYMBOL_SIGNAL), FE_HAS_SIGNAL); OSDDRAWSTATUSFRONTEND(2, OSDSYMBOL(SYMBOL_SIGNAL), DTV_STAT_HAS_SIGNAL);
OSDDRAWSTATUSFRONTEND(3, OSDSYMBOL(SYMBOL_CARRIER), FE_HAS_CARRIER); OSDDRAWSTATUSFRONTEND(3, OSDSYMBOL(SYMBOL_CARRIER), DTV_STAT_HAS_CARRIER);
OSDDRAWSTATUSFRONTEND(4, OSDSYMBOL(SYMBOL_VITERBI), FE_HAS_VITERBI); OSDDRAWSTATUSFRONTEND(4, OSDSYMBOL(SYMBOL_VITERBI), DTV_STAT_HAS_VITERBI);
OSDDRAWSTATUSFRONTEND(5, OSDSYMBOL(SYMBOL_SYNC), FE_HAS_SYNC); OSDDRAWSTATUSFRONTEND(5, OSDSYMBOL(SYMBOL_SYNC), DTV_STAT_HAS_SYNC);
} }
OSDDRAWSTATUSBOTTOMBAR(); OSDDRAWSTATUSBOTTOMBAR();
osdM->Flush(); osdM->Flush();
@ -601,16 +593,16 @@ void cFemonOsd::Action(void)
strengthM = cDevice::ActualDevice()->SignalStrength(); strengthM = cDevice::ActualDevice()->SignalStrength();
strengthValidM = (strengthM >= 0); strengthValidM = (strengthM >= 0);
frontendNameM = cDevice::ActualDevice()->DeviceName(); 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; frontendStatusValidM = strengthValidM;
signalM = uint16_t(strengthM * 0xFFFF / 100); signalM = strengthM;
signalValidM = strengthValidM; signalValidM = strengthValidM;
snrM = 0; cnrM = 0;
snrValidM = false; cnrValidM = false;
berM = 0; berM = 0;
berValidM = false; berValidM = false;
uncM = 0; perM = 0;
uncValidM = false; perValidM = false;
break; break;
case DEVICESOURCE_IPTV: case DEVICESOURCE_IPTV:
qualityM = cDevice::ActualDevice()->SignalQuality(); qualityM = cDevice::ActualDevice()->SignalQuality();
@ -618,49 +610,20 @@ void cFemonOsd::Action(void)
strengthM = cDevice::ActualDevice()->SignalStrength(); strengthM = cDevice::ActualDevice()->SignalStrength();
strengthValidM = (strengthM >= 0); strengthValidM = (strengthM >= 0);
frontendNameM = cDevice::ActualDevice()->DeviceName(); 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; frontendStatusValidM = strengthValidM;
signalM = uint16_t(strengthM * 0xFFFF / 100); signalM = strengthM;
signalValidM = strengthValidM; signalValidM = strengthValidM;
snrM = uint16_t(qualityM * 0xFFFF / 100); cnrM = qualityM;
snrValidM = qualityValidM; cnrValidM = qualityValidM;
berM = 0; berM = 0;
berValidM = false; berValidM = false;
uncM = 0; perM = 0;
uncValidM = false; perValidM = false;
break; break;
default: default:
case DEVICESOURCE_DVBAPI: case DEVICESOURCE_DVBAPI:
if (frontendM != -1) { if (svdrpConnectionM.handle >= 0) {
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) {
cmd.handle = svdrpConnectionM.handle; cmd.handle = svdrpConnectionM.handle;
svdrpPluginM->Service("SvdrpCommand-v1.0", &cmd); svdrpPluginM->Service("SvdrpCommand-v1.0", &cmd);
if (cmd.responseCode == 900) { if (cmd.responseCode == 900) {
@ -668,9 +631,9 @@ void cFemonOsd::Action(void)
qualityValidM = false; qualityValidM = false;
frontendStatusValidM = false; frontendStatusValidM = false;
signalValidM = false; signalValidM = false;
snrValidM = false; cnrValidM = false;
berValidM = false; berValidM = false;
uncValidM = false; perValidM = false;
for (cLine *line = cmd.reply.First(); line; line = cmd.reply.Next(line)) { for (cLine *line = cmd.reply.First(); line; line = cmd.reply.Next(line)) {
const char *s = line->Text(); const char *s = line->Text();
if (!strncasecmp(s, "CARD:", 5)) if (!strncasecmp(s, "CARD:", 5))
@ -683,38 +646,61 @@ void cFemonOsd::Action(void)
qualityM = (int)strtol(s + 5, NULL, 10); qualityM = (int)strtol(s + 5, NULL, 10);
qualityValidM = (qualityM >= 0); qualityValidM = (qualityM >= 0);
} }
else if (!strncasecmp(s, "TYPE:", 5)) else if (!strncasecmp(s, "TYPE:", 5)) {
frontendInfoM.type = (fe_type_t)strtol(s + 5, NULL, 10); frontendTypeM = s + 5;
}
else if (!strncasecmp(s, "NAME:", 5)) { else if (!strncasecmp(s, "NAME:", 5)) {
frontendNameM = s + 5; frontendNameM = s + 5;
} }
else if (!strncasecmp(s, "STAT:", 5)) { else if (!strncasecmp(s, "STAT:", 5)) {
frontendStatusM = (fe_status_t)strtol(s + 5, NULL, 16); frontendStatusM = strtol(s + 5, NULL, 16);
frontendStatusValidM = true; frontendStatusValidM = true;
} }
else if (!strncasecmp(s, "SGNL:", 5)) { else if (!strncasecmp(s, "SGNL:", 5)) {
signalM = (uint16_t)strtol(s + 5, NULL, 16); signalM = atod(s + 5);
signalValidM = true; signalValidM = true;
} }
else if (!strncasecmp(s, "SNRA:", 5)) { else if (!strncasecmp(s, "CNRA:", 5)) {
snrM = (uint16_t)strtol(s + 5, NULL, 16); cnrM = atod(s + 5);
snrValidM = true; cnrValidM = true;
} }
else if (!strncasecmp(s, "BERA:", 5)) { else if (!strncasecmp(s, "BERA:", 5)) {
berM = (uint32_t)strtol(s + 5, NULL, 16); berM = atod(s + 5);
berValidM = true; berValidM = true;
} }
else if (!strncasecmp(s, "UNCB:", 5)) { else if (!strncasecmp(s, "PERA:", 5)) {
uncM = (uint32_t)strtol(s + 5, NULL, 16); perM = atod(s + 5);
uncValidM = true; perValidM = true;
} }
else if (!strncasecmp(s, "VIBR:", 5)) else if (!strncasecmp(s, "VIBR:", 5))
svdrpVideoBitRateM = (double)strtol(s + 5, NULL, 10); svdrpVideoBitRateM = atod(s + 5);
else if (!strncasecmp(s, "AUBR:", 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; break;
} }
DrawInfoWindow(); DrawInfoWindow();
@ -765,11 +751,6 @@ bool cFemonOsd::AttachFrontend(void)
LOCK_CHANNELS_READ; LOCK_CHANNELS_READ;
const cChannel *channel = Channels->GetByNumber(cDevice::CurrentChannel()); const cChannel *channel = Channels->GetByNumber(cDevice::CurrentChannel());
if (frontendM >= 0) {
close(frontendM);
frontendM = -1;
}
deviceSourceM = DEVICESOURCE_DVBAPI; deviceSourceM = DEVICESOURCE_DVBAPI;
if (channel) { if (channel) {
if (channel->IsSourceType('I')) if (channel->IsSourceType('I'))
@ -780,30 +761,12 @@ bool cFemonOsd::AttachFrontend(void)
if (deviceSourceM == DEVICESOURCE_DVBAPI) { if (deviceSourceM == DEVICESOURCE_DVBAPI) {
if (!strstr(*cDevice::ActualDevice()->DeviceType(), SATIP_DEVICE)) { if (!strstr(*cDevice::ActualDevice()->DeviceType(), SATIP_DEVICE)) {
cDvbDevice *dev = getDvbDevice(cDevice::ActualDevice()); if (FemonConfig.GetUseSvdrp()) {
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 (!SvdrpConnect() || !SvdrpTune()) if (!SvdrpConnect() || !SvdrpTune())
return false; return false;
} }
else {
error("%s Cannot open frontend device", __PRETTY_FUNCTION__);
return false;
}
} }
} }
else
frontendM = -1;
return true; return true;
} }

18
osd.h
View File

@ -8,9 +8,7 @@
#ifndef __FEMON_OSD_H #ifndef __FEMON_OSD_H
#define __FEMON_OSD_H #define __FEMON_OSD_H
#include <linux/dvb/frontend.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/ioctl.h>
#include <vdr/osd.h> #include <vdr/osd.h>
#include <vdr/thread.h> #include <vdr/thread.h>
#include <vdr/status.h> #include <vdr/status.h>
@ -37,7 +35,6 @@ private:
cOsd *osdM; cOsd *osdM;
cFemonReceiver *receiverM; cFemonReceiver *receiverM;
int frontendM;
int svdrpFrontendM; int svdrpFrontendM;
double svdrpVideoBitRateM; double svdrpVideoBitRateM;
double svdrpAudioBitRateM; double svdrpAudioBitRateM;
@ -49,16 +46,17 @@ private:
bool qualityValidM; bool qualityValidM;
int strengthM; int strengthM;
bool strengthValidM; bool strengthValidM;
uint16_t snrM; double cnrM;
bool snrValidM; bool cnrValidM;
uint16_t signalM; double signalM;
bool signalValidM; bool signalValidM;
uint32_t berM; double berM;
bool berValidM; bool berValidM;
uint32_t uncM; double perM;
bool uncValidM; bool perValidM;
cString frontendNameM; cString frontendNameM;
fe_status_t frontendStatusM; cString frontendTypeM;
int frontendStatusM;
bool frontendStatusValidM; bool frontendStatusValidM;
dvb_frontend_info frontendInfoM; dvb_frontend_info frontendInfoM;
eDeviceSourceType deviceSourceM; eDeviceSourceType deviceSourceM;

159
tools.c
View File

@ -13,8 +13,6 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <sys/ioctl.h>
#include <linux/dvb/frontend.h>
#include "osd.h" #include "osd.h"
#include "receiver.h" #include "receiver.h"
@ -91,61 +89,42 @@ static const char *getUserString(int valueP, const tDvbParameterMap *mapP)
return "---"; return "---";
} }
cDvbDevice *getDvbDevice(cDevice* deviceP) cString getFrontendInfo(cDevice *deviceP)
{ {
cDvbDevice *dev = dynamic_cast<cDvbDevice*>(deviceP); const cChannel *channel;
#ifdef __DYNAMIC_DEVICE_PROBE int status, valid = DTV_STAT_VALID_NONE;
if (!dev && deviceP && deviceP->HasSubDevice())
dev = dynamic_cast<cDvbDevice*>(deviceP->SubDevice());
#endif
return dev;
}
cString getFrontendInfo(cDvbDevice *deviceP)
{
struct dvb_frontend_info value;
fe_status_t status;
cString info = ""; cString info = "";
uint16_t signal = 0; double signal = 0, cnr = 0, ber = 0, per = 0;
uint16_t snr = 0;
uint32_t ber = 0;
uint32_t unc = 0;
LOCK_CHANNELS_READ;
const cChannel *channel = Channels->GetByNumber(cDevice::CurrentChannel());
if (!deviceP) if (!deviceP)
return info; return info;
int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); info = cString::sprintf("CARD:%d\nSTRG:%d\nQUAL:%d\nTYPE:%s\nNAME:%s", deviceP->CardIndex(), deviceP->SignalStrength(), deviceP->SignalQuality(), *deviceP->DeviceType(), *deviceP->DeviceName());
if (fe < 0) if (deviceP && deviceP->SignalStats(valid, &signal, &cnr, NULL, &ber, &per, &status)) {
return info; if (valid & DTV_STAT_VALID_STATUS)
info = cString::sprintf("%s\nSTAT:%04X", *info, status);
info = cString::sprintf("CARD:%d\nSTRG:%d\nQUAL:%d", deviceP->CardIndex(), deviceP->SignalStrength(), deviceP->SignalQuality()); if (valid & DTV_STAT_VALID_STRENGTH)
info = cString::sprintf("%s\nSGNL:%s", *info, *dtoa(signal, "%.2f"));
if (ioctl(fe, FE_GET_INFO, &value) >= 0) if (valid & DTV_STAT_VALID_CNR)
info = cString::sprintf("%s\nTYPE:%d\nNAME:%s", *info, value.type, *deviceP->DeviceName()); info = cString::sprintf("%s\nCNRA:%s", *info, *dtoa(cnr, "%.2f"));
if (ioctl(fe, FE_READ_STATUS, &status) >= 0) if (valid & DTV_STAT_VALID_BERPOST)
info = cString::sprintf("%s\nSTAT:%02X", *info, status); info = cString::sprintf("%s\nBERA:%s", *info, *dtoa(ber, "%.0f"));
if (ioctl(fe, FE_READ_SIGNAL_STRENGTH, &signal) >= 0) if (valid & DTV_STAT_VALID_PER)
info = cString::sprintf("%s\nSGNL:%04X", *info, signal); info = cString::sprintf("%s\nPERA:%s", *info, *dtoa(per, "%.0f"));
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);
if (cFemonOsd::Instance()) 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) if (channel)
info = cString::sprintf("%s\nCHAN:%s", *info, *channel->ToText()); info = cString::sprintf("%s\nCHAN:%s", *info, *channel->ToText());
return info; return info;
} }
cString getFrontendName(cDvbDevice *deviceP) cString getFrontendName(cDevice *deviceP)
{ {
if (!deviceP) if (!deviceP)
return NULL; return NULL;
@ -153,85 +132,69 @@ cString getFrontendName(cDvbDevice *deviceP)
return (cString::sprintf("%s on deviceP #%d", *deviceP->DeviceName(), deviceP->CardIndex())); 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) if (deviceP && deviceP->SignalStats(valid, NULL, NULL, NULL, NULL, NULL, &status)) {
return NULL; 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); return NULL;
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()));
} }
uint16_t getSignal(cDvbDevice *deviceP) double getSignal(cDevice *deviceP)
{ {
uint16_t value = 0; double strength;
int valid = DTV_STAT_VALID_NONE;
if (!deviceP) if (deviceP && deviceP->SignalStats(valid, &strength, NULL, NULL, NULL, NULL, NULL)) {
return (value); if (valid & DTV_STAT_VALID_STRENGTH)
return strength;
}
int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); return 0;
if (fe < 0)
return (value);
ioctl(fe, FE_READ_SIGNAL_STRENGTH, &value);
close(fe);
return (value);
} }
uint16_t getSNR(cDvbDevice *deviceP) double getCNR(cDevice *deviceP)
{ {
uint16_t value = 0; double cnr;
int valid = DTV_STAT_VALID_NONE;
if (!deviceP) if (deviceP && deviceP->SignalStats(valid, NULL, &cnr, NULL, NULL, NULL, NULL)) {
return (value); if (valid & DTV_STAT_VALID_CNR)
return cnr;
}
int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); return 0;
if (fe < 0)
return (value);
ioctl(fe, FE_READ_SNR, &value);
close(fe);
return (value);
} }
uint32_t getBER(cDvbDevice *deviceP) double getBER(cDevice *deviceP)
{ {
uint32_t value = 0; double ber;
int valid = DTV_STAT_VALID_NONE;
if (!deviceP) if (deviceP && deviceP->SignalStats(valid, NULL, NULL, NULL, &ber, NULL, NULL)) {
return (value); if (valid & DTV_STAT_VALID_BERPOST)
return ber;
}
int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); return 0;
if (fe < 0)
return (value);
ioctl(fe, FE_READ_BER, &value);
close(fe);
return (value);
} }
uint32_t getUNC(cDvbDevice *deviceP) double getPER(cDevice *deviceP)
{ {
uint32_t value = 0; double per;
int valid = DTV_STAT_VALID_NONE;
if (!deviceP) if (deviceP && deviceP->SignalStats(valid, NULL, NULL, NULL, NULL, &per, NULL)) {
return (value); if (valid & DTV_STAT_VALID_PER)
return per;
}
int fe = open(*cString::sprintf(FRONTEND_DEVICE, deviceP->Adapter(), deviceP->Frontend()), O_RDONLY | O_NONBLOCK); return 0;
if (fe < 0)
return (value);
ioctl(fe, FE_READ_UNCORRECTED_BLOCKS, &value);
close(fe);
return (value);
} }
cString getApids(const cChannel *channelP) cString getApids(const cChannel *channelP)

17
tools.h
View File

@ -20,17 +20,14 @@
#define SATIP_DEVICE "SAT>IP" #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); double getCNR(cDevice *deviceP);
cString getFrontendName(cDvbDevice *deviceP); double getSignal(cDevice *deviceP);
cString getFrontendStatus(cDvbDevice *deviceP); double getBER(cDevice *deviceP);
double getPER(cDevice *deviceP);
uint16_t getSNR(cDvbDevice *deviceP);
uint16_t getSignal(cDvbDevice *deviceP);
uint32_t getBER(cDvbDevice *deviceP);
uint32_t getUNC(cDvbDevice *deviceP);
cString getApids(const cChannel *channelP); cString getApids(const cChannel *channelP);
cString getDpids(const cChannel *channelP); cString getDpids(const cChannel *channelP);