mirror of
				https://github.com/vdr-projects/vdr.git
				synced 2025-03-01 10:50:46 +00:00 
			
		
		
		
	Implemented signal strength and quality handling
This commit is contained in:
		| @@ -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<6F> 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(); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user