mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Implemented signal strength and quality handling
This commit is contained in:
parent
40278ec121
commit
e572cbda47
@ -1104,6 +1104,7 @@ Rolf Ahrenberg <rahrenbe@cc.hut.fi>
|
||||
for adding support for "registration descriptor" to 'libsi' and using it in pat.c
|
||||
for adding an include of VDR's 'Make.global' to libsi's Makefile
|
||||
for adding handling of "ANSI/SCTE 57" descriptors
|
||||
for some input on how to use BER and UNC values to generate a "quality" value
|
||||
|
||||
Ralf Klueber <ralf.klueber@vodafone.com>
|
||||
for reporting a bug in cutting a recording if there is only a single editing mark
|
||||
|
10
HISTORY
10
HISTORY
@ -6607,7 +6607,7 @@ Video Disk Recorder Revision History
|
||||
- Avoiding an unecessary call to Recordings.ResetResume() (thanks to Reinhard
|
||||
Nissl).
|
||||
|
||||
2011-05-22: Version 1.7.19
|
||||
2011-06-02: Version 1.7.19
|
||||
|
||||
- Fixed cString's operator=(const char *String) in case the given string is the
|
||||
same as the existing one (thanks to Dirk Leber).
|
||||
@ -6624,3 +6624,11 @@ Video Disk Recorder Revision History
|
||||
- Fixed a possible race condition in cDiseqc::Execute() (reported by Marco Göbenich).
|
||||
The return value of cDiseqcs::Get() is now const, so plugin authors may need to
|
||||
adjust their code if they use this function.
|
||||
- The new functions cDevice::SignalStrength() and cDevice::SignalQuality() can be
|
||||
used to determine the signal strength and quality of a given device (thanks to
|
||||
Rolf Ahrenberg for some input on how to use BER and UNC values to generate a
|
||||
"quality" value).
|
||||
- The 'sttng' skin now displays two colored bars at the bottom of the channel display,
|
||||
indicating the strength (upper bar) and quality (lower bar) of the received signal.
|
||||
The number to the left of these bars indicates the actual device the current
|
||||
channel is being received with.
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* See the README file for copyright information and how to reach the author.
|
||||
*
|
||||
* $Id: dvbsdffdevice.c 2.28 2011/05/21 13:24:35 kls Exp $
|
||||
* $Id: dvbsdffdevice.c 2.29 2011/05/22 15:22:14 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbsdffdevice.h"
|
||||
@ -777,22 +777,7 @@ bool cDvbSdFfDeviceProbe::Probe(int Adapter, int Frontend)
|
||||
0x13C21002, // Technotrend/Hauppauge WinTV DVB-S rev1.3 SE
|
||||
0x00000000
|
||||
};
|
||||
cString FileName;
|
||||
cReadLine ReadLine;
|
||||
FILE *f = NULL;
|
||||
uint32_t SubsystemId = 0;
|
||||
FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_vendor", Adapter, Frontend);
|
||||
if ((f = fopen(FileName, "r")) != NULL) {
|
||||
if (char *s = ReadLine.Read(f))
|
||||
SubsystemId = strtoul(s, NULL, 0) << 16;
|
||||
fclose(f);
|
||||
}
|
||||
FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_device", Adapter, Frontend);
|
||||
if ((f = fopen(FileName, "r")) != NULL) {
|
||||
if (char *s = ReadLine.Read(f))
|
||||
SubsystemId |= strtoul(s, NULL, 0);
|
||||
fclose(f);
|
||||
}
|
||||
uint32_t SubsystemId = GetSubsystemId(Adapter, Frontend);
|
||||
for (uint32_t *sid = SubsystemIds; *sid; sid++) {
|
||||
if (*sid == SubsystemId) {
|
||||
dsyslog("creating cDvbSdFfDevice");
|
||||
|
12
device.c
12
device.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.c 2.40 2011/05/22 09:42:57 kls Exp $
|
||||
* $Id: device.c 2.41 2011/06/02 13:14:16 kls Exp $
|
||||
*/
|
||||
|
||||
#include "device.h"
|
||||
@ -618,6 +618,16 @@ int cDevice::NumProvidedSystems(void) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cDevice::SignalStrength(void) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cDevice::SignalQuality(void) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
const cChannel *cDevice::GetCurrentlyTunedTransponder(void) const
|
||||
{
|
||||
return NULL;
|
||||
|
12
device.h
12
device.h
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: device.h 2.25 2011/05/21 12:54:43 kls Exp $
|
||||
* $Id: device.h 2.26 2011/06/02 13:15:31 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DEVICE_H
|
||||
@ -253,6 +253,16 @@ public:
|
||||
///< actually provide channels must implement this function.
|
||||
///< The result of this function is used when selecting a device, in order
|
||||
///< to avoid devices that provide more than one system.
|
||||
virtual int SignalStrength(void) const;
|
||||
///< Returns the "strength" of the currently received signal.
|
||||
///< This is a value in the range 0 (no signal at all) through
|
||||
///< 100 (best possible signal). A value of -1 indicates that this
|
||||
///< device has no concept of a "signal strength".
|
||||
virtual int SignalQuality(void) const;
|
||||
///< Returns the "quality" of the currently received signal.
|
||||
///< This is a value in the range 0 (worst quality) through
|
||||
///< 100 (best possible quality). A value of -1 indicates that this
|
||||
///< device has no concept of a "signal quality".
|
||||
virtual const cChannel *GetCurrentlyTunedTransponder(void) const;
|
||||
///< Returns a pointer to the currently tuned transponder.
|
||||
///< This is not one of the channels in the global cChannels list, but rather
|
||||
|
175
dvbdevice.c
175
dvbdevice.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.c 2.39 2011/05/22 10:34:49 kls Exp $
|
||||
* $Id: dvbdevice.c 2.40 2011/06/02 13:28:42 kls Exp $
|
||||
*/
|
||||
|
||||
#include "dvbdevice.h"
|
||||
@ -253,12 +253,15 @@ bool cDvbTransponderParameters::Parse(const char *s)
|
||||
|
||||
// --- cDvbTuner -------------------------------------------------------------
|
||||
|
||||
#define TUNER_POLL_TIMEOUT 10 // ms
|
||||
|
||||
class cDvbTuner : public cThread {
|
||||
private:
|
||||
enum eTunerStatus { tsIdle, tsSet, tsTuned, tsLocked };
|
||||
int device;
|
||||
int fd_frontend;
|
||||
int adapter, frontend;
|
||||
uint32_t subsystemId;
|
||||
int tuneTimeout;
|
||||
int lockTimeout;
|
||||
time_t lastTimeoutReport;
|
||||
@ -269,16 +272,20 @@ private:
|
||||
cMutex mutex;
|
||||
cCondVar locked;
|
||||
cCondVar newSet;
|
||||
bool GetFrontendStatus(fe_status_t &Status, int TimeoutMs = 0);
|
||||
void ClearEventQueue(void) const;
|
||||
bool GetFrontendStatus(fe_status_t &Status) const;
|
||||
bool SetFrontend(void);
|
||||
virtual void Action(void);
|
||||
public:
|
||||
cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_delivery_system FrontendType);
|
||||
virtual ~cDvbTuner();
|
||||
const cChannel *GetTransponder(void) const { return &channel; }
|
||||
uint32_t SubsystemId(void) const { return subsystemId; }
|
||||
bool IsTunedTo(const cChannel *Channel) const;
|
||||
void Set(const cChannel *Channel);
|
||||
bool Locked(int TimeoutMs = 0);
|
||||
int GetSignalStrength(void) const;
|
||||
int GetSignalQuality(void) const;
|
||||
};
|
||||
|
||||
cDvbTuner::cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_delivery_system FrontendType)
|
||||
@ -288,6 +295,7 @@ cDvbTuner::cDvbTuner(int Device, int Fd_Frontend, int Adapter, int Frontend, fe_
|
||||
adapter = Adapter;
|
||||
frontend = Frontend;
|
||||
frontendType = FrontendType;
|
||||
subsystemId = cDvbDeviceProbe::GetSubsystemId(adapter, frontend);
|
||||
tuneTimeout = 0;
|
||||
lockTimeout = 0;
|
||||
lastTimeoutReport = 0;
|
||||
@ -339,16 +347,19 @@ bool cDvbTuner::Locked(int TimeoutMs)
|
||||
return tunerStatus >= tsLocked;
|
||||
}
|
||||
|
||||
bool cDvbTuner::GetFrontendStatus(fe_status_t &Status, int TimeoutMs)
|
||||
void cDvbTuner::ClearEventQueue(void) const
|
||||
{
|
||||
if (TimeoutMs) {
|
||||
cPoller Poller(fd_frontend);
|
||||
if (Poller.Poll(TimeoutMs)) {
|
||||
dvb_frontend_event Event;
|
||||
while (ioctl(fd_frontend, FE_GET_EVENT, &Event) == 0)
|
||||
; // just to clear the event queue - we'll read the actual status below
|
||||
}
|
||||
cPoller Poller(fd_frontend);
|
||||
if (Poller.Poll(TUNER_POLL_TIMEOUT)) {
|
||||
dvb_frontend_event Event;
|
||||
while (ioctl(fd_frontend, FE_GET_EVENT, &Event) == 0)
|
||||
; // just to clear the event queue - we'll read the actual status below
|
||||
}
|
||||
}
|
||||
|
||||
bool cDvbTuner::GetFrontendStatus(fe_status_t &Status) const
|
||||
{
|
||||
ClearEventQueue();
|
||||
while (1) {
|
||||
if (ioctl(fd_frontend, FE_READ_STATUS, &Status) != -1)
|
||||
return true;
|
||||
@ -358,6 +369,104 @@ bool cDvbTuner::GetFrontendStatus(fe_status_t &Status, int TimeoutMs)
|
||||
return false;
|
||||
}
|
||||
|
||||
//#define DEBUG_SIGNALSTRENGTH
|
||||
//#define DEBUG_SIGNALQUALITY
|
||||
|
||||
int cDvbTuner::GetSignalStrength(void) const
|
||||
{
|
||||
ClearEventQueue();
|
||||
uint16_t Signal;
|
||||
while (1) {
|
||||
if (ioctl(fd_frontend, FE_READ_SIGNAL_STRENGTH, &Signal) != -1)
|
||||
break;
|
||||
if (errno != EINTR)
|
||||
return -1;
|
||||
}
|
||||
uint16_t MaxSignal = 0xFFFF; // Let's assume the default is using the entire range.
|
||||
// Use the subsystemId to identify individual devices in case they need
|
||||
// special treatment to map their Signal value into the range 0...0xFFFF.
|
||||
int s = int(Signal) * 100 / MaxSignal;
|
||||
if (s > 100)
|
||||
s = 100;
|
||||
#ifdef DEBUG_SIGNALSTRENGTH
|
||||
fprintf(stderr, "FE %d/%d: %08X S = %04X %04X %3d%%\n", adapter, frontend, subsystemId, MaxSignal, Signal, s);
|
||||
#endif
|
||||
return s;
|
||||
}
|
||||
|
||||
#define LOCK_THRESHOLD 10
|
||||
|
||||
int cDvbTuner::GetSignalQuality(void) const
|
||||
{
|
||||
fe_status_t Status;
|
||||
if (GetFrontendStatus(Status)) {
|
||||
if ((Status & FE_HAS_SIGNAL) == 0)
|
||||
return 0;
|
||||
if ((Status & FE_HAS_CARRIER) == 0)
|
||||
return LOCK_THRESHOLD / 4;
|
||||
if ((Status & FE_HAS_VITERBI) == 0)
|
||||
return LOCK_THRESHOLD / 3;
|
||||
if ((Status & FE_HAS_SYNC) == 0)
|
||||
return LOCK_THRESHOLD / 2;
|
||||
if ((Status & FE_HAS_LOCK) == 0)
|
||||
return LOCK_THRESHOLD;
|
||||
bool HasSnr = true;
|
||||
uint16_t Snr;
|
||||
while (1) {
|
||||
if (ioctl(fd_frontend, FE_READ_SNR, &Snr) != -1)
|
||||
break;
|
||||
if (errno == EOPNOTSUPP) {
|
||||
Snr = 0xFFFF;
|
||||
HasSnr = false;
|
||||
break;
|
||||
}
|
||||
if (errno != EINTR)
|
||||
return -1;
|
||||
}
|
||||
bool HasBer = true;
|
||||
uint32_t Ber;
|
||||
while (1) {
|
||||
if (ioctl(fd_frontend, FE_READ_BER, &Ber) != -1)
|
||||
break;
|
||||
if (errno == EOPNOTSUPP) {
|
||||
Ber = 0;
|
||||
HasBer = false;
|
||||
break;
|
||||
}
|
||||
if (errno != EINTR)
|
||||
return -1;
|
||||
}
|
||||
bool HasUnc = true;
|
||||
uint32_t Unc;
|
||||
while (1) {
|
||||
if (ioctl(fd_frontend, FE_READ_UNCORRECTED_BLOCKS, &Unc) != -1)
|
||||
break;
|
||||
if (errno == EOPNOTSUPP) {
|
||||
Unc = 0;
|
||||
HasUnc = false;
|
||||
break;
|
||||
}
|
||||
if (errno != EINTR)
|
||||
return -1;
|
||||
}
|
||||
uint16_t MaxSnr = 0xFFFF; // Let's assume the default is using the entire range.
|
||||
// Use the subsystemId to identify individual devices in case they need
|
||||
// special treatment to map their Snr value into the range 0...0xFFFF.
|
||||
int a = int(Snr) * 100 / MaxSnr;
|
||||
int b = 100 - (Unc * 10 + (Ber / 256) * 5);
|
||||
if (b < 0)
|
||||
b = 0;
|
||||
int q = LOCK_THRESHOLD + a * b * (100 - LOCK_THRESHOLD) / 100 / 100;
|
||||
if (q > 100)
|
||||
q = 100;
|
||||
#ifdef DEBUG_SIGNALQUALITY
|
||||
fprintf(stderr, "FE %d/%d: %08X Q = %04X %04X %5d %5d %3d%%\n", adapter, frontend, subsystemId, MaxSnr, Snr, HasBer ? int(Ber) : -1, HasUnc ? int(Unc) : -1, q);
|
||||
#endif
|
||||
return q;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static unsigned int FrequencyToHz(unsigned int f)
|
||||
{
|
||||
while (f && f < 1000000)
|
||||
@ -504,9 +613,9 @@ bool cDvbTuner::SetFrontend(void)
|
||||
SETCMD(DTV_FREQUENCY, FrequencyToHz(channel.Frequency()));
|
||||
SETCMD(DTV_INVERSION, dtp.Inversion());
|
||||
SETCMD(DTV_MODULATION, dtp.Modulation());
|
||||
|
||||
|
||||
tuneTimeout = ATSC_TUNE_TIMEOUT;
|
||||
lockTimeout = ATSC_LOCK_TIMEOUT;
|
||||
lockTimeout = ATSC_LOCK_TIMEOUT;
|
||||
}
|
||||
else {
|
||||
esyslog("ERROR: attempt to set channel with unknown DVB frontend type");
|
||||
@ -527,7 +636,7 @@ void cDvbTuner::Action(void)
|
||||
fe_status_t Status = (fe_status_t)0;
|
||||
while (Running()) {
|
||||
fe_status_t NewStatus;
|
||||
if (GetFrontendStatus(NewStatus, 10))
|
||||
if (GetFrontendStatus(NewStatus))
|
||||
Status = NewStatus;
|
||||
cMutexLock MutexLock(&mutex);
|
||||
switch (tunerStatus) {
|
||||
@ -936,7 +1045,7 @@ bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *Ne
|
||||
bool hasPriority = Priority < 0 || Priority > this->Priority();
|
||||
bool needsDetachReceivers = false;
|
||||
|
||||
if (ProvidesTransponder(Channel)) {
|
||||
if (dvbTuner && ProvidesTransponder(Channel)) {
|
||||
result = hasPriority;
|
||||
if (Priority >= 0 && Receiving(true)) {
|
||||
if (dvbTuner->IsTunedTo(Channel)) {
|
||||
@ -969,19 +1078,30 @@ int cDvbDevice::NumProvidedSystems(void) const
|
||||
return numProvidedSystems;
|
||||
}
|
||||
|
||||
int cDvbDevice::SignalStrength(void) const
|
||||
{
|
||||
return dvbTuner ? dvbTuner->GetSignalStrength() : -1;
|
||||
}
|
||||
|
||||
int cDvbDevice::SignalQuality(void) const
|
||||
{
|
||||
return dvbTuner ? dvbTuner->GetSignalQuality() : -1;
|
||||
}
|
||||
|
||||
const cChannel *cDvbDevice::GetCurrentlyTunedTransponder(void) const
|
||||
{
|
||||
return dvbTuner->GetTransponder();
|
||||
return dvbTuner ? dvbTuner->GetTransponder() : NULL;
|
||||
}
|
||||
|
||||
bool cDvbDevice::IsTunedToTransponder(const cChannel *Channel)
|
||||
{
|
||||
return dvbTuner->IsTunedTo(Channel);
|
||||
return dvbTuner ? dvbTuner->IsTunedTo(Channel) : false;
|
||||
}
|
||||
|
||||
bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView)
|
||||
{
|
||||
dvbTuner->Set(Channel);
|
||||
if (dvbTuner)
|
||||
dvbTuner->Set(Channel);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1036,3 +1156,24 @@ cDvbDeviceProbe::~cDvbDeviceProbe()
|
||||
{
|
||||
DvbDeviceProbes.Del(this, false);
|
||||
}
|
||||
|
||||
uint32_t cDvbDeviceProbe::GetSubsystemId(int Adapter, int Frontend)
|
||||
{
|
||||
cString FileName;
|
||||
cReadLine ReadLine;
|
||||
FILE *f = NULL;
|
||||
uint32_t SubsystemId = 0;
|
||||
FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_vendor", Adapter, Frontend);
|
||||
if ((f = fopen(FileName, "r")) != NULL) {
|
||||
if (char *s = ReadLine.Read(f))
|
||||
SubsystemId = strtoul(s, NULL, 0) << 16;
|
||||
fclose(f);
|
||||
}
|
||||
FileName = cString::sprintf("/sys/class/dvb/dvb%d.frontend%d/device/subsystem_device", Adapter, Frontend);
|
||||
if ((f = fopen(FileName, "r")) != NULL) {
|
||||
if (char *s = ReadLine.Read(f))
|
||||
SubsystemId |= strtoul(s, NULL, 0);
|
||||
fclose(f);
|
||||
}
|
||||
return SubsystemId;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: dvbdevice.h 2.14 2010/04/11 10:29:37 kls Exp $
|
||||
* $Id: dvbdevice.h 2.15 2011/06/02 13:20:05 kls Exp $
|
||||
*/
|
||||
|
||||
#ifndef __DVBDEVICE_H
|
||||
@ -141,6 +141,8 @@ public:
|
||||
virtual bool ProvidesTransponder(const cChannel *Channel) const;
|
||||
virtual bool ProvidesChannel(const cChannel *Channel, int Priority = -1, bool *NeedsDetachReceivers = NULL) const;
|
||||
virtual int NumProvidedSystems(void) const;
|
||||
virtual int SignalStrength(void) const;
|
||||
virtual int SignalQuality(void) const;
|
||||
virtual const cChannel *GetCurrentlyTunedTransponder(void) const;
|
||||
virtual bool IsTunedToTransponder(const cChannel *Channel);
|
||||
protected:
|
||||
@ -196,6 +198,7 @@ class cDvbDeviceProbe : public cListObject {
|
||||
public:
|
||||
cDvbDeviceProbe(void);
|
||||
virtual ~cDvbDeviceProbe();
|
||||
static uint32_t GetSubsystemId(int Adapter, int Frontend);
|
||||
virtual bool Probe(int Adapter, int Frontend) = 0;
|
||||
///< Probes for a DVB device at the given Adapter and creates the appropriate
|
||||
///< object derived from cDvbDevice if applicable.
|
||||
|
40
skinsttng.c
40
skinsttng.c
@ -4,7 +4,7 @@
|
||||
* See the main source file 'vdr.c' for copyright information and
|
||||
* how to reach the author.
|
||||
*
|
||||
* $Id: skinsttng.c 2.7 2011/02/20 13:02:49 kls Exp $
|
||||
* $Id: skinsttng.c 2.8 2011/06/02 12:54:43 kls Exp $
|
||||
*/
|
||||
|
||||
// Star Trek: The Next Generation® is a registered trademark of Paramount Pictures
|
||||
@ -92,6 +92,8 @@ THEME_CLR(Theme, clrChannelEpgTitle, clrCyan);
|
||||
THEME_CLR(Theme, clrChannelEpgShortText, clrYellow);
|
||||
THEME_CLR(Theme, clrChannelTimebarSeen, clrYellow);
|
||||
THEME_CLR(Theme, clrChannelTimebarRest, clrGray50);
|
||||
THEME_CLR(Theme, clrChannelSignalValue, clrGreen);
|
||||
THEME_CLR(Theme, clrChannelSignalRest, clrRed);
|
||||
THEME_CLR(Theme, clrMenuFrame, clrYellow);
|
||||
THEME_CLR(Theme, clrMenuTitle, clrBlack);
|
||||
THEME_CLR(Theme, clrMenuDate, clrBlack);
|
||||
@ -134,6 +136,9 @@ private:
|
||||
const cEvent *present;
|
||||
cString lastDate;
|
||||
int lastSeen;
|
||||
int lastDeviceNumber;
|
||||
int lastSignalStrength;
|
||||
int lastSignalQuality;
|
||||
tTrackId lastTrackId;
|
||||
static cBitmap bmTeletext, bmRadio, bmAudio, bmDolbyDigital, bmEncrypted, bmRecording;
|
||||
public:
|
||||
@ -156,6 +161,9 @@ cSkinSTTNGDisplayChannel::cSkinSTTNGDisplayChannel(bool WithInfo)
|
||||
{
|
||||
present = NULL;
|
||||
lastSeen = -1;
|
||||
lastDeviceNumber = -1;
|
||||
lastSignalStrength = -1;
|
||||
lastSignalQuality = -1;
|
||||
memset(&lastTrackId, 0, sizeof(lastTrackId));
|
||||
const cFont *font = cFont::GetFont(fontOsd);
|
||||
withInfo = WithInfo;
|
||||
@ -344,6 +352,36 @@ void cSkinSTTNGDisplayChannel::Flush(void)
|
||||
osd->DrawRectangle(x1 + Gap, y3, x1 + Gap + ScrollWidth - 1, y3 + seen, Theme.Color(clrChannelTimebarSeen));
|
||||
lastSeen = seen;
|
||||
}
|
||||
int DeviceNumber = cDevice::ActualDevice()->DeviceNumber() + 1;
|
||||
int SignalStrength = cDevice::ActualDevice()->SignalStrength();
|
||||
int SignalQuality = cDevice::ActualDevice()->SignalQuality();
|
||||
if (DeviceNumber != lastDeviceNumber || SignalStrength != lastSignalStrength || SignalQuality != lastSignalQuality) {
|
||||
int d = 3;
|
||||
int h = ((y7 - y6 + 1) - 3 * d) / 2;
|
||||
int w = (x4 - x3) / 5;
|
||||
int x = (x3 + x4) / 2 - w / 2;
|
||||
if (SignalStrength >= 0) {
|
||||
int s = SignalStrength * w / 100;
|
||||
osd->DrawRectangle(x, y6 + d, x + s - 1, y6 + d + h - 1, Theme.Color(clrChannelSignalValue));
|
||||
osd->DrawRectangle(x + s, y6 + d, x + w - 1, y6 + d + h - 1, Theme.Color(clrChannelSignalRest));
|
||||
}
|
||||
else if (DeviceNumber != lastDeviceNumber)
|
||||
osd->DrawRectangle(x, y6 + d, x + w - 1, y6 + d + h - 1, Theme.Color(clrChannelFrame));
|
||||
if (SignalQuality >= 0) {
|
||||
int q = SignalQuality * w / 100;
|
||||
osd->DrawRectangle(x, y7 - d - h + 1, x + q - 1, y7 - d, Theme.Color(clrChannelSignalValue));
|
||||
osd->DrawRectangle(x + q, y7 - d - h + 1, x + w - 1, y7 - d, Theme.Color(clrChannelSignalRest));
|
||||
}
|
||||
else if (DeviceNumber != lastDeviceNumber)
|
||||
osd->DrawRectangle(x, y7 - d - h + 1, x + w - 1, y7 - d, Theme.Color(clrChannelFrame));
|
||||
cString dn = cString::sprintf(" %d ", DeviceNumber);
|
||||
const cFont *font = cFont::GetFont(fontSml);
|
||||
int dw = font->Width(dn);
|
||||
osd->DrawText(x - 2 * d - dw, y6, dn, Theme.Color(clrChannelDate), frameColor, font, dw);
|
||||
lastDeviceNumber = DeviceNumber;
|
||||
lastSignalStrength = SignalStrength;
|
||||
lastSignalQuality = SignalQuality;
|
||||
}
|
||||
}
|
||||
osd->Flush();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user