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]|
|[=====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

44
femon.c
View File

@ -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<FemonService_v1_0*>(dataP);
if (!cDevice::ActualDevice())
FemonService_v1_1 *data = reinterpret_cast<FemonService_v1_1*>(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 <card index>\n"
" Print the signal strength from driver.",
"SNRA <card index>\n"
" Print the signal-to-noise ratio from driver.",
"CNRA <card index>\n"
" Print the carrier-to-noise ratio from driver.",
"BERA <card index>\n"
" Print the bit error rate.",
"UNCB <card index>\n"
" Print the uncorrected blocks rate.",
" Print the bit error rate from driver.",
"PERA <card index>\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<cDvbDevice*>(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())

View File

@ -8,15 +8,13 @@
#ifndef __FEMONSERVICE_H
#define __FEMONSERVICE_H
#include <linux/dvb/frontend.h>
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;

193
osd.c
View File

@ -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;
}

18
osd.h
View File

@ -8,9 +8,7 @@
#ifndef __FEMON_OSD_H
#define __FEMON_OSD_H
#include <linux/dvb/frontend.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <vdr/osd.h>
#include <vdr/thread.h>
#include <vdr/status.h>
@ -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;

159
tools.c
View File

@ -13,8 +13,6 @@
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/dvb/frontend.h>
#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<cDvbDevice*>(deviceP);
#ifdef __DYNAMIC_DEVICE_PROBE
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;
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)

17
tools.h
View File

@ -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);