--- config.c.orig 2009-04-13 19:20:00.000000000 -0600 +++ config.c 2009-11-25 14:57:42.000000000 -0700 @@ -14,7 +14,7 @@ cSoppalusikkaConfig::cSoppalusikkaConfig() : logodir(""), showauxinfo(1), showlogo(0), showvps(1), - showduration(1), showsymbols(0), showprogressbar(1), + showduration(1), showsignalinfo(1), showsymbols(0), showprogressbar(1), cachesize(100) { } --- config.h.orig 2009-04-13 19:20:00.000000000 -0600 +++ config.h 2009-11-25 14:57:42.000000000 -0700 @@ -21,6 +21,7 @@ int showlogo; int showvps; int showduration; // 0 = remaining; 1 = total + int showsignalinfo; int showsymbols; int showprogressbar; int cachesize; --- skinsoppalusikka.c.orig 2009-04-13 19:20:00.000000000 -0600 +++ skinsoppalusikka.c 2009-11-25 14:57:42.000000000 -0700 @@ -154,6 +154,7 @@ else if (!strcasecmp(Name, "ShowProgressBar")) SoppalusikkaConfig.showprogressbar = atoi(Value); else if (!strcasecmp(Name, "ShowSymbols")) SoppalusikkaConfig.showsymbols = atoi(Value); else if (!strcasecmp(Name, "ShowLogo")) SoppalusikkaConfig.showlogo = atoi(Value); + else if (!strcasecmp(Name, "ShowSignalInfo")) SoppalusikkaConfig.showsignalinfo = atoi(Value); else if (!strcasecmp(Name, "ShowVPS")) SoppalusikkaConfig.showvps = atoi(Value); else if (!strcasecmp(Name, "ShowDuration")) SoppalusikkaConfig.showduration = atoi(Value); else if (!strcasecmp(Name, "CacheSize")) SoppalusikkaConfig.cachesize = atoi(Value); @@ -213,6 +214,9 @@ Add(new cMenuEditBoolItem(tr("Show symbols"), &data.showsymbols)); help.Append(tr("Define whether symbols are shown in recordings and schedule menus.")); + Add(new cMenuEditBoolItem(tr("Show signal info"), &data.showsignalinfo)); + help.Append(tr("Define whether signal information is shown in channel info menu.")); + Add(new cMenuEditBoolItem(tr("Show VPS in channel info"), &data.showvps)); help.Append(tr("Define whether VPS information is shown in channel info menu.")); @@ -240,6 +244,7 @@ SetupStore("ShowProgressBar", SoppalusikkaConfig.showprogressbar); SetupStore("ShowSymbols", SoppalusikkaConfig.showsymbols); SetupStore("ShowLogo", SoppalusikkaConfig.showlogo); + SetupStore("ShowSignalInfo", SoppalusikkaConfig.showsignalinfo); SetupStore("ShowVPS", SoppalusikkaConfig.showvps); SetupStore("ShowDuration", SoppalusikkaConfig.showduration); SetupStore("CacheSize", SoppalusikkaConfig.cachesize); --- soppalusikka.c.orig 2009-11-01 10:48:30.000000000 -0700 +++ soppalusikka.c 2009-11-25 16:45:36.000000000 -0700 @@ -11,6 +11,8 @@ #include "soppalusikka.h" #include #include +#include +#include #include #include #include @@ -154,6 +156,10 @@ THEME_CLR(Theme, clrReplayProgressSelected, 0xFFFF0000); THEME_CLR(Theme, clrReplayProgressMark, 0xFF000000); THEME_CLR(Theme, clrReplayProgressCurrent, 0xFFFF0000); +THEME_CLR(Theme, clrSignalHighFg, 0xFE34A024); +THEME_CLR(Theme, clrSignalMediumFg, 0xFDD0A024); +THEME_CLR(Theme, clrSignalLowFg, 0xFDBF0000); +THEME_CLR(Theme, clrSignalBg, 0xFFAEAEAE); #define TinyGap 1 #define SmallGap 2 @@ -161,6 +167,8 @@ #define BigGap 8 #define Roundness 10 +#define MIN_CI_SIGNALBAR 74 + // --- cSkinSoppalusikkaDisplayChannel -------------------------------------------- class cSkinSoppalusikkaDisplayChannel : public cSkinDisplayChannel { @@ -173,11 +181,16 @@ int y0, y1; int yt0, yt1, yt2, yt3, yt4; int yb0, yb1, yb2, yb3, yb4, yb5; + int xSignalBarLeft, nChanRowCenter, nStrBarWidth, nSnrBarWidth, nInitStrBarWidth, nInitSnrBarWidth; + int cardIndex, m_Frontend; + cTimeMs UpdateSignalTimer; cString lastDate; bool HasChannelTimerRecording(const cChannel *Channel); void ResetTopAreaCoordinates(bool islogo = false); void DrawTopArea(const cChannel *Channel = NULL); void DrawBottomArea(void); + int GetSignal(uint16_t &str, uint16_t &snr, fe_status_t &status); + void UpdateSignal(void); cString GetChannelName(const cChannel *Channel); cString GetChannelNumber(const cChannel *Channel, int Number); public: @@ -194,6 +207,10 @@ const cFont *font = cFont::GetFont(fontOsd); int lineHeight = font->Height(); islogo = false; + xSignalBarLeft = SoppalusikkaConfig.showsignalinfo ? 0 : -1; + nStrBarWidth = nSnrBarWidth = nInitStrBarWidth = nInitSnrBarWidth = 10000; + m_Frontend = -1; + UpdateSignalTimer.Set(); // general coordinates x0 = 0; x1 = cOsd::OsdWidth(); @@ -264,6 +281,9 @@ cSkinSoppalusikkaDisplayChannel::~cSkinSoppalusikkaDisplayChannel() { + if (m_Frontend >= 0) + close(m_Frontend); + delete osd; } @@ -344,6 +364,167 @@ osd->DrawEllipse(xb5, yb4, xb6 - 1, yb5 - 1, clrTransparent, -4); } +#define FRONTEND_DEVICE "/dev/dvb/adapter%d/frontend%d" + +int cSkinSoppalusikkaDisplayChannel::GetSignal(uint16_t &str, uint16_t &snr, fe_status_t & /* status */) { + if (m_Frontend < 0) { + cString dev = cString::sprintf(FRONTEND_DEVICE, cardIndex, 0); + str = 0; + snr = 0; + + m_Frontend = open(dev, O_RDONLY | O_NONBLOCK); + if (m_Frontend < 0) + return -1; + } + else if (UpdateSignalTimer.Elapsed() < 500) { + return 0; + } + + CHECK(ioctl(m_Frontend, FE_READ_SIGNAL_STRENGTH, &str)); + CHECK(ioctl(m_Frontend, FE_READ_SNR, &snr)); + UpdateSignalTimer.Set(); + close(m_Frontend); + + return 0; +} + +void cSkinSoppalusikkaDisplayChannel::UpdateSignal() { + if (xSignalBarLeft < 0) + return; + + cardIndex = cDevice::ActualDevice()->CardIndex(); + + fe_status_t status; + uint16_t str = 0; + uint16_t snr = 0; + + if (GetSignal(str, snr, status) < 0) + { + xSignalBarLeft = -1; + return; + } + if (snr == 0 && str == 0) + { + return; + } + + xSignalBarLeft = xt7 - Roundness - MIN_CI_SIGNALBAR; + + // --- code mainly gathered from femon plugin --- + struct dvb_frontend_info m_FrontendInfo; + cString dev = cString::sprintf(FRONTEND_DEVICE, cardIndex, 0); + + m_Frontend = open(dev, O_RDONLY | O_NONBLOCK); + if (m_Frontend < 0) + return; + CHECK(ioctl(m_Frontend, FE_GET_INFO, &m_FrontendInfo)); + + //fprintf(stdout,"cardIndex=%d\n", cardIndex); + //fprintf(stdout,"FrontendInfo.type=%d (numeric value)\nFrontendInfo.name=%s\n", m_FrontendInfo.type, m_FrontendInfo.name); + //fprintf(stdout,"str=%d, snr=%d (raw values)\n",str, snr); + + bool check_2g, check_q16; + check_2g = m_FrontendInfo.caps & FE_CAN_2G_MODULATION; + check_q16 = m_FrontendInfo.caps & FE_CAN_QAM_16; + + switch (m_FrontendInfo.type) { + case FE_QPSK: + if (check_q16) { + if ((snr > 0x1500) && (str == 0xffff)) { + snr = 0; + str = 0; + //fprintf(stdout,"Found DVB_S2\n"); + } + else { + str = str * 100 / 0xFFFF; + snr = snr * 100 / 0x1268; + //fprintf(stdout,"Found DVB_S (other)\n"); + } + } + else { + if (check_2g) { + str = str * 100 / 0xFFFF; + snr = snr * 100 / 0xFFFF; + //fprintf(stdout,"Found DVB_S ??\n"); + } + else { + str = str * 100 / 0xFFFF; + snr = snr * 100 / 0x1268; // not sure about this value - needs testing + //fprintf(stdout,"Found DVB_S\n"); + } + } + break; + case FE_ATSC: + str = str * 100 / 0xFFFF; + snr = snr * 100 / 0x3DAD; + //fprintf(stdout,"Found ATSC\n"); + break; + default: + snr = 0; + str = 0; + fprintf(stdout,"Could not find frontend type!\n"); + } + fprintf(stdout,"str=%d%%, snr=%d%%\n",str, snr); + // ---------------------------------------------- + + // change signal percentage to bar width (MIN_CI_SIGNALBAR = 74) + nStrBarWidth = str * MIN_CI_SIGNALBAR / 100; + nSnrBarWidth = snr * MIN_CI_SIGNALBAR / 100; + + if ( nStrBarWidth != nInitStrBarWidth || nSnrBarWidth != nInitSnrBarWidth) { + nInitStrBarWidth = nStrBarWidth; + nInitSnrBarWidth = nSnrBarWidth; + nChanRowCenter = ((yt4 - Gap - yt3 - Gap - Gap ) / 2); + + // draw signal bar backgrounds + osd->DrawRectangle(xt6 - MIN_CI_SIGNALBAR, yt3 + Gap, xt6 - 1, yt3 + Gap + nChanRowCenter , Theme.Color(clrSignalBg)); + osd->DrawRectangle(xt6 - MIN_CI_SIGNALBAR, yt3 + Gap + nChanRowCenter + Gap, xt6 - 1, yt4 - Gap - 1, Theme.Color(clrSignalBg)); + + // draw signal strength bar foreground + if (str) { + if (nStrBarWidth <= 25) { + osd->DrawRectangle(xSignalBarLeft, yt3 + Gap, xt6 - MIN_CI_SIGNALBAR + nStrBarWidth - 1, yt3 + Gap + nChanRowCenter , Theme.Color(clrSignalLowFg)); + } + else if (nStrBarWidth <= 49) { + osd->DrawRectangle(xSignalBarLeft, yt3 + Gap, xt6 - MIN_CI_SIGNALBAR + 25 - 1, yt3 + Gap + nChanRowCenter , Theme.Color(clrSignalLowFg)); + osd->DrawRectangle(xSignalBarLeft + 25, yt3 + Gap, xt6 - MIN_CI_SIGNALBAR + nStrBarWidth - 1, yt3 + Gap + nChanRowCenter , Theme.Color(clrSignalMediumFg)); + } + else if (nStrBarWidth <= MIN_CI_SIGNALBAR) { + osd->DrawRectangle(xSignalBarLeft, yt3 + Gap, xt6 - MIN_CI_SIGNALBAR + 25 - 1, yt3 + Gap + nChanRowCenter , Theme.Color(clrSignalLowFg)); + osd->DrawRectangle(xSignalBarLeft + 25, yt3 + Gap, xt6 - MIN_CI_SIGNALBAR + 49 - 1, yt3 + Gap + nChanRowCenter , Theme.Color(clrSignalMediumFg)); + // make sure it doesn't draw outside the background if signal spikes + if ((xt6 - MIN_CI_SIGNALBAR + nStrBarWidth -1) > (xt6 - 1)) + osd->DrawRectangle(xSignalBarLeft + 49, yt3 + Gap, xt6 - 1, yt3 + Gap + nChanRowCenter , Theme.Color(clrSignalHighFg)); + else + osd->DrawRectangle(xSignalBarLeft + 49, yt3 + Gap, xt6 - MIN_CI_SIGNALBAR + nStrBarWidth - 1, yt3 + Gap + nChanRowCenter , Theme.Color(clrSignalHighFg)); + } + } + // draw signal quality bar foreground + if (snr) { + if (nSnrBarWidth <= 25) { + osd->DrawRectangle(xSignalBarLeft, yt3 + Gap + nChanRowCenter + Gap, xt6 - MIN_CI_SIGNALBAR + nSnrBarWidth - 1, yt4 - Gap - 1 , Theme.Color(clrSignalLowFg)); + } + else if (nSnrBarWidth <= 49) { + osd->DrawRectangle(xSignalBarLeft, yt3 + Gap + nChanRowCenter + Gap, xt6 - MIN_CI_SIGNALBAR + 25 - 1, yt4 - Gap - 1 , Theme.Color(clrSignalLowFg)); + osd->DrawRectangle(xSignalBarLeft + 25, yt3 + Gap + nChanRowCenter + Gap, xt6 - MIN_CI_SIGNALBAR + nSnrBarWidth - 1, yt4 - Gap - 1 , Theme.Color(clrSignalMediumFg)); + } + else if (nSnrBarWidth <= MIN_CI_SIGNALBAR) { + osd->DrawRectangle(xSignalBarLeft, yt3 + Gap + nChanRowCenter + Gap, xt6 - MIN_CI_SIGNALBAR + 25 - 1, yt4 - Gap - 1 , Theme.Color(clrSignalLowFg)); + osd->DrawRectangle(xSignalBarLeft + 25, yt3 + Gap + nChanRowCenter + Gap, xt6 - MIN_CI_SIGNALBAR + 49 - 1, yt4 - Gap - 1 , Theme.Color(clrSignalMediumFg)); + // make sure it doesn't draw outside the background if signal spikes + if ((xt6 - MIN_CI_SIGNALBAR + nSnrBarWidth -1) > (xt6 - 1)) + osd->DrawRectangle(xSignalBarLeft + 49, yt3 + Gap + nChanRowCenter + Gap, xt6 - 1, yt4 - Gap - 1 , Theme.Color(clrSignalHighFg)); + else + osd->DrawRectangle(xSignalBarLeft + 49, yt3 + Gap + nChanRowCenter + Gap, xt6 - MIN_CI_SIGNALBAR + nSnrBarWidth - 1, yt4 - Gap - 1 , Theme.Color(clrSignalHighFg)); + } + } + if (m_Frontend >= 0) { + close(m_Frontend); + m_Frontend = -1; + } + } +} + cString cSkinSoppalusikkaDisplayChannel::GetChannelName(const cChannel *Channel) { char buffer[256]; @@ -383,6 +564,11 @@ osd->DrawText(xt2, yt0, GetChannelNumber(Channel, Number), Theme.Color(clrChannelNumberDateFg), Theme.Color(clrChannelNumberDateBg), cFont::GetFont(fontSml), xt3 - xt2, yt2 - yt0); // draw channel name osd->DrawText(xt2, yt3, GetChannelName(Channel), Theme.Color(clrChannelNameFg), Theme.Color(clrChannelNameBg), cFont::GetFont(fontSml), xt6 - xt2, yt4 - yt3); + // draw initial signal bar backgrounds + if (SoppalusikkaConfig.showsignalinfo) { + osd->DrawRectangle(xt6 - MIN_CI_SIGNALBAR, yt3 + Gap, xt6 - 1, yt3 + Gap + ((yt4 - Gap - yt3 - Gap - Gap ) / 2) , Theme.Color(clrSignalBg)); + osd->DrawRectangle(xt6 - MIN_CI_SIGNALBAR, yt3 + Gap + ((yt4 - Gap - yt3 - Gap - Gap ) / 2) + Gap, xt6 - 1, yt4 - Gap - 1, Theme.Color(clrSignalBg)); + } // draw symbols if (Channel && !Channel->GroupSep()) { int xs = xt8; @@ -449,6 +635,8 @@ void cSkinSoppalusikkaDisplayChannel::SetEvents(const cEvent *Present, const cEvent *Following) { + // draw signal bar levels + UpdateSignal(); // draw bottom area DrawBottomArea(); // check epg datas @@ -559,6 +747,7 @@ osd->DrawText(xt3, yt0, date, Theme.Color(clrChannelNumberDateFg), Theme.Color(clrChannelNumberDateBg), cFont::GetFont(fontSml), xt4 - xt3, yt2 - yt0, taRight); lastDate = date; } + UpdateSignal(); osd->Flush(); }